[Bf-blender-cvs] [e3b80d62025] strand_editmode: Multithreading support for the mesh sampling library.
Lukas Tönne
noreply at git.blender.org
Sun Aug 20 19:57:53 CEST 2017
Commit: e3b80d620250b3229359efe7e195fa8e7886f57a
Author: Lukas Tönne
Date: Sun Aug 20 18:50:58 2017 +0100
Branches: strand_editmode
https://developer.blender.org/rBe3b80d620250b3229359efe7e195fa8e7886f57a
Multithreading support for the mesh sampling library.
Samples can be generated either one-by-one using the existing "make_sample"
function (which uses a default context), or use the more efficient batch
generation functions. These optionally support threading via the task scheduler
now.
===================================================================
M source/blender/blenkernel/BKE_mesh_sample.h
M source/blender/blenkernel/intern/mesh_sample.c
M source/blender/editors/hair/hair_stroke.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_mesh_sample.h b/source/blender/blenkernel/BKE_mesh_sample.h
index 377f0c2c182..4721e0aae2d 100644
--- a/source/blender/blenkernel/BKE_mesh_sample.h
+++ b/source/blender/blenkernel/BKE_mesh_sample.h
@@ -36,7 +36,9 @@ struct MeshSampleGenerator;
typedef struct MeshSampleGenerator MeshSampleGenerator;
typedef float (*MeshSampleVertexWeightFp)(struct DerivedMesh *dm, struct MVert *vert, unsigned int index, void *userdata);
-typedef bool (*MeshSampleRayFp)(void *userdata, float ray_start[3], float ray_end[3]);
+typedef void* (*MeshSampleThreadContextCreateFp)(void *userdata, int start);
+typedef void (*MeshSampleThreadContextFreeFp)(void *userdata, void *thread_ctx);
+typedef bool (*MeshSampleRayFp)(void *userdata, void *thread_ctx, float ray_start[3], float ray_end[3]);
/* ==== Evaluate ==== */
@@ -55,16 +57,33 @@ struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_vertices(struct DerivedM
/* face_weights is optional */
struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_random(struct DerivedMesh *dm, unsigned int seed);
struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_random_ex(struct DerivedMesh *dm, unsigned int seed,
- MeshSampleVertexWeightFp vertex_weight_cb, void *userdata, bool use_facearea);
+ MeshSampleVertexWeightFp vertex_weight_cb, void *userdata, bool use_facearea);
-struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_raycast(struct DerivedMesh *dm, MeshSampleRayFp ray_cb, void *userdata);
+struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_raycast(
+ struct DerivedMesh *dm,
+ MeshSampleThreadContextCreateFp thread_context_create_cb,
+ MeshSampleThreadContextFreeFp thread_context_free_cb,
+ MeshSampleRayFp ray_cb,
+ void *userdata);
struct MeshSampleGenerator *BKE_mesh_sample_gen_volume_random_bbray(struct DerivedMesh *dm, unsigned int seed, float density);
void BKE_mesh_sample_free_generator(struct MeshSampleGenerator *gen);
+/* Generate a single sample.
+ * Not threadsafe!
+ */
bool BKE_mesh_sample_generate(struct MeshSampleGenerator *gen, struct MeshSample *sample);
+/* Generate a large number of samples.
+ */
+int BKE_mesh_sample_generate_batch_ex(struct MeshSampleGenerator *gen,
+ void *output_buffer, int output_stride, int count,
+ bool use_threads);
+
+int BKE_mesh_sample_generate_batch(struct MeshSampleGenerator *gen,
+ MeshSample *output_buffer, int count);
+
/* ==== Utilities ==== */
struct ParticleSystem;
diff --git a/source/blender/blenkernel/intern/mesh_sample.c b/source/blender/blenkernel/intern/mesh_sample.c
index 9f8541d4dfb..f0c91e5d465 100644
--- a/source/blender/blenkernel/intern/mesh_sample.c
+++ b/source/blender/blenkernel/intern/mesh_sample.c
@@ -33,6 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "BKE_bvhutils.h"
#include "BKE_mesh_sample.h"
@@ -41,6 +42,8 @@
#include "BLI_strict_flags.h"
+#define DEFAULT_TASK_SIZE 1024
+
/* ==== Evaluate ==== */
bool BKE_mesh_sample_is_volume_sample(const MeshSample *sample)
@@ -174,18 +177,34 @@ BLI_INLINE void mesh_sample_weights_from_loc(MeshSample *sample, DerivedMesh *dm
/* ==== Sampling ==== */
typedef void (*GeneratorFreeFp)(struct MeshSampleGenerator *gen);
-typedef bool (*GeneratorMakeSampleFp)(struct MeshSampleGenerator *gen, struct MeshSample *sample);
+typedef void* (*GeneratorThreadContextCreateFp)(const struct MeshSampleGenerator *gen, int start);
+typedef void (*GeneratorThreadContextFreeFp)(const struct MeshSampleGenerator *gen, void *thread_ctx);
+typedef bool (*GeneratorMakeSampleFp)(const struct MeshSampleGenerator *gen, void *thread_ctx, struct MeshSample *sample);
typedef struct MeshSampleGenerator
{
GeneratorFreeFp free;
+ GeneratorThreadContextCreateFp thread_context_create;
+ GeneratorThreadContextFreeFp thread_context_free;
GeneratorMakeSampleFp make_sample;
+
+ void *default_ctx;
+ int task_size;
} MeshSampleGenerator;
-static void sample_generator_init(MeshSampleGenerator *gen, GeneratorFreeFp free, GeneratorMakeSampleFp make_sample)
+static void sample_generator_init(MeshSampleGenerator *gen,
+ GeneratorFreeFp free,
+ GeneratorThreadContextCreateFp thread_context_create,
+ GeneratorThreadContextFreeFp thread_context_free,
+ GeneratorMakeSampleFp make_sample)
{
gen->free = free;
+ gen->thread_context_create = thread_context_create;
+ gen->thread_context_free = thread_context_free;
gen->make_sample = make_sample;
+
+ gen->default_ctx = NULL;
+ gen->task_size = DEFAULT_TASK_SIZE;
}
/* ------------------------------------------------------------------------- */
@@ -195,7 +214,6 @@ typedef struct MSurfaceSampleGenerator_Vertices {
DerivedMesh *dm;
int (*vert_loop_map)[3];
- int cur_vert;
} MSurfaceSampleGenerator_Vertices;
static void generator_vertices_free(MSurfaceSampleGenerator_Vertices *gen)
@@ -206,14 +224,28 @@ static void generator_vertices_free(MSurfaceSampleGenerator_Vertices *gen)
MEM_freeN(gen);
}
-static bool generator_vertices_make_sample(MSurfaceSampleGenerator_Vertices *gen, MeshSample *sample)
+static void* generator_vertices_thread_context_create(const MSurfaceSampleGenerator_Vertices *UNUSED(gen), int start)
+{
+ int *cur_vert = MEM_callocN(sizeof(int), "generator_vertices_thread_context");
+ *cur_vert = start;
+ return cur_vert;
+}
+
+static void generator_vertices_thread_context_free(const MSurfaceSampleGenerator_Vertices *UNUSED(gen), void *thread_ctx)
+{
+ MEM_freeN(thread_ctx);
+}
+
+static bool generator_vertices_make_sample(const MSurfaceSampleGenerator_Vertices *gen, void *thread_ctx, MeshSample *sample)
{
DerivedMesh *dm = gen->dm;
const int num_verts = dm->getNumVerts(dm);
const MLoop *mloops = dm->getLoopArray(dm);
- while (gen->cur_vert < num_verts) {
- int cur_vert = gen->cur_vert++;
+ int cur_vert = *(int *)thread_ctx;
+ bool found_vert = false;
+ while (cur_vert < num_verts) {
+ ++cur_vert;
const int *loops = gen->vert_loop_map[cur_vert];
if (loops[0] >= 0) {
@@ -231,10 +263,13 @@ static bool generator_vertices_make_sample(MSurfaceSampleGenerator_Vertices *gen
sample->orig_weights[1] = 0.0f;
sample->orig_weights[2] = 0.0f;
- return true;
+ found_vert = true;
+ break;
}
}
- return false;
+
+ *(int *)thread_ctx = cur_vert;
+ return found_vert;
}
MeshSampleGenerator *BKE_mesh_sample_gen_surface_vertices(DerivedMesh *dm)
@@ -244,10 +279,13 @@ MeshSampleGenerator *BKE_mesh_sample_gen_surface_vertices(DerivedMesh *dm)
DM_ensure_normals(dm);
gen = MEM_callocN(sizeof(MSurfaceSampleGenerator_Vertices), "MSurfaceSampleGenerator_Vertices");
- sample_generator_init(&gen->base, (GeneratorFreeFp)generator_vertices_free, (GeneratorMakeSampleFp)generator_vertices_make_sample);
+ sample_generator_init(&gen->base,
+ (GeneratorFreeFp)generator_vertices_free,
+ (GeneratorThreadContextCreateFp)generator_vertices_thread_context_create,
+ (GeneratorThreadContextFreeFp)generator_vertices_thread_context_free,
+ (GeneratorMakeSampleFp)generator_vertices_make_sample);
gen->dm = dm;
- gen->cur_vert = 0;
{
const int num_verts = dm->getNumVerts(dm);
@@ -292,7 +330,7 @@ typedef struct MSurfaceSampleGenerator_Random {
MeshSampleGenerator base;
DerivedMesh *dm;
- RNG *rng;
+ unsigned int seed;
float *tri_weights;
float *vertex_weights;
@@ -327,11 +365,21 @@ static void generator_random_free(MSurfaceSampleGenerator_Random *gen)
MEM_freeN(gen->tri_weights);
if (gen->vertex_weights)
MEM_freeN(gen->vertex_weights);
- if (gen->rng)
- BLI_rng_free(gen->rng);
MEM_freeN(gen);
}
+static void* generator_random_thread_context_create(const MSurfaceSampleGenerator_Random *gen, int start)
+{
+ RNG *rng = BLI_rng_new(gen->seed);
+ BLI_rng_skip(rng, start);
+ return rng;
+}
+
+static void generator_random_thread_context_free(const MSurfaceSampleGenerator_Random *UNUSED(gen), void *thread_ctx)
+{
+ BLI_rng_free(thread_ctx);
+}
+
/* Find the index in "sum" array before "value" is crossed. */
BLI_INLINE int weight_array_binary_search(const float *sum, int size, float value)
{
@@ -357,10 +405,10 @@ BLI_INLINE int weight_array_binary_search(const float *sum, int size, float valu
return low;
}
-static bool generator_random_make_sample(MSurfaceSampleGenerator_Random *gen, MeshSample *sample)
+static bool generator_random_make_sample(const MSurfaceSampleGenerator_Random *gen, void *thread_ctx, MeshSample *sample)
{
DerivedMesh *dm = gen->dm;
- RNG *rng = gen->rng;
+ RNG *rng = thread_ctx;
const MLoop *mloops = dm->getLoopArray(dm);
const MLoopTri *mtris = dm->getLoopTriArray(dm);
int tottris = dm->getNumLoopTri(dm);
@@ -430,10 +478,14 @@ MeshSampleGenerator *BKE_mesh_sample_gen_surface_random_ex(DerivedMesh *dm, unsi
DM_ensure_normals(dm);
gen = MEM_callocN(sizeof(MSurfaceSampleGenerator_Random), "MSurfaceSampleGenerator_Random");
- sample_generator_init(&gen->base, (GeneratorFreeFp)generator_random_free, (GeneratorMakeSampleFp)generator_random_make_sample);
+ sample_generator_init(&gen->base,
+ (GeneratorFreeFp)generator_random_free,
+ (GeneratorThreadContextCreateFp)generator_random_thread_context_create,
+ (GeneratorThreadContextFreeFp)generator_random_thread_context_free,
+ (GeneratorMakeSampleFp)generator_random_make_sample);
gen->dm = dm;
- gen->rng = BLI_rng_new(seed);
+ gen->seed = seed;
if (use_facearea) {
int numtris = dm->getNumLoopTri(dm);
@@ -488,6 +540,8 @@ typedef struct MSurfaceSampleGenerator_RayCast {
BVHTreeFromMesh bvhdata;
MeshSampleRayFp ray_cb;
+ MeshSampleThreadContextCreateFp thread_context_create_cb;
+ MeshSampleThreadContex
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list