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:
committed by
Marge Bot
parent
1bc25f4754
commit
20db9b77aa
@@ -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);
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
Reference in New Issue
Block a user