MSL: Fix access chain for deep struct hierarchy on array of buffers.

This commit is contained in:
Hans-Kristian Arntzen 2020-03-31 14:09:36 +02:00
parent 84ec99c531
commit 3cb6aeb480
5 changed files with 107 additions and 1 deletions

View File

@ -0,0 +1,32 @@
#include <metal_stdlib>
#include <simd/simd.h>
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;
}

View File

@ -0,0 +1,33 @@
#include <metal_stdlib>
#include <simd/simd.h>
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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<SPIRType>(var->basetype));
}