[Bf-blender-cvs] [e378bd70ed6] master: Cleanup: remove code duplication in cycles light sampling

Weizhen Huang noreply at git.blender.org
Mon Dec 12 21:25:14 CET 2022


Commit: e378bd70ed6cb255f9a1cc092b88515bbf25d37c
Author: Weizhen Huang
Date:   Thu Dec 8 12:56:49 2022 +0100
Branches: master
https://developer.blender.org/rBe378bd70ed6cb255f9a1cc092b88515bbf25d37c

Cleanup: remove code duplication in cycles light sampling

There has been an attempt to reorganize this part, however, it seems that didn't compile on HIP, and is reverted in
rBc2dc65dfa4ae60fa5d2c3b0cfe86f99dcb5bf16f. This is another attempt of refactoring. as I have no idea why some things don't work on HIP, it's
best to check whether this compiles on other platforms.
The main changes are creating a new struct named `MeshLight` that is shared between `KernelLightDistribution` and `KernelLightTreeEmitter`,
and a bit of renaming, so that light sampling with or without light tree could call the same function.
Also, I noticed a patch D16714 referring to HIP compilation error. Not sure if it's related, but browsing
https://builder.blender.org/admin/#/builders/30/builds/7826/steps/7/logs/stdio, it didn't work on gfx1102, not gfx9*.

Differential Revision: https://developer.blender.org/D16722

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

M	intern/cycles/kernel/light/distribution.h
M	intern/cycles/kernel/light/light.h
M	intern/cycles/kernel/light/tree.h
M	intern/cycles/kernel/light/triangle.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/light.cpp

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

diff --git a/intern/cycles/kernel/light/distribution.h b/intern/cycles/kernel/light/distribution.h
index 2f75a53ec2a..97c60376748 100644
--- a/intern/cycles/kernel/light/distribution.h
+++ b/intern/cycles/kernel/light/distribution.h
@@ -59,41 +59,9 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
 {
   /* Sample light index from distribution. */
   const int index = light_distribution_sample(kg, &randu);
-  ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(light_distribution,
-                                                                               index);
-  const int prim = kdistribution->prim;
-
-  if (prim >= 0) {
-    /* Mesh light. */
-    const int object = kdistribution->mesh_light.object_id;
-
-    /* Exclude synthetic meshes from shadow catcher pass. */
-    if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
-        !(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
-      return false;
-    }
-
-    const int shader_flag = kdistribution->mesh_light.shader_flag;
-    if (!triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P)) {
-      return false;
-    }
-    ls->shader |= shader_flag;
-  }
-  else {
-    const int lamp = -prim - 1;
-
-    if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
-      return false;
-    }
-
-    if (!light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls)) {
-      return false;
-    }
-    ls->pdf_selection = kernel_data.integrator.distribution_pdf_lights;
-  }
-
-  ls->pdf *= ls->pdf_selection;
-  return (ls->pdf > 0.0f);
+  const float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
+  return light_sample<in_volume_segment>(
+      kg, randu, randv, time, P, bounce, path_flag, index, pdf_selection, ls);
 }
 
 ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg)
diff --git a/intern/cycles/kernel/light/light.h b/intern/cycles/kernel/light/light.h
index b33aecf8b62..d04bffe8f8b 100644
--- a/intern/cycles/kernel/light/light.h
+++ b/intern/cycles/kernel/light/light.h
@@ -14,6 +14,13 @@
 
 CCL_NAMESPACE_BEGIN
 
+/* Light info. */
+
+ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals kg, int index, int bounce)
+{
+  return (bounce > kernel_data_fetch(lights, index).max_bounces);
+}
+
 /* Sample point on an individual light. */
 
 template<bool in_volume_segment>
@@ -90,6 +97,68 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
   return in_volume_segment || (ls->pdf > 0.0f);
 }
 
+/* Sample a point on the chosen emitter. */
+
+template<bool in_volume_segment>
+ccl_device_noinline bool light_sample(KernelGlobals kg,
+                                      const float randu,
+                                      const float randv,
+                                      const float time,
+                                      const float3 P,
+                                      const int bounce,
+                                      const uint32_t path_flag,
+                                      const int emitter_index,
+                                      const float pdf_selection,
+                                      ccl_private LightSample *ls)
+{
+  int prim;
+  MeshLight mesh_light;
+  if (kernel_data.integrator.use_light_tree) {
+    ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
+                                                                           emitter_index);
+    prim = kemitter->prim;
+    mesh_light = kemitter->mesh_light;
+  }
+  else {
+    ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(
+        light_distribution, emitter_index);
+    prim = kdistribution->prim;
+    mesh_light = kdistribution->mesh_light;
+  }
+
+  /* A different value would be assigned in `triangle_light_sample()` if `!use_light_tree`. */
+  ls->pdf_selection = pdf_selection;
+
+  if (prim >= 0) {
+    /* Mesh light. */
+    const int object = mesh_light.object_id;
+
+    /* Exclude synthetic meshes from shadow catcher pass. */
+    if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
+        !(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
+      return false;
+    }
+
+    const int shader_flag = mesh_light.shader_flag;
+    if (!triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P)) {
+      return false;
+    }
+    ls->shader |= shader_flag;
+  }
+  else {
+    if (UNLIKELY(light_select_reached_max_bounces(kg, ~prim, bounce))) {
+      return false;
+    }
+
+    if (!light_sample<in_volume_segment>(kg, ~prim, randu, randv, P, path_flag, ls)) {
+      return false;
+    }
+  }
+
+  ls->pdf *= ls->pdf_selection;
+  return (ls->pdf > 0.0f);
+}
+
 /* Intersect ray with individual light. */
 
 ccl_device bool lights_intersect(KernelGlobals kg,
@@ -230,11 +299,4 @@ ccl_device_forceinline void light_update_position(KernelGlobals kg,
   }
 }
 
-/* Light info. */
-
-ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals kg, int index, int bounce)
-{
-  return (bounce > kernel_data_fetch(lights, index).max_bounces);
-}
-
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 3b683b5562f..19fdb87f803 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -189,7 +189,7 @@ ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg,
                                                  ccl_private float3 &centroid,
                                                  ccl_private packed_float3 &dir)
 {
-  const int prim_id = kemitter->prim_id;
+  const int prim_id = kemitter->prim;
   if (prim_id < 0) {
     const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ~prim_id);
     centroid = klight->co;
@@ -223,10 +223,10 @@ ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg,
     triangle_world_space_vertices(kg, object, prim_id, -1.0f, vertices);
     centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
 
-    if (kemitter->mesh_light.emission_sampling == EMISSION_SAMPLING_FRONT) {
+    if (kemitter->emission_sampling == EMISSION_SAMPLING_FRONT) {
       dir = safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
     }
-    else if (kemitter->mesh_light.emission_sampling == EMISSION_SAMPLING_BACK) {
+    else if (kemitter->emission_sampling == EMISSION_SAMPLING_BACK) {
       dir = -safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
     }
     else {
@@ -264,7 +264,7 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
     return;
   }
 
-  const int prim_id = kemitter->prim_id;
+  const int prim_id = kemitter->prim;
 
   if (in_volume_segment) {
     const float3 D = N_or_D;
@@ -568,8 +568,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
 
   const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
   float pdf_leaf = 1.0f;
-  float pdf_emitter_from_leaf = 1.0f;
-  int selected_light = -1;
+  float pdf_selection = 1.0f;
+  int selected_emitter = -1;
 
   int node_index = 0; /* Root node. */
 
@@ -579,8 +579,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
 
     if (knode->child_index <= 0) {
       /* At a leaf node, we pick an emitter. */
-      selected_light = light_tree_cluster_select_emitter<in_volume_segment>(
-          kg, randv, P, N_or_D, t, has_transmission, knode, &pdf_emitter_from_leaf);
+      selected_emitter = light_tree_cluster_select_emitter<in_volume_segment>(
+          kg, randv, P, N_or_D, t, has_transmission, knode, &pdf_selection);
       break;
     }
 
@@ -602,46 +602,14 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
     pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
   }
 
-  if (selected_light < 0) {
+  if (selected_emitter < 0) {
     return false;
   }
 
-  /* Sample a point on the chosen emitter. */
-  ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
-                                                                         selected_light);
-
-  /* TODO: this is the same code as light_distribution_sample, except the index is determined
-   * differently. Would it be better to refactor this into a separate function? */
-  const int prim = kemitter->prim_id;
-  if (prim >= 0) {
-    /* Mesh light. */
-    const int object = kemitter->mesh_light.object_id;
-
-    /* Exclude synthetic meshes from shadow catcher pass. */
-    if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
-        !(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
-      return false;
-    }
-
-    const int mesh_shader_flag = kemitter->mesh_light.shader_flag;
-    if (!triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P)) {
-      return false;
-    }
-    ls->shader |= mesh_shader_flag;
-  }
-  else {
-    if (UNLIKELY(light_select_reached_max_bounces(kg, ~prim, bounce))) {
-      return false;
-    }
-
-    if (!light_sample<in_volume_segment>(kg, ~prim, randu, randv, P, path_flag, ls)) {
-      return false;
-    }
-  }
+  pdf_selection *= pdf_leaf;
 
-  ls->pdf_selection = pdf_leaf * pdf_emitter_from_leaf;
-  ls->pdf *= ls->pdf_selection;
-  return (ls->pdf > 0);
+  return light_sample<in_volume_segment>(
+      kg, randu, randv, time, P, bounce, path_flag, selected_emitter, pdf_selection, ls);
 }
 
 /* We need to be able to find the probability of selecting a given light for MIS. */
diff --git a/intern/cycles/kernel/light/triangle.h b/intern/cycles/kernel/light/triangle.h
index 1a5e8e9e62c..829bacb31f3 100644
--- a/intern/cycles/kernel/light/triangle.h
+++ b/intern/cycles/kernel/light/triangle.h
@@ -306,7 +306,7 @@ ccl_device_forceinline bool triangle_light_tree_parameters(
 
   const int object = kemitter->mesh_light.object_id;
   float3 vertices[3];
-  triangle_world_space_vertices(kg, object, kemitter->prim_id, -1.0f, vertices);
+  triangle_world_space_vertices(kg, object, kemitter->prim, -1.0f, vertices);
 
   bool shape_above_surface = false;
   for (int i = 0; i < 3; i++) {
diff --git a/intern/cycles/ke

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list