diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-03-03 13:59:20 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-03-03 14:02:31 +0300 |
commit | 8c113a95e3536dfa0be37c9e2e924ea8172bb613 (patch) | |
tree | fc71fffa34bc552168f79efccd5bd02b14700556 | |
parent | ba7eb0c7b9d93987173780d5b819c7f2ec79b96e (diff) |
Make texture node threaded
Quite trivial idea -- just pass tread ID to the texture sampling function.
Implemented as a TLS to avoid passing huge amount of extra contexts around.
Should be working on all platforms, but compilation test is required.
Reviewers: juicyfruit, campbellbarton
Reviewed By: campbellbarton
Differential Revision: https://developer.blender.org/D1831
10 files changed, 81 insertions, 28 deletions
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 30696012221..12bce70594b 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -757,7 +757,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP scene_color_manage = BKE_scene_check_color_management_enabled(eff->scene); - hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL, scene_color_manage, false); + hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, 0, NULL, scene_color_manage, false); if (hasrgb && mode==PFIELD_TEX_RGB) { force[0] = (0.5f - result->tr) * strength; @@ -768,15 +768,15 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP strength/=nabla; tex_co[0] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL, scene_color_manage, false); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, 0, NULL, scene_color_manage, false); tex_co[0] -= nabla; tex_co[1] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL, scene_color_manage, false); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, 0, NULL, scene_color_manage, false); tex_co[1] -= nabla; tex_co[2] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL, scene_color_manage, false); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, 0, NULL, scene_color_manage, false); if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */ /* generate intensity if texture only has rgb value */ diff --git a/source/blender/compositor/intern/COM_CPUDevice.cpp b/source/blender/compositor/intern/COM_CPUDevice.cpp index c7c3f7769fe..a5824ec5248 100644 --- a/source/blender/compositor/intern/COM_CPUDevice.cpp +++ b/source/blender/compositor/intern/COM_CPUDevice.cpp @@ -22,6 +22,12 @@ #include "COM_CPUDevice.h" +CPUDevice::CPUDevice(int thread_id) + : Device(), + m_thread_id(thread_id) +{ +} + void CPUDevice::execute(WorkPackage *work) { const unsigned int chunkNumber = work->getChunkNumber(); diff --git a/source/blender/compositor/intern/COM_CPUDevice.h b/source/blender/compositor/intern/COM_CPUDevice.h index 3dc8fff66a3..d12666593d4 100644 --- a/source/blender/compositor/intern/COM_CPUDevice.h +++ b/source/blender/compositor/intern/COM_CPUDevice.h @@ -31,11 +31,18 @@ */ class CPUDevice : public Device { public: + CPUDevice(int thread_id); + /** * @brief execute a WorkPackage * @param work the WorkPackage to execute */ void execute(WorkPackage *work); + + int thread_id() { return m_thread_id; } + +protected: + int m_thread_id; }; #endif diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index fc6ea1299cf..4c85f11f655 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -50,7 +50,8 @@ /// @brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is created -static vector<CPUDevice *> g_cpudevices; +static vector<CPUDevice*> g_cpudevices; +static ThreadLocal(CPUDevice*) g_thread_device; #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE /// @brief list of all thread for every CPUDevice in cpudevices a thread exists @@ -153,9 +154,9 @@ int COM_isHighlightedbNode(bNode *bnode) #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE void *WorkScheduler::thread_execute_cpu(void *data) { - Device *device = (Device *)data; + CPUDevice *device = (CPUDevice *)data; WorkPackage *work; - + BLI_thread_local_set(g_thread_device, device); while ((work = (WorkPackage *)BLI_thread_queue_pop(g_cpuqueue))) { HIGHLIGHT(work); device->execute(work); @@ -310,18 +311,20 @@ void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads) device->deinitialize(); delete device; } - + if (g_cpuInitialized) { + BLI_thread_local_delete(g_thread_device); + } g_cpuInitialized = false; } /* initialize CPU threads */ if (!g_cpuInitialized) { for (int index = 0; index < num_cpu_threads; index++) { - CPUDevice *device = new CPUDevice(); + CPUDevice *device = new CPUDevice(index); device->initialize(); g_cpudevices.push_back(device); } - + BLI_thread_local_create(g_thread_device); g_cpuInitialized = true; } @@ -407,7 +410,7 @@ void WorkScheduler::deinitialize() device->deinitialize(); delete device; } - + BLI_thread_local_delete(g_thread_device); g_cpuInitialized = false; } @@ -450,3 +453,8 @@ void WorkScheduler::deinitialize() } } +int WorkScheduler::current_thread_id() +{ + CPUDevice *device = (CPUDevice *)BLI_thread_local_get(g_thread_device); + return device->thread_id(); +} diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h index 27afdf6efd0..67d3fc87ce1 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.h +++ b/source/blender/compositor/intern/COM_WorkScheduler.h @@ -113,6 +113,8 @@ public: */ static bool hasGPUDevices(); + static int current_thread_id(); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkScheduler") #endif diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 7d1d24a9747..665bffc2c1c 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -21,6 +21,7 @@ */ #include "COM_TextureOperation.h" +#include "COM_WorkScheduler.h" #include "BLI_listbase.h" #include "BLI_threads.h" @@ -30,9 +31,7 @@ extern "C" { #include "BKE_node.h" } -static ThreadMutex mutex_lock = BLI_MUTEX_INITIALIZER; - -TextureBaseOperation::TextureBaseOperation() : SingleThreadedOperation() +TextureBaseOperation::TextureBaseOperation() : NodeOperation() { this->addInputSocket(COM_DT_VECTOR); //offset this->addInputSocket(COM_DT_VECTOR); //size @@ -63,7 +62,7 @@ void TextureBaseOperation::initExecution() { ntreeTexBeginExecTree(this->m_texture->nodetree); } - SingleThreadedOperation::initExecution(); + NodeOperation::initExecution(); } void TextureBaseOperation::deinitExecution() { @@ -78,7 +77,7 @@ void TextureBaseOperation::deinitExecution() { ntreeTexEndExecTree(this->m_texture->nodetree->execdata); } - SingleThreadedOperation::deinitExecution(); + NodeOperation::deinitExecution(); } void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -121,12 +120,16 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y vec[1] = textureSize[1] * (v + textureOffset[1]); vec[2] = textureSize[2] * textureOffset[2]; - /* TODO(sergey): Need to pass thread ID to the multitex code, - * then we can avoid having mutex here. - */ - BLI_mutex_lock(&mutex_lock); - retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool, m_sceneColorManage, false); - BLI_mutex_unlock(&mutex_lock); + const int thread_id = WorkScheduler::current_thread_id(); + retval = multitex_ext(this->m_texture, + vec, + NULL, NULL, + 0, + &texres, + thread_id, + m_pool, + m_sceneColorManage, + false); if (texres.talpha) output[3] = texres.ta; diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index 47ef40882c5..4cc203b54a2 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -24,7 +24,7 @@ #ifndef _COM_TextureOperation_h #define _COM_TextureOperation_h -#include "COM_SingleThreadedOperation.h" +#include "COM_NodeOperation.h" #include "DNA_texture_types.h" #include "BLI_listbase.h" extern "C" { @@ -39,7 +39,7 @@ extern "C" { * * @todo: rename to operation. */ -class TextureBaseOperation : public SingleThreadedOperation { +class TextureBaseOperation : public NodeOperation { private: Tex *m_texture; const RenderData *m_rd; diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index a27ba6ea06d..ef1ef5e1469 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -74,7 +74,7 @@ static void texture_evaluate(struct Tex *tex, float value[3], float r_color[4]) TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; /* TODO(sergey): always use color management now. */ - multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL, true, false); + multitex_ext(tex, value, NULL, NULL, 1, &texres, 0, NULL, true, false); r_color[0] = texres.tr; r_color[1] = texres.tg; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 2b07ace26db..12b97aedbd3 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -198,7 +198,15 @@ struct ImagePool; struct Object; /* this one uses nodes */ -int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image); +int multitex_ext(struct Tex *tex, + float texvec[3], + float dxt[3], float dyt[3], + int osatex, + struct TexResult *texres, + const short thread, + struct ImagePool *pool, + bool scene_color_manage, + const bool skip_load_image); /* nodes disabled */ int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image); /* only for internal node usage */ diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 172fc999897..193f619c09c 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1377,9 +1377,28 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt * * Use it for stuff which is out of render pipeline. */ -int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) +int multitex_ext(Tex *tex, + float texvec[3], + float dxt[3], float dyt[3], + int osatex, + TexResult *texres, + const short thread, + struct ImagePool *pool, + bool scene_color_manage, + const bool skip_load_image) { - return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image, false); + return multitex_nodes_intern(tex, + texvec, + dxt, dyt, + osatex, + texres, + thread, + 0, + NULL, NULL, + pool, + scene_color_manage, + skip_load_image, + false); } /* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on)\ |