glsl: make gl_nir_validate_intrastage_arrays() more flexible

This will allow us to use it before shaders from the same stage have
been linked and merged.

Acked-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31137>
This commit is contained in:
Timothy Arceri 2024-06-25 15:45:24 +10:00 committed by Marge Bot
parent ffbd763586
commit 1fc9d5223e
3 changed files with 17 additions and 18 deletions

View file

@ -115,7 +115,7 @@ static bool
intrastage_match(nir_variable *a,
nir_variable *b,
struct gl_shader_program *prog,
unsigned a_stage,
nir_shader *a_shader,
bool match_precision)
{
/* From section 4.7 "Precision and Precision Qualifiers" in GLSL 4.50:
@ -165,7 +165,8 @@ intrastage_match(nir_variable *a,
*/
if (!type_match && (glsl_type_is_array(b->type) || glsl_type_is_array(a->type)) &&
(is_interface_instance(b) || is_interface_instance(a)) &&
!gl_nir_validate_intrastage_arrays(prog, b, a, a_stage, match_precision))
!gl_nir_validate_intrastage_arrays(prog, b, a, a_shader,
match_precision))
return false;
return true;
@ -225,7 +226,7 @@ interstage_match(struct gl_shader_program *prog, nir_variable *producer,
}
struct ifc_var {
unsigned stage;
nir_shader *shader;
nir_variable *var;
};
@ -256,11 +257,11 @@ ifc_lookup(struct hash_table *ht, nir_variable *var)
*/
static void
ifc_store(void *mem_ctx, struct hash_table *ht, nir_variable *var,
unsigned stage)
nir_shader *shader)
{
struct ifc_var *ifc_var = ralloc(mem_ctx, struct ifc_var);
ifc_var->var = var;
ifc_var->stage = stage;
ifc_var->shader = shader;
if (var->data.explicit_location &&
var->data.location >= VARYING_SLOT_VAR0) {
@ -349,10 +350,10 @@ gl_nir_validate_intrastage_interface_blocks(struct gl_shader_program *prog,
* it into the appropriate data structure.
*/
ifc_store(mem_ctx, definitions, var,
shader_list[i]->nir->info.stage);
shader_list[i]->nir);
} else {
nir_variable *prev_def = ifc_var->var;
if (!intrastage_match(prev_def, var, prog, ifc_var->stage,
if (!intrastage_match(prev_def, var, prog, ifc_var->shader,
true /* match_precision */)) {
linker_error(prog, "definitions of interface block `%s' do not"
" match\n", glsl_get_type_name(var->interface_type));
@ -466,7 +467,7 @@ gl_nir_validate_interstage_inout_blocks(struct gl_shader_program *prog,
return;
}
ifc_store(mem_ctx, ht, var, producer->Program->nir->info.stage);
ifc_store(mem_ctx, ht, var, producer->Program->nir);
}
/* Verify that the consumer's input interfaces match. */
@ -543,14 +544,14 @@ gl_nir_validate_interstage_uniform_blocks(struct gl_shader_program *prog,
struct ifc_var *ifc_var = ifc_lookup(ht, var);
if (ifc_var == NULL) {
ifc_store(mem_ctx, ht, var, i);
ifc_store(mem_ctx, ht, var, stage->Program->nir);
} else {
/* Interstage uniform matching rules are the same as intrastage
* uniform matchin rules (for uniforms, it is as though all
* shaders are in the same shader stage).
*/
nir_variable *old_def = ifc_var->var;
if (!intrastage_match(old_def, var, prog, ifc_var->stage, false)) {
if (!intrastage_match(old_def, var, prog, ifc_var->shader, false)) {
linker_error(prog, "definitions of uniform block `%s' do not "
"match\n", glsl_get_type_name(var->interface_type));
ralloc_free(mem_ctx);

View file

@ -1623,7 +1623,7 @@ gl_nir_link_spirv(const struct gl_constants *consts,
bool
gl_nir_validate_intrastage_arrays(struct gl_shader_program *prog,
nir_variable *var, nir_variable *existing,
unsigned existing_stage,
nir_shader *existing_shader,
bool match_precision)
{
/* Consider the types to be "the same" if both types are arrays
@ -1655,9 +1655,7 @@ gl_nir_validate_intrastage_arrays(struct gl_shader_program *prog,
existing->data.max_array_access);
}
existing->type = var->type;
nir_shader *s = prog->_LinkedShaders[existing_stage]->Program->nir;
nir_fixup_deref_types(s);
nir_fixup_deref_types(existing_shader);
return true;
} else if (glsl_array_size(existing->type) != 0) {
if((int)glsl_array_size(existing->type) <= var->data.max_array_access &&
@ -1695,7 +1693,7 @@ nir_constant_compare(const nir_constant *c1, const nir_constant *c2)
}
struct ifc_var {
unsigned stage;
nir_shader *shader;
nir_variable *var;
};
@ -1747,7 +1745,7 @@ cross_validate_globals(void *mem_ctx, const struct gl_constants *consts,
/* Check if types match. */
if (var->type != existing->type) {
if (!gl_nir_validate_intrastage_arrays(prog, var, existing,
existing_ifc->stage, true)) {
existing_ifc->shader, true)) {
/* If it is an unsized array in a Shader Storage Block,
* two different shaders can access to different elements.
* Because of that, they might be converted to different
@ -1985,7 +1983,7 @@ cross_validate_globals(void *mem_ctx, const struct gl_constants *consts,
} else {
struct ifc_var *ifc_var = ralloc(mem_ctx, struct ifc_var);
ifc_var->var = var;
ifc_var->stage = shader->info.stage;
ifc_var->shader = shader;
_mesa_hash_table_insert(variables, var->name, ifc_var);
}
}

View file

@ -81,7 +81,7 @@ const char * gl_nir_mode_string(const nir_variable *var);
bool gl_nir_validate_intrastage_arrays(struct gl_shader_program *prog,
nir_variable *var,
nir_variable *existing,
unsigned existing_stage,
nir_shader *existing_shader,
bool match_precision);
struct nir_xfb_info *