ast_operators op,
struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
{
- if (!state->check_bitwise_operations_allowed(loc)) {
- return glsl_type::error_type;
- }
-
- /* From page 50 (page 56 of PDF) of GLSL 1.30 spec:
- *
- * "The bitwise operators and (&), exclusive-or (^), and inclusive-or
- * (|). The operands must be of type signed or unsigned integers or
- * integer vectors."
- */
- if (!type_a->is_integer()) {
- _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer",
- ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
- if (!type_b->is_integer()) {
- _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer",
+ if (!state->check_bitwise_operations_allowed(loc)) {
+ return glsl_type::error_type;
+ }
+
+ /* From page 50 (page 56 of PDF) of GLSL 1.30 spec:
+ *
+ * "The bitwise operators and (&), exclusive-or (^), and inclusive-or
+ * (|). The operands must be of type signed or unsigned integers or
+ * integer vectors."
+ */
+ if (!type_a->is_integer()) {
+ _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer",
ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "The fundamental types of the operands (signed or unsigned) must
- * match,"
- */
- if (type_a->base_type != type_b->base_type) {
- _mesa_glsl_error(loc, state, "operands of `%s' must have the same "
- "base type", ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "The operands cannot be vectors of differing size." */
- if (type_a->is_vector() &&
- type_b->is_vector() &&
- type_a->vector_elements != type_b->vector_elements) {
- _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of "
- "different sizes", ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "If one operand is a scalar and the other a vector, the scalar is
- * applied component-wise to the vector, resulting in the same type as
- * the vector. The fundamental types of the operands [...] will be the
- * resulting fundamental type."
- */
- if (type_a->is_scalar())
- return type_b;
- else
- return type_a;
+ return glsl_type::error_type;
+ }
+ if (!type_b->is_integer()) {
+ _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer",
+ ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "The fundamental types of the operands (signed or unsigned) must
+ * match,"
+ */
+ if (type_a->base_type != type_b->base_type) {
+ _mesa_glsl_error(loc, state, "operands of `%s' must have the same "
+ "base type", ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "The operands cannot be vectors of differing size." */
+ if (type_a->is_vector() &&
+ type_b->is_vector() &&
+ type_a->vector_elements != type_b->vector_elements) {
+ _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of "
+ "different sizes", ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "If one operand is a scalar and the other a vector, the scalar is
+ * applied component-wise to the vector, resulting in the same type as
+ * the vector. The fundamental types of the operands [...] will be the
+ * resulting fundamental type."
+ */
+ if (type_a->is_scalar())
+ return type_b;
+ else
+ return type_a;
}
static const struct glsl_type *
-modulus_result_type(const struct glsl_type *type_a,
- const struct glsl_type *type_b,
+modulus_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
{
+ const glsl_type *type_a = value_a->type;
+ const glsl_type *type_b = value_b->type;
+
if (!state->check_version(130, 300, loc, "operator '%%' is reserved")) {
return glsl_type::error_type;
}
- /* From GLSL 1.50 spec, page 56:
+ /* Section 5.9 (Expressions) of the GLSL 4.00 specification says:
+ *
* "The operator modulus (%) operates on signed or unsigned integers or
- * integer vectors. The operand types must both be signed or both be
- * unsigned."
+ * integer vectors."
*/
if (!type_a->is_integer()) {
_mesa_glsl_error(loc, state, "LHS 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) {
+
+ /* "If the fundamental types in the operands do not match, then the
+ * conversions from section 4.1.10 "Implicit Conversions" are applied
+ * to create matching types."
+ *
+ * Note that GLSL 4.00 (and GL_ARB_gpu_shader5) introduced implicit
+ * int -> uint conversion rules. Prior to that, there were no implicit
+ * conversions. So it's harmless to apply them universally - no implicit
+ * conversions will exist. If the types don't match, we'll receive false,
+ * and raise an error, satisfying the GLSL 1.50 spec, page 56:
+ *
+ * "The operand types must both be signed or unsigned."
+ */
+ if (!apply_implicit_conversion(type_a, value_b, state) &&
+ !apply_implicit_conversion(type_b, value_a, state)) {
_mesa_glsl_error(loc, state,
- "operands of %% must have the same base type");
+ "could not implicitly convert operands to "
+ "modulus (%%) operator");
return glsl_type::error_type;
}
+ type_a = value_a->type;
+ type_b = value_b->type;
/* "The operands cannot be vectors of differing size. If one operand is
* a scalar and the other vector, then the scalar is applied component-
* Note: Whole-array assignments are not permitted in GLSL 1.10, but this
* is handled by ir_dereference::is_lvalue.
*/
- if (lhs->type->is_unsized_array() && rhs->type->is_array()
- && (lhs->type->fields.array == rhs->type->fields.array)) {
+ const glsl_type *lhs_t = lhs->type;
+ const glsl_type *rhs_t = rhs->type;
+ bool unsized_array = false;
+ while(lhs_t->is_array()) {
+ if (rhs_t == lhs_t)
+ break; /* the rest of the inner arrays match so break out early */
+ if (!rhs_t->is_array()) {
+ unsized_array = false;
+ break; /* number of dimensions mismatch */
+ }
+ if (lhs_t->length == rhs_t->length) {
+ lhs_t = lhs_t->fields.array;
+ rhs_t = rhs_t->fields.array;
+ continue;
+ } else if (lhs_t->is_unsized_array()) {
+ unsized_array = true;
+ } else {
+ unsized_array = false;
+ break; /* sized array mismatch */
+ }
+ lhs_t = lhs_t->fields.array;
+ rhs_t = rhs_t->fields.array;
+ }
+ if (unsized_array) {
if (is_initializer) {
return rhs;
} else {
{
void *ctx = state;
bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
- ir_rvalue *extract_channel = NULL;
-
- /* 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 lhs_expr = lhs->as_expression();
-
- if (unlikely(lhs_expr->operation == ir_binop_vector_extract)) {
- ir_rvalue *new_rhs =
- validate_assignment(state, lhs_loc, lhs,
- rhs, is_initializer);
-
- if (new_rhs == NULL) {
- return lhs;
- } else {
- /* This converts:
- * - LHS: (expression float vector_extract <vec> <channel>)
- * - RHS: <scalar>
- * into:
- * - LHS: <vec>
- * - RHS: (expression vec2 vector_insert <vec> <channel> <scalar>)
- *
- * The LHS type is now a vector instead of a scalar. Since GLSL
- * allows assignments to be used as rvalues, we need to re-extract
- * the channel from assignment_temp when returning the rvalue.
- */
- extract_channel = lhs_expr->operands[1];
- rhs = new(ctx) ir_expression(ir_triop_vector_insert,
- lhs_expr->operands[0]->type,
- lhs_expr->operands[0],
- new_rhs,
- extract_channel);
- lhs = lhs_expr->operands[0]->clone(ctx, NULL);
- }
- }
- }
ir_variable *lhs_var = lhs->variable_referenced();
if (lhs_var)
}
ir_rvalue *rvalue = new(ctx) ir_dereference_variable(var);
- if (extract_channel) {
- rvalue = new(ctx) ir_expression(ir_binop_vector_extract,
- rvalue,
- extract_channel->clone(ctx, NULL));
- }
-
*out_rvalue = rvalue;
} else {
if (!error_emitted)
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
- type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+ type = modulus_result_type(op[0], op[1], state, &loc);
assert(operations[this->oper] == ir_binop_mod);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
- type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+ type = modulus_result_type(op[0], op[1], state, &loc);
assert(operations[this->oper] == ir_binop_mod);
break;
}
+ case ast_unsized_array_dim:
+ assert(!"ast_unsized_array_dim: Should never get here.");
+ break;
+
case ast_function_call:
/* Should *NEVER* get here. ast_function_call should always be handled
* by ast_function_expression::hir.
case ast_function_call:
unreachable("should be handled by ast_function_expression::hir");
+
+ case ast_unsized_array_dim:
+ unreachable("ast_unsized_array_dim: Should never get here.");
}
return false;
exec_list dummy_instructions;
ast_node *array_size = exec_node_data(ast_node, node, link);
+
+ /**
+ * Dimensions other than the outermost dimension can by unsized if they
+ * are immediately sized by a constructor or initializer.
+ */
+ if (((ast_expression*)array_size)->oper == ast_unsized_array_dim)
+ return 0;
+
ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
YYLTYPE loc = array_size->get_location();
}
ir_constant *const size = ir->constant_expression_value();
- if (size == NULL) {
+ if (size == NULL || array_size->has_sequence_subexpression()) {
_mesa_glsl_error(& loc, state, "array size must be a "
"constant valued expression");
return 0;
*
* "Only one-dimensional arrays may be declared."
*/
- if (!state->ARB_arrays_of_arrays_enable) {
- _mesa_glsl_error(loc, state,
- "invalid array of `%s'"
- "GL_ARB_arrays_of_arrays "
- "required for defining arrays of arrays",
- base->name);
- return glsl_type::error_type;
- }
-
- if (base->length == 0) {
- _mesa_glsl_error(loc, state,
- "only the outermost array dimension can "
- "be unsized",
- base->name);
+ if (!state->check_arrays_of_arrays_allowed(loc)) {
return glsl_type::error_type;
}
}
unsigned array_size = process_array_size(node, state);
array_type = glsl_type::get_array_instance(array_type, array_size);
}
-
- if (array_specifier->is_unsized_array)
- array_type = glsl_type::get_array_instance(array_type, 0);
}
return array_type;
}
+static bool
+precision_qualifier_allowed(const glsl_type *type)
+{
+ /* Precision qualifiers apply to floating point, integer and opaque
+ * types.
+ *
+ * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
+ * "Any floating point or any integer declaration can have the type
+ * preceded by one of these precision qualifiers [...] Literal
+ * constants do not have precision qualifiers. Neither do Boolean
+ * variables.
+ *
+ * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30
+ * spec also says:
+ *
+ * "Precision qualifiers are added for code portability with OpenGL
+ * ES, not for functionality. They have the same syntax as in OpenGL
+ * ES."
+ *
+ * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says:
+ *
+ * "uniform lowp sampler2D sampler;
+ * highp vec2 coord;
+ * ...
+ * lowp vec4 col = texture2D (sampler, coord);
+ * // texture2D returns lowp"
+ *
+ * From this, we infer that GLSL 1.30 (and later) should allow precision
+ * qualifiers on sampler types just like float and integer types.
+ */
+ return (type->is_float()
+ || type->is_integer()
+ || type->contains_opaque())
+ && !type->without_array()->is_record();
+}
const glsl_type *
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
+/**
+ * From the OpenGL ES 3.0 spec, 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, (...) If type is float,
+ * the directive applies to non-precision-qualified floating point type
+ * (scalar, vector, and matrix) declarations. If type is int, the directive
+ * applies to all non-precision-qualified integer type (scalar, vector, signed,
+ * and unsigned) declarations."
+ *
+ * We use the symbol table to keep the values of the default precisions for
+ * each 'type' in each scope and we use the 'type' string from the precision
+ * statement as key in the symbol table. When we want to retrieve the default
+ * precision associated with a given glsl_type we need to know the type string
+ * associated with it. This is what this function returns.
+ */
+static const char *
+get_type_name_for_precision_qualifier(const glsl_type *type)
{
- const struct glsl_type *type = this->specifier->glsl_type(name, state);
-
- if (type == NULL)
- return NULL;
+ switch (type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ return "float";
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ return "int";
+ case GLSL_TYPE_ATOMIC_UINT:
+ return "atomic_uint";
+ case GLSL_TYPE_IMAGE:
+ /* fallthrough */
+ case GLSL_TYPE_SAMPLER: {
+ const unsigned type_idx =
+ type->sampler_array + 2 * type->sampler_shadow;
+ const unsigned offset = type->base_type == GLSL_TYPE_SAMPLER ? 0 : 4;
+ assert(type_idx < 4);
+ switch (type->sampler_type) {
+ case GLSL_TYPE_FLOAT:
+ switch (type->sampler_dimensionality) {
+ case GLSL_SAMPLER_DIM_1D: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "sampler1D", "sampler1DArray",
+ "sampler1DShadow", "sampler1DArrayShadow"
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_2D: {
+ static const char *const names[8] = {
+ "sampler2D", "sampler2DArray",
+ "sampler2DShadow", "sampler2DArrayShadow",
+ "image2D", "image2DArray", NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_3D: {
+ static const char *const names[8] = {
+ "sampler3D", NULL, NULL, NULL,
+ "image3D", NULL, NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_CUBE: {
+ static const char *const names[8] = {
+ "samplerCube", "samplerCubeArray",
+ "samplerCubeShadow", "samplerCubeArrayShadow",
+ "imageCube", NULL, NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_MS: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "sampler2DMS", "sampler2DMSArray", NULL, NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_RECT: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "samplerRect", NULL, "samplerRectShadow", NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_BUF: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "samplerBuffer", NULL, NULL, NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_EXTERNAL: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "samplerExternalOES", NULL, NULL, NULL
+ };
+ return names[type_idx];
+ }
+ default:
+ unreachable("Unsupported sampler/image dimensionality");
+ } /* sampler/image float dimensionality */
+ break;
+ case GLSL_TYPE_INT:
+ switch (type->sampler_dimensionality) {
+ case GLSL_SAMPLER_DIM_1D: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "isampler1D", "isampler1DArray", NULL, NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_2D: {
+ static const char *const names[8] = {
+ "isampler2D", "isampler2DArray", NULL, NULL,
+ "iimage2D", "iimage2DArray", NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_3D: {
+ static const char *const names[8] = {
+ "isampler3D", NULL, NULL, NULL,
+ "iimage3D", NULL, NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_CUBE: {
+ static const char *const names[8] = {
+ "isamplerCube", "isamplerCubeArray", NULL, NULL,
+ "iimageCube", NULL, NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_MS: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "isampler2DMS", "isampler2DMSArray", NULL, NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_RECT: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "isamplerRect", NULL, "isamplerRectShadow", NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_BUF: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "isamplerBuffer", NULL, NULL, NULL
+ };
+ return names[type_idx];
+ }
+ default:
+ unreachable("Unsupported isampler/iimage dimensionality");
+ } /* sampler/image int dimensionality */
+ break;
+ case GLSL_TYPE_UINT:
+ switch (type->sampler_dimensionality) {
+ case GLSL_SAMPLER_DIM_1D: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "usampler1D", "usampler1DArray", NULL, NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_2D: {
+ static const char *const names[8] = {
+ "usampler2D", "usampler2DArray", NULL, NULL,
+ "uimage2D", "uimage2DArray", NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_3D: {
+ static const char *const names[8] = {
+ "usampler3D", NULL, NULL, NULL,
+ "uimage3D", NULL, NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_CUBE: {
+ static const char *const names[8] = {
+ "usamplerCube", "usamplerCubeArray", NULL, NULL,
+ "uimageCube", NULL, NULL, NULL
+ };
+ return names[offset + type_idx];
+ }
+ case GLSL_SAMPLER_DIM_MS: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "usampler2DMS", "usampler2DMSArray", NULL, NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_RECT: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "usamplerRect", NULL, "usamplerRectShadow", NULL
+ };
+ return names[type_idx];
+ }
+ case GLSL_SAMPLER_DIM_BUF: {
+ assert(type->base_type == GLSL_TYPE_SAMPLER);
+ static const char *const names[4] = {
+ "usamplerBuffer", NULL, NULL, NULL
+ };
+ return names[type_idx];
+ }
+ default:
+ unreachable("Unsupported usampler/uimage dimensionality");
+ } /* sampler/image uint dimensionality */
+ break;
+ default:
+ unreachable("Unsupported sampler/image type");
+ } /* sampler/image type */
+ break;
+ } /* GLSL_TYPE_SAMPLER/GLSL_TYPE_IMAGE */
+ break;
+ default:
+ unreachable("Unsupported type");
+ } /* base type */
+}
- if (type->base_type == GLSL_TYPE_FLOAT
- && state->es_shader
- && state->stage == MESA_SHADER_FRAGMENT
- && 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);
+static unsigned
+select_gles_precision(unsigned qual_precision,
+ const glsl_type *type,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ /* Precision qualifiers do not have any meaning in Desktop GLSL.
+ * In GLES we take the precision from the type qualifier if present,
+ * otherwise, if the type of the variable allows precision qualifiers at
+ * all, we look for the default precision qualifier for that type in the
+ * current scope.
+ */
+ assert(state->es_shader);
+
+ unsigned precision = GLSL_PRECISION_NONE;
+ if (qual_precision) {
+ precision = qual_precision;
+ } else if (precision_qualifier_allowed(type)) {
+ const char *type_name =
+ get_type_name_for_precision_qualifier(type->without_array());
+ assert(type_name != NULL);
+
+ precision =
+ state->symbols->get_default_precision_qualifier(type_name);
+ if (precision == ast_precision_none) {
+ _mesa_glsl_error(loc, state,
+ "No precision specified in this scope for type `%s'",
+ type->name);
+ }
}
+ return precision;
+}
- return type;
+const glsl_type *
+ast_fully_specified_type::glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state) const
+{
+ return this->specifier->glsl_type(name, state);
}
/**
const struct gl_context *const ctx = state->ctx;
unsigned max_loc = qual->location + var->type->uniform_locations() - 1;
- /* ARB_explicit_uniform_location specification states:
- *
- * "The explicitly defined locations and the generated locations
- * must be in the range of 0 to MAX_UNIFORM_LOCATIONS minus one."
- *
- * "Valid locations for default-block uniform variable locations
- * are in the range of 0 to the implementation-defined maximum
- * number of uniform locations."
- */
- if (qual->location < 0) {
- _mesa_glsl_error(loc, state,
- "explicit location < 0 for uniform %s", var->name);
- return;
- }
-
if (max_loc >= ctx->Const.MaxUserAssignableUniformLocations) {
_mesa_glsl_error(loc, state, "location(s) consumed by uniform %s "
">= MAX_UNIFORM_LOCATIONS (%u)", var->name,
} else {
var->data.explicit_location = true;
- /* This bit of silliness is needed because invalid explicit locations
- * are supposed to be flagged during linking. Small negative values
- * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias
- * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS).
- * The linker needs to be able to differentiate these cases. This
- * ensures that negative values stay negative.
- */
- if (qual->location >= 0) {
- switch (state->stage) {
- case MESA_SHADER_VERTEX:
- var->data.location = (var->data.mode == ir_var_shader_in)
- ? (qual->location + VERT_ATTRIB_GENERIC0)
- : (qual->location + VARYING_SLOT_VAR0);
- break;
+ switch (state->stage) {
+ case MESA_SHADER_VERTEX:
+ var->data.location = (var->data.mode == ir_var_shader_in)
+ ? (qual->location + VERT_ATTRIB_GENERIC0)
+ : (qual->location + VARYING_SLOT_VAR0);
+ break;
- case MESA_SHADER_TESS_CTRL:
- case MESA_SHADER_TESS_EVAL:
- case MESA_SHADER_GEOMETRY:
- if (var->data.patch)
- var->data.location = qual->location + VARYING_SLOT_PATCH0;
- else
- var->data.location = qual->location + VARYING_SLOT_VAR0;
- break;
+ case MESA_SHADER_TESS_CTRL:
+ case MESA_SHADER_TESS_EVAL:
+ case MESA_SHADER_GEOMETRY:
+ if (var->data.patch)
+ var->data.location = qual->location + VARYING_SLOT_PATCH0;
+ else
+ var->data.location = qual->location + VARYING_SLOT_VAR0;
+ break;
- case MESA_SHADER_FRAGMENT:
- var->data.location = (var->data.mode == ir_var_shader_out)
- ? (qual->location + FRAG_RESULT_DATA0)
- : (qual->location + VARYING_SLOT_VAR0);
- break;
- case MESA_SHADER_COMPUTE:
- assert(!"Unexpected shader type");
- break;
- }
- } else {
- var->data.location = qual->location;
+ case MESA_SHADER_FRAGMENT:
+ var->data.location = (var->data.mode == ir_var_shader_out)
+ ? (qual->location + FRAG_RESULT_DATA0)
+ : (qual->location + VARYING_SLOT_VAR0);
+ break;
+ case MESA_SHADER_COMPUTE:
+ assert(!"Unexpected shader type");
+ break;
}
if (qual->flags.q.explicit_index) {
return false;
}
+static inline void
+validate_array_dimensions(const glsl_type *t,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc) {
+ if (t->is_array()) {
+ t = t->fields.array;
+ while (t->is_array()) {
+ if (t->is_unsized_array()) {
+ _mesa_glsl_error(loc, state,
+ "only the outermost array dimension can "
+ "be unsized",
+ t->name);
+ break;
+ }
+ t = t->fields.array;
+ }
+ }
+}
+
static void
-apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
- ir_variable *var,
- struct _mesa_glsl_parse_state *state,
- YYLTYPE *loc,
- bool is_parameter)
+apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
{
- STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i));
+ if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) {
- if (qual->flags.q.invariant) {
- if (var->data.used) {
+ /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says:
+ *
+ * "Within any shader, the first redeclarations of gl_FragCoord
+ * must appear before any use of gl_FragCoord."
+ *
+ * Generate a compiler error if above condition is not met by the
+ * fragment shader.
+ */
+ ir_variable *earlier = state->symbols->get_variable("gl_FragCoord");
+ if (earlier != NULL &&
+ earlier->data.used &&
+ !state->fs_redeclares_gl_fragcoord) {
_mesa_glsl_error(loc, state,
- "variable `%s' may not be redeclared "
- "`invariant' after being used",
- var->name);
- } else {
- var->data.invariant = 1;
+ "gl_FragCoord used before its first redeclaration "
+ "in fragment shader");
+ }
+
+ /* Make sure all gl_FragCoord redeclarations specify the same layout
+ * qualifiers.
+ */
+ if (is_conflicting_fragcoord_redeclaration(state, qual)) {
+ const char *const qual_string =
+ get_layout_qualifier_string(qual->flags.q.origin_upper_left,
+ qual->flags.q.pixel_center_integer);
+
+ const char *const state_string =
+ get_layout_qualifier_string(state->fs_origin_upper_left,
+ state->fs_pixel_center_integer);
+
+ _mesa_glsl_error(loc, state,
+ "gl_FragCoord redeclared with different layout "
+ "qualifiers (%s) and (%s) ",
+ state_string,
+ qual_string);
+ }
+ state->fs_origin_upper_left = qual->flags.q.origin_upper_left;
+ state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer;
+ state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers =
+ !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer;
+ state->fs_redeclares_gl_fragcoord =
+ state->fs_origin_upper_left ||
+ state->fs_pixel_center_integer ||
+ state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
+ }
+
+ var->data.pixel_center_integer = qual->flags.q.pixel_center_integer;
+ var->data.origin_upper_left = qual->flags.q.origin_upper_left;
+ if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer)
+ && (strcmp(var->name, "gl_FragCoord") != 0)) {
+ const char *const qual_string = (qual->flags.q.origin_upper_left)
+ ? "origin_upper_left" : "pixel_center_integer";
+
+ _mesa_glsl_error(loc, state,
+ "layout qualifier `%s' can only be applied to "
+ "fragment shader input `gl_FragCoord'",
+ qual_string);
+ }
+
+ if (qual->flags.q.explicit_location) {
+ validate_explicit_location(qual, var, state, loc);
+ } else if (qual->flags.q.explicit_index) {
+ _mesa_glsl_error(loc, state, "explicit index requires explicit location");
+ }
+
+ if (qual->flags.q.explicit_binding &&
+ validate_binding_qualifier(state, loc, var->type, qual)) {
+ var->data.explicit_binding = true;
+ var->data.binding = qual->binding;
+ }
+
+ if (state->stage == MESA_SHADER_GEOMETRY &&
+ qual->flags.q.out && qual->flags.q.stream) {
+ var->data.stream = qual->stream;
+ }
+
+ if (var->type->contains_atomic()) {
+ if (var->data.mode == ir_var_uniform) {
+ if (var->data.explicit_binding) {
+ unsigned *offset =
+ &state->atomic_counter_offsets[var->data.binding];
+
+ if (*offset % ATOMIC_COUNTER_SIZE)
+ _mesa_glsl_error(loc, state,
+ "misaligned atomic counter offset");
+
+ var->data.atomic.offset = *offset;
+ *offset += var->type->atomic_size();
+
+ } else {
+ _mesa_glsl_error(loc, state,
+ "atomic counters require explicit binding point");
+ }
+ } else if (var->data.mode != ir_var_function_in) {
+ _mesa_glsl_error(loc, state, "atomic counters may only be declared as "
+ "function parameters or uniform-qualified "
+ "global variables");
+ }
+ }
+
+ /* Is the 'layout' keyword used with parameters that allow relaxed checking.
+ * Many implementations of GL_ARB_fragment_coord_conventions_enable and some
+ * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable
+ * allowed the layout qualifier to be used with 'varying' and 'attribute'.
+ * These extensions and all following extensions that add the 'layout'
+ * keyword have been modified to require the use of 'in' or 'out'.
+ *
+ * The following extension do not allow the deprecated keywords:
+ *
+ * GL_AMD_conservative_depth
+ * GL_ARB_conservative_depth
+ * GL_ARB_gpu_shader5
+ * GL_ARB_separate_shader_objects
+ * GL_ARB_tessellation_shader
+ * GL_ARB_transform_feedback3
+ * GL_ARB_uniform_buffer_object
+ *
+ * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5
+ * allow layout with the deprecated keywords.
+ */
+ const bool relaxed_layout_qualifier_checking =
+ state->ARB_fragment_coord_conventions_enable;
+
+ const bool uses_deprecated_qualifier = qual->flags.q.attribute
+ || qual->flags.q.varying;
+ if (qual->has_layout() && uses_deprecated_qualifier) {
+ if (relaxed_layout_qualifier_checking) {
+ _mesa_glsl_warning(loc, state,
+ "`layout' qualifier may not be used with "
+ "`attribute' or `varying'");
+ } else {
+ _mesa_glsl_error(loc, state,
+ "`layout' qualifier may not be used with "
+ "`attribute' or `varying'");
+ }
+ }
+
+ /* Layout qualifiers for gl_FragDepth, which are enabled by extension
+ * AMD_conservative_depth.
+ */
+ int depth_layout_count = qual->flags.q.depth_any
+ + qual->flags.q.depth_greater
+ + qual->flags.q.depth_less
+ + qual->flags.q.depth_unchanged;
+ if (depth_layout_count > 0
+ && !state->AMD_conservative_depth_enable
+ && !state->ARB_conservative_depth_enable) {
+ _mesa_glsl_error(loc, state,
+ "extension GL_AMD_conservative_depth or "
+ "GL_ARB_conservative_depth must be enabled "
+ "to use depth layout qualifiers");
+ } else if (depth_layout_count > 0
+ && strcmp(var->name, "gl_FragDepth") != 0) {
+ _mesa_glsl_error(loc, state,
+ "depth layout qualifiers can be applied only to "
+ "gl_FragDepth");
+ } else if (depth_layout_count > 1
+ && strcmp(var->name, "gl_FragDepth") == 0) {
+ _mesa_glsl_error(loc, state,
+ "at most one depth layout qualifier can be applied to "
+ "gl_FragDepth");
+ }
+ if (qual->flags.q.depth_any)
+ var->data.depth_layout = ir_depth_layout_any;
+ else if (qual->flags.q.depth_greater)
+ var->data.depth_layout = ir_depth_layout_greater;
+ else if (qual->flags.q.depth_less)
+ var->data.depth_layout = ir_depth_layout_less;
+ else if (qual->flags.q.depth_unchanged)
+ var->data.depth_layout = ir_depth_layout_unchanged;
+ else
+ var->data.depth_layout = ir_depth_layout_none;
+
+ if (qual->flags.q.std140 ||
+ qual->flags.q.std430 ||
+ qual->flags.q.packed ||
+ qual->flags.q.shared) {
+ _mesa_glsl_error(loc, state,
+ "uniform and shader storage block layout qualifiers "
+ "std140, std430, packed, and shared can only be "
+ "applied to uniform or shader storage blocks, not "
+ "members");
+ }
+
+ if (qual->flags.q.row_major || qual->flags.q.column_major) {
+ validate_matrix_layout_for_type(state, loc, var->type, var);
+ }
+
+ /* From section 4.4.1.3 of the GLSL 4.50 specification (Fragment Shader
+ * Inputs):
+ *
+ * "Fragment shaders also allow the following layout qualifier on in only
+ * (not with variable declarations)
+ * layout-qualifier-id
+ * early_fragment_tests
+ * [...]"
+ */
+ if (qual->flags.q.early_fragment_tests) {
+ _mesa_glsl_error(loc, state, "early_fragment_tests layout qualifier only "
+ "valid in fragment shader input layout declaration.");
+ }
+}
+
+static void
+apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ bool is_parameter)
+{
+ STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i));
+
+ if (qual->flags.q.invariant) {
+ if (var->data.used) {
+ _mesa_glsl_error(loc, state,
+ "variable `%s' may not be redeclared "
+ "`invariant' after being used",
+ var->name);
+ } else {
+ var->data.invariant = 1;
}
}
if (qual->flags.q.sample)
var->data.sample = 1;
- if (state->stage == MESA_SHADER_GEOMETRY &&
- qual->flags.q.out && qual->flags.q.stream) {
- var->data.stream = qual->stream;
+ /* Precision qualifiers do not hold any meaning in Desktop GLSL */
+ if (state->es_shader) {
+ var->data.precision =
+ select_gles_precision(qual->precision, var->type, state, loc);
}
if (qual->flags.q.patch)
var->data.mode = ir_var_uniform;
else if (qual->flags.q.buffer)
var->data.mode = ir_var_shader_storage;
+ else if (qual->flags.q.shared_storage)
+ var->data.mode = ir_var_shader_shared;
if (!is_parameter && is_varying_var(var, state->stage)) {
/* User-defined ins/outs are not permitted in compute shaders. */
break;
default:
_mesa_glsl_error(loc, state, "illegal type for a varying variable");
- break;
- }
- }
-
- if (state->all_invariant && (state->current_function == NULL)) {
- switch (state->stage) {
- case MESA_SHADER_VERTEX:
- if (var->data.mode == ir_var_shader_out)
- var->data.invariant = true;
- break;
- case MESA_SHADER_TESS_CTRL:
- case MESA_SHADER_TESS_EVAL:
- case MESA_SHADER_GEOMETRY:
- if ((var->data.mode == ir_var_shader_in)
- || (var->data.mode == ir_var_shader_out))
- var->data.invariant = true;
- break;
- case MESA_SHADER_FRAGMENT:
- if (var->data.mode == ir_var_shader_in)
- var->data.invariant = true;
- break;
- case MESA_SHADER_COMPUTE:
- /* Invariance isn't meaningful in compute shaders. */
- break;
- }
- }
-
- var->data.interpolation =
- interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode,
- state, loc);
-
- var->data.pixel_center_integer = qual->flags.q.pixel_center_integer;
- var->data.origin_upper_left = qual->flags.q.origin_upper_left;
- if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer)
- && (strcmp(var->name, "gl_FragCoord") != 0)) {
- const char *const qual_string = (qual->flags.q.origin_upper_left)
- ? "origin_upper_left" : "pixel_center_integer";
-
- _mesa_glsl_error(loc, state,
- "layout qualifier `%s' can only be applied to "
- "fragment shader input `gl_FragCoord'",
- qual_string);
- }
-
- if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) {
-
- /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says:
- *
- * "Within any shader, the first redeclarations of gl_FragCoord
- * must appear before any use of gl_FragCoord."
- *
- * Generate a compiler error if above condition is not met by the
- * fragment shader.
- */
- ir_variable *earlier = state->symbols->get_variable("gl_FragCoord");
- if (earlier != NULL &&
- earlier->data.used &&
- !state->fs_redeclares_gl_fragcoord) {
- _mesa_glsl_error(loc, state,
- "gl_FragCoord used before its first redeclaration "
- "in fragment shader");
- }
-
- /* Make sure all gl_FragCoord redeclarations specify the same layout
- * qualifiers.
- */
- if (is_conflicting_fragcoord_redeclaration(state, qual)) {
- const char *const qual_string =
- get_layout_qualifier_string(qual->flags.q.origin_upper_left,
- qual->flags.q.pixel_center_integer);
-
- const char *const state_string =
- get_layout_qualifier_string(state->fs_origin_upper_left,
- state->fs_pixel_center_integer);
-
- _mesa_glsl_error(loc, state,
- "gl_FragCoord redeclared with different layout "
- "qualifiers (%s) and (%s) ",
- state_string,
- qual_string);
- }
- state->fs_origin_upper_left = qual->flags.q.origin_upper_left;
- state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer;
- state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers =
- !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer;
- state->fs_redeclares_gl_fragcoord =
- state->fs_origin_upper_left ||
- state->fs_pixel_center_integer ||
- state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
- }
-
- if (qual->flags.q.explicit_location) {
- validate_explicit_location(qual, var, state, loc);
- } else if (qual->flags.q.explicit_index) {
- _mesa_glsl_error(loc, state, "explicit index requires explicit location");
- }
-
- if (qual->flags.q.explicit_binding &&
- validate_binding_qualifier(state, loc, var->type, qual)) {
- var->data.explicit_binding = true;
- var->data.binding = qual->binding;
- }
-
- if (var->type->contains_atomic()) {
- if (var->data.mode == ir_var_uniform) {
- if (var->data.explicit_binding) {
- unsigned *offset =
- &state->atomic_counter_offsets[var->data.binding];
-
- if (*offset % ATOMIC_COUNTER_SIZE)
- _mesa_glsl_error(loc, state,
- "misaligned atomic counter offset");
-
- var->data.atomic.offset = *offset;
- *offset += var->type->atomic_size();
-
- } else {
- _mesa_glsl_error(loc, state,
- "atomic counters require explicit binding point");
- }
- } else if (var->data.mode != ir_var_function_in) {
- _mesa_glsl_error(loc, state, "atomic counters may only be declared as "
- "function parameters or uniform-qualified "
- "global variables");
+ break;
+ }
+ }
+
+ if (state->all_invariant && (state->current_function == NULL)) {
+ switch (state->stage) {
+ case MESA_SHADER_VERTEX:
+ if (var->data.mode == ir_var_shader_out)
+ var->data.invariant = true;
+ break;
+ case MESA_SHADER_TESS_CTRL:
+ case MESA_SHADER_TESS_EVAL:
+ case MESA_SHADER_GEOMETRY:
+ if ((var->data.mode == ir_var_shader_in)
+ || (var->data.mode == ir_var_shader_out))
+ var->data.invariant = true;
+ break;
+ case MESA_SHADER_FRAGMENT:
+ if (var->data.mode == ir_var_shader_in)
+ var->data.invariant = true;
+ break;
+ case MESA_SHADER_COMPUTE:
+ /* Invariance isn't meaningful in compute shaders. */
+ break;
}
}
+ var->data.interpolation =
+ interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode,
+ state, loc);
+
/* Does the declaration use the deprecated 'attribute' or 'varying'
* keywords?
*/
"`out' or `varying' variables between shader stages");
}
-
- /* Is the 'layout' keyword used with parameters that allow relaxed checking.
- * Many implementations of GL_ARB_fragment_coord_conventions_enable and some
- * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable
- * allowed the layout qualifier to be used with 'varying' and 'attribute'.
- * These extensions and all following extensions that add the 'layout'
- * keyword have been modified to require the use of 'in' or 'out'.
- *
- * The following extension do not allow the deprecated keywords:
- *
- * GL_AMD_conservative_depth
- * GL_ARB_conservative_depth
- * GL_ARB_gpu_shader5
- * GL_ARB_separate_shader_objects
- * GL_ARB_tessellation_shader
- * GL_ARB_transform_feedback3
- * GL_ARB_uniform_buffer_object
- *
- * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5
- * allow layout with the deprecated keywords.
- */
- const bool relaxed_layout_qualifier_checking =
- state->ARB_fragment_coord_conventions_enable;
-
- if (qual->has_layout() && uses_deprecated_qualifier) {
- if (relaxed_layout_qualifier_checking) {
- _mesa_glsl_warning(loc, state,
- "`layout' qualifier may not be used with "
- "`attribute' or `varying'");
- } else {
- _mesa_glsl_error(loc, state,
- "`layout' qualifier may not be used with "
- "`attribute' or `varying'");
- }
- }
-
- /* Layout qualifiers for gl_FragDepth, which are enabled by extension
- * AMD_conservative_depth.
- */
- int depth_layout_count = qual->flags.q.depth_any
- + qual->flags.q.depth_greater
- + qual->flags.q.depth_less
- + qual->flags.q.depth_unchanged;
- if (depth_layout_count > 0
- && !state->AMD_conservative_depth_enable
- && !state->ARB_conservative_depth_enable) {
- _mesa_glsl_error(loc, state,
- "extension GL_AMD_conservative_depth or "
- "GL_ARB_conservative_depth must be enabled "
- "to use depth layout qualifiers");
- } else if (depth_layout_count > 0
- && strcmp(var->name, "gl_FragDepth") != 0) {
- _mesa_glsl_error(loc, state,
- "depth layout qualifiers can be applied only to "
- "gl_FragDepth");
- } else if (depth_layout_count > 1
- && strcmp(var->name, "gl_FragDepth") == 0) {
- _mesa_glsl_error(loc, state,
- "at most one depth layout qualifier can be applied to "
- "gl_FragDepth");
- }
- if (qual->flags.q.depth_any)
- var->data.depth_layout = ir_depth_layout_any;
- else if (qual->flags.q.depth_greater)
- var->data.depth_layout = ir_depth_layout_greater;
- else if (qual->flags.q.depth_less)
- var->data.depth_layout = ir_depth_layout_less;
- else if (qual->flags.q.depth_unchanged)
- var->data.depth_layout = ir_depth_layout_unchanged;
- else
- var->data.depth_layout = ir_depth_layout_none;
-
- if (qual->flags.q.std140 ||
- qual->flags.q.std430 ||
- qual->flags.q.packed ||
- qual->flags.q.shared) {
+ if (qual->flags.q.shared_storage && state->stage != MESA_SHADER_COMPUTE) {
_mesa_glsl_error(loc, state,
- "uniform and shader storage block layout qualifiers "
- "std140, std430, packed, and shared can only be "
- "applied to uniform or shader storage blocks, not "
- "members");
- }
-
- if (qual->flags.q.row_major || qual->flags.q.column_major) {
- validate_matrix_layout_for_type(state, loc, var->type, var);
+ "the shared storage qualifiers can only be used with "
+ "compute shaders");
}
apply_image_qualifier_to_variable(qual, var, state, loc);
-
- /* From section 4.4.1.3 of the GLSL 4.50 specification (Fragment Shader
- * Inputs):
- *
- * "Fragment shaders also allow the following layout qualifier on in only
- * (not with variable declarations)
- * layout-qualifier-id
- * early_fragment_tests
- * [...]"
- */
- if (qual->flags.q.early_fragment_tests) {
- _mesa_glsl_error(loc, state, "early_fragment_tests layout qualifier only "
- "valid in fragment shader input layout declaration.");
- }
}
/**
}
}
-static bool
-precision_qualifier_allowed(const glsl_type *type)
-{
- /* Precision qualifiers apply to floating point, integer and opaque
- * types.
- *
- * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
- * "Any floating point or any integer declaration can have the type
- * preceded by one of these precision qualifiers [...] Literal
- * constants do not have precision qualifiers. Neither do Boolean
- * variables.
- *
- * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30
- * spec also says:
- *
- * "Precision qualifiers are added for code portability with OpenGL
- * ES, not for functionality. They have the same syntax as in OpenGL
- * ES."
- *
- * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says:
- *
- * "uniform lowp sampler2D sampler;
- * highp vec2 coord;
- * ...
- * lowp vec4 col = texture2D (sampler, coord);
- * // texture2D returns lowp"
- *
- * From this, we infer that GLSL 1.30 (and later) should allow precision
- * qualifiers on sampler types just like float and integer types.
- */
- return type->is_float()
- || type->is_integer()
- || type->is_record()
- || type->contains_opaque();
-}
-
ir_rvalue *
ast_declarator_list::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
& loc, false);
+ apply_layout_qualifier_to_variable(&this->type->qualifier, var, state,
+ &loc);
if (this->type->qualifier.flags.q.invariant) {
if (!is_varying_var(var, state->stage)) {
result = process_initializer((earlier == NULL) ? var : earlier,
decl, this->type,
&initializer_instructions, state);
+ } else {
+ validate_array_dimensions(var_type, state, &loc);
}
/* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec:
return NULL;
}
- if (type->base_type == GLSL_TYPE_FLOAT
- && state->es_shader
- && state->stage == MESA_SHADER_FRAGMENT) {
+ if (state->es_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
* 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
+ * variables. So, we can track the state of the default precision
+ * qualifiers 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_auto);
-
- state->symbols->add_variable(junk);
+ state->symbols->add_default_precision_qualifier(this->type_name,
+ this->default_precision);
}
/* FINISHME: Translate precision statements into IR. */
* 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,
- enum glsl_matrix_layout matrix_layout,
- bool allow_reserved_names,
- ir_variable_mode var_mode,
- ast_type_qualifier *layout)
+ast_process_struct_or_iface_block_members(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state,
+ exec_list *declarations,
+ YYLTYPE &loc,
+ glsl_struct_field **fields_ret,
+ bool is_interface,
+ enum glsl_matrix_layout matrix_layout,
+ bool allow_reserved_names,
+ ir_variable_mode var_mode,
+ ast_type_qualifier *layout)
{
unsigned decl_count = 0;
- /* For blocks that accept memory qualifiers (i.e. shader storage), verify
- * that we don't have incompatible qualifiers
- */
- if (layout && layout->flags.q.read_only && layout->flags.q.write_only) {
- _mesa_glsl_error(&loc, state,
- "Interface block sets both readonly and writeonly");
- }
-
/* 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
const glsl_type *decl_type =
decl_list->type->glsl_type(& type_name, state);
- foreach_list_typed (ast_declaration, decl, link,
- &decl_list->declarations) {
- if (!allow_reserved_names)
- validate_identifier(decl->identifier, loc, state);
+ const struct ast_type_qualifier *const qual =
+ &decl_list->type->qualifier;
- /* From section 4.3.9 of the GLSL 4.40 spec:
- *
- * "[In interface blocks] opaque types are not allowed."
+ /* From section 4.3.9 of the GLSL 4.40 spec:
+ *
+ * "[In interface blocks] opaque types are not allowed."
+ *
+ * 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.
+ */
+ assert(decl_type);
+
+ if (is_interface && decl_type->contains_opaque()) {
+ YYLTYPE loc = decl_list->get_location();
+ _mesa_glsl_error(&loc, state,
+ "uniform/buffer in non-default interface block contains "
+ "opaque variable");
+ }
+
+ if (decl_type->contains_atomic()) {
+ /* From section 4.1.7.3 of the GLSL 4.40 spec:
*
- * 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.
+ * "Members of structures cannot be declared as atomic counter
+ * types."
*/
- assert(decl_type);
+ YYLTYPE loc = decl_list->get_location();
+ _mesa_glsl_error(&loc, state, "atomic counter in structure, "
+ "shader storage block or uniform block");
+ }
- if (is_interface && decl_type->contains_opaque()) {
- YYLTYPE loc = decl_list->get_location();
- _mesa_glsl_error(&loc, state,
- "uniform/buffer in non-default interface block contains "
- "opaque variable");
- }
+ if (decl_type->contains_image()) {
+ /* FINISHME: Same problem as with atomic counters.
+ * FINISHME: Request clarification from Khronos and add
+ * FINISHME: spec quotation here.
+ */
+ YYLTYPE loc = decl_list->get_location();
+ _mesa_glsl_error(&loc, state,
+ "image in structure, shader storage block or "
+ "uniform block");
+ }
- if (decl_type->contains_atomic()) {
- /* From section 4.1.7.3 of the GLSL 4.40 spec:
- *
- * "Members of structures cannot be declared as atomic counter
- * types."
- */
- YYLTYPE loc = decl_list->get_location();
- _mesa_glsl_error(&loc, state, "atomic counter in structure, "
- "shader storage block or uniform block");
- }
+ if (qual->flags.q.explicit_binding)
+ validate_binding_qualifier(state, &loc, decl_type, qual);
- if (decl_type->contains_image()) {
- /* FINISHME: Same problem as with atomic counters.
- * FINISHME: Request clarification from Khronos and add
- * FINISHME: spec quotation here.
- */
- YYLTYPE loc = decl_list->get_location();
- _mesa_glsl_error(&loc, state,
- "image in structure, shader storage block or "
- "uniform block");
- }
+ if (qual->flags.q.std140 ||
+ qual->flags.q.std430 ||
+ qual->flags.q.packed ||
+ qual->flags.q.shared) {
+ _mesa_glsl_error(&loc, state,
+ "uniform/shader storage block layout qualifiers "
+ "std140, std430, packed, and shared can only be "
+ "applied to uniform/shader storage blocks, not "
+ "members");
+ }
+
+ if (qual->flags.q.constant) {
+ YYLTYPE loc = decl_list->get_location();
+ _mesa_glsl_error(&loc, state,
+ "const storage qualifier cannot be applied "
+ "to struct or interface block members");
+ }
- const struct ast_type_qualifier *const qual =
- & decl_list->type->qualifier;
+ /* From Section 4.4.2.3 (Geometry Outputs) of the GLSL 4.50 spec:
+ *
+ * "A block member may be declared with a stream identifier, but
+ * the specified stream must match the stream associated with the
+ * containing block."
+ */
+ if (qual->flags.q.explicit_stream &&
+ qual->stream != layout->stream) {
+ _mesa_glsl_error(&loc, state, "stream layout qualifier on interface "
+ "block member does not match the interface block "
+ "(%d vs %d)", qual->stream, layout->stream);
+ }
- if (qual->flags.q.explicit_binding)
- validate_binding_qualifier(state, &loc, decl_type, qual);
+ if (qual->flags.q.uniform && qual->has_interpolation()) {
+ _mesa_glsl_error(&loc, state,
+ "interpolation qualifiers cannot be used "
+ "with uniform interface blocks");
+ }
- if (qual->flags.q.std140 ||
- qual->flags.q.std430 ||
- qual->flags.q.packed ||
- qual->flags.q.shared) {
- _mesa_glsl_error(&loc, state,
- "uniform/shader storage block layout qualifiers "
- "std140, std430, packed, and shared can only be "
- "applied to uniform/shader storage blocks, not "
- "members");
- }
+ if ((qual->flags.q.uniform || !is_interface) &&
+ qual->has_auxiliary_storage()) {
+ _mesa_glsl_error(&loc, state,
+ "auxiliary storage qualifiers cannot be used "
+ "in uniform blocks or structures.");
+ }
- if (qual->flags.q.constant) {
- YYLTYPE loc = decl_list->get_location();
+ if (qual->flags.q.row_major || qual->flags.q.column_major) {
+ if (!qual->flags.q.uniform && !qual->flags.q.buffer) {
_mesa_glsl_error(&loc, state,
- "const storage qualifier cannot be applied "
- "to struct or interface block members");
- }
+ "row_major and column_major can only be "
+ "applied to interface blocks");
+ } else
+ validate_matrix_layout_for_type(state, &loc, decl_type, NULL);
+ }
+
+ if (qual->flags.q.read_only && qual->flags.q.write_only) {
+ _mesa_glsl_error(&loc, state, "buffer variable can't be both "
+ "readonly and writeonly.");
+ }
+
+ foreach_list_typed (ast_declaration, decl, link,
+ &decl_list->declarations) {
+ if (!allow_reserved_names)
+ validate_identifier(decl->identifier, loc, state);
const struct glsl_type *field_type =
process_array_type(&loc, decl_type, decl->array_specifier, state);
+ validate_array_dimensions(field_type, state, &loc);
fields[i].type = field_type;
fields[i].name = decl->identifier;
fields[i].location = -1;
fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
fields[i].sample = qual->flags.q.sample ? 1 : 0;
fields[i].patch = qual->flags.q.patch ? 1 : 0;
-
- /* Only save explicitly defined streams in block's field */
- fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1;
-
- if (qual->flags.q.row_major || qual->flags.q.column_major) {
- if (!qual->flags.q.uniform && !qual->flags.q.buffer) {
- _mesa_glsl_error(&loc, state,
- "row_major and column_major can only be "
- "applied to interface blocks");
- } else
- validate_matrix_layout_for_type(state, &loc, field_type, NULL);
- }
-
- if (qual->flags.q.uniform && qual->has_interpolation()) {
- _mesa_glsl_error(&loc, state,
- "interpolation qualifiers cannot be used "
- "with uniform interface blocks");
- }
-
- if ((qual->flags.q.uniform || !is_interface) &&
- qual->has_auxiliary_storage()) {
- _mesa_glsl_error(&loc, state,
- "auxiliary storage qualifiers cannot be used "
- "in uniform blocks or structures.");
- }
+ fields[i].precision = qual->precision;
/* Propogate row- / column-major information down the fields of the
* structure or interface block. Structures need this data because
* be defined inside shader storage buffer objects
*/
if (layout && var_mode == ir_var_shader_storage) {
- if (qual->flags.q.read_only && qual->flags.q.write_only) {
- _mesa_glsl_error(&loc, state,
- "buffer variable `%s' can't be "
- "readonly and writeonly.", fields[i].name);
- }
-
/* For readonly and writeonly qualifiers the field definition,
* if set, overwrites the layout qualifier.
*/
glsl_struct_field *fields;
unsigned decl_count =
- ast_process_structure_or_interface_block(instructions,
- state,
- &this->declarations,
- loc,
- &fields,
- false,
- GLSL_MATRIX_LAYOUT_INHERITED,
- false /* allow_reserved_names */,
- ir_var_auto,
- NULL);
+ ast_process_struct_or_iface_block_members(instructions,
+ state,
+ &this->declarations,
+ loc,
+ &fields,
+ false,
+ GLSL_MATRIX_LAYOUT_INHERITED,
+ false /* allow_reserved_names */,
+ ir_var_auto,
+ NULL);
validate_identifier(this->name, loc, state);
*/
state->struct_specifier_depth++;
+ /* For blocks that accept memory qualifiers (i.e. shader storage), verify
+ * that we don't have incompatible qualifiers
+ */
+ if (this->layout.flags.q.read_only && this->layout.flags.q.write_only) {
+ _mesa_glsl_error(&loc, state,
+ "Interface block sets both readonly and writeonly");
+ }
+
unsigned int num_variables =
- ast_process_structure_or_interface_block(&declared_variables,
- state,
- &this->declarations,
- loc,
- &fields,
- true,
- matrix_layout,
- redeclaring_per_vertex,
- var_mode,
- &this->layout);
+ ast_process_struct_or_iface_block_members(&declared_variables,
+ state,
+ &this->declarations,
+ loc,
+ &fields,
+ true,
+ matrix_layout,
+ redeclaring_per_vertex,
+ var_mode,
+ &this->layout);
state->struct_specifier_depth--;
_mesa_shader_stage_to_string(state->stage));
}
if (this->instance_name == NULL ||
- strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL) {
+ strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL ||
+ !this->array_specifier->is_single_dimension()) {
_mesa_glsl_error(&loc, state,
"gl_PerVertex input must be redeclared as "
"gl_in[]");
earlier_per_vertex->fields.structure[j].sample;
fields[i].patch =
earlier_per_vertex->fields.structure[j].patch;
+ fields[i].precision =
+ earlier_per_vertex->fields.structure[j].precision;
}
}
ir_variable *var;
if (this->array_specifier != NULL) {
+ const glsl_type *block_array_type =
+ process_array_type(&loc, block_type, this->array_specifier, state);
+
/* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says:
*
* For uniform blocks declared an array, each individual array
* tessellation control shader output, and tessellation evaluation
* shader input.
*/
- if (this->array_specifier->is_unsized_array) {
+ if (block_array_type->is_unsized_array()) {
bool allow_inputs = state->stage == MESA_SHADER_GEOMETRY ||
state->stage == MESA_SHADER_TESS_CTRL ||
state->stage == MESA_SHADER_TESS_EVAL;
}
}
- const glsl_type *block_array_type =
- process_array_type(&loc, block_type, this->array_specifier, state);
-
/* From section 4.3.9 (Interface Blocks) of the GLSL ES 3.10 spec:
*
* * Arrays of arrays of blocks are not allowed
var->data.explicit_binding = this->layout.flags.q.explicit_binding;
var->data.binding = this->layout.binding;
+ var->data.stream = this->layout.stream;
+
state->symbols->add_variable(var);
instructions->push_tail(var);
}
var->data.centroid = fields[i].centroid;
var->data.sample = fields[i].sample;
var->data.patch = fields[i].patch;
+ var->data.stream = this->layout.stream;
var->init_interface_type(block_type);
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
var->data.read_only = true;
+ /* Precision qualifiers do not have any meaning in Desktop GLSL */
+ if (state->es_shader) {
+ var->data.precision =
+ select_gles_precision(fields[i].precision, fields[i].type,
+ state, &loc);
+ }
+
if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) {
var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
var->data.matrix_layout = fields[i].matrix_layout;
}
- if (fields[i].stream != -1 &&
- ((unsigned)fields[i].stream) != this->layout.stream) {
- _mesa_glsl_error(&loc, state,
- "stream layout qualifier on "
- "interface block member `%s' does not match "
- "the interface block (%d vs %d)",
- var->name, fields[i].stream, this->layout.stream);
- }
-
- var->data.stream = this->layout.stream;
-
if (var->data.mode == ir_var_shader_storage) {
var->data.image_read_only = fields[i].image_read_only;
var->data.image_write_only = fields[i].image_write_only;