summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ast.h4
-rw-r--r--src/glsl/ast_to_hir.cpp68
2 files changed, 68 insertions, 4 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 9b194dbd043..335374de16b 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -610,6 +610,10 @@ public:
virtual void print(void) const;
bool has_qualifiers() const;
+ const struct glsl_type *glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state)
+ const;
+
ast_type_qualifier qualifier;
ast_type_specifier *specifier;
};
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 88d9fd60b56..d94faa885b5 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1797,6 +1797,28 @@ ast_type_specifier::glsl_type(const char **name,
return type;
}
+const glsl_type *
+ast_fully_specified_type::glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state) const
+{
+ const struct glsl_type *type = this->specifier->glsl_type(name, state);
+
+ if (type == NULL)
+ return NULL;
+
+ if (type->base_type == GLSL_TYPE_FLOAT
+ && state->es_shader
+ && state->target == fragment_shader
+ && this->qualifier.precision == ast_precision_none
+ && state->symbols->get_variable("#default precision") == NULL) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state,
+ "no precision specified this scope for type `%s'",
+ type->name);
+ }
+
+ return type;
+}
/**
* Determine whether a toplevel variable declaration declares a varying. This
@@ -2693,7 +2715,7 @@ ast_declarator_list::hir(exec_list *instructions,
*/
(void) this->type->specifier->hir(instructions, state);
- decl_type = this->type->specifier->glsl_type(& type_name, state);
+ decl_type = this->type->glsl_type(& type_name, state);
if (this->declarations.is_empty()) {
/* If there is no structure involved in the program text, there are two
* possible scenarios:
@@ -3277,7 +3299,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
const char *name = NULL;
YYLTYPE loc = this->get_location();
- type = this->type->specifier->glsl_type(& name, state);
+ type = this->type->glsl_type(& name, state);
if (type == NULL) {
if (name != NULL) {
@@ -3484,7 +3506,7 @@ ast_function::hir(exec_list *instructions,
const char *return_type_name;
const glsl_type *return_type =
- this->return_type->specifier->glsl_type(& return_type_name, state);
+ this->return_type->glsl_type(& return_type_name, state);
if (!return_type) {
YYLTYPE loc = this->get_location();
@@ -4288,6 +4310,44 @@ ast_type_specifier::hir(exec_list *instructions,
return NULL;
}
+ if (type->base_type == GLSL_TYPE_FLOAT
+ && state->es_shader
+ && state->target == fragment_shader) {
+ /* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00
+ * spec says:
+ *
+ * "The fragment language has no default precision qualifier for
+ * floating point types."
+ *
+ * As a result, we have to track whether or not default precision has
+ * been specified for float in GLSL ES fragment shaders.
+ *
+ * Earlier in that same section, the spec says:
+ *
+ * "Non-precision qualified declarations will use the precision
+ * qualifier specified in the most recent precision statement
+ * that is still in scope. The precision statement has the same
+ * scoping rules as variable declarations. If it is declared
+ * inside a compound statement, its effect stops at the end of
+ * the innermost statement it was declared in. Precision
+ * statements in nested scopes override precision statements in
+ * outer scopes. Multiple precision statements for the same basic
+ * type can appear inside the same scope, with later statements
+ * overriding earlier statements within that scope."
+ *
+ * Default precision specifications follow the same scope rules as
+ * variables. So, we can track the state of the default float
+ * precision in the symbol table, and the rules will just work. This
+ * is a slight abuse of the symbol table, but it has the semantics
+ * that we want.
+ */
+ ir_variable *const junk =
+ new(state) ir_variable(type, "#default precision",
+ ir_var_temporary);
+
+ state->symbols->add_variable(junk);
+ }
+
/* FINISHME: Translate precision statements into IR. */
return NULL;
}
@@ -4368,7 +4428,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
}
const glsl_type *decl_type =
- decl_list->type->specifier->glsl_type(& type_name, state);
+ decl_list->type->glsl_type(& type_name, state);
foreach_list_typed (ast_declaration, decl, link,
&decl_list->declarations) {