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
}
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 *
case SpvCapabilityVariablePointersStorageBuffer:
case SpvCapabilityVariablePointers:
spv_check_supported(variable_pointers, cap);
+ b->variable_pointers = true;
break;
case SpvCapabilityStorageUniformBufferBlock16:
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: