diff options
author | Jason Ekstrand <[email protected]> | 2015-03-18 15:05:28 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-03-19 13:18:39 -0700 |
commit | 8a33f95b7a1128b5e46bd30306961bac72f5f12e (patch) | |
tree | b7ce2057a75ad7c6798d20436babe8164af7366b | |
parent | 25db44a84597960a6aea6b252bcf2c3d7e17fc74 (diff) |
nir/lower_io: Add a assign_locations function that sorts by [in]direct use
v2: Delete the set of indirectly accessed variables when we're done with it
v3: Rename from _packed to _scalar
Reviewed-by: Connor Abbott <[email protected]>
-rw-r--r-- | src/glsl/nir/nir.h | 4 | ||||
-rw-r--r-- | src/glsl/nir/nir_lower_io.c | 71 |
2 files changed, 75 insertions, 0 deletions
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h index a2a03b22707..29fe942431c 100644 --- a/src/glsl/nir/nir.h +++ b/src/glsl/nir/nir.h @@ -1579,6 +1579,10 @@ void nir_lower_locals_to_regs(nir_shader *shader); void nir_assign_var_locations_scalar(struct exec_list *var_list, unsigned *size); +void nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size); void nir_lower_io(nir_shader *shader); diff --git a/src/glsl/nir/nir_lower_io.c b/src/glsl/nir/nir_lower_io.c index 602b8c95b8e..03eed04e1e9 100644 --- a/src/glsl/nir/nir_lower_io.c +++ b/src/glsl/nir/nir_lower_io.c @@ -110,6 +110,77 @@ deref_has_indirect(nir_deref_var *deref) return false; } +static bool +mark_indirect_uses_block(nir_block *block, void *void_state) +{ + struct set *indirect_set = void_state; + + nir_foreach_instr(block, instr) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + + for (unsigned i = 0; + i < nir_intrinsic_infos[intrin->intrinsic].num_variables; i++) { + if (deref_has_indirect(intrin->variables[i])) + _mesa_set_add(indirect_set, intrin->variables[i]->var); + } + } + + return true; +} + +/* Identical to nir_assign_var_locations_packed except that it assigns + * locations to the variables that are used 100% directly first and then + * assigns locations to variables that are used indirectly. + */ +void +nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size) +{ + struct set *indirect_set = _mesa_set_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + + nir_foreach_overload(shader, overload) { + if (overload->impl) + nir_foreach_block(overload->impl, mark_indirect_uses_block, + indirect_set); + } + + unsigned location = 0; + + foreach_list_typed(nir_variable, var, node, var_list) { + if (var->data.mode == nir_var_uniform && var->interface_type != NULL) + continue; + + if (_mesa_set_search(indirect_set, var)) + continue; + + var->data.driver_location = location; + location += type_size(var->type); + } + + *direct_size = location; + + foreach_list_typed(nir_variable, var, node, var_list) { + if (var->data.mode == nir_var_uniform && var->interface_type != NULL) + continue; + + if (!_mesa_set_search(indirect_set, var)) + continue; + + var->data.driver_location = location; + location += type_size(var->type); + } + + *size = location; + + _mesa_set_destroy(indirect_set, NULL); +} + static unsigned get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect, struct lower_io_state *state) |