Merge pull request #706 from cdavis5e/component-swizzle

MSL: Add an option to insert texture swizzles into generated shaders.
This commit is contained in:
Hans-Kristian Arntzen 2018-09-25 10:06:03 +02:00 committed by GitHub
commit 69b034f26e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1757 additions and 3 deletions

View File

@ -489,6 +489,7 @@ struct CLIArguments
bool yflip = false;
bool sso = false;
bool support_nonzero_baseinstance = true;
bool msl_swizzle_texture_samples = false;
vector<PLSArg> pls_in;
vector<PLSArg> pls_out;
vector<Remap> remaps;
@ -703,6 +704,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
cbs.add("--msl-swizzle-texture-samples", [&args](CLIParser &) { args.msl_swizzle_texture_samples = true; });
cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
auto old_name = parser.next_string();
@ -822,6 +824,7 @@ static int main_inner(int argc, char *argv[])
auto msl_opts = msl_comp->get_msl_options();
if (args.set_msl_version)
msl_opts.msl_version = args.msl_version;
msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
msl_comp->set_msl_options(msl_opts);
}
else if (args.hlsl)

View File

@ -0,0 +1,162 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
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, spvSwizzle s)
{
switch (s)
{
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;
default:
break;
}
return 0;
}
// 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, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, 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, 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);
}
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], 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)]])
{
float4 c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0)), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(texCube.sample(texCubeSamp, float3(0.0)), spvAuxBuffer.swizzleConst[3]);
c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]);
c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]);
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSamp, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[8]);
c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySamp, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[9]);
c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvAuxBuffer.swizzleConst[10]);
c = spvTextureSwizzle(tex1d.sample(tex1dSamp, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]);
float4 _152 = float4(0.0, 0.0, 1.0, 1.0);
_152.z = float4(0.0, 0.0, 1.0, 1.0).w;
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, _152.xy / _152.z, float4(0.0, 0.0, 1.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(texCube.sample(texCubeSamp, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]);
c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]);
c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]);
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.sample(tex1dSamp, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]);
float4 _202 = float4(0.0, 0.0, 1.0, 1.0);
_202.z = float4(0.0, 0.0, 1.0, 1.0).w;
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, _202.xy / _202.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]);
c = texBuffer.read(spvTexelBufferCoord(0));
c = spvGatherSwizzle<float, texture2d<float>, float2, int2>(tex2dSamp, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]);
c = spvGatherSwizzle<float, texturecube<float>, float3>(texCubeSamp, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]);
c = spvGatherSwizzle<float, texture2d_array<float>, float2, uint, int2>(tex2dArraySamp, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]);
c = spvGatherSwizzle<float, texturecube_array<float>, float3, uint>(texCubeArraySamp, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]);
c = depth2d.gather_compare(depth2dSamp, float2(0.0), 1.0);
c = depthCube.gather_compare(depthCubeSamp, float3(0.0), 1.0);
c = depth2dArray.gather_compare(depth2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0);
c = depthCubeArray.gather_compare(depthCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0);
}

View File

@ -0,0 +1,147 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
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, spvSwizzle s)
{
switch (s)
{
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;
default:
break;
}
return 0;
}
// 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, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, 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, 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);
}
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], 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)]])
{
float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]));
c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]));
c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]));
c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]));
c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]));
c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]));
c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]));
c = float4(texBuffer.read(spvTexelBufferCoord(0)));
c = float4(spvGatherSwizzle<int, texture2d<int>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]));
c = float4(spvGatherSwizzle<int, texturecube<int>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]));
c = float4(spvGatherSwizzle<int, texture2d_array<int>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]));
c = float4(spvGatherSwizzle<int, texturecube_array<int>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]));
}

View File

@ -0,0 +1,168 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
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, spvSwizzle s)
{
switch (s)
{
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;
default:
break;
}
return 0;
}
// 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, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, 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, 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);
}
}
float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr, thread texture2d<float> tex2d, thread const sampler tex2dSmplr, thread texture3d<float> tex3d, thread const sampler tex3dSmplr, thread texturecube<float> texCube, thread const sampler texCubeSmplr, thread texture2d_array<float> tex2dArray, thread const sampler tex2dArraySmplr, thread texturecube_array<float> texCubeArray, thread const sampler texCubeArraySmplr, thread depth2d<float> depth2d, thread const sampler depth2dSmplr, thread depthcube<float> depthCube, thread const sampler depthCubeSmplr, thread depth2d_array<float> depth2dArray, thread const sampler depth2dArraySmplr, thread depthcube_array<float> depthCubeArray, thread const sampler depthCubeArraySmplr, thread texture2d<float> texBuffer, constant spvAux& spvAuxBuffer)
{
float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]);
c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]);
c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]);
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[8]);
c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[9]);
c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvAuxBuffer.swizzleConst[10]);
c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]);
float4 _103 = float4(0.0, 0.0, 1.0, 1.0);
_103.z = float4(0.0, 0.0, 1.0, 1.0).w;
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _103.xy / _103.z, float4(0.0, 0.0, 1.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]);
c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]);
c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]);
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]);
float4 _131 = float4(0.0, 0.0, 1.0, 1.0);
_131.z = float4(0.0, 0.0, 1.0, 1.0).w;
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _131.xy / _131.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]);
c = texBuffer.read(spvTexelBufferCoord(0));
c = spvGatherSwizzle<float, texture2d<float>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]);
c = spvGatherSwizzle<float, texturecube<float>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]);
c = spvGatherSwizzle<float, texture2d_array<float>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]);
c = spvGatherSwizzle<float, texturecube_array<float>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]);
c = depth2d.gather_compare(depth2dSmplr, float2(0.0), 1.0);
c = depthCube.gather_compare(depthCubeSmplr, float3(0.0), 1.0);
c = depth2dArray.gather_compare(depth2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0);
c = depthCubeArray.gather_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0);
return c;
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], 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)]])
{
float4 c = doSwizzle(tex1d, tex1dSmplr, tex2d, tex2dSmplr, tex3d, tex3dSmplr, texCube, texCubeSmplr, tex2dArray, tex2dArraySmplr, texCubeArray, texCubeArraySmplr, depth2d, depth2dSmplr, depthCube, depthCubeSmplr, depth2dArray, depth2dArraySmplr, depthCubeArray, depthCubeArraySmplr, texBuffer, spvAuxBuffer);
}

View File

@ -0,0 +1,147 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
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, spvSwizzle s)
{
switch (s)
{
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;
default:
break;
}
return 0;
}
// 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, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, 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, 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);
}
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], 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)]])
{
float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]));
c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]));
c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]));
c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]));
c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]));
c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]));
c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]));
c = float4(spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]));
c = float4(spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]));
c = float4(spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]));
c = float4(texBuffer.read(spvTexelBufferCoord(0)));
c = float4(spvGatherSwizzle<uint, texture2d<uint>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]));
c = float4(spvGatherSwizzle<uint, texturecube<uint>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]));
c = float4(spvGatherSwizzle<uint, texture2d_array<uint>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]));
c = float4(spvGatherSwizzle<uint, texturecube_array<uint>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]));
}

View File

@ -0,0 +1,162 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct spvAux
{
uint swizzleConst[1];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
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, spvSwizzle s)
{
switch (s)
{
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;
default:
break;
}
return 0;
}
// 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, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, 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, 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);
}
}
fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], 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)]])
{
float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]);
c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]);
c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]);
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[8]);
c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[9]);
c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvAuxBuffer.swizzleConst[10]);
c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]);
float4 _100 = float4(0.0, 0.0, 1.0, 1.0);
_100.z = float4(0.0, 0.0, 1.0, 1.0).w;
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _100.xy / _100.z, float4(0.0, 0.0, 1.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]);
c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]);
c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]);
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]);
float4 _128 = float4(0.0, 0.0, 1.0, 1.0);
_128.z = float4(0.0, 0.0, 1.0, 1.0).w;
c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _128.xy / _128.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
c = spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]);
c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]);
c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]);
c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]);
c = texBuffer.read(spvTexelBufferCoord(0));
c = spvGatherSwizzle<float, texture2d<float>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]);
c = spvGatherSwizzle<float, texturecube<float>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]);
c = spvGatherSwizzle<float, texture2d_array<float>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]);
c = spvGatherSwizzle<float, texturecube_array<float>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]);
c = depth2d.gather_compare(depth2dSmplr, float2(0.0), 1.0);
c = depthCube.gather_compare(depthCubeSmplr, float3(0.0), 1.0);
c = depth2dArray.gather_compare(depth2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0);
c = depthCubeArray.gather_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0);
}

View File

@ -0,0 +1,364 @@
; SPIR-V
; Version: 1.3
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 247
; Schema: 0
OpCapability Shader
OpCapability Sampled1D
OpCapability SampledCubeArray
OpCapability SampledBuffer
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %c "c"
OpName %tex1d "tex1d"
OpName %tex2d "tex2d"
OpName %tex3d "tex3d"
OpName %texCube "texCube"
OpName %tex2dArray "tex2dArray"
OpName %texCubeArray "texCubeArray"
OpName %depth2d "depth2d"
OpName %depthCube "depthCube"
OpName %depth2dArray "depth2dArray"
OpName %depthCubeArray "depthCubeArray"
OpName %texBuffer "texBuffer"
OpName %tex1dSamp "tex1dSamp"
OpName %tex2dSamp "tex2dSamp"
OpName %tex3dSamp "tex3dSamp"
OpName %texCubeSamp "texCubeSamp"
OpName %tex2dArraySamp "tex2dArraySamp"
OpName %texCubeArraySamp "texCubeArraySamp"
OpName %depth2dSamp "depth2dSamp"
OpName %depthCubeSamp "depthCubeSamp"
OpName %depth2dArraySamp "depth2dArraySamp"
OpName %depthCubeArraySamp "depthCubeArraySamp"
OpDecorate %tex1d DescriptorSet 0
OpDecorate %tex1d Binding 0
OpDecorate %tex2d DescriptorSet 0
OpDecorate %tex2d Binding 1
OpDecorate %tex3d DescriptorSet 0
OpDecorate %tex3d Binding 2
OpDecorate %texCube DescriptorSet 0
OpDecorate %texCube Binding 3
OpDecorate %tex2dArray DescriptorSet 0
OpDecorate %tex2dArray Binding 4
OpDecorate %texCubeArray DescriptorSet 0
OpDecorate %texCubeArray Binding 5
OpDecorate %depth2d DescriptorSet 0
OpDecorate %depth2d Binding 7
OpDecorate %depthCube DescriptorSet 0
OpDecorate %depthCube Binding 8
OpDecorate %depth2dArray DescriptorSet 0
OpDecorate %depth2dArray Binding 9
OpDecorate %depthCubeArray DescriptorSet 0
OpDecorate %depthCubeArray Binding 10
OpDecorate %texBuffer DescriptorSet 0
OpDecorate %texBuffer Binding 6
OpDecorate %tex1dSamp DescriptorSet 1
OpDecorate %tex1dSamp Binding 0
OpDecorate %tex2dSamp DescriptorSet 1
OpDecorate %tex2dSamp Binding 1
OpDecorate %tex3dSamp DescriptorSet 1
OpDecorate %tex3dSamp Binding 2
OpDecorate %texCubeSamp DescriptorSet 1
OpDecorate %texCubeSamp Binding 3
OpDecorate %tex2dArraySamp DescriptorSet 1
OpDecorate %tex2dArraySamp Binding 4
OpDecorate %texCubeArraySamp DescriptorSet 1
OpDecorate %texCubeArraySamp Binding 5
OpDecorate %depth2dSamp DescriptorSet 1
OpDecorate %depth2dSamp Binding 7
OpDecorate %depthCubeSamp DescriptorSet 1
OpDecorate %depthCubeSamp Binding 8
OpDecorate %depth2dArraySamp DescriptorSet 1
OpDecorate %depth2dArraySamp Binding 9
OpDecorate %depthCubeArraySamp DescriptorSet 1
OpDecorate %depthCubeArraySamp Binding 10
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Function_v4float = OpTypePointer Function %v4float
%10 = OpTypeImage %float 1D 0 0 0 1 Unknown
%11 = OpTypeSampledImage %10
%12 = OpTypeSampler
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
%tex1d = OpVariable %_ptr_UniformConstant_10 UniformConstant
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
%tex1dSamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%float_0 = OpConstant %float 0
%17 = OpTypeImage %float 2D 0 0 0 1 Unknown
%18 = OpTypeSampledImage %17
%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
%tex2d = OpVariable %_ptr_UniformConstant_17 UniformConstant
%tex2dSamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%v2float = OpTypeVector %float 2
%23 = OpConstantComposite %v2float %float_0 %float_0
%25 = OpTypeImage %float 3D 0 0 0 1 Unknown
%26 = OpTypeSampledImage %25
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
%tex3d = OpVariable %_ptr_UniformConstant_25 UniformConstant
%tex3dSamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%v3float = OpTypeVector %float 3
%31 = OpConstantComposite %v3float %float_0 %float_0 %float_0
%33 = OpTypeImage %float Cube 0 0 0 1 Unknown
%34 = OpTypeSampledImage %33
%_ptr_UniformConstant_33 = OpTypePointer UniformConstant %33
%texCube = OpVariable %_ptr_UniformConstant_33 UniformConstant
%texCubeSamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%39 = OpTypeImage %float 2D 0 1 0 1 Unknown
%40 = OpTypeSampledImage %39
%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39
%tex2dArray = OpVariable %_ptr_UniformConstant_39 UniformConstant
%tex2dArraySamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%45 = OpTypeImage %float Cube 0 1 0 1 Unknown
%46 = OpTypeSampledImage %45
%_ptr_UniformConstant_45 = OpTypePointer UniformConstant %45
%texCubeArray = OpVariable %_ptr_UniformConstant_45 UniformConstant
%texCubeArraySamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%52 = OpTypeImage %float 2D 1 0 0 1 Unknown
%53 = OpTypeSampledImage %52
%_ptr_UniformConstant_52 = OpTypePointer UniformConstant %52
%depth2d = OpVariable %_ptr_UniformConstant_52 UniformConstant
%depth2dSamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%float_1 = OpConstant %float 1
%58 = OpConstantComposite %v3float %float_0 %float_0 %float_1
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%_ptr_Function_float = OpTypePointer Function %float
%65 = OpTypeImage %float Cube 1 0 0 1 Unknown
%66 = OpTypeSampledImage %65
%_ptr_UniformConstant_65 = OpTypePointer UniformConstant %65
%depthCube = OpVariable %_ptr_UniformConstant_65 UniformConstant
%depthCubeSamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%70 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
%74 = OpTypeImage %float 2D 1 1 0 1 Unknown
%75 = OpTypeSampledImage %74
%_ptr_UniformConstant_74 = OpTypePointer UniformConstant %74
%depth2dArray = OpVariable %_ptr_UniformConstant_74 UniformConstant
%depth2dArraySamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%82 = OpTypeImage %float Cube 1 1 0 1 Unknown
%83 = OpTypeSampledImage %82
%_ptr_UniformConstant_82 = OpTypePointer UniformConstant %82
%depthCubeArray = OpVariable %_ptr_UniformConstant_82 UniformConstant
%depthCubeArraySamp = OpVariable %_ptr_UniformConstant_12 UniformConstant
%97 = OpConstantComposite %v2float %float_0 %float_1
%98 = OpConstantComposite %v4float %float_0 %float_0 %float_1 %float_1
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%v2int = OpTypeVector %int 2
%138 = OpConstantComposite %v2int %int_0 %int_0
%v3int = OpTypeVector %int 3
%143 = OpConstantComposite %v3int %int_0 %int_0 %int_0
%149 = OpTypeImage %float Buffer 0 0 0 1 Unknown
%_ptr_UniformConstant_149 = OpTypePointer UniformConstant %149
%texBuffer = OpVariable %_ptr_UniformConstant_149 UniformConstant
%int_1 = OpConstant %int 1
%int_2 = OpConstant %int 2
%int_3 = OpConstant %int 3
%main = OpFunction %void None %3
%5 = OpLabel
%c = OpVariable %_ptr_Function_v4float Function
%13 = OpLoad %10 %tex1d
%14 = OpLoad %12 %tex1dSamp
%15 = OpSampledImage %11 %13 %14
%16 = OpImageSampleImplicitLod %v4float %15 %float_0
OpStore %c %16
%19 = OpLoad %17 %tex2d
%20 = OpLoad %12 %tex2dSamp
%21 = OpSampledImage %18 %19 %20
%24 = OpImageSampleImplicitLod %v4float %21 %23
OpStore %c %24
%27 = OpLoad %25 %tex3d
%28 = OpLoad %12 %tex3dSamp
%29 = OpSampledImage %26 %27 %28
%32 = OpImageSampleImplicitLod %v4float %29 %31
OpStore %c %32
%35 = OpLoad %33 %texCube
%36 = OpLoad %12 %texCubeSamp
%37 = OpSampledImage %34 %35 %36
%38 = OpImageSampleImplicitLod %v4float %37 %31
OpStore %c %38
%41 = OpLoad %39 %tex2dArray
%42 = OpLoad %12 %tex2dArraySamp
%43 = OpSampledImage %40 %41 %42
%44 = OpImageSampleImplicitLod %v4float %43 %31
OpStore %c %44
%47 = OpLoad %45 %texCubeArray
%48 = OpLoad %12 %texCubeArraySamp
%49 = OpSampledImage %46 %47 %48
%51 = OpImageSampleImplicitLod %v4float %49 %50
OpStore %c %51
%54 = OpLoad %52 %depth2d
%55 = OpLoad %12 %depth2dSamp
%56 = OpSampledImage %53 %54 %55
%59 = OpCompositeExtract %float %58 2
%60 = OpImageSampleDrefImplicitLod %float %56 %58 %59
%64 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %64 %60
%67 = OpLoad %65 %depthCube
%68 = OpLoad %12 %depthCubeSamp
%69 = OpSampledImage %66 %67 %68
%71 = OpCompositeExtract %float %70 3
%72 = OpImageSampleDrefImplicitLod %float %69 %70 %71
%73 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %73 %72
%76 = OpLoad %74 %depth2dArray
%77 = OpLoad %12 %depth2dArraySamp
%78 = OpSampledImage %75 %76 %77
%79 = OpCompositeExtract %float %70 3
%80 = OpImageSampleDrefImplicitLod %float %78 %70 %79
%81 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %81 %80
%84 = OpLoad %82 %depthCubeArray
%85 = OpLoad %12 %depthCubeArraySamp
%86 = OpSampledImage %83 %84 %85
%87 = OpImageSampleDrefImplicitLod %float %86 %50 %float_1
%88 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %88 %87
%89 = OpLoad %10 %tex1d
%90 = OpLoad %12 %tex1dSamp
%91 = OpSampledImage %11 %89 %90
%92 = OpImageSampleProjImplicitLod %v4float %91 %97
OpStore %c %92
%93 = OpLoad %17 %tex2d
%94 = OpLoad %12 %tex2dSamp
%95 = OpSampledImage %18 %93 %94
%96 = OpImageSampleProjImplicitLod %v4float %95 %58
OpStore %c %96
%99 = OpLoad %25 %tex3d
%100 = OpLoad %12 %tex3dSamp
%101 = OpSampledImage %26 %99 %100
%102 = OpImageSampleProjImplicitLod %v4float %101 %70
OpStore %c %102
%103 = OpLoad %52 %depth2d
%104 = OpLoad %12 %depth2dSamp
%105 = OpSampledImage %53 %103 %104
%106 = OpCompositeExtract %float %98 2
%107 = OpCompositeExtract %float %98 3
%108 = OpCompositeInsert %v4float %107 %98 2
%109 = OpImageSampleProjDrefImplicitLod %float %105 %108 %106
%110 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %110 %109
%111 = OpLoad %10 %tex1d
%112 = OpLoad %12 %tex1dSamp
%113 = OpSampledImage %11 %111 %112
%114 = OpImageSampleExplicitLod %v4float %113 %float_0 Lod %float_0
OpStore %c %114
%115 = OpLoad %17 %tex2d
%116 = OpLoad %12 %tex2dSamp
%117 = OpSampledImage %18 %115 %116
%118 = OpImageSampleExplicitLod %v4float %117 %23 Lod %float_0
OpStore %c %118
%119 = OpLoad %25 %tex3d
%120 = OpLoad %12 %tex3dSamp
%121 = OpSampledImage %26 %119 %120
%122 = OpImageSampleExplicitLod %v4float %121 %31 Lod %float_0
OpStore %c %122
%123 = OpLoad %33 %texCube
%124 = OpLoad %12 %texCubeSamp
%125 = OpSampledImage %34 %123 %124
%126 = OpImageSampleExplicitLod %v4float %125 %31 Lod %float_0
OpStore %c %126
%127 = OpLoad %39 %tex2dArray
%128 = OpLoad %12 %tex2dArraySamp
%129 = OpSampledImage %40 %127 %128
%130 = OpImageSampleExplicitLod %v4float %129 %31 Lod %float_0
OpStore %c %130
%131 = OpLoad %45 %texCubeArray
%132 = OpLoad %12 %texCubeArraySamp
%133 = OpSampledImage %46 %131 %132
%134 = OpImageSampleExplicitLod %v4float %133 %50 Lod %float_0
OpStore %c %134
%135 = OpLoad %52 %depth2d
%136 = OpLoad %12 %depth2dSamp
%137 = OpSampledImage %53 %135 %136
%139 = OpCompositeExtract %float %58 2
%140 = OpImageSampleDrefExplicitLod %float %137 %58 %139 Lod %float_0
%141 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %141 %140
%142 = OpLoad %10 %tex1d
%144 = OpLoad %12 %tex1dSamp
%145 = OpSampledImage %11 %142 %144
%146 = OpImageSampleProjExplicitLod %v4float %145 %97 Lod %float_0
OpStore %c %146
%147 = OpLoad %17 %tex2d
%148 = OpLoad %12 %tex2dSamp
%150 = OpSampledImage %18 %147 %148
%151 = OpImageSampleProjExplicitLod %v4float %150 %58 Lod %float_0
OpStore %c %151
%152 = OpLoad %25 %tex3d
%153 = OpLoad %12 %tex3dSamp
%154 = OpSampledImage %26 %152 %153
%155 = OpImageSampleProjExplicitLod %v4float %154 %70 Lod %float_0
OpStore %c %155
%156 = OpLoad %52 %depth2d
%157 = OpLoad %12 %depth2dSamp
%158 = OpSampledImage %53 %156 %157
%159 = OpCompositeExtract %float %98 2
%160 = OpCompositeExtract %float %98 3
%161 = OpCompositeInsert %v4float %160 %98 2
%162 = OpImageSampleProjDrefExplicitLod %float %158 %161 %159 Lod %float_0
%163 = OpAccessChain %_ptr_Function_float %c %uint_0
OpStore %163 %162
%164 = OpLoad %10 %tex1d
%165 = OpImageFetch %v4float %164 %int_0 Lod %int_0
OpStore %c %165
%166 = OpLoad %17 %tex2d
%167 = OpImageFetch %v4float %166 %138 Lod %int_0
OpStore %c %167
%168 = OpLoad %25 %tex3d
%169 = OpImageFetch %v4float %168 %143 Lod %int_0
OpStore %c %169
%170 = OpLoad %39 %tex2dArray
%171 = OpImageFetch %v4float %170 %143 Lod %int_0
OpStore %c %171
%172 = OpLoad %149 %texBuffer
%173 = OpImageFetch %v4float %172 %int_0
OpStore %c %173
%174 = OpLoad %17 %tex2d
%175 = OpLoad %12 %tex2dSamp
%176 = OpSampledImage %18 %174 %175
%177 = OpImageGather %v4float %176 %23 %int_0
OpStore %c %177
%178 = OpLoad %33 %texCube
%179 = OpLoad %12 %texCubeSamp
%180 = OpSampledImage %34 %178 %179
%181 = OpImageGather %v4float %180 %31 %int_1
OpStore %c %181
%182 = OpLoad %39 %tex2dArray
%183 = OpLoad %12 %tex2dArraySamp
%184 = OpSampledImage %40 %182 %183
%185 = OpImageGather %v4float %184 %31 %int_2
OpStore %c %185
%186 = OpLoad %45 %texCubeArray
%187 = OpLoad %12 %texCubeArraySamp
%188 = OpSampledImage %46 %186 %187
%189 = OpImageGather %v4float %188 %50 %int_3
OpStore %c %189
%190 = OpLoad %52 %depth2d
%191 = OpLoad %12 %depth2dSamp
%192 = OpSampledImage %53 %190 %191
%193 = OpImageDrefGather %v4float %192 %23 %float_1
OpStore %c %193
%194 = OpLoad %65 %depthCube
%195 = OpLoad %12 %depthCubeSamp
%196 = OpSampledImage %66 %194 %195
%197 = OpImageDrefGather %v4float %196 %31 %float_1
OpStore %c %197
%198 = OpLoad %74 %depth2dArray
%199 = OpLoad %12 %depth2dArraySamp
%200 = OpSampledImage %75 %198 %199
%201 = OpImageDrefGather %v4float %200 %31 %float_1
OpStore %c %201
%202 = OpLoad %82 %depthCubeArray
%203 = OpLoad %12 %depthCubeArraySamp
%204 = OpSampledImage %83 %202 %203
%205 = OpImageDrefGather %v4float %204 %50 %float_1
OpStore %c %205
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,53 @@
#version 450
layout(binding = 0) uniform isampler1D tex1d;
layout(binding = 1) uniform isampler2D tex2d;
layout(binding = 2) uniform isampler3D tex3d;
layout(binding = 3) uniform isamplerCube texCube;
layout(binding = 4) uniform isampler2DArray tex2dArray;
layout(binding = 5) uniform isamplerCubeArray texCubeArray;
layout(binding = 6) uniform isamplerBuffer texBuffer;
void main()
{
// OpImageSampleImplicitLod
vec4 c = texture(tex1d, 0.0);
c = texture(tex2d, vec2(0.0, 0.0));
c = texture(tex3d, vec3(0.0, 0.0, 0.0));
c = texture(texCube, vec3(0.0, 0.0, 0.0));
c = texture(tex2dArray, vec3(0.0, 0.0, 0.0));
c = texture(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0));
// OpImageSampleProjImplicitLod
c = textureProj(tex1d, vec2(0.0, 1.0));
c = textureProj(tex2d, vec3(0.0, 0.0, 1.0));
c = textureProj(tex3d, vec4(0.0, 0.0, 0.0, 1.0));
// OpImageSampleExplicitLod
c = textureLod(tex1d, 0.0, 0.0);
c = textureLod(tex2d, vec2(0.0, 0.0), 0.0);
c = textureLod(tex3d, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCube, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(tex2dArray, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 0.0);
// OpImageSampleProjExplicitLod
c = textureProjLod(tex1d, vec2(0.0, 1.0), 0.0);
c = textureProjLod(tex2d, vec3(0.0, 0.0, 1.0), 0.0);
c = textureProjLod(tex3d, vec4(0.0, 0.0, 0.0, 1.0), 0.0);
// OpImageFetch
c = texelFetch(tex1d, 0, 0);
c = texelFetch(tex2d, ivec2(0, 0), 0);
c = texelFetch(tex3d, ivec3(0, 0, 0), 0);
c = texelFetch(tex2dArray, ivec3(0, 0, 0), 0);
// Show that this transformation doesn't apply to Buffer images.
c = texelFetch(texBuffer, 0);
// OpImageGather
c = textureGather(tex2d, vec2(0.0, 0.0), 0);
c = textureGather(texCube, vec3(0.0, 0.0, 0.0), 1);
c = textureGather(tex2dArray, vec3(0.0, 0.0, 0.0), 2);
c = textureGather(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 3);
}

View File

@ -0,0 +1,86 @@
#version 450
layout(binding = 0) uniform sampler1D tex1d;
layout(binding = 1) uniform sampler2D tex2d;
layout(binding = 2) uniform sampler3D tex3d;
layout(binding = 3) uniform samplerCube texCube;
layout(binding = 4) uniform sampler2DArray tex2dArray;
layout(binding = 5) uniform samplerCubeArray texCubeArray;
layout(binding = 6) uniform samplerBuffer texBuffer;
layout(binding = 7) uniform sampler2DShadow depth2d;
layout(binding = 8) uniform samplerCubeShadow depthCube;
layout(binding = 9) uniform sampler2DArrayShadow depth2dArray;
layout(binding = 10) uniform samplerCubeArrayShadow depthCubeArray;
vec4 doSwizzle()
{
// OpImageSampleImplicitLod
vec4 c = texture(tex1d, 0.0);
c = texture(tex2d, vec2(0.0, 0.0));
c = texture(tex3d, vec3(0.0, 0.0, 0.0));
c = texture(texCube, vec3(0.0, 0.0, 0.0));
c = texture(tex2dArray, vec3(0.0, 0.0, 0.0));
c = texture(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0));
// OpImageSampleDrefImplicitLod
c.r = texture(depth2d, vec3(0.0, 0.0, 1.0));
c.r = texture(depthCube, vec4(0.0, 0.0, 0.0, 1.0));
c.r = texture(depth2dArray, vec4(0.0, 0.0, 0.0, 1.0));
c.r = texture(depthCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 1.0);
// OpImageSampleProjImplicitLod
c = textureProj(tex1d, vec2(0.0, 1.0));
c = textureProj(tex2d, vec3(0.0, 0.0, 1.0));
c = textureProj(tex3d, vec4(0.0, 0.0, 0.0, 1.0));
// OpImageSampleProjDrefImplicitLod
c.r = textureProj(depth2d, vec4(0.0, 0.0, 1.0, 1.0));
// OpImageSampleExplicitLod
c = textureLod(tex1d, 0.0, 0.0);
c = textureLod(tex2d, vec2(0.0, 0.0), 0.0);
c = textureLod(tex3d, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCube, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(tex2dArray, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 0.0);
// OpImageSampleDrefExplicitLod
c.r = textureLod(depth2d, vec3(0.0, 0.0, 1.0), 0.0);
// OpImageSampleProjExplicitLod
c = textureProjLod(tex1d, vec2(0.0, 1.0), 0.0);
c = textureProjLod(tex2d, vec3(0.0, 0.0, 1.0), 0.0);
c = textureProjLod(tex3d, vec4(0.0, 0.0, 0.0, 1.0), 0.0);
// OpImageSampleProjDrefExplicitLod
c.r = textureProjLod(depth2d, vec4(0.0, 0.0, 1.0, 1.0), 0.0);
// OpImageFetch
c = texelFetch(tex1d, 0, 0);
c = texelFetch(tex2d, ivec2(0, 0), 0);
c = texelFetch(tex3d, ivec3(0, 0, 0), 0);
c = texelFetch(tex2dArray, ivec3(0, 0, 0), 0);
// Show that this transformation doesn't apply to Buffer images.
c = texelFetch(texBuffer, 0);
// OpImageGather
c = textureGather(tex2d, vec2(0.0, 0.0), 0);
c = textureGather(texCube, vec3(0.0, 0.0, 0.0), 1);
c = textureGather(tex2dArray, vec3(0.0, 0.0, 0.0), 2);
c = textureGather(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 3);
// OpImageDrefGather
c = textureGather(depth2d, vec2(0.0, 0.0), 1.0);
c = textureGather(depthCube, vec3(0.0, 0.0, 0.0), 1.0);
c = textureGather(depth2dArray, vec3(0.0, 0.0, 0.0), 1.0);
c = textureGather(depthCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 1.0);
return c;
}
void main()
{
vec4 c = doSwizzle();
}

View File

@ -0,0 +1,53 @@
#version 450
layout(binding = 0) uniform usampler1D tex1d;
layout(binding = 1) uniform usampler2D tex2d;
layout(binding = 2) uniform usampler3D tex3d;
layout(binding = 3) uniform usamplerCube texCube;
layout(binding = 4) uniform usampler2DArray tex2dArray;
layout(binding = 5) uniform usamplerCubeArray texCubeArray;
layout(binding = 6) uniform usamplerBuffer texBuffer;
void main()
{
// OpImageSampleImplicitLod
vec4 c = texture(tex1d, 0.0);
c = texture(tex2d, vec2(0.0, 0.0));
c = texture(tex3d, vec3(0.0, 0.0, 0.0));
c = texture(texCube, vec3(0.0, 0.0, 0.0));
c = texture(tex2dArray, vec3(0.0, 0.0, 0.0));
c = texture(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0));
// OpImageSampleProjImplicitLod
c = textureProj(tex1d, vec2(0.0, 1.0));
c = textureProj(tex2d, vec3(0.0, 0.0, 1.0));
c = textureProj(tex3d, vec4(0.0, 0.0, 0.0, 1.0));
// OpImageSampleExplicitLod
c = textureLod(tex1d, 0.0, 0.0);
c = textureLod(tex2d, vec2(0.0, 0.0), 0.0);
c = textureLod(tex3d, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCube, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(tex2dArray, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 0.0);
// OpImageSampleProjExplicitLod
c = textureProjLod(tex1d, vec2(0.0, 1.0), 0.0);
c = textureProjLod(tex2d, vec3(0.0, 0.0, 1.0), 0.0);
c = textureProjLod(tex3d, vec4(0.0, 0.0, 0.0, 1.0), 0.0);
// OpImageFetch
c = texelFetch(tex1d, 0, 0);
c = texelFetch(tex2d, ivec2(0, 0), 0);
c = texelFetch(tex3d, ivec3(0, 0, 0), 0);
c = texelFetch(tex2dArray, ivec3(0, 0, 0), 0);
// Show that this transformation doesn't apply to Buffer images.
c = texelFetch(texBuffer, 0);
// OpImageGather
c = textureGather(tex2d, vec2(0.0, 0.0), 0);
c = textureGather(texCube, vec3(0.0, 0.0, 0.0), 1);
c = textureGather(tex2dArray, vec3(0.0, 0.0, 0.0), 2);
c = textureGather(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 3);
}

View File

@ -0,0 +1,79 @@
#version 450
layout(binding = 0) uniform sampler1D tex1d;
layout(binding = 1) uniform sampler2D tex2d;
layout(binding = 2) uniform sampler3D tex3d;
layout(binding = 3) uniform samplerCube texCube;
layout(binding = 4) uniform sampler2DArray tex2dArray;
layout(binding = 5) uniform samplerCubeArray texCubeArray;
layout(binding = 6) uniform samplerBuffer texBuffer;
layout(binding = 7) uniform sampler2DShadow depth2d;
layout(binding = 8) uniform samplerCubeShadow depthCube;
layout(binding = 9) uniform sampler2DArrayShadow depth2dArray;
layout(binding = 10) uniform samplerCubeArrayShadow depthCubeArray;
void main()
{
// OpImageSampleImplicitLod
vec4 c = texture(tex1d, 0.0);
c = texture(tex2d, vec2(0.0, 0.0));
c = texture(tex3d, vec3(0.0, 0.0, 0.0));
c = texture(texCube, vec3(0.0, 0.0, 0.0));
c = texture(tex2dArray, vec3(0.0, 0.0, 0.0));
c = texture(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0));
// OpImageSampleDrefImplicitLod
c.r = texture(depth2d, vec3(0.0, 0.0, 1.0));
c.r = texture(depthCube, vec4(0.0, 0.0, 0.0, 1.0));
c.r = texture(depth2dArray, vec4(0.0, 0.0, 0.0, 1.0));
c.r = texture(depthCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 1.0);
// OpImageSampleProjImplicitLod
c = textureProj(tex1d, vec2(0.0, 1.0));
c = textureProj(tex2d, vec3(0.0, 0.0, 1.0));
c = textureProj(tex3d, vec4(0.0, 0.0, 0.0, 1.0));
// OpImageSampleProjDrefImplicitLod
c.r = textureProj(depth2d, vec4(0.0, 0.0, 1.0, 1.0));
// OpImageSampleExplicitLod
c = textureLod(tex1d, 0.0, 0.0);
c = textureLod(tex2d, vec2(0.0, 0.0), 0.0);
c = textureLod(tex3d, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCube, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(tex2dArray, vec3(0.0, 0.0, 0.0), 0.0);
c = textureLod(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 0.0);
// OpImageSampleDrefExplicitLod
c.r = textureLod(depth2d, vec3(0.0, 0.0, 1.0), 0.0);
// OpImageSampleProjExplicitLod
c = textureProjLod(tex1d, vec2(0.0, 1.0), 0.0);
c = textureProjLod(tex2d, vec3(0.0, 0.0, 1.0), 0.0);
c = textureProjLod(tex3d, vec4(0.0, 0.0, 0.0, 1.0), 0.0);
// OpImageSampleProjDrefExplicitLod
c.r = textureProjLod(depth2d, vec4(0.0, 0.0, 1.0, 1.0), 0.0);
// OpImageFetch
c = texelFetch(tex1d, 0, 0);
c = texelFetch(tex2d, ivec2(0, 0), 0);
c = texelFetch(tex3d, ivec3(0, 0, 0), 0);
c = texelFetch(tex2dArray, ivec3(0, 0, 0), 0);
// Show that this transformation doesn't apply to Buffer images.
c = texelFetch(texBuffer, 0);
// OpImageGather
c = textureGather(tex2d, vec2(0.0, 0.0), 0);
c = textureGather(texCube, vec3(0.0, 0.0, 0.0), 1);
c = textureGather(tex2dArray, vec3(0.0, 0.0, 0.0), 2);
c = textureGather(texCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 3);
// OpImageDrefGather
c = textureGather(depth2d, vec2(0.0, 0.0), 1.0);
c = textureGather(depthCube, vec3(0.0, 0.0, 0.0), 1.0);
c = textureGather(depth2dArray, vec3(0.0, 0.0, 0.0), 1.0);
c = textureGather(depthCubeArray, vec4(0.0, 0.0, 0.0, 0.0), 1.0);
}

View File

@ -1237,6 +1237,7 @@ struct Meta
Decoration decoration;
std::vector<Decoration> members;
uint32_t sampler = 0;
uint32_t image = 0;
std::unordered_map<uint32_t, uint32_t> decoration_word_offset;

View File

@ -1096,6 +1096,12 @@ const SPIRType &Compiler::get_non_pointer_type(uint32_t type_id) const
return get_non_pointer_type(get<SPIRType>(type_id));
}
bool Compiler::is_sampled_image_type(const SPIRType &type)
{
return (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage) &&
type.image.sampled == 1 && type.image.dim != DimBuffer;
}
void Compiler::set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration,
const std::string &argument)
{

View File

@ -179,6 +179,9 @@ public:
// Gets the SPIR-V type underlying the given type_id, which might be a pointer.
const SPIRType &get_non_pointer_type(uint32_t type_id) const;
// Returns if the given type refers to a sampled image.
bool is_sampled_image_type(const SPIRType &type);
// Gets the underlying storage class for an OpVariable.
spv::StorageClass get_storage_class(uint32_t id) const;

View File

@ -28,6 +28,8 @@ 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(vector<uint32_t> spirv_, vector<MSLVertexAttr> *p_vtx_attrs,
vector<MSLResourceBinding> *p_res_bindings)
: CompilerGLSL(move(spirv_))
@ -139,6 +141,53 @@ void CompilerMSL::build_implicit_builtins()
builtin_sample_id_id = var_id;
}
}
if (msl_options.swizzle_texture_samples && has_sampled_images)
{
uint32_t offset = increase_bound_by(5);
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;
// Create a buffer to hold the swizzle constants.
SPIRType uint_type;
uint_type.basetype = SPIRType::UInt;
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 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, 0, "swizzleConst");
set_member_decoration(struct_id, 0, DecorationOffset, 0);
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");
// 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;
}
}
static string create_sampler_address(const char *prefix, MSLSamplerAddress addr)
@ -323,11 +372,14 @@ string CompilerMSL::compile()
build_function_control_flow_graphs_and_analyze();
update_active_builtins();
analyze_image_and_sampler_usage();
analyze_sampled_image_usage();
build_implicit_builtins();
fixup_image_load_store_access();
set_enabled_interface_variables(get_active_interface_variables());
if (aux_buffer_id)
active_interface_variables.insert(aux_buffer_id);
// Preprocess OpCodes to extract the need to output additional header content
preprocess_op_codes();
@ -537,6 +589,13 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
added_arg_ids.insert(builtin_frag_coord_id);
}
if (msl_options.swizzle_texture_samples && is_sampled_image_type(type))
{
// Implicitly reads spvAuxBuffer.
assert(aux_buffer_id != 0);
added_arg_ids.insert(aux_buffer_id);
}
break;
}
@ -1584,6 +1643,113 @@ void CompilerMSL::emit_custom_functions()
statement("");
break;
case SPVFuncImplTextureSwizzle:
statement("enum class spvSwizzle : uint");
begin_scope();
statement("none = 0,");
statement("zero,");
statement("one,");
statement("red,");
statement("green,");
statement("blue,");
statement("alpha");
end_scope_decl();
statement("");
statement("template<typename T> struct spvRemoveReference { typedef T type; };");
statement("template<typename T> struct spvRemoveReference<thread T&> { typedef T type; };");
statement("template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; };");
statement("template<typename T> inline constexpr thread T&& spvForward(thread typename "
"spvRemoveReference<T>::type& x)");
begin_scope();
statement("return static_cast<thread T&&>(x);");
end_scope();
statement("template<typename T> inline constexpr thread T&& spvForward(thread typename "
"spvRemoveReference<T>::type&& x)");
begin_scope();
statement("return static_cast<thread T&&>(x);");
end_scope();
statement("");
statement("template<typename T>");
statement("inline T spvGetSwizzle(vec<T, 4> x, spvSwizzle s)");
begin_scope();
statement("switch (s)");
begin_scope();
statement("case spvSwizzle::zero:");
statement(" return 0;");
statement("case spvSwizzle::one:");
statement(" return 1;");
statement("case spvSwizzle::red:");
statement(" return x.r;");
statement("case spvSwizzle::green:");
statement(" return x.g;");
statement("case spvSwizzle::blue:");
statement(" return x.b;");
statement("case spvSwizzle::alpha:");
statement(" return x.a;");
statement("default:");
statement(" break;");
end_scope();
statement("return 0;");
end_scope();
statement("");
statement("// Wrapper function that swizzles texture samples and fetches.");
statement("template<typename T>");
statement("inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s)");
begin_scope();
statement("if (!s)");
statement(" return x;");
statement("return vec<T, 4>(spvGetSwizzle(x, spvSwizzle((s >> 0) & 0xFF)), "
"spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), "
"spvGetSwizzle(x, spvSwizzle((s >> 24) & 0xFF)));");
end_scope();
statement("");
statement("template<typename T>");
statement("inline T spvTextureSwizzle(T x, uint s)");
begin_scope();
statement("return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x;");
end_scope();
statement("");
statement("// Wrapper function that swizzles texture gathers.");
statement("template<typename T, typename Tex, typename... Ts>");
statement("inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) "
"METAL_CONST_ARG(c)");
begin_scope();
statement("if (sw)");
begin_scope();
statement("switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF))");
begin_scope();
statement("case spvSwizzle::none:");
statement(" break;");
statement("case spvSwizzle::zero:");
statement(" return vec<T, 4>(0, 0, 0, 0);");
statement("case spvSwizzle::one:");
statement(" return vec<T, 4>(1, 1, 1, 1);");
statement("case spvSwizzle::red:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::x);");
statement("case spvSwizzle::green:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::y);");
statement("case spvSwizzle::blue:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::z);");
statement("case spvSwizzle::alpha:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::w);");
end_scope();
end_scope();
// texture::gather insists on its component parameter being a constant
// expression, so we need this silly workaround just to compile the shader.
statement("switch (c)");
begin_scope();
statement("case component::x:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::x);");
statement("case component::y:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::y);");
statement("case component::z:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::z);");
statement("case component::w:");
statement(" return t.gather(s, spvForward<Ts>(params)..., component::w);");
end_scope();
end_scope();
statement("");
default:
break;
}
@ -2680,11 +2846,41 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
}
// Returns the texture sampling function string for the specified image and sampling characteristics.
string CompilerMSL::to_function_name(uint32_t img, const SPIRType &, bool is_fetch, bool is_gather, bool, bool, bool,
bool, bool has_dref, uint32_t)
string CompilerMSL::to_function_name(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool, bool,
bool, bool, bool has_dref, uint32_t)
{
// Special-case gather. We have to alter the component being looked up
// in the swizzle case.
if (msl_options.swizzle_texture_samples && is_gather && !imgtype.image.depth)
{
string fname =
"spvGatherSwizzle<" + type_to_glsl(get<SPIRType>(imgtype.image.type)) + ", " + type_to_glsl(imgtype);
// Add the arg types ourselves. Yes, this sucks, but Clang can't
// deduce template pack parameters in the middle of an argument list.
switch (imgtype.image.dim)
{
case Dim2D:
fname += ", float2";
if (imgtype.image.arrayed)
fname += ", uint";
fname += ", int2";
break;
case DimCube:
fname += ", float3";
if (imgtype.image.arrayed)
fname += ", uint";
break;
default:
SPIRV_CROSS_THROW("Invalid texture dimension for gather op.");
}
fname += ">";
return fname;
}
// Texture reference
string fname = to_expression(img) + ".";
if (msl_options.swizzle_texture_samples && !is_gather && is_sampled_image_type(imgtype))
fname = "spvTextureSwizzle(" + fname;
// Texture function and sampler
if (is_fetch)
@ -2701,7 +2897,7 @@ string CompilerMSL::to_function_name(uint32_t img, const SPIRType &, bool is_fet
}
// Returns the function args for a texture sampling function for the specified image and sampling characteristics.
string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool, bool is_proj,
string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj,
uint32_t coord, uint32_t, uint32_t dref, uint32_t grad_x, uint32_t grad_y,
uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t comp,
uint32_t sample, bool *p_forward)
@ -2710,6 +2906,13 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
if (!is_fetch)
farg_str += to_sampler_expression(img);
if (msl_options.swizzle_texture_samples && is_gather && !imgtype.image.depth)
{
if (!farg_str.empty())
farg_str += ", ";
farg_str += to_expression(img);
}
// Texture coordinates
bool forward = should_forward(coord);
auto coord_expr = to_enclosed_expression(coord);
@ -2958,6 +3161,28 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
farg_str += to_expression(sample);
}
if (msl_options.swizzle_texture_samples && is_sampled_image_type(imgtype) &&
(!is_gather || !imgtype.image.depth))
{
// Add the swizzle constant from the swizzle buffer.
if (!is_gather)
farg_str += ")";
// Get the original input variable for this image.
uint32_t img_var = img;
if (meta[img].image)
img_var = meta[img].image;
if (auto *var = maybe_get_backing_variable(img_var))
{
if (var->parameter && !var->parameter->alias_global_variable)
SPIRV_CROSS_THROW("Cannot yet map non-aliased parameter to Metal resource!");
img_var = var->self;
}
auto &aux_type = expression_type(aux_buffer_id);
farg_str += ", " + to_name(aux_buffer_id) + "." + to_member_name(aux_type, k_aux_mbr_idx_swizzle_const) + "[" +
convert_to_string(get_metal_resource_index(get<SPIRVariable>(img_var), SPIRType::Image)) + "]";
used_aux_buffer = true;
}
*p_forward = forward;
return farg_str;
@ -3003,6 +3228,7 @@ void CompilerMSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_id
{
set<SPIRExpression>(result_id, to_expression(image_id), result_type, true);
meta[result_id].sampler = samp_id;
meta[result_id].image = image_id;
}
// Returns a string representation of the ID, usable as a function arg.
@ -4422,6 +4648,54 @@ bool CompilerMSL::skip_argument(uint32_t) const
return false;
}
void CompilerMSL::analyze_sampled_image_usage()
{
if (msl_options.swizzle_texture_samples)
{
SampledImageScanner scanner(*this);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), scanner);
}
}
bool CompilerMSL::SampledImageScanner::handle(spv::Op opcode, const uint32_t *args, uint32_t length)
{
switch (opcode)
{
case OpLoad:
case OpImage:
case OpSampledImage:
{
if (length < 3)
return false;
uint32_t result_type = args[0];
auto &type = compiler.get<SPIRType>(result_type);
if ((type.basetype != SPIRType::Image && type.basetype != SPIRType::SampledImage) || type.image.sampled != 1)
return true;
uint32_t id = args[1];
compiler.set<SPIRExpression>(id, "", result_type, true);
break;
}
case OpImageSampleExplicitLod:
case OpImageSampleProjExplicitLod:
case OpImageSampleDrefExplicitLod:
case OpImageSampleProjDrefExplicitLod:
case OpImageSampleImplicitLod:
case OpImageSampleProjImplicitLod:
case OpImageSampleDrefImplicitLod:
case OpImageSampleProjDrefImplicitLod:
case OpImageFetch:
case OpImageGather:
compiler.has_sampled_images = compiler.has_sampled_images ||
compiler.is_sampled_image_type(compiler.expression_type(args[2]));
break;
default:
break;
}
return true;
}
bool CompilerMSL::OpCodePreprocessor::handle(Op opcode, const uint32_t *args, uint32_t length)
{
// Since MSL exists in a single execution scope, function prototype declarations are not
@ -4569,9 +4843,25 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
if (tid && compiler.get<SPIRType>(tid).image.dim == DimBuffer)
return SPVFuncImplTexelBufferCoords;
if (opcode == OpImageFetch && compiler.msl_options.swizzle_texture_samples)
return SPVFuncImplTextureSwizzle;
break;
}
case OpImageSampleExplicitLod:
case OpImageSampleProjExplicitLod:
case OpImageSampleDrefExplicitLod:
case OpImageSampleProjDrefExplicitLod:
case OpImageSampleImplicitLod:
case OpImageSampleProjImplicitLod:
case OpImageSampleDrefImplicitLod:
case OpImageSampleProjDrefImplicitLod:
case OpImageGather:
if (compiler.msl_options.swizzle_texture_samples)
return SPVFuncImplTextureSwizzle;
break;
case OpCompositeConstruct:
{
auto &type = compiler.get<SPIRType>(args[0]);

View File

@ -152,9 +152,11 @@ 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 = 0;
bool enable_point_size_builtin = true;
bool disable_rasterization = false;
bool resolve_specialized_array_lengths = true;
bool swizzle_texture_samples = false;
bool is_ios()
{
@ -211,6 +213,13 @@ public:
return is_rasterization_disabled && (get_entry_point().model == spv::ExecutionModelVertex);
}
// Provide feedback to calling API to allow it to pass an auxiliary
// buffer if the shader needs it.
bool needs_aux_buffer() const
{
return used_aux_buffer;
}
// An enum of SPIR-V functions that are implemented in additional
// source code that is added to the shader if necessary.
enum SPVFuncImpl
@ -241,6 +250,7 @@ public:
SPVFuncImplRowMajor3x4,
SPVFuncImplRowMajor4x2,
SPVFuncImplRowMajor4x3,
SPVFuncImplTextureSwizzle,
SPVFuncImplArrayCopyMultidimMax = 6
};
@ -374,10 +384,13 @@ protected:
void emit_entry_point_declarations() override;
uint32_t builtin_frag_coord_id = 0;
uint32_t builtin_sample_id_id = 0;
uint32_t aux_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;
void analyze_sampled_image_usage();
Options msl_options;
std::set<SPVFuncImpl> spv_function_implementations;
std::unordered_map<uint32_t, MSLVertexAttr *> vtx_attrs_by_location;
@ -389,9 +402,11 @@ protected:
MSLResourceBinding next_metal_resource_index;
uint32_t stage_in_var_id = 0;
uint32_t stage_out_var_id = 0;
bool has_sampled_images = false;
bool needs_vertex_idx_arg = false;
bool needs_instance_idx_arg = false;
bool is_rasterization_disabled = false;
bool used_aux_buffer = false;
std::string qual_pos_var_name;
std::string stage_in_var_name = "in";
std::string stage_out_var_name = "out";
@ -419,6 +434,19 @@ protected:
bool uses_resource_write = false;
};
// OpcodeHandler that scans for uses of sampled images
struct SampledImageScanner : OpcodeHandler
{
SampledImageScanner(CompilerMSL &compiler_)
: compiler(compiler_)
{
}
bool handle(spv::Op opcode, const uint32_t *args, uint32_t) override;
CompilerMSL &compiler;
};
// Sorts the members of a SPIRType and associated Meta info based on a settable sorting
// aspect, which defines which aspect of the struct members will be used to sort them.
// Regardless of the sorting aspect, built-in members always appear at the end of the struct.

View File

@ -137,6 +137,8 @@ def cross_compile_msl(shader, spirv, opt):
msl_args = [spirv_cross_path, '--entry', 'main', '--output', msl_path, spirv_path, '--msl']
msl_args.append('--msl-version')
msl_args.append(path_to_msl_standard_cli(shader))
if '.swizzle.' in shader:
msl_args.append('--msl-swizzle-texture-samples')
subprocess.check_call(msl_args)