mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 02:40:11 +01:00
glsl: Remove unused gl_PerVertex interface blocks.
The GLSL 4.10 rules for redeclaration of built-in interface blocks
(which we've chosen to regard as clarifications of GLSL 1.50) only
require gl_PerVertex blocks to match in shaders that actually use
those blocks. The easiest way to implement this is to detect
situations where a compiled shader doesn't refer to any elements of
gl_PerVertex, and remove all the associated ir_variables from the
shader at the end of ast-to-ir conversion.
Fixes piglit tests
linker/interstage-{pervertex,pervertex-in,pervertex-out}-redeclaration-unneeded.
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
This commit is contained in:
parent
37d97668ae
commit
719bf30165
1 changed files with 90 additions and 0 deletions
|
|
@ -60,6 +60,10 @@
|
||||||
static void
|
static void
|
||||||
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
|
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
|
||||||
exec_list *instructions);
|
exec_list *instructions);
|
||||||
|
static void
|
||||||
|
remove_per_vertex_blocks(exec_list *instructions,
|
||||||
|
_mesa_glsl_parse_state *state, ir_variable_mode mode);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
|
_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
|
||||||
|
|
@ -114,6 +118,40 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
|
||||||
var->remove();
|
var->remove();
|
||||||
instructions->push_head(var);
|
instructions->push_head(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* From section 7.1 (Built-In Language Variables) of the GLSL 4.10 spec:
|
||||||
|
*
|
||||||
|
* If multiple shaders using members of a built-in block belonging to
|
||||||
|
* the same interface are linked together in the same program, they
|
||||||
|
* must all redeclare the built-in block in the same way, as described
|
||||||
|
* in section 4.3.7 "Interface Blocks" for interface block matching, or
|
||||||
|
* a link error will result.
|
||||||
|
*
|
||||||
|
* The phrase "using members of a built-in block" implies that if two
|
||||||
|
* shaders are linked together and one of them *does not use* any members
|
||||||
|
* of the built-in block, then that shader does not need to have a matching
|
||||||
|
* redeclaration of the built-in block.
|
||||||
|
*
|
||||||
|
* This appears to be a clarification to the behaviour established for
|
||||||
|
* gl_PerVertex by GLSL 1.50, therefore implement it regardless of GLSL
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* The definition of "interface" in section 4.3.7 that applies here is as
|
||||||
|
* follows:
|
||||||
|
*
|
||||||
|
* The boundary between adjacent programmable pipeline stages: This
|
||||||
|
* spans all the outputs in all compilation units of the first stage
|
||||||
|
* and all the inputs in all compilation units of the second stage.
|
||||||
|
*
|
||||||
|
* Therefore this rule applies to both inter- and intra-stage linking.
|
||||||
|
*
|
||||||
|
* The easiest way to implement this is to check whether the shader uses
|
||||||
|
* gl_PerVertex right after ast-to-ir conversion, and if it doesn't, simply
|
||||||
|
* remove all the relevant variable declaration from the IR, so that the
|
||||||
|
* linker won't see them and complain about mismatches.
|
||||||
|
*/
|
||||||
|
remove_per_vertex_blocks(instructions, state, ir_var_shader_in);
|
||||||
|
remove_per_vertex_blocks(instructions, state, ir_var_shader_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5141,3 +5179,55 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
|
||||||
user_defined_fs_output->name);
|
user_defined_fs_output->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_per_vertex_blocks(exec_list *instructions,
|
||||||
|
_mesa_glsl_parse_state *state, ir_variable_mode mode)
|
||||||
|
{
|
||||||
|
/* Find the gl_PerVertex interface block of the appropriate (in/out) mode,
|
||||||
|
* if it exists in this shader type.
|
||||||
|
*/
|
||||||
|
const glsl_type *per_vertex = NULL;
|
||||||
|
switch (mode) {
|
||||||
|
case ir_var_shader_in:
|
||||||
|
if (ir_variable *gl_in = state->symbols->get_variable("gl_in"))
|
||||||
|
per_vertex = gl_in->get_interface_type();
|
||||||
|
break;
|
||||||
|
case ir_var_shader_out:
|
||||||
|
if (ir_variable *gl_Position =
|
||||||
|
state->symbols->get_variable("gl_Position")) {
|
||||||
|
per_vertex = gl_Position->get_interface_type();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"Unexpected mode");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we didn't find a built-in gl_PerVertex interface block, then we don't
|
||||||
|
* need to do anything.
|
||||||
|
*/
|
||||||
|
if (per_vertex == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If the interface block is used by the shader, then we don't need to do
|
||||||
|
* anything.
|
||||||
|
*/
|
||||||
|
interface_block_usage_visitor v(mode, per_vertex);
|
||||||
|
v.run(instructions);
|
||||||
|
if (v.usage_found())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Remove any ir_variable declarations that refer to the interface block
|
||||||
|
* we're removing.
|
||||||
|
*/
|
||||||
|
foreach_list_safe(node, instructions) {
|
||||||
|
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||||
|
if (var != NULL && var->get_interface_type() == per_vertex &&
|
||||||
|
var->mode == mode) {
|
||||||
|
state->symbols->disable_variable(var->name);
|
||||||
|
var->remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue