radv/rt: Don't enable midpoint sorting

Midpoint sorting is incompatible with how our traversal works.
Specifically, we change tMax when a hit is committed so we can skip over
BVH nodes that are guaranteed not to produce a closer hit. However,
changing tMax also changes the intersection interval of box nodes with
the ray, and thus, the midpoints of that interval. Stackless traversal
relies on getting nodes back in the exact same order as before, and if
that requirement is not met, traversal may incorrectly skip over nodes.

The likely benefit of midpoint sorting does not make up for the loss of
ability to skip over BVH nodes exceeding tMax, so simply disable
midpoint sorting.

This fixes geometry being visible behind other geometry when it
shouldn't be in various applications, including Half-Life 2 RTX.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40795>
This commit is contained in:
Natalie Vock 2026-04-05 11:53:23 +02:00 committed by Marge Bot
parent 1be54acdee
commit c1a7680d93

View file

@ -560,15 +560,12 @@ create_bvh_descriptor(nir_builder *b, const struct radv_physical_device *pdev, s
/* Enable pointer flags on GFX11+ */
dword3 |= BITFIELD_BIT(119 - 96);
/* Instead of the default box sorting (closest point), use largest for terminate_on_first_hit rays and midpoint
* for closest hit; this makes it more likely that the ray traversal will visit fewer nodes. */
/* Instead of the default box sorting (closest point), use largest for terminate_on_first_hit rays;
* this makes it more likely that the ray traversal will visit fewer nodes. */
const uint32_t box_sort_largest = 1;
const uint32_t box_sort_midpoint = 2;
/* Only use largest/midpoint sorting when all invocations have the same ray flags, otherwise
/* Only use largest sorting when all invocations have the same ray flags, otherwise
* fall back to the default closest point. */
dword1 = nir_bcsel(b, nir_vote_any(b, 1, ray_flags->terminate_on_first_hit), dword1,
nir_imm_int(b, (box_sort_midpoint << 21) | sort_triangles_first | box_sort_enable));
dword1 = nir_bcsel(b, nir_vote_all(b, 1, ray_flags->terminate_on_first_hit),
nir_imm_int(b, (box_sort_largest << 21) | sort_triangles_first | box_sort_enable), dword1);
}