brw: add pre ray trace intrinsic moves
Some intrinsics are implemented by reading memory location that could be rewritten by a further tracing calls. So we need to move those reads prior to tracing operations in the shaders. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Cc: mesa-stable Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8979 Tested-by: Sviatoslav Peleshko <sviatoslav.peleshko@globallogic.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34214> (cherry picked from commit c434050a0088ec3f07d63fd1019aea541632faed)
This commit is contained in:

committed by
Eric Engestrom

parent
8780fd7da5
commit
0ce1adf683
@@ -4,7 +4,7 @@
|
||||
"description": "brw: add pre ray trace intrinsic moves",
|
||||
"nominated": true,
|
||||
"nomination_type": 1,
|
||||
"resolution": 0,
|
||||
"resolution": 1,
|
||||
"main_sha": null,
|
||||
"because_sha": null,
|
||||
"notes": null
|
||||
|
111
src/intel/compiler/brw_nir_lower_rt_intrinsics_pre_trace.c
Normal file
111
src/intel/compiler/brw_nir_lower_rt_intrinsics_pre_trace.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* Copyright © 2025 Intel Corporation
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "brw_nir_rt.h"
|
||||
|
||||
static bool
|
||||
add_intrinsics_to_set(nir_builder *b,
|
||||
nir_intrinsic_instr *intrin,
|
||||
void *data)
|
||||
{
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_load_ray_world_origin:
|
||||
case nir_intrinsic_load_ray_world_direction:
|
||||
case nir_intrinsic_load_ray_object_origin:
|
||||
case nir_intrinsic_load_ray_object_direction:
|
||||
case nir_intrinsic_load_ray_t_min:
|
||||
case nir_intrinsic_load_ray_t_max:
|
||||
case nir_intrinsic_load_ray_object_to_world:
|
||||
case nir_intrinsic_load_ray_flags: {
|
||||
struct set *intrinsics = data;
|
||||
_mesa_set_add(intrinsics, intrin);
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Move some RT intrinsics pre shader calls
|
||||
*
|
||||
* Some RT intrinsics are implemented by reading the ray structure in memory.
|
||||
* This structure is written just before triggering a tracing call. Those
|
||||
* intrinsics should be considered as input values to the shader (kind of like
|
||||
* thread payload in legacy stages).
|
||||
*
|
||||
* If the values are read after a bindless shader call, we need to move the
|
||||
* read from memory prior to the call because called shaders could overwrite
|
||||
* the memory location if they trigger another tracing call.
|
||||
*
|
||||
* Call this pass before nir_lower_shader_calls().
|
||||
*/
|
||||
bool
|
||||
brw_nir_lower_rt_intrinsics_pre_trace(nir_shader *nir)
|
||||
{
|
||||
/* According to spec, only those stages can do a recursing traceRayEXT().
|
||||
*/
|
||||
if (nir->info.stage != MESA_SHADER_CLOSEST_HIT &&
|
||||
nir->info.stage != MESA_SHADER_MISS)
|
||||
return false;
|
||||
|
||||
/* Find all the intrinsics we might need to move */
|
||||
struct set *intrinsics = _mesa_set_create(NULL,
|
||||
_mesa_hash_pointer,
|
||||
_mesa_key_pointer_equal);
|
||||
|
||||
nir_shader_intrinsics_pass(nir,
|
||||
add_intrinsics_to_set,
|
||||
nir_metadata_all,
|
||||
intrinsics);
|
||||
|
||||
bool progress = false;
|
||||
|
||||
if (intrinsics->entries > 0) {
|
||||
nir_foreach_function_with_impl(func, impl, nir) {
|
||||
nir_metadata_require(impl, nir_metadata_dominance);
|
||||
|
||||
/* Going in reverse order of blocks, move the intrinsics gather above
|
||||
* in the LCA block to trace calls.
|
||||
*/
|
||||
nir_foreach_block_reverse(block, impl) {
|
||||
nir_foreach_instr_reverse_safe(instr, block) {
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
continue;
|
||||
|
||||
nir_intrinsic_instr *trace = nir_instr_as_intrinsic(instr);
|
||||
if (trace->intrinsic != nir_intrinsic_trace_ray)
|
||||
continue;
|
||||
|
||||
set_foreach(intrinsics, entry) {
|
||||
nir_intrinsic_instr *intrin = (void *)entry->key;
|
||||
|
||||
/* Coming from a different function, ignore */
|
||||
if (nir_cf_node_get_function(&intrin->instr.block->cf_node) != impl)
|
||||
continue;
|
||||
|
||||
/* The trace dominates the intrinsic, move it before */
|
||||
nir_block *move_block = nir_dominance_lca(trace->instr.block,
|
||||
intrin->instr.block);
|
||||
if (move_block == trace->instr.block) {
|
||||
if (nir_instr_is_before(&trace->instr, &intrin->instr)) {
|
||||
nir_instr_move(nir_before_instr(&trace->instr),
|
||||
&intrin->instr);
|
||||
progress = true;
|
||||
}
|
||||
} else {
|
||||
nir_instr_move(nir_before_block_after_phis(move_block),
|
||||
&intrin->instr);
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_set_destroy(intrinsics, NULL);
|
||||
|
||||
return progress;
|
||||
}
|
@@ -55,6 +55,8 @@ void brw_nir_lower_shader_returns(nir_shader *shader);
|
||||
|
||||
bool brw_nir_lower_shader_calls(nir_shader *shader, struct brw_bs_prog_key *key);
|
||||
|
||||
bool brw_nir_lower_rt_intrinsics_pre_trace(nir_shader *nir);
|
||||
|
||||
void brw_nir_lower_rt_intrinsics(nir_shader *shader,
|
||||
const struct brw_base_prog_key *key,
|
||||
const struct intel_device_info *devinfo);
|
||||
|
@@ -74,6 +74,7 @@ libintel_compiler_brw_files = files(
|
||||
'brw_nir_lower_intersection_shader.c',
|
||||
'brw_nir_lower_ray_queries.c',
|
||||
'brw_nir_lower_rt_intrinsics.c',
|
||||
'brw_nir_lower_rt_intrinsics_pre_trace.c',
|
||||
'brw_nir_lower_sample_index_in_coord.c',
|
||||
'brw_nir_lower_shader_calls.c',
|
||||
'brw_nir_lower_storage_image.c',
|
||||
|
@@ -3373,6 +3373,8 @@ compile_upload_rt_shader(struct anv_ray_tracing_pipeline *pipeline,
|
||||
.should_remat_callback = should_remat_cb,
|
||||
};
|
||||
|
||||
NIR_PASS(_, nir, brw_nir_lower_rt_intrinsics_pre_trace);
|
||||
|
||||
NIR_PASS(_, nir, nir_lower_shader_calls, &opts,
|
||||
&resume_shaders, &num_resume_shaders, mem_ctx);
|
||||
NIR_PASS(_, nir, brw_nir_lower_shader_calls, &stage->key.bs);
|
||||
|
Reference in New Issue
Block a user