diff options
author | Chad Versace <[email protected]> | 2011-01-16 21:44:57 -0800 |
---|---|---|
committer | Chad Versace <[email protected]> | 2011-01-17 10:20:47 -0800 |
commit | 08a286c9cc8fecb081057e0f551c88a446c47b6f (patch) | |
tree | 6b8272d30e0d6a8111af47ccf7129c92a543ef0f | |
parent | 889e1a5b6c6602198d649ea5881e0010dec575e9 (diff) |
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.
-rw-r--r-- | src/glsl/ast.h | 8 | ||||
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 52 | ||||
-rw-r--r-- | src/glsl/ast_type.cpp | 3 | ||||
-rw-r--r-- | 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 2b9b7861b0f..0e2811ca665 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 764c549005f..e3164d8c617 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 f9c371514f5..d14077473f0 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 903d3f09903..d0941ecef7d 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; } ; |