static unsigned
get_io_offset(nir_builder *b, nir_deref_instr *deref, nir_variable *var,
- unsigned *element_index, nir_ssa_def **vertex_index)
+ unsigned *element_index, unsigned *xfb_offset,
+ nir_ssa_def **vertex_index)
{
nir_deref_path path;
nir_deref_path_init(&path, deref, NULL);
}
unsigned offset = 0;
+ *xfb_offset = 0;
for (; *p; p++) {
if ((*p)->deref_type == nir_deref_type_array) {
/* must not be indirect dereference */
unsigned size = glsl_count_attribute_slots((*p)->type, false);
offset += size * index;
+ xfb_offset += index * glsl_get_component_slots((*p)->type) * 4;
+
unsigned num_elements = glsl_type_is_array((*p)->type) ?
glsl_get_aoa_size((*p)->type) : 1;
nir_ssa_def *vertex_index = NULL;
unsigned elements_index = 0;
+ unsigned xfb_offset = 0;
unsigned io_offset = get_io_offset(b, nir_src_as_deref(intr->src[0]),
- var, &elements_index, &vertex_index);
+ var, &elements_index, &xfb_offset,
+ &vertex_index);
nir_variable *element = elements[elements_index];
if (!element) {
element = nir_variable_clone(var, b->shader);
element->data.location = var->data.location + io_offset;
+ if (var->data.explicit_offset)
+ element->data.offset = var->data.offset + xfb_offset;
+
const struct glsl_type *type = glsl_without_array(element->type);
/* This pass also splits matrices so we need give them a new type. */
- if (glsl_type_is_matrix(type)) {
- type = glsl_vector_type(glsl_get_base_type(type),
- glsl_get_vector_elements(type));
- }
+ if (glsl_type_is_matrix(type))
+ type = glsl_get_column_type(type);
if (nir_is_per_vertex_io(var, b->shader->info.stage)) {
- type = glsl_get_array_instance(type,
- glsl_get_length(element->type));
+ type = glsl_array_type(type, glsl_get_length(element->type),
+ glsl_get_explicit_stride(element->type));
}
element->type = type;
intr->num_components, intr->dest.ssa.bit_size, NULL);
if (intr->intrinsic == nir_intrinsic_interp_deref_at_offset ||
- intr->intrinsic == nir_intrinsic_interp_deref_at_sample) {
+ intr->intrinsic == nir_intrinsic_interp_deref_at_sample ||
+ intr->intrinsic == nir_intrinsic_interp_deref_at_vertex) {
nir_src_copy(&element_intr->src[1], &intr->src[1],
&element_intr->instr);
}
* indirect indexing.
*/
static void
-create_indirects_mask(nir_shader *shader, uint64_t *indirects,
- uint64_t *patch_indirects, nir_variable_mode mode)
+create_indirects_mask(nir_shader *shader,
+ BITSET_WORD *indirects, nir_variable_mode mode)
{
nir_foreach_function(function, shader) {
if (function->impl) {
intr->intrinsic != nir_intrinsic_store_deref &&
intr->intrinsic != nir_intrinsic_interp_deref_at_centroid &&
intr->intrinsic != nir_intrinsic_interp_deref_at_sample &&
- intr->intrinsic != nir_intrinsic_interp_deref_at_offset)
+ intr->intrinsic != nir_intrinsic_interp_deref_at_offset &&
+ intr->intrinsic != nir_intrinsic_interp_deref_at_vertex)
continue;
nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
- nir_variable *var = nir_deref_instr_get_variable(deref);
-
- if (var->data.mode != mode)
+ if (deref->mode != mode)
continue;
+ nir_variable *var = nir_deref_instr_get_variable(deref);
+
nir_deref_path path;
nir_deref_path_init(&path, deref, NULL);
- uint64_t loc_mask = ((uint64_t)1) << var->data.location;
- if (var->data.patch) {
- if (deref_has_indirect(&b, var, &path))
- patch_indirects[var->data.location_frac] |= loc_mask;
- } else {
- if (deref_has_indirect(&b, var, &path))
- indirects[var->data.location_frac] |= loc_mask;
- }
+ int loc = var->data.location * 4 + var->data.location_frac;
+ if (deref_has_indirect(&b, var, &path))
+ BITSET_SET(indirects, loc);
nir_deref_path_finish(&path);
}
static void
lower_io_arrays_to_elements(nir_shader *shader, nir_variable_mode mask,
- uint64_t *indirects, uint64_t *patch_indirects,
+ BITSET_WORD *indirects,
struct hash_table *varyings,
bool after_cross_stage_opts)
{
intr->intrinsic != nir_intrinsic_store_deref &&
intr->intrinsic != nir_intrinsic_interp_deref_at_centroid &&
intr->intrinsic != nir_intrinsic_interp_deref_at_sample &&
- intr->intrinsic != nir_intrinsic_interp_deref_at_offset)
+ intr->intrinsic != nir_intrinsic_interp_deref_at_offset &&
+ intr->intrinsic != nir_intrinsic_interp_deref_at_vertex)
continue;
- nir_variable *var =
- nir_deref_instr_get_variable(nir_src_as_deref(intr->src[0]));
+ nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
+ if (!(deref->mode & mask))
+ continue;
+
+ nir_variable *var = nir_deref_instr_get_variable(deref);
+
+ /* Drivers assume compact arrays are, in fact, arrays. */
+ if (var->data.compact)
+ continue;
+
+ /* Per-view variables are expected to remain arrays. */
+ if (var->data.per_view)
+ continue;
/* Skip indirects */
- uint64_t loc_mask = ((uint64_t)1) << var->data.location;
- if (var->data.patch) {
- if (patch_indirects[var->data.location_frac] & loc_mask)
- continue;
- } else {
- if (indirects[var->data.location_frac] & loc_mask)
- continue;
- }
+ int loc = var->data.location * 4 + var->data.location_frac;
+ if (BITSET_TEST(indirects, loc))
+ continue;
nir_variable_mode mode = var->data.mode;
* TODO: Add support for struct splitting.
*/
if ((!glsl_type_is_array(type) && !glsl_type_is_matrix(type))||
- glsl_type_is_struct(glsl_without_array(type)))
+ glsl_type_is_struct_or_ifc(glsl_without_array(type)))
continue;
/* Skip builtins */
case nir_intrinsic_interp_deref_at_centroid:
case nir_intrinsic_interp_deref_at_sample:
case nir_intrinsic_interp_deref_at_offset:
+ case nir_intrinsic_interp_deref_at_vertex:
case nir_intrinsic_load_deref:
case nir_intrinsic_store_deref:
if ((mask & nir_var_shader_in && mode == nir_var_shader_in) ||
nir_lower_io_arrays_to_elements_no_indirects(nir_shader *shader,
bool outputs_only)
{
- struct hash_table *split_inputs =
- _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- struct hash_table *split_outputs =
- _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
+ struct hash_table *split_inputs = _mesa_pointer_hash_table_create(NULL);
+ struct hash_table *split_outputs = _mesa_pointer_hash_table_create(NULL);
- uint64_t indirects[4] = {0}, patch_indirects[4] = {0};
+ BITSET_DECLARE(indirects, 4 * VARYING_SLOT_TESS_MAX) = {0};
- lower_io_arrays_to_elements(shader, nir_var_shader_out, indirects,
- patch_indirects, split_outputs, true);
+ lower_io_arrays_to_elements(shader, nir_var_shader_out,
+ indirects, split_outputs, true);
if (!outputs_only) {
- lower_io_arrays_to_elements(shader, nir_var_shader_in, indirects,
- patch_indirects, split_inputs, true);
+ lower_io_arrays_to_elements(shader, nir_var_shader_in,
+ indirects, split_inputs, true);
/* Remove old input from the shaders inputs list */
- struct hash_entry *entry;
hash_table_foreach(split_inputs, entry) {
nir_variable *var = (nir_variable *) entry->key;
exec_node_remove(&var->node);
}
/* Remove old output from the shaders outputs list */
- struct hash_entry *entry;
hash_table_foreach(split_outputs, entry) {
nir_variable *var = (nir_variable *) entry->key;
exec_node_remove(&var->node);
void
nir_lower_io_arrays_to_elements(nir_shader *producer, nir_shader *consumer)
{
- struct hash_table *split_inputs =
- _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- struct hash_table *split_outputs =
- _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
+ struct hash_table *split_inputs = _mesa_pointer_hash_table_create(NULL);
+ struct hash_table *split_outputs = _mesa_pointer_hash_table_create(NULL);
+
+ BITSET_DECLARE(indirects, 4 * VARYING_SLOT_TESS_MAX) = {0};
- uint64_t indirects[4] = {0}, patch_indirects[4] = {0};
- create_indirects_mask(producer, indirects, patch_indirects,
- nir_var_shader_out);
- create_indirects_mask(consumer, indirects, patch_indirects,
- nir_var_shader_in);
+ create_indirects_mask(producer, indirects, nir_var_shader_out);
+ create_indirects_mask(consumer, indirects, nir_var_shader_in);
- lower_io_arrays_to_elements(producer, nir_var_shader_out, indirects,
- patch_indirects, split_outputs, false);
+ lower_io_arrays_to_elements(producer, nir_var_shader_out,
+ indirects, split_outputs, false);
- lower_io_arrays_to_elements(consumer, nir_var_shader_in, indirects,
- patch_indirects, split_inputs, false);
+ lower_io_arrays_to_elements(consumer, nir_var_shader_in,
+ indirects, split_inputs, false);
/* Remove old input from the shaders inputs list */
- struct hash_entry *entry;
hash_table_foreach(split_inputs, entry) {
nir_variable *var = (nir_variable *) entry->key;
exec_node_remove(&var->node);