diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2019-10-16 11:36:01 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2019-10-16 11:36:01 +0300 |
commit | c2fbe46b0f0fde44b8a40d89601a195da27d28fb (patch) | |
tree | f66e3e50758acb36001e2774c6e4ede5fc8bead6 /source/blender/blenkernel/intern/pbvh_parallel.cc | |
parent | 386ba094988fc793f8e060d15438566e5e2d2cae (diff) | |
parent | dcf57e34f3866bba5ddd9cfdfe858a1a5eedc4c2 (diff) |
Merge branch 'master' into temp-gpencil-drw-enginetemp-gpencil-drw-engine
Diffstat (limited to 'source/blender/blenkernel/intern/pbvh_parallel.cc')
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_parallel.cc | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/pbvh_parallel.cc b/source/blender/blenkernel/intern/pbvh_parallel.cc new file mode 100644 index 00000000000..aa4c659c8bd --- /dev/null +++ b/source/blender/blenkernel/intern/pbvh_parallel.cc @@ -0,0 +1,145 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_task.h" +#include "BLI_threads.h" + +#include "BKE_pbvh.h" + +#include "atomic_ops.h" + +#ifdef WITH_TBB + +# include <tbb/tbb.h> + +/* Functor for running TBB parallel_for and parallel_reduce. */ +struct PBVHTask { + PBVHParallelRangeFunc func; + void *userdata; + const PBVHParallelSettings *settings; + + void *userdata_chunk; + + /* Root constructor. */ + PBVHTask(PBVHParallelRangeFunc func, void *userdata, const PBVHParallelSettings *settings) + : func(func), userdata(userdata), settings(settings) + { + init_chunk(settings->userdata_chunk); + } + + /* Copy constructor. */ + PBVHTask(const PBVHTask &other) + : func(other.func), userdata(other.userdata), settings(other.settings) + { + init_chunk(other.userdata_chunk); + } + + /* Splitting constructor for parallel reduce. */ + PBVHTask(PBVHTask &other, tbb::split) + : func(other.func), userdata(other.userdata), settings(other.settings) + { + init_chunk(settings->userdata_chunk); + } + + ~PBVHTask() + { + MEM_SAFE_FREE(userdata_chunk); + } + + void init_chunk(void *from_chunk) + { + if (from_chunk) { + userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "PBVHTask"); + memcpy(userdata_chunk, from_chunk, settings->userdata_chunk_size); + } + else { + userdata_chunk = NULL; + } + } + + void operator()(const tbb::blocked_range<int> &r) const + { + TaskParallelTLS tls; + tls.thread_id = get_thread_id(); + tls.userdata_chunk = userdata_chunk; + for (int i = r.begin(); i != r.end(); ++i) { + func(userdata, i, &tls); + } + } + + void join(const PBVHTask &other) + { + settings->func_reduce(userdata, userdata_chunk, other.userdata_chunk); + } + + int get_thread_id() const + { + /* Get a unique thread ID for texture nodes. In the future we should get rid + * of the thread ID and change texture evaluation to not require per-thread + * storage that can't be efficiently allocated on the stack. */ + static tbb::enumerable_thread_specific<int> pbvh_thread_id(-1); + static int pbvh_thread_id_counter = 0; + + int &thread_id = pbvh_thread_id.local(); + if (thread_id == -1) { + thread_id = atomic_fetch_and_add_int32(&pbvh_thread_id_counter, 1); + if (thread_id >= BLENDER_MAX_THREADS) { + BLI_assert(!"Maximum number of threads exceeded for sculpting"); + thread_id = thread_id % BLENDER_MAX_THREADS; + } + } + return thread_id; + } +}; + +#endif + +void BKE_pbvh_parallel_range(const int start, + const int stop, + void *userdata, + PBVHParallelRangeFunc func, + const struct PBVHParallelSettings *settings) +{ +#ifdef WITH_TBB + /* Multithreading. */ + if (settings->use_threading) { + PBVHTask task(func, userdata, settings); + + if (settings->func_reduce) { + parallel_reduce(tbb::blocked_range<int>(start, stop), task); + if (settings->userdata_chunk) { + memcpy(settings->userdata_chunk, task.userdata_chunk, settings->userdata_chunk_size); + } + } + else { + parallel_for(tbb::blocked_range<int>(start, stop), task); + } + + return; + } +#endif + + /* Single threaded. Nothing to reduce as everything is accumulated into the + * main userdata chunk directly. */ + TaskParallelTLS tls; + tls.thread_id = 0; + tls.userdata_chunk = settings->userdata_chunk; + for (int i = start; i < stop; i++) { + func(userdata, i, &tls); + } +} |