[Bf-blender-cvs] [50dbc55b955] cycles-x: Cycles X: refactor path termination in preparation for volume bounces

Brecht Van Lommel noreply at git.blender.org
Mon Jun 28 17:15:24 CEST 2021


Commit: 50dbc55b9554a3e81d0475935f109943e9e9031d
Author: Brecht Van Lommel
Date:   Thu Jun 17 17:56:33 2021 +0200
Branches: cycles-x
https://developer.blender.org/rB50dbc55b9554a3e81d0475935f109943e9e9031d

Cycles X: refactor path termination in preparation for volume bounces

To support similar logic as transparent and emissive surfaces.

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

M	intern/cycles/kernel/integrator/integrator_intersect_closest.h
M	intern/cycles/kernel/integrator/integrator_shade_shadow.h
M	intern/cycles/kernel/integrator/integrator_shade_surface.h
M	intern/cycles/kernel/integrator/integrator_state_util.h
M	intern/cycles/kernel/kernel_path_state.h
M	intern/cycles/kernel/kernel_types.h

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

diff --git a/intern/cycles/kernel/integrator/integrator_intersect_closest.h b/intern/cycles/kernel/integrator/integrator_intersect_closest.h
index a4538e8f771..39a0cad8c03 100644
--- a/intern/cycles/kernel/integrator/integrator_intersect_closest.h
+++ b/intern/cycles/kernel/integrator/integrator_intersect_closest.h
@@ -34,11 +34,17 @@ ccl_device_forceinline bool integrator_intersect_terminate(INTEGRATOR_STATE_ARGS
                                                            const int shader_flags)
 {
 
-  /* Optional AO bounce termination. */
+  /* Optional AO bounce termination.
+   * We continue evaluating emissive/transparent surfaces and volumes, similar
+   * to direct lighting. Only if we know there are none can we terminate the
+   * path immediately. */
   if (path_state_ao_bounce(INTEGRATOR_STATE_PASS)) {
     if (shader_flags & (SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
       INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
     }
+    else if (!integrator_state_volume_stack_is_empty(INTEGRATOR_STATE_PASS)) {
+      INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_TERMINATE_AFTER_VOLUME;
+    }
     else {
       return true;
     }
@@ -52,15 +58,20 @@ ccl_device_forceinline bool integrator_intersect_terminate(INTEGRATOR_STATE_ARGS
    * and evaluating the shader when not needed. Only for emission and transparent
    * surfaces in front of emission do we need to evaluate the shader, since we
    * perform MIS as part of indirect rays. */
-  const float probability = path_state_continuation_probability(INTEGRATOR_STATE_PASS);
+  const int path_flag = INTEGRATOR_STATE(path, flag);
+  const float probability = path_state_continuation_probability(INTEGRATOR_STATE_PASS, path_flag);
 
   if (probability != 1.0f) {
     const float terminate = path_state_rng_1D(kg, &rng_state, PRNG_TERMINATE);
 
     if (probability == 0.0f || terminate >= probability) {
-      if (shader_flags & (SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
-        /* Mark path to be terminated right after shader evaluation. */
-        INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_TERMINATE_IMMEDIATE;
+      if (shader_flags & SD_HAS_EMISSION) {
+        /* Mark path to be terminated right after shader evaluation on the surface. */
+        INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_TERMINATE_ON_NEXT_SURFACE;
+      }
+      else if (!integrator_state_volume_stack_is_empty(INTEGRATOR_STATE_PASS)) {
+        /* TODO: only do this for emissive volumes. */
+        INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_TERMINATE_IN_NEXT_VOLUME;
       }
       else {
         return true;
@@ -130,11 +141,20 @@ ccl_device void integrator_intersect_closest(INTEGRATOR_STATE_ARGS)
   integrator_state_write_isect(INTEGRATOR_STATE_PASS, &isect);
 
 #ifdef __VOLUME__
-  if (INTEGRATOR_STATE_ARRAY(volume_stack, 0, shader) != SHADER_NONE) {
-    /* Continue with volume kernel if we are inside a volume, regardless
-     * if we hit anything. */
-    INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST,
-                         DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME);
+  if (!integrator_state_volume_stack_is_empty(INTEGRATOR_STATE_PASS)) {
+    const int shader = (hit) ? intersection_get_shader(kg, &isect) : SHADER_NONE;
+    const int flags = (hit) ? kernel_tex_fetch(__shaders, shader).flags : 0;
+
+    if (!integrator_intersect_terminate<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>(
+            INTEGRATOR_STATE_PASS, &isect, flags)) {
+      /* Continue with volume kernel if we are inside a volume, regardless
+       * if we hit anything. */
+      INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST,
+                           DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME);
+    }
+    else {
+      INTEGRATOR_PATH_TERMINATE(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST);
+    }
     return;
   }
 #endif
diff --git a/intern/cycles/kernel/integrator/integrator_shade_shadow.h b/intern/cycles/kernel/integrator/integrator_shade_shadow.h
index d140a7461d4..4bc9d00817f 100644
--- a/intern/cycles/kernel/integrator/integrator_shade_shadow.h
+++ b/intern/cycles/kernel/integrator/integrator_shade_shadow.h
@@ -105,7 +105,7 @@ ccl_device_inline bool integrate_transparent_shadow(INTEGRATOR_STATE_ARGS, const
     /* Volume shaders. */
     if (hit < num_recorded_hits || !shadow_intersections_has_remaining(num_hits)) {
 #  ifdef __VOLUME__
-      if (INTEGRATOR_STATE_ARRAY(shadow_volume_stack, 0, shader) != SHADER_NONE) {
+      if (!integrator_state_shadow_volume_stack_is_empty(INTEGRATOR_STATE_PASS)) {
         const float3 shadow = integrate_transparent_volume_shadow(
             INTEGRATOR_STATE_PASS, hit, num_recorded_hits);
         const float3 throughput = INTEGRATOR_STATE(shadow_path, throughput) * shadow;
diff --git a/intern/cycles/kernel/integrator/integrator_shade_surface.h b/intern/cycles/kernel/integrator/integrator_shade_surface.h
index d07f6704b8c..6f04d261e11 100644
--- a/intern/cycles/kernel/integrator/integrator_shade_surface.h
+++ b/intern/cycles/kernel/integrator/integrator_shade_surface.h
@@ -297,14 +297,17 @@ ccl_device bool integrate_surface(INTEGRATOR_STATE_ARGS,
   if (!(sd.flag & SD_HAS_ONLY_VOLUME)) {
 #endif
 
-    const int path_flag = INTEGRATOR_STATE(path, flag);
+    {
+      const int path_flag = INTEGRATOR_STATE(path, flag);
 #ifdef __SUBSURFACE__
-    /* Can skip shader evaluation for BSSRDF exit point without bump mapping. */
-    if (!(path_flag & PATH_RAY_SUBSURFACE) || ((sd.flag & SD_HAS_BSSRDF_BUMP)))
+      /* Can skip shader evaluation for BSSRDF exit point without bump mapping. */
+      if (!(path_flag & PATH_RAY_SUBSURFACE) || ((sd.flag & SD_HAS_BSSRDF_BUMP)))
 #endif
-    {
-      /* Evaluate shader. */
-      shader_eval_surface<node_feature_mask>(INTEGRATOR_STATE_PASS, &sd, render_buffer, path_flag);
+      {
+        /* Evaluate shader. */
+        shader_eval_surface<node_feature_mask>(
+            INTEGRATOR_STATE_PASS, &sd, render_buffer, path_flag);
+      }
     }
 
 #ifdef __SUBSURFACE__
@@ -344,7 +347,11 @@ ccl_device bool integrate_surface(INTEGRATOR_STATE_ARGS,
     /* Perform path termination. Most paths have already been terminated in
      * the intersect_closest kernel, this is just for emission and for dividing
      * throughput by the probability at the right moment. */
-    const float probability = path_state_continuation_probability(INTEGRATOR_STATE_PASS);
+    const int path_flag = INTEGRATOR_STATE(path, flag);
+    const float probability = (path_flag & PATH_RAY_TERMINATE_ON_NEXT_SURFACE) ?
+                                  0.0f :
+                                  path_state_continuation_probability(INTEGRATOR_STATE_PASS,
+                                                                      path_flag);
     if (probability == 0.0f) {
       return false;
     }
diff --git a/intern/cycles/kernel/integrator/integrator_state_util.h b/intern/cycles/kernel/integrator/integrator_state_util.h
index 2d38522e9b7..a15c187b127 100644
--- a/intern/cycles/kernel/integrator/integrator_state_util.h
+++ b/intern/cycles/kernel/integrator/integrator_state_util.h
@@ -113,6 +113,11 @@ ccl_device_forceinline void integrator_state_write_volume_stack(INTEGRATOR_STATE
   INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, shader) = entry.shader;
 }
 
+ccl_device_forceinline bool integrator_state_volume_stack_is_empty(INTEGRATOR_STATE_CONST_ARGS)
+{
+  return INTEGRATOR_STATE_ARRAY(volume_stack, 0, shader) == SHADER_NONE;
+}
+
 /* Shadow Intersection */
 
 ccl_device_forceinline void integrator_state_write_shadow_isect(
@@ -162,6 +167,12 @@ integrator_state_read_shadow_volume_stack(INTEGRATOR_STATE_CONST_ARGS, int i)
   return entry;
 }
 
+ccl_device_forceinline bool integrator_state_shadow_volume_stack_is_empty(
+    INTEGRATOR_STATE_CONST_ARGS)
+{
+  return INTEGRATOR_STATE_ARRAY(shadow_volume_stack, 0, shader) == SHADER_NONE;
+}
+
 ccl_device_forceinline void integrator_state_write_shadow_volume_stack(INTEGRATOR_STATE_ARGS,
                                                                        int i,
                                                                        VolumeStack entry)
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index c2a156c9b77..f736285dfa1 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -105,7 +105,7 @@ ccl_device_inline void path_state_next(INTEGRATOR_STATE_ARGS, int label)
 
     flag |= PATH_RAY_TRANSPARENT;
     if (transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
-      flag |= PATH_RAY_TERMINATE_IMMEDIATE;
+      flag |= PATH_RAY_TERMINATE_ON_NEXT_SURFACE;
     }
 
     if (!kernel_data.integrator.transparent_shadows)
@@ -245,15 +245,10 @@ ccl_device_inline uint path_state_ray_visibility(INTEGRATOR_STATE_CONST_ARGS)
   return visibility;
 }
 
-ccl_device_inline float path_state_continuation_probability(INTEGRATOR_STATE_CONST_ARGS)
+ccl_device_inline float path_state_continuation_probability(INTEGRATOR_STATE_CONST_ARGS,
+                                                            const uint32_t path_flag)
 {
-  const uint32_t flag = INTEGRATOR_STATE(path, flag);
-
-  if (flag & PATH_RAY_TERMINATE_IMMEDIATE) {
-    /* Ray is to be terminated immediately. */
-    return 0.0f;
-  }
-  else if (flag & PATH_RAY_TRANSPARENT) {
+  if (path_flag & PATH_RAY_TRANSPARENT) {
     const uint32_t transparent_bounce = INTEGRATOR_STATE(path, transparent_bounce);
     /* Do at least specified number of bounces without RR. */
     if (transparent_bounce <= kernel_data.integrator.transparent_min_bounce) {
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index f8a470291d4..38b0f830f79 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -263,44 +263,49 @@ enum PathRayFlag {
   PATH_RAY_TRANSPARENT_BACKGROUND = (1 << 14),
 
   /* Terminate ray immediately at next bounce. */
-  PATH_RAY_TERMINATE_IMMEDIATE = (1 << 15),
+  PATH_RAY_TERMINATE_ON_NEXT_SURFACE = (1 << 15),
+  PATH_RAY_TERMINATE_IN_NEXT_VOLUME = (1 << 16),
 
   /* Ray is to be terminated, but continue with transparent bounces and
  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list