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 <natalie.vock@gmx.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39508>
This commit is contained in:
Konstantin Seurer 2026-01-24 12:21:58 +01:00 committed by Marge Bot
parent 0817551f00
commit 20322687e0

View file

@ -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;