[Bf-blender-cvs] [eecaca8b2af] ui-asset-view-template: Fix Cycles NaN assert in random walk SSS due to very small throughput

Brecht Van Lommel noreply at git.blender.org
Sun Mar 21 16:12:00 CET 2021


Commit: eecaca8b2af2564a9eabbf44f93ab3c16d83a96f
Author: Brecht Van Lommel
Date:   Fri Mar 19 13:14:56 2021 +0100
Branches: ui-asset-view-template
https://developer.blender.org/rBeecaca8b2af2564a9eabbf44f93ab3c16d83a96f

Fix Cycles NaN assert in random walk SSS due to very small throughput

Now terminate if there are many bounces and the throughput gets so small
that we get precision issues.

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

M	intern/cycles/kernel/kernel_subsurface.h
M	intern/cycles/kernel/kernel_volume.h

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

diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 55bbe7f95db..c75958e79c5 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -640,6 +640,12 @@ ccl_device_noinline
       /* If we hit the surface, we are done. */
       break;
     }
+    else if (throughput.x < VOLUME_THROUGHPUT_EPSILON &&
+             throughput.y < VOLUME_THROUGHPUT_EPSILON &&
+             throughput.z < VOLUME_THROUGHPUT_EPSILON) {
+      /* Avoid unnecessary work and precision issue when throughput gets really small. */
+      break;
+    }
   }
 
   kernel_assert(isfinite_safe(throughput.x) && isfinite_safe(throughput.y) &&
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 22a89997683..f6b34be040e 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -16,6 +16,12 @@
 
 CCL_NAMESPACE_BEGIN
 
+/* Ignore paths that have volume throughput below this value, to avoid unnecessary work
+ * and precision issues.
+ * todo: this value could be tweaked or turned into a probability to avoid unnecessary
+ * work in volumes and subsurface scattering. */
+#define VOLUME_THROUGHPUT_EPSILON 1e-6f
+
 /* Events for probalistic scattering */
 
 typedef enum VolumeIntegrateResult {
@@ -226,7 +232,6 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
                                                    const float object_step_size)
 {
   float3 tp = *throughput;
-  const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
 
   /* Prepare for stepping.
    * For shadows we do not offset all segments, since the starting point is
@@ -254,13 +259,15 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
     /* compute attenuation over segment */
     if (volume_shader_extinction_sample(kg, sd, state, new_P, &sigma_t)) {
       /* Compute expf() only for every Nth step, to save some calculations
-       * because exp(a)*exp(b) = exp(a+b), also do a quick tp_eps check then. */
+       * because exp(a)*exp(b) = exp(a+b), also do a quick VOLUME_THROUGHPUT_EPSILON
+       * check then. */
       sum += (-sigma_t * dt);
       if ((i & 0x07) == 0) { /* ToDo: Other interval? */
         tp = *throughput * exp3(sum);
 
         /* stop if nearly all light is blocked */
-        if (tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
+        if (tp.x < VOLUME_THROUGHPUT_EPSILON && tp.y < VOLUME_THROUGHPUT_EPSILON &&
+            tp.z < VOLUME_THROUGHPUT_EPSILON)
           break;
       }
     }
@@ -572,7 +579,6 @@ kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
                                                const float object_step_size)
 {
   float3 tp = *throughput;
-  const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
 
   /* Prepare for stepping.
    * Using a different step offset for the first step avoids banding artifacts. */
@@ -669,7 +675,8 @@ kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
         tp = new_tp;
 
         /* stop if nearly all light blocked */
-        if (tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps) {
+        if (tp.x < VOLUME_THROUGHPUT_EPSILON && tp.y < VOLUME_THROUGHPUT_EPSILON &&
+            tp.z < VOLUME_THROUGHPUT_EPSILON) {
           tp = zero_float3();
           break;
         }
@@ -770,8 +777,6 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
                                                VolumeSegment *segment,
                                                const float object_step_size)
 {
-  const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
-
   /* prepare for volume stepping */
   int max_steps;
   float step_size, step_shade_offset, steps_offset;
@@ -895,8 +900,9 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
       break;
 
     /* stop if nearly all light blocked */
-    if (accum_transmittance.x < tp_eps && accum_transmittance.y < tp_eps &&
-        accum_transmittance.z < tp_eps)
+    if (accum_transmittance.x < VOLUME_THROUGHPUT_EPSILON &&
+        accum_transmittance.y < VOLUME_THROUGHPUT_EPSILON &&
+        accum_transmittance.z < VOLUME_THROUGHPUT_EPSILON)
       break;
   }



More information about the Bf-blender-cvs mailing list