[Bf-blender-cvs] [92030f83362] soc-2018-hair-shader: Ringfence possible NaNs with degenerate hair geometry

L. E. Segovia noreply at git.blender.org
Wed May 23 23:01:19 CEST 2018


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;



More information about the Bf-blender-cvs mailing list