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.
This commit is contained in:
Hans-Kristian Arntzen 2019-05-09 12:15:45 +02:00 committed by Hans-Kristian Arntzen
parent a57226e84a
commit eaf7afed97
18 changed files with 575 additions and 190 deletions

View File

@ -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)

View File

@ -5,11 +5,6 @@
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
enum class spvSwizzle : uint
{
none = 0,
@ -130,9 +125,9 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
kernel void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
{
constant uint32_t& fooSwzl = 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)));
}

View File

@ -0,0 +1,156 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant uint* spvSwizzleConstants [[id(0)]];
array<texture2d<float>, 4> uSampler0 [[id(1)]];
array<sampler, 4> 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<typename T> struct spvRemoveReference { typedef T type; };
template<typename T> struct spvRemoveReference<thread T&> { typedef T type; };
template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; };
template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type& x)
{
return static_cast<thread T&&>(x);
}
template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type&& x)
{
return static_cast<thread T&&>(x);
}
template<typename T>
inline T spvGetSwizzle(vec<T, 4> 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<typename T>
inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s)
{
if (!s)
return x;
return vec<T, 4>(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<typename T>
inline T spvTextureSwizzle(T x, uint s)
{
return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x;
}
// Wrapper function that swizzles texture gathers.
template<typename T, typename Tex, typename... Ts>
inline vec<T, 4> 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<T, 4>(0, 0, 0, 0);
case spvSwizzle::one:
return vec<T, 4>(1, 1, 1, 1);
case spvSwizzle::red:
return t.gather(s, spvForward<Ts>(params)..., component::x);
case spvSwizzle::green:
return t.gather(s, spvForward<Ts>(params)..., component::y);
case spvSwizzle::blue:
return t.gather(s, spvForward<Ts>(params)..., component::z);
case spvSwizzle::alpha:
return t.gather(s, spvForward<Ts>(params)..., component::w);
}
}
switch (c)
{
case component::x:
return t.gather(s, spvForward<Ts>(params)..., component::x);
case component::y:
return t.gather(s, spvForward<Ts>(params)..., component::y);
case component::z:
return t.gather(s, spvForward<Ts>(params)..., component::z);
case component::w:
return t.gather(s, spvForward<Ts>(params)..., component::w);
}
}
// Wrapper function that swizzles depth texture gathers.
template<typename T, typename Tex, typename... Ts>
inline vec<T, 4> 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<T, 4>(0, 0, 0, 0);
case spvSwizzle::one:
return vec<T, 4>(1, 1, 1, 1);
}
}
return t.gather_compare(s, spvForward<Ts>(params)...);
}
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> uSampler1 [[texture(0)]], sampler uSampler1Smplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* spvDescriptorSet0_uSampler0Swzl = &spvDescriptorSet0.spvSwizzleConstants[1];
constant uint32_t& uSampler1Swzl = spvSwizzleConstants[0];
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;
}

View File

@ -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<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
fragment main0_out main0(main0_in in [[stage_in]], constant spvAux& spvAuxBuffer [[buffer(30)]], array<texture2d<float>, 4> uSampler [[texture(0)]], array<sampler, 4> uSamplerSmplr [[sampler(0)]])
fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvSwizzleConstants [[buffer(30)]], array<texture2d<float>, 4> uSampler [[texture(0)]], array<sampler, 4> uSamplerSmplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* uSamplerSwzl = &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;

View File

@ -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<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSamp [[sampler(0)]], sampler tex2dSamp [[sampler(1)]], sampler tex3dSamp [[sampler(2)]], sampler texCubeSamp [[sampler(3)]], sampler tex2dArraySamp [[sampler(4)]], sampler texCubeArraySamp [[sampler(5)]], sampler depth2dSamp [[sampler(7)]], sampler depthCubeSamp [[sampler(8)]], sampler depth2dArraySamp [[sampler(9)]], sampler depthCubeArraySamp [[sampler(10)]])
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSamp [[sampler(0)]], sampler tex2dSamp [[sampler(1)]], sampler tex3dSamp [[sampler(2)]], sampler texCubeSamp [[sampler(3)]], sampler tex2dArraySamp [[sampler(4)]], sampler texCubeArraySamp [[sampler(5)]], sampler depth2dSamp [[sampler(7)]], sampler depthCubeSamp [[sampler(8)]], sampler depth2dArraySamp [[sampler(9)]], sampler depthCubeArraySamp [[sampler(10)]])
{
constant uint32_t& tex1dSwzl = 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);

View File

@ -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<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture1d<int> tex1d [[texture(0)]], texture2d<int> tex2d [[texture(1)]], texture3d<int> tex3d [[texture(2)]], texturecube<int> texCube [[texture(3)]], texture2d_array<int> tex2dArray [[texture(4)]], texturecube_array<int> texCubeArray [[texture(5)]], texture2d<int> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<int> tex1d [[texture(0)]], texture2d<int> tex2d [[texture(1)]], texture3d<int> tex3d [[texture(2)]], texturecube<int> texCube [[texture(3)]], texture2d_array<int> tex2dArray [[texture(4)]], texturecube_array<int> texCubeArray [[texture(5)]], texture2d<int> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
{
constant uint32_t& tex1dSwzl = 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));

View File

@ -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<float> tex1d, thread const sampler tex1dSmplr,
return c;
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
{
constant uint32_t& tex1dSwzl = 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);
}

View File

@ -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<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture1d<uint> tex1d [[texture(0)]], texture2d<uint> tex2d [[texture(1)]], texture3d<uint> tex3d [[texture(2)]], texturecube<uint> texCube [[texture(3)]], texture2d_array<uint> tex2dArray [[texture(4)]], texturecube_array<uint> texCubeArray [[texture(5)]], texture2d<uint> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<uint> tex1d [[texture(0)]], texture2d<uint> tex2d [[texture(1)]], texture3d<uint> tex3d [[texture(2)]], texturecube<uint> texCube [[texture(3)]], texture2d_array<uint> tex2dArray [[texture(4)]], texturecube_array<uint> texCubeArray [[texture(5)]], texture2d<uint> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
{
constant uint32_t& tex1dSwzl = 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));

View File

@ -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<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
{
constant uint32_t& tex1dSwzl = 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);

View File

@ -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<float> t1, thread const sampler t1Smplr
return c;
}
fragment main0_out main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex3dSmplr [[sampler(2)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depthCubeArraySmplr [[sampler(10)]], sampler defaultSampler [[sampler(11)]], sampler shadowSampler [[sampler(12)]])
fragment main0_out main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex3dSmplr [[sampler(2)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depthCubeArraySmplr [[sampler(10)]], sampler defaultSampler [[sampler(11)]], sampler shadowSampler [[sampler(12)]])
{
main0_out out = {};
constant uint32_t& tex1dSwzl = 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;
}

View File

@ -5,11 +5,6 @@
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
enum class spvSwizzle : uint
{
none = 0,
@ -130,9 +125,9 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... p
return t.gather_compare(s, spvForward<Ts>(params)...);
}
kernel void main0(constant spvAux& spvAuxBuffer [[buffer(30)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
kernel void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
{
constant uint32_t& fooSwzl = 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)));
}

View File

@ -0,0 +1,171 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvDescriptorSetBuffer0
{
constant uint* spvSwizzleConstants [[id(0)]];
array<texture2d<float>, 4> uSampler0 [[id(1)]];
array<sampler, 4> 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<typename T> struct spvRemoveReference { typedef T type; };
template<typename T> struct spvRemoveReference<thread T&> { typedef T type; };
template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; };
template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type& x)
{
return static_cast<thread T&&>(x);
}
template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type&& x)
{
return static_cast<thread T&&>(x);
}
template<typename T>
inline T spvGetSwizzle(vec<T, 4> 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<typename T>
inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s)
{
if (!s)
return x;
return vec<T, 4>(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<typename T>
inline T spvTextureSwizzle(T x, uint s)
{
return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x;
}
// Wrapper function that swizzles texture gathers.
template<typename T, typename Tex, typename... Ts>
inline vec<T, 4> 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<T, 4>(0, 0, 0, 0);
case spvSwizzle::one:
return vec<T, 4>(1, 1, 1, 1);
case spvSwizzle::red:
return t.gather(s, spvForward<Ts>(params)..., component::x);
case spvSwizzle::green:
return t.gather(s, spvForward<Ts>(params)..., component::y);
case spvSwizzle::blue:
return t.gather(s, spvForward<Ts>(params)..., component::z);
case spvSwizzle::alpha:
return t.gather(s, spvForward<Ts>(params)..., component::w);
}
}
switch (c)
{
case component::x:
return t.gather(s, spvForward<Ts>(params)..., component::x);
case component::y:
return t.gather(s, spvForward<Ts>(params)..., component::y);
case component::z:
return t.gather(s, spvForward<Ts>(params)..., component::z);
case component::w:
return t.gather(s, spvForward<Ts>(params)..., component::w);
}
}
// Wrapper function that swizzles depth texture gathers.
template<typename T, typename Tex, typename... Ts>
inline vec<T, 4> 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<T, 4>(0, 0, 0, 0);
case spvSwizzle::one:
return vec<T, 4>(1, 1, 1, 1);
}
}
return t.gather_compare(s, spvForward<Ts>(params)...);
}
float4 sample_in_func_1(thread const array<texture2d<float>, 4> uSampler0, thread const array<sampler, 4> uSampler0Smplr, constant uint32_t* uSampler0Swzl, thread float2& vUV)
{
return spvTextureSwizzle(uSampler0[2].sample(uSampler0Smplr[2], vUV), uSampler0Swzl[2]);
}
float4 sample_in_func_2(thread float2& vUV, thread texture2d<float> uSampler1, thread const sampler uSampler1Smplr, constant uint32_t& uSampler1Swzl)
{
return spvTextureSwizzle(uSampler1.sample(uSampler1Smplr, vUV), uSampler1Swzl);
}
float4 sample_single_in_func(thread const texture2d<float> s, thread const sampler sSmplr, constant uint32_t& sSwzl, thread float2& vUV)
{
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<float> uSampler1 [[texture(0)]], sampler uSampler1Smplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* spvDescriptorSet0_uSampler0Swzl = &spvDescriptorSet0.spvSwizzleConstants[1];
constant uint32_t& uSampler1Swzl = spvSwizzleConstants[0];
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;
}

View File

@ -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<float> 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<texture2d<float>, 4> uSampler [[texture(0)]], array<sampler, 4> uSamplerSmplr [[sampler(0)]])
fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvSwizzleConstants [[buffer(30)]], array<texture2d<float>, 4> uSampler [[texture(0)]], array<sampler, 4> uSamplerSmplr [[sampler(0)]])
{
main0_out out = {};
constant uint32_t* uSamplerSwzl = &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;

View File

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

View File

@ -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<CompilerMSL *>(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

View File

@ -33,7 +33,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 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);

View File

@ -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<uint32_t> 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<SPIRType>(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<SPIRType>(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<SPIRType>(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<SPIRType>(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<SPIRType>(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<SPIRType>(struct_ptr_id, struct_type_ptr);
ptr_type.self = struct_id;
set<SPIRVariable>(var_id, struct_ptr_id, StorageClassUniform);
set_name(var_id, "spvAuxBuffer");
set<SPIRVariable>(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<SPIRVariable>(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<SPIRCombinedImageSampler>(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<SPIRFunction>(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<SPIRType>(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<Resource> resources_in_set[kMaxArgumentBuffers];
bool set_needs_swizzle_buffer[kMaxArgumentBuffers] = {};
ir.for_each_typed_id<SPIRVariable>([&](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<SPIRType>(type_id, uint_type);
SPIRType uint_type_pointer = uint_type;
uint_type_pointer.pointer = true;
uint_type_pointer.pointer_depth = 1;
uint_type_pointer.parent_type = type_id;
uint_type_pointer.storage = StorageClassUniform;
set<SPIRType>(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<SPIRVariable>(var_id, swizzle_buffer_type_id, StorageClassUniformConstant);
set_name(var_id, "spvSwizzleConstants");
set_decoration(var_id, DecorationDescriptorSet, desc_set);
set_decoration(var_id, DecorationBinding, kSwizzleBufferBinding);
resources_in_set[desc_set].push_back(
{ &var, to_name(var_id), SPIRType::UInt, get_metal_resource_index(var, SPIRType::UInt) });
}
}
for (uint32_t desc_set = 0; desc_set < kMaxArgumentBuffers; desc_set++)
{
auto &resources = resources_in_set[desc_set];

View File

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