From 457eac7d66a8c840b53e6f8ca4331fd1fb6532c0 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 3 Apr 2026 13:08:36 +0200 Subject: [PATCH] nir: add new variable modes for the resource/sampler heap pointers These two new variable modes are used to relax restrictions on deref casts through because it's possible to cast different modes from the heap pointers. Signed-off-by: Samuel Pitoiset Part-of: --- src/compiler/nir/nir.c | 2 ++ src/compiler/nir/nir.h | 2 +- src/compiler/nir/nir_defines.h | 13 ++++++++----- src/compiler/nir/nir_deref.c | 7 +++++++ src/compiler/nir/nir_print.c | 4 ++++ src/compiler/nir/nir_validate.c | 25 ++++++++++++++++++++----- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 988b5b2011f..9604154aef7 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -259,6 +259,8 @@ nir_shader_add_variable(nir_shader *shader, nir_variable *var) case nir_var_mem_pixel_local_in: case nir_var_mem_pixel_local_out: case nir_var_mem_pixel_local_inout: + case nir_var_resource_heap: + case nir_var_sampler_heap: break; default: diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index e666695ed05..2e3fe5d91d3 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -484,7 +484,7 @@ typedef struct nir_variable { * * :c:struct:`nir_variable_mode` */ - unsigned mode : 24; + unsigned mode : 26; /** * Is the variable read-only? diff --git a/src/compiler/nir/nir_defines.h b/src/compiler/nir/nir_defines.h index ec4af3009e2..c220974f2fc 100644 --- a/src/compiler/nir/nir_defines.h +++ b/src/compiler/nir/nir_defines.h @@ -84,13 +84,16 @@ typedef enum { nir_var_function_out = (1 << 18), nir_var_function_inout = (1 << 19), + nir_var_resource_heap = (1 << 20), + nir_var_sampler_heap = (1 << 21), + /* Generic modes intentionally come last. See encode_dref_modes() in * nir_serialize.c for more details. */ - nir_var_shader_temp = (1 << 20), - nir_var_function_temp = (1 << 21), - nir_var_mem_shared = (1 << 22), - nir_var_mem_global = (1 << 23), + nir_var_shader_temp = (1 << 22), + nir_var_function_temp = (1 << 23), + nir_var_mem_shared = (1 << 24), + nir_var_mem_global = (1 << 25), nir_var_mem_generic = (nir_var_shader_temp | nir_var_function_temp | @@ -114,7 +117,7 @@ typedef enum { nir_var_mem_pixel_local_out | nir_var_mem_pixel_local_inout, - nir_num_variable_modes = 24, + nir_num_variable_modes = 26, nir_var_all = (1 << nir_num_variable_modes) - 1, } nir_variable_mode; MESA_DEFINE_CPP_ENUM_BITFIELD_OPERATORS(nir_variable_mode) diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c index feb463fcc4a..e56a37d12d8 100644 --- a/src/compiler/nir/nir_deref.c +++ b/src/compiler/nir/nir_deref.c @@ -1086,6 +1086,13 @@ opt_restrict_deref_modes(nir_deref_instr *deref) if (parent == NULL || parent->modes == deref->modes) return false; + /* Casts from the heap pointers shouldn't be restricted because it's allowed + * to cast to some variable modes. + */ + if (parent->modes & (nir_var_resource_heap | + nir_var_sampler_heap)) + return false; + assert(parent->modes & deref->modes); deref->modes &= parent->modes; return true; diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index f44d8ba95e3..964c77d96bf 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -813,6 +813,10 @@ get_variable_mode_str(nir_variable_mode mode, bool want_local_global_mode) return "node_payload"; case nir_var_mem_node_payload_in: return "node_payload_in"; + case nir_var_resource_heap: + return "resource_heap"; + case nir_var_sampler_heap: + return "sampler_heap"; default: if (mode && (mode & nir_var_mem_generic) == mode) return "generic"; diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 58275b64306..ca3d3791cdb 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -330,10 +330,23 @@ validate_deref_instr(nir_deref_instr *instr, validate_state *state) nir_deref_instr *parent = nir_src_as_deref(instr->parent); if (parent) { - /* Casts can change the mode but it can't change completely. The new - * mode must have some bits in common with the old. - */ - validate_assert(state, instr->modes & parent->modes); + if (parent->modes & nir_var_resource_heap) { + /* Some casts from the resource heap pointer are allowed. */ + validate_assert(state, instr->modes & (nir_var_resource_heap | + nir_var_image | + nir_var_uniform | + nir_var_mem_ubo | + nir_var_mem_ssbo)); + } else if (parent->modes & nir_var_sampler_heap) { + /* Some casts from the sampler heap pointer are allowed. */ + validate_assert(state, instr->modes & (nir_var_sampler_heap | + nir_var_uniform)); + } else { + /* Casts can change the mode but it can't change completely. The + * new mode must have some bits in common with the old. + */ + validate_assert(state, instr->modes & parent->modes); + } } else { /* If our parent isn't a deref, just assert the mode is there */ validate_assert(state, instr->modes != 0); @@ -2353,7 +2366,9 @@ nir_validate_shader(nir_shader *shader, const char *when) nir_var_mem_pixel_local_in | nir_var_mem_pixel_local_out | nir_var_mem_pixel_local_inout | - nir_var_image; + nir_var_image | + nir_var_resource_heap | + nir_var_sampler_heap; if (mesa_shader_stage_is_callable(shader->info.stage)) valid_modes |= nir_var_shader_call_data;