diff --git a/CMakeLists.txt b/CMakeLists.txt index 0be765e6..d1fc0281 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,7 +267,7 @@ endif() if (SPIRV_CROSS_SHARED) set(spirv-cross-abi-major 0) - set(spirv-cross-abi-minor 7) + set(spirv-cross-abi-minor 8) set(spirv-cross-abi-patch 0) set(SPIRV_CROSS_VERSION ${spirv-cross-abi-major}.${spirv-cross-abi-minor}.${spirv-cross-abi-patch}) set(SPIRV_CROSS_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib) 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 c06d8ba1..2d9d423e 100644 --- a/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp +++ b/reference/opt/shaders-msl/comp/force-recompile-hooks.swizzle.comp @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - enum class spvSwizzle : uint { none = 0, @@ -130,9 +125,9 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -kernel void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture2d foo [[texture(0)]], texture2d bar [[texture(1)]], sampler fooSmplr [[sampler(0)]]) +kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d foo [[texture(0)]], texture2d bar [[texture(1)]], sampler fooSmplr [[sampler(0)]]) { - constant uint32_t& fooSwzl = spvAuxBuffer.swizzleConst[0]; + constant uint32_t& 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 new file mode 100644 index 00000000..b8e8f9d8 --- /dev/null +++ b/reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag @@ -0,0 +1,156 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + constant uint* spvSwizzleConstants [[id(0)]]; + array, 4> uSampler0 [[id(1)]]; + array uSampler0Smplr [[id(5)]]; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vUV [[user(locn0)]]; +}; + +enum class spvSwizzle : uint +{ + none = 0, + zero, + one, + red, + green, + blue, + alpha +}; + +template struct spvRemoveReference { typedef T type; }; +template struct spvRemoveReference { typedef T type; }; +template struct spvRemoveReference { typedef T type; }; +template inline constexpr thread T&& spvForward(thread typename spvRemoveReference::type& x) +{ + return static_cast(x); +} +template inline constexpr thread T&& spvForward(thread typename spvRemoveReference::type&& x) +{ + return static_cast(x); +} + +template +inline T spvGetSwizzle(vec x, T c, spvSwizzle s) +{ + switch (s) + { + case spvSwizzle::none: + return c; + case spvSwizzle::zero: + return 0; + case spvSwizzle::one: + return 1; + case spvSwizzle::red: + return x.r; + case spvSwizzle::green: + return x.g; + case spvSwizzle::blue: + return x.b; + case spvSwizzle::alpha: + return x.a; + } +} + +// Wrapper function that swizzles texture samples and fetches. +template +inline vec spvTextureSwizzle(vec x, uint s) +{ + if (!s) + return x; + return vec(spvGetSwizzle(x, x.r, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, x.g, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, x.b, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, x.a, spvSwizzle((s >> 24) & 0xFF))); +} + +template +inline T spvTextureSwizzle(T x, uint s) +{ + return spvTextureSwizzle(vec(x, 0, 0, 1), s).x; +} + +// Wrapper function that swizzles texture gathers. +template +inline vec spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c) +{ + if (sw) + { + switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF)) + { + case spvSwizzle::none: + break; + case spvSwizzle::zero: + return vec(0, 0, 0, 0); + case spvSwizzle::one: + return vec(1, 1, 1, 1); + case spvSwizzle::red: + return t.gather(s, spvForward(params)..., component::x); + case spvSwizzle::green: + return t.gather(s, spvForward(params)..., component::y); + case spvSwizzle::blue: + return t.gather(s, spvForward(params)..., component::z); + case spvSwizzle::alpha: + return t.gather(s, spvForward(params)..., component::w); + } + } + switch (c) + { + case component::x: + return t.gather(s, spvForward(params)..., component::x); + case component::y: + return t.gather(s, spvForward(params)..., component::y); + case component::z: + return t.gather(s, spvForward(params)..., component::z); + case component::w: + return t.gather(s, spvForward(params)..., component::w); + } +} + +// Wrapper function that swizzles depth texture gathers. +template +inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) +{ + if (sw) + { + switch (spvSwizzle(sw & 0xFF)) + { + case spvSwizzle::none: + case spvSwizzle::red: + break; + case spvSwizzle::zero: + case spvSwizzle::green: + case spvSwizzle::blue: + case spvSwizzle::alpha: + return vec(0, 0, 0, 0); + case spvSwizzle::one: + return vec(1, 1, 1, 1); + } + } + return t.gather_compare(s, spvForward(params)...); +} + +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]; + 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]); + out.FragColor += spvTextureSwizzle(uSampler1.sample(uSampler1Smplr, in.vUV), uSampler1Swzl); + return out; +} + 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 9a03e1fd..8e97cab9 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - struct main0_out { float4 FragColor [[color(0)]]; @@ -140,10 +135,10 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -fragment main0_out main0(main0_in in [[stage_in]], constant spvAux& spvAuxBuffer [[buffer(30)]], array, 4> uSampler [[texture(0)]], array uSamplerSmplr [[sampler(0)]]) +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 = &spvAuxBuffer.swizzleConst[0]; + constant uint32_t* 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 ea433e16..68445b79 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - // Returns 2D texture coords corresponding to 1D texel buffer coords uint2 spvTexelBufferCoord(uint tc) { @@ -136,18 +131,18 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -fragment void main0(constant spvAux& spvAuxBuffer [[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)]]) +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 = spvAuxBuffer.swizzleConst[0]; - constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1]; - constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2]; - constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3]; - constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4]; - constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5]; - constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7]; - constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8]; - constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9]; - constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[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]; 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 997d5b55..3f854e70 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - // Returns 2D texture coords corresponding to 1D texel buffer coords uint2 spvTexelBufferCoord(uint tc) { @@ -136,14 +131,14 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -fragment void main0(constant spvAux& spvAuxBuffer [[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)]]) +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 = spvAuxBuffer.swizzleConst[0]; - constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1]; - constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2]; - constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3]; - constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4]; - constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[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]; 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 076dcc17..01a5ae64 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - // Returns 2D texture coords corresponding to 1D texel buffer coords uint2 spvTexelBufferCoord(uint tc) { @@ -183,18 +178,18 @@ float4 doSwizzle(thread texture1d tex1d, thread const sampler tex1dSmplr, return c; } -fragment void main0(constant spvAux& spvAuxBuffer [[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)]]) +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 = spvAuxBuffer.swizzleConst[0]; - constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1]; - constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2]; - constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3]; - constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4]; - constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5]; - constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7]; - constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8]; - constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9]; - constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[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]; 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 81ffec75..5a3013ba 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - // Returns 2D texture coords corresponding to 1D texel buffer coords uint2 spvTexelBufferCoord(uint tc) { @@ -136,14 +131,14 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -fragment void main0(constant spvAux& spvAuxBuffer [[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)]]) +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 = spvAuxBuffer.swizzleConst[0]; - constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1]; - constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2]; - constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3]; - constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4]; - constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[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]; 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 98ab50ea..befee5bc 100644 --- a/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag +++ b/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - // Returns 2D texture coords corresponding to 1D texel buffer coords uint2 spvTexelBufferCoord(uint tc) { @@ -136,18 +131,18 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -fragment void main0(constant spvAux& spvAuxBuffer [[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)]]) +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 = spvAuxBuffer.swizzleConst[0]; - constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1]; - constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2]; - constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3]; - constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4]; - constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5]; - constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7]; - constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8]; - constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9]; - constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[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]; 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 e99cd69a..aa3aae23 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - struct main0_out { float4 fragColor [[color(0)]]; @@ -188,19 +183,19 @@ float4 do_samples(thread const texture1d t1, thread const sampler t1Smplr return c; } -fragment main0_out main0(constant spvAux& spvAuxBuffer [[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)]]) +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 = spvAuxBuffer.swizzleConst[0]; - constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1]; - constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2]; - constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3]; - constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4]; - constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5]; - constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7]; - constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8]; - constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9]; - constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[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]; 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/force-recompile-hooks.swizzle.comp b/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp index d8b4af79..b784940e 100644 --- a/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp +++ b/reference/shaders-msl/comp/force-recompile-hooks.swizzle.comp @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - enum class spvSwizzle : uint { none = 0, @@ -130,9 +125,9 @@ inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p return t.gather_compare(s, spvForward(params)...); } -kernel void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture2d foo [[texture(0)]], texture2d bar [[texture(1)]], sampler fooSmplr [[sampler(0)]]) +kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d foo [[texture(0)]], texture2d bar [[texture(1)]], sampler fooSmplr [[sampler(0)]]) { - constant uint32_t& fooSwzl = spvAuxBuffer.swizzleConst[0]; + constant uint32_t& 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 new file mode 100644 index 00000000..5e749b3a --- /dev/null +++ b/reference/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag @@ -0,0 +1,171 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct spvDescriptorSetBuffer0 +{ + constant uint* spvSwizzleConstants [[id(0)]]; + array, 4> uSampler0 [[id(1)]]; + array uSampler0Smplr [[id(5)]]; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vUV [[user(locn0)]]; +}; + +enum class spvSwizzle : uint +{ + none = 0, + zero, + one, + red, + green, + blue, + alpha +}; + +template struct spvRemoveReference { typedef T type; }; +template struct spvRemoveReference { typedef T type; }; +template struct spvRemoveReference { typedef T type; }; +template inline constexpr thread T&& spvForward(thread typename spvRemoveReference::type& x) +{ + return static_cast(x); +} +template inline constexpr thread T&& spvForward(thread typename spvRemoveReference::type&& x) +{ + return static_cast(x); +} + +template +inline T spvGetSwizzle(vec x, T c, spvSwizzle s) +{ + switch (s) + { + case spvSwizzle::none: + return c; + case spvSwizzle::zero: + return 0; + case spvSwizzle::one: + return 1; + case spvSwizzle::red: + return x.r; + case spvSwizzle::green: + return x.g; + case spvSwizzle::blue: + return x.b; + case spvSwizzle::alpha: + return x.a; + } +} + +// Wrapper function that swizzles texture samples and fetches. +template +inline vec spvTextureSwizzle(vec x, uint s) +{ + if (!s) + return x; + return vec(spvGetSwizzle(x, x.r, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, x.g, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, x.b, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, x.a, spvSwizzle((s >> 24) & 0xFF))); +} + +template +inline T spvTextureSwizzle(T x, uint s) +{ + return spvTextureSwizzle(vec(x, 0, 0, 1), s).x; +} + +// Wrapper function that swizzles texture gathers. +template +inline vec spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c) +{ + if (sw) + { + switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF)) + { + case spvSwizzle::none: + break; + case spvSwizzle::zero: + return vec(0, 0, 0, 0); + case spvSwizzle::one: + return vec(1, 1, 1, 1); + case spvSwizzle::red: + return t.gather(s, spvForward(params)..., component::x); + case spvSwizzle::green: + return t.gather(s, spvForward(params)..., component::y); + case spvSwizzle::blue: + return t.gather(s, spvForward(params)..., component::z); + case spvSwizzle::alpha: + return t.gather(s, spvForward(params)..., component::w); + } + } + switch (c) + { + case component::x: + return t.gather(s, spvForward(params)..., component::x); + case component::y: + return t.gather(s, spvForward(params)..., component::y); + case component::z: + return t.gather(s, spvForward(params)..., component::z); + case component::w: + return t.gather(s, spvForward(params)..., component::w); + } +} + +// Wrapper function that swizzles depth texture gathers. +template +inline vec spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) +{ + if (sw) + { + switch (spvSwizzle(sw & 0xFF)) + { + case spvSwizzle::none: + case spvSwizzle::red: + break; + case spvSwizzle::zero: + case spvSwizzle::green: + case spvSwizzle::blue: + case spvSwizzle::alpha: + return vec(0, 0, 0, 0); + case spvSwizzle::one: + return vec(1, 1, 1, 1); + } + } + 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) +{ + 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) +{ + 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) +{ + return spvTextureSwizzle(s.sample(sSmplr, vUV), sSwzl); +} + +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]; + 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); + out.FragColor += sample_single_in_func(uSampler1, uSampler1Smplr, uSampler1Swzl, in.vUV); + return out; +} + 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 39d059c3..0e4972c6 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 @@ -5,11 +5,6 @@ using namespace metal; -struct spvAux -{ - uint swizzleConst[1]; -}; - struct main0_out { float4 FragColor [[color(0)]]; @@ -150,10 +145,10 @@ float4 sample_single_in_func(thread const texture2d s, thread const sampl return spvTextureSwizzle(s.sample(sSmplr, vUV), sSwzl); } -fragment main0_out main0(main0_in in [[stage_in]], constant spvAux& spvAuxBuffer [[buffer(30)]], array, 4> uSampler [[texture(0)]], array uSamplerSmplr [[sampler(0)]]) +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 = &spvAuxBuffer.swizzleConst[0]; + constant uint32_t* 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/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag b/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag new file mode 100644 index 00000000..556cc9ca --- /dev/null +++ b/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag @@ -0,0 +1,31 @@ +#version 450 + +layout(set = 0, binding = 1) uniform sampler2D uSampler0[4]; +layout(set = 2, binding = 0) uniform sampler2D uSampler1; +layout(set = 1, binding = 4) uniform sampler2D uSamp; +layout(location = 0) in vec2 vUV; + +layout(location = 0) out vec4 FragColor; + +vec4 sample_in_func_1() +{ + return texture(uSampler0[2], vUV); +} + +vec4 sample_in_func_2() +{ + return texture(uSampler1, vUV); +} + +vec4 sample_single_in_func(sampler2D s) +{ + return texture(s, vUV); +} + +void main() +{ + FragColor = sample_in_func_1(); + FragColor += sample_in_func_2(); + FragColor += sample_single_in_func(uSampler0[1]); + FragColor += sample_single_in_func(uSampler1); +} diff --git a/spirv_cross_c.cpp b/spirv_cross_c.cpp index 7d777546..92d622a6 100644 --- a/spirv_cross_c.cpp +++ b/spirv_cross_c.cpp @@ -474,8 +474,8 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c options->msl.texel_buffer_texture_width = value; break; - case SPVC_COMPILER_OPTION_MSL_AUX_BUFFER_INDEX: - options->msl.aux_buffer_index = value; + case SPVC_COMPILER_OPTION_MSL_SWIZZLE_BUFFER_INDEX: + options->msl.swizzle_buffer_index = value; break; case SPVC_COMPILER_OPTION_MSL_INDIRECT_PARAMS_BUFFER_INDEX: @@ -726,7 +726,7 @@ spvc_bool spvc_compiler_msl_is_rasterization_disabled(spvc_compiler compiler) #endif } -spvc_bool spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler) +spvc_bool spvc_compiler_msl_needs_swizzle_buffer(spvc_compiler compiler) { #if SPIRV_CROSS_C_API_MSL if (compiler->backend != SPVC_BACKEND_MSL) @@ -736,13 +736,18 @@ spvc_bool spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler) } auto &msl = *static_cast(compiler->compiler.get()); - return msl.needs_aux_buffer() ? SPVC_TRUE : SPVC_FALSE; + return msl.needs_swizzle_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); +} + spvc_bool spvc_compiler_msl_needs_output_buffer(spvc_compiler compiler) { #if SPIRV_CROSS_C_API_MSL diff --git a/spirv_cross_c.h b/spirv_cross_c.h index 9e10d070..b03e60e0 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 7 +#define SPVC_C_API_VERSION_MINOR 8 /* Bumped if internal implementation details change. */ #define SPVC_C_API_VERSION_PATCH 0 @@ -290,9 +290,12 @@ 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)) + +/* Obsolete. Sticks around for backwards compatibility. */ #define SPVC_MSL_AUX_BUFFER_STRUCT_VERSION 1 -/* Runtime check for incompatibility. */ +/* Runtime check for incompatibility. Obsolete. */ SPVC_PUBLIC_API unsigned spvc_msl_get_aux_buffer_struct_version(void); /* Maps to C++ API. */ @@ -407,7 +410,11 @@ typedef enum spvc_compiler_option SPVC_COMPILER_OPTION_MSL_VERSION = 17 | SPVC_COMPILER_OPTION_MSL_BIT, SPVC_COMPILER_OPTION_MSL_TEXEL_BUFFER_TEXTURE_WIDTH = 18 | SPVC_COMPILER_OPTION_MSL_BIT, + + /* Obsolete, use SWIZZLE_BUFFER_INDEX instead. */ SPVC_COMPILER_OPTION_MSL_AUX_BUFFER_INDEX = 19 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SWIZZLE_BUFFER_INDEX = 19 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_INDIRECT_PARAMS_BUFFER_INDEX = 20 | SPVC_COMPILER_OPTION_MSL_BIT, SPVC_COMPILER_OPTION_MSL_SHADER_OUTPUT_BUFFER_INDEX = 21 | SPVC_COMPILER_OPTION_MSL_BIT, SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_OUTPUT_BUFFER_INDEX = 22 | SPVC_COMPILER_OPTION_MSL_BIT, @@ -505,7 +512,11 @@ SPVC_PUBLIC_API spvc_variable_id spvc_compiler_hlsl_remap_num_workgroups_builtin * Maps to C++ API. */ SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_rasterization_disabled(spvc_compiler compiler); + +/* 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_output_buffer(spvc_compiler compiler); SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_patch_output_buffer(spvc_compiler compiler); SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_input_threadgroup_mem(spvc_compiler compiler); diff --git a/spirv_msl.cpp b/spirv_msl.cpp index c4c75a22..1d57ccec 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -28,8 +28,6 @@ using namespace std; static const uint32_t k_unknown_location = ~0u; static const uint32_t k_unknown_component = ~0u; -static const uint32_t k_aux_mbr_idx_swizzle_const = 0u; - CompilerMSL::CompilerMSL(std::vector spirv_) : CompilerGLSL(move(spirv_)) { @@ -387,14 +385,13 @@ void CompilerMSL::build_implicit_builtins() } } - if (needs_aux_buffer_def) + if (needs_swizzle_buffer_def) { - uint32_t offset = ir.increase_bound_by(5); + uint32_t offset = ir.increase_bound_by(4); uint32_t type_id = offset; - uint32_t type_arr_id = offset + 1; - uint32_t struct_id = offset + 2; - uint32_t struct_ptr_id = offset + 3; - uint32_t var_id = offset + 4; + 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; @@ -402,36 +399,25 @@ void CompilerMSL::build_implicit_builtins() uint_type.width = 32; set(type_id, uint_type); - SPIRType uint_type_arr = uint_type; - uint_type_arr.array.push_back(0); - uint_type_arr.array_size_literal.push_back(true); - uint_type_arr.parent_type = type_id; - set(type_arr_id, uint_type_arr); - set_decoration(type_arr_id, DecorationArrayStride, 4); + 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 struct_type; - struct_type.basetype = SPIRType::Struct; - struct_type.member_types.push_back(type_arr_id); - auto &type = set(struct_id, struct_type); - type.self = struct_id; - set_decoration(struct_id, DecorationBlock); - set_name(struct_id, "spvAux"); - set_member_name(struct_id, k_aux_mbr_idx_swizzle_const, "swizzleConst"); - set_member_decoration(struct_id, k_aux_mbr_idx_swizzle_const, DecorationOffset, 0); + 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); - SPIRType struct_type_ptr = struct_type; - struct_type_ptr.pointer = true; - struct_type_ptr.parent_type = struct_id; - struct_type_ptr.storage = StorageClassUniform; - auto &ptr_type = set(struct_ptr_id, struct_type_ptr); - ptr_type.self = struct_id; - - set(var_id, struct_ptr_id, StorageClassUniform); - set_name(var_id, "spvAuxBuffer"); + set(var_id, type_ptr_ptr_id, StorageClassUniformConstant); + set_name(var_id, "spvSwizzleConstants"); // This should never match anything. set_decoration(var_id, DecorationDescriptorSet, 0xFFFFFFFE); - set_decoration(var_id, DecorationBinding, msl_options.aux_buffer_index); - aux_buffer_id = var_id; + set_decoration(var_id, DecorationBinding, msl_options.swizzle_buffer_index); + swizzle_buffer_id = var_id; } } @@ -678,8 +664,8 @@ string CompilerMSL::compile() fixup_image_load_store_access(); set_enabled_interface_variables(get_active_interface_variables()); - if (aux_buffer_id) - active_interface_variables.insert(aux_buffer_id); + if (swizzle_buffer_id) + active_interface_variables.insert(swizzle_buffer_id); // Create structs to hold input, output and uniform variables. // Do output first to ensure out. is declared at top of entry function. @@ -4960,7 +4946,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool if (!is_gather) farg_str += ")"; farg_str += ", " + to_swizzle_expression(img); - used_aux_buffer = true; + used_swizzle_buffer = true; } *p_forward = forward; @@ -5051,8 +5037,17 @@ string CompilerMSL::to_func_call_arg(uint32_t id) arg_str += ", " + to_sampler_expression(var_id ? var_id : id); } + if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type)) - arg_str += ", " + to_swizzle_expression(id); + { + // 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); + } return arg_str; } @@ -5083,9 +5078,15 @@ string CompilerMSL::to_sampler_expression(uint32_t id) string CompilerMSL::to_swizzle_expression(uint32_t id) { auto *combined = maybe_get(id); + auto expr = to_expression(combined ? combined->image : id); auto index = expr.find_first_of('['); + // If an image 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 + swizzle_name_suffix; else @@ -5738,7 +5739,8 @@ string CompilerMSL::get_type_address_space(const SPIRType &type, uint32_t id) else return "constant"; } - break; + else + return "constant"; case StorageClassFunction: case StorageClassGeneric: @@ -6020,7 +6022,10 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args) ep_args += " [[texture(" + convert_to_string(r.index) + ")]]"; break; default: - SPIRV_CROSS_THROW("Unexpected resource type"); + if (!ep_args.empty()) + ep_args += ", "; + ep_args += type_to_glsl(type, var_id) + " " + r.name; + ep_args += " [[buffer(" + convert_to_string(r.index) + ")]]"; break; } } @@ -6056,14 +6061,23 @@ void CompilerMSL::fix_up_shader_inputs_outputs() { auto &entry_func = this->get(ir.default_entry_point); entry_func.fixup_hooks_in.push_back([this, &type, &var, var_id]() { - auto &aux_type = expression_type(aux_buffer_id); bool is_array_type = !type.array.empty(); - // 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), - is_array_type ? " = &" : " = ", to_name(aux_buffer_id), ".", - to_member_name(aux_type, k_aux_mbr_idx_swizzle_const), "[", - convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];"); + 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), + is_array_type ? " = &" : " = ", to_name(argument_buffer_ids[desc_set]), + ".spvSwizzleConstants", "[", + 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 uint32_t", 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)), "];"); + } }); } } @@ -6230,20 +6244,23 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base itr->second = true; switch (basetype) { - case SPIRType::Struct: - return itr->first.msl_buffer; case SPIRType::Image: return itr->first.msl_texture; case SPIRType::Sampler: return itr->first.msl_sampler; default: - return 0; + return itr->first.msl_buffer; } } // If there is no explicit mapping of bindings to MSL, use the declared binding. if (has_decoration(var.self, DecorationBinding)) - return get_decoration(var.self, DecorationBinding); + { + var_binding = get_decoration(var.self, DecorationBinding); + // Avoid emitting sentinel bindings. + if (var_binding < 0x80000000u) + return var_binding; + } uint32_t binding_stride = 1; auto &type = get(var.basetype); @@ -6254,10 +6271,6 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base uint32_t resource_index; switch (basetype) { - case SPIRType::Struct: - resource_index = next_metal_resource_index_buffer; - next_metal_resource_index_buffer += binding_stride; - break; case SPIRType::Image: resource_index = next_metal_resource_index_texture; next_metal_resource_index_texture += binding_stride; @@ -6267,7 +6280,8 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base next_metal_resource_index_sampler += binding_stride; break; default: - resource_index = 0; + resource_index = next_metal_resource_index_buffer; + next_metal_resource_index_buffer += binding_stride; break; } return resource_index; @@ -7764,7 +7778,7 @@ bool CompilerMSL::SampledImageScanner::handle(spv::Op opcode, const uint32_t *ar case OpImageDrefGather: compiler.has_sampled_images = compiler.has_sampled_images || compiler.is_sampled_image_type(compiler.expression_type(args[2])); - compiler.needs_aux_buffer_def = compiler.needs_aux_buffer_def || compiler.has_sampled_images; + compiler.needs_swizzle_buffer_def = compiler.needs_swizzle_buffer_def || compiler.has_sampled_images; break; default: break; @@ -8227,6 +8241,8 @@ void CompilerMSL::analyze_argument_buffers() }; SmallVector resources_in_set[kMaxArgumentBuffers]; + bool set_needs_swizzle_buffer[kMaxArgumentBuffers] = {}; + ir.for_each_typed_id([&](uint32_t self, SPIRVariable &var) { if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant || var.storage == StorageClassStorageBuffer) && @@ -8270,9 +8286,54 @@ void CompilerMSL::analyze_argument_buffers() resources_in_set[desc_set].push_back( { &var, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype) }); } + + // 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; } }); + if (needs_swizzle_buffer_def) + { + uint32_t swizzle_buffer_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]) + continue; + + if (swizzle_buffer_type_id == 0) + { + uint32_t offset = ir.increase_bound_by(2); + uint32_t type_id = offset; + swizzle_buffer_type_id = offset + 1; + + // 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(swizzle_buffer_type_id, uint_type_pointer); + set_decoration(swizzle_buffer_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) }); + } + } + for (uint32_t desc_set = 0; desc_set < kMaxArgumentBuffers; desc_set++) { auto &resources = resources_in_set[desc_set]; diff --git a/spirv_msl.hpp b/spirv_msl.hpp index e10fd2b2..6e7c83c3 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -152,11 +152,11 @@ static const uint32_t kPushConstDescSet = ~(0u); // element to indicate the bindings for the push constants. static const uint32_t kPushConstBinding = 0; -static const uint32_t kMaxArgumentBuffers = 8; +// Special constant used in a MSLResourceBinding binding +// element to indicate the buffer binding for swizzle buffers. +static const uint32_t kSwizzleBufferBinding = ~(1u); -// The current version of the aux buffer structure. It must be incremented any time a -// new field is added to the aux buffer. -#define SPIRV_CROSS_MSL_AUX_BUFFER_STRUCT_VERSION 1 +static const uint32_t kMaxArgumentBuffers = 8; // Decompiles SPIR-V to Metal Shading Language class CompilerMSL : public CompilerGLSL @@ -174,7 +174,7 @@ public: Platform platform = macOS; uint32_t msl_version = make_msl_version(1, 2); uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers - uint32_t aux_buffer_index = 30; + uint32_t swizzle_buffer_index = 30; uint32_t indirect_params_buffer_index = 29; uint32_t shader_output_buffer_index = 28; uint32_t shader_patch_output_buffer_index = 27; @@ -243,10 +243,10 @@ public: } // Provide feedback to calling API to allow it to pass an auxiliary - // buffer if the shader needs it. - bool needs_aux_buffer() const + // swizzle buffer if the shader needs it. + bool needs_swizzle_buffer() const { - return used_aux_buffer; + return used_swizzle_buffer; } // Provide feedback to calling API to allow it to pass an output @@ -486,7 +486,7 @@ protected: uint32_t builtin_primitive_id_id = 0; uint32_t builtin_subgroup_invocation_id_id = 0; uint32_t builtin_subgroup_size_id = 0; - uint32_t aux_buffer_id = 0; + uint32_t swizzle_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; @@ -524,8 +524,8 @@ protected: bool needs_instance_idx_arg = false; bool is_rasterization_disabled = false; bool capture_output_to_buffer = false; - bool needs_aux_buffer_def = false; - bool used_aux_buffer = false; + bool needs_swizzle_buffer_def = false; + bool used_swizzle_buffer = false; bool added_builtin_tess_level = false; bool needs_subgroup_invocation_id = false; std::string qual_pos_var_name;