From 77579801392c23d6fa425982dd8fa7cbdec2ca2e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 6 Jan 2011 10:49:56 -0800 Subject: [PATCH] glsl: Support the 'invariant(all)' pragma Previously the 'STDGL invariant(all)' pragma added in GLSL 1.20 was simply ignored by the compiler. This adds support for setting all variable invariant. In GLSL 1.10 and GLSL ES 1.00 the pragma is ignored, per the specs, but a warning is generated. Fixes piglit test glsl-invariant-pragma and bugzilla #31925. NOTE: This is a candidate for the 7.9 and 7.10 branches. (cherry-picked from commit 86b4398cd158024f6be9fa830554a11c2a7ebe0c) --- src/glsl/ast_to_hir.cpp | 17 +++++++++++++++++ src/glsl/glsl_lexer.lpp | 4 ++++ src/glsl/glsl_parser.ypp | 14 ++++++++++++++ src/glsl/glsl_parser_extras.h | 7 +++++++ 4 files changed, 42 insertions(+) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 53d8e4bf536..88b05d80f30 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1692,6 +1692,23 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else if (qual->uniform) var->mode = ir_var_uniform; + if (state->all_invariant && (state->current_function == NULL)) { + switch (state->target) { + case vertex_shader: + if (var->mode == ir_var_out) + var->invariant = true; + break; + case geometry_shader: + if ((var->mode == ir_var_in) || (var->mode == ir_var_out)) + var->invariant = true; + break; + case fragment_shader: + if (var->mode == ir_var_in) + var->invariant = true; + break; + } + } + if (qual->flat) var->interpolation = ir_var_flat; else if (qual->noperspective) diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp index 786fc68c625..eba5e728df1 100644 --- a/src/glsl/glsl_lexer.lpp +++ b/src/glsl/glsl_lexer.lpp @@ -137,6 +137,10 @@ HASH ^{SPC}#{SPC} BEGIN PP; return PRAGMA_OPTIMIZE_OFF; } +^{SPC}#{SPC}pragma{SPCP}STDGL{SPCP}invariant{SPC}\({SPC}all{SPC}\) { + BEGIN PP; + return PRAGMA_INVARIANT_ALL; + } ^{SPC}#{SPC}pragma{SPCP} { BEGIN PRAGMA; } \n { BEGIN 0; yylineno++; yycolumn = 0; } diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp index 0df1e480ce3..209e1802020 100644 --- a/src/glsl/glsl_parser.ypp +++ b/src/glsl/glsl_parser.ypp @@ -111,6 +111,7 @@ %token VERSION EXTENSION LINE COLON EOL INTERFACE OUTPUT %token PRAGMA_DEBUG_ON PRAGMA_DEBUG_OFF %token PRAGMA_OPTIMIZE_ON PRAGMA_OPTIMIZE_OFF +%token PRAGMA_INVARIANT_ALL %token LAYOUT_TOK /* Reserved words that are not actually used in the grammar. @@ -243,6 +244,19 @@ pragma_statement: | PRAGMA_DEBUG_OFF EOL | PRAGMA_OPTIMIZE_ON EOL | PRAGMA_OPTIMIZE_OFF EOL + | PRAGMA_INVARIANT_ALL EOL + { + if (state->language_version < 120) { + _mesa_glsl_warning(& @1, state, + "pragma `invariant(all)' not supported in " + "GLSL%s %d.%02d", + state->es_shader ? " ES" : "", + state->language_version / 100, + state->language_version % 100); + } else { + state->all_invariant = true; + } + } ; extension_statement_list: diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index ddc2138b765..10de53683ee 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -109,6 +109,13 @@ struct _mesa_glsl_parse_state { /** Was there an error during compilation? */ bool error; + /** + * Are all shader inputs / outputs invariant? + * + * This is set when the 'STDGL invariant(all)' pragma is used. + */ + bool all_invariant; + /** Loop or switch statement containing the current instructions. */ class ir_instruction *loop_or_switch_nesting; class ast_iteration_statement *loop_or_switch_nesting_ast;