#include "glsl_parser_extras.h"
#include "ast.h"
#include "compiler/glsl_types.h"
-#include "program/hash_table.h"
+#include "util/hash_table.h"
+#include "main/macros.h"
#include "main/shaderobj.h"
#include "ir.h"
#include "ir_builder.h"
+#include "builtin_functions.h"
using namespace ir_builder;
static void
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
- exec_list *instructions);
+ exec_list *instructions);
static void
remove_per_vertex_blocks(exec_list *instructions,
_mesa_glsl_parse_state *state, ir_variable_mode mode);
}
case GLSL_TYPE_UINT:
- if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable)
+ if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable
+ && !state->MESA_shader_integer_functions_enable)
return (ir_expression_operation)0;
switch (from->base_type) {
case GLSL_TYPE_INT: return ir_unop_i2u;
case GLSL_TYPE_INT: return ir_unop_i2d;
case GLSL_TYPE_UINT: return ir_unop_u2d;
case GLSL_TYPE_FLOAT: return ir_unop_f2d;
+ case GLSL_TYPE_INT64: return ir_unop_i642d;
+ case GLSL_TYPE_UINT64: return ir_unop_u642d;
+ default: return (ir_expression_operation)0;
+ }
+
+ case GLSL_TYPE_UINT64:
+ if (!state->has_int64())
+ return (ir_expression_operation)0;
+ switch (from->base_type) {
+ case GLSL_TYPE_INT: return ir_unop_i2u64;
+ case GLSL_TYPE_UINT: return ir_unop_u2u64;
+ case GLSL_TYPE_INT64: return ir_unop_i642u64;
+ default: return (ir_expression_operation)0;
+ }
+
+ case GLSL_TYPE_INT64:
+ if (!state->has_int64())
+ return (ir_expression_operation)0;
+ switch (from->base_type) {
+ case GLSL_TYPE_INT: return ir_unop_i2i64;
default: return (ir_expression_operation)0;
}
* If a conversion is possible (or unnecessary), \c true is returned.
* Otherwise \c false is returned.
*/
-bool
+static bool
apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
struct _mesa_glsl_parse_state *state)
{
*/
assert(type_a->is_matrix() || type_b->is_matrix());
assert(type_a->base_type == GLSL_TYPE_FLOAT ||
- type_a->base_type == GLSL_TYPE_DOUBLE);
+ type_a->is_double());
assert(type_b->base_type == GLSL_TYPE_FLOAT ||
- type_b->base_type == GLSL_TYPE_DOUBLE);
+ type_b->is_double());
/* "* The operator is add (+), subtract (-), or divide (/), and the
* operands are matrices with the same number of rows and the same
* (|). The operands must be of type signed or unsigned integers or
* integer vectors."
*/
- if (!type_a->is_integer()) {
+ if (!type_a->is_integer_32_64()) {
_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()) {
+ if (!type_b->is_integer_32_64()) {
_mesa_glsl_error(loc, state, "RHS of `%s' must be an integer",
ast_expression::operator_string(op));
return glsl_type::error_type;
* "The operator modulus (%) operates on signed or unsigned integers or
* integer vectors."
*/
- if (!type_a->is_integer()) {
+ if (!type_a->is_integer_32_64()) {
_mesa_glsl_error(loc, state, "LHS of operator %% must be an integer");
return glsl_type::error_type;
}
- if (!type_b->is_integer()) {
+ if (!type_b->is_integer_32_64()) {
_mesa_glsl_error(loc, state, "RHS of operator %% must be an integer");
return glsl_type::error_type;
}
* must be signed or unsigned integers or integer vectors. One operand
* can be signed while the other is unsigned."
*/
- if (!type_a->is_integer()) {
+ if (!type_a->is_integer_32_64()) {
_mesa_glsl_error(loc, state, "LHS of operator %s must be an integer or "
"integer vector", ast_expression::operator_string(op));
return glsl_type::error_type;
*/
if (state->stage == MESA_SHADER_TESS_CTRL && !lhs->type->is_error()) {
ir_variable *var = lhs->variable_referenced();
- if (var->data.mode == ir_var_shader_out && !var->data.patch) {
+ if (var && var->data.mode == ir_var_shader_out && !var->data.patch) {
ir_rvalue *index = find_innermost_array_index(lhs);
ir_variable *index_var = index ? index->variable_referenced() : NULL;
if (!index_var || strcmp(index_var->name, "gl_InvocationID") != 0) {
/* Check for implicit conversion in GLSL 1.20 */
if (apply_implicit_conversion(lhs->type, rhs, state)) {
if (rhs->type == lhs->type)
- return rhs;
+ return rhs;
}
_mesa_glsl_error(&loc, state,
assert(var != NULL);
- if (var->data.max_array_access >= unsigned(rhs->type->array_size())) {
+ if (var->data.max_array_access >= rhs->type->array_size()) {
/* FINISHME: This should actually log the location of the RHS. */
_mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to "
"previous access",
* i = j += 1;
*/
if (needs_rvalue) {
- ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
- ir_var_temporary);
- instructions->push_tail(var);
- instructions->push_tail(assign(var, rhs));
-
+ ir_rvalue *rvalue;
if (!error_emitted) {
- ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
+ ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
+ ir_var_temporary);
+ instructions->push_tail(var);
+ instructions->push_tail(assign(var, rhs));
+
+ ir_dereference_variable *deref_var =
+ new(ctx) ir_dereference_variable(var);
instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var));
+ rvalue = new(ctx) ir_dereference_variable(var);
+ } else {
+ rvalue = ir_rvalue::error_value(ctx);
}
- ir_rvalue *rvalue = new(ctx) ir_dereference_variable(var);
-
*out_rvalue = rvalue;
} else {
if (!error_emitted)
ir_variable *var;
var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
- ir_var_temporary);
+ ir_var_temporary);
instructions->push_tail(var);
instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
- lvalue));
+ lvalue));
return new(ctx) ir_dereference_variable(var);
}
return false;
}
+void
+ast_node::set_is_lhs(bool /* new_value */)
+{
+}
+
void
ast_function_expression::hir_no_rvalue(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
case GLSL_TYPE_INT:
case GLSL_TYPE_BOOL:
case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
return new(mem_ctx) ir_expression(operation, op0, op1);
case GLSL_TYPE_ARRAY: {
*/
ir_rvalue *
get_scalar_boolean_operand(exec_list *instructions,
- struct _mesa_glsl_parse_state *state,
- ast_expression *parent_expr,
- int operand,
- const char *operand_name,
- bool *error_emitted)
+ struct _mesa_glsl_parse_state *state,
+ ast_expression *parent_expr,
+ int operand,
+ const char *operand_name,
+ bool *error_emitted)
{
ast_expression *expr = parent_expr->subexpressions[operand];
void *ctx = state;
_mesa_glsl_error(&loc, state, "`gl_TexCoord' array size cannot "
"be larger than gl_MaxTextureCoords (%u)",
state->Const.MaxTextureCoords);
- } else if (strcmp("gl_ClipDistance", name) == 0
- && size > state->Const.MaxClipPlanes) {
- /* From section 7.1 (Vertex Shader Special Variables) of the
- * GLSL 1.30 spec:
- *
- * "The gl_ClipDistance array is predeclared as unsized and
- * must be sized by the shader either redeclaring it with a
- * size or indexing it only with integral constant
- * expressions. ... The size can be at most
- * gl_MaxClipDistances."
- */
- _mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot "
- "be larger than gl_MaxClipDistances (%u)",
- state->Const.MaxClipPlanes);
+ } else if (strcmp("gl_ClipDistance", name) == 0) {
+ state->clip_dist_size = size;
+ if (size + state->cull_dist_size > state->Const.MaxClipPlanes) {
+ /* From section 7.1 (Vertex Shader Special Variables) of the
+ * GLSL 1.30 spec:
+ *
+ * "The gl_ClipDistance array is predeclared as unsized and
+ * must be sized by the shader either redeclaring it with a
+ * size or indexing it only with integral constant
+ * expressions. ... The size can be at most
+ * gl_MaxClipDistances."
+ */
+ _mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot "
+ "be larger than gl_MaxClipDistances (%u)",
+ state->Const.MaxClipPlanes);
+ }
+ } else if (strcmp("gl_CullDistance", name) == 0) {
+ state->cull_dist_size = size;
+ if (size + state->clip_dist_size > state->Const.MaxClipPlanes) {
+ /* From the ARB_cull_distance spec:
+ *
+ * "The gl_CullDistance array is predeclared as unsized and
+ * must be sized by the shader either redeclaring it with
+ * a size or indexing it only with integral constant
+ * expressions. The size determines the number and set of
+ * enabled cull distances and can be at most
+ * gl_MaxCullDistances."
+ */
+ _mesa_glsl_error(&loc, state, "`gl_CullDistance' array size cannot "
+ "be larger than gl_MaxCullDistances (%u)",
+ state->Const.MaxClipPlanes);
+ }
}
}
return new(ctx) ir_constant((unsigned) 1);
case GLSL_TYPE_INT:
return new(ctx) ir_constant(1);
+ case GLSL_TYPE_UINT64:
+ return new(ctx) ir_constant((uint64_t) 1);
+ case GLSL_TYPE_INT64:
+ return new(ctx) ir_constant((int64_t) 1);
default:
case GLSL_TYPE_FLOAT:
return new(ctx) ir_constant(1.0f);
ast_expression::set_is_lhs(bool new_value)
{
/* is_lhs is tracked only to print "variable used uninitialized" warnings,
- * if we lack a identifier we can just skip it.
+ * if we lack an identifier we can just skip it.
*/
if (this->primary_expression.identifier == NULL)
return;
-1, /* ast_float_constant doesn't conv to ir_expression. */
-1, /* ast_bool_constant doesn't conv to ir_expression. */
-1, /* ast_sequence doesn't convert to ir_expression. */
+ -1, /* ast_aggregate shouldn't ever even get here. */
};
ir_rvalue *result = NULL;
ir_rvalue *op[3];
- const struct glsl_type *type; /* a temporary variable for switch cases */
+ const struct glsl_type *type, *orig_type;
bool error_emitted = false;
YYLTYPE loc;
* in a scalar boolean. See page 57 of the GLSL 1.50 spec.
*/
assert(type->is_error()
- || ((type->base_type == GLSL_TYPE_BOOL)
- && type->is_scalar()));
+ || (type->is_boolean() && type->is_scalar()));
result = new(ctx) ir_expression(operations[this->oper], type,
op[0], op[1]);
!state->check_version(120, 300, &loc,
"array comparisons forbidden")) {
error_emitted = true;
+ } else if ((op[0]->type->contains_subroutine() ||
+ op[1]->type->contains_subroutine())) {
+ _mesa_glsl_error(&loc, state, "subroutine comparisons forbidden");
+ error_emitted = true;
} else if ((op[0]->type->contains_opaque() ||
op[1]->type->contains_opaque())) {
_mesa_glsl_error(&loc, state, "opaque type comparisons forbidden");
error_emitted = true;
}
- if (!op[0]->type->is_integer()) {
+ if (!op[0]->type->is_integer_32_64()) {
_mesa_glsl_error(&loc, state, "operand of `~' must be an integer");
error_emitted = true;
}
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
+ orig_type = op[0]->type;
type = arithmetic_result_type(op[0], op[1],
(this->oper == ast_mul_assign),
state, & loc);
+ if (type != orig_type) {
+ _mesa_glsl_error(& loc, state,
+ "could not implicitly convert "
+ "%s to %s", type->name, orig_type->name);
+ type = glsl_type::error_type;
+ }
+
ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
op[0], op[1]);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
+ orig_type = op[0]->type;
type = modulus_result_type(op[0], op[1], state, &loc);
+ if (type != orig_type) {
+ _mesa_glsl_error(& loc, state,
+ "could not implicitly convert "
+ "%s to %s", type->name, orig_type->name);
+ type = glsl_type::error_type;
+ }
+
assert(operations[this->oper] == ir_binop_mod);
ir_rvalue *temp_rhs;
this->subexpressions[0]->set_is_lhs(true);
op[0] = this->subexpressions[0]->hir(instructions, state);
op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ orig_type = op[0]->type;
type = bit_logic_result_type(op[0], op[1], this->oper, state, &loc);
+
+ if (type != orig_type) {
+ _mesa_glsl_error(& loc, state,
+ "could not implicitly convert "
+ "%s to %s", type->name, orig_type->name);
+ type = glsl_type::error_type;
+ }
+
ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
type, op[0], op[1]);
error_emitted =
ir_variable *var =
state->symbols->get_variable(this->primary_expression.identifier);
+ if (var == NULL) {
+ /* the identifier might be a subroutine name */
+ char *sub_name;
+ sub_name = ralloc_asprintf(ctx, "%s_%s", _mesa_shader_stage_to_subroutine_prefix(state->stage), this->primary_expression.identifier);
+ var = state->symbols->get_variable(sub_name);
+ ralloc_free(sub_name);
+ }
+
if (var != NULL) {
var->data.used = true;
result = new(ctx) ir_dereference_variable(var);
if ((var->data.mode == ir_var_auto || var->data.mode == ir_var_shader_out)
&& !this->is_lhs
- && result->variable_referenced()->data.assigned != true) {
+ && result->variable_referenced()->data.assigned != true
+ && !is_gl_identifier(var->name)) {
_mesa_glsl_warning(&loc, state, "`%s' used uninitialized",
this->primary_expression.identifier);
}
result = new(ctx) ir_constant(this->primary_expression.double_constant);
break;
+ case ast_uint64_constant:
+ result = new(ctx) ir_constant(this->primary_expression.uint64_constant);
+ break;
+
+ case ast_int64_constant:
+ result = new(ctx) ir_constant(this->primary_expression.int64_constant);
+ break;
+
case ast_sequence: {
/* It should not be possible to generate a sequence in the AST without
* any expressions in it.
* therefore add instructions to the instruction list), they get dropped
* on the floor.
*/
- exec_node *previous_tail_pred = NULL;
+ exec_node *previous_tail = NULL;
YYLTYPE previous_operand_loc = loc;
foreach_list_typed (ast_node, ast, link, &this->expressions) {
/* If one of the operands of comma operator does not generate any
* code, we want to emit a warning. At each pass through the loop
- * previous_tail_pred will point to the last instruction in the
- * stream *before* processing the previous operand. Naturally,
- * instructions->tail_pred will point to the last instruction in the
- * stream *after* processing the previous operand. If the two
+ * previous_tail will point to the last instruction in the stream
+ * *before* processing the previous operand. Naturally,
+ * instructions->get_tail_raw() will point to the last instruction in
+ * the stream *after* processing the previous operand. If the two
* pointers match, then the previous operand had no effect.
*
* The warning behavior here differs slightly from GCC. GCC will
* effect, but I don't think these cases exist in GLSL. Either way,
* it would be a giant hassle to replicate that behavior.
*/
- if (previous_tail_pred == instructions->tail_pred) {
+ if (previous_tail == instructions->get_tail_raw()) {
_mesa_glsl_warning(&previous_operand_loc, state,
"left-hand operand of comma expression has "
"no effect");
}
- /* tail_pred is directly accessed instead of using the get_tail()
+ /* The tail is directly accessed instead of using the get_tail()
* method for performance reasons. get_tail() has extra code to
* return NULL when the list is empty. We don't care about that
- * here, so using tail_pred directly is fine.
+ * here, so using get_tail_raw() is fine.
*/
- previous_tail_pred = instructions->tail_pred;
+ previous_tail = instructions->get_tail_raw();
previous_operand_loc = ast->get_location();
result = ast->hir(instructions, state);
case ast_float_constant:
case ast_bool_constant:
case ast_double_constant:
+ case ast_int64_constant:
+ case ast_uint64_constant:
return false;
case ast_aggregate:
- unreachable("ast_aggregate: Should never get here.");
+ return false;
case ast_function_call:
unreachable("should be handled by ast_function_expression::hir");
}
}
- for (exec_node *node = array_specifier->array_dimensions.tail_pred;
+ for (exec_node *node = array_specifier->array_dimensions.get_tail_raw();
!node->is_head_sentinel(); node = node->prev) {
unsigned array_size = process_array_size(node, state);
array_type = glsl_type::get_array_instance(array_type, array_size);
* 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 *const t = type->without_array();
+
+ return (t->is_float() || t->is_integer() || t->contains_opaque()) &&
+ !t->is_record();
}
const glsl_type *
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;
+ const unsigned offset = type->is_sampler() ? 0 : 4;
assert(type_idx < 4);
switch (type->sampled_type) {
case GLSL_TYPE_FLOAT:
switch (type->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"sampler1D", "sampler1DArray",
"sampler1DShadow", "sampler1DArrayShadow"
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_MS: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_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);
+ assert(type->is_sampler());
static const char *const names[4] = {
"samplerRect", NULL, "samplerRectShadow", NULL
};
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_EXTERNAL: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"samplerExternalOES", NULL, NULL, NULL
};
case GLSL_TYPE_INT:
switch (type->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"isampler1D", "isampler1DArray", NULL, NULL
};
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_MS: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_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);
+ assert(type->is_sampler());
static const char *const names[4] = {
"isamplerRect", NULL, "isamplerRectShadow", NULL
};
case GLSL_TYPE_UINT:
switch (type->sampler_dimensionality) {
case GLSL_SAMPLER_DIM_1D: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_sampler());
static const char *const names[4] = {
"usampler1D", "usampler1DArray", NULL, NULL
};
return names[offset + type_idx];
}
case GLSL_SAMPLER_DIM_MS: {
- assert(type->base_type == GLSL_TYPE_SAMPLER);
+ assert(type->is_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);
+ assert(type->is_sampler());
static const char *const names[4] = {
"usamplerRect", NULL, "usamplerRectShadow", NULL
};
type->name);
}
}
+
+
+ /* Section 4.1.7.3 (Atomic Counters) of the GLSL ES 3.10 spec says:
+ *
+ * "The default precision of all atomic types is highp. It is an error to
+ * declare an atomic type with a different precision or to specify the
+ * default precision for an atomic type to be lowp or mediump."
+ */
+ if (type->is_atomic_uint() && precision != ast_precision_high) {
+ _mesa_glsl_error(loc, state,
+ "atomic_uint can only have highp precision qualifier");
+ }
+
return precision;
}
}
}
+static bool
+is_allowed_invariant(ir_variable *var, struct _mesa_glsl_parse_state *state)
+{
+ if (is_varying_var(var, state->stage))
+ return true;
+
+ /* From Section 4.6.1 ("The Invariant Qualifier") GLSL 1.20 spec:
+ * "Only variables output from a vertex shader can be candidates
+ * for invariance".
+ */
+ if (!state->is_version(130, 0))
+ return false;
+
+ /*
+ * Later specs remove this language - so allowed invariant
+ * on fragment shader outputs as well.
+ */
+ if (state->stage == MESA_SHADER_FRAGMENT &&
+ var->data.mode == ir_var_shader_out)
+ return true;
+ return false;
+}
/**
* Matrix layout qualifiers are only allowed on certain types
}
}
+static bool
+validate_xfb_buffer_qualifier(YYLTYPE *loc,
+ struct _mesa_glsl_parse_state *state,
+ unsigned xfb_buffer) {
+ if (xfb_buffer >= state->Const.MaxTransformFeedbackBuffers) {
+ _mesa_glsl_error(loc, state,
+ "invalid xfb_buffer specified %d is larger than "
+ "MAX_TRANSFORM_FEEDBACK_BUFFERS - 1 (%d).",
+ xfb_buffer,
+ state->Const.MaxTransformFeedbackBuffers - 1);
+ return false;
+ }
+
+ return true;
+}
+
+/* From the ARB_enhanced_layouts spec:
+ *
+ * "Variables and block members qualified with *xfb_offset* can be
+ * scalars, vectors, matrices, structures, and (sized) arrays of these.
+ * The offset must be a multiple of the size of the first component of
+ * the first qualified variable or block member, or a compile-time error
+ * results. Further, if applied to an aggregate containing a double,
+ * the offset must also be a multiple of 8, and the space taken in the
+ * buffer will be a multiple of 8.
+ */
+static bool
+validate_xfb_offset_qualifier(YYLTYPE *loc,
+ struct _mesa_glsl_parse_state *state,
+ int xfb_offset, const glsl_type *type,
+ unsigned component_size) {
+ const glsl_type *t_without_array = type->without_array();
+
+ if (xfb_offset != -1 && type->is_unsized_array()) {
+ _mesa_glsl_error(loc, state,
+ "xfb_offset can't be used with unsized arrays.");
+ return false;
+ }
+
+ /* Make sure nested structs don't contain unsized arrays, and validate
+ * any xfb_offsets on interface members.
+ */
+ if (t_without_array->is_record() || t_without_array->is_interface())
+ for (unsigned int i = 0; i < t_without_array->length; i++) {
+ const glsl_type *member_t = t_without_array->fields.structure[i].type;
+
+ /* When the interface block doesn't have an xfb_offset qualifier then
+ * we apply the component size rules at the member level.
+ */
+ if (xfb_offset == -1)
+ component_size = member_t->contains_double() ? 8 : 4;
+
+ int xfb_offset = t_without_array->fields.structure[i].offset;
+ validate_xfb_offset_qualifier(loc, state, xfb_offset, member_t,
+ component_size);
+ }
+
+ /* Nested structs or interface block without offset may not have had an
+ * offset applied yet so return.
+ */
+ if (xfb_offset == -1) {
+ return true;
+ }
+
+ if (xfb_offset % component_size) {
+ _mesa_glsl_error(loc, state,
+ "invalid qualifier xfb_offset=%d must be a multiple "
+ "of the first component size of the first qualified "
+ "variable or block member. Or double if an aggregate "
+ "that contains a double (%d).",
+ xfb_offset, component_size);
+ return false;
+ }
+
+ return true;
+}
+
static bool
validate_stream_qualifier(YYLTYPE *loc, struct _mesa_glsl_parse_state *state,
unsigned stream)
return;
}
+static void
+validate_fragment_flat_interpolation_input(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const glsl_interp_mode interpolation,
+ const struct glsl_type *var_type,
+ ir_variable_mode mode)
+{
+ if (state->stage != MESA_SHADER_FRAGMENT ||
+ interpolation == INTERP_MODE_FLAT ||
+ mode != ir_var_shader_in)
+ return;
+
+ /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES,
+ * so must integer vertex outputs.
+ *
+ * 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."
+ *
+ * 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. See Khronos bug #15671.
+ */
+ if (state->is_version(130, 300)
+ && var_type->contains_integer()) {
+ _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
+ "an integer, then it must be qualified with 'flat'");
+ }
+
+ /* Double fragment inputs must be qualified with 'flat'.
+ *
+ * From the "Overview" of the ARB_gpu_shader_fp64 extension spec:
+ * "This extension does not support interpolation of double-precision
+ * values; doubles used as fragment shader inputs must be qualified as
+ * "flat"."
+ *
+ * From section 4.3.4 ("Inputs") of the GLSL 4.00 spec:
+ * "Fragment shader inputs that are signed or unsigned integers, integer
+ * vectors, or any double-precision floating-point type must be
+ * qualified with the interpolation qualifier flat."
+ *
+ * Note that the GLSL specs are missing the text "or contain"; this is
+ * presumably an oversight. See Khronos bug #15671.
+ *
+ * The 'double' type does not exist in GLSL ES so far.
+ */
+ if (state->has_double()
+ && var_type->contains_double()) {
+ _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
+ "a double, then it must be qualified with 'flat'");
+ }
+}
+
+static void
+validate_interpolation_qualifier(struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc,
+ const glsl_interp_mode interpolation,
+ const struct ast_type_qualifier *qual,
+ const struct glsl_type *var_type,
+ ir_variable_mode mode)
+{
+ /* Interpolation qualifiers can only apply to shader inputs or outputs, but
+ * not to vertex shader inputs nor fragment shader outputs.
+ *
+ * From section 4.3 ("Storage Qualifiers") of the GLSL 1.30 spec:
+ * "Outputs from a vertex shader (out) and inputs to a fragment
+ * shader (in) can be further qualified with one or more of these
+ * interpolation qualifiers"
+ * ...
+ * "These interpolation qualifiers may only precede the qualifiers in,
+ * centroid in, out, or centroid out in a declaration. They do not apply
+ * to the deprecated storage qualifiers varying or centroid
+ * varying. They also do not apply to inputs into a vertex shader or
+ * outputs from a fragment shader."
+ *
+ * From section 4.3 ("Storage Qualifiers") of the GLSL ES 3.00 spec:
+ * "Outputs from a shader (out) and inputs to a shader (in) can be
+ * further qualified with one of these interpolation qualifiers."
+ * ...
+ * "These interpolation qualifiers may only precede the qualifiers
+ * in, centroid in, out, or centroid out in a declaration. They do
+ * not apply to inputs into a vertex shader or outputs from a
+ * fragment shader."
+ */
+ if (state->is_version(130, 300)
+ && interpolation != INTERP_MODE_NONE) {
+ const char *i = interpolation_string(interpolation);
+ 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.", i);
+
+ switch (state->stage) {
+ case MESA_SHADER_VERTEX:
+ if (mode == ir_var_shader_in) {
+ _mesa_glsl_error(loc, state,
+ "interpolation qualifier '%s' cannot be applied to "
+ "vertex shader inputs", i);
+ }
+ break;
+ case MESA_SHADER_FRAGMENT:
+ if (mode == ir_var_shader_out) {
+ _mesa_glsl_error(loc, state,
+ "interpolation qualifier '%s' cannot be applied to "
+ "fragment shader outputs", i);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Interpolation qualifiers cannot be applied to 'centroid' and
+ * 'centroid varying'.
+ *
+ * From section 4.3 ("Storage Qualifiers") of the GLSL 1.30 spec:
+ * "interpolation qualifiers may only precede the qualifiers in,
+ * centroid in, out, or centroid out in a declaration. They do not apply
+ * to the deprecated storage qualifiers varying or centroid varying."
+ *
+ * These deprecated storage qualifiers do not exist in GLSL ES 3.00.
+ */
+ if (state->is_version(130, 0)
+ && interpolation != INTERP_MODE_NONE
+ && qual->flags.q.varying) {
+
+ const char *i = interpolation_string(interpolation);
+ const char *s;
+ if (qual->flags.q.centroid)
+ s = "centroid varying";
+ else
+ s = "varying";
+
+ _mesa_glsl_error(loc, state,
+ "qualifier '%s' cannot be applied to the "
+ "deprecated storage qualifier '%s'", i, s);
+ }
+
+ validate_fragment_flat_interpolation_input(state, loc, interpolation,
+ var_type, mode);
+}
-static glsl_interp_qualifier
+static glsl_interp_mode
interpret_interpolation_qualifier(const struct ast_type_qualifier *qual,
+ const struct glsl_type *var_type,
ir_variable_mode mode,
struct _mesa_glsl_parse_state *state,
YYLTYPE *loc)
{
- glsl_interp_qualifier interpolation;
+ glsl_interp_mode interpolation;
if (qual->flags.q.flat)
- interpolation = INTERP_QUALIFIER_FLAT;
+ interpolation = INTERP_MODE_FLAT;
else if (qual->flags.q.noperspective)
- interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
+ interpolation = INTERP_MODE_NOPERSPECTIVE;
else if (qual->flags.q.smooth)
- interpolation = INTERP_QUALIFIER_SMOOTH;
- else
- interpolation = INTERP_QUALIFIER_NONE;
-
- if (interpolation != INTERP_QUALIFIER_NONE) {
- 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.",
- interpolation_string(interpolation));
-
- }
-
- if ((state->stage == MESA_SHADER_VERTEX && mode == ir_var_shader_in) ||
- (state->stage == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) {
- _mesa_glsl_error(loc, state,
- "interpolation qualifier `%s' cannot be applied to "
- "vertex shader inputs or fragment shader outputs",
- interpolation_string(interpolation));
- }
- } else if (state->es_shader &&
- ((mode == ir_var_shader_in &&
- state->stage != MESA_SHADER_VERTEX) ||
- (mode == ir_var_shader_out &&
- state->stage != MESA_SHADER_FRAGMENT))) {
+ interpolation = INTERP_MODE_SMOOTH;
+ else if (state->es_shader &&
+ ((mode == ir_var_shader_in &&
+ state->stage != MESA_SHADER_VERTEX) ||
+ (mode == ir_var_shader_out &&
+ state->stage != MESA_SHADER_FRAGMENT)))
/* Section 4.3.9 (Interpolation) of the GLSL ES 3.00 spec says:
*
* "When no interpolation qualifier is present, smooth interpolation
* is used."
*/
- interpolation = INTERP_QUALIFIER_SMOOTH;
- }
+ interpolation = INTERP_MODE_SMOOTH;
+ else
+ interpolation = INTERP_MODE_NONE;
+
+ validate_interpolation_qualifier(state, loc,
+ interpolation,
+ qual, var_type, mode);
return interpolation;
}
}
/* Check if index was set for the uniform instead of the function */
- if (qual->flags.q.explicit_index && qual->flags.q.subroutine) {
+ if (qual->flags.q.explicit_index && qual->is_subroutine_decl()) {
_mesa_glsl_error(loc, state, "an index qualifier can only be "
"used with subroutine functions");
return;
{
const glsl_type *base_type = var->type->without_array();
- if (base_type->is_image()) {
- if (var->data.mode != ir_var_uniform &&
- var->data.mode != ir_var_function_in) {
- _mesa_glsl_error(loc, state, "image variables may only be declared as "
- "function parameters or uniform-qualified "
- "global variables");
+ if (!base_type->is_image()) {
+ if (qual->flags.q.read_only ||
+ qual->flags.q.write_only ||
+ qual->flags.q.coherent ||
+ qual->flags.q._volatile ||
+ qual->flags.q.restrict_flag ||
+ qual->flags.q.explicit_image_format) {
+ _mesa_glsl_error(loc, state, "memory qualifiers may only be applied "
+ "to images");
}
+ return;
+ }
- var->data.image_read_only |= qual->flags.q.read_only;
- var->data.image_write_only |= qual->flags.q.write_only;
- var->data.image_coherent |= qual->flags.q.coherent;
- var->data.image_volatile |= qual->flags.q._volatile;
- var->data.image_restrict |= qual->flags.q.restrict_flag;
- var->data.read_only = true;
+ if (var->data.mode != ir_var_uniform &&
+ var->data.mode != ir_var_function_in) {
+ _mesa_glsl_error(loc, state, "image variables may only be declared as "
+ "function parameters or uniform-qualified "
+ "global variables");
+ }
- if (qual->flags.q.explicit_image_format) {
- if (var->data.mode == ir_var_function_in) {
- _mesa_glsl_error(loc, state, "format qualifiers cannot be "
- "used on image function parameters");
- }
+ var->data.image_read_only |= qual->flags.q.read_only;
+ var->data.image_write_only |= qual->flags.q.write_only;
+ var->data.image_coherent |= qual->flags.q.coherent;
+ var->data.image_volatile |= qual->flags.q._volatile;
+ var->data.image_restrict |= qual->flags.q.restrict_flag;
+ var->data.read_only = true;
- if (qual->image_base_type != base_type->sampled_type) {
- _mesa_glsl_error(loc, state, "format qualifier doesn't match the "
- "base data type of the image");
- }
+ if (qual->flags.q.explicit_image_format) {
+ if (var->data.mode == ir_var_function_in) {
+ _mesa_glsl_error(loc, state, "format qualifiers cannot be used on "
+ "image function parameters");
+ }
- var->data.image_format = qual->image_format;
- } else {
- if (var->data.mode == ir_var_uniform) {
- if (state->es_shader) {
- _mesa_glsl_error(loc, state, "all image uniforms "
- "must have a format layout qualifier");
+ if (qual->image_base_type != base_type->sampled_type) {
+ _mesa_glsl_error(loc, state, "format qualifier doesn't match the base "
+ "data type of the image");
+ }
- } else if (!qual->flags.q.write_only) {
- _mesa_glsl_error(loc, state, "image uniforms not qualified with "
- "`writeonly' must have a format layout "
- "qualifier");
- }
+ var->data.image_format = qual->image_format;
+ } else {
+ if (var->data.mode == ir_var_uniform) {
+ if (state->es_shader) {
+ _mesa_glsl_error(loc, state, "all image uniforms must have a "
+ "format layout qualifier");
+ } else if (!qual->flags.q.write_only) {
+ _mesa_glsl_error(loc, state, "image uniforms not qualified with "
+ "`writeonly' must have a format layout qualifier");
}
-
- var->data.image_format = GL_NONE;
}
+ var->data.image_format = GL_NONE;
+ }
- /* From page 70 of the GLSL ES 3.1 specification:
- *
- * "Except for image variables qualified with the format qualifiers
- * r32f, r32i, and r32ui, image variables must specify either memory
- * qualifier readonly or the memory qualifier writeonly."
- */
- if (state->es_shader &&
- var->data.image_format != GL_R32F &&
- var->data.image_format != GL_R32I &&
- var->data.image_format != GL_R32UI &&
- !var->data.image_read_only &&
- !var->data.image_write_only) {
- _mesa_glsl_error(loc, state, "image variables of format other than "
- "r32f, r32i or r32ui must be qualified `readonly' or "
- "`writeonly'");
- }
-
- } else if (qual->flags.q.read_only ||
- qual->flags.q.write_only ||
- qual->flags.q.coherent ||
- qual->flags.q._volatile ||
- qual->flags.q.restrict_flag ||
- qual->flags.q.explicit_image_format) {
- _mesa_glsl_error(loc, state, "memory qualifiers may only be applied to "
- "images");
+ /* From page 70 of the GLSL ES 3.1 specification:
+ *
+ * "Except for image variables qualified with the format qualifiers r32f,
+ * r32i, and r32ui, image variables must specify either memory qualifier
+ * readonly or the memory qualifier writeonly."
+ */
+ if (state->es_shader &&
+ var->data.image_format != GL_R32F &&
+ var->data.image_format != GL_R32I &&
+ var->data.image_format != GL_R32UI &&
+ !var->data.image_read_only &&
+ !var->data.image_write_only) {
+ _mesa_glsl_error(loc, state, "image variables of format other than r32f, "
+ "r32i or r32ui must be qualified `readonly' or "
+ "`writeonly'");
}
}
? "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);
+ "layout qualifier `%s' can only be applied to "
+ "fragment shader input `gl_FragCoord'",
+ qual_string);
}
if (qual->flags.q.explicit_location) {
apply_explicit_location(qual, var, state, loc);
+
+ if (qual->flags.q.explicit_component) {
+ unsigned qual_component;
+ if (process_qualifier_constant(state, loc, "component",
+ qual->component, &qual_component)) {
+ const glsl_type *type = var->type->without_array();
+ unsigned components = type->component_slots();
+
+ if (type->is_matrix() || type->is_record()) {
+ _mesa_glsl_error(loc, state, "component layout qualifier "
+ "cannot be applied to a matrix, a structure, "
+ "a block, or an array containing any of "
+ "these.");
+ } else if (qual_component != 0 &&
+ (qual_component + components - 1) > 3) {
+ _mesa_glsl_error(loc, state, "component overflow (%u > 3)",
+ (qual_component + components - 1));
+ } else if (qual_component == 1 && type->is_64bit()) {
+ /* We don't bother checking for 3 as it should be caught by the
+ * overflow check above.
+ */
+ _mesa_glsl_error(loc, state, "doubles cannot begin at "
+ "component 1 or 3");
+ } else {
+ var->data.explicit_component = true;
+ var->data.location_frac = qual_component;
+ }
+ }
+ }
} else if (qual->flags.q.explicit_index) {
- if (!qual->flags.q.subroutine_def)
+ if (!qual->subroutine_list)
_mesa_glsl_error(loc, state,
"explicit index requires explicit location");
+ } else if (qual->flags.q.explicit_component) {
+ _mesa_glsl_error(loc, state,
+ "explicit component requires explicit location");
}
if (qual->flags.q.explicit_binding) {
}
}
+ if (qual->flags.q.out && qual->flags.q.xfb_buffer) {
+ unsigned qual_xfb_buffer;
+ if (process_qualifier_constant(state, loc, "xfb_buffer",
+ qual->xfb_buffer, &qual_xfb_buffer) &&
+ validate_xfb_buffer_qualifier(loc, state, qual_xfb_buffer)) {
+ var->data.xfb_buffer = qual_xfb_buffer;
+ if (qual->flags.q.explicit_xfb_buffer)
+ var->data.explicit_xfb_buffer = true;
+ }
+ }
+
+ if (qual->flags.q.explicit_xfb_offset) {
+ unsigned qual_xfb_offset;
+ unsigned component_size = var->type->contains_double() ? 8 : 4;
+
+ if (process_qualifier_constant(state, loc, "xfb_offset",
+ qual->offset, &qual_xfb_offset) &&
+ validate_xfb_offset_qualifier(loc, state, (int) qual_xfb_offset,
+ var->type, component_size)) {
+ var->data.offset = qual_xfb_offset;
+ var->data.explicit_xfb_offset = true;
+ }
+ }
+
+ if (qual->flags.q.explicit_xfb_stride) {
+ unsigned qual_xfb_stride;
+ if (process_qualifier_constant(state, loc, "xfb_stride",
+ qual->xfb_stride, &qual_xfb_stride)) {
+ var->data.xfb_stride = qual_xfb_stride;
+ var->data.explicit_xfb_stride = true;
+ }
+ }
+
if (var->type->contains_atomic()) {
if (var->data.mode == ir_var_uniform) {
if (var->data.explicit_binding) {
}
}
+ if (var->type->contains_sampler()) {
+ if (var->data.mode != ir_var_uniform &&
+ var->data.mode != ir_var_function_in) {
+ _mesa_glsl_error(loc, state, "sampler variables 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
/* 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
+ if (qual->flags.q.depth_type
+ && !state->is_version(420, 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
+ } else if (qual->flags.q.depth_type
&& 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)
+
+ switch (qual->depth_type) {
+ case ast_depth_any:
var->data.depth_layout = ir_depth_layout_any;
- else if (qual->flags.q.depth_greater)
+ break;
+ case ast_depth_greater:
var->data.depth_layout = ir_depth_layout_greater;
- else if (qual->flags.q.depth_less)
+ break;
+ case ast_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;
+ break;
+ case ast_depth_unchanged:
+ var->data.depth_layout = ir_depth_layout_unchanged;
+ break;
+ default:
+ var->data.depth_layout = ir_depth_layout_none;
+ break;
+ }
if (qual->flags.q.std140 ||
qual->flags.q.std430 ||
_mesa_glsl_error(loc, state, "early_fragment_tests layout qualifier only "
"valid in fragment shader input layout declaration.");
}
+
+ if (qual->flags.q.inner_coverage) {
+ _mesa_glsl_error(loc, state, "inner_coverage layout qualifier only "
+ "valid in fragment shader input layout declaration.");
+ }
+
+ if (qual->flags.q.post_depth_coverage) {
+ _mesa_glsl_error(loc, state, "post_depth_coverage layout qualifier only "
+ "valid in fragment shader input layout declaration.");
+ }
}
static void
}
}
- if (qual->flags.q.subroutine && !qual->flags.q.uniform) {
+ if (qual->is_subroutine_decl() && !qual->flags.q.uniform) {
_mesa_glsl_error(loc, state,
"`subroutine' may only be applied to uniforms, "
"subroutine type declarations, or function definitions");
*/
assert(var->data.mode != ir_var_temporary);
if (qual->flags.q.in && qual->flags.q.out)
- var->data.mode = ir_var_function_inout;
+ var->data.mode = is_parameter ? ir_var_function_inout : ir_var_shader_out;
else if (qual->flags.q.in)
var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in;
else if (qual->flags.q.attribute
- || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT)))
+ || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT)))
var->data.mode = ir_var_shader_in;
else if (qual->flags.q.out)
var->data.mode = is_parameter ? ir_var_function_out : ir_var_shader_out;
else if (qual->flags.q.shared_storage)
var->data.mode = ir_var_shader_shared;
+ var->data.fb_fetch_output = state->stage == MESA_SHADER_FRAGMENT &&
+ qual->flags.q.in && qual->flags.q.out;
+
if (!is_parameter && is_varying_var(var, state->stage)) {
/* User-defined ins/outs are not permitted in compute shaders. */
if (state->stage == MESA_SHADER_COMPUTE) {
"varying variables may not be of type struct");
break;
case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
break;
default:
_mesa_glsl_error(loc, state, "illegal type for a varying variable");
}
var->data.interpolation =
- interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode,
+ interpret_interpolation_qualifier(qual, var->type,
+ (ir_variable_mode) var->data.mode,
state, loc);
/* Does the declaration use the deprecated 'attribute' or 'varying'
}
/**
- * Get the variable that is being redeclared by this declaration
+ * Get the variable that is being redeclared by this declaration or if it
+ * does not exist, the current declared variable.
*
* Semantic checks to verify the validity of the redeclaration are also
* performed. If semantic checks fail, compilation error will be emitted via
*
* \returns
* A pointer to an existing variable in the current scope if the declaration
- * is a redeclaration, \c NULL otherwise.
+ * is a redeclaration, current variable otherwise. \c is_declared boolean
+ * will return \c true if the declaration is a redeclaration, \c false
+ * otherwise.
*/
static ir_variable *
get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
struct _mesa_glsl_parse_state *state,
- bool allow_all_redeclarations)
+ bool allow_all_redeclarations,
+ bool *is_redeclaration)
{
/* Check if this declaration is actually a re-declaration, either to
* resize an array or add qualifiers to an existing variable.
if (earlier == NULL ||
(state->current_function != NULL &&
!state->symbols->name_declared_this_scope(var->name))) {
- return NULL;
+ *is_redeclaration = false;
+ return var;
}
+ *is_redeclaration = true;
/* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
*
* FINISHME: required or not.
*/
- const unsigned size = unsigned(var->type->array_size());
+ const int size = var->type->array_size();
check_builtin_array_max_size(var->name, size, loc, state);
if ((size > 0) && (size <= earlier->data.max_array_access)) {
_mesa_glsl_error(& loc, state, "array size must be > %u due to "
earlier->data.interpolation = var->data.interpolation;
/* Layout qualifiers for gl_FragDepth. */
- } else if ((state->AMD_conservative_depth_enable ||
+ } else if ((state->is_version(420, 0) ||
+ state->AMD_conservative_depth_enable ||
state->ARB_conservative_depth_enable)
&& strcmp(var->name, "gl_FragDepth") == 0
&& earlier->type == var->type
earlier->data.depth_layout = var->data.depth_layout;
+ } else if (state->has_framebuffer_fetch() &&
+ strcmp(var->name, "gl_LastFragData") == 0 &&
+ var->type == earlier->type &&
+ var->data.mode == ir_var_auto) {
+ /* According to the EXT_shader_framebuffer_fetch spec:
+ *
+ * "By default, gl_LastFragData is declared with the mediump precision
+ * qualifier. This can be changed by redeclaring the corresponding
+ * variables with the desired precision qualifier."
+ */
+ earlier->data.precision = var->data.precision;
+
} else if (allow_all_redeclarations) {
if (earlier->data.mode != var->data.mode) {
_mesa_glsl_error(&loc, state,
*/
ir_rvalue *
process_initializer(ir_variable *var, ast_declaration *decl,
- ast_fully_specified_type *type,
- exec_list *initializer_instructions,
- struct _mesa_glsl_parse_state *state)
+ ast_fully_specified_type *type,
+ exec_list *initializer_instructions,
+ struct _mesa_glsl_parse_state *state)
{
ir_rvalue *result = NULL;
if (var->data.patch)
return;
- /* Unsized arrays are implicitly sized to gl_MaxPatchVertices. */
+ /* The ARB_tessellation_shader spec says:
+ *
+ * "Declaring an array size is optional. If no size is specified, it
+ * will be taken from the implementation-dependent maximum patch size
+ * (gl_MaxPatchVertices). If a size is specified, it must match the
+ * maximum patch size; otherwise, a compile or link error will occur."
+ *
+ * This text appears twice, once for TCS inputs, and again for TES inputs.
+ */
if (var->type->is_unsized_array()) {
var->type = glsl_type::get_array_instance(var->type->fields.array,
state->Const.MaxPatchVertices);
+ } else if (var->type->length != state->Const.MaxPatchVertices) {
+ _mesa_glsl_error(&loc, state,
+ "per-vertex tessellation shader input arrays must be "
+ "sized to gl_MaxPatchVertices (%d).",
+ state->Const.MaxPatchVertices);
}
}
_mesa_glsl_error(& loc, state,
"undeclared variable `%s' cannot be marked "
"invariant", decl->identifier);
- } else if (!is_varying_var(earlier, state->stage)) {
+ } else if (!is_allowed_invariant(earlier, state)) {
_mesa_glsl_error(&loc, state,
"`%s' cannot be marked invariant; interfaces between "
"shader stages only.", decl->identifier);
state->atomic_counter_offsets[qual_binding] = qual_offset;
}
}
+
+ ast_type_qualifier allowed_atomic_qual_mask;
+ allowed_atomic_qual_mask.flags.i = 0;
+ allowed_atomic_qual_mask.flags.q.explicit_binding = 1;
+ allowed_atomic_qual_mask.flags.q.explicit_offset = 1;
+ allowed_atomic_qual_mask.flags.q.uniform = 1;
+
+ type->qualifier.validate_flags(&loc, state, allowed_atomic_qual_mask,
+ "invalid layout qualifier for",
+ "atomic_uint");
}
if (this->declarations.is_empty()) {
* confusing error.
*/
assert(this->type->specifier->structure == NULL || decl_type != NULL
- || state->error);
+ || state->error);
if (decl_type == NULL) {
_mesa_glsl_error(&loc, state,
"invalid type `%s' in empty declaration",
type_name);
} else {
- if (decl_type->base_type == GLSL_TYPE_ARRAY) {
+ if (decl_type->is_array()) {
/* From Section 13.22 (Array Declarations) of the GLSL ES 3.2
* spec:
*
validate_array_dimensions(decl_type, state, &loc);
}
- if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {
+ if (decl_type->is_atomic_uint()) {
/* Empty atomic counter declarations are allowed and useful
* to set the default offset qualifier.
*/
continue;
}
- if (this->type->qualifier.flags.q.subroutine) {
+ if (this->type->qualifier.is_subroutine_decl()) {
const glsl_type *t;
const char *name;
}
apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
- & loc, false);
+ & loc, false);
apply_layout_qualifier_to_variable(&this->type->qualifier, var, state,
&loc);
+ if ((var->data.mode == ir_var_auto || var->data.mode == ir_var_temporary)
+ && (var->type->is_numeric() || var->type->is_boolean())
+ && state->zero_init) {
+ const ir_constant_data data = { { 0 } };
+ var->data.has_initializer = true;
+ var->constant_initializer = new(var) ir_constant(var->type, &data);
+ }
+
if (this->type->qualifier.flags.q.invariant) {
- if (!is_varying_var(var, state->stage)) {
+ if (!is_allowed_invariant(var, state)) {
_mesa_glsl_error(&loc, state,
"`%s' cannot be marked invariant; interfaces between "
"shader stages only", var->name);
*/
if (this->type->qualifier.flags.q.attribute) {
mode = "attribute";
- } else if (this->type->qualifier.flags.q.subroutine) {
+ } else if (this->type->qualifier.is_subroutine_decl()) {
mode = "subroutine uniform";
} else if (this->type->qualifier.flags.q.uniform) {
mode = "uniform";
switch (check_type->base_type) {
case GLSL_TYPE_FLOAT:
break;
+ case GLSL_TYPE_UINT64:
+ case GLSL_TYPE_INT64:
+ break;
case GLSL_TYPE_UINT:
case GLSL_TYPE_INT:
if (state->is_version(120, 300))
break;
case GLSL_TYPE_DOUBLE:
- if (check_type->base_type == GLSL_TYPE_DOUBLE && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable))
+ if (check_type->is_double() && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable))
break;
/* FALLTHROUGH */
default:
* * A matrix
* * A structure
* * An array of array
+ *
+ * ES 3.20 updates this to apply to tessellation and geometry shaders
+ * as well. Because there are per-vertex arrays in the new stages,
+ * it strikes the "array of..." rules and replaces them with these:
+ *
+ * * For per-vertex-arrayed variables (applies to tessellation
+ * control, tessellation evaluation and geometry shaders):
+ *
+ * * Per-vertex-arrayed arrays of arrays
+ * * Per-vertex-arrayed arrays of structures
+ *
+ * * For non-per-vertex-arrayed variables:
+ *
+ * * An array of arrays
+ * * An array of structures
+ *
+ * which basically says to unwrap the per-vertex aspect and apply
+ * the old rules.
*/
if (state->es_shader) {
if (var->type->is_array() &&
"cannot have an array of arrays",
_mesa_shader_stage_to_string(state->stage));
}
- if (state->stage == MESA_SHADER_VERTEX) {
- if (var->type->is_array() &&
- var->type->fields.array->is_record()) {
+ if (state->stage <= MESA_SHADER_GEOMETRY) {
+ const glsl_type *type = var->type;
+
+ if (state->stage == MESA_SHADER_TESS_CTRL &&
+ !var->data.patch && var->type->is_array()) {
+ type = var->type->fields.array;
+ }
+
+ if (type->is_array() && type->fields.array->is_record()) {
_mesa_glsl_error(&loc, state,
- "vertex shader output "
- "cannot have an array of structs");
+ "%s shader output cannot have "
+ "an array of structs",
+ _mesa_shader_stage_to_string(state->stage));
}
- if (var->type->is_record()) {
- for (unsigned i = 0; i < var->type->length; i++) {
- if (var->type->fields.structure[i].type->is_array() ||
- var->type->fields.structure[i].type->is_record())
+ if (type->is_record()) {
+ for (unsigned i = 0; i < type->length; i++) {
+ if (type->fields.structure[i].type->is_array() ||
+ type->fields.structure[i].type->is_record())
_mesa_glsl_error(&loc, state,
- "vertex shader output cannot have a "
+ "%s shader output cannot have a "
"struct that contains an "
- "array or struct");
+ "array or struct",
+ _mesa_shader_stage_to_string(state->stage));
}
}
}
var->data.how_declared = ir_var_hidden;
}
- /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES,
- * so must integer vertex outputs.
- *
- * 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."
- *
- * 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) &&
- var->type->contains_integer() &&
- var->data.interpolation != INTERP_QUALIFIER_FLAT &&
- ((state->stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in)
- || (state->stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out
- && state->es_shader))) {
- const char *var_type = (state->stage == MESA_SHADER_VERTEX) ?
- "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);
- }
-
- /* Double fragment inputs must be qualified with 'flat'. */
- if (var->type->contains_double() &&
- var->data.interpolation != INTERP_QUALIFIER_FLAT &&
- state->stage == MESA_SHADER_FRAGMENT &&
- var->data.mode == ir_var_shader_in) {
- _mesa_glsl_error(&loc, state, "if a fragment input is (or contains) "
- "a double, then it must be qualified with 'flat'",
- var_type);
- }
-
- /* Interpolation qualifiers cannot be applied to 'centroid' and
- * 'centroid varying'.
- *
- * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
- * "interpolation qualifiers may only precede the qualifiers in,
- * centroid in, out, or centroid out in a declaration. They do not apply
- * to the deprecated storage qualifiers varying or centroid varying."
- *
- * These deprecated storage qualifiers do not exist in GLSL ES 3.00.
- */
- if (state->is_version(130, 0)
- && this->type->qualifier.has_interpolation()
- && this->type->qualifier.flags.q.varying) {
-
- const char *i = interpolation_string(var->data.interpolation);
- const char *s;
- if (this->type->qualifier.flags.q.centroid)
- s = "centroid varying";
- else
- s = "varying";
-
- _mesa_glsl_error(&loc, state,
- "qualifier '%s' cannot be applied to the "
- "deprecated storage qualifier '%s'", i, s);
- }
-
-
- /* Interpolation qualifiers can only apply to vertex shader outputs and
- * fragment shader inputs.
- *
- * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
- * "Outputs from a vertex shader (out) and inputs to a fragment
- * shader (in) can be further qualified with one or more of these
- * interpolation qualifiers"
- *
- * From page 31 (page 37 of the PDF) of the GLSL ES 3.00 spec:
- * "These interpolation qualifiers may only precede the qualifiers
- * in, centroid in, out, or centroid out in a declaration. They do
- * not apply to inputs into a vertex shader or outputs from a
- * fragment shader."
- */
- if (state->is_version(130, 300)
- && this->type->qualifier.has_interpolation()) {
-
- const char *i = interpolation_string(var->data.interpolation);
- switch (state->stage) {
- case MESA_SHADER_VERTEX:
- if (this->type->qualifier.flags.q.in) {
- _mesa_glsl_error(&loc, state,
- "qualifier '%s' cannot be applied to vertex "
- "shader inputs", i);
- }
- break;
- case MESA_SHADER_FRAGMENT:
- if (this->type->qualifier.flags.q.out) {
- _mesa_glsl_error(&loc, state,
- "qualifier '%s' cannot be applied to fragment "
- "shader outputs", i);
- }
- break;
- default:
- break;
- }
- }
-
-
/* From section 4.3.4 of the GLSL 4.00 spec:
* "Input variables may not be declared using the patch in qualifier
* in tessellation control or geometry shaders."
state->check_precision_qualifiers_allowed(&loc);
}
-
- /* If a precision qualifier is allowed on a type, it is allowed on
- * an array of that type.
- */
- if (!(this->type->qualifier.precision == ast_precision_none
- || precision_qualifier_allowed(var->type->without_array()))) {
-
+ if (this->type->qualifier.precision != ast_precision_none &&
+ !precision_qualifier_allowed(var->type)) {
_mesa_glsl_error(&loc, state,
"precision qualifiers apply only to floating point"
", integer and opaque types");
/* Examine var name here since var may get deleted in the next call */
bool var_is_gl_id = is_gl_identifier(var->name);
- ir_variable *earlier =
+ bool is_redeclaration;
+ ir_variable *declared_var =
get_variable_being_redeclared(var, decl->get_location(), state,
- false /* allow_all_redeclarations */);
- if (earlier != NULL) {
+ false /* allow_all_redeclarations */,
+ &is_redeclaration);
+ if (is_redeclaration) {
if (var_is_gl_id &&
- earlier->data.how_declared == ir_var_declared_in_block) {
+ declared_var->data.how_declared == ir_var_declared_in_block) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared using "
- "gl_PerVertex", earlier->name);
+ "gl_PerVertex", declared_var->name);
}
- earlier->data.how_declared = ir_var_declared_normally;
+ declared_var->data.how_declared = ir_var_declared_normally;
}
if (decl->initializer != NULL) {
- result = process_initializer((earlier == NULL) ? var : earlier,
+ result = process_initializer(declared_var,
decl, this->type,
&initializer_instructions, state);
} else {
}
if (state->es_shader) {
- const glsl_type *const t = (earlier == NULL)
- ? var->type : earlier->type;
+ const glsl_type *const t = declared_var->type;
- if (t->is_unsized_array())
+ /* Skip the unsized array check for TCS/TES/GS inputs & TCS outputs.
+ *
+ * The GL_OES_tessellation_shader spec says about inputs:
+ *
+ * "Declaring an array size is optional. If no size is specified,
+ * it will be taken from the implementation-dependent maximum
+ * patch size (gl_MaxPatchVertices)."
+ *
+ * and about TCS outputs:
+ *
+ * "If no size is specified, it will be taken from output patch
+ * size declared in the shader."
+ *
+ * The GL_OES_geometry_shader spec says:
+ *
+ * "All geometry shader input unsized array declarations will be
+ * sized by an earlier input primitive layout qualifier, when
+ * present, as per the following table."
+ */
+ const bool implicitly_sized =
+ (declared_var->data.mode == ir_var_shader_in &&
+ state->stage >= MESA_SHADER_TESS_CTRL &&
+ state->stage <= MESA_SHADER_GEOMETRY) ||
+ (declared_var->data.mode == ir_var_shader_out &&
+ state->stage == MESA_SHADER_TESS_CTRL);
+
+ if (t->is_unsized_array() && !implicitly_sized)
/* 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
* semantic checks that must be applied. In addition, variable that was
* created for the declaration should be added to the IR stream.
*/
- if (earlier == NULL) {
+ if (!is_redeclaration) {
validate_identifier(decl->identifier, loc, state);
/* Add the variable to the symbol table. Note that the initializer's
* after the initializer if present or immediately after the name
* being declared if not."
*/
- if (!state->symbols->add_variable(var)) {
+ if (!state->symbols->add_variable(declared_var)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state, "name `%s' already taken in the "
"current scope", decl->identifier);
* global var is decled, then the function is defined with usage of
* the global var. See glslparsertest's CorrectModule.frag.
*/
- instructions->push_head(var);
+ instructions->push_head(declared_var);
}
instructions->append_list(&initializer_instructions);
state->is_version(120, 100)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state,
- "declaration of function `%s' not allowed within "
- "function body", name);
+ "declaration of function `%s' not allowed within "
+ "function body", name);
}
validate_identifier(name, this->get_location(), state);
* "Subroutine declarations cannot be prototyped. It is an error to prepend
* subroutine(...) to a function declaration."
*/
- if (this->return_type->qualifier.flags.q.subroutine_def && !is_definition) {
+ if (this->return_type->qualifier.subroutine_list && !is_definition) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state,
"function declaration `%s' cannot have subroutine prepended",
name);
}
+ /**/
+ if (return_type->is_subroutine()) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state,
+ "function `%s' return type can't be a subroutine type",
+ name);
+ }
+
+
/* Create an ir_function if one doesn't already exist. */
f = state->symbols->get_function(name);
if (f == NULL) {
f = new(ctx) ir_function(name);
- if (!this->return_type->qualifier.flags.q.subroutine) {
+ if (!this->return_type->qualifier.is_subroutine_decl()) {
if (!state->symbols->add_function(f)) {
/* This function name shadows a non-function use of the same name. */
YYLTYPE loc = this->get_location();
if (state->es_shader && state->language_version >= 300) {
/* Local shader has no exact candidates; check the built-ins. */
_mesa_glsl_initialize_builtin_functions();
- if (_mesa_glsl_find_builtin_function_by_name(name)) {
+ if (_mesa_glsl_has_builtin_function(name)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state,
"A shader cannot redefine or overload built-in "
sig->replace_parameters(&hir_parameters);
signature = sig;
- if (this->return_type->qualifier.flags.q.subroutine_def) {
+ if (this->return_type->qualifier.subroutine_list) {
int idx;
if (this->return_type->qualifier.flags.q.explicit_index) {
if (!type) {
_mesa_glsl_error(& loc, state, "unknown type '%s' in subroutine function definition", decl->identifier);
}
+
+ for (int i = 0; i < state->num_subroutine_types; i++) {
+ ir_function *fn = state->subroutine_types[i];
+ ir_function_signature *tsig = NULL;
+
+ if (strcmp(fn->name, decl->identifier))
+ continue;
+
+ tsig = fn->matching_signature(state, &sig->parameters,
+ false);
+ if (!tsig) {
+ _mesa_glsl_error(& loc, state, "subroutine type mismatch '%s' - signatures do not match\n", decl->identifier);
+ } else {
+ if (tsig->return_type != sig->return_type) {
+ _mesa_glsl_error(& loc, state, "subroutine type mismatch '%s' - return types do not match\n", decl->identifier);
+ }
+ }
+ }
f->subroutine_types[idx++] = type;
}
state->subroutines = (ir_function **)reralloc(state, state->subroutines,
}
- if (this->return_type->qualifier.flags.q.subroutine) {
+ if (this->return_type->qualifier.is_subroutine_decl()) {
if (!state->symbols->add_type(this->identifier, glsl_type::get_subroutine_instance(this->identifier))) {
_mesa_glsl_error(& loc, state, "type '%s' previously defined", this->identifier);
return NULL;
}
+/* Used for detection of duplicate case values, compare
+ * given contents directly.
+ */
+static bool
+compare_case_value(const void *a, const void *b)
+{
+ return *(unsigned *) a == *(unsigned *) b;
+}
+
+
+/* Used for detection of duplicate case values, just
+ * returns key contents as is.
+ */
+static unsigned
+key_contents(const void *key)
+{
+ return *(unsigned *) key;
+}
+
+
ir_rvalue *
ast_switch_statement::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
state->switch_state.is_switch_innermost = true;
state->switch_state.switch_nesting_ast = this;
- state->switch_state.labels_ht = hash_table_ctor(0, hash_table_pointer_hash,
- hash_table_pointer_compare);
+ state->switch_state.labels_ht =
+ _mesa_hash_table_create(NULL, key_contents,
+ compare_case_value);
state->switch_state.previous_default = NULL;
/* Initalize is_fallthru state to false.
instructions->push_tail(irif);
}
- hash_table_dtor(state->switch_state.labels_ht);
+ _mesa_hash_table_destroy(state->switch_state.labels_ht, NULL);
state->switch_state = saved;
*/
test_expression->set_is_lhs(true);
/* Cache value of test expression. */
- ir_rvalue *const test_val =
- test_expression->hir(instructions,
- state);
+ ir_rvalue *const test_val = test_expression->hir(instructions, state);
state->switch_state.test_var = new(ctx) ir_variable(test_val->type,
"switch_test_tmp",
/* Stuff a dummy value in to allow processing to continue. */
label_const = new(ctx) ir_constant(0);
} else {
- ast_expression *previous_label = (ast_expression *)
- hash_table_find(state->switch_state.labels_ht,
- (void *)(uintptr_t)label_const->value.u[0]);
+ hash_entry *entry =
+ _mesa_hash_table_search(state->switch_state.labels_ht,
+ (void *)(uintptr_t)&label_const->value.u[0]);
- if (previous_label) {
+ if (entry) {
+ ast_expression *previous_label = (ast_expression *) entry->data;
YYLTYPE loc = this->test_value->get_location();
_mesa_glsl_error(& loc, state, "duplicate case value");
loc = previous_label->get_location();
_mesa_glsl_error(& loc, state, "this is the previous case label");
} else {
- hash_table_insert(state->switch_state.labels_ht,
- this->test_value,
- (void *)(uintptr_t)label_const->value.u[0]);
+ _mesa_hash_table_insert(state->switch_state.labels_ht,
+ (void *)(uintptr_t)&label_const->value.u[0],
+ this->test_value);
}
}
ir_variable_mode var_mode,
ast_type_qualifier *layout,
unsigned block_stream,
+ unsigned block_xfb_buffer,
+ unsigned block_xfb_offset,
unsigned expl_location,
unsigned expl_align)
{
* the types to HIR. This ensures that structure definitions embedded in
* other structure definitions or in interface blocks are processed.
*/
- glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field,
- decl_count);
+ glsl_struct_field *const fields = rzalloc_array(state, glsl_struct_field,
+ decl_count);
bool first_member = true;
bool first_member_has_explicit_location = false;
}
}
+ int xfb_buffer;
+ unsigned explicit_xfb_buffer = 0;
+ if (qual->flags.q.explicit_xfb_buffer) {
+ unsigned qual_xfb_buffer;
+ if (process_qualifier_constant(state, &loc, "xfb_buffer",
+ qual->xfb_buffer, &qual_xfb_buffer)) {
+ explicit_xfb_buffer = 1;
+ if (qual_xfb_buffer != block_xfb_buffer)
+ _mesa_glsl_error(&loc, state, "xfb_buffer layout qualifier on "
+ "interface block member does not match "
+ "the interface block (%u vs %u)",
+ qual_xfb_buffer, block_xfb_buffer);
+ }
+ xfb_buffer = (int) qual_xfb_buffer;
+ } else {
+ if (layout)
+ explicit_xfb_buffer = layout->flags.q.explicit_xfb_buffer;
+ xfb_buffer = (int) block_xfb_buffer;
+ }
+
+ int xfb_stride = -1;
+ if (qual->flags.q.explicit_xfb_stride) {
+ unsigned qual_xfb_stride;
+ if (process_qualifier_constant(state, &loc, "xfb_stride",
+ qual->xfb_stride, &qual_xfb_stride)) {
+ xfb_stride = (int) qual_xfb_stride;
+ }
+ }
+
if (qual->flags.q.uniform && qual->has_interpolation()) {
_mesa_glsl_error(&loc, state,
"interpolation qualifiers cannot be used "
fields[i].type = field_type;
fields[i].name = decl->identifier;
fields[i].interpolation =
- interpret_interpolation_qualifier(qual, var_mode, state, &loc);
+ interpret_interpolation_qualifier(qual, field_type,
+ var_mode, state, &loc);
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;
fields[i].precision = qual->precision;
+ fields[i].offset = -1;
+ fields[i].explicit_xfb_buffer = explicit_xfb_buffer;
+ fields[i].xfb_buffer = xfb_buffer;
+ fields[i].xfb_stride = xfb_stride;
if (qual->flags.q.explicit_location) {
unsigned qual_location;
if (process_qualifier_constant(state, &loc, "location",
qual->location, &qual_location)) {
- fields[i].location = VARYING_SLOT_VAR0 + qual_location;
+ fields[i].location = qual_location +
+ (fields[i].patch ? VARYING_SLOT_PATCH0 : VARYING_SLOT_VAR0);
expl_location = fields[i].location +
fields[i].type->count_attribute_slots(false);
}
"with std430 and std140 layouts");
}
}
- } else {
- fields[i].offset = -1;
}
if (qual->flags.q.explicit_align || expl_align != 0) {
fields[i].offset = glsl_align(offset, expl_align);
next_offset = glsl_align(fields[i].offset + size, align);
}
- }
-
- if (!qual->flags.q.explicit_offset) {
+ } else if (!qual->flags.q.explicit_offset) {
if (align != 0 && size != 0)
next_offset = glsl_align(next_offset + size, align);
}
+ /* From the ARB_enhanced_layouts spec:
+ *
+ * "The given offset applies to the first component of the first
+ * member of the qualified entity. Then, within the qualified
+ * entity, subsequent components are each assigned, in order, to
+ * the next available offset aligned to a multiple of that
+ * component's size. Aggregate types are flattened down to the
+ * component level to get this sequence of components."
+ */
+ if (qual->flags.q.explicit_xfb_offset) {
+ unsigned xfb_offset;
+ if (process_qualifier_constant(state, &loc, "xfb_offset",
+ qual->offset, &xfb_offset)) {
+ fields[i].offset = xfb_offset;
+ block_xfb_offset = fields[i].offset +
+ MAX2(xfb_stride, (int) (4 * field_type->component_slots()));
+ }
+ } else {
+ if (layout && layout->flags.q.explicit_xfb_offset) {
+ unsigned align = field_type->is_64bit() ? 8 : 4;
+ fields[i].offset = glsl_align(block_xfb_offset, align);
+ block_xfb_offset +=
+ MAX2(xfb_stride, (int) (4 * field_type->component_slots()));
+ }
+ }
+
/* Propogate row- / column-major information down the fields of the
* structure or interface block. Structures need this data because
* the structure may contain a structure that contains ... a matrix
* that need the proper layout.
*/
- if (is_interface &&
+ if (is_interface && layout &&
(layout->flags.q.uniform || layout->flags.q.buffer) &&
(field_type->without_array()->is_matrix()
|| field_type->without_array()->is_record())) {
ir_var_auto,
layout,
0, /* for interface only */
+ 0, /* for interface only */
+ 0, /* for interface only */
expl_location,
0 /* for interface only */);
glsl_type::get_record_instance(fields, decl_count, this->name);
if (!state->symbols->add_type(name, t)) {
- _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
+ const glsl_type *match = state->symbols->get_type(name);
+ /* allow struct matching for desktop GL - older UE4 does this */
+ if (match != NULL && state->is_version(130, 0) && match->record_compare(t, false))
+ _mesa_glsl_warning(& loc, state, "struct `%s' previously defined", name);
+ else
+ _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
} else {
const glsl_type **s = reralloc(state, state->user_structures,
const glsl_type *,
return false;
}
+static void
+apply_memory_qualifiers(ir_variable *var, glsl_struct_field field)
+{
+ var->data.image_read_only = field.image_read_only;
+ var->data.image_write_only = field.image_write_only;
+ var->data.image_coherent = field.image_coherent;
+ var->data.image_volatile = field.image_volatile;
+ var->data.image_restrict = field.image_restrict;
+}
+
ir_rvalue *
ast_interface_block::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
this->block_name);
}
- if (!this->layout.flags.q.buffer &&
- this->layout.flags.q.std430) {
- _mesa_glsl_error(&loc, state,
- "std430 storage block layout qualifier is supported "
- "only for shader storage blocks");
+ /* Validate qualifiers:
+ *
+ * - Layout Qualifiers as per the table in Section 4.4
+ * ("Layout Qualifiers") of the GLSL 4.50 spec.
+ *
+ * - Memory Qualifiers as per Section 4.10 ("Memory Qualifiers") of the
+ * GLSL 4.50 spec:
+ *
+ * "Additionally, memory qualifiers may also be used in the declaration
+ * of shader storage blocks"
+ *
+ * Note the table in Section 4.4 says std430 is allowed on both uniform and
+ * buffer blocks however Section 4.4.5 (Uniform and Shader Storage Block
+ * Layout Qualifiers) of the GLSL 4.50 spec says:
+ *
+ * "The std430 qualifier is supported only for shader storage blocks;
+ * using std430 on a uniform block will result in a compile-time error."
+ */
+ ast_type_qualifier allowed_blk_qualifiers;
+ allowed_blk_qualifiers.flags.i = 0;
+ if (this->layout.flags.q.buffer || this->layout.flags.q.uniform) {
+ allowed_blk_qualifiers.flags.q.shared = 1;
+ allowed_blk_qualifiers.flags.q.packed = 1;
+ allowed_blk_qualifiers.flags.q.std140 = 1;
+ allowed_blk_qualifiers.flags.q.row_major = 1;
+ allowed_blk_qualifiers.flags.q.column_major = 1;
+ allowed_blk_qualifiers.flags.q.explicit_align = 1;
+ allowed_blk_qualifiers.flags.q.explicit_binding = 1;
+ if (this->layout.flags.q.buffer) {
+ allowed_blk_qualifiers.flags.q.buffer = 1;
+ allowed_blk_qualifiers.flags.q.std430 = 1;
+ allowed_blk_qualifiers.flags.q.coherent = 1;
+ allowed_blk_qualifiers.flags.q._volatile = 1;
+ allowed_blk_qualifiers.flags.q.restrict_flag = 1;
+ allowed_blk_qualifiers.flags.q.read_only = 1;
+ allowed_blk_qualifiers.flags.q.write_only = 1;
+ } else {
+ allowed_blk_qualifiers.flags.q.uniform = 1;
+ }
+ } else {
+ /* Interface block */
+ assert(this->layout.flags.q.in || this->layout.flags.q.out);
+
+ allowed_blk_qualifiers.flags.q.explicit_location = 1;
+ if (this->layout.flags.q.out) {
+ allowed_blk_qualifiers.flags.q.out = 1;
+ if (state->stage == MESA_SHADER_GEOMETRY ||
+ state->stage == MESA_SHADER_TESS_CTRL ||
+ state->stage == MESA_SHADER_TESS_EVAL ||
+ state->stage == MESA_SHADER_VERTEX ) {
+ allowed_blk_qualifiers.flags.q.explicit_xfb_offset = 1;
+ allowed_blk_qualifiers.flags.q.explicit_xfb_buffer = 1;
+ allowed_blk_qualifiers.flags.q.xfb_buffer = 1;
+ allowed_blk_qualifiers.flags.q.explicit_xfb_stride = 1;
+ allowed_blk_qualifiers.flags.q.xfb_stride = 1;
+ if (state->stage == MESA_SHADER_GEOMETRY) {
+ allowed_blk_qualifiers.flags.q.stream = 1;
+ allowed_blk_qualifiers.flags.q.explicit_stream = 1;
+ }
+ if (state->stage == MESA_SHADER_TESS_CTRL) {
+ allowed_blk_qualifiers.flags.q.patch = 1;
+ }
+ }
+ } else {
+ allowed_blk_qualifiers.flags.q.in = 1;
+ if (state->stage == MESA_SHADER_TESS_EVAL) {
+ allowed_blk_qualifiers.flags.q.patch = 1;
+ }
+ }
}
+ this->layout.validate_flags(&loc, state, allowed_blk_qualifiers,
+ "invalid qualifier for block",
+ this->block_name);
+
/* 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.
return NULL;
}
+ unsigned qual_xfb_buffer;
+ if (!process_qualifier_constant(state, &loc, "xfb_buffer",
+ layout.xfb_buffer, &qual_xfb_buffer) ||
+ !validate_xfb_buffer_qualifier(&loc, state, qual_xfb_buffer)) {
+ return NULL;
+ }
+
+ unsigned qual_xfb_offset;
+ if (layout.flags.q.explicit_xfb_offset) {
+ if (!process_qualifier_constant(state, &loc, "xfb_offset",
+ layout.offset, &qual_xfb_offset)) {
+ return NULL;
+ }
+ }
+
+ unsigned qual_xfb_stride;
+ if (layout.flags.q.explicit_xfb_stride) {
+ if (!process_qualifier_constant(state, &loc, "xfb_stride",
+ layout.xfb_stride, &qual_xfb_stride)) {
+ return NULL;
+ }
+ }
+
unsigned expl_location = 0;
if (layout.flags.q.explicit_location) {
if (!process_qualifier_constant(state, &loc, "location",
layout.location, &expl_location)) {
return NULL;
} else {
- expl_location = VARYING_SLOT_VAR0 + expl_location;
+ expl_location += this->layout.flags.q.patch ? VARYING_SLOT_PATCH0
+ : VARYING_SLOT_VAR0;
}
}
var_mode,
&this->layout,
qual_stream,
+ qual_xfb_buffer,
+ qual_xfb_offset,
expl_location,
expl_align);
earlier_per_vertex->fields.structure[j].precision;
fields[i].explicit_xfb_buffer =
earlier_per_vertex->fields.structure[j].explicit_xfb_buffer;
+ fields[i].xfb_buffer =
+ earlier_per_vertex->fields.structure[j].xfb_buffer;
+ fields[i].xfb_stride =
+ earlier_per_vertex->fields.structure[j].xfb_stride;
}
}
glsl_type::get_interface_instance(fields,
num_variables,
packing,
+ matrix_layout ==
+ GLSL_MATRIX_LAYOUT_ROW_MAJOR,
this->block_name);
+ unsigned component_size = block_type->contains_double() ? 8 : 4;
+ int xfb_offset =
+ layout.flags.q.explicit_xfb_offset ? (int) qual_xfb_offset : -1;
+ validate_xfb_offset_qualifier(&loc, state, xfb_offset, block_type,
+ component_size);
+
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' "
_mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays");
} else if ((state->stage == MESA_SHADER_TESS_CTRL ||
state->stage == MESA_SHADER_TESS_EVAL) &&
+ !this->layout.flags.q.patch &&
this->array_specifier == NULL &&
var_mode == ir_var_shader_in) {
_mesa_glsl_error(&loc, state, "per-vertex tessellation shader inputs must be arrays");
} else if (state->stage == MESA_SHADER_TESS_CTRL &&
+ !this->layout.flags.q.patch &&
this->array_specifier == NULL &&
var_mode == ir_var_shader_out) {
_mesa_glsl_error(&loc, state, "tessellation control shader outputs must be arrays");
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
var->data.read_only = true;
+ var->data.patch = this->layout.flags.q.patch;
+
if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
handle_geometry_shader_input_decl(state, loc, var);
else if ((state->stage == MESA_SHADER_TESS_CTRL ||
handle_tess_ctrl_shader_output_decl(state, loc, var);
for (unsigned i = 0; i < num_variables; i++) {
- if (fields[i].type->is_unsized_array()) {
- if (var_mode == ir_var_shader_storage) {
- if (i != (num_variables - 1)) {
- _mesa_glsl_error(&loc, state, "unsized array `%s' definition: "
- "only last member of a shader storage block "
- "can be defined as unsized array",
- fields[i].name);
- }
- } else {
- /* From GLSL ES 3.10 spec, section 4.1.9 "Arrays":
- *
- * "If an array is declared as the last member of a shader storage
- * block and the size is not specified at compile-time, it is
- * sized at run-time. In all other cases, arrays are sized only
- * at compile-time."
- */
- if (state->es_shader) {
- _mesa_glsl_error(&loc, state, "unsized array `%s' definition: "
- "only last member of a shader storage block "
- "can be defined as unsized array",
- fields[i].name);
- }
- }
- }
+ if (var->data.mode == ir_var_shader_storage)
+ apply_memory_qualifiers(var, fields[i]);
}
if (ir_variable *earlier =
var->data.patch = fields[i].patch;
var->data.stream = qual_stream;
var->data.location = fields[i].location;
+
if (fields[i].location != -1)
var->data.explicit_location = true;
+
+ var->data.explicit_xfb_buffer = fields[i].explicit_xfb_buffer;
+ var->data.xfb_buffer = fields[i].xfb_buffer;
+
+ if (fields[i].offset != -1)
+ var->data.explicit_xfb_offset = true;
+ var->data.offset = fields[i].offset;
+
var->init_interface_type(block_type);
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
var->data.matrix_layout = fields[i].matrix_layout;
}
- 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;
- var->data.image_coherent = fields[i].image_coherent;
- var->data.image_volatile = fields[i].image_volatile;
- var->data.image_restrict = fields[i].image_restrict;
- }
+ if (var->data.mode == ir_var_shader_storage)
+ apply_memory_qualifiers(var, fields[i]);
/* Examine var name here since var may get deleted in the next call */
bool var_is_gl_id = is_gl_identifier(var->name);
if (redeclaring_per_vertex) {
- ir_variable *earlier =
+ bool is_redeclaration;
+ ir_variable *declared_var =
get_variable_being_redeclared(var, loc, state,
- true /* allow_all_redeclarations */);
- if (!var_is_gl_id || earlier == NULL) {
+ true /* allow_all_redeclarations */,
+ &is_redeclaration);
+ if (!var_is_gl_id || !is_redeclaration) {
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex can only "
"include built-in variables");
- } else if (earlier->data.how_declared == ir_var_declared_normally) {
+ } else if (declared_var->data.how_declared == ir_var_declared_normally) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared",
- earlier->name);
+ declared_var->name);
} else {
- earlier->data.how_declared = ir_var_declared_in_block;
- earlier->reinit_interface_type(block_type);
+ declared_var->data.how_declared = ir_var_declared_in_block;
+ declared_var->reinit_interface_type(block_type);
}
continue;
}
}
if (var->type->is_unsized_array()) {
- if (var->is_in_shader_storage_block()) {
- if (!is_unsized_array_last_element(var)) {
- _mesa_glsl_error(&loc, state, "unsized array `%s' definition: "
- "only last member of a shader storage block "
- "can be defined as unsized array",
- var->name);
- }
+ if (var->is_in_shader_storage_block() &&
+ is_unsized_array_last_element(var)) {
var->data.from_ssbo_unsized_array = true;
} else {
/* From GLSL ES 3.10 spec, section 4.1.9 "Arrays":
- *
- * "If an array is declared as the last member of a shader storage
- * block and the size is not specified at compile-time, it is
- * sized at run-time. In all other cases, arrays are sized only
- * at compile-time."
- */
+ *
+ * "If an array is declared as the last member of a shader storage
+ * block and the size is not specified at compile-time, it is
+ * sized at run-time. In all other cases, arrays are sized only
+ * at compile-time."
+ *
+ * In desktop GLSL it is allowed to have unsized-arrays that are
+ * not last, as long as we can determine that they are implicitly
+ * sized.
+ */
if (state->es_shader) {
- _mesa_glsl_error(&loc, state, "unsized array `%s' definition: "
- "only last member of a shader storage block "
- "can be defined as unsized array",
- var->name);
+ _mesa_glsl_error(&loc, state, "unsized array `%s' "
+ "definition: only last member of a shader "
+ "storage block can be defined as unsized "
+ "array", fields[i].name);
}
}
}
ir_rvalue *
ast_tcs_output_layout::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
+ struct _mesa_glsl_parse_state *state)
{
YYLTYPE loc = this->get_location();
*/
if (state->tcs_output_size != 0 && state->tcs_output_size != num_vertices) {
_mesa_glsl_error(&loc, state,
- "this tessellation control shader output layout "
- "specifies %u vertices, but a previous output "
- "is declared with size %u",
- num_vertices, state->tcs_output_size);
+ "this tessellation control shader output layout "
+ "specifies %u vertices, but a previous output "
+ "is declared with size %u",
+ num_vertices, state->tcs_output_size);
return NULL;
}
foreach_in_list (ir_instruction, node, instructions) {
ir_variable *var = node->as_variable();
if (var == NULL || var->data.mode != ir_var_shader_out)
- continue;
+ continue;
/* Note: Not all tessellation control shader output are arrays. */
if (!var->type->is_unsized_array() || var->data.patch)
continue;
- if (var->data.max_array_access >= num_vertices) {
- _mesa_glsl_error(&loc, state,
- "this tessellation control shader output layout "
- "specifies %u vertices, but an access to element "
- "%u of output `%s' already exists", num_vertices,
- var->data.max_array_access, var->name);
+ if (var->data.max_array_access >= (int)num_vertices) {
+ _mesa_glsl_error(&loc, state,
+ "this tessellation control shader output layout "
+ "specifies %u vertices, but an access to element "
+ "%u of output `%s' already exists", num_vertices,
+ var->data.max_array_access, var->name);
} else {
- var->type = glsl_type::get_array_instance(var->type->fields.array,
- num_vertices);
+ var->type = glsl_type::get_array_instance(var->type->fields.array,
+ num_vertices);
}
}
{
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->in_qualifier->prim_type != this->prim_type) {
- _mesa_glsl_error(&loc, state,
- "geometry shader input layout does not match"
- " previous declaration");
- return NULL;
- }
+ /* Should have been prevented by the parser. */
+ assert(!state->gs_input_prim_type_specified
+ || state->in_qualifier->prim_type == this->prim_type);
/* If any shader inputs occurred before this declaration and specified an
* array size, make sure the size they specified is consistent with the
*/
if (var->type->is_unsized_array()) {
- if (var->data.max_array_access >= num_vertices) {
+ if (var->data.max_array_access >= (int)num_vertices) {
_mesa_glsl_error(&loc, state,
"this geometry shader input layout implies %u"
" vertices, but an access to element %u of input"
}
}
+ /* The ARB_compute_variable_group_size spec says:
+ *
+ * If a compute shader including a *local_size_variable* qualifier also
+ * declares a fixed local group size using the *local_size_x*,
+ * *local_size_y*, or *local_size_z* qualifiers, a compile-time error
+ * results
+ */
+ if (state->cs_input_local_size_variable_specified) {
+ _mesa_glsl_error(&loc, state,
+ "compute shader can't include both a variable and a "
+ "fixed local group size");
+ return NULL;
+ }
+
state->cs_input_local_size_specified = true;
for (int i = 0; i < 3; i++)
state->cs_input_local_size[i] = qual_local_size[i];
gl_FragColor_assigned = true;
else if (strcmp(var->name, "gl_FragData") == 0)
gl_FragData_assigned = true;
- else if (strcmp(var->name, "gl_SecondaryFragColorEXT") == 0)
+ else if (strcmp(var->name, "gl_SecondaryFragColorEXT") == 0)
gl_FragSecondaryColor_assigned = true;
- else if (strcmp(var->name, "gl_SecondaryFragDataEXT") == 0)
+ else if (strcmp(var->name, "gl_SecondaryFragDataEXT") == 0)
gl_FragSecondaryData_assigned = true;
else if (!is_gl_identifier(var->name)) {
if (state->stage == MESA_SHADER_FRAGMENT &&