[Bf-blender-cvs] [a4576b671c1] soc-2020-production-ready-light-tree: Fixed CUDA support for the light tree.

Sam Kottler noreply at git.blender.org
Sat Jul 4 21:26:51 CEST 2020


Commit: a4576b671c10b8c093769ad24f328616e49744e0
Author: Sam Kottler
Date:   Sat Jul 4 13:23:53 2020 -0600
Branches: soc-2020-production-ready-light-tree
https://developer.blender.org/rBa4576b671c10b8c093769ad24f328616e49744e0

Fixed CUDA support for the light tree.

Users can now use the light tree, with splitting, using CUDA.

The problem was that a few of the light tree functions used recursion
which meant the CUDA compiler couldn't predict how much stack space
to use.

===================================================================

M	intern/cycles/kernel/kernel_light.h
M	intern/cycles/kernel/kernel_path_surface.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 104df3ec8e2..b05bdde8d43 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -1610,35 +1610,7 @@ ccl_device float light_tree_pdf(KernelGlobals *kg,
   /* read in first part of node of light tree */
   int right_child_offset, first_distribution_id, num_emitters;
   update_node(kg, offset, &right_child_offset, &first_distribution_id, &num_emitters);
-
-  /* found a leaf */
-  if (right_child_offset == -1) {
-
-    /* if there are several emitters in this leaf then pick one of them */
-    if (num_emitters > 1) {
-
-      /* the case of being a light inside a leaf node with several lights.
-       * during sampling, a CDF is created based on importance, so here
-       * the probability of sampling this light using the CDF has to be
-       * computed. This is done by dividing the importance of this light
-       * by the total sum of the importance of all lights in the leaf. */
-      float sum = 0.0f;
-      for (int i = 0; i < num_emitters; ++i) {
-        sum += calc_light_importance(kg, P, N, offset, i);
-      }
-
-      if (sum == 0.0f) {
-        return 0.0f;
-      }
-
-      pdf *= calc_light_importance(kg, P, N, offset, distribution_id - first_distribution_id) /
-             sum;
-    }
-
-    return pdf;
-  }
-  else {  // Interior node, choose which child(ren) to go down
-
+  while (right_child_offset != -1) {
     int child_offsetL = offset + 4;
     int child_offsetR = 4 * right_child_offset;
 
@@ -1679,10 +1651,31 @@ ccl_device float light_tree_pdf(KernelGlobals *kg,
         offset = child_offsetR;
         pdf *= 1.0f - P_L;
       }
+      update_node(kg, offset, &right_child_offset, &first_distribution_id, &num_emitters);
+    }
+  }
 
-      return light_tree_pdf(kg, P, N, distribution_id, offset, pdf, false);
+  /* if there are several emitters in this leaf then pick one of them */
+  if (num_emitters > 1) {
+
+    /* the case of being a light inside a leaf node with several lights.
+     * during sampling, a CDF is created based on importance, so here
+     * the probability of sampling this light using the CDF has to be
+     * computed. This is done by dividing the importance of this light
+     * by the total sum of the importance of all lights in the leaf. */
+    float sum = 0.0f;
+    for (int i = 0; i < num_emitters; ++i) {
+      sum += calc_light_importance(kg, P, N, offset, i);
     }
+
+    if (sum == 0.0f) {
+      return 0.0f;
+    }
+
+    pdf *= calc_light_importance(kg, P, N, offset, distribution_id - first_distribution_id) / sum;
   }
+
+  return pdf;
 }
 
 /* computes the the probability of picking the given light out of all lights.
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index c8634c30dd8..c783305d99f 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -70,159 +70,161 @@ ccl_device void accum_light_tree_contribution(KernelGlobals *kg,
   float time = sd->time;
   int bounce = state->bounce;
 
-  /* read in first part of node of light tree */
-  int right_child_offset, distribution_id, num_emitters;
-  update_node(kg, offset, &right_child_offset, &distribution_id, &num_emitters);
-
-  /* found a leaf */
-  if (right_child_offset == -1) {
-
-    /* if there are several emitters in this leaf then pick one of them */
-    if (num_emitters > 1) {
+  float randu_stack[64];
+  float randv_stack[64];
+  int offset_stack[64];
+  float pdf_stack[64];
+
+  randu_stack[0] = randu;
+  randv_stack[0] = randv;
+  offset_stack[0] = offset;
+  pdf_stack[0] = pdf_factor;
+
+  int stack_idx = 0;
+
+  while (stack_idx > -1) {
+    randu = randu_stack[stack_idx];
+    randv = randv_stack[stack_idx];
+    offset = offset_stack[stack_idx];
+    pdf_factor = pdf_stack[stack_idx];
+    /* read in first part of node of light tree */
+    int right_child_offset, distribution_id, num_emitters;
+    update_node(kg, offset, &right_child_offset, &distribution_id, &num_emitters);
+
+    /* found a leaf */
+    if (right_child_offset == -1) {
+
+      /* if there are several emitters in this leaf then pick one of them */
+      if (num_emitters > 1) {
+
+        /* create and sample CDF without dynamic allocation.
+         * see comment in light_tree_sample() for this piece of code */
+        float sum = 0.0f;
+        for (int i = 0; i < num_emitters; ++i) {
+          sum += calc_light_importance(kg, P, N, offset, i);
+        }
 
-      /* create and sample CDF without dynamic allocation.
-       * see comment in light_tree_sample() for this piece of code */
-      float sum = 0.0f;
-      for (int i = 0; i < num_emitters; ++i) {
-        sum += calc_light_importance(kg, P, N, offset, i);
-      }
+        if (sum == 0.0f) {
+          --stack_idx;
+          continue;
+        }
 
-      if (sum == 0.0f) {
-        return;
-      }
+        float sum_inv = 1.0f / sum;
+        float cdf_L = 0.0f;
+        float cdf_R = 0.0f;
+        float prob = 0.0f;
+        int light;
+        for (int i = 1; i < num_emitters + 1; ++i) {
+          prob = calc_light_importance(kg, P, N, offset, i - 1) * sum_inv;
+          cdf_R = cdf_L + prob;
+          if (randu < cdf_R) {
+            light = i - 1;
+            break;
+          }
 
-      float sum_inv = 1.0f / sum;
-      float cdf_L = 0.0f;
-      float cdf_R = 0.0f;
-      float prob = 0.0f;
-      int light;
-      for (int i = 1; i < num_emitters + 1; ++i) {
-        prob = calc_light_importance(kg, P, N, offset, i - 1) * sum_inv;
-        cdf_R = cdf_L + prob;
-        if (randu < cdf_R) {
-          light = i - 1;
-          break;
+          cdf_L = cdf_R;
         }
+        distribution_id += light;
+        pdf_factor *= prob;
 
-        cdf_L = cdf_R;
+        /* rescale random number */
+        randu = (randu - cdf_L) / (cdf_R - cdf_L);
       }
-      distribution_id += light;
-      pdf_factor *= prob;
 
-      /* rescale random number */
-      randu = (randu - cdf_L) / (cdf_R - cdf_L);
-    }
+      /* pick a point on the chosen light(distribution_id) and calculate the
+       * probability of picking this point */
+      LightSample ls;
+      light_point_sample(kg, -1, randu, randv, time, P, bounce, distribution_id, &ls);
 
-    /* pick a point on the chosen light(distribution_id) and calculate the
-     * probability of picking this point */
-    LightSample ls;
-    light_point_sample(kg, -1, randu, randv, time, P, bounce, distribution_id, &ls);
+      /* combine pdfs */
+      ls.pdf *= pdf_factor;
 
-    /* combine pdfs */
-    ls.pdf *= pdf_factor;
-
-    if (ls.pdf <= 0.0f)
-      return;
+      if (ls.pdf <= 0.0f) {
+        --stack_idx;
+        continue;
+      }
 
-    /* compute and accumulate the total contribution of this light */
-    Ray light_ray;
-    light_ray.t = 0.0f;
+      /* compute and accumulate the total contribution of this light */
+      Ray light_ray;
+      light_ray.t = 0.0f;
 #ifdef __OBJECT_MOTION__
-    light_ray.time = sd->time;
+      light_ray.time = sd->time;
 #endif
-    BsdfEval L_light;
-    bool is_lamp;
-    float terminate = path_state_rng_light_termination(kg, state);
-    accum_light_contribution(kg,
-                             sd,
-                             emission_sd,
-                             &ls,
-                             state,
-                             &light_ray,
-                             &L_light,
-                             L,
-                             &is_lamp,
-                             terminate,
-                             throughput,
-                             scale_factor);
-
-    return;
-  }
-  else {  // Interior node, choose which child(ren) to go down
-
-    int child_offsetL = offset + 4;
-    int child_offsetR = 4 * right_child_offset;
+      BsdfEval L_light;
+      bool is_lamp;
+      float terminate = path_state_rng_light_termination(kg, state);
+      accum_light_contribution(kg,
+                               sd,
+                               emission_sd,
+                               &ls,
+                               state,
+                               &light_ray,
+                               &L_light,
+                               L,
+                               &is_lamp,
+                               terminate,
+                               throughput,
+                               scale_factor);
 
-    /* choose whether to go down both(split) or only one of the children */
-    if (can_split && split(kg, P, offset)) {
-      /* go down both child nodes */
-      accum_light_tree_contribution(kg,
-                                    randu,
-                                    randv,
-                                    child_offsetL,
-                                    pdf_factor,
-                                    true,
-                                    throughput,
-                                    scale_factor,
-                                    L,
-                                    state,
-                                    sd,
-                                    emission_sd);
-      accum_light_tree_contribution(kg,
-                                    randu,
-                                    randv,
-                                    child_offsetR,
-                                    pdf_factor,
-                                    true,
-                                    throughput,
-                                    scale_factor,
-                                    L,
-                                    state,
-                                    sd,
-                                    emission_sd);
+      --stack_idx;
+      continue;
     }
-    else {
-      /* go down one of the child nodes */
+    else {  // Interior node, choose which child(ren) to go down
+
+      int child_offsetL = offset + 4;
+      int child_offsetR = 4 * right_child_offset;
+
+      /* choose whether to go down both(split) or only one of the children */
+      if (can_split && split(kg, P, offset)) {
+        /* go down both child nodes */
+        //++stack_idx;
+        r

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list