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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to