From 20322687e08a78f66c005a2075e1f2df89c2b7b4 Mon Sep 17 00:00:00 2001 From: Konstantin Seurer Date: Sat, 24 Jan 2026 12:21:58 +0100 Subject: [PATCH] vulkan: Avoid NAN in the IR BVH Build and encoding stages should be able to assume that AABBs don't have NANs. This commit covers all possible sources of NAN. Fixes: 091b43b ("radv: Use HPLOC for TLAS builds") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14696 Reviewed-by: Natalie Vock Part-of: --- src/vulkan/runtime/bvh/leaf.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/vulkan/runtime/bvh/leaf.h b/src/vulkan/runtime/bvh/leaf.h index 04ec004dbca..f4658ec7150 100644 --- a/src/vulkan/runtime/bvh/leaf.h +++ b/src/vulkan/runtime/bvh/leaf.h @@ -37,16 +37,6 @@ build_triangle(inout vk_aabb bounds, VOID_REF dst_ptr, vk_bvh_geometry_data geom triangle_vertices vertices = load_vertices(geom_data.data, indices, geom_data.vertex_format, geom_data.stride); - /* An inactive triangle is one for which the first (X) component of any vertex is NaN. If any - * other vertex component is NaN, and the first is not, the behavior is undefined. If the vertex - * format does not have a NaN representation, then all triangles are considered active. - */ - if (isnan(vertices.vertex[0].x) || isnan(vertices.vertex[1].x) || isnan(vertices.vertex[2].x)) { - is_valid = false; - if (!VK_BUILD_FLAG(VK_BUILD_FLAG_ALWAYS_ACTIVE)) - return false; - } - if (geom_data.transform != NULL) { mat4 transform = mat4(1.0); @@ -58,6 +48,17 @@ build_triangle(inout vk_aabb bounds, VOID_REF dst_ptr, vk_bvh_geometry_data geom vertices.vertex[i] = transform * vertices.vertex[i]; } + /* An inactive triangle is one for which the first (X) component of any vertex is NaN. If any + * other vertex component is NaN, and the first is not, the behavior is undefined. We treat those + * undefined cases as inactive to filter out NaNs. If the vertex format does not have a NaN + * representation, then all triangles are considered active. + */ + if (any(isnan(vertices.vertex[0])) || any(isnan(vertices.vertex[1])) || any(isnan(vertices.vertex[2]))) { + is_valid = false; + if (!VK_BUILD_FLAG(VK_BUILD_FLAG_ALWAYS_ACTIVE)) + return false; + } + REF(vk_ir_triangle_node) node = REF(vk_ir_triangle_node)(dst_ptr); bounds.min = vec3(INFINITY); @@ -94,9 +95,10 @@ build_aabb(inout vk_aabb bounds, VOID_REF src_ptr, VOID_REF dst_ptr, uint32_t ge } /* An inactive AABB is one for which the minimum X coordinate is NaN. If any other component is - * NaN, and the first is not, the behavior is undefined. + * NaN, and the first is not, the behavior is undefined. We treat those undefined cases as inactive + * to filter out NaNs. */ - if (isnan(bounds.min.x)) { + if (any(isnan(bounds.min)) || any(isnan(bounds.max))) { is_valid = false; if (!VK_BUILD_FLAG(VK_BUILD_FLAG_ALWAYS_ACTIVE)) return false; @@ -147,11 +149,11 @@ build_instance(inout vk_aabb bounds, VOID_REF src_ptr, VOID_REF dst_ptr, uint32_ vk_aabb blas_aabb = DEREF(REF(vk_aabb)(instance.accelerationStructureReference + BVH_BOUNDS_OFFSET)); - if (any(isnan(blas_aabb.min)) || any(isnan(blas_aabb.max))) - return false; - bounds = calculate_instance_node_bounds(blas_aabb, mat3x4(transform)); + if (any(isnan(bounds.min)) || any(isnan(bounds.max))) + return false; + #ifdef CALCULATE_FINE_INSTANCE_NODE_BOUNDS vec3 blas_aabb_extent = blas_aabb.max - blas_aabb.min; float blas_aabb_volume = blas_aabb_extent.x * blas_aabb_extent.y * blas_aabb_extent.z;