From c8ce254e4c82870d2d71e29fbac3a4df94a82a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Briano?= Date: Mon, 29 Jul 2024 10:19:54 -0700 Subject: [PATCH] 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 Part-of: (cherry picked from commit f8553f56acdb1abd061a1049d52e5a1937b2b759) --- .pick_status.json | 2 +- .../brw_nir_lower_intersection_shader.c | 35 ++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 82905cb06de..9b2f25a5a80 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -4034,7 +4034,7 @@ "description": "intel/rt: fix terminateOnFirstHit handling", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/intel/compiler/brw_nir_lower_intersection_shader.c b/src/intel/compiler/brw_nir_lower_intersection_shader.c index b26339bdac1..ebb6fbfa767 100644 --- a/src/intel/compiler/brw_nir_lower_intersection_shader.c +++ b/src/intel/compiler/brw_nir_lower_intersection_shader.c @@ -136,6 +136,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, @@ -168,14 +181,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); { @@ -242,6 +248,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); }