diff options
author | Jason Ekstrand <[email protected]> | 2018-10-25 10:34:34 -0500 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2019-01-08 00:38:29 +0000 |
commit | 639c236e74e99524245c22f1fa0758603f558cf2 (patch) | |
tree | 51ba30915624b144e1e416789593619d196a324e /src/compiler/spirv/vtn_variables.c | |
parent | c59f07684c0c99fad0c246dd4a475f6bef5d3cbc (diff) |
spirv: Emit NIR deref instructions on-the-fly
This simplifies our deref handling by emitting the actual NIR deref
instructions on-the-fly instead of of building up a deref chain and then
emitting them at the last moment. In order for this to work with the
parts of the compiler that assume they can chase deref chains, we have
to run nir_rematerialize_derefs_in_use_blocks_impl to put the derefs
back in the right places. Otherwise, in cases such as loop continues
where the SPIR-V blocks are not in the same order as the NIR blocks, we
may end up with a deref chain with a parent that does not dominate it's
child and nir_repair_ssa_impl will insert phis in the deref chain.
Reviewed-by: Alejandro PiƱeiro <[email protected]>
Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]>
Diffstat (limited to 'src/compiler/spirv/vtn_variables.c')
-rw-r--r-- | src/compiler/spirv/vtn_variables.c | 90 |
1 files changed, 31 insertions, 59 deletions
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 23fcd8b54d2..d50e445778e 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -43,21 +43,6 @@ vtn_access_chain_create(struct vtn_builder *b, unsigned length) return chain; } -static struct vtn_access_chain * -vtn_access_chain_extend(struct vtn_builder *b, struct vtn_access_chain *old, - unsigned new_ids) -{ - struct vtn_access_chain *chain; - - unsigned old_len = old ? old->length : 0; - chain = vtn_access_chain_create(b, old_len + new_ids); - - for (unsigned i = 0; i < old_len; i++) - chain->link[i] = old->link[i]; - - return chain; -} - static bool vtn_pointer_uses_ssa_offset(struct vtn_builder *b, struct vtn_pointer *ptr) @@ -82,29 +67,42 @@ vtn_pointer_is_external_block(struct vtn_builder *b, /* Dereference the given base pointer by the access chain */ static struct vtn_pointer * -vtn_access_chain_pointer_dereference(struct vtn_builder *b, - struct vtn_pointer *base, - struct vtn_access_chain *deref_chain) +vtn_nir_deref_pointer_dereference(struct vtn_builder *b, + struct vtn_pointer *base, + struct vtn_access_chain *deref_chain) { - struct vtn_access_chain *chain = - vtn_access_chain_extend(b, base->chain, deref_chain->length); struct vtn_type *type = base->type; enum gl_access_qualifier access = base->access; + nir_deref_instr *tail; + if (base->deref) { + tail = base->deref; + } else { + assert(base->var && base->var->var); + tail = nir_build_deref_var(&b->nb, base->var->var); + } + /* OpPtrAccessChain is only allowed on things which support variable * pointers. For everything else, the client is expected to just pass us * the right access chain. */ vtn_assert(!deref_chain->ptr_as_array); - unsigned start = base->chain ? base->chain->length : 0; for (unsigned i = 0; i < deref_chain->length; i++) { - chain->link[start + i] = deref_chain->link[i]; - if (glsl_type_is_struct(type->type)) { vtn_assert(deref_chain->link[i].mode == vtn_access_mode_literal); - type = type->members[deref_chain->link[i].id]; + unsigned idx = deref_chain->link[i].id; + tail = nir_build_deref_struct(&b->nb, tail, idx); + type = type->members[idx]; } else { + nir_ssa_def *index; + if (deref_chain->link[i].mode == vtn_access_mode_literal) { + index = nir_imm_int(&b->nb, deref_chain->link[i].id); + } else { + vtn_assert(deref_chain->link[i].mode == vtn_access_mode_id); + index = vtn_ssa_value(b, deref_chain->link[i].id)->def; + } + tail = nir_build_deref_array(&b->nb, tail, index); type = type->array_element; } @@ -115,8 +113,7 @@ vtn_access_chain_pointer_dereference(struct vtn_builder *b, ptr->mode = base->mode; ptr->type = type; ptr->var = base->var; - ptr->deref = base->deref; - ptr->chain = chain; + ptr->deref = tail; ptr->access = access; return ptr; @@ -362,7 +359,7 @@ vtn_pointer_dereference(struct vtn_builder *b, if (vtn_pointer_uses_ssa_offset(b, base)) { return vtn_ssa_offset_pointer_dereference(b, base, deref_chain); } else { - return vtn_access_chain_pointer_dereference(b, base, deref_chain); + return vtn_nir_deref_pointer_dereference(b, base, deref_chain); } } @@ -412,39 +409,15 @@ vtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr) if (ptr->var && ptr->var->copy_prop_sampler) return vtn_pointer_to_deref(b, ptr->var->copy_prop_sampler); - nir_deref_instr *tail; - if (ptr->deref) { - tail = ptr->deref; - } else { - assert(ptr->var && ptr->var->var); - tail = nir_build_deref_var(&b->nb, ptr->var->var); - } - - /* Raw variable access */ - if (!ptr->chain) - return tail; - - struct vtn_access_chain *chain = ptr->chain; - vtn_assert(chain); - - for (unsigned i = 0; i < chain->length; i++) { - if (glsl_type_is_struct(tail->type)) { - vtn_assert(chain->link[i].mode == vtn_access_mode_literal); - unsigned idx = chain->link[i].id; - tail = nir_build_deref_struct(&b->nb, tail, idx); - } else { - nir_ssa_def *index; - if (chain->link[i].mode == vtn_access_mode_literal) { - index = nir_imm_int(&b->nb, chain->link[i].id); - } else { - vtn_assert(chain->link[i].mode == vtn_access_mode_id); - index = vtn_ssa_value(b, chain->link[i].id)->def; - } - tail = nir_build_deref_array(&b->nb, tail, index); - } + vtn_assert(!vtn_pointer_uses_ssa_offset(b, ptr)); + if (!ptr->deref) { + struct vtn_access_chain chain = { + .length = 0, + }; + ptr = vtn_nir_deref_pointer_dereference(b, ptr, &chain); } - return tail; + return ptr->deref; } static void @@ -1447,7 +1420,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member, if (val->value_type == vtn_value_type_pointer) { assert(val->pointer->var == void_var); - assert(val->pointer->chain == NULL); assert(member == -1); } else { assert(val->value_type == vtn_value_type_type); |