[Bf-blender-cvs] [f30b0c6] master: Switch BKE_smoke from OMP to BLI_task.
Bastien Montagne
noreply at git.blender.org
Mon Dec 28 00:40:04 CET 2015
Commit: f30b0c60cffc962e3925cfe950ce760261e8c7d7
Author: Bastien Montagne
Date: Mon Dec 28 00:29:36 2015 +0100
Branches: master
https://developer.blender.org/rBf30b0c60cffc962e3925cfe950ce760261e8c7d7
Switch BKE_smoke from OMP to BLI_task.
Gives a global speedup of about 5% in smoke simulation (as usual, parallelized chunks themselves
are about 15-25% quicker with BLI_task than with OMP), using a simple setup with two generators
(one from mesh, one from particles), an obstacle and a windfield.
===================================================================
M source/blender/blenkernel/intern/smoke.c
===================================================================
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 09cda60..ad2736a 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -44,6 +44,7 @@
#include "BLI_math.h"
#include "BLI_kdtree.h"
#include "BLI_kdopbvh.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_voxel.h"
@@ -723,7 +724,75 @@ static int get_lamp(Scene *scene, float *light)
* Obstacles
**********************************************************/
-static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds, SmokeCollSettings *scs, unsigned char *obstacle_map, float *velocityX, float *velocityY, float *velocityZ, float dt)
+typedef struct ObstaclesFromDMData {
+ SmokeDomainSettings *sds;
+ const MVert *mvert;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
+ BVHTreeFromMesh *tree;
+ unsigned char *obstacle_map;
+
+ bool has_velocity;
+ float *vert_vel;
+ float *velocityX, *velocityY, *velocityZ;
+} ObstaclesFromDMData;
+
+static void obstacles_from_derivedmesh_task_cb(void *userdata, void *UNUSED(userdata_chunk), int z)
+{
+ ObstaclesFromDMData *data = userdata;
+ SmokeDomainSettings *sds = data->sds;
+
+ /* slightly rounded-up sqrt(3 * (0.5)^2) == max. distance of cell boundary along the diagonal */
+ const float surface_distance = 0.867f;
+
+ for (int x = sds->res_min[0]; x < sds->res_max[0]; x++) {
+ for (int y = sds->res_min[1]; y < sds->res_max[1]; y++) {
+ const int index = smoke_get_index(x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]);
+
+ float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
+ BVHTreeNearest nearest = {0};
+ nearest.index = -1;
+ nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance */
+
+ /* find the nearest point on the mesh */
+ if (BLI_bvhtree_find_nearest(data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) != -1) {
+ const MLoopTri *lt = &data->looptri[nearest.index];
+ float weights[4];
+ int v1, v2, v3;
+
+ /* calculate barycentric weights for nearest point */
+ v1 = data->mloop[lt->tri[0]].v;
+ v2 = data->mloop[lt->tri[1]].v;
+ v3 = data->mloop[lt->tri[2]].v;
+ interp_weights_face_v3(
+ weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, NULL, nearest.co);
+
+ // DG TODO
+ if (data->has_velocity)
+ {
+ /* apply object velocity */
+ {
+ float hit_vel[3];
+ interp_v3_v3v3v3(hit_vel, &data->vert_vel[v1 * 3], &data->vert_vel[v2 * 3], &data->vert_vel[v3 * 3], weights);
+ data->velocityX[index] += hit_vel[0];
+ data->velocityY[index] += hit_vel[1];
+ data->velocityZ[index] += hit_vel[2];
+ }
+ }
+
+ /* tag obstacle cells */
+ data->obstacle_map[index] = 1;
+
+ if (data->has_velocity)
+ data->obstacle_map[index] |= 8;
+ }
+ }
+ }
+}
+
+static void obstacles_from_derivedmesh(
+ Object *coll_ob, SmokeDomainSettings *sds, SmokeCollSettings *scs,
+ unsigned char *obstacle_map, float *velocityX, float *velocityY, float *velocityZ, float dt)
{
if (!scs->dm) return;
{
@@ -732,13 +801,10 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
const MLoopTri *looptri;
const MLoop *mloop;
BVHTreeFromMesh treeData = {NULL};
- int numverts, i, z;
-
- /* slightly rounded-up sqrt(3 * (0.5)^2) == max. distance of cell boundary along the diagonal */
- const float surface_distance = 0.867f;
+ int numverts, i;
float *vert_vel = NULL;
- int has_velocity = 0;
+ bool has_velocity = false;
tstart();
@@ -763,7 +829,7 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
scs->numverts = numverts;
}
else {
- has_velocity = 1;
+ has_velocity = true;
}
}
@@ -795,51 +861,14 @@ static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds
}
if (bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6)) {
-#pragma omp parallel for schedule(static)
- for (z = sds->res_min[2]; z < sds->res_max[2]; z++) {
- int x, y;
- for (x = sds->res_min[0]; x < sds->res_max[0]; x++)
- for (y = sds->res_min[1]; y < sds->res_max[1]; y++) {
- int index = smoke_get_index(x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]);
-
- float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
- BVHTreeNearest nearest = {0};
- nearest.index = -1;
- nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance */
-
- /* find the nearest point on the mesh */
- if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, treeData.nearest_callback, &treeData) != -1) {
- const MLoopTri *lt = &looptri[nearest.index];
- float weights[4];
- int v1, v2, v3;
-
- /* calculate barycentric weights for nearest point */
- v1 = mloop[lt->tri[0]].v;
- v2 = mloop[lt->tri[1]].v;
- v3 = mloop[lt->tri[2]].v;
- interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
-
- // DG TODO
- if (has_velocity)
- {
- /* apply object velocity */
- {
- float hit_vel[3];
- interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
- velocityX[index] += hit_vel[0];
- velocityY[index] += hit_vel[1];
- velocityZ[index] += hit_vel[2];
- }
- }
-
- /* tag obstacle cells */
- obstacle_map[index] = 1;
-
- if (has_velocity)
- obstacle_map[index] |= 8;
- }
- }
- }
+ ObstaclesFromDMData data = {
+ .sds = sds, .mvert = mvert, .mloop = mloop, .looptri = looptri,
+ .tree = &treeData, .obstacle_map = obstacle_map,
+ .has_velocity = has_velocity, .vert_vel = vert_vel,
+ .velocityX = velocityX, .velocityY = velocityY, .velocityZ = velocityZ
+ };
+ BLI_task_parallel_range_ex(
+ sds->res_min[2], sds->res_max[2], &data, NULL, 0, obstacles_from_derivedmesh_task_cb, 0, false);
}
/* free bvh tree */
free_bvhtree_from_mesh(&treeData);
@@ -1220,8 +1249,85 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult
em_freeData(&em1);
}
+typedef struct EmitFromParticlesData {
+ SmokeFlowSettings *sfs;
+ KDTree *tree;
+ int hires_multiplier;
+
+ EmissionMap *em;
+ float *particle_vel;
+ float hr;
+
+ int *min, *max, *res;
+
+ float solid;
+ float smooth;
+ float hr_smooth;
+} EmitFromParticlesData;
+
+static void emit_from_particles_task_cb(void *userdata, void *UNUSED(userdata_chunk), int z)
+{
+ EmitFromParticlesData *data = userdata;
+ SmokeFlowSettings *sfs = data->sfs;
+ EmissionMap *em = data->em;
+ const int hires_multiplier = data->hires_multiplier;
+
+ for (int x = data->min[0]; x < data->max[0]; x++) {
+ for (int y = data->min[1]; y < data->max[1]; y++) {
+ /* take low res samples where possible */
+ if (hires_multiplier <= 1 || !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
+ /* get low res space coordinates */
+ const int lx = x / hires_multiplier;
+ const int ly = y / hires_multiplier;
+ const int lz = z / hires_multiplier;
+
+ const int index = smoke_get_index(lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
+ const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
+
+ /* find particle distance from the kdtree */
+ KDTreeNearest nearest;
+ const float range = data->solid + data->smooth;
+ BLI_kdtree_find_nearest(data->tree, ray_start, &nearest);
+
+ if (nearest.dist < range) {
+ em->influence[index] = (nearest.dist < data->solid) ?
+ 1.0f : (1.0f - (nearest.dist - data->solid) / data->smooth);
+ /* Uses particle velocity as initial velocity for smoke */
+ if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (sfs->psys->part->phystype != PART_PHYS_NO)) {
+ VECADDFAC(&em->velocity[index * 3], &em->velocity[index * 3],
+ &data->particle_vel[nearest.index * 3], sfs->vel_multi);
+ }
+ }
+ }
+
+ /* take high res samples if required */
+ if (hires_multiplier > 1) {
+ /* get low res space coordinates */
+ const float lx = ((float)x) * data->hr;
+ const float ly = ((float)y) * data->hr;
+ const float lz = ((float)z) * data->hr;
+
+ const int index = smoke_get_index(
+ x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
+ const float ray_start[3] = {lx + 0.5f * data->hr, ly + 0.5f * data->hr, lz + 0.5f * data->hr};
+
+ /* find particle distance from the kdtree */
+ KDTreeNearest nearest;
+ const float range = data->solid + data->hr_smooth;
+ BLI_kdtree_find_nearest(data->tree, ray_start, &nearest);
+
+ if (nearest.dist < range) {
+ em->influence_high[index] = (nearest.dist < data->solid) ?
+ 1.0f : (1.0f - (nearest.dist - data->solid) / data->smooth);
+ }
+ }
+
+ }
+ }
+}
-static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, Scene *scene, float dt)
+static void emit_from_particles(
+ Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, Scene *scene, float dt)
{
if (sfs && sfs->psys && sfs->psys->part && ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) // is particle system selected
{
@@ -1235,11 +1341,10 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
int bounds_margin = 1;
/* radius based flow */
- float solid = sfs->particle_size * 0.5f;
- float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
+ const float solid = sfs->particle_size * 0.5f;
+ const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
int hires_multiplier = 1;
- int z;
- KDTree *tree;
+ KDTree *tree = NULL;
sim.scene = scene;
sim.ob = flow_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list