diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 0376bc2d324..c876f85091f 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -395,6 +395,27 @@ vtn_push_nir_ssa(struct vtn_builder *b, uint32_t value_id, nir_def *def) return vtn_push_ssa_value(b, value_id, ssa); } +nir_deref_instr * +vtn_get_deref_for_id(struct vtn_builder *b, uint32_t value_id) +{ + return vtn_get_deref_for_ssa_value(b, vtn_ssa_value(b, value_id)); +} + +nir_deref_instr * +vtn_get_deref_for_ssa_value(struct vtn_builder *b, struct vtn_ssa_value *ssa) +{ + vtn_fail_if(!ssa->is_variable, "Expected an SSA value with a nir_variable"); + return nir_build_deref_var(&b->nb, ssa->var); +} + +struct vtn_value * +vtn_push_var_ssa(struct vtn_builder *b, uint32_t value_id, nir_variable *var) +{ + struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, var->type); + vtn_set_ssa_value_var(b, ssa, var); + return vtn_push_ssa_value(b, value_id, ssa); +} + static enum gl_access_qualifier spirv_to_gl_access_qualifier(struct vtn_builder *b, SpvAccessQualifier access_qualifier) @@ -2680,6 +2701,15 @@ vtn_create_ssa_value(struct vtn_builder *b, const struct glsl_type *type) return val; } +void +vtn_set_ssa_value_var(struct vtn_builder *b, struct vtn_ssa_value *ssa, nir_variable *var) +{ + vtn_assert(glsl_type_is_cmat(var->type)); + vtn_assert(var->type == ssa->type); + ssa->is_variable = true; + ssa->var = var; +} + static nir_tex_src vtn_tex_src(struct vtn_builder *b, unsigned index, nir_tex_src_type type) { @@ -4163,6 +4193,8 @@ vtn_vector_construct(struct vtn_builder *b, unsigned num_components, static struct vtn_ssa_value * vtn_composite_copy(void *mem_ctx, struct vtn_ssa_value *src) { + assert(!src->is_variable); + struct vtn_ssa_value *dest = rzalloc(mem_ctx, struct vtn_ssa_value); dest->type = src->type; @@ -5668,7 +5700,27 @@ vtn_nir_select(struct vtn_builder *b, struct vtn_ssa_value *src0, struct vtn_ssa_value *dest = rzalloc(b, struct vtn_ssa_value); dest->type = src1->type; - if (glsl_type_is_vector_or_scalar(src1->type)) { + if (src1->is_variable || src2->is_variable) { + vtn_assert(src1->is_variable && src2->is_variable); + + nir_variable *dest_var = + nir_local_variable_create(b->nb.impl, dest->type, "var_select"); + nir_deref_instr *dest_deref = nir_build_deref_var(&b->nb, dest_var); + + nir_push_if(&b->nb, src0->def); + { + nir_deref_instr *src1_deref = vtn_get_deref_for_ssa_value(b, src1); + vtn_local_store(b, vtn_local_load(b, src1_deref, 0), dest_deref, 0); + } + nir_push_else(&b->nb, NULL); + { + nir_deref_instr *src2_deref = vtn_get_deref_for_ssa_value(b, src2); + vtn_local_store(b, vtn_local_load(b, src2_deref, 0), dest_deref, 0); + } + nir_pop_if(&b->nb, NULL); + + vtn_set_ssa_value_var(b, dest, dest_var); + } else if (glsl_type_is_vector_or_scalar(src1->type)) { dest->def = nir_bcsel(&b->nb, src0->def, src1->def, src2->def); } else { unsigned elems = glsl_get_length(src1->type); diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index e295e12b11c..66c5cdbbea2 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -251,8 +251,11 @@ vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start, const uint32_t *end, vtn_instruction_handler handler); struct vtn_ssa_value { + bool is_variable; + union { nir_def *def; + nir_variable *var; struct vtn_ssa_value **elems; }; @@ -856,6 +859,10 @@ struct vtn_value *vtn_push_ssa_value(struct vtn_builder *b, uint32_t value_id, nir_def *vtn_get_nir_ssa(struct vtn_builder *b, uint32_t value_id); struct vtn_value *vtn_push_nir_ssa(struct vtn_builder *b, uint32_t value_id, nir_def *def); +nir_deref_instr *vtn_get_deref_for_id(struct vtn_builder *b, uint32_t value_id); +nir_deref_instr *vtn_get_deref_for_ssa_value(struct vtn_builder *b, struct vtn_ssa_value *ssa); +struct vtn_value *vtn_push_var_ssa(struct vtn_builder *b, uint32_t value_id, + nir_variable *var); struct vtn_value *vtn_push_pointer(struct vtn_builder *b, uint32_t value_id, @@ -875,6 +882,7 @@ vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id, struct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b, const struct glsl_type *type); +void vtn_set_ssa_value_var(struct vtn_builder *b, struct vtn_ssa_value *ssa, nir_variable *var); struct vtn_ssa_value *vtn_ssa_transpose(struct vtn_builder *b, struct vtn_ssa_value *src); diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 9b627c0557d..9e14d695e12 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -139,7 +139,6 @@ vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id, { struct vtn_value *src = vtn_untyped_value(b, src_value_id); struct vtn_value *dst = vtn_untyped_value(b, dst_value_id); - struct vtn_value src_copy = *src; vtn_fail_if(dst->value_type != vtn_value_type_invalid, "SPIR-V id %u has already been written by another instruction", @@ -148,6 +147,19 @@ vtn_copy_value(struct vtn_builder *b, uint32_t src_value_id, vtn_fail_if(dst->type->id != src->type->id, "Result Type must equal Operand type"); + if (src->value_type == vtn_value_type_ssa && src->ssa->is_variable) { + nir_variable *dst_var = + nir_local_variable_create(b->nb.impl, src->ssa->type, "var_copy"); + nir_deref_instr *dst_deref = nir_build_deref_var(&b->nb, dst_var); + nir_deref_instr *src_deref = vtn_get_deref_for_ssa_value(b, src->ssa); + + vtn_local_store(b, vtn_local_load(b, src_deref, 0), dst_deref, 0); + + vtn_push_var_ssa(b, dst_value_id, dst_var); + return; + } + + struct vtn_value src_copy = *src; src_copy.name = dst->name; src_copy.decoration = dst->decoration; src_copy.type = dst->type;