intel/rt: fix terminateOnFirstHit handling

If TraceRay() is called with the TerminateOnFirstHit flag, we need to
terminate the ray on the first confirmed intersection. This is handled
by the lowering of accept_ray_intersection and it's working fine for the
case of multiple instances of the intersection shader being called.

But if the shader calls reportIntersection() more than once, we were
handling them all and accepting the closest one regardless of the flag.

Check for the flag on every confirmed intersection and, if set, accept
it right there. The subsequent lowering will take care of terminating
handling the ray termination if necessary.

Fixes new test dEQP-VK.ray_tracing_pipeline.amber.flags-accept-first

Cc: mesa-stable

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30418>
This commit is contained in:
Iván Briano 2024-07-29 10:19:54 -07:00 committed by Marge Bot
parent c6bf1f02c4
commit f8553f56ac

View File

@ -132,6 +132,19 @@ lower_any_hit_for_intersection(nir_shader *any_hit)
return impl;
}
static void
build_accept_ray(nir_builder *b)
{
/* Set the "valid" bit in mem_hit */
nir_def *ray_addr = brw_nir_rt_mem_hit_addr(b, false /* committed */);
nir_def *flags_dw_addr = nir_iadd_imm(b, ray_addr, 12);
nir_store_global(b, flags_dw_addr, 4,
nir_ior(b, nir_load_global(b, flags_dw_addr, 4, 1, 32),
nir_imm_int(b, 1 << 16)), 0x1 /* write_mask */);
nir_accept_ray_intersection(b);
}
void
brw_nir_lower_intersection_shader(nir_shader *intersection,
const nir_shader *any_hit,
@ -164,14 +177,7 @@ brw_nir_lower_intersection_shader(nir_shader *intersection,
b->cursor = nir_after_block_before_jump(block);
nir_push_if(b, nir_load_var(b, commit));
{
/* Set the "valid" bit in mem_hit */
nir_def *ray_addr = brw_nir_rt_mem_hit_addr(b, false /* committed */);
nir_def *flags_dw_addr = nir_iadd_imm(b, ray_addr, 12);
nir_store_global(b, flags_dw_addr, 4,
nir_ior(b, nir_load_global(b, flags_dw_addr, 4, 1, 32),
nir_imm_int(b, 1 << 16)), 0x1 /* write_mask */);
nir_accept_ray_intersection(b);
build_accept_ray(b);
}
nir_push_else(b, NULL);
{
@ -238,6 +244,19 @@ brw_nir_lower_intersection_shader(nir_shader *intersection,
nir_store_global(b, t_addr, 4,
nir_vec2(b, nir_fmin(b, hit_t, hit_in.t), hit_kind),
0x3);
/* There may be multiple reportIntersection() calls in
* the shader, so if terminateOnFirstHit was requested,
* accept the hit now. The lowering of
* accept_ray_intersection will handle the rest.
*/
nir_def *terminate = nir_test_mask(b, nir_load_ray_flags(b),
BRW_RT_RAY_FLAG_TERMINATE_ON_FIRST_HIT);
nir_push_if(b, terminate);
{
build_accept_ray(b);
}
nir_pop_if(b, NULL);
}
nir_pop_if(b, NULL);
}