state->toplevel_ir = instructions;
state->gs_input_prim_type_specified = false;
+ state->cs_input_local_size_specified = false;
/* Section 4.2 of the GLSL 1.20 specification states:
* "The built-in functions are scoped in a scope outside the global scope
{
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 expr = lhs->as_expression();
+ ir_expression *const lhs_expr = lhs->as_expression();
- if (unlikely(expr->operation == ir_binop_vector_extract)) {
+ if (unlikely(lhs_expr->operation == ir_binop_vector_extract)) {
ir_rvalue *new_rhs =
validate_assignment(state, lhs_loc, lhs->type,
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,
- expr->operands[0]->type,
- expr->operands[0],
+ lhs_expr->operands[0]->type,
+ lhs_expr->operands[0],
new_rhs,
- expr->operands[1]);
- lhs = expr->operands[0]->clone(ctx, NULL);
+ extract_channel);
+ lhs = lhs_expr->operands[0]->clone(ctx, NULL);
}
}
}
rhs->type->array_size());
d->type = var->type;
}
- mark_whole_array_access(rhs);
- mark_whole_array_access(lhs);
+ if (lhs->type->is_array()) {
+ mark_whole_array_access(rhs);
+ mark_whole_array_access(lhs);
+ }
}
/* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
if (!error_emitted)
instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var));
+ if (extract_channel) {
+ return new(ctx) ir_expression(ir_binop_vector_extract,
+ new(ctx) ir_dereference_variable(var),
+ extract_channel->clone(ctx, NULL));
+ }
return new(ctx) ir_dereference_variable(var);
}
case GLSL_TYPE_ERROR:
case GLSL_TYPE_VOID:
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_ATOMIC_UINT:
/* I assume a comparison of a struct containing a sampler just
return NULL;
}
+/**
+ * Evaluate the given exec_node (which should be an ast_node representing
+ * a single array dimension) and return its integer value.
+ */
+static const unsigned
+process_array_size(exec_node *node,
+ struct _mesa_glsl_parse_state *state)
+{
+ exec_list dummy_instructions;
+
+ ast_node *array_size = exec_node_data(ast_node, node, link);
+ ir_rvalue *const ir = array_size->hir(& dummy_instructions,
+ state);
+ YYLTYPE loc = array_size->get_location();
+
+ if (ir == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "array size could not be resolved");
+ return 0;
+ }
+
+ if (!ir->type->is_integer()) {
+ _mesa_glsl_error(& loc, state,
+ "array size must be integer type");
+ return 0;
+ }
+
+ if (!ir->type->is_scalar()) {
+ _mesa_glsl_error(& loc, state,
+ "array size must be scalar type");
+ return 0;
+ }
+
+ ir_constant *const size = ir->constant_expression_value();
+ if (size == NULL) {
+ _mesa_glsl_error(& loc, state, "array size must be a "
+ "constant valued expression");
+ return 0;
+ }
+
+ if (size->value.i[0] <= 0) {
+ _mesa_glsl_error(& loc, state, "array size must be > 0");
+ return 0;
+ }
+
+ assert(size->type == ir->type);
+
+ /* If the array size is const (and we've verified that
+ * it is) then no instructions should have been emitted
+ * when we converted it to HIR. If they were emitted,
+ * then either the array size isn't const after all, or
+ * we are emitting unnecessary instructions.
+ */
+ assert(dummy_instructions.is_empty());
+
+ return size->value.u[0];
+}
static const glsl_type *
-process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
- struct _mesa_glsl_parse_state *state)
+process_array_type(YYLTYPE *loc, const glsl_type *base,
+ ast_array_specifier *array_specifier,
+ struct _mesa_glsl_parse_state *state)
{
- unsigned length = 0;
+ const glsl_type *array_type = base;
- if (base == NULL)
- return glsl_type::error_type;
+ if (array_specifier != NULL) {
+ if (base->is_array()) {
- /* From page 19 (page 25) of the GLSL 1.20 spec:
- *
- * "Only one-dimensional arrays may be declared."
- */
- if (base->is_array()) {
- _mesa_glsl_error(loc, state,
- "invalid array of `%s' (only one-dimensional arrays "
- "may be declared)",
- base->name);
- return glsl_type::error_type;
- }
+ /* From page 19 (page 25) of the GLSL 1.20 spec:
+ *
+ * "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 (array_size != NULL) {
- exec_list dummy_instructions;
- ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
- YYLTYPE loc = array_size->get_location();
+ if (base->length == 0) {
+ _mesa_glsl_error(loc, state,
+ "only the outermost array dimension can "
+ "be unsized",
+ base->name);
+ return glsl_type::error_type;
+ }
+ }
- if (ir != NULL) {
- if (!ir->type->is_integer()) {
- _mesa_glsl_error(& loc, state, "array size must be integer type");
- } else if (!ir->type->is_scalar()) {
- _mesa_glsl_error(& loc, state, "array size must be scalar type");
- } else {
- ir_constant *const size = ir->constant_expression_value();
-
- if (size == NULL) {
- _mesa_glsl_error(& loc, state, "array size must be a "
- "constant valued expression");
- } else if (size->value.i[0] <= 0) {
- _mesa_glsl_error(& loc, state, "array size must be > 0");
- } else {
- assert(size->type == ir->type);
- length = size->value.u[0];
-
- /* If the array size is const (and we've verified that
- * it is) then no instructions should have been emitted
- * when we converted it to HIR. If they were emitted,
- * then either the array size isn't const after all, or
- * we are emitting unnecessary instructions.
- */
- assert(dummy_instructions.is_empty());
- }
- }
+ for (exec_node *node = array_specifier->array_dimensions.tail_pred;
+ !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);
}
+
+ if (array_specifier->is_unsized_array)
+ array_type = glsl_type::get_array_instance(array_type, 0);
}
- const glsl_type *array_type = glsl_type::get_array_instance(base, length);
- return array_type != NULL ? array_type : glsl_type::error_type;
+ return array_type;
}
type = state->symbols->get_type(this->type_name);
*name = this->type_name;
- if (this->is_array) {
- YYLTYPE loc = this->get_location();
- type = process_array_type(&loc, type, this->array_size, state);
- }
+ YYLTYPE loc = this->get_location();
+ type = process_array_type(&loc, type, this->array_specifier, state);
return type;
}
if (type->base_type == GLSL_TYPE_FLOAT
&& state->es_shader
- && state->target == fragment_shader
+ && state->stage == MESA_SHADER_FRAGMENT
&& this->qualifier.precision == ast_precision_none
&& state->symbols->get_variable("#default precision") == NULL) {
YYLTYPE loc = this->get_location();
* this function will produce undefined results.
*/
static bool
-is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target)
+is_varying_var(ir_variable *var, gl_shader_stage target)
{
switch (target) {
- case vertex_shader:
+ case MESA_SHADER_VERTEX:
return var->data.mode == ir_var_shader_out;
- case fragment_shader:
+ case MESA_SHADER_FRAGMENT:
return var->data.mode == ir_var_shader_in;
default:
return var->data.mode == ir_var_shader_out || var->data.mode == ir_var_shader_in;
* with an array of size N, all elements of the array from binding
* through binding + N - 1 must be within this range."
*/
- unsigned limit = 0;
- switch (state->target) {
- case vertex_shader:
- limit = ctx->Const.VertexProgram.MaxTextureImageUnits;
- break;
- case geometry_shader:
- limit = ctx->Const.GeometryProgram.MaxTextureImageUnits;
- break;
- case fragment_shader:
- limit = ctx->Const.FragmentProgram.MaxTextureImageUnits;
- break;
- }
+ unsigned limit = ctx->Const.Program[state->stage].MaxTextureImageUnits;
if (max_index >= limit) {
_mesa_glsl_error(loc, state, "layout(binding = %d) for %d samplers "
}
- if ((state->target == vertex_shader && mode == ir_var_shader_in) ||
- (state->target == fragment_shader && mode == ir_var_shader_out)) {
+ 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",
* In the fragment shader only shader outputs can be given explicit
* locations.
*/
- switch (state->target) {
- case vertex_shader:
+ switch (state->stage) {
+ case MESA_SHADER_VERTEX:
if (var->data.mode == ir_var_shader_in) {
if (!state->check_explicit_attrib_location_allowed(loc, var))
return;
fail = true;
break;
- case geometry_shader:
+ case MESA_SHADER_GEOMETRY:
_mesa_glsl_error(loc, state,
"geometry shader variables cannot be given "
"explicit locations");
return;
- case fragment_shader:
+ case MESA_SHADER_FRAGMENT:
if (var->data.mode == ir_var_shader_out) {
if (!state->check_explicit_attrib_location_allowed(loc, var))
return;
fail = true;
break;
+
+ case MESA_SHADER_COMPUTE:
+ _mesa_glsl_error(loc, state,
+ "compute shader variables cannot be given "
+ "explicit locations");
+ return;
};
if (fail) {
_mesa_glsl_error(loc, state,
"%s cannot be given an explicit location in %s shader",
mode_string(var),
- _mesa_glsl_shader_target_name(state->target));
+ _mesa_shader_stage_to_string(state->stage));
} else {
var->data.explicit_location = true;
* ensures that negative values stay negative.
*/
if (qual->location >= 0) {
- var->data.location = (state->target == vertex_shader)
+ var->data.location = (state->stage == MESA_SHADER_VERTEX)
? (qual->location + VERT_ATTRIB_GENERIC0)
: (qual->location + FRAG_RESULT_DATA0);
} else {
return;
}
+static void
+apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
+{
+ const glsl_type *base_type =
+ (var->type->is_array() ? var->type->element_type() : var->type);
+
+ 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");
+ }
+
+ 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_flag |= qual->flags.q.restrict_flag;
+ var->data.read_only = true;
+
+ 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");
+ }
+
+ if (qual->image_base_type != base_type->sampler_type) {
+ _mesa_glsl_error(loc, state, "format qualifier doesn't match the "
+ "base data type of the image");
+ }
+
+ var->data.image.format = qual->image_format;
+ } else {
+ if (var->data.mode == ir_var_uniform && !qual->flags.q.write_only) {
+ _mesa_glsl_error(loc, state, "uniforms not qualified with "
+ "`writeonly' must have a format layout "
+ "qualifier");
+ }
+
+ var->data.image.format = GL_NONE;
+ }
+ }
+}
+
static void
apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
ir_variable *var,
if (qual->flags.q.constant || qual->flags.q.attribute
|| qual->flags.q.uniform
- || (qual->flags.q.varying && (state->target == fragment_shader)))
+ || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT)))
var->data.read_only = 1;
if (qual->flags.q.centroid)
if (qual->flags.q.sample)
var->data.sample = 1;
- if (qual->flags.q.attribute && state->target != vertex_shader) {
+ if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) {
var->type = glsl_type::error_type;
_mesa_glsl_error(loc, state,
"`attribute' variables may not be declared in the "
"%s shader",
- _mesa_glsl_shader_target_name(state->target));
+ _mesa_shader_stage_to_string(state->stage));
}
/* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says:
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->target == fragment_shader)))
+ || (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.varying && (state->target == vertex_shader))
+ else if (qual->flags.q.varying && (state->stage == MESA_SHADER_VERTEX))
var->data.mode = ir_var_shader_out;
else if (qual->flags.q.uniform)
var->data.mode = ir_var_uniform;
- if (!is_parameter && is_varying_var(var, state->target)) {
+ 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) {
+ _mesa_glsl_error(loc, state,
+ "user-defined input and output variables are not "
+ "permitted in compute shaders");
+ }
+
/* This variable is being used to link data between shader stages (in
* pre-glsl-1.30 parlance, it's a "varying"). Check that it has a type
* that is allowed for such purposes.
}
if (state->all_invariant && (state->current_function == NULL)) {
- switch (state->target) {
- case vertex_shader:
+ switch (state->stage) {
+ case MESA_SHADER_VERTEX:
if (var->data.mode == ir_var_shader_out)
var->data.invariant = true;
break;
- case geometry_shader:
+ 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 fragment_shader:
+ 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;
}
}
if (qual->flags.q.row_major || qual->flags.q.column_major) {
validate_matrix_layout_for_type(state, loc, var->type, var);
}
+
+ if (var->type->contains_image())
+ apply_image_qualifier_to_variable(qual, var, state, loc);
}
/**
"cannot initialize uniforms");
}
- if (var->type->is_sampler()) {
+ /* From section 4.1.7 of the GLSL 4.40 spec:
+ *
+ * "Opaque variables [...] are initialized only through the
+ * OpenGL API; they cannot be declared with an initializer in a
+ * shader."
+ */
+ if (var->type->contains_opaque()) {
_mesa_glsl_error(& initializer_loc, state,
- "cannot initialize samplers");
+ "cannot initialize opaque variable");
}
if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) {
_mesa_glsl_error(& initializer_loc, state,
"cannot initialize %s shader input / %s",
- _mesa_glsl_shader_target_name(state->target),
- (state->target == vertex_shader)
+ _mesa_shader_stage_to_string(state->stage),
+ (state->stage == MESA_SHADER_VERTEX)
? "attribute" : "varying");
}
+ /* If the initializer is an ast_aggregate_initializer, recursively store
+ * type information from the LHS into it, so that its hir() function can do
+ * type checking.
+ */
+ if (decl->initializer->oper == ast_aggregate)
+ _mesa_ast_set_aggregate_type(var->type, decl->initializer);
+
ir_dereference *const lhs = new(state) ir_dereference_variable(var);
ir_rvalue *rhs = decl->initializer->hir(initializer_instructions,
state);
}
foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
- assert(!decl->is_array);
- assert(decl->array_size == NULL);
+ assert(decl->array_specifier == NULL);
assert(decl->initializer == NULL);
ir_variable *const earlier =
_mesa_glsl_error(& loc, state,
"undeclared variable `%s' cannot be marked "
"invariant", decl->identifier);
- } else if ((state->target == vertex_shader)
+ } else if ((state->stage == MESA_SHADER_VERTEX)
&& (earlier->data.mode != ir_var_shader_out)) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, vertex shader "
"outputs only", decl->identifier);
- } else if ((state->target == fragment_shader)
+ } else if ((state->stage == MESA_SHADER_FRAGMENT)
&& (earlier->data.mode != ir_var_shader_in)) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, fragment shader "
continue;
}
- if (decl->is_array) {
- var_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
- if (var_type->is_error())
- continue;
- } else {
- var_type = decl_type;
- }
+ var_type = process_array_type(&loc, decl_type, decl->array_specifier,
+ state);
var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
& loc, false);
if (this->type->qualifier.flags.q.invariant) {
- if ((state->target == vertex_shader) &&
+ if ((state->stage == MESA_SHADER_VERTEX) &&
var->data.mode != ir_var_shader_out) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, vertex shader "
"outputs only", var->name);
- } else if ((state->target == fragment_shader) &&
+ } else if ((state->stage == MESA_SHADER_FRAGMENT) &&
var->data.mode != ir_var_shader_in) {
/* FINISHME: Note that this doesn't work for invariant on
* a function signature inval
} else if (var->data.mode == ir_var_shader_in) {
var->data.read_only = true;
- if (state->target == vertex_shader) {
+ if (state->stage == MESA_SHADER_VERTEX) {
bool error_emitted = false;
/* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
* vectors. Vertex shader inputs cannot be arrays or
* structures."
*/
- const glsl_type *check_type = var->type->is_array()
- ? var->type->fields.array : var->type;
+ const glsl_type *check_type = var->type;
+ while (check_type->is_array())
+ check_type = check_type->element_type();
switch (check_type->base_type) {
case GLSL_TYPE_FLOAT:
"cannot have array type")) {
error_emitted = true;
}
- } else if (state->target == geometry_shader) {
+ } else if (state->stage == MESA_SHADER_GEOMETRY) {
/* From section 4.3.4 (Inputs) of the GLSL 1.50 spec:
*
* Geometry shader input variables get the per-vertex values
if (state->is_version(130, 300) &&
var->type->contains_integer() &&
var->data.interpolation != INTERP_QUALIFIER_FLAT &&
- ((state->target == fragment_shader && var->data.mode == ir_var_shader_in)
- || (state->target == vertex_shader && var->data.mode == ir_var_shader_out
+ ((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->target == vertex_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'",
const char *i = this->type->qualifier.interpolation_string();
assert(i != NULL);
- switch (state->target) {
- case vertex_shader:
+ 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 fragment_shader:
+ case MESA_SHADER_FRAGMENT:
if (this->type->qualifier.flags.q.out) {
_mesa_glsl_error(&loc, state,
"qualifier '%s' cannot be applied to fragment "
if (state->is_version(130, 300)
&& this->type->qualifier.flags.q.centroid
&& this->type->qualifier.flags.q.in
- && state->target == vertex_shader) {
+ && state->stage == MESA_SHADER_VERTEX) {
_mesa_glsl_error(&loc, state,
"'centroid in' cannot be used in a vertex shader");
}
- if (state->target == vertex_shader
+ if (state->stage == MESA_SHADER_VERTEX
&& this->type->qualifier.flags.q.sample
&& this->type->qualifier.flags.q.in) {
* "It is an error to use auxiliary storage qualifiers or interpolation
* qualifiers on an output in a fragment shader."
*/
- if (state->target == fragment_shader &&
+ if (state->stage == MESA_SHADER_FRAGMENT &&
this->type->qualifier.flags.q.out &&
this->type->qualifier.has_auxiliary_storage()) {
_mesa_glsl_error(&loc, state,
", integer and sampler types");
}
- /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
+ /* From section 4.1.7 of the GLSL 4.40 spec:
*
- * "[Sampler types] can only be declared as function
- * parameters or uniform variables (see Section 4.3.5
- * "Uniform")".
+ * "[Opaque types] can only be declared as function
+ * parameters or uniform-qualified variables."
*/
- if (var_type->contains_sampler() &&
+ if (var_type->contains_opaque() &&
!this->type->qualifier.flags.q.uniform) {
- _mesa_glsl_error(&loc, state, "samplers must be declared uniform");
+ _mesa_glsl_error(&loc, state,
+ "opaque variables must be declared uniform");
}
/* Process the initializer and add its instructions to a temporary
/* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...)
* call already handled the "vec4[..] foo" case.
*/
- if (this->is_array) {
- type = process_array_type(&loc, type, this->array_size, state);
- }
+ type = process_array_type(&loc, type, this->array_specifier, state);
if (!type->is_error() && type->is_unsized_array()) {
_mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc,
true);
- /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
+ /* From section 4.1.7 of the GLSL 4.40 spec:
*
- * "Samplers cannot be treated as l-values; hence cannot be used
- * as out or inout function parameters, nor can they be assigned
- * into."
+ * "Opaque variables cannot be treated as l-values; hence cannot
+ * be used as out or inout function parameters, nor can they be
+ * assigned into."
*/
if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out)
- && type->contains_sampler()) {
- _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers");
+ && type->contains_opaque()) {
+ _mesa_glsl_error(&loc, state, "out and inout parameters cannot "
+ "contain opaque variables");
type = glsl_type::error_type;
}
"sized", name);
}
- /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
+ /* From section 4.1.7 of the GLSL 4.40 spec:
*
- * "[Sampler types] can only be declared as function parameters
- * or uniform variables (see Section 4.3.5 "Uniform")".
+ * "[Opaque types] can only be declared as function parameters
+ * or uniform-qualified variables."
*/
- if (return_type->contains_sampler()) {
+ if (return_type->contains_opaque()) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state,
- "function `%s' return type can't contain a sampler",
+ "function `%s' return type can't contain an opaque type",
name);
}
* Add these to the symbol table.
*/
state->symbols->push_scope();
- foreach_iter(exec_list_iterator, iter, signature->parameters) {
- ir_variable *const var = ((ir_instruction *) iter.get())->as_variable();
+ foreach_list(n, &signature->parameters) {
+ ir_variable *const var = ((ir_instruction *) n)->as_variable();
assert(var != NULL);
}
case ast_discard:
- if (state->target != fragment_shader) {
+ if (state->stage != MESA_SHADER_FRAGMENT) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state,
_mesa_glsl_error(& loc, state,
"break may only appear in a loop or a switch");
} else {
- /* For a loop, inline the for loop expression again,
- * since we don't know where near the end of
- * the loop body the normal copy of it
- * is going to be placed.
+ /* For a loop, inline the for loop expression again, since we don't
+ * know where near the end of the loop body the normal copy of it is
+ * going to be placed. Same goes for the condition for a do-while
+ * loop.
*/
if (state->loop_nesting_ast != NULL &&
- mode == ast_continue &&
- state->loop_nesting_ast->rest_expression) {
- state->loop_nesting_ast->rest_expression->hir(instructions,
- state);
- }
+ mode == ast_continue) {
+ if (state->loop_nesting_ast->rest_expression) {
+ state->loop_nesting_ast->rest_expression->hir(instructions,
+ state);
+ }
+ if (state->loop_nesting_ast->mode ==
+ ast_iteration_statement::ast_do_while) {
+ state->loop_nesting_ast->condition_to_hir(instructions, state);
+ }
+ }
if (state->switch_state.is_switch_innermost &&
mode == ast_break) {
}
void
-ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+ast_iteration_statement::condition_to_hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
void *ctx = state;
if (condition != NULL) {
ir_rvalue *const cond =
- condition->hir(& stmt->body_instructions, state);
+ condition->hir(instructions, state);
if ((cond == NULL)
|| !cond->type->is_boolean() || !cond->type->is_scalar()) {
new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
if_stmt->then_instructions.push_tail(break_stmt);
- stmt->body_instructions.push_tail(if_stmt);
+ instructions->push_tail(if_stmt);
}
}
}
state->switch_state.is_switch_innermost = false;
if (mode != ast_do_while)
- condition_to_hir(stmt, state);
+ condition_to_hir(&stmt->body_instructions, state);
if (body != NULL)
body->hir(& stmt->body_instructions, state);
rest_expression->hir(& stmt->body_instructions, state);
if (mode == ast_do_while)
- condition_to_hir(stmt, state);
+ condition_to_hir(&stmt->body_instructions, state);
if (mode != ast_do_while)
state->symbols->pop_scope();
return NULL;
}
- if (this->is_array) {
+ if (this->array_specifier != NULL) {
_mesa_glsl_error(&loc, state,
"default precision statements do not apply to "
"arrays");
if (type->base_type == GLSL_TYPE_FLOAT
&& state->es_shader
- && state->target == fragment_shader) {
+ && state->stage == MESA_SHADER_FRAGMENT) {
/* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00
* spec says:
*
if (!allow_reserved_names)
validate_identifier(decl->identifier, loc, state);
- /* From the GL_ARB_uniform_buffer_object spec:
+ /* From section 4.3.9 of the GLSL 4.40 spec:
*
- * "Sampler types are not allowed inside of uniform
- * blocks. All other types, arrays, and structures
- * allowed for uniforms are allowed within a uniform
- * block."
+ * "[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
const struct glsl_type *field_type =
decl_type != NULL ? decl_type : glsl_type::error_type;
- if (is_interface && field_type->contains_sampler()) {
+ if (is_interface && field_type->contains_opaque()) {
YYLTYPE loc = decl_list->get_location();
_mesa_glsl_error(&loc, state,
- "uniform in non-default uniform block contains sampler");
+ "uniform in non-default uniform block contains "
+ "opaque variable");
}
if (field_type->contains_atomic()) {
"uniform block");
}
+ if (field_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 or uniform block");
+ }
+
const struct ast_type_qualifier *const qual =
& decl_list->type->qualifier;
if (qual->flags.q.std140 ||
"members");
}
- if (decl->is_array) {
- field_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
- }
+ field_type = process_array_type(&loc, decl_type,
+ decl->array_specifier, state);
fields[i].type = field_type;
fields[i].name = decl->identifier;
fields[i].location = -1;
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex input not allowed "
"in the %s shader",
- _mesa_glsl_shader_target_name(state->target));
+ _mesa_shader_stage_to_string(state->stage));
}
if (this->instance_name == NULL ||
- strcmp(this->instance_name, "gl_in") != 0 || !this->is_array) {
+ strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL) {
_mesa_glsl_error(&loc, state,
"gl_PerVertex input must be redeclared as "
"gl_in[]");
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex output not "
"allowed in the %s shader",
- _mesa_glsl_shader_target_name(state->target));
+ _mesa_shader_stage_to_string(state->stage));
}
if (this->instance_name != NULL) {
_mesa_glsl_error(&loc, state,
* variable (or input block, see interface blocks below) needs to be
* declared as an array.
*/
- if (state->target == geometry_shader && !this->is_array &&
+ if (state->stage == MESA_SHADER_GEOMETRY && this->array_specifier == NULL &&
var_mode == ir_var_shader_in) {
_mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays");
}
ir_variable *var;
- if (this->is_array) {
+ if (this->array_specifier != NULL) {
/* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says:
*
* For uniform blocks declared an array, each individual array
* interface array size *doesn't* need to be specified is on a
* geometry shader input.
*/
- if (this->array_size == NULL &&
- (state->target != geometry_shader || !this->layout.flags.q.in)) {
+ if (this->array_specifier->is_unsized_array &&
+ (state->stage != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) {
_mesa_glsl_error(&loc, state,
"only geometry shader inputs may be unsized "
"instance block arrays");
}
const glsl_type *block_array_type =
- process_array_type(&loc, block_type, this->array_size, state);
+ process_array_type(&loc, block_type, this->array_specifier, state);
var = new(state) ir_variable(block_array_type,
this->instance_name,
var_mode);
}
- if (state->target == geometry_shader && var_mode == ir_var_shader_in)
+ if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
handle_geometry_shader_input_decl(state, loc, var);
if (ir_variable *earlier =
/* In order to have an array size, the block must also be declared with
* an instane name.
*/
- assert(!this->is_array);
+ assert(this->array_specifier == NULL);
for (unsigned i = 0; i < num_variables; i++) {
ir_variable *var =
}
+ir_rvalue *
+ast_cs_input_layout::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ YYLTYPE loc = this->get_location();
+
+ /* If any compute input layout declaration preceded this one, make sure it
+ * was consistent with this one.
+ */
+ if (state->cs_input_local_size_specified) {
+ for (int i = 0; i < 3; i++) {
+ if (state->cs_input_local_size[i] != this->local_size[i]) {
+ _mesa_glsl_error(&loc, state,
+ "compute shader input layout does not match"
+ " previous declaration");
+ return NULL;
+ }
+ }
+ }
+
+ /* From the ARB_compute_shader specification:
+ *
+ * If the local size of the shader in any dimension is greater
+ * than the maximum size supported by the implementation for that
+ * dimension, a compile-time error results.
+ *
+ * It is not clear from the spec how the error should be reported if
+ * the total size of the work group exceeds
+ * MAX_COMPUTE_WORK_GROUP_INVOCATIONS, but it seems reasonable to
+ * report it at compile time as well.
+ */
+ GLuint64 total_invocations = 1;
+ for (int i = 0; i < 3; i++) {
+ if (this->local_size[i] > state->ctx->Const.MaxComputeWorkGroupSize[i]) {
+ _mesa_glsl_error(&loc, state,
+ "local_size_%c exceeds MAX_COMPUTE_WORK_GROUP_SIZE"
+ " (%d)", 'x' + i,
+ state->ctx->Const.MaxComputeWorkGroupSize[i]);
+ break;
+ }
+ total_invocations *= this->local_size[i];
+ if (total_invocations >
+ state->ctx->Const.MaxComputeWorkGroupInvocations) {
+ _mesa_glsl_error(&loc, state,
+ "product of local_sizes exceeds "
+ "MAX_COMPUTE_WORK_GROUP_INVOCATIONS (%d)",
+ state->ctx->Const.MaxComputeWorkGroupInvocations);
+ break;
+ }
+ }
+
+ state->cs_input_local_size_specified = true;
+ for (int i = 0; i < 3; i++)
+ state->cs_input_local_size[i] = this->local_size[i];
+
+ /* We may now declare the built-in constant gl_WorkGroupSize (see
+ * builtin_variable_generator::generate_constants() for why we didn't
+ * declare it earlier).
+ */
+ ir_variable *var = new(state->symbols)
+ ir_variable(glsl_type::ivec3_type, "gl_WorkGroupSize", ir_var_auto);
+ var->data.how_declared = ir_var_declared_implicitly;
+ var->data.read_only = true;
+ instructions->push_tail(var);
+ state->symbols->add_variable(var);
+ ir_constant_data data;
+ memset(&data, 0, sizeof(data));
+ for (int i = 0; i < 3; i++)
+ data.i[i] = this->local_size[i];
+ var->constant_value = new(var) ir_constant(glsl_type::ivec3_type, &data);
+ var->constant_initializer =
+ new(var) ir_constant(glsl_type::ivec3_type, &data);
+ var->data.has_initializer = true;
+
+ return NULL;
+}
+
+
static void
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
exec_list *instructions)
else if (strcmp(var->name, "gl_FragData") == 0)
gl_FragData_assigned = true;
else if (strncmp(var->name, "gl_", 3) != 0) {
- if (state->target == fragment_shader &&
+ if (state->stage == MESA_SHADER_FRAGMENT &&
var->data.mode == ir_var_shader_out) {
user_defined_fs_output_assigned = true;
user_defined_fs_output = var;