From eaf7afed970a02aa5f3d1493c2df43e88742058d Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Thu, 9 May 2019 12:15:45 +0200 Subject: [PATCH] MSL: Support argument buffers and image swizzling. Change aux buffer to swizzle buffer. There is no good reason to expand the aux buffer, so name it appropriately. Make the code cleaner by emitting a straight pointer to uint rather than a dummy struct which only contains a single unsized array member anyways. This will also end up being very similar to how we implement swizzle buffers for argument buffers. Do not use implied binding if it overflows int32_t. --- CMakeLists.txt | 2 +- .../comp/force-recompile-hooks.swizzle.comp | 9 +- ...wizzle.msl2.argument.discrete.swizzle.frag | 156 ++++++++++++++++ ...array-of-texture-swizzle.msl2.swizzle.frag | 9 +- .../asm/frag/texture-access.swizzle.asm.frag | 27 ++- .../frag/texture-access-int.swizzle.frag | 19 +- .../frag/texture-access-leaf.swizzle.frag | 27 ++- .../frag/texture-access-uint.swizzle.frag | 19 +- .../frag/texture-access.swizzle.frag | 27 ++- .../texture-access-function.swizzle.vk.frag | 27 ++- .../comp/force-recompile-hooks.swizzle.comp | 9 +- ...wizzle.msl2.argument.discrete.swizzle.frag | 171 +++++++++++++++++ ...array-of-texture-swizzle.msl2.swizzle.frag | 9 +- ...wizzle.msl2.argument.discrete.swizzle.frag | 31 ++++ spirv_cross_c.cpp | 13 +- spirv_cross_c.h | 15 +- spirv_msl.cpp | 173 ++++++++++++------ spirv_msl.hpp | 22 +-- 18 files changed, 575 insertions(+), 190 deletions(-) create mode 100644 reference/opt/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag create mode 100644 reference/shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag create mode 100644 shaders-msl/frag/array-of-texture-swizzle.msl2.argument.discrete.swizzle.frag 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;