#include "ir_rvalue_visitor.h"
#include "program/hash_table.h"
+static const glsl_type *
+process_array_type(const glsl_type *type, unsigned idx)
+{
+ const glsl_type *element_type = type->fields.array;
+ if (element_type->is_array()) {
+ const glsl_type *new_array_type = process_array_type(element_type, idx);
+ return glsl_type::get_array_instance(new_array_type, type->length);
+ } else {
+ return glsl_type::get_array_instance(
+ element_type->fields.structure[idx].type, type->length);
+ }
+}
+
+static ir_rvalue *
+process_array_ir(void * const mem_ctx,
+ ir_dereference_array *deref_array_prev,
+ ir_rvalue *deref_var)
+{
+ ir_dereference_array *deref_array =
+ deref_array_prev->array->as_dereference_array();
+
+ if (deref_array == NULL) {
+ return new(mem_ctx) ir_dereference_array(deref_var,
+ deref_array_prev->array_index);
+ } else {
+ deref_array = (ir_dereference_array *) process_array_ir(mem_ctx,
+ deref_array,
+ deref_var);
+ return new(mem_ctx) ir_dereference_array(deref_array,
+ deref_array_prev->array_index);
+ }
+}
+
+namespace {
+
class flatten_named_interface_blocks_declarations : public ir_rvalue_visitor
{
public:
virtual void handle_rvalue(ir_rvalue **rvalue);
};
+} /* anonymous namespace */
+
void
flatten_named_interface_blocks_declarations::run(exec_list *instructions)
{
* The interface block variables are stored in the interface_namespace
* hash table so they can be used in the second pass.
*/
- foreach_list_safe(node, instructions) {
- ir_variable *var = ((ir_instruction *) node)->as_variable();
+ foreach_in_list_safe(ir_instruction, node, instructions) {
+ ir_variable *var = node->as_variable();
if (!var || !var->is_interface_instance())
continue;
* but, this will require changes to the other uniform block
* support code.
*/
- if (var->mode == ir_var_uniform)
+ if (var->data.mode == ir_var_uniform ||
+ var->data.mode == ir_var_shader_storage)
continue;
- const glsl_type * iface_t = var->type;
- const glsl_type * array_t = NULL;
+ const glsl_type * iface_t = var->type->without_array();
exec_node *insert_pos = var;
- if (iface_t->is_array()) {
- array_t = iface_t;
- iface_t = array_t->fields.array;
- }
-
assert (iface_t->is_interface());
for (unsigned i = 0; i < iface_t->length; i++) {
const char * field_name = iface_t->fields.structure[i].name;
char *iface_field_name =
- ralloc_asprintf(mem_ctx, "%s.%s",
- iface_t->name, field_name);
+ ralloc_asprintf(mem_ctx, "%s %s.%s.%s",
+ var->data.mode == ir_var_shader_in ? "in" : "out",
+ iface_t->name, var->name, field_name);
ir_variable *found_var =
(ir_variable *) hash_table_find(interface_namespace,
iface_field_name);
if (!found_var) {
ir_variable *new_var;
- if (array_t == NULL) {
- char *var_name =
- ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
+ char *var_name =
+ ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name);
+ if (!var->type->is_array()) {
new_var =
new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
var_name,
- (ir_variable_mode) var->mode);
+ (ir_variable_mode) var->data.mode);
+ new_var->data.from_named_ifc_block_nonarray = 1;
} else {
const glsl_type *new_array_type =
- glsl_type::get_array_instance(
- iface_t->fields.structure[i].type,
- array_t->length);
- char *var_name =
- ralloc_asprintf(mem_ctx, "%s[%d]",
- iface_t->fields.structure[i].name,
- array_t->length);
+ process_array_type(var->type, i);
new_var =
new(mem_ctx) ir_variable(new_array_type,
var_name,
- (ir_variable_mode) var->mode);
+ (ir_variable_mode) var->data.mode);
+ new_var->data.from_named_ifc_block_array = 1;
}
+ new_var->data.location = iface_t->fields.structure[i].location;
+ new_var->data.explicit_location = (new_var->data.location >= 0);
+ new_var->data.interpolation =
+ iface_t->fields.structure[i].interpolation;
+ new_var->data.centroid = iface_t->fields.structure[i].centroid;
+ new_var->data.sample = iface_t->fields.structure[i].sample;
+ new_var->data.patch = iface_t->fields.structure[i].patch;
+ new_var->data.stream = var->data.stream;
+ new_var->data.how_declared = var->data.how_declared;
- new_var->interface_type = iface_t;
+ new_var->init_interface_type(iface_t);
hash_table_insert(interface_namespace, new_var,
iface_field_name);
insert_pos->insert_after(new_var);
return;
ir_variable *var = ir->variable_referenced();
+ if (var == NULL)
+ return;
if (!var->is_interface_instance())
return;
* but, this will require changes to the other uniform block
* support code.
*/
- if (var->mode == ir_var_uniform)
+ if (var->data.mode == ir_var_uniform || var->data.mode == ir_var_shader_storage)
return;
- if (var->interface_type != NULL) {
+ if (var->get_interface_type() != NULL) {
char *iface_field_name =
- ralloc_asprintf(mem_ctx, "%s.%s", var->interface_type->name,
- ir->field);
+ ralloc_asprintf(mem_ctx, "%s %s.%s.%s",
+ var->data.mode == ir_var_shader_in ? "in" : "out",
+ var->get_interface_type()->name,
+ var->name, ir->field);
/* Find the variable in the set of flattened interface blocks */
ir_variable *found_var =
(ir_variable *) hash_table_find(interface_namespace,
ir_dereference_array *deref_array =
ir->record->as_dereference_array();
if (deref_array != NULL) {
- *rvalue =
- new(mem_ctx) ir_dereference_array(deref_var,
- deref_array->array_index);
+ *rvalue = process_array_ir(mem_ctx, deref_array,
+ (ir_rvalue *)deref_var);
} else {
*rvalue = deref_var;
}