nir/opt_access: support RT/callable shaders

I don't know if this affects any real application.

No fossil-db changes.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35938>
This commit is contained in:
Rhys Perry
2025-07-03 12:05:45 +01:00
committed by Marge Bot
parent a9a1da0264
commit 928c9c618d
+57 -13
View File
@@ -46,6 +46,9 @@ struct access_state {
bool buffers_written;
bool images_read;
bool buffers_read;
nir_variable_mode make_available_shader_call_or_gt;
nir_variable_mode make_visible_shader_call_or_gt;
bool has_calls;
};
static void
@@ -148,11 +151,41 @@ gather_intrinsic(struct access_state *state, nir_intrinsic_instr *instr)
break;
}
case nir_intrinsic_barrier:
if (nir_intrinsic_memory_scope(instr) >= SCOPE_SHADER_CALL) {
nir_variable_mode modes = nir_intrinsic_memory_modes(instr);
if (nir_intrinsic_memory_semantics(instr) & NIR_MEMORY_MAKE_AVAILABLE)
state->make_available_shader_call_or_gt |= modes;
if (nir_intrinsic_memory_semantics(instr) & NIR_MEMORY_MAKE_VISIBLE)
state->make_visible_shader_call_or_gt |= modes;
}
break;
/* These are what SPIR-V to NIR generates, but they might be lowered later. */
case nir_intrinsic_trace_ray:
case nir_intrinsic_execute_callable:
state->has_calls = true;
break;
default:
break;
}
}
static bool
maybe_written_outside_module(struct access_state *state, nir_variable_mode mode, unsigned access)
{
bool has_shader_call_scope_make_visible = state->make_visible_shader_call_or_gt & mode;
return state->has_calls && (access & ACCESS_COHERENT || has_shader_call_scope_make_visible);
}
static bool
maybe_read_outside_module(struct access_state *state, nir_variable_mode mode, unsigned access)
{
bool has_shader_call_scope_make_available = state->make_available_shader_call_or_gt & mode;
return state->has_calls && (access & ACCESS_COHERENT || has_shader_call_scope_make_available);
}
static bool
process_variable(struct access_state *state, nir_variable *var)
{
@@ -170,14 +203,16 @@ process_variable(struct access_state *state, nir_variable *var)
bool is_buffer = var->data.mode == nir_var_mem_ssbo ||
glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF;
if (!(access & ACCESS_NON_WRITEABLE)) {
if (!maybe_written_outside_module(state, var->data.mode, access) &&
!(access & ACCESS_NON_WRITEABLE)) {
if (is_buffer ? !state->buffers_written : !state->images_written)
access |= ACCESS_NON_WRITEABLE;
else if ((access & ACCESS_RESTRICT) && !_mesa_set_search(state->vars_written, var))
access |= ACCESS_NON_WRITEABLE;
}
if (!(access & ACCESS_NON_READABLE)) {
if (!maybe_read_outside_module(state, var->data.mode, access) &&
!(access & ACCESS_NON_READABLE)) {
if (is_buffer ? !state->buffers_read : !state->images_read)
access |= ACCESS_NON_READABLE;
else if ((access & ACCESS_RESTRICT) && !_mesa_set_search(state->vars_read, var))
@@ -190,7 +225,8 @@ process_variable(struct access_state *state, nir_variable *var)
}
static bool
update_access(struct access_state *state, nir_intrinsic_instr *instr, bool is_buffer, bool is_global)
update_access(struct access_state *state, nir_intrinsic_instr *instr, nir_variable_mode mode,
bool is_buffer, bool is_global)
{
enum gl_access_qualifier access = nir_intrinsic_access(instr);
@@ -207,12 +243,18 @@ update_access(struct access_state *state, nir_intrinsic_instr *instr, bool is_bu
is_memory_writeonly |= var && (var->data.access & ACCESS_NON_READABLE);
}
if (is_global) {
is_memory_readonly |= !state->buffers_written && !state->images_written;
is_memory_writeonly |= !state->buffers_read && !state->images_read;
} else {
is_memory_readonly |= is_buffer ? !state->buffers_written : !state->images_written;
is_memory_writeonly |= is_buffer ? !state->buffers_read : !state->images_read;
if (!maybe_written_outside_module(state, mode, access)) {
if (is_global)
is_memory_readonly |= !state->buffers_written && !state->images_written;
else
is_memory_readonly |= is_buffer ? !state->buffers_written : !state->images_written;
}
if (!maybe_read_outside_module(state, mode, access)) {
if (is_global)
is_memory_writeonly |= !state->buffers_read && !state->images_read;
else
is_memory_writeonly |= is_buffer ? !state->buffers_read : !state->images_read;
}
if (is_memory_readonly)
@@ -234,15 +276,16 @@ process_intrinsic(struct access_state *state, nir_intrinsic_instr *instr)
case nir_intrinsic_bindless_image_load:
case nir_intrinsic_bindless_image_store:
case nir_intrinsic_bindless_image_sparse_load:
return update_access(state, instr, nir_intrinsic_image_dim(instr) == GLSL_SAMPLER_DIM_BUF,
return update_access(state, instr, nir_var_image,
nir_intrinsic_image_dim(instr) == GLSL_SAMPLER_DIM_BUF,
false);
case nir_intrinsic_load_deref:
case nir_intrinsic_store_deref: {
if (nir_deref_mode_is(nir_src_as_deref(instr->src[0]), nir_var_mem_global))
return update_access(state, instr, false, true);
return update_access(state, instr, nir_var_mem_global, false, true);
else if (nir_deref_mode_is(nir_src_as_deref(instr->src[0]), nir_var_mem_ssbo))
return update_access(state, instr, true, false);
return update_access(state, instr, nir_var_mem_ssbo, true, false);
else
return false;
}
@@ -255,7 +298,7 @@ process_intrinsic(struct access_state *state, nir_intrinsic_instr *instr)
bool is_buffer =
glsl_get_sampler_dim(glsl_without_array(var->type)) == GLSL_SAMPLER_DIM_BUF;
return update_access(state, instr, is_buffer, false);
return update_access(state, instr, nir_var_image, is_buffer, false);
}
default:
@@ -288,6 +331,7 @@ nir_opt_access(nir_shader *shader, const nir_opt_access_options *options)
.shader = shader,
.vars_written = _mesa_pointer_set_create(NULL),
.vars_read = _mesa_pointer_set_create(NULL),
.has_calls = gl_shader_stage_is_callable(shader->info.stage),
};
bool var_progress = false;