Mesa (glsl2): glsl2: Support AST-to-IR translation of invariant keyword

Ian Romanick idr at kemper.freedesktop.org
Fri Jul 2 03:43:39 UTC 2010


Module: Mesa
Branch: glsl2
Commit: 6f0823da09384cc1b557385b9e19a9cc7e901ad7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6f0823da09384cc1b557385b9e19a9cc7e901ad7

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Thu Jul  1 20:39:08 2010 -0700

glsl2: Support AST-to-IR translation of invariant keyword

---

 src/glsl/ast_to_hir.cpp |   84 +++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 3a7fcf1..3bd0bd6 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1550,29 +1550,73 @@ ast_declarator_list::hir(exec_list *instructions,
    ir_rvalue *result = NULL;
    YYLTYPE loc = this->get_location();
 
+   /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec:
+    *
+    *     "To ensure that a particular output variable is invariant, it is
+    *     necessary to use the invariant qualifier. It can either be used to
+    *     qualify a previously declared variable as being invariant
+    *
+    *         invariant gl_Position; // make existing gl_Position be invariant"
+    *
+    * In these cases the parser will set the 'invariant' flag in the declarator
+    * list, and the type will be NULL.
+    */
+   if (this->invariant) {
+      assert(this->type == NULL);
+
+      if (state->current_function != NULL) {
+	 _mesa_glsl_error(& loc, state,
+			  "All uses of `invariant' keyword must be at global "
+			  "scope\n");
+      }
+
+      foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+	 assert(!decl->is_array);
+	 assert(decl->array_size == NULL);
+	 assert(decl->initializer == NULL);
+
+	 ir_variable *const earlier =
+	    state->symbols->get_variable(decl->identifier);
+	 if (earlier == NULL) {
+	    _mesa_glsl_error(& loc, state,
+			     "Undeclared variable `%s' cannot be marked "
+			     "invariant\n", decl->identifier);
+	 } else if ((state->target == vertex_shader)
+	       && (earlier->mode != ir_var_out)) {
+	    _mesa_glsl_error(& loc, state,
+			     "`%s' cannot be marked invariant, vertex shader "
+			     "outputs only\n", decl->identifier);
+	 } else if ((state->target == fragment_shader)
+	       && (earlier->mode != ir_var_in)) {
+	    _mesa_glsl_error(& loc, state,
+			     "`%s' cannot be marked invariant, fragment shader "
+			     "inputs only\n", decl->identifier);
+	 } else {
+	    earlier->invariant = true;
+	 }
+      }
+
+      /* Invariant redeclarations do not have r-values.
+       */
+      return NULL;
+   }
+
+   assert(this->type != NULL);
+   assert(!this->invariant);
+
    /* The type specifier may contain a structure definition.  Process that
     * before any of the variable declarations.
     */
    (void) this->type->specifier->hir(instructions, state);
 
-   /* FINISHME: Handle vertex shader "invariant" declarations that do not
-    * FINISHME: include a type.  These re-declare built-in variables to be
-    * FINISHME: invariant.
-    */
-
    decl_type = this->type->specifier->glsl_type(& type_name, state);
    if (this->declarations.is_empty()) {
-      /* There are only two valid cases where the declaration list can be
-       * empty.
-       *
-       * 1. The declaration is setting the default precision of a built-in
-       *    type (e.g., 'precision highp vec4;').
-       *
-       * 2. Adding 'invariant' to an existing vertex shader output.
+      /* The only valid case where the declaration list can be empty is when
+       * the declaration is setting the default precision of a built-in type
+       * (e.g., 'precision highp vec4;').
        */
 
-      if (this->type->qualifier.invariant) {
-      } else if (decl_type != NULL) {
+      if (decl_type != NULL) {
       } else {
 	    _mesa_glsl_error(& loc, state, "incomplete declaration");
       }
@@ -1636,6 +1680,18 @@ ast_declarator_list::hir(exec_list *instructions,
       apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
 				       & loc);
 
+      if (this->type->qualifier.invariant) {
+	 if ((state->target == vertex_shader) && !var->shader_out) {
+	    _mesa_glsl_error(& loc, state,
+			     "`%s' cannot be marked invariant, vertex shader "
+			     "outputs only\n", var->name);
+	 } else if ((state->target == fragment_shader) && !var->shader_in) {
+	    _mesa_glsl_error(& loc, state,
+			     "`%s' cannot be marked invariant, fragment shader "
+			     "inputs only\n", var->name);
+	 }
+      }
+
       if (state->current_function != NULL) {
 	 const char *mode = NULL;
 	 const char *extra = "";




More information about the mesa-commit mailing list