glsl: use common intrastage array validation

Use common intrastage array validation for interface blocks.

This change also allows us to support interface blocks
that are arrays of arrays.

V2: Reinsert unsized array asserts in interstage_match()

Reviewed-by: Mark Janes <mark.a.janes@intel.com>
This commit is contained in:
Timothy Arceri
2015-02-22 22:52:48 +11:00
parent 50859c688c
commit c5a56a63f9

View File

@@ -50,18 +50,20 @@ struct interface_block_definition
* represents either the interface instance (for named interfaces), or a
* member of the interface (for unnamed interfaces).
*/
explicit interface_block_definition(const ir_variable *var)
: type(var->get_interface_type()),
instance_name(NULL),
array_size(-1)
explicit interface_block_definition(ir_variable *var)
: var(var),
type(var->get_interface_type()),
instance_name(NULL)
{
if (var->is_interface_instance()) {
instance_name = var->name;
if (var->type->is_array())
array_size = var->type->length;
}
explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly);
}
/**
* Interface block ir_variable
*/
ir_variable *var;
/**
* Interface block type
@@ -73,12 +75,6 @@ struct interface_block_definition
*/
const char *instance_name;
/**
* For an interface block array, the array size (or 0 if unsized).
* Otherwise -1.
*/
int array_size;
/**
* True if this interface block was explicitly declared in the shader;
* false if it was an implicitly declared built-in interface block.
@@ -95,7 +91,8 @@ struct interface_block_definition
bool
intrastage_match(interface_block_definition *a,
const interface_block_definition *b,
ir_variable_mode mode)
ir_variable_mode mode,
struct gl_shader_program *prog)
{
/* Types must match. */
if (a->type != b->type) {
@@ -120,18 +117,13 @@ intrastage_match(interface_block_definition *a,
return false;
}
/* Array vs. nonarray must be consistent, and sizes must be
* consistent, with the exception that unsized arrays match sized
* arrays.
/* If a block is an array then it must match across the shader.
* Unsized arrays are also processed and matched agaist sized arrays.
*/
if ((a->array_size == -1) != (b->array_size == -1))
if (b->var->type != a->var->type &&
(b->instance_name != NULL || a->instance_name != NULL) &&
!validate_intrastage_arrays(prog, b->var, a->var))
return false;
if (b->array_size != 0) {
if (a->array_size == 0)
a->array_size = b->array_size;
else if (a->array_size != b->array_size)
return false;
}
return true;
}
@@ -153,8 +145,8 @@ interstage_match(const interface_block_definition *producer,
/* Unsized arrays should not occur during interstage linking. They
* should have all been assigned a size by link_intrastage_shaders.
*/
assert(consumer->array_size != 0);
assert(producer->array_size != 0);
assert(!consumer->var->type->is_unsized_array());
assert(!producer->var->type->is_unsized_array());
/* Types must match. */
if (consumer->type != producer->type) {
@@ -165,20 +157,27 @@ interstage_match(const interface_block_definition *producer,
if (consumer->explicitly_declared || producer->explicitly_declared)
return false;
}
/* Ignore outermost array if geom shader */
const glsl_type *consumer_instance_type;
if (extra_array_level) {
/* Consumer must be an array, and producer must not. */
if (consumer->array_size == -1)
return false;
if (producer->array_size != -1)
return false;
consumer_instance_type = consumer->var->type->fields.array;
} else {
/* Array vs. nonarray must be consistent, and sizes must be consistent.
* Since unsized arrays have been ruled out, we can check this by just
* making sure the sizes are equal.
*/
if (consumer->array_size != producer->array_size)
consumer_instance_type = consumer->var->type;
}
/* If a block is an array then it must match across shaders.
* Since unsized arrays have been ruled out, we can check this by just
* making sure the types are equal.
*/
if ((consumer->instance_name != NULL &&
consumer_instance_type->is_array()) ||
(producer->instance_name != NULL &&
producer->var->type->is_array())) {
if (consumer_instance_type != producer->var->type)
return false;
}
return true;
}
@@ -298,7 +297,8 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
*/
definitions->store(def);
} else if (!intrastage_match(prev_def, &def,
(ir_variable_mode) var->data.mode)) {
(ir_variable_mode) var->data.mode,
prog)) {
linker_error(prog, "definitions of interface block `%s' do not"
" match\n", iface_type->name);
return;
@@ -374,7 +374,7 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog,
* uniform matchin rules (for uniforms, it is as though all
* shaders are in the same shader stage).
*/
if (!intrastage_match(old_def, &new_def, ir_var_uniform)) {
if (!intrastage_match(old_def, &new_def, ir_var_uniform, prog)) {
linker_error(prog, "definitions of interface block `%s' do not "
"match\n", var->get_interface_type()->name);
return;