spirv: Let vtn_ssa_value hold references to variables

In certain cases, we have complex opaque objects that are loaded
into (SPIR-V) SSA values.  To represent these, we now can store a
reference to a variable in vtn_ssa_value.

Also implements a few operations we know will have to be supported,
like Select and Copy.

Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23825>
This commit is contained in:
Caio Oliveira 2023-09-23 01:19:26 -07:00 committed by Marge Bot
parent 3d7e5ec758
commit b17a2c35bc
3 changed files with 74 additions and 2 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;