Merge pull request #848 from cdavis5e/capture-output-buffer
MSL: Add a setting to capture vertex shader output to a buffer.
This commit is contained in:
commit
d9ed3dcc7a
4
main.cpp
4
main.cpp
@ -490,6 +490,7 @@ struct CLIArguments
|
||||
bool yflip = false;
|
||||
bool sso = false;
|
||||
bool support_nonzero_baseinstance = true;
|
||||
bool msl_capture_output_to_buffer = false;
|
||||
bool msl_swizzle_texture_samples = false;
|
||||
bool msl_ios = false;
|
||||
bool msl_pad_fragment_output = false;
|
||||
@ -545,6 +546,7 @@ static void print_help()
|
||||
"\t[--cpp-interface-name <name>]\n"
|
||||
"\t[--msl]\n"
|
||||
"\t[--msl-version <MMmmpp>]\n"
|
||||
"\t[--msl-capture-output]\n"
|
||||
"\t[--msl-swizzle-texture-samples]\n"
|
||||
"\t[--msl-ios]\n"
|
||||
"\t[--msl-pad-fragment-output]\n"
|
||||
@ -714,6 +716,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-capture-output", [&args](CLIParser &) { args.msl_capture_output_to_buffer = true; });
|
||||
cbs.add("--msl-swizzle-texture-samples", [&args](CLIParser &) { args.msl_swizzle_texture_samples = true; });
|
||||
cbs.add("--msl-ios", [&args](CLIParser &) { args.msl_ios = true; });
|
||||
cbs.add("--msl-pad-fragment-output", [&args](CLIParser &) { args.msl_pad_fragment_output = true; });
|
||||
@ -843,6 +846,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.capture_output_to_buffer = args.msl_capture_output_to_buffer;
|
||||
msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
|
||||
if (args.msl_ios)
|
||||
msl_opts.platform = CompilerMSL::Options::iOS;
|
||||
|
@ -130,7 +130,7 @@ 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(0)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
|
||||
kernel void main0(constant spvAux& spvAuxBuffer [[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];
|
||||
bar.write(spvTextureSwizzle(foo.sample(fooSmplr, float2(1.0), level(0.0)), fooSwzl), uint2(int2(0)));
|
||||
|
29
reference/opt/shaders-msl/vert/basic.capture.vert
Normal file
29
reference/opt/shaders-msl/vert/basic.capture.vert
Normal file
@ -0,0 +1,29 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 uMVP;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float3 vNormal [[user(locn0)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 aVertex [[attribute(0)]];
|
||||
float3 aNormal [[attribute(1)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], constant UBO& _16 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]], device main0_out* spvOut [[buffer(28)]], device uint* spvIndirectParams [[buffer(29)]])
|
||||
{
|
||||
device main0_out& out = spvOut[(gl_InstanceIndex - gl_BaseInstance) * spvIndirectParams[0] + gl_VertexIndex - gl_BaseVertex];
|
||||
out.gl_Position = _16.uMVP * in.aVertex;
|
||||
out.vNormal = in.aNormal;
|
||||
}
|
||||
|
29
reference/opt/shaders-msl/vert/leaf-function.capture.vert
Normal file
29
reference/opt/shaders-msl/vert/leaf-function.capture.vert
Normal file
@ -0,0 +1,29 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 uMVP;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float3 vNormal [[user(locn0)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 aVertex [[attribute(0)]];
|
||||
float3 aNormal [[attribute(1)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], constant UBO& _18 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]], device main0_out* spvOut [[buffer(28)]], device uint* spvIndirectParams [[buffer(29)]])
|
||||
{
|
||||
device main0_out& out = spvOut[(gl_InstanceIndex - gl_BaseInstance) * spvIndirectParams[0] + gl_VertexIndex - gl_BaseVertex];
|
||||
out.gl_Position = _18.uMVP * in.aVertex;
|
||||
out.vNormal = in.aNormal;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ 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(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)]])
|
||||
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)]])
|
||||
{
|
||||
constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
|
||||
constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
|
||||
|
@ -136,7 +136,7 @@ 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(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)]])
|
||||
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)]])
|
||||
{
|
||||
constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
|
||||
constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
|
||||
|
@ -183,7 +183,7 @@ float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr,
|
||||
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)]])
|
||||
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)]])
|
||||
{
|
||||
constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
|
||||
constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
|
||||
|
@ -136,7 +136,7 @@ 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(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)]])
|
||||
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)]])
|
||||
{
|
||||
constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
|
||||
constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
|
||||
|
@ -136,7 +136,7 @@ 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(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)]])
|
||||
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)]])
|
||||
{
|
||||
constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
|
||||
constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
|
||||
|
@ -188,7 +188,7 @@ float4 do_samples(thread const texture1d<float> t1, thread const sampler t1Smplr
|
||||
return c;
|
||||
}
|
||||
|
||||
fragment main0_out 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 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 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)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
|
||||
|
@ -130,7 +130,7 @@ 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(0)]], texture2d<float> foo [[texture(0)]], texture2d<float, access::write> bar [[texture(1)]], sampler fooSmplr [[sampler(0)]])
|
||||
kernel void main0(constant spvAux& spvAuxBuffer [[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];
|
||||
float4 a = spvTextureSwizzle(foo.sample(fooSmplr, float2(1.0), level(0.0)), fooSwzl);
|
||||
|
29
reference/shaders-msl/vert/basic.capture.vert
Normal file
29
reference/shaders-msl/vert/basic.capture.vert
Normal file
@ -0,0 +1,29 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 uMVP;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float3 vNormal [[user(locn0)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 aVertex [[attribute(0)]];
|
||||
float3 aNormal [[attribute(1)]];
|
||||
};
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], constant UBO& _16 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]], device main0_out* spvOut [[buffer(28)]], device uint* spvIndirectParams [[buffer(29)]])
|
||||
{
|
||||
device main0_out& out = spvOut[(gl_InstanceIndex - gl_BaseInstance) * spvIndirectParams[0] + gl_VertexIndex - gl_BaseVertex];
|
||||
out.gl_Position = _16.uMVP * in.aVertex;
|
||||
out.vNormal = in.aNormal;
|
||||
}
|
||||
|
36
reference/shaders-msl/vert/leaf-function.capture.vert
Normal file
36
reference/shaders-msl/vert/leaf-function.capture.vert
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 uMVP;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float3 vNormal [[user(locn0)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 aVertex [[attribute(0)]];
|
||||
float3 aNormal [[attribute(1)]];
|
||||
};
|
||||
|
||||
void set_output(device float4& gl_Position, constant UBO& v_18, thread float4& aVertex, device float3& vNormal, thread float3& aNormal)
|
||||
{
|
||||
gl_Position = v_18.uMVP * aVertex;
|
||||
vNormal = aNormal;
|
||||
}
|
||||
|
||||
vertex void main0(main0_in in [[stage_in]], constant UBO& v_18 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]], device main0_out* spvOut [[buffer(28)]], device uint* spvIndirectParams [[buffer(29)]])
|
||||
{
|
||||
device main0_out& out = spvOut[(gl_InstanceIndex - gl_BaseInstance) * spvIndirectParams[0] + gl_VertexIndex - gl_BaseVertex];
|
||||
set_output(out.gl_Position, v_18, in.aVertex, out.vNormal, in.aNormal);
|
||||
}
|
||||
|
17
shaders-msl/vert/basic.capture.vert
Normal file
17
shaders-msl/vert/basic.capture.vert
Normal file
@ -0,0 +1,17 @@
|
||||
#version 310 es
|
||||
|
||||
layout(std140) uniform UBO
|
||||
{
|
||||
uniform mat4 uMVP;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 aVertex;
|
||||
layout(location = 1) in vec3 aNormal;
|
||||
|
||||
layout(location = 0) out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = uMVP * aVertex;
|
||||
vNormal = aNormal;
|
||||
}
|
22
shaders-msl/vert/leaf-function.capture.vert
Normal file
22
shaders-msl/vert/leaf-function.capture.vert
Normal file
@ -0,0 +1,22 @@
|
||||
#version 310 es
|
||||
|
||||
layout(std140) uniform UBO
|
||||
{
|
||||
uniform mat4 uMVP;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 aVertex;
|
||||
layout(location = 1) in vec3 aNormal;
|
||||
|
||||
layout(location = 0) out vec3 vNormal;
|
||||
|
||||
void set_output()
|
||||
{
|
||||
gl_Position = uMVP * aVertex;
|
||||
vNormal = aNormal;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
set_output();
|
||||
}
|
197
spirv_msl.cpp
197
spirv_msl.cpp
@ -90,25 +90,55 @@ void CompilerMSL::set_fragment_output_components(uint32_t location, uint32_t com
|
||||
void CompilerMSL::build_implicit_builtins()
|
||||
{
|
||||
bool need_sample_pos = active_input_builtins.get(BuiltInSamplePosition);
|
||||
if (need_subpass_input || need_sample_pos)
|
||||
if (need_subpass_input || need_sample_pos || capture_output_to_buffer)
|
||||
{
|
||||
bool has_frag_coord = false;
|
||||
bool has_sample_id = false;
|
||||
bool has_vertex_idx = false;
|
||||
bool has_base_vertex = false;
|
||||
bool has_instance_idx = false;
|
||||
bool has_base_instance = false;
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
if (need_subpass_input && var.storage == StorageClassInput && ir.meta[var.self].decoration.builtin &&
|
||||
ir.meta[var.self].decoration.builtin_type == BuiltInFragCoord)
|
||||
if (var.storage != StorageClassInput || !ir.meta[var.self].decoration.builtin)
|
||||
return;
|
||||
|
||||
if (need_subpass_input && ir.meta[var.self].decoration.builtin_type == BuiltInFragCoord)
|
||||
{
|
||||
builtin_frag_coord_id = var.self;
|
||||
has_frag_coord = true;
|
||||
}
|
||||
|
||||
if (need_sample_pos && var.storage == StorageClassInput && ir.meta[var.self].decoration.builtin &&
|
||||
ir.meta[var.self].decoration.builtin_type == BuiltInSampleId)
|
||||
if (need_sample_pos && ir.meta[var.self].decoration.builtin_type == BuiltInSampleId)
|
||||
{
|
||||
builtin_sample_id_id = var.self;
|
||||
has_sample_id = true;
|
||||
}
|
||||
|
||||
if (capture_output_to_buffer)
|
||||
{
|
||||
switch (ir.meta[var.self].decoration.builtin_type)
|
||||
{
|
||||
case BuiltInVertexIndex:
|
||||
builtin_vertex_idx_id = var.self;
|
||||
has_vertex_idx = true;
|
||||
break;
|
||||
case BuiltInBaseVertex:
|
||||
builtin_base_vertex_id = var.self;
|
||||
has_base_vertex = true;
|
||||
break;
|
||||
case BuiltInInstanceIndex:
|
||||
builtin_instance_idx_id = var.self;
|
||||
has_instance_idx = true;
|
||||
break;
|
||||
case BuiltInBaseInstance:
|
||||
builtin_base_instance_id = var.self;
|
||||
has_base_instance = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!has_frag_coord && need_subpass_input)
|
||||
@ -163,9 +193,67 @@ void CompilerMSL::build_implicit_builtins()
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInSampleId);
|
||||
builtin_sample_id_id = var_id;
|
||||
}
|
||||
|
||||
if (capture_output_to_buffer &&
|
||||
(!has_vertex_idx || !has_base_vertex || !has_instance_idx || !has_base_instance))
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(2);
|
||||
uint32_t type_id = offset;
|
||||
uint32_t type_ptr_id = offset + 1;
|
||||
|
||||
SPIRType uint_type;
|
||||
uint_type.basetype = SPIRType::UInt;
|
||||
uint_type.width = 32;
|
||||
set<SPIRType>(type_id, uint_type);
|
||||
|
||||
SPIRType uint_type_ptr;
|
||||
uint_type_ptr = uint_type;
|
||||
uint_type_ptr.pointer = true;
|
||||
uint_type_ptr.parent_type = type_id;
|
||||
uint_type_ptr.storage = StorageClassInput;
|
||||
auto &ptr_type = set<SPIRType>(type_ptr_id, uint_type_ptr);
|
||||
ptr_type.self = type_id;
|
||||
|
||||
if (!has_vertex_idx)
|
||||
{
|
||||
uint32_t var_id = ir.increase_bound_by(1);
|
||||
|
||||
// Create gl_VertexIndex.
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInVertexIndex);
|
||||
builtin_vertex_idx_id = var_id;
|
||||
}
|
||||
if (!has_base_vertex)
|
||||
{
|
||||
uint32_t var_id = ir.increase_bound_by(1);
|
||||
|
||||
// Create gl_BaseVertex.
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInBaseVertex);
|
||||
builtin_base_vertex_id = var_id;
|
||||
}
|
||||
if (!has_instance_idx)
|
||||
{
|
||||
uint32_t var_id = ir.increase_bound_by(1);
|
||||
|
||||
// Create gl_InstanceIndex.
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInInstanceIndex);
|
||||
builtin_instance_idx_id = var_id;
|
||||
}
|
||||
if (!has_base_instance)
|
||||
{
|
||||
uint32_t var_id = ir.increase_bound_by(1);
|
||||
|
||||
// Create gl_BaseInstance.
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInBaseInstance);
|
||||
builtin_base_instance_id = var_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msl_options.swizzle_texture_samples && has_sampled_images)
|
||||
if (needs_aux_buffer_def)
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(5);
|
||||
uint32_t type_id = offset;
|
||||
@ -174,7 +262,7 @@ void CompilerMSL::build_implicit_builtins()
|
||||
uint32_t struct_ptr_id = offset + 3;
|
||||
uint32_t var_id = offset + 4;
|
||||
|
||||
// Create a buffer to hold the swizzle constants.
|
||||
// Create a buffer to hold extra data, including the swizzle constants.
|
||||
SPIRType uint_type;
|
||||
uint_type.basetype = SPIRType::UInt;
|
||||
uint_type.width = 32;
|
||||
@ -194,8 +282,8 @@ void CompilerMSL::build_implicit_builtins()
|
||||
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);
|
||||
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 struct_type_ptr = struct_type;
|
||||
struct_type_ptr.pointer = true;
|
||||
@ -232,6 +320,12 @@ static string create_sampler_address(const char *prefix, MSLSamplerAddress addr)
|
||||
}
|
||||
}
|
||||
|
||||
SPIRType &CompilerMSL::get_stage_out_struct_type()
|
||||
{
|
||||
auto &so_var = get<SPIRVariable>(stage_out_var_id);
|
||||
return get_variable_data_type(so_var);
|
||||
}
|
||||
|
||||
void CompilerMSL::emit_entry_point_declarations()
|
||||
{
|
||||
// FIXME: Get test coverage here ...
|
||||
@ -409,7 +503,8 @@ string CompilerMSL::compile()
|
||||
backend.allow_truncated_access_chain = true;
|
||||
backend.array_is_value_type = false;
|
||||
|
||||
is_rasterization_disabled = msl_options.disable_rasterization;
|
||||
capture_output_to_buffer = msl_options.capture_output_to_buffer;
|
||||
is_rasterization_disabled = msl_options.disable_rasterization || capture_output_to_buffer;
|
||||
|
||||
replace_illegal_names();
|
||||
|
||||
@ -1392,14 +1487,35 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
|
||||
bool ep_should_return_output = !get_is_rasterization_disabled();
|
||||
uint32_t rtn_id = ep_should_return_output ? ib_var_id : 0;
|
||||
auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
|
||||
entry_func.add_local_variable(ib_var_id);
|
||||
for (auto &blk_id : entry_func.blocks)
|
||||
if (!capture_output_to_buffer)
|
||||
{
|
||||
auto &blk = get<SPIRBlock>(blk_id);
|
||||
if (blk.terminator == SPIRBlock::Return)
|
||||
blk.return_value = rtn_id;
|
||||
entry_func.add_local_variable(ib_var_id);
|
||||
for (auto &blk_id : entry_func.blocks)
|
||||
{
|
||||
auto &blk = get<SPIRBlock>(blk_id);
|
||||
if (blk.terminator == SPIRBlock::Return)
|
||||
blk.return_value = rtn_id;
|
||||
}
|
||||
vars_needing_early_declaration.push_back(ib_var_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Instead of declaring a struct variable to hold the output and then
|
||||
// copying that to the output buffer, we'll declare the output variable
|
||||
// as a reference to the final output element in the buffer. Then we can
|
||||
// avoid the extra copy.
|
||||
entry_func.fixup_hooks_in.push_back([=]() {
|
||||
if (stage_out_var_id)
|
||||
{
|
||||
// The first member of the indirect buffer is always the number of vertices
|
||||
// to draw.
|
||||
statement("device ", to_name(ir.default_entry_point), "_", ib_var_ref, "& ", ib_var_ref, " = ",
|
||||
output_buffer_var_name, "[(", to_expression(builtin_instance_idx_id), " - ",
|
||||
to_expression(builtin_base_instance_id), ") * spvIndirectParams[0] + ",
|
||||
to_expression(builtin_vertex_idx_id), " - ", to_expression(builtin_base_vertex_id), "];");
|
||||
}
|
||||
});
|
||||
}
|
||||
vars_needing_early_declaration.push_back(ib_var_id);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4069,9 +4185,9 @@ void CompilerMSL::emit_fixup()
|
||||
}
|
||||
}
|
||||
|
||||
// Emit a structure member, padding and packing to maintain the correct memeber alignments.
|
||||
void CompilerMSL::emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
|
||||
const string &qualifier, uint32_t)
|
||||
// Return a string defining a structure member, with padding and packing.
|
||||
string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
|
||||
const string &qualifier)
|
||||
{
|
||||
auto &membertype = get<SPIRType>(member_type_id);
|
||||
|
||||
@ -4116,8 +4232,15 @@ void CompilerMSL::emit_struct_member(const SPIRType &type, uint32_t member_type_
|
||||
pack_pfx = "packed_";
|
||||
}
|
||||
|
||||
statement(pack_pfx, type_to_glsl(*effective_membertype), " ", qualifier, to_member_name(type, index),
|
||||
member_attribute_qualifier(type, index), type_to_array_glsl(*effective_membertype), ";");
|
||||
return join(pack_pfx, type_to_glsl(*effective_membertype), " ", qualifier, to_member_name(type, index),
|
||||
member_attribute_qualifier(type, index), type_to_array_glsl(membertype), ";");
|
||||
}
|
||||
|
||||
// Emit a structure member, padding and packing to maintain the correct memeber alignments.
|
||||
void CompilerMSL::emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
|
||||
const string &qualifier, uint32_t)
|
||||
{
|
||||
statement(to_struct_member(type, member_type_id, index, qualifier));
|
||||
}
|
||||
|
||||
// Return a MSL qualifier for the specified function attribute member
|
||||
@ -4354,11 +4477,7 @@ string CompilerMSL::func_type_decl(SPIRType &type)
|
||||
// If an outgoing interface block has been defined, and it should be returned, override the entry point return type
|
||||
bool ep_should_return_output = !get_is_rasterization_disabled();
|
||||
if (stage_out_var_id && ep_should_return_output)
|
||||
{
|
||||
auto &so_var = get<SPIRVariable>(stage_out_var_id);
|
||||
auto &so_type = get_variable_data_type(so_var);
|
||||
return_type = type_to_glsl(so_type) + type_to_array_glsl(type);
|
||||
}
|
||||
return_type = type_to_glsl(get_stage_out_struct_type()) + type_to_array_glsl(type);
|
||||
|
||||
// Prepend a entry type, based on the execution model
|
||||
string entry_type;
|
||||
@ -4421,6 +4540,11 @@ string CompilerMSL::get_argument_address_space(const SPIRVariable &argument)
|
||||
// No address space for plain values.
|
||||
return type.pointer ? "thread" : "";
|
||||
|
||||
case StorageClassOutput:
|
||||
if (capture_output_to_buffer)
|
||||
return "device";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -4458,6 +4582,11 @@ string CompilerMSL::get_type_address_space(const SPIRType &type)
|
||||
// No address space for plain values.
|
||||
return type.pointer ? "thread" : "";
|
||||
|
||||
case StorageClassOutput:
|
||||
if (capture_output_to_buffer)
|
||||
return "device";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -4623,6 +4752,21 @@ string CompilerMSL::entry_point_args(bool append_comma)
|
||||
if (needs_instance_idx_arg)
|
||||
ep_args += built_in_func_arg(BuiltInInstanceIndex, !ep_args.empty());
|
||||
|
||||
if (capture_output_to_buffer)
|
||||
{
|
||||
// Add parameters to hold the indirect draw parameters and the shader output. This has to be handled
|
||||
// specially because it needs to be a pointer, not a reference.
|
||||
if (stage_out_var_id)
|
||||
{
|
||||
if (!ep_args.empty())
|
||||
ep_args += ", ";
|
||||
ep_args += join("device ", type_to_glsl(get_stage_out_struct_type()), "* ", output_buffer_var_name,
|
||||
" [[buffer(", msl_options.shader_output_buffer_index, ")]], ");
|
||||
ep_args +=
|
||||
join("device uint* spvIndirectParams [[buffer(", msl_options.indirect_params_buffer_index, ")]]");
|
||||
}
|
||||
}
|
||||
|
||||
if (!ep_args.empty() && append_comma)
|
||||
ep_args += ", ";
|
||||
|
||||
@ -5837,6 +5981,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;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -147,6 +147,10 @@ static const uint32_t kPushConstDescSet = ~(0u);
|
||||
// element to indicate the bindings for the push constants.
|
||||
static const uint32_t kPushConstBinding = 0;
|
||||
|
||||
// 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
|
||||
|
||||
// Decompiles SPIR-V to Metal Shading Language
|
||||
class CompilerMSL : public CompilerGLSL
|
||||
{
|
||||
@ -163,9 +167,12 @@ 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;
|
||||
uint32_t aux_buffer_index = 30;
|
||||
uint32_t indirect_params_buffer_index = 29;
|
||||
uint32_t shader_output_buffer_index = 28;
|
||||
bool enable_point_size_builtin = true;
|
||||
bool disable_rasterization = false;
|
||||
bool capture_output_to_buffer = false;
|
||||
bool swizzle_texture_samples = false;
|
||||
|
||||
// Fragment output in MSL must have at least as many components as the render pass.
|
||||
@ -234,6 +241,13 @@ public:
|
||||
return used_aux_buffer;
|
||||
}
|
||||
|
||||
// Provide feedback to calling API to allow it to pass an output
|
||||
// buffer if the shader needs it.
|
||||
bool needs_output_buffer() const
|
||||
{
|
||||
return capture_output_to_buffer && stage_out_var_id != 0;
|
||||
}
|
||||
|
||||
// An enum of SPIR-V functions that are implemented in additional
|
||||
// source code that is added to the shader if necessary.
|
||||
enum SPVFuncImpl
|
||||
@ -329,6 +343,8 @@ protected:
|
||||
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
|
||||
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
|
||||
void emit_fixup() override;
|
||||
std::string to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
|
||||
const std::string &qualifier = "");
|
||||
void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
|
||||
const std::string &qualifier = "", uint32_t base_offset = 0) override;
|
||||
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
|
||||
@ -415,6 +431,7 @@ protected:
|
||||
MSLStructMemberKey get_struct_member_key(uint32_t type_id, uint32_t index);
|
||||
std::string get_argument_address_space(const SPIRVariable &argument);
|
||||
std::string get_type_address_space(const SPIRType &type);
|
||||
SPIRType &get_stage_out_struct_type();
|
||||
void emit_atomic_func_op(uint32_t result_type, uint32_t result_id, const char *op, uint32_t mem_order_1,
|
||||
uint32_t mem_order_2, bool has_mem_order_2, uint32_t op0, uint32_t op1 = 0,
|
||||
bool op1_is_pointer = false, bool op1_is_literal = false, uint32_t op2 = 0);
|
||||
@ -427,6 +444,10 @@ protected:
|
||||
void emit_entry_point_declarations() override;
|
||||
uint32_t builtin_frag_coord_id = 0;
|
||||
uint32_t builtin_sample_id_id = 0;
|
||||
uint32_t builtin_vertex_idx_id = 0;
|
||||
uint32_t builtin_base_vertex_id = 0;
|
||||
uint32_t builtin_instance_idx_id = 0;
|
||||
uint32_t builtin_base_instance_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;
|
||||
@ -451,12 +472,15 @@ protected:
|
||||
bool needs_vertex_idx_arg = false;
|
||||
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;
|
||||
std::string qual_pos_var_name;
|
||||
std::string stage_in_var_name = "in";
|
||||
std::string stage_out_var_name = "out";
|
||||
std::string sampler_name_suffix = "Smplr";
|
||||
std::string swizzle_name_suffix = "Swzl";
|
||||
std::string output_buffer_var_name = "spvOut";
|
||||
spv::Op previous_instruction_opcode = spv::OpNop;
|
||||
|
||||
std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers;
|
||||
|
@ -154,6 +154,8 @@ def cross_compile_msl(shader, spirv, opt):
|
||||
msl_args.append('--msl-ios')
|
||||
if '.pad-fragment.' in shader:
|
||||
msl_args.append('--msl-pad-fragment-output')
|
||||
if '.capture.' in shader:
|
||||
msl_args.append('--msl-capture-output')
|
||||
|
||||
subprocess.check_call(msl_args)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user