From 48398b223be54f3bbe7b082f59ac421ca3f3e43a Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 28 Feb 2025 19:50:23 +0100 Subject: [PATCH] Cleanup: Fix various divisions by zero reported by ASAN Pull Request: https://projects.blender.org/blender/blender/pulls/135326 --- intern/cycles/bvh/binning.cpp | 2 +- intern/cycles/kernel/closure/bsdf_microfacet.h | 2 +- intern/cycles/kernel/geom/shader_data.h | 15 +++++++++------ .../kernel/integrator/intersect_volume_stack.h | 2 +- intern/cycles/kernel/light/area.h | 8 ++++---- intern/cycles/kernel/light/point.h | 4 ++-- intern/cycles/kernel/light/sample.h | 2 +- intern/cycles/kernel/light/spot.h | 4 ++-- intern/cycles/scene/camera.cpp | 4 ++-- 9 files changed, 23 insertions(+), 20 deletions(-) diff --git a/intern/cycles/bvh/binning.cpp b/intern/cycles/bvh/binning.cpp index 8c440438217..760859c52bc 100644 --- a/intern/cycles/bvh/binning.cpp +++ b/intern/cycles/bvh/binning.cpp @@ -77,7 +77,7 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange &job, /* compute number of bins to use and precompute scaling factor for binning */ num_bins = min(size_t(MAX_BINS), size_t(4.0f + 0.05f * size())); - scale = reciprocal(cent_bounds_.size()) * make_float3((float)num_bins); + scale = safe_divide(cent_bounds_.size(), make_float3((float)num_bins)); /* initialize binning counter and bounds */ BoundBox bin_bounds[MAX_BINS][4]; /* bounds for every bin in every dimension */ diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index f72abff6e7e..22eaa5df1c5 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -677,7 +677,7 @@ ccl_device int bsdf_microfacet_sample(KernelGlobals kg, } const float m_eta = bsdf->ior; - const float m_inv_eta = 1.0f / bsdf->ior; + const float m_inv_eta = safe_divide(1.0f, bsdf->ior); const float alpha_x = bsdf->alpha_x; const float alpha_y = bsdf->alpha_y; bool m_singular = !bsdf_microfacet_eval_flag(bsdf); diff --git a/intern/cycles/kernel/geom/shader_data.h b/intern/cycles/kernel/geom/shader_data.h index a8cdaf46f29..99cd7ae04f5 100644 --- a/intern/cycles/kernel/geom/shader_data.h +++ b/intern/cycles/kernel/geom/shader_data.h @@ -274,6 +274,9 @@ ccl_device void shader_setup_from_displace(KernelGlobals kg, 0.5f, !(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED), false); + + /* Assign some incoming direction to avoid division by zero. */ + sd->wi = sd->N; } /* ShaderData setup for point on curve. */ @@ -321,7 +324,7 @@ ccl_device void shader_setup_from_curve(KernelGlobals kg, P_curve[3] = kernel_data_fetch(curve_keys, kb); /* Interpolate position and tangent. */ - sd->P = make_float3(catmull_rom_basis_derivative(P_curve, sd->u)); + sd->P = make_float3(catmull_rom_basis_eval(P_curve, sd->u)); # ifdef __DPDU__ sd->dPdu = make_float3(catmull_rom_basis_derivative(P_curve, sd->u)); # endif @@ -334,12 +337,12 @@ ccl_device void shader_setup_from_curve(KernelGlobals kg, # endif } - /* No view direction, normals or bitangent. */ - sd->wi = zero_float3(); - sd->N = zero_float3(); - sd->Ng = zero_float3(); + /* Pick arbitrary view direction, normals and bitangent to avoid NaNs elsewhere. */ + sd->wi = normalize(cross(make_float3(0, 1, 0), sd->dPdu)); + sd->N = sd->wi; + sd->Ng = sd->wi; # ifdef __DPDU__ - sd->dPdv = zero_float3(); + sd->dPdv = cross(sd->dPdu, sd->Ng); # endif /* No ray differentials currently. */ diff --git a/intern/cycles/kernel/integrator/intersect_volume_stack.h b/intern/cycles/kernel/integrator/intersect_volume_stack.h index d539a558b2e..14ff1f779cc 100644 --- a/intern/cycles/kernel/integrator/intersect_volume_stack.h +++ b/intern/cycles/kernel/integrator/intersect_volume_stack.h @@ -28,7 +28,7 @@ ccl_device void integrator_volume_stack_update_for_subsurface(KernelGlobals kg, Ray volume_ray ccl_optional_struct_init; volume_ray.P = from_P; - volume_ray.D = normalize_len(to_P - from_P, &volume_ray.tmax); + volume_ray.D = safe_normalize_len(to_P - from_P, &volume_ray.tmax); volume_ray.tmin = 0.0f; volume_ray.self.object = INTEGRATOR_STATE(state, isect, object); volume_ray.self.prim = INTEGRATOR_STATE(state, isect, prim); diff --git a/intern/cycles/kernel/light/area.h b/intern/cycles/kernel/light/area.h index 4a118f50cb2..af0db8c76b2 100644 --- a/intern/cycles/kernel/light/area.h +++ b/intern/cycles/kernel/light/area.h @@ -67,7 +67,7 @@ ccl_device_inline float area_light_rect_sample(const float3 P, * the extra +pi that would remain in the expression for au can be removed by flipping the sign * of cos(au) and sin(au), which also cancels if we flip the sign of b1 in the fu term. */ const float au = rand.x * S + g2 + g3; - const float fu = (cosf(au) * b0 + b1) / sinf(au); + const float fu = safe_divide(cosf(au) * b0 + b1, sinf(au)); float cu = copysignf(1.0f / sqrtf(fu * fu + b0sq), fu); cu = clamp(cu, -1.0f, 1.0f); /* Compute xu. */ @@ -96,7 +96,7 @@ ccl_device_inline float area_light_rect_sample(const float3 P, * needed for the case where the light is viewed from grazing angles, see e.g. #98930. */ const float t = len(dir); - return -t * t * t / (z0 * len_u * len_v); + return safe_divide(-t * t * t, (z0 * len_u * len_v)); } return 1.0f / S; } @@ -306,7 +306,7 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight, if (sample_coord) { *light_P = light_P_new; - ls->D = normalize_len(*light_P - ray_P, &ls->t); + ls->D = safe_normalize_len(*light_P - ray_P, &ls->t); } /* Convert radiant flux to radiance. */ @@ -384,7 +384,7 @@ ccl_device_forceinline void area_light_mnee_sample_update(const ccl_global Kerne area_light_eval(klight, P, &ls->P, ls, zero_float2(), true); } else { - ls->D = normalize_len(ls->P - P, &ls->t); + ls->D = safe_normalize_len(ls->P - P, &ls->t); area_light_eval(klight, P, &ls->P, ls, zero_float2(), false); /* Convert pdf to be in area measure. */ ls->pdf /= light_pdf_area_to_solid_angle(ls->Ng, -ls->D, ls->t); diff --git a/intern/cycles/kernel/light/point.h b/intern/cycles/kernel/light/point.h index 8346351a920..3bc8a0a2eb7 100644 --- a/intern/cycles/kernel/light/point.h +++ b/intern/cycles/kernel/light/point.h @@ -66,7 +66,7 @@ ccl_device_inline bool point_light_sample(KernelGlobals kg, ls->P += disk_light_sample(lightN, rand) * klight->spot.radius; } - ls->D = normalize_len(ls->P - P, &ls->t); + ls->D = safe_normalize_len(ls->P - P, &ls->t); ls->Ng = -ls->D; /* PDF. */ @@ -102,7 +102,7 @@ ccl_device_forceinline void point_light_mnee_sample_update(KernelGlobals kg, const float3 N, const uint32_t path_flag) { - ls->D = normalize_len(ls->P - P, &ls->t); + ls->D = safe_normalize_len(ls->P - P, &ls->t); const float radius = klight->spot.radius; diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h index 7e2434b72dd..e550bf93b2a 100644 --- a/intern/cycles/kernel/light/sample.h +++ b/intern/cycles/kernel/light/sample.h @@ -233,7 +233,7 @@ ccl_device_inline void shadow_ray_setup(const ccl_private ShaderData *ccl_restri else { /* other lights, avoid self-intersection */ ray->D = ls->P - P; - ray->D = normalize_len(ray->D, &ray->tmax); + ray->D = safe_normalize_len(ray->D, &ray->tmax); } } else { diff --git a/intern/cycles/kernel/light/spot.h b/intern/cycles/kernel/light/spot.h index 9fb4f1498df..55447556363 100644 --- a/intern/cycles/kernel/light/spot.h +++ b/intern/cycles/kernel/light/spot.h @@ -133,7 +133,7 @@ ccl_device_inline bool spot_light_sample(KernelGlobals kg, ls->P += disk_light_sample(lightN, rand) * klight->spot.radius; } - ls->D = normalize_len(ls->P - P, &ls->t); + ls->D = safe_normalize_len(ls->P - P, &ls->t); ls->Ng = -ls->D; /* Attenuation. */ @@ -177,7 +177,7 @@ ccl_device_forceinline void spot_light_mnee_sample_update(KernelGlobals kg, const float3 N, const uint32_t path_flag) { - ls->D = normalize_len(ls->P - P, &ls->t); + ls->D = safe_normalize_len(ls->P - P, &ls->t); ls->eval_fac = klight->spot.eval_fac; diff --git a/intern/cycles/scene/camera.cpp b/intern/cycles/scene/camera.cpp index d0386273699..afde310bc9b 100644 --- a/intern/cycles/scene/camera.cpp +++ b/intern/cycles/scene/camera.cpp @@ -312,11 +312,11 @@ void Camera::update(Scene *scene) if (camera_type == CAMERA_PERSPECTIVE) { float3 v = transform_perspective(&full_rastertocamera, - make_float3(full_width, full_height, 1.0f)); + make_float3(full_width, full_height, 0.0f)); frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x)); frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y)); - v = transform_perspective(&full_rastertocamera, make_float3(0.0f, 0.0f, 1.0f)); + v = transform_perspective(&full_rastertocamera, make_float3(0.0f, 0.0f, 0.0f)); frustum_left_normal = normalize(make_float3(-v.z, 0.0f, v.x)); frustum_bottom_normal = normalize(make_float3(0.0f, -v.z, v.y)); }