if (glsl_type_is_array(type)) {
const struct glsl_type *elem =
member_type(glsl_get_array_element(type), index);
- return glsl_get_array_instance(elem, glsl_get_length(type));
+ assert(glsl_get_explicit_stride(type) == 0);
+ return glsl_array_type(elem, glsl_get_length(type), 0);
} else {
- assert(glsl_type_is_struct(type));
+ assert(glsl_type_is_struct_or_ifc(type));
assert(index < glsl_get_length(type));
return glsl_get_struct_field(type, index);
}
assert(var->state_slots == NULL);
/* Constant initializers are currently not handled */
- assert(var->constant_initializer == NULL);
+ assert(var->constant_initializer == NULL && var->pointer_initializer == NULL);
nir_variable **members =
ralloc_array(dead_ctx, nir_variable *, var->num_members);
_mesa_hash_table_insert(var_to_member_map, var, members);
}
-static bool
-split_variables_in_list(struct exec_list *var_list, nir_shader *shader,
- struct hash_table *var_to_member_map, void *dead_ctx)
-{
- bool progress = false;
-
- nir_foreach_variable_safe(var, var_list) {
- if (var->num_members == 0)
- continue;
-
- split_variable(var, shader, var_to_member_map, dead_ctx);
- exec_node_remove(&var->node);
- progress = true;
- }
-
- return progress;
-}
-
static nir_deref_instr *
build_member_deref(nir_builder *b, nir_deref_instr *deref, nir_variable *member)
{
nir_deref_instr_remove_if_unused(deref);
}
-static void
-rewrite_deref_var(nir_instr *instr, nir_deref_var **deref,
- struct hash_table *var_to_member_map)
-{
- if ((*deref)->var->members == 0)
- return;
-
- nir_deref_struct *strct = NULL;
- for (nir_deref *d = (*deref)->deref.child; d; d = d->child) {
- if (d->deref_type == nir_deref_type_struct) {
- strct = nir_deref_as_struct(d);
- break;
- }
- }
- assert(strct);
-
- nir_variable *member = find_var_member((*deref)->var, strct->index,
- var_to_member_map);
-
- nir_deref_var *head = nir_deref_var_create(ralloc_parent(*deref), member);
- nir_deref *tail = &head->deref;
- for (nir_deref *d = (*deref)->deref.child;
- d != &strct->deref; d = d->child) {
- nir_deref_array *arr = nir_deref_as_array(d);
-
- nir_deref_array *narr = nir_deref_array_create(tail);
- narr->deref.type = glsl_get_array_element(tail->type);
- narr->deref_array_type = arr->deref_array_type;
- narr->base_offset = arr->base_offset;
-
- if (arr->deref_array_type == nir_deref_array_type_indirect)
- nir_instr_move_src(instr, &narr->indirect, &arr->indirect);
-
- assert(tail->child == NULL);
- tail->child = &narr->deref;
- tail = &narr->deref;
- }
-
- ralloc_steal(tail, strct->deref.child);
- tail->child = strct->deref.child;
-
- ralloc_free(*deref);
- *deref = head;
-}
-
-static void
-rewrite_intrinsic_instr(nir_intrinsic_instr *intrin,
- struct hash_table *var_to_member_map)
-{
- for (unsigned i = 0;
- i < nir_intrinsic_infos[intrin->intrinsic].num_variables; i++) {
- rewrite_deref_var(&intrin->instr, &intrin->variables[i],
- var_to_member_map);
- }
-}
-
-static void
-rewrite_tex_instr(nir_tex_instr *tex, struct hash_table *var_to_member_map)
-{
- if (tex->texture)
- rewrite_deref_var(&tex->instr, &tex->texture, var_to_member_map);
- if (tex->sampler)
- rewrite_deref_var(&tex->instr, &tex->sampler, var_to_member_map);
-}
-
bool
nir_split_per_member_structs(nir_shader *shader)
{
bool progress = false;
void *dead_ctx = ralloc_context(NULL);
struct hash_table *var_to_member_map =
- _mesa_hash_table_create(dead_ctx, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
+ _mesa_pointer_hash_table_create(dead_ctx);
- progress |= split_variables_in_list(&shader->inputs, shader,
- var_to_member_map, dead_ctx);
- progress |= split_variables_in_list(&shader->outputs, shader,
- var_to_member_map, dead_ctx);
- progress |= split_variables_in_list(&shader->system_values, shader,
- var_to_member_map, dead_ctx);
- if (!progress)
+ nir_foreach_variable_with_modes_safe(var, shader, nir_var_shader_in |
+ nir_var_shader_out |
+ nir_var_system_value) {
+ if (var->num_members == 0)
+ continue;
+
+ split_variable(var, shader, var_to_member_map, dead_ctx);
+ exec_node_remove(&var->node);
+ progress = true;
+ }
+
+ if (!progress) {
+ ralloc_free(dead_ctx);
return false;
+ }
nir_foreach_function(function, shader) {
if (!function->impl)
nir_builder_init(&b, function->impl);
nir_foreach_block(block, function->impl) {
nir_foreach_instr_safe(instr, block) {
- switch (instr->type) {
- case nir_instr_type_deref:
+ if (instr->type == nir_instr_type_deref) {
rewrite_deref_instr(&b, nir_instr_as_deref(instr),
var_to_member_map);
- break;
-
- case nir_instr_type_intrinsic:
- rewrite_intrinsic_instr(nir_instr_as_intrinsic(instr),
- var_to_member_map);
- break;
-
- case nir_instr_type_tex:
- rewrite_tex_instr(nir_instr_as_tex(instr), var_to_member_map);
- break;
-
- case nir_instr_type_call:
- unreachable("Functions must be inlined before this pass");
-
- default:
- break;
}
}
}
+
+ nir_metadata_preserve(function->impl,
+ nir_metadata_block_index |
+ nir_metadata_dominance);
}
ralloc_free(dead_ctx);