diff --git a/reference/opt/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert b/reference/opt/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert new file mode 100644 index 000000000..27eb53f25 --- /dev/null +++ b/reference/opt/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert @@ -0,0 +1,47 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float3 vNormal; + float4 gl_Position; +}; + +struct main0_in +{ + float4 aVertex [[attribute(0)]]; + float3 aNormal [[attribute(1)]]; +}; + +struct spvVertexData0 +{ + packed_half4 aVertex; + packed_short4 aNormal; +}; +static_assert(alignof(spvVertexData0) == 2, "Unexpected alignment"); +static_assert(sizeof(spvVertexData0) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData0& data0) +{ + main0_in out; + out.aVertex = float4(half4(data0.aVertex)); + out.aNormal = max(float4(short4(data0.aNormal)) * (1.f / 32767), -1.f).rgb; + return out; +} + +kernel void main0(device const spvVertexData0* spvVertexBuffer0 [[buffer(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 spvStageInputSize [[grid_size]], uint3 spvDispatchBase [[grid_origin]], device main0_out* spvOut [[buffer(28)]], const device ushort* spvIndices [[buffer(21)]]) +{ + device main0_out& out = spvOut[gl_GlobalInvocationID.y * spvStageInputSize.x + gl_GlobalInvocationID.x]; + if (any(gl_GlobalInvocationID >= spvStageInputSize)) + return; + uint gl_VertexIndex = spvIndices[gl_GlobalInvocationID.x] + spvDispatchBase.x; + uint gl_BaseVertex = spvDispatchBase.x; + uint gl_InstanceIndex = gl_GlobalInvocationID.y + spvDispatchBase.y; + uint gl_BaseInstance = spvDispatchBase.y; + main0_in in = spvLoadVertex(spvVertexBuffer0[gl_VertexIndex]); + out.gl_Position = in.aVertex; + out.vNormal = in.aNormal; +} + diff --git a/reference/opt/shaders-msl/vert/basic.vertex-loader.vert b/reference/opt/shaders-msl/vert/basic.vertex-loader.vert new file mode 100644 index 000000000..a51c6c2e1 --- /dev/null +++ b/reference/opt/shaders-msl/vert/basic.vertex-loader.vert @@ -0,0 +1,42 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float3 vNormal [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 aVertex [[attribute(0)]]; + float3 aNormal [[attribute(1)]]; +}; + +struct spvVertexData0 +{ + packed_half4 aVertex; + packed_short4 aNormal; +}; +static_assert(alignof(spvVertexData0) == 2, "Unexpected alignment"); +static_assert(sizeof(spvVertexData0) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData0& data0) +{ + main0_in out; + out.aVertex = float4(half4(data0.aVertex)); + out.aNormal = max(float4(short4(data0.aNormal)) * (1.f / 32767), -1.f).rgb; + return out; +} + +vertex main0_out main0(device const spvVertexData0* spvVertexBuffer0 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer0[gl_VertexIndex]); + out.gl_Position = in.aVertex; + out.vNormal = in.aNormal; + return out; +} + diff --git a/reference/opt/shaders-msl/vert/pack-align.vertex-loader.msl23.vert b/reference/opt/shaders-msl/vert/pack-align.vertex-loader.msl23.vert new file mode 100644 index 000000000..1220c0521 --- /dev/null +++ b/reference/opt/shaders-msl/vert/pack-align.vertex-loader.msl23.vert @@ -0,0 +1,48 @@ +#include +#include + +using namespace metal; + +struct UBO +{ + float4x4 uMVP; +}; + +struct main0_out +{ + float3 vNormal [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 aVertex [[attribute(2)]]; + float3 aNormal [[attribute(3)]]; +}; + +struct alignas(4) spvVertexData1 +{ + rgba8unorm aVertex; + uchar spvPad4; + packed_uchar3 aNormal; +}; +static_assert(alignof(spvVertexData1) == 4, "Unexpected alignment"); +static_assert(sizeof(spvVertexData1) == 8, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData1& data1) +{ + main0_in out; + out.aVertex = unpack_unorm4x8_to_float(reinterpret_cast(data1.aVertex)); + out.aNormal = float3(data1.aNormal).bgr; + return out; +} + +vertex main0_out main0(device const spvVertexData1* spvVertexBuffer1 [[buffer(1)]], 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]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer1[gl_InstanceIndex]); + out.gl_Position = _16.uMVP * in.aVertex; + out.vNormal = in.aNormal; + return out; +} + diff --git a/reference/opt/shaders-msl/vert/packed-formats.vertex-loader.vert b/reference/opt/shaders-msl/vert/packed-formats.vertex-loader.vert new file mode 100644 index 000000000..d664801f0 --- /dev/null +++ b/reference/opt/shaders-msl/vert/packed-formats.vertex-loader.vert @@ -0,0 +1,64 @@ +#include +#include + +using namespace metal; + +static half3 spvLoadVertexRG11B10Half(uint value) +{ + ushort3 res = ushort3(value << 5, (value >> 6) & 0xffc0, (value >> 16) & 0xff80); + return as_type(res); +} +static float3 spvLoadVertexRGB9E5Float(uint value) +{ + float exponent = exp2(float(value >> 27)) * exp2(float(-(15 + 9))); + int3 mantissa = int3(value & 0x1ff, extract_bits(value, 9, 9), extract_bits(value, 18, 9)); + return float3(mantissa) * exp2(float(exponent)); +} +struct UBO +{ + float4x4 uMVP; +}; + +struct main0_out +{ + float3 vNormal [[user(locn0)]]; + float3 vExtra [[user(locn1)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 aVertex [[attribute(4)]]; + float3 aNormal [[attribute(5)]]; + float3 aExtra [[attribute(6)]]; +}; + +struct spvVertexData2 +{ + uint aVertex; + uint aNormal; + uint aExtra; + uint spvPad12; +}; +static_assert(alignof(spvVertexData2) == 4, "Unexpected alignment"); +static_assert(sizeof(spvVertexData2) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData2& data2) +{ + main0_in out; + out.aVertex = unpack_unorm10a2_to_float(data2.aVertex); + out.aNormal = spvLoadVertexRGB9E5Float(data2.aNormal); + out.aExtra = float3(spvLoadVertexRG11B10Half(data2.aExtra)); + return out; +} + +vertex main0_out main0(device const spvVertexData2* spvVertexBuffer2 [[buffer(2)]], 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]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer2[gl_BaseInstance]); + out.gl_Position = _16.uMVP * in.aVertex; + out.vNormal = in.aNormal; + out.vExtra = in.aExtra; + return out; +} + diff --git a/reference/opt/shaders-msl/vert/past-stride.vertex-loader.vert b/reference/opt/shaders-msl/vert/past-stride.vertex-loader.vert new file mode 100644 index 000000000..4addcfb6b --- /dev/null +++ b/reference/opt/shaders-msl/vert/past-stride.vertex-loader.vert @@ -0,0 +1,39 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + uint aUInt [[attribute(7)]]; + float aUNorm [[attribute(8)]]; +}; + +struct alignas(4) spvVertexData3 +{ + uchar data[16]; +}; +static_assert(alignof(spvVertexData3) == 4, "Unexpected alignment"); +static_assert(sizeof(spvVertexData3) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData3& data3) +{ + main0_in out; + out.aUInt = reinterpret_cast(data3.data[32]); + out.aUNorm = float(data3.data[1]) * (1.f / 255); + return out; +} + +vertex main0_out main0(device const spvVertexData3* spvVertexBuffer3 [[buffer(3)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer3[gl_BaseInstance + (gl_InstanceIndex - gl_BaseInstance) / 4]); + out.gl_Position = float4(float(in.aUInt) * 0.015625, in.aUNorm, 0.0, 1.0); + return out; +} + diff --git a/reference/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert b/reference/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert new file mode 100644 index 000000000..27eb53f25 --- /dev/null +++ b/reference/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert @@ -0,0 +1,47 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float3 vNormal; + float4 gl_Position; +}; + +struct main0_in +{ + float4 aVertex [[attribute(0)]]; + float3 aNormal [[attribute(1)]]; +}; + +struct spvVertexData0 +{ + packed_half4 aVertex; + packed_short4 aNormal; +}; +static_assert(alignof(spvVertexData0) == 2, "Unexpected alignment"); +static_assert(sizeof(spvVertexData0) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData0& data0) +{ + main0_in out; + out.aVertex = float4(half4(data0.aVertex)); + out.aNormal = max(float4(short4(data0.aNormal)) * (1.f / 32767), -1.f).rgb; + return out; +} + +kernel void main0(device const spvVertexData0* spvVertexBuffer0 [[buffer(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 spvStageInputSize [[grid_size]], uint3 spvDispatchBase [[grid_origin]], device main0_out* spvOut [[buffer(28)]], const device ushort* spvIndices [[buffer(21)]]) +{ + device main0_out& out = spvOut[gl_GlobalInvocationID.y * spvStageInputSize.x + gl_GlobalInvocationID.x]; + if (any(gl_GlobalInvocationID >= spvStageInputSize)) + return; + uint gl_VertexIndex = spvIndices[gl_GlobalInvocationID.x] + spvDispatchBase.x; + uint gl_BaseVertex = spvDispatchBase.x; + uint gl_InstanceIndex = gl_GlobalInvocationID.y + spvDispatchBase.y; + uint gl_BaseInstance = spvDispatchBase.y; + main0_in in = spvLoadVertex(spvVertexBuffer0[gl_VertexIndex]); + out.gl_Position = in.aVertex; + out.vNormal = in.aNormal; +} + diff --git a/reference/shaders-msl/vert/basic.vertex-loader.vert b/reference/shaders-msl/vert/basic.vertex-loader.vert new file mode 100644 index 000000000..a51c6c2e1 --- /dev/null +++ b/reference/shaders-msl/vert/basic.vertex-loader.vert @@ -0,0 +1,42 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float3 vNormal [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 aVertex [[attribute(0)]]; + float3 aNormal [[attribute(1)]]; +}; + +struct spvVertexData0 +{ + packed_half4 aVertex; + packed_short4 aNormal; +}; +static_assert(alignof(spvVertexData0) == 2, "Unexpected alignment"); +static_assert(sizeof(spvVertexData0) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData0& data0) +{ + main0_in out; + out.aVertex = float4(half4(data0.aVertex)); + out.aNormal = max(float4(short4(data0.aNormal)) * (1.f / 32767), -1.f).rgb; + return out; +} + +vertex main0_out main0(device const spvVertexData0* spvVertexBuffer0 [[buffer(0)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer0[gl_VertexIndex]); + out.gl_Position = in.aVertex; + out.vNormal = in.aNormal; + return out; +} + diff --git a/reference/shaders-msl/vert/pack-align.vertex-loader.msl23.vert b/reference/shaders-msl/vert/pack-align.vertex-loader.msl23.vert new file mode 100644 index 000000000..1220c0521 --- /dev/null +++ b/reference/shaders-msl/vert/pack-align.vertex-loader.msl23.vert @@ -0,0 +1,48 @@ +#include +#include + +using namespace metal; + +struct UBO +{ + float4x4 uMVP; +}; + +struct main0_out +{ + float3 vNormal [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 aVertex [[attribute(2)]]; + float3 aNormal [[attribute(3)]]; +}; + +struct alignas(4) spvVertexData1 +{ + rgba8unorm aVertex; + uchar spvPad4; + packed_uchar3 aNormal; +}; +static_assert(alignof(spvVertexData1) == 4, "Unexpected alignment"); +static_assert(sizeof(spvVertexData1) == 8, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData1& data1) +{ + main0_in out; + out.aVertex = unpack_unorm4x8_to_float(reinterpret_cast(data1.aVertex)); + out.aNormal = float3(data1.aNormal).bgr; + return out; +} + +vertex main0_out main0(device const spvVertexData1* spvVertexBuffer1 [[buffer(1)]], 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]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer1[gl_InstanceIndex]); + out.gl_Position = _16.uMVP * in.aVertex; + out.vNormal = in.aNormal; + return out; +} + diff --git a/reference/shaders-msl/vert/packed-formats.vertex-loader.vert b/reference/shaders-msl/vert/packed-formats.vertex-loader.vert new file mode 100644 index 000000000..d664801f0 --- /dev/null +++ b/reference/shaders-msl/vert/packed-formats.vertex-loader.vert @@ -0,0 +1,64 @@ +#include +#include + +using namespace metal; + +static half3 spvLoadVertexRG11B10Half(uint value) +{ + ushort3 res = ushort3(value << 5, (value >> 6) & 0xffc0, (value >> 16) & 0xff80); + return as_type(res); +} +static float3 spvLoadVertexRGB9E5Float(uint value) +{ + float exponent = exp2(float(value >> 27)) * exp2(float(-(15 + 9))); + int3 mantissa = int3(value & 0x1ff, extract_bits(value, 9, 9), extract_bits(value, 18, 9)); + return float3(mantissa) * exp2(float(exponent)); +} +struct UBO +{ + float4x4 uMVP; +}; + +struct main0_out +{ + float3 vNormal [[user(locn0)]]; + float3 vExtra [[user(locn1)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 aVertex [[attribute(4)]]; + float3 aNormal [[attribute(5)]]; + float3 aExtra [[attribute(6)]]; +}; + +struct spvVertexData2 +{ + uint aVertex; + uint aNormal; + uint aExtra; + uint spvPad12; +}; +static_assert(alignof(spvVertexData2) == 4, "Unexpected alignment"); +static_assert(sizeof(spvVertexData2) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData2& data2) +{ + main0_in out; + out.aVertex = unpack_unorm10a2_to_float(data2.aVertex); + out.aNormal = spvLoadVertexRGB9E5Float(data2.aNormal); + out.aExtra = float3(spvLoadVertexRG11B10Half(data2.aExtra)); + return out; +} + +vertex main0_out main0(device const spvVertexData2* spvVertexBuffer2 [[buffer(2)]], 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]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer2[gl_BaseInstance]); + out.gl_Position = _16.uMVP * in.aVertex; + out.vNormal = in.aNormal; + out.vExtra = in.aExtra; + return out; +} + diff --git a/reference/shaders-msl/vert/past-stride.vertex-loader.vert b/reference/shaders-msl/vert/past-stride.vertex-loader.vert new file mode 100644 index 000000000..5af1d4126 --- /dev/null +++ b/reference/shaders-msl/vert/past-stride.vertex-loader.vert @@ -0,0 +1,39 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + uint aUInt [[attribute(7)]]; + float aUNorm [[attribute(8)]]; +}; + +struct alignas(4) spvVertexData3 +{ + uchar data[16]; +}; +static_assert(alignof(spvVertexData3) == 4, "Unexpected alignment"); +static_assert(sizeof(spvVertexData3) == 16, "Unexpected size"); + +main0_in spvLoadVertex(const device spvVertexData3& data3) +{ + main0_in out; + out.aUInt = reinterpret_cast(data3.data[32]); + out.aUNorm = float(data3.data[1]) * (1.f / 255); + return out; +} + +vertex main0_out main0(device const spvVertexData3* spvVertexBuffer3 [[buffer(3)]], uint gl_VertexIndex [[vertex_id]], uint gl_BaseVertex [[base_vertex]], uint gl_InstanceIndex [[instance_id]], uint gl_BaseInstance [[base_instance]]) +{ + main0_out out = {}; + main0_in in = spvLoadVertex(spvVertexBuffer3[gl_BaseInstance + (gl_InstanceIndex - gl_BaseInstance) / 4]); + out.gl_Position = float4(float(in.aUInt) / 64.0, in.aUNorm, 0.0, 1.0); + return out; +} + diff --git a/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert b/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert new file mode 100644 index 000000000..af7b62382 --- /dev/null +++ b/shaders-msl/vert/basic.vertex-loader.for-tess.index-u16.vert @@ -0,0 +1,12 @@ +#version 310 es + +layout(location = 0) in vec4 aVertex; +layout(location = 1) in vec3 aNormal; + +layout(location = 0) out vec3 vNormal; + +void main() +{ + gl_Position = aVertex; + vNormal = aNormal; +} diff --git a/shaders-msl/vert/basic.vertex-loader.vert b/shaders-msl/vert/basic.vertex-loader.vert new file mode 100644 index 000000000..af7b62382 --- /dev/null +++ b/shaders-msl/vert/basic.vertex-loader.vert @@ -0,0 +1,12 @@ +#version 310 es + +layout(location = 0) in vec4 aVertex; +layout(location = 1) in vec3 aNormal; + +layout(location = 0) out vec3 vNormal; + +void main() +{ + gl_Position = aVertex; + vNormal = aNormal; +} diff --git a/shaders-msl/vert/pack-align.vertex-loader.msl23.vert b/shaders-msl/vert/pack-align.vertex-loader.msl23.vert new file mode 100644 index 000000000..d18cbbf91 --- /dev/null +++ b/shaders-msl/vert/pack-align.vertex-loader.msl23.vert @@ -0,0 +1,17 @@ +#version 310 es + +layout(std140) uniform UBO +{ + uniform mat4 uMVP; +}; + +layout(location = 2) in vec4 aVertex; +layout(location = 3) in vec3 aNormal; + +layout(location = 0) out vec3 vNormal; + +void main() +{ + gl_Position = uMVP * aVertex; + vNormal = aNormal; +} diff --git a/shaders-msl/vert/packed-formats.vertex-loader.vert b/shaders-msl/vert/packed-formats.vertex-loader.vert new file mode 100644 index 000000000..ea89f2062 --- /dev/null +++ b/shaders-msl/vert/packed-formats.vertex-loader.vert @@ -0,0 +1,20 @@ +#version 310 es + +layout(std140) uniform UBO +{ + uniform mat4 uMVP; +}; + +layout(location = 4) in vec4 aVertex; +layout(location = 5) in vec3 aNormal; +layout(location = 6) in vec3 aExtra; + +layout(location = 0) out vec3 vNormal; +layout(location = 1) out vec3 vExtra; + +void main() +{ + gl_Position = uMVP * aVertex; + vNormal = aNormal; + vExtra = aExtra; +} diff --git a/shaders-msl/vert/past-stride.vertex-loader.vert b/shaders-msl/vert/past-stride.vertex-loader.vert new file mode 100644 index 000000000..3b9e0fa5e --- /dev/null +++ b/shaders-msl/vert/past-stride.vertex-loader.vert @@ -0,0 +1,9 @@ +#version 310 es + +layout(location = 7) in uint aUInt; +layout(location = 8) in float aUNorm; + +void main() +{ + gl_Position = vec4(float(aUInt) / 64.0, aUNorm, 0.0, 1.0); +} diff --git a/test_shaders.py b/test_shaders.py index 887cb5b73..49bb983c5 100755 --- a/test_shaders.py +++ b/test_shaders.py @@ -378,6 +378,23 @@ def cross_compile_msl(shader, spirv, opt, iterations, paths): msl_args.append('ClipDistance') if '.relax-nan.' in shader: msl_args.append('--relax-nan-checks') + if '.index-u16.' in shader: + msl_args.extend(['--msl-vertex-index-type', 'uint16']) + if '.vertex-loader.' in shader: + # Some random vertex bindings + msl_args.extend(['--msl-vertex-binding', '0', '16', 'vertex', '1']) + msl_args.extend(['--msl-vertex-binding', '1', '8', 'instance', '1']) + msl_args.extend(['--msl-vertex-binding', '2', '16', 'instance', '0']) + msl_args.extend(['--msl-vertex-binding', '3', '16', 'instance', '4']) + msl_args.extend(['--msl-vertex-attribute', '0', '0', 'r16g16b16a16_sfloat', '0']) + msl_args.extend(['--msl-vertex-attribute', '1', '0', 'r16g16b16a16_snorm', '8']) + msl_args.extend(['--msl-vertex-attribute', '2', '1', 'a8b8g8r8_unorm_pack32', '0']) + msl_args.extend(['--msl-vertex-attribute', '3', '1', 'b8g8r8_uscaled', '5']) + msl_args.extend(['--msl-vertex-attribute', '4', '2', 'a2b10g10r10_unorm_pack32', '0']) + msl_args.extend(['--msl-vertex-attribute', '5', '2', 'e5b9g9r9_ufloat_pack32', '4']) + msl_args.extend(['--msl-vertex-attribute', '6', '2', 'b10g11r11_ufloat_pack32', '8']) + msl_args.extend(['--msl-vertex-attribute', '7', '3', 'r32_uint', '32']) + msl_args.extend(['--msl-vertex-attribute', '8', '3', 'r8_unorm', '1']) subprocess.check_call(msl_args)