}
static void
+array_stride_decoration_cb(struct vtn_builder *b,
+ struct vtn_value *val, int member,
+ const struct vtn_decoration *dec, void *void_ctx)
+{
+ struct vtn_type *type = val->type;
+
+ if (dec->decoration == SpvDecorationArrayStride) {
+ vtn_fail_if(dec->literals[0] == 0, "ArrayStride must be non-zero");
+ type->stride = dec->literals[0];
+ }
+}
+
+static void
struct_member_decoration_cb(struct vtn_builder *b,
struct vtn_value *val, int member,
const struct vtn_decoration *dec, void *void_ctx)
break;
case SpvDecorationOffset:
ctx->type->offsets[member] = dec->literals[0];
+ ctx->fields[member].offset = dec->literals[0];
break;
case SpvDecorationMatrixStride:
/* Handled as a second pass */
}
}
+/** Chases the array type all the way down to the tail and rewrites the
+ * glsl_types to be based off the tail's glsl_type.
+ */
+static void
+vtn_array_type_rewrite_glsl_type(struct vtn_type *type)
+{
+ if (type->base_type != vtn_base_type_array)
+ return;
+
+ vtn_array_type_rewrite_glsl_type(type->array_element);
+
+ type->type = glsl_array_type(type->array_element->type,
+ type->length, type->stride);
+}
+
/* Matrix strides are handled as a separate pass because we need to know
* whether the matrix is row-major or not first.
*/
vtn_fail_if(member < 0,
"The MatrixStride decoration is only allowed on members "
"of OpTypeStruct");
+ vtn_fail_if(dec->literals[0] == 0, "MatrixStride must be non-zero");
struct member_decoration_ctx *ctx = void_ctx;
mat_type->array_element = vtn_type_copy(b, mat_type->array_element);
mat_type->stride = mat_type->array_element->stride;
mat_type->array_element->stride = dec->literals[0];
+
+ mat_type->type = glsl_explicit_matrix_type(mat_type->type,
+ dec->literals[0], true);
+ mat_type->array_element->type = glsl_get_column_type(mat_type->type);
} else {
vtn_assert(mat_type->array_element->stride > 0);
mat_type->stride = dec->literals[0];
+
+ mat_type->type = glsl_explicit_matrix_type(mat_type->type,
+ dec->literals[0], false);
}
+
+ /* Now that we've replaced the glsl_type with a properly strided matrix
+ * type, rewrite the member type so that it's an array of the proper kind
+ * of glsl_type.
+ */
+ vtn_array_type_rewrite_glsl_type(ctx->type->members[member]);
+ ctx->fields[member].type = ctx->type->members[member]->type;
}
static void
switch (dec->decoration) {
case SpvDecorationArrayStride:
- vtn_assert(type->base_type == vtn_base_type_matrix ||
- type->base_type == vtn_base_type_array ||
+ vtn_assert(type->base_type == vtn_base_type_array ||
type->base_type == vtn_base_type_pointer);
- type->stride = dec->literals[0];
break;
case SpvDecorationBlock:
vtn_assert(type->base_type == vtn_base_type_struct);
}
val->type->base_type = vtn_base_type_array;
- val->type->type = glsl_array_type(array_element->type, val->type->length, 0);
val->type->array_element = array_element;
val->type->stride = 0;
+
+ vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL);
+ val->type->type = glsl_array_type(array_element->type, val->type->length,
+ val->type->stride);
break;
}
val->type->storage_class = storage_class;
val->type->deref = deref_type;
+ vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL);
+
if (storage_class == SpvStorageClassUniform ||
storage_class == SpvStorageClassStorageBuffer) {
/* These can actually be stored to nir_variables and used as SSA
struct vtn_type *ret_type = vtn_callee->type->return_type;
if (ret_type->base_type != vtn_base_type_void) {
nir_variable *ret_tmp =
- nir_local_variable_create(b->nb.impl, ret_type->type, "return_tmp");
+ nir_local_variable_create(b->nb.impl,
+ glsl_get_bare_type(ret_type->type),
+ "return_tmp");
ret_deref = nir_build_deref_var(&b->nb, ret_tmp);
call->params[param_idx++] = nir_src_for_ssa(&ret_deref->dest.ssa);
}
vtn_base_type_void,
"Return with a value from a function returning void");
struct vtn_ssa_value *src = vtn_ssa_value(b, block->branch[1]);
+ const struct glsl_type *ret_type =
+ glsl_get_bare_type(b->func->type->return_type->type);
nir_deref_instr *ret_deref =
nir_build_deref_cast(&b->nb, nir_load_param(&b->nb, 0),
- nir_var_local, src->type);
+ nir_var_local, ret_type);
vtn_local_store(b, src, ret_deref);
}
ptr->block_index = NULL;
ptr->offset = ssa;
} else {
+ assert(!vtn_pointer_is_external_block(b, ptr));
+ const struct glsl_type *deref_type = ptr_type->deref->type;
ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,
- ptr_type->deref->type);
+ glsl_get_bare_type(deref_type));
}
return ptr;
var->var = rzalloc(b->shader, nir_variable);
var->var->name = ralloc_strdup(var->var, val->name);
- /* 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.
- */
if (storage_class == SpvStorageClassAtomicCounter) {
+ /* 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 {
- var->var->type = var->type->type;
+ /* 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 = glsl_get_bare_type(var->type->type);
}
var->var->data.mode = nir_mode;
var->var->data.location = -1;
/* Create the variable normally */
var->var = rzalloc(b->shader, nir_variable);
var->var->name = ralloc_strdup(var->var, val->name);
- var->var->type = var->type->type;
+ /* Workgroup 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 = glsl_get_bare_type(var->type->type);
var->var->data.mode = nir_var_shared;
}
break;
var->var = rzalloc(b->shader, nir_variable);
var->var->name = ralloc_strdup(var->var, val->name);
- var->var->type = var->type->type;
+ /* In Vulkan, shader I/O 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 = glsl_get_bare_type(var->type->type);
var->var->interface_type = interface_type->type;
var->var->data.mode = nir_mode;
var->var->data.patch = var->patch;