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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user