diff --git a/CMakeLists.txt b/CMakeLists.txt index 210ac0ab..316945c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/reference/opt/shaders-msl/comp/array-length.comp b/reference/opt/shaders-msl/comp/array-length.comp new file mode 100644 index 00000000..5e65e71d --- /dev/null +++ b/reference/opt/shaders-msl/comp/array-length.comp @@ -0,0 +1,29 @@ +#include +#include + +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)); +} + diff --git a/reference/opt/shaders-msl/comp/array-length.msl2.argument.discrete.comp b/reference/opt/shaders-msl/comp/array-length.msl2.argument.discrete.comp new file mode 100644 index 00000000..6244b041 --- /dev/null +++ b/reference/opt/shaders-msl/comp/array-length.msl2.argument.discrete.comp @@ -0,0 +1,53 @@ +#include +#include + +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)); +} + diff --git a/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp b/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp index 2d9d423e..7cb8913d 100644 --- a/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp +++ b/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp @@ -127,7 +127,7 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d foo [[texture(0)]], texture2d 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))); } diff --git a/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag b/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag index b8e8f9d8..67a5c2c8 100644 --- a/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag +++ b/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag @@ -145,8 +145,8 @@ inline vec 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 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]); diff --git a/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag b/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag index 8e97cab9..337abb99 100644 --- a/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag +++ b/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag @@ -138,7 +138,7 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvSwizzleConstants [[buffer(30)]], array, 4> uSampler [[texture(0)]], array 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; diff --git a/reference/shaders-msl-no-opt/asm/frag/texture-access.swizzle.asm.frag b/reference/shaders-msl-no-opt/asm/frag/texture-access.swizzle.asm.frag index 68445b79..1652c8c8 100644 --- a/reference/shaders-msl-no-opt/asm/frag/texture-access.swizzle.asm.frag +++ b/reference/shaders-msl-no-opt/asm/frag/texture-access.swizzle.asm.frag @@ -133,16 +133,16 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d texBuffer [[texture(6)]], depth2d depth2d [[texture(7)]], depthcube depthCube [[texture(8)]], depth2d_array depth2dArray [[texture(9)]], depthcube_array 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); diff --git a/reference/shaders-msl-no-opt/frag/texture-access-int.swizzle.frag b/reference/shaders-msl-no-opt/frag/texture-access-int.swizzle.frag index 3f854e70..4cb0fdd5 100644 --- a/reference/shaders-msl-no-opt/frag/texture-access-int.swizzle.frag +++ b/reference/shaders-msl-no-opt/frag/texture-access-int.swizzle.frag @@ -133,12 +133,12 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d 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)); diff --git a/reference/shaders-msl-no-opt/frag/texture-access-leaf.swizzle.frag b/reference/shaders-msl-no-opt/frag/texture-access-leaf.swizzle.frag index 01a5ae64..2b11faa0 100644 --- a/reference/shaders-msl-no-opt/frag/texture-access-leaf.swizzle.frag +++ b/reference/shaders-msl-no-opt/frag/texture-access-leaf.swizzle.frag @@ -131,7 +131,7 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -float4 doSwizzle(thread texture1d tex1d, thread const sampler tex1dSmplr, constant uint32_t& tex1dSwzl, thread texture2d tex2d, thread const sampler tex2dSmplr, constant uint32_t& tex2dSwzl, thread texture3d tex3d, thread const sampler tex3dSmplr, constant uint32_t& tex3dSwzl, thread texturecube texCube, thread const sampler texCubeSmplr, constant uint32_t& texCubeSwzl, thread texture2d_array tex2dArray, thread const sampler tex2dArraySmplr, constant uint32_t& tex2dArraySwzl, thread texturecube_array texCubeArray, thread const sampler texCubeArraySmplr, constant uint32_t& texCubeArraySwzl, thread depth2d depth2d, thread const sampler depth2dSmplr, constant uint32_t& depth2dSwzl, thread depthcube depthCube, thread const sampler depthCubeSmplr, constant uint32_t& depthCubeSwzl, thread depth2d_array depth2dArray, thread const sampler depth2dArraySmplr, constant uint32_t& depth2dArraySwzl, thread depthcube_array depthCubeArray, thread const sampler depthCubeArraySmplr, constant uint32_t& depthCubeArraySwzl, thread texture2d texBuffer) +float4 doSwizzle(thread texture1d tex1d, thread const sampler tex1dSmplr, constant uint& tex1dSwzl, thread texture2d tex2d, thread const sampler tex2dSmplr, constant uint& tex2dSwzl, thread texture3d tex3d, thread const sampler tex3dSmplr, constant uint& tex3dSwzl, thread texturecube texCube, thread const sampler texCubeSmplr, constant uint& texCubeSwzl, thread texture2d_array tex2dArray, thread const sampler tex2dArraySmplr, constant uint& tex2dArraySwzl, thread texturecube_array texCubeArray, thread const sampler texCubeArraySmplr, constant uint& texCubeArraySwzl, thread depth2d depth2d, thread const sampler depth2dSmplr, constant uint& depth2dSwzl, thread depthcube depthCube, thread const sampler depthCubeSmplr, constant uint& depthCubeSwzl, thread depth2d_array depth2dArray, thread const sampler depth2dArraySmplr, constant uint& depth2dArraySwzl, thread depthcube_array depthCubeArray, thread const sampler depthCubeArraySmplr, constant uint& depthCubeArraySwzl, thread texture2d 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 tex1d, thread const sampler tex1dSmplr, fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d texBuffer [[texture(6)]], depth2d depth2d [[texture(7)]], depthcube depthCube [[texture(8)]], depth2d_array depth2dArray [[texture(9)]], depthcube_array 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); } diff --git a/reference/shaders-msl-no-opt/frag/texture-access-uint.swizzle.frag b/reference/shaders-msl-no-opt/frag/texture-access-uint.swizzle.frag index 5a3013ba..86b71253 100644 --- a/reference/shaders-msl-no-opt/frag/texture-access-uint.swizzle.frag +++ b/reference/shaders-msl-no-opt/frag/texture-access-uint.swizzle.frag @@ -133,12 +133,12 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d 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)); diff --git a/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag b/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag index befee5bc..a819e2d5 100644 --- a/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag +++ b/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag @@ -133,16 +133,16 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d texBuffer [[texture(6)]], depth2d depth2d [[texture(7)]], depthcube depthCube [[texture(8)]], depth2d_array depth2dArray [[texture(9)]], depthcube_array 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); diff --git a/reference/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag b/reference/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag index aa3aae23..af920dbf 100644 --- a/reference/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag +++ b/reference/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag @@ -136,7 +136,7 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -float4 do_samples(thread const texture1d t1, thread const sampler t1Smplr, constant uint32_t& t1Swzl, thread const texture2d t2, constant uint32_t& t2Swzl, thread const texture3d t3, thread const sampler t3Smplr, constant uint32_t& t3Swzl, thread const texturecube tc, constant uint32_t& tcSwzl, thread const texture2d_array t2a, thread const sampler t2aSmplr, constant uint32_t& t2aSwzl, thread const texturecube_array tca, thread const sampler tcaSmplr, constant uint32_t& tcaSwzl, thread const texture2d tb, thread const depth2d d2, thread const sampler d2Smplr, constant uint32_t& d2Swzl, thread const depthcube dc, thread const sampler dcSmplr, constant uint32_t& dcSwzl, thread const depth2d_array d2a, constant uint32_t& d2aSwzl, thread const depthcube_array dca, thread const sampler dcaSmplr, constant uint32_t& dcaSwzl, thread sampler defaultSampler, thread sampler shadowSampler) +float4 do_samples(thread const texture1d t1, thread const sampler t1Smplr, constant uint& t1Swzl, thread const texture2d t2, constant uint& t2Swzl, thread const texture3d t3, thread const sampler t3Smplr, constant uint& t3Swzl, thread const texturecube tc, constant uint& tcSwzl, thread const texture2d_array t2a, thread const sampler t2aSmplr, constant uint& t2aSwzl, thread const texturecube_array tca, thread const sampler tcaSmplr, constant uint& tcaSwzl, thread const texture2d tb, thread const depth2d d2, thread const sampler d2Smplr, constant uint& d2Swzl, thread const depthcube dc, thread const sampler dcSmplr, constant uint& dcSwzl, thread const depth2d_array d2a, constant uint& d2aSwzl, thread const depthcube_array 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 t1, thread const sampler t1Smplr fragment main0_out main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d texBuffer [[texture(6)]], depth2d depth2d [[texture(7)]], depthcube depthCube [[texture(8)]], depth2d_array depth2dArray [[texture(9)]], depthcube_array 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; } diff --git a/reference/shaders-msl/comp/array-length.comp b/reference/shaders-msl/comp/array-length.comp new file mode 100644 index 00000000..6bba2ab4 --- /dev/null +++ b/reference/shaders-msl/comp/array-length.comp @@ -0,0 +1,36 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +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); +} + diff --git a/reference/shaders-msl/comp/array-length.msl2.argument.discrete.comp b/reference/shaders-msl/comp/array-length.msl2.argument.discrete.comp new file mode 100644 index 00000000..631c1a7a --- /dev/null +++ b/reference/shaders-msl/comp/array-length.msl2.argument.discrete.comp @@ -0,0 +1,64 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +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); +} + diff --git a/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp b/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp index b784940e..f9608de3 100644 --- a/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp +++ b/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp @@ -127,7 +127,7 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d foo [[texture(0)]], texture2d 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))); } diff --git a/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag b/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag index 5e749b3a..2b5afe23 100644 --- a/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag +++ b/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag @@ -142,17 +142,17 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -float4 sample_in_func_1(thread const array, 4> uSampler0, thread const array uSampler0Smplr, constant uint32_t* uSampler0Swzl, thread float2& vUV) +float4 sample_in_func_1(thread const array, 4> uSampler0, thread const array 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 uSampler1, thread const sampler uSampler1Smplr, constant uint32_t& uSampler1Swzl) +float4 sample_in_func_2(thread float2& vUV, thread texture2d uSampler1, thread const sampler uSampler1Smplr, constant uint& uSampler1Swzl) { return spvTextureSwizzle(uSampler1.sample(uSampler1Smplr, vUV), uSampler1Swzl); } -float4 sample_single_in_func(thread const texture2d s, thread const sampler sSmplr, constant uint32_t& sSwzl, thread float2& vUV) +float4 sample_single_in_func(thread const texture2d 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 s, thread const sampl fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant uint* spvSwizzleConstants [[buffer(30)]], texture2d 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); diff --git a/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag b/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag index 0e4972c6..ebaa28a5 100644 --- a/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag +++ b/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.swizzle.frag @@ -135,12 +135,12 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -float4 sample_in_func(thread const array, 4> uSampler, thread const array uSamplerSmplr, constant uint32_t* uSamplerSwzl, thread float2& vUV) +float4 sample_in_func(thread const array, 4> uSampler, thread const array 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 s, thread const sampler sSmplr, constant uint32_t& sSwzl, thread float2& vUV) +float4 sample_single_in_func(thread const texture2d 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 s, thread const sampl fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvSwizzleConstants [[buffer(30)]], array, 4> uSampler [[texture(0)]], array 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; diff --git a/shaders-msl/comp/array-length.comp b/shaders-msl/comp/array-length.comp new file mode 100644 index 00000000..6189d356 --- /dev/null +++ b/shaders-msl/comp/array-length.comp @@ -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(); +} diff --git a/shaders-msl/comp/array-length.msl2.argument.discrete.comp b/shaders-msl/comp/array-length.msl2.argument.discrete.comp new file mode 100644 index 00000000..d04df241 --- /dev/null +++ b/shaders-msl/comp/array-length.msl2.argument.discrete.comp @@ -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(); +} diff --git a/spirv_cross_c.cpp b/spirv_cross_c.cpp index a4c8db83..0d1645fb 100644 --- a/spirv_cross_c.cpp +++ b/spirv_cross_c.cpp @@ -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(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); diff --git a/spirv_cross_c.h b/spirv_cross_c.h index 4801ba7c..4e55e1af 100644 --- a/spirv_cross_c.h +++ b/spirv_cross_c.h @@ -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); diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 084fb0ae..69bc7284 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -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. diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 1929598b..320684d9 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -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(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(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(type_ptr_ptr_id, uint_type_pointer2); - - set(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(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(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(type_ptr_ptr_id, uint_type_pointer2); + + set(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(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(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([&](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(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(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 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([&](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(swizzle_buffer_type_id, uint_type_pointer); - set_decoration(swizzle_buffer_type_id, DecorationArrayStride, 4); + set(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(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(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(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) }); + } } } diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 6e7c83c3..380c3dad 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -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 constexpr_samplers; + std::unordered_set buffers_requiring_array_length; SmallVector buffer_arrays; uint32_t argument_buffer_ids[kMaxArgumentBuffers];