[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