From 9e3213ad30fdf121f98dc3e250486c1533047c10 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 29 May 2020 17:57:34 -0500 Subject: [PATCH] spirv: Add a helper for getting the NIR type of a vtn_type There are a few cases, atomic counters being one example, where the type used by vtn_ssa_value is not the same as the type we want NIR to use in derefs and variables. To solve this, we add a helper which converts between the types for us. In the next commit, we'll be adding another major user of this: images and samplers. Part-of: --- src/compiler/spirv/spirv_to_nir.c | 27 ++++++++++++++++++ src/compiler/spirv/vtn_private.h | 4 +++ src/compiler/spirv/vtn_variables.c | 57 ++++++++------------------------------ 3 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 7f595c2..a35dbfc 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -702,6 +702,33 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src) return dest; } +static const struct glsl_type * +wrap_type_in_array(const struct glsl_type *type, + const struct glsl_type *array_type) +{ + if (!glsl_type_is_array(array_type)) + return type; + + const struct glsl_type *elem_type = + wrap_type_in_array(type, glsl_get_array_element(array_type)); + return glsl_array_type(elem_type, glsl_get_length(array_type), + glsl_get_explicit_stride(array_type)); +} + +const struct glsl_type * +vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type, + enum vtn_variable_mode mode) +{ + if (mode == vtn_variable_mode_atomic_counter) { + vtn_fail_if(glsl_without_array(type->type) != glsl_uint_type(), + "Variables in the AtomicCounter storage class should be " + "(possibly arrays of arrays of) uint."); + return wrap_type_in_array(glsl_atomic_uint_type(), type->type); + } + + return type->type; +} + static struct vtn_type * mutable_matrix_member(struct vtn_builder *b, struct vtn_type *type, int member) { diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 3ff28a7..b4e7561 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -562,6 +562,10 @@ struct vtn_variable { enum gl_access_qualifier access; }; +const struct glsl_type * +vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type, + enum vtn_variable_mode mode); + struct vtn_image_pointer { struct vtn_pointer *image; nir_ssa_def *coord; diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 05535bc..a16765e 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -361,7 +361,8 @@ vtn_nir_deref_pointer_dereference(struct vtn_builder *b, nir_variable_mode nir_mode = base->mode == vtn_variable_mode_ssbo ? nir_var_mem_ssbo : nir_var_mem_ubo; - tail = nir_build_deref_cast(&b->nb, desc, nir_mode, type->type, + tail = nir_build_deref_cast(&b->nb, desc, nir_mode, + vtn_type_get_nir_type(b, type, base->mode), base->ptr_type->stride); } else { assert(base->var && base->var->var); @@ -602,29 +603,6 @@ vtn_pointer_dereference(struct vtn_builder *b, } } -/* Returns an atomic_uint type based on the original uint type. The returned - * type will be equivalent to the original one but will have an atomic_uint - * type as leaf instead of an uint. - * - * Manages uint scalars, arrays, and arrays of arrays of any nested depth. - */ -static const struct glsl_type * -repair_atomic_type(const struct glsl_type *type) -{ - assert(glsl_get_base_type(glsl_without_array(type)) == GLSL_TYPE_UINT); - assert(glsl_type_is_scalar(glsl_without_array(type))); - - if (glsl_type_is_array(type)) { - const struct glsl_type *atomic = - repair_atomic_type(glsl_get_array_element(type)); - - return glsl_array_type(atomic, glsl_get_length(type), - glsl_get_explicit_stride(type)); - } else { - return glsl_atomic_uint_type(); - } -} - nir_deref_instr * vtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr) { @@ -2015,7 +1993,8 @@ vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa, ptr->offset = ssa; } } else { - const struct glsl_type *deref_type = ptr_type->deref->type; + const struct glsl_type *deref_type = + vtn_type_get_nir_type(b, ptr_type->deref, ptr->mode); if (!vtn_pointer_is_external_block(b, ptr)) { ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode, deref_type, ptr_type->stride); @@ -2040,8 +2019,7 @@ vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa, * storage class with Block can be used. */ ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode, - ptr_type->deref->type, - ptr_type->stride); + deref_type, ptr_type->stride); ptr->deref->dest.ssa.num_components = glsl_get_vector_elements(ptr_type->type); ptr->deref->dest.ssa.bit_size = glsl_get_bit_size(ptr_type->type); @@ -2195,19 +2173,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, /* For these, we create the variable normally */ var->var = rzalloc(b->shader, nir_variable); var->var->name = ralloc_strdup(var->var, val->name); - - if (var->mode == vtn_variable_mode_atomic_counter) { - /* Need to tweak the nir type here as at vtn_handle_type we don't - * have the access to storage_class, that is the one that points us - * that is an atomic uint. - */ - var->var->type = repair_atomic_type(var->type->type); - } else { - /* Private variables don't have any explicit layout but some layouts - * may have leaked through due to type deduplication in the SPIR-V. - */ - var->var->type = var->type->type; - } + var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); var->var->data.mode = nir_mode; var->var->data.location = -1; var->var->interface_type = NULL; @@ -2218,8 +2184,8 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, var->var = rzalloc(b->shader, nir_variable); var->var->name = ralloc_strdup(var->var, val->name); - var->var->type = var->type->type; - var->var->interface_type = var->type->type; + var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); + var->var->interface_type = var->var->type; var->var->data.mode = nir_mode; var->var->data.location = -1; @@ -2234,7 +2200,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, * layouts may have leaked through due to type deduplication in the * SPIR-V. */ - var->var->type = var->type->type; + var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); var->var->data.mode = nir_var_mem_shared; break; @@ -2291,7 +2257,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, * the SPIR-V. We do, however, keep the layouts in the variable's * interface_type because we need offsets for XFB arrays of blocks. */ - var->var->type = var->type->type; + var->var->type = vtn_type_get_nir_type(b, var->type, var->mode); var->var->data.mode = nir_mode; var->var->data.patch = var->patch; @@ -2309,7 +2275,8 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, iface_type = iface_type->array_element; } if (iface_type->base_type == vtn_base_type_struct && iface_type->block) - var->var->interface_type = iface_type->type; + var->var->interface_type = vtn_type_get_nir_type(b, iface_type, + var->mode); if (per_vertex_type->base_type == vtn_base_type_struct && per_vertex_type->block) { -- 2.7.4