summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/spirv/spirv_to_nir.c35
-rw-r--r--src/compiler/spirv/vtn_private.h1
-rw-r--r--src/compiler/spirv/vtn_variables.c17
3 files changed, 53 insertions, 0 deletions
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index cf07eedd972..2968c735f32 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -563,6 +563,29 @@ struct member_decoration_ctx {
struct vtn_type *type;
};
+/**
+ * Returns true if the given type contains a struct decorated Block or
+ * BufferBlock
+ */
+static bool
+vtn_type_contains_block(struct vtn_builder *b, struct vtn_type *type)
+{
+ switch (type->base_type) {
+ case vtn_base_type_array:
+ return vtn_type_contains_block(b, type->array_element);
+ case vtn_base_type_struct:
+ if (type->block || type->buffer_block)
+ return true;
+ for (unsigned i = 0; i < type->length; i++) {
+ if (vtn_type_contains_block(b, type->members[i]))
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
/** Returns true if two types are "compatible", i.e. you can do an OpLoad,
* OpStore, or OpCopyMemory between them without breaking anything.
* Technically, the SPIR-V rules require the exact same type ID but this lets
@@ -1375,6 +1398,17 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
}
vtn_foreach_decoration(b, val, type_decoration_cb, NULL);
+
+ if (val->type->base_type == vtn_base_type_struct &&
+ (val->type->block || val->type->buffer_block)) {
+ for (unsigned i = 0; i < val->type->length; i++) {
+ vtn_fail_if(vtn_type_contains_block(b, val->type->members[i]),
+ "Block and BufferBlock decorations cannot decorate a "
+ "structure type that is nested at any level inside "
+ "another structure type decorated with Block or "
+ "BufferBlock.");
+ }
+ }
}
static nir_constant *
@@ -3598,6 +3632,7 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvCapabilityVariablePointersStorageBuffer:
case SpvCapabilityVariablePointers:
spv_check_supported(variable_pointers, cap);
+ b->variable_pointers = true;
break;
case SpvCapabilityStorageUniformBufferBlock16:
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index 35739255510..342d4b74d71 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -586,6 +586,7 @@ struct vtn_builder {
struct vtn_value *entry_point;
bool origin_upper_left;
bool pixel_center_integer;
+ bool variable_pointers;
struct vtn_function *func;
struct exec_list functions;
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index c177952d7e1..7e80263abf3 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -1686,9 +1686,26 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
switch (mode) {
case vtn_variable_mode_ubo:
+ /* There's no other way to get vtn_variable_mode_ubo */
+ vtn_assert(without_array->block);
b->shader->info.num_ubos++;
break;
case vtn_variable_mode_ssbo:
+ if (storage_class == SpvStorageClassStorageBuffer &&
+ !without_array->block) {
+ if (b->variable_pointers) {
+ vtn_fail("Variables in the StorageBuffer storage class must "
+ "have a struct type with the Block decoration");
+ } else {
+ /* If variable pointers are not present, it's still malformed
+ * SPIR-V but we can parse it and do the right thing anyway.
+ * Since some of the 8-bit storage tests have bugs in this are,
+ * just make it a warning for now.
+ */
+ vtn_warn("Variables in the StorageBuffer storage class must "
+ "have a struct type with the Block decoration");
+ }
+ }
b->shader->info.num_ssbos++;
break;
case vtn_variable_mode_uniform: