MSL: Implement OpArrayLength.

This gets rather complicated because MSL does not support OpArrayLength
natively. We need to pass down a buffer which contains buffer sizes, and
we compute the array length on-demand.

Support both discrete descriptors as well as argument buffers.
This commit is contained in:
Hans-Kristian Arntzen 2019-05-27 11:59:29 +02:00
parent 3cd89c0c0a
commit 7b9e0fb428
24 changed files with 553 additions and 128 deletions

View File

@ -287,7 +287,7 @@ if (SPIRV_CROSS_STATIC)
endif()
set(spirv-cross-abi-major 0)
set(spirv-cross-abi-minor 10)
set(spirv-cross-abi-minor 11)
set(spirv-cross-abi-patch 0)
if (SPIRV_CROSS_SHARED)

View File

@ -0,0 +1,29 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct SSBO
{
uint size;
float4 v[1];
};
struct SSBO1
{
float bz[1];
};
kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device SSBO& _14 [[buffer(1)]], device SSBO1* ssbos_0 [[buffer(2)]], device SSBO1* ssbos_1 [[buffer(3)]])
{
device SSBO1* ssbos[] =
{
ssbos_0,
ssbos_1,
};
constant uint& _14BufferSize = spvBufferSizeConstants[1];
constant uint* ssbosBufferSize = &spvBufferSizeConstants[2];
_14.size = uint(int((_14BufferSize - 16) / 16) + int((ssbosBufferSize[1] - 0) / 4));
}

View File

@ -0,0 +1,53 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct SSBO
{
uint size;
float4 v[1];
};
struct SSBO1
{
float bz[1];
};
struct SSBO2
{
uint size2;
float w[1];
};
struct SSBO3
{
float bz[1];
};
struct spvDescriptorSetBuffer0
{
constant uint* spvBufferSizeConstants [[id(0)]];
device SSBO* m_16 [[id(1)]];
};
struct spvDescriptorSetBuffer1
{
constant uint* spvBufferSizeConstants [[id(1)]];
device SSBO1* ssbos [[id(2)]][2];
};
kernel void main0(constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant spvDescriptorSetBuffer1& spvDescriptorSet1 [[buffer(1)]], constant uint* spvBufferSizeConstants [[buffer(25)]], device SSBO3* ssbos2_0 [[buffer(2)]], device SSBO3* ssbos2_1 [[buffer(3)]])
{
device SSBO3* ssbos2[] =
{
ssbos2_0,
ssbos2_1,
};
constant uint& spvDescriptorSet0_m_16BufferSize = spvDescriptorSet0.spvBufferSizeConstants[1];
constant uint* spvDescriptorSet1_ssbosBufferSize = &spvDescriptorSet1.spvBufferSizeConstants[2];
constant uint* ssbos2BufferSize = &spvBufferSizeConstants[2];
(*spvDescriptorSet0.m_16).size = ((uint(int((spvDescriptorSet0_m_16BufferSize - 16) / 16)) + uint(int((spvDescriptorSet1_ssbosBufferSize[1] - 0) / 4))) + uint(int((_38BufferSize - 16) / 16))) + uint(int((ssbos2BufferSize[0] - 0) / 4));
}

View File

@ -127,7 +127,7 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
{
constant uint32_t& fooSwzl = spvSwizzleConstants[0];
constant uint& fooSwzl = spvSwizzleConstants[0];
bar.write(spvTextureSwizzle(foo.sample(fooSmplr, float2(1.0), level(0.0)), fooSwzl), uint2(int2(0)));
}

View File

@ -145,8 +145,8 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> uSampler1 [[texture(0)]], sampler uSampler1Smplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* spvDescriptorSet0_uSampler0Swzl = &spvDescriptorSet0.spvSwizzleConstants[1];
constant uint32_t& uSampler1Swzl = spvSwizzleConstants[0];
constant uint* spvDescriptorSet0_uSampler0Swzl = &spvDescriptorSet0.spvSwizzleConstants[1];
constant uint& uSampler1Swzl = spvSwizzleConstants[0];
out.FragColor = spvTextureSwizzle(spvDescriptorSet0.uSampler0[2].sample(spvDescriptorSet0.uSampler0Smplr[2], in.vUV), spvDescriptorSet0_uSampler0Swzl[2]);
out.FragColor += spvTextureSwizzle(uSampler1.sample(uSampler1Smplr, in.vUV), uSampler1Swzl);
out.FragColor += spvTextureSwizzle(spvDescriptorSet0.uSampler0[1].sample(spvDescriptorSet0.uSampler0Smplr[1], in.vUV), spvDescriptorSet0_uSampler0Swzl[1]);

View File

@ -138,7 +138,7 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvSwizzleConstants [[buffer(30)]], array<texture2d<float>, 4> uSampler [[texture(0)]], array<sampler, 4> uSamplerSmplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* uSamplerSwzl = &spvSwizzleConstants[0];
constant uint* uSamplerSwzl = &spvSwizzleConstants[0];
out.FragColor = spvTextureSwizzle(uSampler[2].sample(uSamplerSmplr[2], in.vUV), uSamplerSwzl[2]);
out.FragColor += spvTextureSwizzle(uSampler[1].sample(uSamplerSmplr[1], in.vUV), uSamplerSwzl[1]);
return out;

View File

@ -133,16 +133,16 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSamp [[sampler(0)]], sampler tex2dSamp [[sampler(1)]], sampler tex3dSamp [[sampler(2)]], sampler texCubeSamp [[sampler(3)]], sampler tex2dArraySamp [[sampler(4)]], sampler texCubeArraySamp [[sampler(5)]], sampler depth2dSamp [[sampler(7)]], sampler depthCubeSamp [[sampler(8)]], sampler depth2dArraySamp [[sampler(9)]], sampler depthCubeArraySamp [[sampler(10)]])
{
constant uint32_t& tex1dSwzl = spvSwizzleConstants[0];
constant uint32_t& tex2dSwzl = spvSwizzleConstants[1];
constant uint32_t& tex3dSwzl = spvSwizzleConstants[2];
constant uint32_t& texCubeSwzl = spvSwizzleConstants[3];
constant uint32_t& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint32_t& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint32_t& depth2dSwzl = spvSwizzleConstants[7];
constant uint32_t& depthCubeSwzl = spvSwizzleConstants[8];
constant uint32_t& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint32_t& depthCubeArraySwzl = spvSwizzleConstants[10];
constant uint& tex1dSwzl = spvSwizzleConstants[0];
constant uint& tex2dSwzl = spvSwizzleConstants[1];
constant uint& tex3dSwzl = spvSwizzleConstants[2];
constant uint& texCubeSwzl = spvSwizzleConstants[3];
constant uint& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint& depth2dSwzl = spvSwizzleConstants[7];
constant uint& depthCubeSwzl = spvSwizzleConstants[8];
constant uint& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint& depthCubeArraySwzl = spvSwizzleConstants[10];
float4 c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), tex1dSwzl);
c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0)), tex2dSwzl);
c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0)), tex3dSwzl);

View File

@ -133,12 +133,12 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<int> tex1d [[texture(0)]], texture2d<int> tex2d [[texture(1)]], texture3d<int> tex3d [[texture(2)]], texturecube<int> texCube [[texture(3)]], texture2d_array<int> tex2dArray [[texture(4)]], texturecube_array<int> texCubeArray [[texture(5)]], texture2d<int> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
{
constant uint32_t& tex1dSwzl = spvSwizzleConstants[0];
constant uint32_t& tex2dSwzl = spvSwizzleConstants[1];
constant uint32_t& tex3dSwzl = spvSwizzleConstants[2];
constant uint32_t& texCubeSwzl = spvSwizzleConstants[3];
constant uint32_t& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint32_t& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint& tex1dSwzl = spvSwizzleConstants[0];
constant uint& tex2dSwzl = spvSwizzleConstants[1];
constant uint& tex3dSwzl = spvSwizzleConstants[2];
constant uint& texCubeSwzl = spvSwizzleConstants[3];
constant uint& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint& texCubeArraySwzl = spvSwizzleConstants[5];
float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl));

View File

@ -131,7 +131,7 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr, constant uint32_t& tex1dSwzl, thread texture2d<float> tex2d, thread const sampler tex2dSmplr, constant uint32_t& tex2dSwzl, thread texture3d<float> tex3d, thread const sampler tex3dSmplr, constant uint32_t& tex3dSwzl, thread texturecube<float> texCube, thread const sampler texCubeSmplr, constant uint32_t& texCubeSwzl, thread texture2d_array<float> tex2dArray, thread const sampler tex2dArraySmplr, constant uint32_t& tex2dArraySwzl, thread texturecube_array<float> texCubeArray, thread const sampler texCubeArraySmplr, constant uint32_t& texCubeArraySwzl, thread depth2d<float> depth2d, thread const sampler depth2dSmplr, constant uint32_t& depth2dSwzl, thread depthcube<float> depthCube, thread const sampler depthCubeSmplr, constant uint32_t& depthCubeSwzl, thread depth2d_array<float> depth2dArray, thread const sampler depth2dArraySmplr, constant uint32_t& depth2dArraySwzl, thread depthcube_array<float> depthCubeArray, thread const sampler depthCubeArraySmplr, constant uint32_t& depthCubeArraySwzl, thread texture2d<float> texBuffer)
float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr, constant uint& tex1dSwzl, thread texture2d<float> tex2d, thread const sampler tex2dSmplr, constant uint& tex2dSwzl, thread texture3d<float> tex3d, thread const sampler tex3dSmplr, constant uint& tex3dSwzl, thread texturecube<float> texCube, thread const sampler texCubeSmplr, constant uint& texCubeSwzl, thread texture2d_array<float> tex2dArray, thread const sampler tex2dArraySmplr, constant uint& tex2dArraySwzl, thread texturecube_array<float> texCubeArray, thread const sampler texCubeArraySmplr, constant uint& texCubeArraySwzl, thread depth2d<float> depth2d, thread const sampler depth2dSmplr, constant uint& depth2dSwzl, thread depthcube<float> depthCube, thread const sampler depthCubeSmplr, constant uint& depthCubeSwzl, thread depth2d_array<float> depth2dArray, thread const sampler depth2dArraySmplr, constant uint& depth2dArraySwzl, thread depthcube_array<float> depthCubeArray, thread const sampler depthCubeArraySmplr, constant uint& depthCubeArraySwzl, thread texture2d<float> texBuffer)
{
float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl);
@ -180,16 +180,16 @@ float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr,
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
{
constant uint32_t& tex1dSwzl = spvSwizzleConstants[0];
constant uint32_t& tex2dSwzl = spvSwizzleConstants[1];
constant uint32_t& tex3dSwzl = spvSwizzleConstants[2];
constant uint32_t& texCubeSwzl = spvSwizzleConstants[3];
constant uint32_t& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint32_t& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint32_t& depth2dSwzl = spvSwizzleConstants[7];
constant uint32_t& depthCubeSwzl = spvSwizzleConstants[8];
constant uint32_t& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint32_t& depthCubeArraySwzl = spvSwizzleConstants[10];
constant uint& tex1dSwzl = spvSwizzleConstants[0];
constant uint& tex2dSwzl = spvSwizzleConstants[1];
constant uint& tex3dSwzl = spvSwizzleConstants[2];
constant uint& texCubeSwzl = spvSwizzleConstants[3];
constant uint& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint& depth2dSwzl = spvSwizzleConstants[7];
constant uint& depthCubeSwzl = spvSwizzleConstants[8];
constant uint& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint& depthCubeArraySwzl = spvSwizzleConstants[10];
float4 c = doSwizzle(tex1d, tex1dSmplr, tex1dSwzl, tex2d, tex2dSmplr, tex2dSwzl, tex3d, tex3dSmplr, tex3dSwzl, texCube, texCubeSmplr, texCubeSwzl, tex2dArray, tex2dArraySmplr, tex2dArraySwzl, texCubeArray, texCubeArraySmplr, texCubeArraySwzl, depth2d, depth2dSmplr, depth2dSwzl, depthCube, depthCubeSmplr, depthCubeSwzl, depth2dArray, depth2dArraySmplr, depth2dArraySwzl, depthCubeArray, depthCubeArraySmplr, depthCubeArraySwzl, texBuffer);
}

View File

@ -133,12 +133,12 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<uint> tex1d [[texture(0)]], texture2d<uint> tex2d [[texture(1)]], texture3d<uint> tex3d [[texture(2)]], texturecube<uint> texCube [[texture(3)]], texture2d_array<uint> tex2dArray [[texture(4)]], texturecube_array<uint> texCubeArray [[texture(5)]], texture2d<uint> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
{
constant uint32_t& tex1dSwzl = spvSwizzleConstants[0];
constant uint32_t& tex2dSwzl = spvSwizzleConstants[1];
constant uint32_t& tex3dSwzl = spvSwizzleConstants[2];
constant uint32_t& texCubeSwzl = spvSwizzleConstants[3];
constant uint32_t& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint32_t& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint& tex1dSwzl = spvSwizzleConstants[0];
constant uint& tex2dSwzl = spvSwizzleConstants[1];
constant uint& tex3dSwzl = spvSwizzleConstants[2];
constant uint& texCubeSwzl = spvSwizzleConstants[3];
constant uint& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint& texCubeArraySwzl = spvSwizzleConstants[5];
float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl));

View File

@ -133,16 +133,16 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
{
constant uint32_t& tex1dSwzl = spvSwizzleConstants[0];
constant uint32_t& tex2dSwzl = spvSwizzleConstants[1];
constant uint32_t& tex3dSwzl = spvSwizzleConstants[2];
constant uint32_t& texCubeSwzl = spvSwizzleConstants[3];
constant uint32_t& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint32_t& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint32_t& depth2dSwzl = spvSwizzleConstants[7];
constant uint32_t& depthCubeSwzl = spvSwizzleConstants[8];
constant uint32_t& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint32_t& depthCubeArraySwzl = spvSwizzleConstants[10];
constant uint& tex1dSwzl = spvSwizzleConstants[0];
constant uint& tex2dSwzl = spvSwizzleConstants[1];
constant uint& tex3dSwzl = spvSwizzleConstants[2];
constant uint& texCubeSwzl = spvSwizzleConstants[3];
constant uint& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint& depth2dSwzl = spvSwizzleConstants[7];
constant uint& depthCubeSwzl = spvSwizzleConstants[8];
constant uint& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint& depthCubeArraySwzl = spvSwizzleConstants[10];
float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl);

View File

@ -136,7 +136,7 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
float4 do_samples(thread const texture1d<float> t1, thread const sampler t1Smplr, constant uint32_t& t1Swzl, thread const texture2d<float> t2, constant uint32_t& t2Swzl, thread const texture3d<float> t3, thread const sampler t3Smplr, constant uint32_t& t3Swzl, thread const texturecube<float> tc, constant uint32_t& tcSwzl, thread const texture2d_array<float> t2a, thread const sampler t2aSmplr, constant uint32_t& t2aSwzl, thread const texturecube_array<float> tca, thread const sampler tcaSmplr, constant uint32_t& tcaSwzl, thread const texture2d<float> tb, thread const depth2d<float> d2, thread const sampler d2Smplr, constant uint32_t& d2Swzl, thread const depthcube<float> dc, thread const sampler dcSmplr, constant uint32_t& dcSwzl, thread const depth2d_array<float> d2a, constant uint32_t& d2aSwzl, thread const depthcube_array<float> dca, thread const sampler dcaSmplr, constant uint32_t& dcaSwzl, thread sampler defaultSampler, thread sampler shadowSampler)
float4 do_samples(thread const texture1d<float> t1, thread const sampler t1Smplr, constant uint& t1Swzl, thread const texture2d<float> t2, constant uint& t2Swzl, thread const texture3d<float> t3, thread const sampler t3Smplr, constant uint& t3Swzl, thread const texturecube<float> tc, constant uint& tcSwzl, thread const texture2d_array<float> t2a, thread const sampler t2aSmplr, constant uint& t2aSwzl, thread const texturecube_array<float> tca, thread const sampler tcaSmplr, constant uint& tcaSwzl, thread const texture2d<float> tb, thread const depth2d<float> d2, thread const sampler d2Smplr, constant uint& d2Swzl, thread const depthcube<float> dc, thread const sampler dcSmplr, constant uint& dcSwzl, thread const depth2d_array<float> d2a, constant uint& d2aSwzl, thread const depthcube_array<float> dca, thread const sampler dcaSmplr, constant uint& dcaSwzl, thread sampler defaultSampler, thread sampler shadowSampler)
{
float4 c = spvTextureSwizzle(t1.sample(t1Smplr, 0.0), t1Swzl);
c = spvTextureSwizzle(t2.sample(defaultSampler, float2(0.0)), t2Swzl);
@ -186,16 +186,16 @@ float4 do_samples(thread const texture1d<float> t1, thread const sampler t1Smplr
fragment main0_out main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex3dSmplr [[sampler(2)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depthCubeArraySmplr [[sampler(10)]], sampler defaultSampler [[sampler(11)]], sampler shadowSampler [[sampler(12)]])
{
main0_out out = {};
constant uint32_t& tex1dSwzl = spvSwizzleConstants[0];
constant uint32_t& tex2dSwzl = spvSwizzleConstants[1];
constant uint32_t& tex3dSwzl = spvSwizzleConstants[2];
constant uint32_t& texCubeSwzl = spvSwizzleConstants[3];
constant uint32_t& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint32_t& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint32_t& depth2dSwzl = spvSwizzleConstants[7];
constant uint32_t& depthCubeSwzl = spvSwizzleConstants[8];
constant uint32_t& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint32_t& depthCubeArraySwzl = spvSwizzleConstants[10];
constant uint& tex1dSwzl = spvSwizzleConstants[0];
constant uint& tex2dSwzl = spvSwizzleConstants[1];
constant uint& tex3dSwzl = spvSwizzleConstants[2];
constant uint& texCubeSwzl = spvSwizzleConstants[3];
constant uint& tex2dArraySwzl = spvSwizzleConstants[4];
constant uint& texCubeArraySwzl = spvSwizzleConstants[5];
constant uint& depth2dSwzl = spvSwizzleConstants[7];
constant uint& depthCubeSwzl = spvSwizzleConstants[8];
constant uint& depth2dArraySwzl = spvSwizzleConstants[9];
constant uint& depthCubeArraySwzl = spvSwizzleConstants[10];
out.fragColor = do_samples(tex1d, tex1dSmplr, tex1dSwzl, tex2d, tex2dSwzl, tex3d, tex3dSmplr, tex3dSwzl, texCube, texCubeSwzl, tex2dArray, tex2dArraySmplr, tex2dArraySwzl, texCubeArray, texCubeArraySmplr, texCubeArraySwzl, texBuffer, depth2d, depth2dSmplr, depth2dSwzl, depthCube, depthCubeSmplr, depthCubeSwzl, depth2dArray, depth2dArraySwzl, depthCubeArray, depthCubeArraySmplr, depthCubeArraySwzl, defaultSampler, shadowSampler);
return out;
}

View File

@ -0,0 +1,36 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct SSBO
{
uint size;
float4 v[1];
};
struct SSBO1
{
float bz[1];
};
uint get_size(device SSBO& v_14, constant uint& v_14BufferSize, device SSBO1* (&ssbos)[2], constant uint* ssbosBufferSize)
{
return uint(int((v_14BufferSize - 16) / 16) + int((ssbosBufferSize[1] - 0) / 4));
}
kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device SSBO& v_14 [[buffer(1)]], device SSBO1* ssbos_0 [[buffer(2)]], device SSBO1* ssbos_1 [[buffer(3)]])
{
device SSBO1* ssbos[] =
{
ssbos_0,
ssbos_1,
};
constant uint& v_14BufferSize = spvBufferSizeConstants[1];
constant uint* ssbosBufferSize = &spvBufferSizeConstants[2];
v_14.size = get_size(v_14, v_14BufferSize, ssbos, ssbosBufferSize);
}

View File

@ -0,0 +1,64 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct SSBO
{
uint size;
float4 v[1];
};
struct SSBO1
{
float bz[1];
};
struct SSBO2
{
uint size2;
float w[1];
};
struct SSBO3
{
float bz[1];
};
struct spvDescriptorSetBuffer0
{
constant uint* spvBufferSizeConstants [[id(0)]];
device SSBO* v_16 [[id(1)]];
};
struct spvDescriptorSetBuffer1
{
constant uint* spvBufferSizeConstants [[id(1)]];
device SSBO1* ssbos [[id(2)]][2];
};
uint get_size(device SSBO& v_16, constant uint& v_16BufferSize, device SSBO1* constant (&ssbos)[2], constant uint* ssbosBufferSize, device SSBO2& v_38, constant uint& v_38BufferSize, device SSBO3* constant (&ssbos2)[2], constant uint* ssbos2BufferSize)
{
uint len = uint(int((v_16BufferSize - 16) / 16));
len += uint(int((ssbosBufferSize[1] - 0) / 4));
len += uint(int((v_38BufferSize - 16) / 16));
len += uint(int((ssbos2BufferSize[0] - 0) / 4));
return len;
}
kernel void main0(constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant spvDescriptorSetBuffer1& spvDescriptorSet1 [[buffer(1)]], constant uint* spvBufferSizeConstants [[buffer(25)]], device SSBO3* ssbos2_0 [[buffer(2)]], device SSBO3* ssbos2_1 [[buffer(3)]])
{
device SSBO3* ssbos2[] =
{
ssbos2_0,
ssbos2_1,
};
constant uint& spvDescriptorSet0_v_16BufferSize = spvDescriptorSet0.spvBufferSizeConstants[1];
constant uint* spvDescriptorSet1_ssbosBufferSize = &spvDescriptorSet1.spvBufferSizeConstants[2];
constant uint* ssbos2BufferSize = &spvBufferSizeConstants[2];
(*spvDescriptorSet0.v_16).size = get_size((*spvDescriptorSet0.v_16), spvDescriptorSet0_v_16BufferSize, spvDescriptorSet1.ssbos, spvDescriptorSet1_ssbosBufferSize, v_38, v_38BufferSize, ssbos2, ssbos2BufferSize);
}

View File

@ -127,7 +127,7 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
{
constant uint32_t& fooSwzl = spvSwizzleConstants[0];
constant uint& fooSwzl = spvSwizzleConstants[0];
float4 a = spvTextureSwizzle(foo.sample(fooSmplr, float2(1.0), level(0.0)), fooSwzl);
bar.write(a, uint2(int2(0)));
}

View File

@ -142,17 +142,17 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
float4 sample_in_func_1(thread const array<texture2d<float>, 4> uSampler0, thread const array<sampler, 4> uSampler0Smplr, constant uint32_t* uSampler0Swzl, thread float2& vUV)
float4 sample_in_func_1(thread const array<texture2d<float>, 4> uSampler0, thread const array<sampler, 4> uSampler0Smplr, constant uint* uSampler0Swzl, thread float2& vUV)
{
return spvTextureSwizzle(uSampler0[2].sample(uSampler0Smplr[2], vUV), uSampler0Swzl[2]);
}
float4 sample_in_func_2(thread float2& vUV, thread texture2d<float> uSampler1, thread const sampler uSampler1Smplr, constant uint32_t& uSampler1Swzl)
float4 sample_in_func_2(thread float2& vUV, thread texture2d<float> uSampler1, thread const sampler uSampler1Smplr, constant uint& uSampler1Swzl)
{
return spvTextureSwizzle(uSampler1.sample(uSampler1Smplr, vUV), uSampler1Swzl);
}
float4 sample_single_in_func(thread const texture2d<float> s, thread const sampler sSmplr, constant uint32_t& sSwzl, thread float2& vUV)
float4 sample_single_in_func(thread const texture2d<float> s, thread const sampler sSmplr, constant uint& sSwzl, thread float2& vUV)
{
return spvTextureSwizzle(s.sample(sSmplr, vUV), sSwzl);
}
@ -160,8 +160,8 @@ float4 sample_single_in_func(thread const texture2d<float> s, thread const sampl
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> uSampler1 [[texture(0)]], sampler uSampler1Smplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* spvDescriptorSet0_uSampler0Swzl = &spvDescriptorSet0.spvSwizzleConstants[1];
constant uint32_t& uSampler1Swzl = spvSwizzleConstants[0];
constant uint* spvDescriptorSet0_uSampler0Swzl = &spvDescriptorSet0.spvSwizzleConstants[1];
constant uint& uSampler1Swzl = spvSwizzleConstants[0];
out.FragColor = sample_in_func_1(spvDescriptorSet0.uSampler0, spvDescriptorSet0.uSampler0Smplr, spvDescriptorSet0_uSampler0Swzl, in.vUV);
out.FragColor += sample_in_func_2(in.vUV, uSampler1, uSampler1Smplr, uSampler1Swzl);
out.FragColor += sample_single_in_func(spvDescriptorSet0.uSampler0[1], spvDescriptorSet0.uSampler0Smplr[1], spvDescriptorSet0_uSampler0Swzl[1], in.vUV);

View File

@ -135,12 +135,12 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
float4 sample_in_func(thread const array<texture2d<float>, 4> uSampler, thread const array<sampler, 4> uSamplerSmplr, constant uint32_t* uSamplerSwzl, thread float2& vUV)
float4 sample_in_func(thread const array<texture2d<float>, 4> uSampler, thread const array<sampler, 4> uSamplerSmplr, constant uint* uSamplerSwzl, thread float2& vUV)
{
return spvTextureSwizzle(uSampler[2].sample(uSamplerSmplr[2], vUV), uSamplerSwzl[2]);
}
float4 sample_single_in_func(thread const texture2d<float> s, thread const sampler sSmplr, constant uint32_t& sSwzl, thread float2& vUV)
float4 sample_single_in_func(thread const texture2d<float> s, thread const sampler sSmplr, constant uint& sSwzl, thread float2& vUV)
{
return spvTextureSwizzle(s.sample(sSmplr, vUV), sSwzl);
}
@ -148,7 +148,7 @@ float4 sample_single_in_func(thread const texture2d<float> s, thread const sampl
fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvSwizzleConstants [[buffer(30)]], array<texture2d<float>, 4> uSampler [[texture(0)]], array<sampler, 4> uSamplerSmplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* uSamplerSwzl = &spvSwizzleConstants[0];
constant uint* uSamplerSwzl = &spvSwizzleConstants[0];
out.FragColor = sample_in_func(uSampler, uSamplerSmplr, uSamplerSwzl, in.vUV);
out.FragColor += sample_single_in_func(uSampler[1], uSamplerSmplr[1], uSamplerSwzl[1], in.vUV);
return out;

View File

@ -0,0 +1,22 @@
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 1, std140) buffer SSBO
{
uint size;
float v[];
};
layout(set = 0, binding = 2, std430) buffer SSBO1
{
float bz[];
} ssbos[2];
uint get_size()
{
return v.length() + ssbos[1].bz.length();
}
void main()
{
size = get_size();
}

View File

@ -0,0 +1,38 @@
#version 450
layout(local_size_x = 1) in;
layout(set = 0, binding = 1, std140) buffer SSBO
{
uint size;
float v[];
};
layout(set = 1, binding = 2, std430) buffer SSBO1
{
float bz[];
} ssbos[2];
layout(set = 2, binding = 1, std140) buffer SSBO2
{
uint size2;
float w[];
};
layout(set = 3, binding = 2, std430) buffer SSBO3
{
float bz[];
} ssbos2[2];
uint get_size()
{
uint len = v.length();
len += ssbos[1].bz.length();
len += w.length();
len += ssbos2[0].bz.length();
return len;
}
void main()
{
size = get_size();
}

View File

@ -538,6 +538,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_MSL_TEXTURE_BUFFER_NATIVE:
options->msl.texture_buffer_native = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_BUFFER_SIZE_BUFFER_INDEX:
options->msl.buffer_size_buffer_index = value;
break;
#endif
default:
@ -748,6 +752,23 @@ spvc_bool spvc_compiler_msl_needs_swizzle_buffer(spvc_compiler compiler)
#endif
}
spvc_bool spvc_compiler_msl_needs_buffer_size_buffer(spvc_compiler compiler)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_FALSE;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
return msl.needs_buffer_size_buffer() ? SPVC_TRUE : SPVC_FALSE;
#else
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_FALSE;
#endif
}
spvc_bool spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler)
{
return spvc_compiler_msl_needs_swizzle_buffer(compiler);

View File

@ -33,7 +33,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 10
#define SPVC_C_API_VERSION_MINOR 11
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@ -302,6 +302,7 @@ SPVC_PUBLIC_API void spvc_msl_resource_binding_init(spvc_msl_resource_binding *b
#define SPVC_MSL_PUSH_CONSTANT_DESC_SET (~(0u))
#define SPVC_MSL_PUSH_CONSTANT_BINDING (0)
#define SPVC_MSL_SWIZZLE_BUFFER_BINDING (~(1u))
#define SPVC_MSL_BUFFER_SIZE_BUFFER_BINDING (~(2u))
/* Obsolete. Sticks around for backwards compatibility. */
#define SPVC_MSL_AUX_BUFFER_STRUCT_VERSION 1
@ -446,6 +447,8 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS = 35 | SPVC_COMPILER_OPTION_GLSL_BIT,
SPVC_COMPILER_OPTION_MSL_BUFFER_SIZE_BUFFER_INDEX = 36 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;
@ -527,6 +530,7 @@ SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_rasterization_disabled(spvc_compi
/* Obsolete. Renamed to needs_swizzle_buffer. */
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler);
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_swizzle_buffer(spvc_compiler compiler);
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_buffer_size_buffer(spvc_compiler compiler);
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_output_buffer(spvc_compiler compiler);
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_patch_output_buffer(spvc_compiler compiler);

View File

@ -2764,13 +2764,22 @@ string CompilerGLSL::dereference_expression(const SPIRType &expr_type, const std
string CompilerGLSL::address_of_expression(const std::string &expr)
{
// If this expression starts with a dereference operator ('*'), then
// just return the part after the operator.
// TODO: Strip parens if unnecessary?
if (expr.front() == '*')
if (expr.size() > 3 && expr[0] == '(' && expr[1] == '*' && expr.back() == ')')
{
// If we have an expression which looks like (*foo), taking the address of it is the same as stripping
// the first two and last characters. We might have to enclose the expression.
// This doesn't work for cases like (*foo + 10),
// but this is an r-value expression which we cannot take the address of anyways.
return enclose_expression(expr.substr(2, expr.size() - 3));
}
else if (expr.front() == '*')
{
// If this expression starts with a dereference operator ('*'), then
// just return the part after the operator.
return expr.substr(1);
}
else
return join('&', expr);
return join('&', enclose_expression(expr));
}
// Just like to_expression except that we enclose the expression inside parentheses if needed.

View File

@ -387,38 +387,54 @@ void CompilerMSL::build_implicit_builtins()
if (needs_swizzle_buffer_def)
{
uint32_t offset = ir.increase_bound_by(4);
uint32_t type_id = offset;
uint32_t type_ptr_id = offset + 1;
uint32_t type_ptr_ptr_id = offset + 2;
uint32_t var_id = offset + 3;
// Create a buffer to hold extra data, including the swizzle constants.
SPIRType uint_type;
uint_type.basetype = SPIRType::UInt;
uint_type.width = 32;
set<SPIRType>(type_id, uint_type);
SPIRType uint_type_pointer = uint_type;
uint_type_pointer.pointer = true;
uint_type_pointer.pointer_depth = 1;
uint_type_pointer.parent_type = type_id;
uint_type_pointer.storage = StorageClassUniform;
set<SPIRType>(type_ptr_id, uint_type_pointer);
set_decoration(type_ptr_id, DecorationArrayStride, 4);
SPIRType uint_type_pointer2 = uint_type_pointer;
uint_type_pointer2.pointer_depth++;
uint_type_pointer2.parent_type = type_ptr_id;
set<SPIRType>(type_ptr_ptr_id, uint_type_pointer2);
set<SPIRVariable>(var_id, type_ptr_ptr_id, StorageClassUniformConstant);
uint32_t var_id = build_constant_uint_array_pointer();
set_name(var_id, "spvSwizzleConstants");
// This should never match anything.
set_decoration(var_id, DecorationDescriptorSet, 0xFFFFFFFE);
set_decoration(var_id, DecorationDescriptorSet, kSwizzleBufferBinding);
set_decoration(var_id, DecorationBinding, msl_options.swizzle_buffer_index);
swizzle_buffer_id = var_id;
}
if (!buffers_requiring_array_length.empty())
{
uint32_t var_id = build_constant_uint_array_pointer();
set_name(var_id, "spvBufferSizeConstants");
// This should never match anything.
set_decoration(var_id, DecorationDescriptorSet, kBufferSizeBufferBinding);
set_decoration(var_id, DecorationBinding, msl_options.buffer_size_buffer_index);
buffer_size_buffer_id = var_id;
}
}
uint32_t CompilerMSL::build_constant_uint_array_pointer()
{
uint32_t offset = ir.increase_bound_by(4);
uint32_t type_id = offset;
uint32_t type_ptr_id = offset + 1;
uint32_t type_ptr_ptr_id = offset + 2;
uint32_t var_id = offset + 3;
// Create a buffer to hold extra data, including the swizzle constants.
SPIRType uint_type;
uint_type.basetype = SPIRType::UInt;
uint_type.width = 32;
set<SPIRType>(type_id, uint_type);
SPIRType uint_type_pointer = uint_type;
uint_type_pointer.pointer = true;
uint_type_pointer.pointer_depth = 1;
uint_type_pointer.parent_type = type_id;
uint_type_pointer.storage = StorageClassUniform;
set<SPIRType>(type_ptr_id, uint_type_pointer);
set_decoration(type_ptr_id, DecorationArrayStride, 4);
SPIRType uint_type_pointer2 = uint_type_pointer;
uint_type_pointer2.pointer_depth++;
uint_type_pointer2.parent_type = type_ptr_id;
set<SPIRType>(type_ptr_ptr_id, uint_type_pointer2);
set<SPIRVariable>(var_id, type_ptr_ptr_id, StorageClassUniformConstant);
return var_id;
}
static string create_sampler_address(const char *prefix, MSLSamplerAddress addr)
@ -667,6 +683,8 @@ string CompilerMSL::compile()
set_enabled_interface_variables(get_active_interface_variables());
if (swizzle_buffer_id)
active_interface_variables.insert(swizzle_buffer_id);
if (buffer_size_buffer_id)
active_interface_variables.insert(buffer_size_buffer_id);
// Create structs to hold input, output and uniform variables.
// Do output first to ensure out. is declared at top of entry function.
@ -846,6 +864,7 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
case OpInBoundsAccessChain:
case OpAccessChain:
case OpPtrAccessChain:
case OpArrayLength:
{
uint32_t base_id = ops[2];
if (global_var_ids.find(base_id) != global_var_ids.end())
@ -4029,6 +4048,17 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
break;
}
case OpArrayLength:
{
auto &type = expression_type(ops[2]);
uint32_t offset = type_struct_member_offset(type, ops[3]);
uint32_t stride = type_struct_member_array_stride(type, ops[3]);
auto expr = join("(", to_buffer_size_expression(ops[2]), " - ", offset, ") / ", stride);
emit_op(ops[0], ops[1], expr, true);
break;
}
default:
CompilerGLSL::emit_instruction(instruction);
break;
@ -4560,7 +4590,13 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(arg_type))
{
bool arg_is_array = !arg_type.array.empty();
decl += join(", constant uint32_t", arg_is_array ? "* " : "& ", to_swizzle_expression(arg.id));
decl += join(", constant uint", arg_is_array ? "* " : "& ", to_swizzle_expression(arg.id));
}
if (buffers_requiring_array_length.count(name_id))
{
bool arg_is_array = !arg_type.array.empty();
decl += join(", constant uint", arg_is_array ? "* " : "& ", to_buffer_size_expression(name_id));
}
if (&arg != &func.arguments.back())
@ -5040,17 +5076,20 @@ string CompilerMSL::to_func_call_arg(uint32_t id)
arg_str += ", " + to_sampler_expression(var_id ? var_id : id);
}
uint32_t var_id = 0;
auto *var = maybe_get<SPIRVariable>(id);
if (var)
var_id = var->basevariable;
if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
{
// Need to check the base variable in case we need to apply a qualified alias.
uint32_t var_id = 0;
auto *sampler_var = maybe_get<SPIRVariable>(id);
if (sampler_var)
var_id = sampler_var->basevariable;
arg_str += ", " + to_swizzle_expression(var_id ? var_id : id);
}
if (buffers_requiring_array_length.count(var_id))
arg_str += ", " + to_buffer_size_expression(var_id ? var_id : id);
return arg_str;
}
@ -5099,6 +5138,32 @@ string CompilerMSL::to_swizzle_expression(uint32_t id)
}
}
string CompilerMSL::to_buffer_size_expression(uint32_t id)
{
auto expr = to_expression(id);
auto index = expr.find_first_of('[');
// This is quite crude, but we need to translate the reference name (*spvDescriptorSetN.name) to
// the pointer expression spvDescriptorSetN.name to make a reasonable expression here.
// This only happens if we have argument buffers and we are using OpArrayLength on a lone SSBO in that set.
if (expr.size() >= 3 && expr[0] == '(' && expr[1] == '*')
expr = address_of_expression(expr);
// If a buffer is part of an argument buffer translate this to a legal identifier.
for (auto &c : expr)
if (c == '.')
c = '_';
if (index == string::npos)
return expr + buffer_size_name_suffix;
else
{
auto buffer_expr = expr.substr(0, index);
auto array_expr = expr.substr(index);
return buffer_expr + buffer_size_name_suffix + array_expr;
}
}
// Checks whether the type is a Block all of whose members have DecorationPatch.
bool CompilerMSL::is_patch_block(const SPIRType &type)
{
@ -6049,15 +6114,13 @@ string CompilerMSL::entry_point_args_classic(bool append_comma)
void CompilerMSL::fix_up_shader_inputs_outputs()
{
// Look for sampled images. Add hooks to set up the swizzle constants.
// Look for sampled images and buffer. Add hooks to set up the swizzle constants or array lengths.
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
auto &type = get_variable_data_type(var);
uint32_t var_id = var.self;
bool ssbo = has_decoration(type.self, DecorationBufferBlock);
if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
var.storage == StorageClassPushConstant || var.storage == StorageClassStorageBuffer) &&
!is_hidden_variable(var))
if (var.storage == StorageClassUniformConstant && !is_hidden_variable(var))
{
if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
{
@ -6068,7 +6131,7 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
uint32_t desc_set = get_decoration(var_id, DecorationDescriptorSet);
if (descriptor_set_is_argument_buffer(desc_set))
{
statement("constant uint32_t", is_array_type ? "* " : "& ", to_swizzle_expression(var_id),
statement("constant uint", is_array_type ? "* " : "& ", to_swizzle_expression(var_id),
is_array_type ? " = &" : " = ", to_name(argument_buffer_ids[desc_set]),
".spvSwizzleConstants", "[",
convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];");
@ -6076,13 +6139,39 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
else
{
// If we have an array of images, we need to be able to index into it, so take a pointer instead.
statement("constant uint32_t", is_array_type ? "* " : "& ", to_swizzle_expression(var_id),
statement("constant uint", is_array_type ? "* " : "& ", to_swizzle_expression(var_id),
is_array_type ? " = &" : " = ", to_name(swizzle_buffer_id), "[",
convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];");
}
});
}
}
else if ((var.storage == StorageClassStorageBuffer || (var.storage == StorageClassUniform && ssbo)) && !is_hidden_variable(var))
{
if (buffers_requiring_array_length.count(var.self))
{
auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
entry_func.fixup_hooks_in.push_back([this, &type, &var, var_id]() {
bool is_array_type = !type.array.empty();
uint32_t desc_set = get_decoration(var_id, DecorationDescriptorSet);
if (descriptor_set_is_argument_buffer(desc_set))
{
statement("constant uint", is_array_type ? "* " : "& ", to_buffer_size_expression(var_id),
is_array_type ? " = &" : " = ", to_name(argument_buffer_ids[desc_set]),
".spvBufferSizeConstants", "[",
convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];");
}
else
{
// If we have an array of images, we need to be able to index into it, so take a pointer instead.
statement("constant uint", is_array_type ? "* " : "& ", to_buffer_size_expression(var_id),
is_array_type ? " = &" : " = ", to_name(buffer_size_buffer_id), "[",
convert_to_string(get_metal_resource_index(var, type.basetype)), "];");
}
});
}
}
});
// Builtin variables
@ -7849,6 +7938,28 @@ bool CompilerMSL::OpCodePreprocessor::handle(Op opcode, const uint32_t *args, ui
needs_subgroup_invocation_id = true;
break;
case OpArrayLength:
{
auto *var = compiler.maybe_get_backing_variable(args[2]);
if (var)
compiler.buffers_requiring_array_length.insert(var->self);
break;
}
case OpInBoundsAccessChain:
case OpAccessChain:
case OpPtrAccessChain:
{
// OpArrayLength might want to know if taking ArrayLength of an array of SSBOs.
uint32_t result_type = args[0];
uint32_t id = args[1];
uint32_t ptr = args[2];
compiler.set<SPIRExpression>(id, "", result_type, true);
compiler.register_read(id, ptr, true);
compiler.ir.ids[id].set_allow_type_rewrite();
break;
}
default:
break;
}
@ -8244,6 +8355,8 @@ void CompilerMSL::analyze_argument_buffers()
SmallVector<Resource> resources_in_set[kMaxArgumentBuffers];
bool set_needs_swizzle_buffer[kMaxArgumentBuffers] = {};
bool set_needs_buffer_sizes[kMaxArgumentBuffers] = {};
bool needs_buffer_sizes = false;
ir.for_each_typed_id<SPIRVariable>([&](uint32_t self, SPIRVariable &var) {
if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
@ -8292,24 +8405,29 @@ void CompilerMSL::analyze_argument_buffers()
// Check if this descriptor set needs a swizzle buffer.
if (needs_swizzle_buffer_def && is_sampled_image_type(type))
set_needs_swizzle_buffer[desc_set] = true;
else if (buffers_requiring_array_length.count(var_id) != 0)
{
set_needs_buffer_sizes[desc_set] = true;
needs_buffer_sizes = true;
}
}
});
if (needs_swizzle_buffer_def)
if (needs_swizzle_buffer_def || needs_buffer_sizes)
{
uint32_t swizzle_buffer_type_id = 0;
uint32_t uint_ptr_type_id = 0;
// We might have to add a swizzle buffer resource to the set.
for (uint32_t desc_set = 0; desc_set < kMaxArgumentBuffers; desc_set++)
{
if (!set_needs_swizzle_buffer[desc_set])
if (!set_needs_swizzle_buffer[desc_set] && !set_needs_buffer_sizes[desc_set])
continue;
if (swizzle_buffer_type_id == 0)
if (uint_ptr_type_id == 0)
{
uint32_t offset = ir.increase_bound_by(2);
uint32_t type_id = offset;
swizzle_buffer_type_id = offset + 1;
uint_ptr_type_id = offset + 1;
// Create a buffer to hold extra data, including the swizzle constants.
SPIRType uint_type;
@ -8322,17 +8440,31 @@ void CompilerMSL::analyze_argument_buffers()
uint_type_pointer.pointer_depth = 1;
uint_type_pointer.parent_type = type_id;
uint_type_pointer.storage = StorageClassUniform;
set<SPIRType>(swizzle_buffer_type_id, uint_type_pointer);
set_decoration(swizzle_buffer_type_id, DecorationArrayStride, 4);
set<SPIRType>(uint_ptr_type_id, uint_type_pointer);
set_decoration(uint_ptr_type_id, DecorationArrayStride, 4);
}
uint32_t var_id = ir.increase_bound_by(1);
auto &var = set<SPIRVariable>(var_id, swizzle_buffer_type_id, StorageClassUniformConstant);
set_name(var_id, "spvSwizzleConstants");
set_decoration(var_id, DecorationDescriptorSet, desc_set);
set_decoration(var_id, DecorationBinding, kSwizzleBufferBinding);
resources_in_set[desc_set].push_back(
{ &var, to_name(var_id), SPIRType::UInt, get_metal_resource_index(var, SPIRType::UInt) });
if (set_needs_swizzle_buffer[desc_set])
{
uint32_t var_id = ir.increase_bound_by(1);
auto &var = set<SPIRVariable>(var_id, uint_ptr_type_id, StorageClassUniformConstant);
set_name(var_id, "spvSwizzleConstants");
set_decoration(var_id, DecorationDescriptorSet, desc_set);
set_decoration(var_id, DecorationBinding, kSwizzleBufferBinding);
resources_in_set[desc_set].push_back(
{ &var, to_name(var_id), SPIRType::UInt, get_metal_resource_index(var, SPIRType::UInt) });
}
if (set_needs_buffer_sizes[desc_set])
{
uint32_t var_id = ir.increase_bound_by(1);
auto &var = set<SPIRVariable>(var_id, uint_ptr_type_id, StorageClassUniformConstant);
set_name(var_id, "spvBufferSizeConstants");
set_decoration(var_id, DecorationDescriptorSet, desc_set);
set_decoration(var_id, DecorationBinding, kBufferSizeBufferBinding);
resources_in_set[desc_set].push_back(
{ &var, to_name(var_id), SPIRType::UInt, get_metal_resource_index(var, SPIRType::UInt) });
}
}
}

View File

@ -156,6 +156,10 @@ static const uint32_t kPushConstBinding = 0;
// element to indicate the buffer binding for swizzle buffers.
static const uint32_t kSwizzleBufferBinding = ~(1u);
// Special constant used in a MSLResourceBinding binding
// element to indicate the buffer binding for buffer size buffers to support OpArrayLength.
static const uint32_t kBufferSizeBufferBinding = ~(2u);
static const uint32_t kMaxArgumentBuffers = 8;
// Decompiles SPIR-V to Metal Shading Language
@ -179,6 +183,7 @@ public:
uint32_t shader_output_buffer_index = 28;
uint32_t shader_patch_output_buffer_index = 27;
uint32_t shader_tess_factor_buffer_index = 26;
uint32_t buffer_size_buffer_index = 25;
uint32_t shader_input_wg_index = 0;
bool enable_point_size_builtin = true;
bool disable_rasterization = false;
@ -249,6 +254,13 @@ public:
return used_swizzle_buffer;
}
// Provide feedback to calling API to allow it to pass a buffer
// containing STORAGE_BUFFER buffer sizes to support OpArrayLength.
bool needs_buffer_size_buffer() const
{
return !buffers_requiring_array_length.empty();
}
// Provide feedback to calling API to allow it to pass an output
// buffer if the shader needs it.
bool needs_output_buffer() const
@ -446,6 +458,7 @@ protected:
std::string ensure_valid_name(std::string name, std::string pfx);
std::string to_sampler_expression(uint32_t id);
std::string to_swizzle_expression(uint32_t id);
std::string to_buffer_size_expression(uint32_t id);
std::string builtin_qualifier(spv::BuiltIn builtin);
std::string builtin_type_decl(spv::BuiltIn builtin);
std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
@ -475,6 +488,7 @@ protected:
void emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem);
void emit_array_copy(const std::string &lhs, uint32_t rhs_id) override;
void build_implicit_builtins();
uint32_t build_constant_uint_array_pointer();
void emit_entry_point_declarations() override;
uint32_t builtin_frag_coord_id = 0;
uint32_t builtin_sample_id_id = 0;
@ -487,6 +501,7 @@ protected:
uint32_t builtin_subgroup_invocation_id_id = 0;
uint32_t builtin_subgroup_size_id = 0;
uint32_t swizzle_buffer_id = 0;
uint32_t buffer_size_buffer_id = 0;
void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
@ -535,6 +550,7 @@ protected:
std::string patch_stage_out_var_name = "patchOut";
std::string sampler_name_suffix = "Smplr";
std::string swizzle_name_suffix = "Swzl";
std::string buffer_size_name_suffix = "BufferSize";
std::string input_wg_var_name = "gl_in";
std::string output_buffer_var_name = "spvOut";
std::string patch_output_buffer_var_name = "spvPatchOut";
@ -542,6 +558,7 @@ protected:
spv::Op previous_instruction_opcode = spv::OpNop;
std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers;
std::unordered_set<uint32_t> buffers_requiring_array_length;
SmallVector<uint32_t> buffer_arrays;
uint32_t argument_buffer_ids[kMaxArgumentBuffers];