From 4a1b71e4a1266e34d8b3ffa75816663649b658ad 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 3088357ed26..b2fba769528 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -94,7 +94,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 0e8bea43972..dc6c859bf58 100644 --- a/src/intel/compiler/brw_nir_lower_intersection_shader.c +++ b/src/intel/compiler/brw_nir_lower_intersection_shader.c @@ -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); }