glsl: move invariant builtin validation to the nir linker

We don't attempt to recreate a nir implementation of the symbol table
instead here we simply use location to find the variables we need to
validate.

Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28142>
This commit is contained in:
Timothy Arceri
2024-03-05 15:06:48 +11:00
committed by Marge Bot
parent 1bc25f4754
commit 20db9b77aa
2 changed files with 90 additions and 67 deletions
+90
View File
@@ -1450,6 +1450,90 @@ validate_sampler_array_indexing(const struct gl_constants *consts,
return true;
}
static nir_variable *
find_frag_builtin(nir_shader *shader, bool is_sysval, unsigned sysval,
unsigned varying)
{
unsigned location = is_sysval ? sysval : varying;
nir_variable_mode mode =
is_sysval ? nir_var_system_value : nir_var_shader_in;
return nir_find_variable_with_location(shader, mode, location);
}
/**
* Verifies the invariance of built-in special variables.
*/
static bool
validate_invariant_builtins(const struct gl_constants *consts,
struct gl_shader_program *prog,
const struct gl_linked_shader *vert,
const struct gl_linked_shader *frag)
{
const nir_variable *var_vert;
const nir_variable *var_frag;
if (!vert || !frag)
return true;
/*
* From OpenGL ES Shading Language 1.0 specification
* (4.6.4 Invariance and Linkage):
* "The invariance of varyings that are declared in both the vertex and
* fragment shaders must match. For the built-in special variables,
* gl_FragCoord can only be declared invariant if and only if
* gl_Position is declared invariant. Similarly gl_PointCoord can only
* be declared invariant if and only if gl_PointSize is declared
* invariant. It is an error to declare gl_FrontFacing as invariant.
* The invariance of gl_FrontFacing is the same as the invariance of
* gl_Position."
*/
var_frag = find_frag_builtin(frag->Program->nir,
consts->GLSLFragCoordIsSysVal,
SYSTEM_VALUE_FRAG_COORD, VARYING_SLOT_POS);
if (var_frag && var_frag->data.invariant) {
var_vert = nir_find_variable_with_location(vert->Program->nir,
nir_var_shader_out,
VARYING_SLOT_POS);
if (var_vert && !var_vert->data.invariant) {
linker_error(prog,
"fragment shader built-in `%s' has invariant qualifier, "
"but vertex shader built-in `%s' lacks invariant qualifier\n",
var_frag->name, var_vert->name);
return false;
}
}
var_frag = find_frag_builtin(frag->Program->nir,
consts->GLSLPointCoordIsSysVal,
SYSTEM_VALUE_POINT_COORD, VARYING_SLOT_PNTC);
if (var_frag && var_frag->data.invariant) {
var_vert = nir_find_variable_with_location(vert->Program->nir,
nir_var_shader_out,
VARYING_SLOT_PSIZ);
if (var_vert && !var_vert->data.invariant) {
linker_error(prog,
"fragment shader built-in `%s' has invariant qualifier, "
"but vertex shader built-in `%s' lacks invariant qualifier\n",
var_frag->name, var_vert->name);
return false;
}
}
var_frag = find_frag_builtin(frag->Program->nir,
consts->GLSLFrontFacingIsSysVal,
SYSTEM_VALUE_FRONT_FACE, VARYING_SLOT_FACE);
if (var_frag && var_frag->data.invariant) {
linker_error(prog,
"fragment shader built-in `%s' can not be declared as invariant\n",
var_frag->name);
return false;
}
return true;
}
bool
gl_nir_link_glsl(const struct gl_constants *consts,
const struct gl_extensions *exts,
@@ -1461,6 +1545,12 @@ gl_nir_link_glsl(const struct gl_constants *consts,
MESA_TRACE_FUNC();
if (prog->IsES && prog->GLSL_Version == 100)
if (!validate_invariant_builtins(consts, prog,
prog->_LinkedShaders[MESA_SHADER_VERTEX],
prog->_LinkedShaders[MESA_SHADER_FRAGMENT]))
return false;
/* Check and validate stream emissions in geometry shaders */
validate_geometry_shader_emissions(consts, prog);
-67
View File
@@ -960,67 +960,6 @@ cross_validate_uniforms(const struct gl_constants *consts,
}
}
/**
* Verifies the invariance of built-in special variables.
*/
static bool
validate_invariant_builtins(struct gl_shader_program *prog,
const gl_linked_shader *vert,
const gl_linked_shader *frag)
{
const ir_variable *var_vert;
const ir_variable *var_frag;
if (!vert || !frag)
return true;
/*
* From OpenGL ES Shading Language 1.0 specification
* (4.6.4 Invariance and Linkage):
* "The invariance of varyings that are declared in both the vertex and
* fragment shaders must match. For the built-in special variables,
* gl_FragCoord can only be declared invariant if and only if
* gl_Position is declared invariant. Similarly gl_PointCoord can only
* be declared invariant if and only if gl_PointSize is declared
* invariant. It is an error to declare gl_FrontFacing as invariant.
* The invariance of gl_FrontFacing is the same as the invariance of
* gl_Position."
*/
var_frag = frag->symbols->get_variable("gl_FragCoord");
if (var_frag && var_frag->data.invariant) {
var_vert = vert->symbols->get_variable("gl_Position");
if (var_vert && !var_vert->data.invariant) {
linker_error(prog,
"fragment shader built-in `%s' has invariant qualifier, "
"but vertex shader built-in `%s' lacks invariant qualifier\n",
var_frag->name, var_vert->name);
return false;
}
}
var_frag = frag->symbols->get_variable("gl_PointCoord");
if (var_frag && var_frag->data.invariant) {
var_vert = vert->symbols->get_variable("gl_PointSize");
if (var_vert && !var_vert->data.invariant) {
linker_error(prog,
"fragment shader built-in `%s' has invariant qualifier, "
"but vertex shader built-in `%s' lacks invariant qualifier\n",
var_frag->name, var_vert->name);
return false;
}
}
var_frag = frag->symbols->get_variable("gl_FrontFacing");
if (var_frag && var_frag->data.invariant) {
linker_error(prog,
"fragment shader built-in `%s' can not be declared as invariant\n",
var_frag->name);
return false;
}
return true;
}
/**
* Populates a shaders symbol table with all global declarations
*/
@@ -2814,12 +2753,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
if (!prog->data->LinkStatus)
goto done;
if (prog->IsES && prog->GLSL_Version == 100)
if (!validate_invariant_builtins(prog,
prog->_LinkedShaders[MESA_SHADER_VERTEX],
prog->_LinkedShaders[MESA_SHADER_FRAGMENT]))
goto done;
done:
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
free(shader_list[i]);