nir: Remove deref chain support from lower_var_copies
Acked-by: Rob Clark <robdclark@gmail.com> Acked-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Acked-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
parent
fc59230a46
commit
c6a9c2b60b
|
@ -34,128 +34,6 @@
|
||||||
* Lowers all copy intrinsics to sequences of load/store intrinsics.
|
* Lowers all copy intrinsics to sequences of load/store intrinsics.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Walks down the deref chain and returns the next deref in the chain whose
|
|
||||||
* child is a wildcard. In other words, given the chain a[1].foo[*].bar,
|
|
||||||
* this function will return the deref to foo. Calling it a second time
|
|
||||||
* with the [*].bar, it will return NULL.
|
|
||||||
*/
|
|
||||||
static nir_deref *
|
|
||||||
deref_next_wildcard_parent(nir_deref *deref)
|
|
||||||
{
|
|
||||||
for (nir_deref *tail = deref; tail->child; tail = tail->child) {
|
|
||||||
if (tail->child->deref_type != nir_deref_type_array)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
nir_deref_array *arr = nir_deref_as_array(tail->child);
|
|
||||||
|
|
||||||
if (arr->deref_array_type == nir_deref_array_type_wildcard)
|
|
||||||
return tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function recursively walks the given deref chain and replaces the
|
|
||||||
* given copy instruction with an equivalent sequence load/store
|
|
||||||
* operations.
|
|
||||||
*
|
|
||||||
* @copy_instr The copy instruction to replace; new instructions will be
|
|
||||||
* inserted before this one
|
|
||||||
*
|
|
||||||
* @dest_head The head of the destination variable deref chain
|
|
||||||
*
|
|
||||||
* @src_head The head of the source variable deref chain
|
|
||||||
*
|
|
||||||
* @dest_tail The current tail of the destination variable deref chain;
|
|
||||||
* this is used for recursion and external callers of this
|
|
||||||
* function should call it with tail == head
|
|
||||||
*
|
|
||||||
* @src_tail The current tail of the source variable deref chain;
|
|
||||||
* this is used for recursion and external callers of this
|
|
||||||
* function should call it with tail == head
|
|
||||||
*
|
|
||||||
* @state The current variable lowering state
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
emit_copy_load_store(nir_intrinsic_instr *copy_instr,
|
|
||||||
nir_deref_var *dest_head, nir_deref_var *src_head,
|
|
||||||
nir_deref *dest_tail, nir_deref *src_tail,
|
|
||||||
nir_shader *shader)
|
|
||||||
{
|
|
||||||
/* Find the next pair of wildcards */
|
|
||||||
nir_deref *src_arr_parent = deref_next_wildcard_parent(src_tail);
|
|
||||||
nir_deref *dest_arr_parent = deref_next_wildcard_parent(dest_tail);
|
|
||||||
|
|
||||||
if (src_arr_parent || dest_arr_parent) {
|
|
||||||
/* Wildcards had better come in matched pairs */
|
|
||||||
assert(src_arr_parent && dest_arr_parent);
|
|
||||||
|
|
||||||
nir_deref_array *src_arr = nir_deref_as_array(src_arr_parent->child);
|
|
||||||
nir_deref_array *dest_arr = nir_deref_as_array(dest_arr_parent->child);
|
|
||||||
|
|
||||||
unsigned length = glsl_get_length(src_arr_parent->type);
|
|
||||||
/* The wildcards should represent the same number of elements */
|
|
||||||
assert(length == glsl_get_length(dest_arr_parent->type));
|
|
||||||
assert(length > 0);
|
|
||||||
|
|
||||||
/* Walk over all of the elements that this wildcard refers to and
|
|
||||||
* call emit_copy_load_store on each one of them */
|
|
||||||
src_arr->deref_array_type = nir_deref_array_type_direct;
|
|
||||||
dest_arr->deref_array_type = nir_deref_array_type_direct;
|
|
||||||
for (unsigned i = 0; i < length; i++) {
|
|
||||||
src_arr->base_offset = i;
|
|
||||||
dest_arr->base_offset = i;
|
|
||||||
emit_copy_load_store(copy_instr, dest_head, src_head,
|
|
||||||
&dest_arr->deref, &src_arr->deref, shader);
|
|
||||||
}
|
|
||||||
src_arr->deref_array_type = nir_deref_array_type_wildcard;
|
|
||||||
dest_arr->deref_array_type = nir_deref_array_type_wildcard;
|
|
||||||
} else {
|
|
||||||
/* In this case, we have no wildcards anymore, so all we have to do
|
|
||||||
* is just emit the load and store operations. */
|
|
||||||
src_tail = nir_deref_tail(src_tail);
|
|
||||||
dest_tail = nir_deref_tail(dest_tail);
|
|
||||||
|
|
||||||
assert(src_tail->type == dest_tail->type);
|
|
||||||
|
|
||||||
unsigned num_components = glsl_get_vector_elements(src_tail->type);
|
|
||||||
unsigned bit_size = glsl_get_bit_size(src_tail->type);
|
|
||||||
|
|
||||||
nir_intrinsic_instr *load =
|
|
||||||
nir_intrinsic_instr_create(shader, nir_intrinsic_load_var);
|
|
||||||
load->num_components = num_components;
|
|
||||||
load->variables[0] = nir_deref_var_clone(src_head, load);
|
|
||||||
nir_ssa_dest_init(&load->instr, &load->dest, num_components, bit_size,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
nir_instr_insert_before(©_instr->instr, &load->instr);
|
|
||||||
|
|
||||||
nir_intrinsic_instr *store =
|
|
||||||
nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
|
|
||||||
store->num_components = num_components;
|
|
||||||
nir_intrinsic_set_write_mask(store, (1 << num_components) - 1);
|
|
||||||
store->variables[0] = nir_deref_var_clone(dest_head, store);
|
|
||||||
|
|
||||||
store->src[0].is_ssa = true;
|
|
||||||
store->src[0].ssa = &load->dest.ssa;
|
|
||||||
|
|
||||||
nir_instr_insert_before(©_instr->instr, &store->instr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lowers a copy instruction to a sequence of load/store instructions
|
|
||||||
*
|
|
||||||
* The new instructions are placed before the copy instruction in the IR.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
nir_lower_var_copy_instr(nir_intrinsic_instr *copy, nir_shader *shader)
|
|
||||||
{
|
|
||||||
assert(copy->intrinsic == nir_intrinsic_copy_var);
|
|
||||||
emit_copy_load_store(copy, copy->variables[0], copy->variables[1],
|
|
||||||
©->variables[0]->deref,
|
|
||||||
©->variables[1]->deref, shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
static nir_deref_instr *
|
static nir_deref_instr *
|
||||||
build_deref_to_next_wildcard(nir_builder *b,
|
build_deref_to_next_wildcard(nir_builder *b,
|
||||||
nir_deref_instr *parent,
|
nir_deref_instr *parent,
|
||||||
|
@ -237,7 +115,6 @@ nir_lower_deref_copy_instr(nir_builder *b, nir_intrinsic_instr *copy)
|
||||||
static bool
|
static bool
|
||||||
lower_var_copies_impl(nir_function_impl *impl)
|
lower_var_copies_impl(nir_function_impl *impl)
|
||||||
{
|
{
|
||||||
nir_shader *shader = impl->function->shader;
|
|
||||||
bool progress = false;
|
bool progress = false;
|
||||||
|
|
||||||
nir_builder b;
|
nir_builder b;
|
||||||
|
@ -249,18 +126,15 @@ lower_var_copies_impl(nir_function_impl *impl)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nir_intrinsic_instr *copy = nir_instr_as_intrinsic(instr);
|
nir_intrinsic_instr *copy = nir_instr_as_intrinsic(instr);
|
||||||
if (copy->intrinsic == nir_intrinsic_copy_var)
|
if (copy->intrinsic != nir_intrinsic_copy_deref)
|
||||||
nir_lower_var_copy_instr(copy, shader);
|
|
||||||
else if (copy->intrinsic == nir_intrinsic_copy_deref)
|
|
||||||
nir_lower_deref_copy_instr(&b, copy);
|
|
||||||
else
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
nir_lower_deref_copy_instr(&b, copy);
|
||||||
|
|
||||||
nir_instr_remove(©->instr);
|
nir_instr_remove(©->instr);
|
||||||
if (copy->intrinsic == nir_intrinsic_copy_deref) {
|
nir_deref_instr_remove_if_unused(nir_src_as_deref(copy->src[0]));
|
||||||
nir_deref_instr_remove_if_unused(nir_src_as_deref(copy->src[0]));
|
nir_deref_instr_remove_if_unused(nir_src_as_deref(copy->src[1]));
|
||||||
nir_deref_instr_remove_if_unused(nir_src_as_deref(copy->src[1]));
|
|
||||||
}
|
|
||||||
progress = true;
|
progress = true;
|
||||||
ralloc_free(copy);
|
ralloc_free(copy);
|
||||||
}
|
}
|
||||||
|
@ -281,6 +155,8 @@ nir_lower_var_copies(nir_shader *shader)
|
||||||
{
|
{
|
||||||
bool progress = false;
|
bool progress = false;
|
||||||
|
|
||||||
|
nir_assert_unlowered_derefs(shader, nir_lower_load_store_derefs);
|
||||||
|
|
||||||
nir_foreach_function(function, shader) {
|
nir_foreach_function(function, shader) {
|
||||||
if (function->impl)
|
if (function->impl)
|
||||||
progress |= lower_var_copies_impl(function->impl);
|
progress |= lower_var_copies_impl(function->impl);
|
||||||
|
|
Loading…
Reference in New Issue