Mesa (master): glsl: Add support for default precision statements

Chad Versace chadversary at kemper.freedesktop.org
Mon Jan 17 10:21:20 PST 2011


Module: Mesa
Branch: master
Commit: 08a286c9cc8fecb081057e0f551c88a446c47b6f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=08a286c9cc8fecb081057e0f551c88a446c47b6f

Author: Chad Versace <chad.versace at intel.com>
Date:   Sun Jan 16 21:44:57 2011 -0800

glsl: Add support for default precision statements

* Add new field ast_type_specifier::is_precision_statement.
* Add semantic checks in ast_type_specifier::hir().
* Alter parser rules accordingly.

---

 src/glsl/ast.h           |    8 +++++-
 src/glsl/ast_to_hir.cpp  |   52 ++++++++++++++++++++++++++++++++++++++++++++++
 src/glsl/ast_type.cpp    |    3 +-
 src/glsl/glsl_parser.ypp |   13 ++++++-----
 4 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 2b9b786..0e2811c 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -462,7 +462,8 @@ public:
    /** Construct a type specifier from a type name */
    ast_type_specifier(const char *name) 
       : type_specifier(ast_type_name), type_name(name), structure(NULL),
-	is_array(false), array_size(NULL), precision(ast_precision_none)
+	is_array(false), array_size(NULL), precision(ast_precision_none),
+	is_precision_statement(false)
    {
       /* empty */
    }
@@ -470,7 +471,8 @@ public:
    /** Construct a type specifier from a structure definition */
    ast_type_specifier(ast_struct_specifier *s)
       : type_specifier(ast_struct), type_name(s->name), structure(s),
-	is_array(false), array_size(NULL), precision(ast_precision_none)
+	is_array(false), array_size(NULL), precision(ast_precision_none),
+	is_precision_statement(false)
    {
       /* empty */
    }
@@ -492,6 +494,8 @@ public:
    ast_expression *array_size;
 
    unsigned precision:2;
+
+   bool is_precision_statement;
 };
 
 
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 764c549..e3164d8 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -3239,6 +3239,58 @@ ir_rvalue *
 ast_type_specifier::hir(exec_list *instructions,
 			  struct _mesa_glsl_parse_state *state)
 {
+   if (!this->is_precision_statement && this->structure == NULL)
+      return NULL;
+
+   YYLTYPE loc = this->get_location();
+
+   if (this->precision != ast_precision_none
+       && state->language_version != 100
+       && state->language_version < 130) {
+      _mesa_glsl_error(&loc, state,
+                       "precision qualifiers exist only in "
+                       "GLSL ES 1.00, and GLSL 1.30 and later");
+      return NULL;
+   }
+   if (this->precision != ast_precision_none
+       && this->structure != NULL) {
+      _mesa_glsl_error(&loc, state,
+                       "precision qualifiers do not apply to structures");
+      return NULL;
+   }
+
+   /* If this is a precision statement, check that the type to which it is
+    * applied is either float or int.
+    *
+    * From section 4.5.3 of the GLSL 1.30 spec:
+    *    "The precision statement
+    *       precision precision-qualifier type;
+    *    can be used to establish a default precision qualifier. The type
+    *    field can be either int or float [...].  Any other types or
+    *    qualifiers will result in an error.
+    */
+   if (this->is_precision_statement) {
+      assert(this->precision != ast_precision_none);
+      assert(this->structure == NULL); /* The check for structures was
+                                        * performed above. */
+      if (this->is_array) {
+         _mesa_glsl_error(&loc, state,
+                          "default precision statements do not apply to "
+                          "arrays");
+         return NULL;
+      }
+      if (this->type_specifier != ast_float
+          && this->type_specifier != ast_int) {
+         _mesa_glsl_error(&loc, state,
+                          "default precision statements apply only to types "
+                          "float and int");
+         return NULL;
+      }
+
+      /* FINISHME: Translate precision statements into IR. */
+      return NULL;
+   }
+
    if (this->structure != NULL)
       return this->structure->hir(instructions, state);
 
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index f9c3715..d140774 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -49,7 +49,8 @@ ast_type_specifier::print(void) const
 
 ast_type_specifier::ast_type_specifier(int specifier)
       : type_specifier(ast_types(specifier)), type_name(NULL), structure(NULL),
-	is_array(false), array_size(NULL), precision(ast_precision_none)
+	is_array(false), array_size(NULL), precision(ast_precision_none),
+	is_precision_statement(false)
 {
    static const char *const names[] = {
       "void",
diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp
index 903d3f0..d0941ec 100644
--- a/src/glsl/glsl_parser.ypp
+++ b/src/glsl/glsl_parser.ypp
@@ -276,16 +276,16 @@ extension_statement:
 external_declaration_list:
 	external_declaration
 	{
-	   /* FINISHME: The NULL test is only required because 'precision'
-	    * FINISHME: statements are not yet supported.
+	   /* FINISHME: The NULL test is required because pragmas are set to
+	    * FINISHME: NULL. (See production rule for external_declaration.)
 	    */
 	   if ($1 != NULL)
 	      state->translation_unit.push_tail(& $1->link);
 	}
 	| external_declaration_list external_declaration
 	{
-	   /* FINISHME: The NULL test is only required because 'precision'
-	    * FINISHME: statements are not yet supported.
+	   /* FINISHME: The NULL test is required because pragmas are set to
+	    * FINISHME: NULL. (See production rule for external_declaration.)
 	    */
 	   if ($2 != NULL)
 	      state->translation_unit.push_tail(& $2->link);
@@ -708,8 +708,9 @@ declaration:
 			       "only be applied to `int' or `float'\n");
 	      YYERROR;
 	   }
-
-	   $$ = NULL; /* FINISHME */
+	   $3->precision = $2;
+	   $3->is_precision_statement = true;
+	   $$ = $3;
 	}
 	;
 



More information about the mesa-commit mailing list