glsl: Allow geometry shader input instance arrays to be unsized.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Paul Berry
2013-07-24 14:57:24 -07:00
parent c1f1d8522c
commit 20ae8e0c91
3 changed files with 49 additions and 17 deletions

View File

@@ -908,11 +908,13 @@ class ast_interface_block : public ast_node {
public:
ast_interface_block(ast_type_qualifier layout,
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
*
* If the block is not declared as an array or if the block instance array
* is unsized, this field will be \c NULL.
*/
ast_expression *array_size;
};

View File

@@ -4409,7 +4409,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);
@@ -4429,7 +4456,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 =

View File

@@ -2243,25 +2243,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);
}
;