summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Berry <stereotype441@gmail.com>2013-07-24 14:57:24 -0700
committerPaul Berry <stereotype441@gmail.com>2013-07-28 21:32:21 -0700
commita404e64f735711f0e0ff7898c3bb7c9b84c6a495 (patch)
treec87335e6867ffbddae1839b51920e5a02daba930
parent2b838dd8bbeaca5d53063a8429051c46e0dec681 (diff)
glsl: Allow geometry shader input instance arrays to be unsized.
-rw-r--r--src/glsl/ast.h24
-rw-r--r--src/glsl/ast_to_hir.cpp31
-rw-r--r--src/glsl/glsl_parser.yy11
3 files changed, 49 insertions, 17 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 3ef9913a78..a40bbc01e7 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -907,12 +907,14 @@ public:
class ast_interface_block : public ast_node {
public:
ast_interface_block(ast_type_qualifier layout,
- const char *instance_name,
- ast_expression *array_size)
+ const char *instance_name,
+ bool is_array,
+ ast_expression *array_size)
: layout(layout), block_name(NULL), instance_name(instance_name),
- array_size(array_size)
+ is_array(is_array), array_size(array_size)
{
- /* empty */
+ if (!is_array)
+ assert(array_size == NULL);
}
virtual ir_rvalue *hir(exec_list *instructions,
@@ -933,13 +935,19 @@ public:
exec_list declarations;
/**
- * Declared array size of the block instance
- *
- * If the block is not declared as an array, this field will be \c NULL.
+ * True if the block is declared as an array
*
* \note
* A block can only be an array if it also has an instance name. If this
- * field is not \c NULL, ::instance_name must also not be \c NULL.
+ * field is true, ::instance_name must also not be \c NULL.
+ */
+ bool is_array;
+
+ /**
+ * Declared array size of the block instance, or NULL if the block instance
+ * array is unsized.
+ *
+ * If the block is not declared as an array, this field will be \c NULL.
*/
ast_expression *array_size;
};
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 3a013c5b44..44399c6728 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -4396,7 +4396,34 @@ ast_interface_block::hir(exec_list *instructions,
if (this->instance_name) {
ir_variable *var;
- if (this->array_size != NULL) {
+ if (this->is_array) {
+ /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says:
+ *
+ * For uniform blocks declared an array, each individual array
+ * element corresponds to a separate buffer object backing one
+ * instance of the block. As the array size indicates the number
+ * of buffer objects needed, uniform block array declarations
+ * must specify an array size.
+ *
+ * And a few paragraphs later:
+ *
+ * Geometry shader input blocks must be declared as arrays and
+ * follow the array declaration and linking rules for all
+ * geometry shader inputs. All other input and output block
+ * arrays must specify an array size.
+ *
+ * The upshot of this is that the only circumstance where an
+ * interface array size *doesn't* need to be specified is on a
+ * geometry shader input.
+ */
+ if (this->array_size == NULL &&
+ (state->target != geometry_shader || !this->layout.flags.q.in)) {
+ _mesa_glsl_error(&loc, state,
+ "only geometry shader inputs may be unsized "
+ "instance block arrays");
+
+ }
+
const glsl_type *block_array_type =
process_array_type(&loc, block_type, this->array_size, state);
@@ -4416,7 +4443,7 @@ ast_interface_block::hir(exec_list *instructions,
/* In order to have an array size, the block must also be declared with
* an instane name.
*/
- assert(this->array_size == NULL);
+ assert(!this->is_array);
for (unsigned i = 0; i < num_variables; i++) {
ir_variable *var =
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 6f39d072ba..8ebc3e1db7 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -2239,25 +2239,22 @@ instance_name_opt:
/* empty */
{
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- NULL, NULL);
+ NULL, false, NULL);
}
| NEW_IDENTIFIER
{
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, NULL);
+ $1, false, NULL);
}
| NEW_IDENTIFIER '[' constant_expression ']'
{
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, $3);
+ $1, true, $3);
}
| NEW_IDENTIFIER '[' ']'
{
- _mesa_glsl_error(& @1, state,
- "instance block arrays must be explicitly sized");
-
$$ = new(state) ast_interface_block(*state->default_uniform_qualifier,
- $1, NULL);
+ $1, true, NULL);
}
;