Commit: 92030f83362fe567f78e519e0acca0700287a933
Author: L. E. Segovia
Date:   Wed May 23 20:59:40 2018 +0000
Branches: soc-2018-hair-shader
https://developer.blender.org/rB92030f83362fe567f78e519e0acca0700287a933

Ringfence possible NaNs with degenerate hair geometry

There are two ways: radiance (F) and intersect position (sd->P)

F comes from invalid core distance, sd->P from invalid intersect position
(which is usually caused from a NaN in ray->t, outside our shader)

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

M       intern/cycles/kernel/closure/bsdf_hair_principled.h
M       intern/cycles/kernel/geom/geom_curve.h
M       intern/cycles/util/util_math_float3.h

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

diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h 
b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index 9b02fb28a7d..36d2325a397 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -160,6 +160,7 @@ ccl_device int bsdf_principled_hair_setup(KernelGlobals 
*kg, ShaderData *sd, Pri
 
        float3 dPdCD, curve_P;
        float h = curve_core_distance(kg, sd, &curve_P, &dPdCD);
+       assert(isfinite_safe(h));
        dPdCD = normalize(dPdCD);
        bsdf->geom = make_float4(dPdCD.x, dPdCD.y, dPdCD.z, h);
 
@@ -205,6 +206,8 @@ ccl_device float3 bsdf_principled_hair_eval(const 
ShaderData *sd, const ShaderCl
        //*pdf = 0.0f;
        //return make_float3(0.0f, 0.0f, 0.0f);
 
+       assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
+
        const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF*) sc;
        float3 dPdCD = float4_to_float3(bsdf->geom);
 
@@ -251,14 +254,18 @@ ccl_device float3 bsdf_principled_hair_eval(const 
ShaderData *sd, const ShaderCl
        float4 F;
        F  = Ap[0] * azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t)
                           * longitudinal_scattering(angles[0], angles[1], 
sin_theta_o, cos_theta_o, bsdf->v);
+       assert(isfinite3_safe(F));
 
        F += Ap[1] * azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t)
                           * longitudinal_scattering(angles[2], angles[3], 
sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
+       assert(isfinite3_safe(F));
 
        F += Ap[2] * azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t)
                           * longitudinal_scattering(angles[4], angles[5], 
sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+       assert(isfinite3_safe(F));
 
        F += Ap[3] * longitudinal_scattering(sin_theta_i, cos_theta_i, 
sin_theta_o, cos_theta_o, 4.0f*bsdf->v) * M_1_2PI_F;
+       assert(isfinite3_safe(F));
 
        //printf("%f %f %f %f\n", (double)F.x, (double)F.y, (double)F.z, 
(double)F.w);
 
@@ -353,14 +360,18 @@ ccl_device int bsdf_principled_hair_sample(ShaderData 
*sd, const ShaderClosure *
        float4 F;
        F  = Ap[0] * azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t)
                           * longitudinal_scattering(angles[0], angles[1], 
sin_theta_o, cos_theta_o, bsdf->v);
+       assert(isfinite3_safe(F));
 
        F += Ap[1] * azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t)
                           * longitudinal_scattering(angles[2], angles[3], 
sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
+       assert(isfinite3_safe(F));
 
        F += Ap[2] * azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t)
                           * longitudinal_scattering(angles[4], angles[5], 
sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+       assert(isfinite3_safe(F));
 
        F += Ap[3] * longitudinal_scattering(sin_theta_i, cos_theta_i, 
sin_theta_o, cos_theta_o, 4.0f*bsdf->v) * M_1_2PI_F;
+       assert(isfinite3_safe(F));
 
        *eval = float4_to_float3(F);
        *pdf = F.w;
diff --git a/intern/cycles/kernel/geom/geom_curve.h 
b/intern/cycles/kernel/geom/geom_curve.h
index d0bad749945..887f1927a94 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -27,27 +27,27 @@ CCL_NAMESPACE_BEGIN
 
 ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 
p2, float3 p3)
 {
-    float fc = 0.71f;
-    float data[4];
-    float t2 = t * t;
-    data[0] = -3.0f * fc          * t2  + 4.0f * fc * t                  - fc;
-    data[1] =  3.0f * (2.0f - fc) * t2  + 2.0f * (fc - 3.0f) * t;
-    data[2] =  3.0f * (fc - 2.0f) * t2  + 2.0f * (3.0f - 2.0f * fc) * t  + fc;
-    data[3] =  3.0f * fc          * t2  - 2.0f * fc * t;
-    return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+       float fc = 0.71f;
+       float data[4];
+       float t2 = t * t;
+       data[0] = -3.0f * fc          * t2  + 4.0f * fc * t                  - 
fc;
+       data[1] =  3.0f * (2.0f - fc) * t2  + 2.0f * (fc - 3.0f) * t;
+       data[2] =  3.0f * (fc - 2.0f) * t2  + 2.0f * (3.0f - 2.0f * fc) * t  + 
fc;
+       data[3] =  3.0f * fc          * t2  - 2.0f * fc * t;
+       return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
 }
 
 ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, 
float3 p3)
 {
-    float data[4];
-    float fc = 0.71f;
-    float t2 = t * t;
-    float t3 = t2 * t;
-    data[0] = -fc          * t3  + 2.0f * fc          * t2 - fc * t;
-    data[1] =  (2.0f - fc) * t3  + (fc - 3.0f)        * t2 + 1.0f;
-    data[2] =  (fc - 2.0f) * t3  + (3.0f - 2.0f * fc) * t2 + fc * t;
-    data[3] =  fc          * t3  - fc * t2;
-    return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+       float data[4];
+       float fc = 0.71f;
+       float t2 = t * t;
+       float t3 = t2 * t;
+       data[0] = -fc          * t3  + 2.0f * fc          * t2 - fc * t;
+       data[1] =  (2.0f - fc) * t3  + (fc - 3.0f)        * t2 + 1.0f;
+       data[2] =  (fc - 2.0f) * t3  + (3.0f - 2.0f * fc) * t2 + fc * t;
+       data[3] =  fc          * t3  - fc * t2;
+       return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
 }
 
 /* Reading attributes on various curve elements */
@@ -128,55 +128,57 @@ ccl_device float3 curve_attribute_float3(KernelGlobals 
*kg, const ShaderData *sd
 
 ccl_device float curve_core_distance(KernelGlobals *kg, ShaderData *sd, float3 
*curve_P, float3 *dPdCD)
 {
-    if((sd->type & PRIMITIVE_ALL_CURVE) == 0) {
-        return 0.0f;
-    }
-
-    int flag = kernel_data.curve.curveflags;
-    float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
-    int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
-    int k1 = k0 + 1;
-
-    float curve_r;
-    if(flag & CURVE_KN_INTERPOLATE) {
-        int ka = max(k0 - 1, __float_as_int(curvedata.x));
-        int kb = min(k1 + 1, __float_as_int(curvedata.x) + 
__float_as_int(curvedata.y) - 1);
-
-        float4 P_curve[4];
-        if(sd->type & PRIMITIVE_CURVE) {
-            P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
-            P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
-            P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
-            P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
-        }
-        else {
-            motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, 
k0, k1, kb, P_curve);
-        }
-
-        *curve_P = curvepoint(sd->u,
-                             float4_to_float3(P_curve[0]),
-                             float4_to_float3(P_curve[1]),
-                             float4_to_float3(P_curve[2]),
-                             float4_to_float3(P_curve[3]));
-        curve_r = mix(P_curve[1].w, P_curve[2].w, sd->u);
-    }
-    else {
-        float4 P_curve[2];
-        if(sd->type & PRIMITIVE_CURVE) {
-            P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
-            P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
-        }
-        else {
-            motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, 
P_curve);
-        }
-        *curve_P = mix(float4_to_float3(P_curve[0]), 
float4_to_float3(P_curve[1]), sd->u);
-        curve_r = mix(P_curve[0].w, P_curve[1].w, sd->u);
-    }
-
-    *dPdCD = normalize(cross(sd->dPdu, sd->I));
-    float h = dot(*dPdCD, sd->P - *curve_P)/curve_r;
-    assert(fabsf(h) <= 2.f);
-    return h;
+       if((sd->type & PRIMITIVE_ALL_CURVE) == 0) {
+               return 0.0f;
+       }
+
+       assert(isfinite3_safe(sd->P));
+
+       int flag = kernel_data.curve.curveflags;
+       float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+       int k0 = __float_as_int(curvedata.x) + 
PRIMITIVE_UNPACK_SEGMENT(sd->type);
+       int k1 = k0 + 1;
+
+       float curve_r;
+       if(flag & CURVE_KN_INTERPOLATE) {
+               int ka = max(k0 - 1, __float_as_int(curvedata.x));
+               int kb = min(k1 + 1, __float_as_int(curvedata.x) + 
__float_as_int(curvedata.y) - 1);
+
+               float4 P_curve[4];
+               if(sd->type & PRIMITIVE_CURVE) {
+                       P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+                       P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+                       P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+                       P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+               }
+               else {
+                       motion_cardinal_curve_keys(kg, sd->object, sd->prim, 
sd->time, ka, k0, k1, kb, P_curve);
+               }
+
+               *curve_P = curvepoint(sd->u,
+                                                        
float4_to_float3(P_curve[0]),
+                                                        
float4_to_float3(P_curve[1]),
+                                                        
float4_to_float3(P_curve[2]),
+                                                        
float4_to_float3(P_curve[3]));
+               curve_r = mix(P_curve[1].w, P_curve[2].w, sd->u);
+       }
+       else {
+               float4 P_curve[2];
+               if(sd->type & PRIMITIVE_CURVE) {
+                       P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+                       P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
+               }
+               else {
+                       motion_curve_keys(kg, sd->object, sd->prim, sd->time, 
k0, k1, P_curve);
+               }
+               *curve_P = mix(float4_to_float3(P_curve[0]), 
float4_to_float3(P_curve[1]), sd->u);
+               curve_r = mix(P_curve[0].w, P_curve[1].w, sd->u);
+       }
+
+       *dPdCD = normalize(cross(sd->dPdu, sd->I));
+       float h = dot(*dPdCD, sd->P - *curve_P)/curve_r;
+       assert(fabsf(h) <= 2.f);
+       return h;
 }
 
 /* Curve thickness */
diff --git a/intern/cycles/util/util_math_float3.h 
b/intern/cycles/util/util_math_float3.h
index 620d0d516fe..aa961b96db5 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -379,12 +379,12 @@ ccl_device_inline bool isequal_float3(const float3 a, 
const float3 b)
 
 ccl_device_inline float3 exp3(float3 v)
 {
-    return make_float3(expf(v.x), expf(v.y), expf(v.z));
+       return make_float3(expf(v.x), expf(v.y), expf(v.z));
 }
 
 ccl_device_inline float3 log3(float3 v)
 {
-    return make_float3(logf(v.x), logf(v.y), logf(v.z));
+       return make_float3(logf(v.x), logf(v.y), logf(v.z));
 }
 
 ccl_device_inline bool isfinite3_safe(float3 v)
@@ -392,6 +392,11 @@ ccl_device_inline bool isfinite3_safe(float3 v)
        return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
 }
 
+ccl_device_inline bool isfinite3_safe(float4 v)
+{
+       return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
+}
+
 ccl_device_inline float3 ensure_finite3(float3 v)
 {
        if(!isfinite_safe(v.x)) v.x = 0.0f;

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to