diff --git a/reference/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.argument.msl2.frag b/reference/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.argument.msl2.frag new file mode 100644 index 00000000..7c601820 --- /dev/null +++ b/reference/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.argument.msl2.frag @@ -0,0 +1,32 @@ +#include +#include + +using namespace metal; + +struct Foo +{ + float4 v; +}; + +struct UBO +{ + Foo foo; +}; + +struct spvDescriptorSetBuffer0 +{ + constant UBO* ubos [[id(0)]][2]; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +fragment main0_out main0(constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) +{ + main0_out out = {}; + out.FragColor = spvDescriptorSet0.ubos[1]->foo.v; + return out; +} + diff --git a/reference/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.frag b/reference/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.frag new file mode 100644 index 00000000..0b1ca91f --- /dev/null +++ b/reference/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.frag @@ -0,0 +1,33 @@ +#include +#include + +using namespace metal; + +struct Foo +{ + float4 v; +}; + +struct UBO +{ + Foo foo; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +fragment main0_out main0(constant UBO* ubos_0 [[buffer(0)]], constant UBO* ubos_1 [[buffer(1)]]) +{ + constant UBO* ubos[] = + { + ubos_0, + ubos_1, + }; + + main0_out out = {}; + out.FragColor = ubos[1]->foo.v; + return out; +} + diff --git a/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.argument.msl2.frag b/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.argument.msl2.frag new file mode 100644 index 00000000..f3cf0e19 --- /dev/null +++ b/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.argument.msl2.frag @@ -0,0 +1,18 @@ +#version 450 + +struct Foo +{ + vec4 v; +}; + +layout(set = 0, binding = 0) uniform UBO +{ + Foo foo; +} ubos[2]; + +layout(location = 0) out vec4 FragColor; + +void main() +{ + FragColor = ubos[1].foo.v; +} diff --git a/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.frag b/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.frag new file mode 100644 index 00000000..f3cf0e19 --- /dev/null +++ b/shaders-msl-no-opt/frag/ubo-array-multiple-structs-access-chain.frag @@ -0,0 +1,18 @@ +#version 450 + +struct Foo +{ + vec4 v; +}; + +layout(set = 0, binding = 0) uniform UBO +{ + Foo foo; +} ubos[2]; + +layout(location = 0) out vec4 FragColor; + +void main() +{ + FragColor = ubos[1].foo.v; +} diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 361c338a..68d55fa4 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -10505,7 +10505,12 @@ string CompilerMSL::to_member_reference(uint32_t base, const SPIRType &type, uin if (var) { - bool is_buffer_variable = var->storage == StorageClassUniform || var->storage == StorageClassStorageBuffer; + // Only allow -> dereference for block types. This is so we get expressions like + // buffer[i]->first_member.second_member, rather than buffer[i]->first->second. + bool is_block = has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock); + + bool is_buffer_variable = + is_block && (var->storage == StorageClassUniform || var->storage == StorageClassStorageBuffer); declared_as_pointer = is_buffer_variable && is_array(get(var->basetype)); }