|| this->flags.q.row_major
|| this->flags.q.packed
|| this->flags.q.explicit_align
+ || this->flags.q.explicit_component
|| this->flags.q.explicit_location
|| this->flags.q.explicit_image_format
|| this->flags.q.explicit_index
*/
bool
ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
- _mesa_glsl_parse_state *state,
+ _mesa_glsl_parse_state *state,
const ast_type_qualifier &q,
bool is_single_layout_merge)
{
input_layout_mask.flags.q.centroid = 1;
/* Function params can have constant */
input_layout_mask.flags.q.constant = 1;
+ input_layout_mask.flags.q.explicit_component = 1;
input_layout_mask.flags.q.explicit_location = 1;
input_layout_mask.flags.q.flat = 1;
input_layout_mask.flags.q.in = 1;
/* Geometry shaders can have several layout qualifiers
* assigning different stream values.
*/
- if (state->stage == MESA_SHADER_GEOMETRY)
+ if (state->stage == MESA_SHADER_GEOMETRY) {
allowed_duplicates_mask.flags.i |=
stream_layout_mask.flags.i;
+ }
if (is_single_layout_merge && !state->has_enhanced_layouts() &&
(this->flags.i & q.flags.i & ~allowed_duplicates_mask.flags.i) != 0) {
- _mesa_glsl_error(loc, state,
- "duplicate layout qualifiers used");
+ _mesa_glsl_error(loc, state, "duplicate layout qualifiers used");
return false;
}
if (q.flags.q.prim_type) {
if (this->flags.q.prim_type && this->prim_type != q.prim_type) {
- _mesa_glsl_error(loc, state,
- "conflicting primitive type qualifiers used");
- return false;
+ _mesa_glsl_error(loc, state,
+ "conflicting primitive type qualifiers used");
+ return false;
}
this->prim_type = q.prim_type;
}
if (q.flags.q.subroutine_def) {
if (this->flags.q.subroutine_def) {
- _mesa_glsl_error(loc, state,
- "conflicting subroutine qualifiers used");
+ _mesa_glsl_error(loc, state,
+ "conflicting subroutine qualifiers used");
} else {
this->subroutine_list = q.subroutine_list;
}
if (q.flags.q.stream) {
this->flags.q.stream = 1;
this->stream = q.stream;
- } else if (!this->flags.q.stream && this->flags.q.out) {
+ } else if (!this->flags.q.stream && this->flags.q.out &&
+ !this->flags.q.in) {
/* Assign default global stream value */
this->flags.q.stream = 1;
this->stream = state->out_qualifier->stream;
if (q.flags.q.xfb_buffer) {
this->flags.q.xfb_buffer = 1;
this->xfb_buffer = q.xfb_buffer;
- } else if (!this->flags.q.xfb_buffer && this->flags.q.out) {
+ } else if (!this->flags.q.xfb_buffer && this->flags.q.out &&
+ !this->flags.q.in) {
/* Assign global xfb_buffer value */
this->flags.q.xfb_buffer = 1;
this->xfb_buffer = state->out_qualifier->xfb_buffer;
if (q.flags.q.vertex_spacing) {
if (this->flags.q.vertex_spacing && this->vertex_spacing != q.vertex_spacing) {
- _mesa_glsl_error(loc, state,
- "conflicting vertex spacing used");
- return false;
+ _mesa_glsl_error(loc, state, "conflicting vertex spacing used");
+ return false;
}
this->vertex_spacing = q.vertex_spacing;
}
if (q.flags.q.ordering) {
if (this->flags.q.ordering && this->ordering != q.ordering) {
- _mesa_glsl_error(loc, state,
- "conflicting ordering used");
- return false;
+ _mesa_glsl_error(loc, state, "conflicting ordering used");
+ return false;
}
this->ordering = q.ordering;
}
if (q.flags.q.point_mode) {
if (this->flags.q.point_mode && this->point_mode != q.point_mode) {
- _mesa_glsl_error(loc, state,
- "conflicting point mode used");
- return false;
+ _mesa_glsl_error(loc, state, "conflicting point mode used");
+ return false;
}
this->point_mode = q.point_mode;
}
if (this->flags.q.in &&
(this->flags.i & ~input_layout_mask.flags.i) != 0) {
- _mesa_glsl_error(loc, state,
- "invalid input layout qualifier used");
+ _mesa_glsl_error(loc, state, "invalid input layout qualifier used");
return false;
}
if (q.flags.q.explicit_index)
this->index = q.index;
+ if (q.flags.q.explicit_component)
+ this->component = q.component;
+
if (q.flags.q.explicit_binding)
this->binding = q.binding;
valid_out_mask.flags.q.xfb_buffer = 1;
valid_out_mask.flags.q.explicit_xfb_stride = 1;
valid_out_mask.flags.q.xfb_stride = 1;
+ } else if (state->stage == MESA_SHADER_FRAGMENT) {
+ valid_out_mask.flags.q.blend_support = 1;
} else {
_mesa_glsl_error(loc, state, "out layout qualifiers only valid in "
"geometry, tessellation and vertex shaders");
/* Generate an error when invalid input layout qualifiers are used. */
if ((q.flags.i & ~valid_out_mask.flags.i) != 0) {
- _mesa_glsl_error(loc, state,
- "invalid output layout qualifiers used");
+ _mesa_glsl_error(loc, state, "invalid output layout qualifiers used");
return false;
}
/* Generate an error when invalid input layout qualifiers are used. */
if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
- _mesa_glsl_error(loc, state,
- "invalid input layout qualifiers used");
+ _mesa_glsl_error(loc, state, "invalid input layout qualifiers used");
return false;
}
return true;
}
+/**
+ * Check if the current type qualifier has any illegal flags.
+ *
+ * If so, print an error message, followed by a list of illegal flags.
+ *
+ * \param message The error message to print.
+ * \param allowed_flags A list of valid flags.
+ */
+bool
+ast_type_qualifier::validate_flags(YYLTYPE *loc,
+ _mesa_glsl_parse_state *state,
+ const ast_type_qualifier &allowed_flags,
+ const char *message, const char *name)
+{
+ ast_type_qualifier bad;
+ bad.flags.i = this->flags.i & ~allowed_flags.flags.i;
+ if (bad.flags.i == 0)
+ return true;
+
+ _mesa_glsl_error(loc, state,
+ "%s '%s':"
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ message, name,
+ bad.flags.q.invariant ? " invariant" : "",
+ bad.flags.q.precise ? " precise" : "",
+ bad.flags.q.constant ? " constant" : "",
+ bad.flags.q.attribute ? " attribute" : "",
+ bad.flags.q.varying ? " varying" : "",
+ bad.flags.q.in ? " in" : "",
+ bad.flags.q.out ? " out" : "",
+ bad.flags.q.centroid ? " centroid" : "",
+ bad.flags.q.sample ? " sample" : "",
+ bad.flags.q.patch ? " patch" : "",
+ bad.flags.q.uniform ? " uniform" : "",
+ bad.flags.q.buffer ? " buffer" : "",
+ bad.flags.q.shared_storage ? " shared_storage" : "",
+ bad.flags.q.smooth ? " smooth" : "",
+ bad.flags.q.flat ? " flat" : "",
+ bad.flags.q.noperspective ? " noperspective" : "",
+ bad.flags.q.origin_upper_left ? " origin_upper_left" : "",
+ bad.flags.q.pixel_center_integer ? " pixel_center_integer" : "",
+ bad.flags.q.explicit_align ? " align" : "",
+ bad.flags.q.explicit_component ? " component" : "",
+ bad.flags.q.explicit_location ? " location" : "",
+ bad.flags.q.explicit_index ? " index" : "",
+ bad.flags.q.explicit_binding ? " binding" : "",
+ bad.flags.q.explicit_offset ? " offset" : "",
+ bad.flags.q.depth_any ? " depth_any" : "",
+ bad.flags.q.depth_greater ? " depth_greater" : "",
+ bad.flags.q.depth_less ? " depth_less" : "",
+ bad.flags.q.depth_unchanged ? " depth_unchanged" : "",
+ bad.flags.q.std140 ? " std140" : "",
+ bad.flags.q.std430 ? " std430" : "",
+ bad.flags.q.shared ? " shared" : "",
+ bad.flags.q.packed ? " packed" : "",
+ bad.flags.q.column_major ? " column_major" : "",
+ bad.flags.q.row_major ? " row_major" : "",
+ bad.flags.q.prim_type ? " prim_type" : "",
+ bad.flags.q.max_vertices ? " max_vertices" : "",
+ bad.flags.q.local_size ? " local_size" : "",
+ bad.flags.q.early_fragment_tests ? " early_fragment_tests" : "",
+ bad.flags.q.explicit_image_format ? " image_format" : "",
+ bad.flags.q.coherent ? " coherent" : "",
+ bad.flags.q._volatile ? " _volatile" : "",
+ bad.flags.q.restrict_flag ? " restrict_flag" : "",
+ bad.flags.q.read_only ? " read_only" : "",
+ bad.flags.q.write_only ? " write_only" : "",
+ bad.flags.q.invocations ? " invocations" : "",
+ bad.flags.q.stream ? " stream" : "",
+ bad.flags.q.explicit_stream ? " stream" : "",
+ bad.flags.q.explicit_xfb_offset ? " xfb_offset" : "",
+ bad.flags.q.xfb_buffer ? " xfb_buffer" : "",
+ bad.flags.q.explicit_xfb_buffer ? " xfb_buffer" : "",
+ bad.flags.q.xfb_stride ? " xfb_stride" : "",
+ bad.flags.q.explicit_xfb_stride ? " xfb_stride" : "",
+ bad.flags.q.vertex_spacing ? " vertex_spacing" : "",
+ bad.flags.q.ordering ? " ordering" : "",
+ bad.flags.q.point_mode ? " point_mode" : "",
+ bad.flags.q.vertices ? " vertices" : "",
+ bad.flags.q.subroutine ? " subroutine" : "",
+ bad.flags.q.subroutine_def ? " subroutine_def" : "");
+ return false;
+}
+
bool
ast_layout_expression::process_qualifier_constant(struct _mesa_glsl_parse_state *state,
const char *qual_indentifier,
unsigned *value,
- bool can_be_zero)
+ bool can_be_zero,
+ bool must_match)
{
int min_value = 0;
bool first_pass = true;
if (!can_be_zero)
min_value = 1;
- for (exec_node *node = layout_const_expressions.head;
- !node->is_tail_sentinel(); node = node->next) {
+ for (exec_node *node = layout_const_expressions.get_head_raw();
+ !node->is_tail_sentinel(); node = node->next) {
exec_list dummy_instructions;
ast_node *const_expression = exec_node_data(ast_node, node, link);
return false;
}
- if (!first_pass && *value != const_int->value.u[0]) {
- YYLTYPE loc = const_expression->get_location();
- _mesa_glsl_error(&loc, state, "%s layout qualifier does not "
- "match previous declaration (%d vs %d)",
- qual_indentifier, *value, const_int->value.i[0]);
- return false;
+ /* From section 4.4 "Layout Qualifiers" of the GLSL 4.50 spec:
+ * "When the same layout-qualifier-name occurs multiple times,
+ * in a single declaration, the last occurrence overrides the
+ * former occurrence(s)."
+ */
+ if (!first_pass) {
+ if ((must_match || !state->has_420pack()) && *value != const_int->value.u[0]) {
+ YYLTYPE loc = const_expression->get_location();
+ _mesa_glsl_error(&loc, state, "%s layout qualifier does not "
+ "match previous declaration (%d vs %d)",
+ qual_indentifier, *value, const_int->value.i[0]);
+ return false;
+ }
} else {
first_pass = false;
*value = const_int->value.u[0];