aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/ast_to_hir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/ast_to_hir.cpp')
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp362
1 files changed, 331 insertions, 31 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 598da92f8..04b16c8aa 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -72,6 +72,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
state->toplevel_ir = instructions;
+ state->gs_input_prim_type_specified = false;
+
/* Section 4.2 of the GLSL 1.20 specification states:
* "The built-in functions are scoped in a scope outside the global scope
* users declare global variables in. That is, a shader's global scope,
@@ -1771,12 +1773,6 @@ process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
}
}
}
- } else if (state->es_shader) {
- /* Section 10.17 of the GLSL ES 1.00 specification states that unsized
- * array declarations have been removed from the language.
- */
- _mesa_glsl_error(loc, state, "unsized array declarations are not "
- "allowed in GLSL ES 1.00");
}
const glsl_type *array_type = glsl_type::get_array_instance(base, length);
@@ -1936,6 +1932,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
bool ubo_qualifiers_valid,
bool is_parameter)
{
+ STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i));
+
if (qual->flags.q.invariant) {
if (var->used) {
_mesa_glsl_error(loc, state,
@@ -1963,6 +1961,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
_mesa_glsl_shader_target_name(state->target));
}
+ /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says:
+ *
+ * "However, the const qualifier cannot be used with out or inout."
+ *
+ * The same section of the GLSL 4.40 spec further clarifies this saying:
+ *
+ * "The const qualifier cannot be used with out or inout, or a
+ * compile-time error results."
+ */
+ if (is_parameter && qual->flags.q.constant && qual->flags.q.out) {
+ _mesa_glsl_error(loc, state,
+ "`const' may not be applied to `out' or `inout' "
+ "function parameters");
+ }
+
/* If there is no qualifier that changes the mode of the variable, leave
* the setting alone.
*/
@@ -2055,13 +2068,24 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
else
var->interpolation = INTERP_QUALIFIER_NONE;
- if (var->interpolation != INTERP_QUALIFIER_NONE &&
- !(state->target == vertex_shader && var->mode == ir_var_shader_out) &&
- !(state->target == fragment_shader && var->mode == ir_var_shader_in)) {
- _mesa_glsl_error(loc, state,
- "interpolation qualifier `%s' can only be applied to "
- "vertex shader outputs and fragment shader inputs",
- var->interpolation_string());
+ if (var->interpolation != INTERP_QUALIFIER_NONE) {
+ ir_variable_mode mode = (ir_variable_mode) var->mode;
+
+ if (mode != ir_var_shader_in && mode != ir_var_shader_out) {
+ _mesa_glsl_error(loc, state,
+ "interpolation qualifier `%s' can only be applied to "
+ "shader inputs or outputs.",
+ var->interpolation_string());
+
+ }
+
+ if ((state->target == vertex_shader && mode == ir_var_shader_in) ||
+ (state->target == fragment_shader && mode == ir_var_shader_out)) {
+ _mesa_glsl_error(loc, state,
+ "interpolation qualifier `%s' cannot be applied to "
+ "vertex shader inputs or fragment shader outputs",
+ var->interpolation_string());
+ }
}
var->pixel_center_integer = qual->flags.q.pixel_center_integer;
@@ -2317,7 +2341,8 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
earlier->type = var->type;
delete var;
var = NULL;
- } else if (state->ARB_fragment_coord_conventions_enable
+ } else if ((state->ARB_fragment_coord_conventions_enable ||
+ state->is_version(150, 0))
&& strcmp(var->name, "gl_FragCoord") == 0
&& earlier->type == var->type
&& earlier->mode == var->mode) {
@@ -2519,6 +2544,81 @@ process_initializer(ir_variable *var, ast_declaration *decl,
return result;
}
+
+/**
+ * Do additional processing necessary for geometry shader input declarations
+ * (this covers both interface blocks arrays and bare input variables).
+ */
+static void
+handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state,
+ YYLTYPE loc, ir_variable *var)
+{
+ unsigned num_vertices = 0;
+ if (state->gs_input_prim_type_specified) {
+ num_vertices = vertices_per_prim(state->gs_input_prim_type);
+ }
+
+ /* Geometry shader input variables must be arrays. Caller should have
+ * reported an error for this.
+ */
+ if (!var->type->is_array()) {
+ assert(state->error);
+
+ /* To avoid cascading failures, short circuit the checks below. */
+ return;
+ }
+
+ if (var->type->length == 0) {
+ /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says:
+ *
+ * All geometry shader input unsized array declarations will be
+ * sized by an earlier input layout qualifier, when present, as per
+ * the following table.
+ *
+ * Followed by a table mapping each allowed input layout qualifier to
+ * the corresponding input length.
+ */
+ if (num_vertices != 0)
+ var->type = glsl_type::get_array_instance(var->type->fields.array,
+ num_vertices);
+ } else {
+ /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec
+ * includes the following examples of compile-time errors:
+ *
+ * // code sequence within one shader...
+ * in vec4 Color1[]; // size unknown
+ * ...Color1.length()...// illegal, length() unknown
+ * in vec4 Color2[2]; // size is 2
+ * ...Color1.length()...// illegal, Color1 still has no size
+ * in vec4 Color3[3]; // illegal, input sizes are inconsistent
+ * layout(lines) in; // legal, input size is 2, matching
+ * in vec4 Color4[3]; // illegal, contradicts layout
+ * ...
+ *
+ * To detect the case illustrated by Color3, we verify that the size of
+ * an explicitly-sized array matches the size of any previously declared
+ * explicitly-sized array. To detect the case illustrated by Color4, we
+ * verify that the size of an explicitly-sized array is consistent with
+ * any previously declared input layout.
+ */
+ if (num_vertices != 0 && var->type->length != num_vertices) {
+ _mesa_glsl_error(&loc, state,
+ "geometry shader input size contradicts previously"
+ " declared layout (size is %u, but layout requires a"
+ " size of %u)", var->type->length, num_vertices);
+ } else if (state->gs_input_size != 0 &&
+ var->type->length != state->gs_input_size) {
+ _mesa_glsl_error(&loc, state,
+ "geometry shader input sizes are "
+ "inconsistent (size is %u, but a previous "
+ "declaration has size %u)",
+ var->type->length, state->gs_input_size);
+ } else {
+ state->gs_input_size = var->type->length;
+ }
+ }
+}
+
ir_rvalue *
ast_declarator_list::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
@@ -2605,6 +2705,11 @@ ast_declarator_list::hir(exec_list *instructions,
* name of a known structure type. This is both invalid and weird.
* Emit an error.
*
+ * - The program text contained something like 'mediump float;'
+ * when the programmer probably meant 'precision mediump
+ * float;' Emit a warning with a description of what they
+ * probably meant to do.
+ *
* Note that if decl_type is NULL and there is a structure involved,
* there must have been some sort of error with the structure. In this
* case we assume that an error was already generated on this line of
@@ -2613,20 +2718,33 @@ ast_declarator_list::hir(exec_list *instructions,
*/
assert(this->type->specifier->structure == NULL || decl_type != NULL
|| state->error);
- if (this->type->specifier->structure == NULL) {
- if (decl_type != NULL) {
- _mesa_glsl_warning(&loc, state, "empty declaration");
- } else {
- _mesa_glsl_error(&loc, state,
- "invalid type `%s' in empty declaration",
- type_name);
- }
- }
- if (this->type->qualifier.precision != ast_precision_none &&
- this->type->specifier->structure != NULL) {
- _mesa_glsl_error(&loc, state, "precision qualifiers can't be applied "
- "to structures");
+ if (decl_type == NULL) {
+ _mesa_glsl_error(&loc, state,
+ "invalid type `%s' in empty declaration",
+ type_name);
+ } else if (this->type->qualifier.precision != ast_precision_none) {
+ if (this->type->specifier->structure != NULL) {
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers can't be applied "
+ "to structures");
+ } else {
+ static const char *const precision_names[] = {
+ "highp",
+ "highp",
+ "mediump",
+ "lowp"
+ };
+
+ _mesa_glsl_warning(&loc, state,
+ "empty declaration with precision qualifier, "
+ "to set the default precision, use "
+ "`precision %s %s;'",
+ precision_names[this->type->qualifier.precision],
+ type_name);
+ }
+ } else {
+ _mesa_glsl_warning(&loc, state, "empty declaration");
}
}
@@ -2662,6 +2780,26 @@ ast_declarator_list::hir(exec_list *instructions,
var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
+ /* The 'varying in' and 'varying out' qualifiers can only be used with
+ * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support
+ * yet.
+ */
+ if (this->type->qualifier.flags.q.varying) {
+ if (this->type->qualifier.flags.q.in) {
+ _mesa_glsl_error(& loc, state,
+ "`varying in' qualifier in declaration of "
+ "`%s' only valid for geometry shaders using "
+ "ARB_geometry_shader4 or EXT_geometry_shader4",
+ decl->identifier);
+ } else if (this->type->qualifier.flags.q.out) {
+ _mesa_glsl_error(& loc, state,
+ "`varying out' qualifier in declaration of "
+ "`%s' only valid for geometry shaders using "
+ "ARB_geometry_shader4 or EXT_geometry_shader4",
+ decl->identifier);
+ }
+ }
+
/* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
*
* "Global variables can only use the qualifiers const,
@@ -2796,7 +2934,22 @@ ast_declarator_list::hir(exec_list *instructions,
"cannot have array type")) {
error_emitted = true;
}
- }
+ } else if (state->target == geometry_shader) {
+ /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec:
+ *
+ * Geometry shader input variables get the per-vertex values
+ * written out by vertex shader output variables of the same
+ * names. Since a geometry shader operates on a set of
+ * vertices, each input varying variable (or input block, see
+ * interface blocks below) needs to be declared as an array.
+ */
+ if (!var->type->is_array()) {
+ _mesa_glsl_error(&loc, state,
+ "geometry shader inputs must be arrays");
+ }
+
+ handle_geometry_shader_input_decl(state, loc, var);
+ }
}
/* Integer fragment inputs must be qualified with 'flat'. In GLSL ES,
@@ -2906,7 +3059,7 @@ ast_declarator_list::hir(exec_list *instructions,
}
break;
default:
- assert(0);
+ break;
}
}
@@ -3015,6 +3168,33 @@ ast_declarator_list::hir(exec_list *instructions,
decl->identifier);
}
+ if (state->es_shader) {
+ const glsl_type *const t = (earlier == NULL)
+ ? var->type : earlier->type;
+
+ if (t->is_array() && t->length == 0)
+ /* Section 10.17 of the GLSL ES 1.00 specification states that
+ * unsized array declarations have been removed from the language.
+ * Arrays that are sized using an initializer are still explicitly
+ * sized. However, GLSL ES 1.00 does not allow array
+ * initializers. That is only allowed in GLSL ES 3.00.
+ *
+ * Section 4.1.9 (Arrays) of the GLSL ES 3.00 spec says:
+ *
+ * "An array type can also be formed without specifying a size
+ * if the definition includes an initializer:
+ *
+ * float x[] = float[2] (1.0, 2.0); // declares an array of size 2
+ * float y[] = float[] (1.0, 2.0, 3.0); // declares an array of size 3
+ *
+ * float a[5];
+ * float b[] = a;"
+ */
+ _mesa_glsl_error(& loc, state,
+ "unsized array declarations are not allowed in "
+ "GLSL ES");
+ }
+
/* If the declaration is not a redeclaration, there are a few additional
* semantic checks that must be applied. In addition, variable that was
* created for the declaration should be added to the IR stream.
@@ -3323,6 +3503,18 @@ ast_function::hir(exec_list *instructions,
"function `%s' return type has qualifiers", name);
}
+ /* Section 6.1 (Function Definitions) of the GLSL 1.20 spec says:
+ *
+ * "Arrays are allowed as arguments and as the return type. In both
+ * cases, the array must be explicitly sized."
+ */
+ if (return_type->is_array() && return_type->length == 0) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state,
+ "function `%s' return type array must be explicitly "
+ "sized", name);
+ }
+
/* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
*
* "[Sampler types] can only be declared as function parameters
@@ -4362,6 +4554,19 @@ ast_interface_block::hir(exec_list *instructions,
*/
assert(declared_variables.is_empty());
+ /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec:
+ *
+ * Geometry shader input variables get the per-vertex values written
+ * out by vertex shader output variables of the same names. Since a
+ * geometry shader operates on a set of vertices, each input varying
+ * variable (or input block, see interface blocks below) needs to be
+ * declared as an array.
+ */
+ if (state->target == geometry_shader && !this->is_array &&
+ var_mode == ir_var_shader_in) {
+ _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays");
+ }
+
/* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec
* says:
*
@@ -4372,7 +4577,34 @@ ast_interface_block::hir(exec_list *instructions,
if (this->instance_name) {
ir_variable *var;
- if (this->array_size != NULL) {
+ if (this->is_array) {
+ /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says:
+ *
+ * For uniform blocks declared an array, each individual array
+ * element corresponds to a separate buffer object backing one
+ * instance of the block. As the array size indicates the number
+ * of buffer objects needed, uniform block array declarations
+ * must specify an array size.
+ *
+ * And a few paragraphs later:
+ *
+ * Geometry shader input blocks must be declared as arrays and
+ * follow the array declaration and linking rules for all
+ * geometry shader inputs. All other input and output block
+ * arrays must specify an array size.
+ *
+ * The upshot of this is that the only circumstance where an
+ * interface array size *doesn't* need to be specified is on a
+ * geometry shader input.
+ */
+ if (this->array_size == NULL &&
+ (state->target != geometry_shader || !this->layout.flags.q.in)) {
+ _mesa_glsl_error(&loc, state,
+ "only geometry shader inputs may be unsized "
+ "instance block arrays");
+
+ }
+
const glsl_type *block_array_type =
process_array_type(&loc, block_type, this->array_size, state);
@@ -4386,13 +4618,15 @@ ast_interface_block::hir(exec_list *instructions,
}
var->interface_type = block_type;
+ if (state->target == geometry_shader && var_mode == ir_var_shader_in)
+ handle_geometry_shader_input_decl(state, loc, var);
state->symbols->add_variable(var);
instructions->push_tail(var);
} else {
/* In order to have an array size, the block must also be declared with
* an instane name.
*/
- assert(this->array_size == NULL);
+ assert(!this->is_array);
for (unsigned i = 0; i < num_variables; i++) {
ir_variable *var =
@@ -4416,6 +4650,72 @@ ast_interface_block::hir(exec_list *instructions,
return NULL;
}
+
+ir_rvalue *
+ast_gs_input_layout::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ YYLTYPE loc = this->get_location();
+
+ /* If any geometry input layout declaration preceded this one, make sure it
+ * was consistent with this one.
+ */
+ if (state->gs_input_prim_type_specified &&
+ state->gs_input_prim_type != this->prim_type) {
+ _mesa_glsl_error(&loc, state,
+ "geometry shader input layout does not match"
+ " previous declaration");
+ return NULL;
+ }
+
+ /* If any shader inputs occurred before this declaration and specified an
+ * array size, make sure the size they specified is consistent with the
+ * primitive type.
+ */
+ unsigned num_vertices = vertices_per_prim(this->prim_type);
+ if (state->gs_input_size != 0 && state->gs_input_size != num_vertices) {
+ _mesa_glsl_error(&loc, state,
+ "this geometry shader input layout implies %u vertices"
+ " per primitive, but a previous input is declared"
+ " with size %u", num_vertices, state->gs_input_size);
+ return NULL;
+ }
+
+ state->gs_input_prim_type_specified = true;
+ state->gs_input_prim_type = this->prim_type;
+
+ /* If any shader inputs occurred before this declaration and did not
+ * specify an array size, their size is determined now.
+ */
+ foreach_list (node, instructions) {
+ ir_variable *var = ((ir_instruction *) node)->as_variable();
+ if (var == NULL || var->mode != ir_var_shader_in)
+ continue;
+
+ /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an
+ * array; skip it.
+ */
+ if (!var->type->is_array())
+ continue;
+
+ if (var->type->length == 0) {
+ if (var->max_array_access >= num_vertices) {
+ _mesa_glsl_error(&loc, state,
+ "this geometry shader input layout implies %u"
+ " vertices, but an access to element %u of input"
+ " `%s' already exists", num_vertices,
+ var->max_array_access, var->name);
+ } else {
+ var->type = glsl_type::get_array_instance(var->type->fields.array,
+ num_vertices);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
static void
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
exec_list *instructions)