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,
detect_conflicting_assignments(state, instructions);
state->toplevel_ir = NULL;
+
+ /* Move all of the variable declarations to the front of the IR list, and
+ * reverse the order. This has the (intended!) side effect that vertex
+ * shader inputs and fragment shader outputs will appear in the IR in the
+ * same order that they appeared in the shader code. This results in the
+ * locations being assigned in the declared order. Many (arguably buggy)
+ * applications depend on this behavior, and it matches what nearly all
+ * other drivers do.
+ */
+ foreach_list_safe(node, instructions) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if (var == NULL)
+ continue;
+
+ var->remove();
+ instructions->push_head(var);
+ }
}
*/
if (!type_a->is_numeric() || !type_b->is_numeric()) {
_mesa_glsl_error(loc, state,
- "Operands to arithmetic operators must be numeric");
+ "operands to arithmetic operators must be numeric");
return glsl_type::error_type;
}
if (!apply_implicit_conversion(type_a, value_b, state)
&& !apply_implicit_conversion(type_b, value_a, state)) {
_mesa_glsl_error(loc, state,
- "Could not implicitly convert operands to "
+ "could not implicitly convert operands to "
"arithmetic operator");
return glsl_type::error_type;
}
*/
if (!type->is_numeric()) {
_mesa_glsl_error(loc, state,
- "Operands to arithmetic operators must be numeric");
+ "operands to arithmetic operators must be numeric");
return glsl_type::error_type;
}
* unsigned."
*/
if (!type_a->is_integer()) {
- _mesa_glsl_error(loc, state, "LHS of operator %% must be an integer.");
+ _mesa_glsl_error(loc, state, "LHS of operator %% must be an integer");
return glsl_type::error_type;
}
if (!type_b->is_integer()) {
- _mesa_glsl_error(loc, state, "RHS of operator %% must be an integer.");
+ _mesa_glsl_error(loc, state, "RHS of operator %% must be an integer");
return glsl_type::error_type;
}
if (type_a->base_type != type_b->base_type) {
|| !type_a->is_scalar()
|| !type_b->is_scalar()) {
_mesa_glsl_error(loc, state,
- "Operands to relational operators must be scalar and "
+ "operands to relational operators must be scalar and "
"numeric");
return glsl_type::error_type;
}
if (!apply_implicit_conversion(type_a, value_b, state)
&& !apply_implicit_conversion(type_b, value_a, state)) {
_mesa_glsl_error(loc, state,
- "Could not implicitly convert operands to "
+ "could not implicitly convert operands to "
"relational operator");
return glsl_type::error_type;
}
* a scalar as well."
*/
if (type_a->is_scalar() && !type_b->is_scalar()) {
- _mesa_glsl_error(loc, state, "If the first operand of %s is scalar, the "
+ _mesa_glsl_error(loc, state, "if the first operand of %s is scalar, the "
"second must be scalar as well",
ast_expression::operator_string(op));
return glsl_type::error_type;
if (type_a->is_vector() &&
type_b->is_vector() &&
type_a->vector_elements != type_b->vector_elements) {
- _mesa_glsl_error(loc, state, "Vector operands to operator %s must "
+ _mesa_glsl_error(loc, state, "vector operands to operator %s must "
"have same number of elements",
ast_expression::operator_string(op));
return glsl_type::error_type;
void *ctx = state;
bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
+ /* If the assignment LHS comes back as an ir_binop_vector_extract
+ * expression, move it to the RHS as an ir_triop_vector_insert.
+ */
+ if (lhs->ir_type == ir_type_expression) {
+ ir_expression *const expr = lhs->as_expression();
+
+ if (unlikely(expr->operation == ir_binop_vector_extract)) {
+ ir_rvalue *new_rhs =
+ validate_assignment(state, lhs->type, rhs, is_initializer);
+
+ if (new_rhs == NULL) {
+ _mesa_glsl_error(& lhs_loc, state, "type mismatch");
+ return lhs;
+ } else {
+ rhs = new(ctx) ir_expression(ir_triop_vector_insert,
+ expr->operands[0]->type,
+ expr->operands[0],
+ new_rhs,
+ expr->operands[1]);
+ lhs = expr->operands[0]->clone(ctx, NULL);
+ }
+ }
+ }
+
ir_variable *lhs_var = lhs->variable_referenced();
if (lhs_var)
lhs_var->assigned = true;
case GLSL_TYPE_ERROR:
case GLSL_TYPE_VOID:
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_INTERFACE:
/* I assume a comparison of a struct containing a sampler just
* ignores the sampler present in the type.
*/
break;
-
- default:
- assert(!"Should not get here.");
- break;
}
if (cmp == NULL)
* If name refers to a builtin array whose maximum allowed size is less than
* size, report an error and return true. Otherwise return false.
*/
-static bool
+void
check_builtin_array_max_size(const char *name, unsigned size,
YYLTYPE loc, struct _mesa_glsl_parse_state *state)
{
* gl_MaxTextureCoords."
*/
_mesa_glsl_error(&loc, state, "`gl_TexCoord' array size cannot "
- "be larger than gl_MaxTextureCoords (%u)\n",
+ "be larger than gl_MaxTextureCoords (%u)",
state->Const.MaxTextureCoords);
- return true;
} else if (strcmp("gl_ClipDistance", name) == 0
&& size > state->Const.MaxClipPlanes) {
/* From section 7.1 (Vertex Shader Special Variables) of the
* gl_MaxClipDistances."
*/
_mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot "
- "be larger than gl_MaxClipDistances (%u)\n",
+ "be larger than gl_MaxClipDistances (%u)",
state->Const.MaxClipPlanes);
- return true;
}
- return false;
}
/**
loc = this->get_location();
switch (this->oper) {
+ case ast_aggregate:
+ assert(!"ast_aggregate: Should never get here.");
+ break;
+
case ast_assign: {
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
|| (op[1]->type != op[2]->type)) {
YYLTYPE loc = this->subexpressions[1]->get_location();
- _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
- "operator must have matching types.");
+ _mesa_glsl_error(& loc, state, "second and third operands of ?: "
+ "operator must have matching types");
error_emitted = true;
type = glsl_type::error_type;
} else {
*/
if (type->is_array() &&
!state->check_version(120, 300, &loc,
- "Second and third operands of ?: operator "
+ "second and third operands of ?: operator "
"cannot be arrays")) {
error_emitted = true;
}
op[0] = subexpressions[0]->hir(instructions, state);
op[1] = subexpressions[1]->hir(instructions, state);
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
-
- ir_rvalue *const array = op[0];
-
- result = new(ctx) ir_dereference_array(op[0], op[1]);
+ result = _mesa_ast_array_index_to_hir(ctx, state, op[0], op[1],
+ loc, index_loc);
- /* Do not use op[0] after this point. Use array.
- */
- op[0] = NULL;
-
-
- if (error_emitted)
- break;
-
- if (!array->type->is_array()
- && !array->type->is_matrix()
- && !array->type->is_vector()) {
- _mesa_glsl_error(& index_loc, state,
- "cannot dereference non-array / non-matrix / "
- "non-vector");
- error_emitted = true;
- }
-
- if (!op[1]->type->is_integer()) {
- _mesa_glsl_error(& index_loc, state,
- "array index must be integer type");
- error_emitted = true;
- } else if (!op[1]->type->is_scalar()) {
- _mesa_glsl_error(& index_loc, state,
- "array index must be scalar");
+ if (result->type->is_error())
error_emitted = true;
- }
-
- /* If the array index is a constant expression and the array has a
- * declared size, ensure that the access is in-bounds. If the array
- * index is not a constant expression, ensure that the array has a
- * declared size.
- */
- ir_constant *const const_index = op[1]->constant_expression_value();
- if (const_index != NULL) {
- const int idx = const_index->value.i[0];
- const char *type_name;
- unsigned bound = 0;
-
- if (array->type->is_matrix()) {
- type_name = "matrix";
- } else if (array->type->is_vector()) {
- type_name = "vector";
- } else {
- type_name = "array";
- }
-
- /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
- *
- * "It is illegal to declare an array with a size, and then
- * later (in the same shader) index the same array with an
- * integral constant expression greater than or equal to the
- * declared size. It is also illegal to index an array with a
- * negative constant expression."
- */
- if (array->type->is_matrix()) {
- if (array->type->row_type()->vector_elements <= idx) {
- bound = array->type->row_type()->vector_elements;
- }
- } else if (array->type->is_vector()) {
- if (array->type->vector_elements <= idx) {
- bound = array->type->vector_elements;
- }
- } else {
- if ((array->type->array_size() > 0)
- && (array->type->array_size() <= idx)) {
- bound = array->type->array_size();
- }
- }
-
- if (bound > 0) {
- _mesa_glsl_error(& loc, state, "%s index must be < %u",
- type_name, bound);
- error_emitted = true;
- } else if (idx < 0) {
- _mesa_glsl_error(& loc, state, "%s index must be >= 0",
- type_name);
- error_emitted = true;
- }
-
- if (array->type->is_array()) {
- /* If the array is a variable dereference, it dereferences the
- * whole array, by definition. Use this to get the variable.
- *
- * FINISHME: Should some methods for getting / setting / testing
- * FINISHME: array access limits be added to ir_dereference?
- */
- ir_variable *const v = array->whole_variable_referenced();
- if ((v != NULL) && (unsigned(idx) > v->max_array_access)) {
- v->max_array_access = idx;
-
- /* Check whether this access will, as a side effect, implicitly
- * cause the size of a built-in array to be too large.
- */
- if (check_builtin_array_max_size(v->name, idx+1, loc, state))
- error_emitted = true;
- }
- }
- } else if (array->type->array_size() == 0) {
- _mesa_glsl_error(&loc, state, "unsized array index must be constant");
- } else {
- if (array->type->is_array()) {
- /* whole_variable_referenced can return NULL if the array is a
- * member of a structure. In this case it is safe to not update
- * the max_array_access field because it is never used for fields
- * of structures.
- */
- ir_variable *v = array->whole_variable_referenced();
- if (v != NULL)
- v->max_array_access = array->type->array_size() - 1;
- }
- }
-
- /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
- *
- * "Samplers aggregated into arrays within a shader (using square
- * brackets [ ]) can only be indexed with integral constant
- * expressions [...]."
- *
- * This restriction was added in GLSL 1.30. Shaders using earlier version
- * of the language should not be rejected by the compiler front-end for
- * using this construct. This allows useful things such as using a loop
- * counter as the index to an array of samplers. If the loop in unrolled,
- * the code should compile correctly. Instead, emit a warning.
- */
- if (array->type->is_array() &&
- array->type->element_type()->is_sampler() &&
- const_index == NULL) {
-
- if (!state->is_version(130, 100)) {
- if (state->es_shader) {
- _mesa_glsl_warning(&loc, state,
- "sampler arrays indexed with non-constant "
- "expressions is optional in %s",
- state->get_version_string());
- } else {
- _mesa_glsl_warning(&loc, state,
- "sampler arrays indexed with non-constant "
- "expressions will be forbidden in GLSL 1.30 and "
- "later");
- }
- } else {
- _mesa_glsl_error(&loc, state,
- "sampler arrays indexed with non-constant "
- "expressions is forbidden in GLSL 1.30 and "
- "later");
- error_emitted = true;
- }
- }
-
- if (error_emitted)
- result->type = glsl_type::error_type;
break;
}
{
unsigned length = 0;
+ if (base == NULL)
+ return glsl_type::error_type;
+
/* From page 19 (page 25) of the GLSL 1.20 spec:
*
* "Only one-dimensional arrays may be declared."
}
}
}
- } 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.");
}
- return glsl_type::get_array_instance(base, length);
+ const glsl_type *array_type = glsl_type::get_array_instance(base, length);
+ return array_type != NULL ? array_type : glsl_type::error_type;
}
{
switch (target) {
case vertex_shader:
- return var->mode == ir_var_out;
+ return var->mode == ir_var_shader_out;
case fragment_shader:
- return var->mode == ir_var_in;
+ return var->mode == ir_var_shader_in;
default:
- return var->mode == ir_var_out || var->mode == ir_var_in;
+ return var->mode == ir_var_shader_out || var->mode == ir_var_shader_in;
+ }
+}
+
+
+/**
+ * Matrix layout qualifiers are only allowed on certain types
+ */
+static void
+validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const glsl_type *type)
+{
+ if (!type->is_matrix() && !type->is_record()) {
+ _mesa_glsl_error(loc, state,
+ "uniform block layout qualifiers row_major and "
+ "column_major can only be applied to matrix and "
+ "structure types");
+ } else if (type->is_record()) {
+ /* We allow 'layout(row_major)' on structure types because it's the only
+ * way to get row-major layouts on matrices contained in structures.
+ */
+ _mesa_glsl_warning(loc, state,
+ "uniform block layout qualifiers row_major and "
+ "column_major applied to structure types is not "
+ "strictly conformant and my be rejected by other "
+ "compilers");
}
}
+static bool
+validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ ir_variable *var,
+ const ast_type_qualifier *qual)
+{
+ if (var->mode != ir_var_uniform) {
+ _mesa_glsl_error(loc, state,
+ "the \"binding\" qualifier only applies to uniforms");
+ return false;
+ }
+
+ if (qual->binding < 0) {
+ _mesa_glsl_error(loc, state, "binding values must be >= 0");
+ return false;
+ }
+
+ const struct gl_context *const ctx = state->ctx;
+ unsigned elements = var->type->is_array() ? var->type->length : 1;
+ unsigned max_index = qual->binding + elements - 1;
+
+ if (var->type->is_interface()) {
+ /* UBOs. From page 60 of the GLSL 4.20 specification:
+ * "If the binding point for any uniform block instance is less than zero,
+ * or greater than or equal to the implementation-dependent maximum
+ * number of uniform buffer bindings, a compilation error will occur.
+ * When the binding identifier is used with a uniform block instanced as
+ * an array of size N, all elements of the array from binding through
+ * binding + N – 1 must be within this range."
+ *
+ * The implementation-dependent maximum is GL_MAX_UNIFORM_BUFFER_BINDINGS.
+ */
+ if (max_index >= ctx->Const.MaxUniformBufferBindings) {
+ _mesa_glsl_error(loc, state, "layout(binding = %d) for %d UBOs exceeds "
+ "the maximum number of UBO binding points (%d)",
+ qual->binding, elements,
+ ctx->Const.MaxUniformBufferBindings);
+ return false;
+ }
+ } else if (var->type->is_sampler() ||
+ (var->type->is_array() && var->type->fields.array->is_sampler())) {
+ /* Samplers. From page 63 of the GLSL 4.20 specification:
+ * "If the binding is less than zero, or greater than or equal to the
+ * implementation-dependent maximum supported number of units, a
+ * compilation error will occur. When the binding identifier is used
+ * with an array of size N, all elements of the array from binding
+ * through binding + N - 1 must be within this range."
+ */
+ unsigned limit;
+ switch (state->target) {
+ case vertex_shader:
+ limit = ctx->Const.VertexProgram.MaxTextureImageUnits;
+ break;
+ case geometry_shader:
+ limit = ctx->Const.GeometryProgram.MaxTextureImageUnits;
+ break;
+ case fragment_shader:
+ limit = ctx->Const.FragmentProgram.MaxTextureImageUnits;
+ break;
+ }
+
+ if (max_index >= limit) {
+ _mesa_glsl_error(loc, state, "layout(binding = %d) for %d samplers "
+ "exceeds the maximum number of texture image units "
+ "(%d)", qual->binding, elements, limit);
+
+ return false;
+ }
+ } else {
+ _mesa_glsl_error(loc, state,
+ "the \"binding\" qualifier only applies to uniform "
+ "blocks, samplers, or arrays of samplers");
+ return false;
+ }
+
+ return true;
+}
static void
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,
_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.
*/
if (qual->flags.q.in && qual->flags.q.out)
- var->mode = ir_var_inout;
- else if (qual->flags.q.attribute || qual->flags.q.in
+ var->mode = ir_var_function_inout;
+ else if (qual->flags.q.in)
+ var->mode = is_parameter ? ir_var_function_in : ir_var_shader_in;
+ else if (qual->flags.q.attribute
|| (qual->flags.q.varying && (state->target == fragment_shader)))
- var->mode = ir_var_in;
- else if (qual->flags.q.out
- || (qual->flags.q.varying && (state->target == vertex_shader)))
- var->mode = ir_var_out;
+ var->mode = ir_var_shader_in;
+ else if (qual->flags.q.out)
+ var->mode = is_parameter ? ir_var_function_out : ir_var_shader_out;
+ else if (qual->flags.q.varying && (state->target == vertex_shader))
+ var->mode = ir_var_shader_out;
else if (qual->flags.q.uniform)
var->mode = ir_var_uniform;
* Similar text exists in the section on vertex shader outputs.
*
* Similar text exists in the GLSL ES 3.00 spec, except that the GLSL ES
- * 3.00 spec claims to allow structs as well. However, this is likely
- * an error, since section 11 of the spec ("Counting of Inputs and
- * Outputs") enumerates all possible types of interstage linkage
- * variables, and it does not mention structs.
+ * 3.00 spec allows structs as well. Varying structs are also allowed
+ * in GLSL 1.50.
*/
switch (var->type->get_scalar_type()->base_type) {
case GLSL_TYPE_FLOAT:
state->get_version_string());
break;
case GLSL_TYPE_STRUCT:
+ if (state->is_version(150, 300))
+ break;
_mesa_glsl_error(loc, state,
"varying variables may not be of type struct");
break;
if (state->all_invariant && (state->current_function == NULL)) {
switch (state->target) {
case vertex_shader:
- if (var->mode == ir_var_out)
+ if (var->mode == ir_var_shader_out)
var->invariant = true;
break;
case geometry_shader:
- if ((var->mode == ir_var_in) || (var->mode == ir_var_out))
+ if ((var->mode == ir_var_shader_in)
+ || (var->mode == ir_var_shader_out))
var->invariant = true;
break;
case fragment_shader:
- if (var->mode == ir_var_in)
+ if (var->mode == ir_var_shader_in)
var->invariant = true;
break;
}
else
var->interpolation = INTERP_QUALIFIER_NONE;
- if (var->interpolation != INTERP_QUALIFIER_NONE &&
- !(state->target == vertex_shader && var->mode == ir_var_out) &&
- !(state->target == fragment_shader && var->mode == ir_var_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;
*/
switch (state->target) {
case vertex_shader:
- if (!global_scope || (var->mode != ir_var_in)) {
+ if (!global_scope || (var->mode != ir_var_shader_in)) {
fail = true;
string = "input";
}
case geometry_shader:
_mesa_glsl_error(loc, state,
"geometry shader variables cannot be given "
- "explicit locations\n");
+ "explicit locations");
break;
case fragment_shader:
- if (!global_scope || (var->mode != ir_var_out)) {
+ if (!global_scope || (var->mode != ir_var_shader_out)) {
fail = true;
string = "output";
}
if (fail) {
_mesa_glsl_error(loc, state,
"only %s shader %s variables can be given an "
- "explicit location\n",
+ "explicit location",
_mesa_glsl_shader_target_name(state->target),
string);
} else {
*/
if (qual->index < 0 || qual->index > 1) {
_mesa_glsl_error(loc, state,
- "explicit index may only be 0 or 1\n");
+ "explicit index may only be 0 or 1");
} else {
var->explicit_index = true;
var->index = qual->index;
}
} else if (qual->flags.q.explicit_index) {
_mesa_glsl_error(loc, state,
- "explicit index requires explicit location\n");
+ "explicit index requires explicit location");
}
- /* Does the declaration use the 'layout' keyword?
- */
- const bool uses_layout = qual->flags.q.pixel_center_integer
- || qual->flags.q.origin_upper_left
- || qual->flags.q.explicit_location; /* no need for index since it relies on location */
+ if (qual->flags.q.explicit_binding &&
+ validate_binding_qualifier(state, loc, var, qual)) {
+ var->explicit_binding = true;
+ var->binding = qual->binding;
+ }
/* Does the declaration use the deprecated 'attribute' or 'varying'
* keywords?
const bool relaxed_layout_qualifier_checking =
state->ARB_fragment_coord_conventions_enable;
- if (uses_layout && uses_deprecated_qualifier) {
+ if (qual->has_layout() && uses_deprecated_qualifier) {
if (relaxed_layout_qualifier_checking) {
_mesa_glsl_warning(loc, state,
"`layout' qualifier may not be used with "
"members");
}
- if (!ubo_qualifiers_valid &&
- (qual->flags.q.row_major || qual->flags.q.column_major)) {
- _mesa_glsl_error(loc, state,
- "uniform block layout qualifiers row_major and "
- "column_major can only be applied to uniform block "
- "members");
+ if (qual->flags.q.row_major || qual->flags.q.column_major) {
+ if (!ubo_qualifiers_valid) {
+ _mesa_glsl_error(loc, state,
+ "uniform block layout qualifiers row_major and "
+ "column_major can only be applied to uniform block "
+ "members");
+ } else
+ validate_matrix_layout_for_type(state, loc, var->type);
}
}
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) {
"cannot initialize samplers");
}
- if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
+ if ((var->mode == ir_var_shader_in) && (state->current_function == NULL)) {
_mesa_glsl_error(& initializer_loc, state,
"cannot initialize %s shader input / %s",
_mesa_glsl_shader_target_name(state->target),
ir_constant *constant_value = rhs->constant_expression_value();
if (!constant_value) {
- _mesa_glsl_error(& initializer_loc, state,
- "initializer of %s variable `%s' must be a "
- "constant expression",
- (type->qualifier.flags.q.constant)
- ? "const" : "uniform",
- decl->identifier);
- if (var->type->is_numeric()) {
- /* Reduce cascading errors. */
- var->constant_value = ir_constant::zero(state, var->type);
- }
- } else {
+ /* If ARB_shading_language_420pack is enabled, initializers of
+ * const-qualified local variables do not have to be constant
+ * expressions. Const-qualified global variables must still be
+ * initialized with constant expressions.
+ */
+ if (!state->ARB_shading_language_420pack_enable
+ || state->current_function == NULL) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "initializer of %s variable `%s' must be a "
+ "constant expression",
+ (type->qualifier.flags.q.constant)
+ ? "const" : "uniform",
+ decl->identifier);
+ if (var->type->is_numeric()) {
+ /* Reduce cascading errors. */
+ var->constant_value = ir_constant::zero(state, var->type);
+ }
+ }
+ } else {
rhs = constant_value;
var->constant_value = constant_value;
}
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)
if (state->current_function != NULL) {
_mesa_glsl_error(& loc, state,
- "All uses of `invariant' keyword must be at global "
- "scope\n");
+ "all uses of `invariant' keyword must be at global "
+ "scope");
}
foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
state->symbols->get_variable(decl->identifier);
if (earlier == NULL) {
_mesa_glsl_error(& loc, state,
- "Undeclared variable `%s' cannot be marked "
- "invariant\n", decl->identifier);
+ "undeclared variable `%s' cannot be marked "
+ "invariant", decl->identifier);
} else if ((state->target == vertex_shader)
- && (earlier->mode != ir_var_out)) {
+ && (earlier->mode != ir_var_shader_out)) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, vertex shader "
- "outputs only\n", decl->identifier);
+ "outputs only", decl->identifier);
} else if ((state->target == fragment_shader)
- && (earlier->mode != ir_var_in)) {
+ && (earlier->mode != ir_var_shader_in)) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, fragment shader "
- "inputs only\n", decl->identifier);
+ "inputs only", decl->identifier);
} else if (earlier->used) {
_mesa_glsl_error(& loc, state,
"variable `%s' may not be redeclared "
* 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
*/
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 (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");
}
}
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,
if (this->type->qualifier.flags.q.out) {
_mesa_glsl_error(& loc, state,
"`out' qualifier in declaration of `%s' "
- "only valid for function parameters in %s.",
+ "only valid for function parameters in %s",
decl->identifier, state->get_version_string());
}
if (this->type->qualifier.flags.q.in) {
_mesa_glsl_error(& loc, state,
"`in' qualifier in declaration of `%s' "
- "only valid for function parameters in %s.",
+ "only valid for function parameters in %s",
decl->identifier, state->get_version_string());
}
/* FINISHME: Test for other invalid qualifiers. */
& loc, this->ubo_qualifiers_valid, false);
if (this->type->qualifier.flags.q.invariant) {
- if ((state->target == vertex_shader) && !(var->mode == ir_var_out ||
- var->mode == ir_var_inout)) {
- /* FINISHME: Note that this doesn't work for invariant on
- * a function signature outval
- */
+ if ((state->target == vertex_shader) &&
+ var->mode != ir_var_shader_out) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, vertex shader "
- "outputs only\n", var->name);
+ "outputs only", var->name);
} else if ((state->target == fragment_shader) &&
- !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
+ var->mode != ir_var_shader_in) {
/* FINISHME: Note that this doesn't work for invariant on
* a function signature inval
*/
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, fragment shader "
- "inputs only\n", var->name);
+ "inputs only", var->name);
}
}
"global scope%s",
mode, var->name, extra);
}
- } else if (var->mode == ir_var_in) {
+ } else if (var->mode == ir_var_shader_in) {
var->read_only = true;
if (state->target == vertex_shader) {
}
if (!error_emitted && var->type->is_array() &&
- !state->check_version(140, 0, &loc,
+ !state->check_version(150, 0, &loc,
"vertex shader input / attribute "
"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 vertex outputs must be qualified with 'flat'.
- *
- * From section 4.3.6 of the GLSL 1.30 spec:
- * "If a vertex output is a signed or unsigned integer or integer
- * vector, then it must be qualified with the interpolation qualifier
- * flat."
+ /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES,
+ * so must integer vertex outputs.
*
- * From section 4.3.4 of the GLSL 3.00 ES spec:
+ * From section 4.3.4 ("Inputs") of the GLSL 1.50 spec:
* "Fragment shader inputs that are signed or unsigned integers or
* integer vectors must be qualified with the interpolation qualifier
* flat."
*
- * Since vertex outputs and fragment inputs must have matching
- * qualifiers, these two requirements are equivalent.
+ * From section 4.3.4 ("Input Variables") of the GLSL 3.00 ES spec:
+ * "Fragment shader inputs that are, or contain, signed or unsigned
+ * integers or integer vectors must be qualified with the
+ * interpolation qualifier flat."
+ *
+ * From section 4.3.6 ("Output Variables") of the GLSL 3.00 ES spec:
+ * "Vertex shader outputs that are, or contain, signed or unsigned
+ * integers or integer vectors must be qualified with the
+ * interpolation qualifier flat."
+ *
+ * Note that prior to GLSL 1.50, this requirement applied to vertex
+ * outputs rather than fragment inputs. That creates problems in the
+ * presence of geometry shaders, so we adopt the GLSL 1.50 rule for all
+ * desktop GL shaders. For GLSL ES shaders, we follow the spec and
+ * apply the restriction to both vertex outputs and fragment inputs.
+ *
+ * Note also that the desktop GLSL specs are missing the text "or
+ * contain"; this is presumably an oversight, since there is no
+ * reasonable way to interpolate a fragment shader input that contains
+ * an integer.
*/
- if (state->is_version(130, 300)
- && state->target == vertex_shader
- && state->current_function == NULL
- && var->type->is_integer()
- && var->mode == ir_var_out
- && var->interpolation != INTERP_QUALIFIER_FLAT) {
-
- _mesa_glsl_error(&loc, state, "If a vertex output is an integer, "
- "then it must be qualified with 'flat'");
+ if (state->is_version(130, 300) &&
+ var->type->contains_integer() &&
+ var->interpolation != INTERP_QUALIFIER_FLAT &&
+ ((state->target == fragment_shader && var->mode == ir_var_shader_in)
+ || (state->target == vertex_shader && var->mode == ir_var_shader_out
+ && state->es_shader))) {
+ const char *var_type = (state->target == vertex_shader) ?
+ "vertex output" : "fragment input";
+ _mesa_glsl_error(&loc, state, "if a %s is (or contains) "
+ "an integer, then it must be qualified with 'flat'",
+ var_type);
}
}
break;
default:
- assert(0);
+ break;
}
}
"'centroid in' cannot be used in a vertex shader");
}
+ /* Section 4.3.6 of the GLSL 1.30 specification states:
+ * "It is an error to use centroid out in a fragment shader."
+ *
+ * The GL_ARB_shading_language_420pack extension specification states:
+ * "It is an error to use auxiliary storage qualifiers or interpolation
+ * qualifiers on an output in a fragment shader."
+ */
+ if (state->target == fragment_shader &&
+ this->type->qualifier.flags.q.out &&
+ this->type->qualifier.has_auxiliary_storage()) {
+ _mesa_glsl_error(&loc, state,
+ "auxiliary storage qualifiers cannot be used on "
+ "fragment shader outputs");
+ }
/* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
*/
- if (this->type->specifier->precision != ast_precision_none) {
+ if (this->type->qualifier.precision != ast_precision_none) {
state->check_precision_qualifiers_allowed(&loc);
}
* From page 87 of the GLSL ES spec:
* "RESOLUTION: Allow sampler types to take a precision qualifier."
*/
- if (this->type->specifier->precision != ast_precision_none
+ if (this->type->qualifier.precision != ast_precision_none
&& !var->type->is_float()
&& !var->type->is_integer()
+ && !var->type->is_record()
&& !(var->type->is_sampler() && state->es_shader)
&& !(var->type->is_array()
&& (var->type->fields.array->is_float()
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.
if (!type->is_error() && type->array_size() == 0) {
_mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
- "a declared size.");
+ "a declared size");
type = glsl_type::error_type;
}
is_void = false;
- ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
+ ir_variable *var = new(ctx)
+ ir_variable(type, this->identifier, ir_var_function_in);
/* Apply any specified qualifiers to the parameter declaration. Note that
* for function parameters the default mode is 'in'.
* as out or inout function parameters, nor can they be assigned
* into."
*/
- if ((var->mode == ir_var_inout || var->mode == ir_var_out)
+ if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out)
&& type->contains_sampler()) {
_mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers");
type = glsl_type::error_type;
* So for GLSL 1.10, passing an array as an out or inout parameter is not
* allowed. This restriction is removed in GLSL 1.20, and in GLSL ES.
*/
- if ((var->mode == ir_var_inout || var->mode == ir_var_out)
+ if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out)
&& type->is_array()
&& !state->check_version(120, 100, &loc,
- "Arrays cannot be out or inout parameters")) {
+ "arrays cannot be out or inout parameters")) {
type = glsl_type::error_type;
}
"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
"match prototype", name);
}
- if (is_definition && sig->is_defined) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
+ if (sig->is_defined) {
+ if (is_definition) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
+ } else {
+ /* We just encountered a prototype that exactly matches a
+ * function that's already been defined. This is redundant,
+ * and we should ignore it.
+ */
+ return NULL;
+ }
}
}
} else {
assert(state->current_function);
if (opt_return_value) {
- ir_rvalue *const ret = opt_return_value->hir(instructions, state);
+ ir_rvalue *ret = opt_return_value->hir(instructions, state);
/* The value of the return type can be NULL if the shader says
* 'return foo();' and foo() is a function that returns void.
const glsl_type *const ret_type =
(ret == NULL) ? glsl_type::void_type : ret->type;
- /* Implicit conversions are not allowed for return values. */
- if (state->current_function->return_type != ret_type) {
+ /* Implicit conversions are not allowed for return values prior to
+ * ARB_shading_language_420pack.
+ */
+ if (state->current_function->return_type != ret_type) {
YYLTYPE loc = this->get_location();
- _mesa_glsl_error(& loc, state,
- "`return' with wrong type %s, in function `%s' "
- "returning %s",
- ret_type->name,
- state->current_function->function_name(),
- state->current_function->return_type->name);
- }
+ if (state->ARB_shading_language_420pack_enable) {
+ if (!apply_implicit_conversion(state->current_function->return_type,
+ ret, state)) {
+ _mesa_glsl_error(& loc, state,
+ "could not implicitly convert return value "
+ "to %s, in function `%s'",
+ state->current_function->return_type->name,
+ state->current_function->function_name());
+ }
+ } else {
+ _mesa_glsl_error(& loc, state,
+ "`return' with wrong type %s, in function `%s' "
+ "returning %s",
+ ret_type->name,
+ state->current_function->function_name(),
+ state->current_function->return_type->name);
+ }
+ } else if (state->current_function->return_type->base_type ==
+ GLSL_TYPE_VOID) {
+ YYLTYPE loc = this->get_location();
+
+ /* The ARB_shading_language_420pack, GLSL ES 3.0, and GLSL 4.20
+ * specs add a clarification:
+ *
+ * "A void function can only use return without a return argument, even if
+ * the return argument has void type. Return statements only accept values:
+ *
+ * void func1() { }
+ * void func2() { return func1(); } // illegal return statement"
+ */
+ _mesa_glsl_error(& loc, state,
+ "void functions can only use `return' without a "
+ "return argument");
+ }
inst = new(ctx) ir_return(ret);
} else {
}
+/**
+ * Determine if the given type is valid for establishing a default precision
+ * qualifier.
+ *
+ * From GLSL ES 3.00 section 4.5.4 ("Default Precision Qualifiers"):
+ *
+ * "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 or any of the sampler types, and the
+ * precision-qualifier can be lowp, mediump, or highp."
+ *
+ * GLSL ES 1.00 has similar language. GLSL 1.30 doesn't allow precision
+ * qualifiers on sampler types, but this seems like an oversight (since the
+ * intention of including these in GLSL 1.30 is to allow compatibility with ES
+ * shaders). So we allow int, float, and all sampler types regardless of GLSL
+ * version.
+ */
+static bool
+is_valid_default_precision_type(const struct glsl_type *const type)
+{
+ if (type == NULL)
+ return false;
+
+ switch (type->base_type) {
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ /* "int" and "float" are valid, but vectors and matrices are not. */
+ return type->vector_elements == 1 && type->matrix_columns == 1;
+ case GLSL_TYPE_SAMPLER:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
ir_rvalue *
ast_type_specifier::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
- if (!this->is_precision_statement && this->structure == NULL)
+ if (this->default_precision == ast_precision_none && this->structure == NULL)
return NULL;
YYLTYPE loc = this->get_location();
- if (this->precision != ast_precision_none
- && !state->check_precision_qualifiers_allowed(&loc)) {
- 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.
*
* 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->default_precision != ast_precision_none) {
+ if (!state->check_precision_qualifiers_allowed(&loc))
+ return NULL;
+
+ if (this->structure != NULL) {
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers do not apply to structures");
+ return NULL;
+ }
+
if (this->is_array) {
_mesa_glsl_error(&loc, state,
"default precision statements do not apply to "
"arrays");
return NULL;
}
- if (strcmp(this->type_name, "float") != 0 &&
- strcmp(this->type_name, "int") != 0) {
+
+ const struct glsl_type *const type =
+ state->symbols->get_type(this->type_name);
+ if (!is_valid_default_precision_type(type)) {
_mesa_glsl_error(&loc, state,
- "default precision statements apply only to types "
- "float and int");
+ "default precision statements apply only to "
+ "float, int, and sampler types");
return NULL;
}
return NULL;
}
- if (this->structure != NULL)
+ /* _mesa_ast_set_aggregate_type() sets the <structure> field so that
+ * process_record_constructor() can do type-checking on C-style initializer
+ * expressions of structs, but ast_struct_specifier should only be translated
+ * to HIR if it is declaring the type of a structure.
+ *
+ * The ->is_declaration field is false for initializers of variables
+ * declared separately from the struct's type definition.
+ *
+ * struct S { ... }; (is_declaration = true)
+ * struct T { ... } t = { ... }; (is_declaration = true)
+ * S s = { ... }; (is_declaration = false)
+ */
+ if (this->structure != NULL && this->structure->is_declaration)
return this->structure->hir(instructions, state);
return NULL;
}
-ir_rvalue *
-ast_struct_specifier::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
+/**
+ * Process a structure or interface block tree into an array of structure fields
+ *
+ * After parsing, where there are some syntax differnces, structures and
+ * interface blocks are almost identical. They are similar enough that the
+ * AST for each can be processed the same way into a set of
+ * \c glsl_struct_field to describe the members.
+ *
+ * \return
+ * The number of fields processed. A pointer to the array structure fields is
+ * stored in \c *fields_ret.
+ */
+unsigned
+ast_process_structure_or_interface_block(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state,
+ exec_list *declarations,
+ YYLTYPE &loc,
+ glsl_struct_field **fields_ret,
+ bool is_interface,
+ bool block_row_major)
{
unsigned decl_count = 0;
- /* Make an initial pass over the list of structure fields to determine how
+ /* Make an initial pass over the list of fields to determine how
* many there are. Each element in this list is an ast_declarator_list.
* This means that we actually need to count the number of elements in the
* 'declarations' list in each of the elements.
*/
- foreach_list_typed (ast_declarator_list, decl_list, link,
- &this->declarations) {
+ foreach_list_typed (ast_declarator_list, decl_list, link, declarations) {
foreach_list_const (decl_ptr, & decl_list->declarations) {
decl_count++;
}
}
- /* Allocate storage for the structure fields and process the field
+ /* Allocate storage for the fields and process the field
* declarations. As the declarations are processed, try to also convert
* the types to HIR. This ensures that structure definitions embedded in
- * other structure definitions are processed.
+ * other structure definitions or in interface blocks are processed.
*/
glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field,
decl_count);
unsigned i = 0;
- foreach_list_typed (ast_declarator_list, decl_list, link,
- &this->declarations) {
+ foreach_list_typed (ast_declarator_list, decl_list, link, declarations) {
const char *type_name;
decl_list->type->specifier->hir(instructions, state);
* embedded structure definitions have been removed from the language.
*/
if (state->es_shader && decl_list->type->specifier->structure != NULL) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state, "Embedded structure definitions are "
- "not allowed in GLSL ES 1.00.");
+ _mesa_glsl_error(&loc, state, "embedded structure definitions are "
+ "not allowed in GLSL ES 1.00");
}
const glsl_type *decl_type =
foreach_list_typed (ast_declaration, decl, link,
&decl_list->declarations) {
- const struct glsl_type *field_type = decl_type;
+ /* From the GL_ARB_uniform_buffer_object spec:
+ *
+ * "Sampler types are not allowed inside of uniform
+ * blocks. All other types, arrays, and structures
+ * allowed for uniforms are allowed within a uniform
+ * block."
+ *
+ * It should be impossible for decl_type to be NULL here. Cases that
+ * might naturally lead to decl_type being NULL, especially for the
+ * is_interface case, will have resulted in compilation having
+ * already halted due to a syntax error.
+ */
+ const struct glsl_type *field_type =
+ decl_type != NULL ? decl_type : glsl_type::error_type;
+
+ if (is_interface && field_type->contains_sampler()) {
+ YYLTYPE loc = decl_list->get_location();
+ _mesa_glsl_error(&loc, state,
+ "uniform in non-default uniform block contains sampler");
+ }
+
+ const struct ast_type_qualifier *const qual =
+ & decl_list->type->qualifier;
+ if (qual->flags.q.std140 ||
+ qual->flags.q.packed ||
+ qual->flags.q.shared) {
+ _mesa_glsl_error(&loc, state,
+ "uniform block layout qualifiers std140, packed, and "
+ "shared can only be applied to uniform blocks, not "
+ "members");
+ }
+
if (decl->is_array) {
- YYLTYPE loc = decl->get_location();
field_type = process_array_type(&loc, decl_type, decl->array_size,
state);
}
- fields[i].type = (field_type != NULL)
- ? field_type : glsl_type::error_type;
+ fields[i].type = field_type;
fields[i].name = decl->identifier;
+
+ if (qual->flags.q.row_major || qual->flags.q.column_major) {
+ if (!qual->flags.q.uniform) {
+ _mesa_glsl_error(&loc, state,
+ "row_major and column_major can only be "
+ "applied to uniform interface blocks");
+ } else if (!field_type->is_matrix() && !field_type->is_record()) {
+ _mesa_glsl_error(&loc, state,
+ "uniform block layout qualifiers row_major and "
+ "column_major can only be applied to matrix and "
+ "structure types");
+ } else
+ validate_matrix_layout_for_type(state, &loc, field_type);
+ }
+
+ if (qual->flags.q.uniform && qual->has_interpolation()) {
+ _mesa_glsl_error(&loc, state,
+ "interpolation qualifiers cannot be used "
+ "with uniform interface blocks");
+ }
+
+ if (field_type->is_matrix() ||
+ (field_type->is_array() && field_type->fields.array->is_matrix())) {
+ fields[i].row_major = block_row_major;
+ if (qual->flags.q.row_major)
+ fields[i].row_major = true;
+ else if (qual->flags.q.column_major)
+ fields[i].row_major = false;
+ }
+
i++;
}
}
assert(i == decl_count);
+ *fields_ret = fields;
+ return decl_count;
+}
+
+
+ir_rvalue *
+ast_struct_specifier::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ YYLTYPE loc = this->get_location();
+
+ /* Section 4.1.8 (Structures) of the GLSL 1.10 spec says:
+ *
+ * "Anonymous structures are not supported; so embedded structures must
+ * have a declarator. A name given to an embedded struct is scoped at
+ * the same level as the struct it is embedded in."
+ *
+ * The same section of the GLSL 1.20 spec says:
+ *
+ * "Anonymous structures are not supported. Embedded structures are not
+ * supported.
+ *
+ * struct S { float f; };
+ * struct T {
+ * S; // Error: anonymous structures disallowed
+ * struct { ... }; // Error: embedded structures disallowed
+ * S s; // Okay: nested structures with name are allowed
+ * };"
+ *
+ * The GLSL ES 1.00 and 3.00 specs have similar langauge and examples. So,
+ * we allow embedded structures in 1.10 only.
+ */
+ if (state->language_version != 110 && state->struct_specifier_depth != 0)
+ _mesa_glsl_error(&loc, state,
+ "embedded structure declartions are not allowed");
+
+ state->struct_specifier_depth++;
+
+ glsl_struct_field *fields;
+ unsigned decl_count =
+ ast_process_structure_or_interface_block(instructions,
+ state,
+ &this->declarations,
+ loc,
+ &fields,
+ false,
+ false);
+
const glsl_type *t =
glsl_type::get_record_instance(fields, decl_count, this->name);
- YYLTYPE loc = this->get_location();
if (!state->symbols->add_type(name, t)) {
_mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
} else {
}
}
+ state->struct_specifier_depth--;
+
/* Structure type definitions do not have r-values.
*/
return NULL;
}
-static struct gl_uniform_block *
-get_next_uniform_block(struct _mesa_glsl_parse_state *state)
-{
- if (state->num_uniform_blocks >= state->uniform_block_array_size) {
- state->uniform_block_array_size *= 2;
- if (state->uniform_block_array_size <= 4)
- state->uniform_block_array_size = 4;
-
- state->uniform_blocks = reralloc(state,
- state->uniform_blocks,
- struct gl_uniform_block,
- state->uniform_block_array_size);
- }
-
- memset(&state->uniform_blocks[state->num_uniform_blocks],
- 0, sizeof(*state->uniform_blocks));
- return &state->uniform_blocks[state->num_uniform_blocks++];
-}
-
ir_rvalue *
-ast_uniform_block::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
+ast_interface_block::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
{
- /* The ast_uniform_block has a list of ast_declarator_lists. We
+ YYLTYPE loc = this->get_location();
+
+ /* The ast_interface_block has a list of ast_declarator_lists. We
* need to turn those into ir_variables with an association
* with this uniform block.
*/
- struct gl_uniform_block *ubo = get_next_uniform_block(state);
- ubo->Name = ralloc_strdup(state->uniform_blocks, this->block_name);
-
- unsigned int num_variables = 0;
- foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) {
- foreach_list_const(node, &decl_list->declarations) {
- num_variables++;
- }
+ enum glsl_interface_packing packing;
+ if (this->layout.flags.q.shared) {
+ packing = GLSL_INTERFACE_PACKING_SHARED;
+ } else if (this->layout.flags.q.packed) {
+ packing = GLSL_INTERFACE_PACKING_PACKED;
+ } else {
+ /* The default layout is std140.
+ */
+ packing = GLSL_INTERFACE_PACKING_STD140;
}
bool block_row_major = this->layout.flags.q.row_major;
+ exec_list declared_variables;
+ glsl_struct_field *fields;
+ unsigned int num_variables =
+ ast_process_structure_or_interface_block(&declared_variables,
+ state,
+ &this->declarations,
+ loc,
+ &fields,
+ true,
+ block_row_major);
+
+ ir_variable_mode var_mode;
+ const char *iface_type_name;
+ if (this->layout.flags.q.in) {
+ var_mode = ir_var_shader_in;
+ iface_type_name = "in";
+ } else if (this->layout.flags.q.out) {
+ var_mode = ir_var_shader_out;
+ iface_type_name = "out";
+ } else if (this->layout.flags.q.uniform) {
+ var_mode = ir_var_uniform;
+ iface_type_name = "uniform";
+ } else {
+ var_mode = ir_var_auto;
+ iface_type_name = "UNKNOWN";
+ assert(!"interface block layout qualifier not found!");
+ }
- ubo->Uniforms = rzalloc_array(state->uniform_blocks,
- struct gl_uniform_buffer_variable,
- num_variables);
+ const glsl_type *block_type =
+ glsl_type::get_interface_instance(fields,
+ num_variables,
+ packing,
+ this->block_name);
- foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) {
- exec_list declared_variables;
+ if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state, "interface block `%s' with type `%s' "
+ "already taken in the current scope",
+ this->block_name, iface_type_name);
+ }
- decl_list->hir(&declared_variables, state);
+ /* Since interface blocks cannot contain statements, it should be
+ * impossible for the block to generate any instructions.
+ */
+ assert(declared_variables.is_empty());
- foreach_list_const(node, &declared_variables) {
- ir_variable *var = (ir_variable *)node;
+ /* 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");
+ }
- struct gl_uniform_buffer_variable *ubo_var =
- &ubo->Uniforms[ubo->NumUniforms++];
+ /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec
+ * says:
+ *
+ * "If an instance name (instance-name) is used, then it puts all the
+ * members inside a scope within its own name space, accessed with the
+ * field selector ( . ) operator (analogously to structures)."
+ */
+ if (this->instance_name) {
+ ir_variable *var;
- var->uniform_block = ubo - state->uniform_blocks;
+ 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");
- ubo_var->Name = ralloc_strdup(state->uniform_blocks, var->name);
- ubo_var->Type = var->type;
- ubo_var->Buffer = ubo - state->uniform_blocks;
- ubo_var->Offset = 0; /* Assigned at link time. */
+ }
- if (var->type->is_matrix() ||
- (var->type->is_array() && var->type->fields.array->is_matrix())) {
- ubo_var->RowMajor = block_row_major;
- if (decl_list->type->qualifier.flags.q.row_major)
- ubo_var->RowMajor = true;
- else if (decl_list->type->qualifier.flags.q.column_major)
- ubo_var->RowMajor = false;
- }
+ const glsl_type *block_array_type =
+ process_array_type(&loc, block_type, this->array_size, state);
- /* From the GL_ARB_uniform_buffer_object spec:
- *
- * "Sampler types are not allowed inside of uniform
- * blocks. All other types, arrays, and structures
- * allowed for uniforms are allowed within a uniform
- * block."
- */
- if (var->type->contains_sampler()) {
- YYLTYPE loc = decl_list->get_location();
- _mesa_glsl_error(&loc, state,
- "Uniform in non-default uniform block contains sampler\n");
- }
+ var = new(state) ir_variable(block_array_type,
+ this->instance_name,
+ var_mode);
+ } else {
+ var = new(state) ir_variable(block_type,
+ this->instance_name,
+ var_mode);
}
- instructions->append_list(&declared_variables);
+ 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->is_array);
+
+ for (unsigned i = 0; i < num_variables; i++) {
+ ir_variable *var =
+ new(state) ir_variable(fields[i].type,
+ ralloc_strdup(state, fields[i].name),
+ var_mode);
+ var->interface_type = block_type;
+
+ /* Propagate the "binding" keyword into this UBO's fields;
+ * the UBO declaration itself doesn't get an ir_variable unless it
+ * has an instance name. This is ugly.
+ */
+ var->explicit_binding = this->layout.flags.q.explicit_binding;
+ var->binding = this->layout.binding;
+
+ state->symbols->add_variable(var);
+ instructions->push_tail(var);
+ }
+ }
+
+ 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)
gl_FragData_assigned = true;
else if (strncmp(var->name, "gl_", 3) != 0) {
if (state->target == fragment_shader &&
- (var->mode == ir_var_out || var->mode == ir_var_inout)) {
+ var->mode == ir_var_shader_out) {
user_defined_fs_output_assigned = true;
user_defined_fs_output = var;
}
*/
if (gl_FragColor_assigned && gl_FragData_assigned) {
_mesa_glsl_error(&loc, state, "fragment shader writes to both "
- "`gl_FragColor' and `gl_FragData'\n");
+ "`gl_FragColor' and `gl_FragData'");
} else if (gl_FragColor_assigned && user_defined_fs_output_assigned) {
_mesa_glsl_error(&loc, state, "fragment shader writes to both "
- "`gl_FragColor' and `%s'\n",
+ "`gl_FragColor' and `%s'",
user_defined_fs_output->name);
} else if (gl_FragData_assigned && user_defined_fs_output_assigned) {
_mesa_glsl_error(&loc, state, "fragment shader writes to both "
- "`gl_FragData' and `%s'\n",
+ "`gl_FragData' and `%s'",
user_defined_fs_output->name);
}
}