Updated spirv-cross.

This commit is contained in:
Бранимир Караџић 2019-06-16 17:47:55 -07:00
parent 896f9952f3
commit a3b0f3ff42
42 changed files with 1500 additions and 51 deletions

View File

@ -287,7 +287,7 @@ if (SPIRV_CROSS_STATIC)
endif() endif()
set(spirv-cross-abi-major 0) set(spirv-cross-abi-major 0)
set(spirv-cross-abi-minor 12) set(spirv-cross-abi-minor 13)
set(spirv-cross-abi-patch 0) set(spirv-cross-abi-patch 0)
if (SPIRV_CROSS_SHARED) if (SPIRV_CROSS_SHARED)
@ -453,6 +453,10 @@ if (SPIRV_CROSS_CLI)
target_link_libraries(spirv-cross-small-vector-test spirv-cross-core) target_link_libraries(spirv-cross-small-vector-test spirv-cross-core)
set_target_properties(spirv-cross-small-vector-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}") set_target_properties(spirv-cross-small-vector-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
add_executable(spirv-cross-msl-constexpr-test tests-other/msl_constexpr_test.cpp)
target_link_libraries(spirv-cross-msl-constexpr-test spirv-cross-c)
set_target_properties(spirv-cross-msl-constexpr-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
target_compile_options(spirv-cross-c-api-test PRIVATE -std=c89 -Wall -Wextra) target_compile_options(spirv-cross-c-api-test PRIVATE -std=c89 -Wall -Wextra)
endif() endif()
@ -463,6 +467,8 @@ if (SPIRV_CROSS_CLI)
${spirv-cross-abi-patch}) ${spirv-cross-abi-patch})
add_test(NAME spirv-cross-small-vector-test add_test(NAME spirv-cross-small-vector-test
COMMAND $<TARGET_FILE:spirv-cross-small-vector-test>) COMMAND $<TARGET_FILE:spirv-cross-small-vector-test>)
add_test(NAME spirv-cross-msl-constexpr-test
COMMAND $<TARGET_FILE:spirv-cross-msl-constexpr-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/msl_constexpr_test.spv)
add_test(NAME spirv-cross-test add_test(NAME spirv-cross-test
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --parallel COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --parallel
${spirv-cross-externals} ${spirv-cross-externals}

View File

@ -0,0 +1,17 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position, invariant]];
};
vertex main0_out main0()
{
main0_out out = {};
out.gl_Position = float4(1.0);
return out;
}

View File

@ -0,0 +1,17 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float3 FragColor [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
out.FragColor = float3(1.0);
return out;
}

View File

@ -0,0 +1,22 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 MRT0 [[color(0)]];
float4 MRT1 [[color(1)]];
uint gl_FragStencilRefARB [[stencil]];
};
fragment main0_out main0()
{
main0_out out = {};
out.MRT0 = float4(1.0);
out.MRT1 = float4(1.0, 0.0, 1.0, 1.0);
out.gl_FragStencilRefARB = uint(100);
out.gl_FragStencilRefARB = uint(int(out.gl_FragStencilRefARB) + 10);
return out;
}

View File

@ -0,0 +1,26 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position, invariant]];
};
struct main0_in
{
float4 vInput0 [[attribute(0)]];
float4 vInput1 [[attribute(1)]];
float4 vInput2 [[attribute(2)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
float4 _20 = in.vInput1 * in.vInput2;
float4 _21 = in.vInput0 + _20;
out.gl_Position = _21;
return out;
}

View File

@ -0,0 +1,13 @@
#version 450
#extension GL_ARB_shader_stencil_export : require
layout(location = 0) out vec4 MRT0;
layout(location = 1) out vec4 MRT1;
void main()
{
MRT0 = vec4(1.0);
MRT1 = vec4(1.0, 0.0, 1.0, 1.0);
gl_FragStencilRefARB = 100;
}

View File

@ -0,0 +1,25 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position, invariant]];
};
float4 _main()
{
return float4(1.0);
}
vertex main0_out main0()
{
main0_out out = {};
float4 _14 = _main();
out.gl_Position = _14;
return out;
}

View File

@ -0,0 +1,39 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct AStruct
{
float4 foobar;
};
struct main0_out
{
float3 FragColor [[color(0)]];
};
void someFunction(thread AStruct& s)
{
s.foobar = float4(1.0);
}
void otherFunction(thread float3& global_variable)
{
global_variable = float3(1.0);
}
fragment main0_out main0()
{
main0_out out = {};
AStruct param;
someFunction(param);
AStruct inputs = param;
float3 global_variable;
otherFunction(global_variable);
out.FragColor = global_variable;
return out;
}

View File

@ -0,0 +1,29 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 MRT0 [[color(0)]];
float4 MRT1 [[color(1)]];
uint gl_FragStencilRefARB [[stencil]];
};
void update_stencil(thread uint& gl_FragStencilRefARB)
{
gl_FragStencilRefARB = uint(int(gl_FragStencilRefARB) + 10);
}
fragment main0_out main0()
{
main0_out out = {};
out.MRT0 = float4(1.0);
out.MRT1 = float4(1.0, 0.0, 1.0, 1.0);
out.gl_FragStencilRefARB = uint(100);
update_stencil(out.gl_FragStencilRefARB);
return out;
}

View File

@ -0,0 +1,26 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position, invariant]];
};
struct main0_in
{
float4 vInput0 [[attribute(0)]];
float4 vInput1 [[attribute(1)]];
float4 vInput2 [[attribute(2)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
float4 _20 = in.vInput1 * in.vInput2;
float4 _21 = in.vInput0 + _20;
out.gl_Position = _21;
return out;
}

View File

@ -0,0 +1,32 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_5" : {
"name" : "SSBO0",
"members" : [
{
"name" : "a",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_5",
"name" : "SSBO0",
"block_size" : 0,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,52 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_4" : {
"name" : "SSBO0",
"members" : [
{
"name" : "a",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
},
"_6" : {
"name" : "SSBO1",
"members" : [
{
"name" : "b",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_4",
"name" : "SSBO0",
"block_size" : 0,
"set" : 0,
"binding" : 0
},
{
"type" : "_6",
"name" : "SSBO1",
"block_size" : 0,
"set" : 0,
"binding" : 1
}
]
}

View File

@ -0,0 +1,32 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_4" : {
"name" : "UAV0",
"members" : [
{
"name" : "_data",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_4",
"name" : "UAV0",
"block_size" : 0,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,39 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_4" : {
"name" : "UAV0",
"members" : [
{
"name" : "_data",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_4",
"name" : "UAV0",
"block_size" : 0,
"set" : 0,
"binding" : 0
},
{
"type" : "_4",
"name" : "UAV1",
"block_size" : 0,
"set" : 0,
"binding" : 1
}
]
}

View File

@ -0,0 +1,32 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_5" : {
"name" : "SSBO0",
"members" : [
{
"name" : "a",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_5",
"name" : "SSBO0",
"block_size" : 0,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,52 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_4" : {
"name" : "SSBO0",
"members" : [
{
"name" : "a",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
},
"_6" : {
"name" : "SSBO1",
"members" : [
{
"name" : "b",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_4",
"name" : "SSBO0",
"block_size" : 0,
"set" : 0,
"binding" : 0
},
{
"type" : "_6",
"name" : "SSBO1",
"block_size" : 0,
"set" : 0,
"binding" : 1
}
]
}

View File

@ -0,0 +1,32 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_4" : {
"name" : "UAV0",
"members" : [
{
"name" : "_data",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_4",
"name" : "UAV0",
"block_size" : 0,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,39 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp"
}
],
"types" : {
"_4" : {
"name" : "UAV0",
"members" : [
{
"name" : "_data",
"type" : "vec4",
"array" : [
0
],
"offset" : 0
}
]
}
},
"ssbos" : [
{
"type" : "_4",
"name" : "UAV0",
"block_size" : 0,
"set" : 0,
"binding" : 0
},
{
"type" : "_4",
"name" : "UAV1",
"block_size" : 0,
"set" : 0,
"binding" : 1
}
]
}

View File

@ -0,0 +1,13 @@
#version 450
#extension GL_ARB_shader_stencil_export : require
layout(location = 0) out vec4 MRT0;
layout(location = 1) out vec4 MRT1;
void main()
{
MRT0 = vec4(1.0);
MRT1 = vec4(1.0, 0.0, 1.0, 1.0);
gl_FragStencilRefARB = 100;
}

View File

@ -0,0 +1,34 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 3
; Bound: 18
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %_entryPointOutput
OpSource HLSL 500
OpName %main "main"
OpName %_main_ "@main("
OpName %_entryPointOutput "@entryPointOutput"
OpDecorate %_entryPointOutput Invariant
OpDecorate %_entryPointOutput BuiltIn Position
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%8 = OpTypeFunction %v4float
%float_1 = OpConstant %float 1
%12 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %3
%5 = OpLabel
%17 = OpFunctionCall %v4float %_main_
OpStore %_entryPointOutput %17
OpReturn
OpFunctionEnd
%_main_ = OpFunction %v4float None %8
%10 = OpLabel
OpReturnValue %12
OpFunctionEnd

View File

@ -0,0 +1,20 @@
#version 450
struct AStruct { vec4 foobar; };
void someFunction(out AStruct s) { s.foobar = vec4(1.0); }
highp vec3 global_variable;
void otherFunction() {
global_variable = vec3(1.0);
}
layout(location = 0) out vec3 FragColor;
void main() {
AStruct inputs;
someFunction(inputs);
otherFunction();
FragColor = global_variable;
}

View File

@ -0,0 +1,17 @@
#version 450
#extension GL_ARB_shader_stencil_export : require
layout(location = 0) out vec4 MRT0;
layout(location = 1) out vec4 MRT1;
void update_stencil()
{
gl_FragStencilRefARB += 10;
}
void main()
{
MRT0 = vec4(1.0);
MRT1 = vec4(1.0, 0.0, 1.0, 1.0);
gl_FragStencilRefARB = 100;
update_stencil();
}

View File

@ -0,0 +1,11 @@
#version 310 es
invariant gl_Position;
layout(location = 0) in vec4 vInput0;
layout(location = 1) in vec4 vInput1;
layout(location = 2) in vec4 vInput2;
void main()
{
gl_Position = vInput0 + vInput1 * vInput2;
}

View File

@ -0,0 +1,53 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 35
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %_
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpName %main "main"
OpName %SSBO0 "SSBO0"
OpMemberName %SSBO0 0 "a"
OpName %_ ""
OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %SSBO0 0 Offset 0
OpDecorate %SSBO0 BufferBlock
OpDecorate %_ DescriptorSet 0
OpDecorate %_ Binding 0
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
OpDecorate %_runtimearr_v4float_0 ArrayStride 16
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%SSBO0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_SSBO0 = OpTypePointer Uniform %SSBO0
%_ = OpVariable %_ptr_Uniform_SSBO0 Uniform
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%uint = OpTypeInt 32 0
%v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
%uint_0 = OpConstant %uint 0
%_ptr_Input_uint = OpTypePointer Input %uint
%float_1 = OpConstant %float 1
%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%_runtimearr_v4float_0 = OpTypeRuntimeArray %v4float
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%main = OpFunction %void None %3
%5 = OpLabel
%20 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
%21 = OpLoad %uint %20
%25 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %21
OpStore %25 %23
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,65 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 35
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpName %main "main"
OpName %SSBO0 "SSBO0"
OpMemberName %SSBO0 0 "a"
OpName %_ ""
OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
OpName %SSBO1 "SSBO1"
OpMemberName %SSBO1 0 "b"
OpName %__0 ""
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %SSBO0 0 Offset 0
OpDecorate %SSBO0 BufferBlock
OpDecorate %_ DescriptorSet 0
OpDecorate %_ Binding 0
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
OpDecorate %_runtimearr_v4float_0 ArrayStride 16
OpMemberDecorate %SSBO1 0 Offset 0
OpDecorate %SSBO1 BufferBlock
OpDecorate %__0 DescriptorSet 0
OpDecorate %__0 Binding 1
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%SSBO0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_SSBO0 = OpTypePointer Uniform %SSBO0
%_ = OpVariable %_ptr_Uniform_SSBO0 Uniform
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%uint = OpTypeInt 32 0
%v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
%uint_0 = OpConstant %uint 0
%_ptr_Input_uint = OpTypePointer Input %uint
%float_1 = OpConstant %float 1
%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%_runtimearr_v4float_0 = OpTypeRuntimeArray %v4float
%SSBO1 = OpTypeStruct %_runtimearr_v4float_0
%_ptr_Uniform_SSBO1 = OpTypePointer Uniform %SSBO1
%__0 = OpVariable %_ptr_Uniform_SSBO1 Uniform
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%main = OpFunction %void None %3
%5 = OpLabel
%20 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
%21 = OpLoad %uint %20
%25 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %21
OpStore %25 %23
%34 = OpAccessChain %_ptr_Uniform_v4float %__0 %int_0 %21
OpStore %34 %33
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,48 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 48
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %threadId
OpExecutionMode %main LocalSize 1 1 1
OpSource HLSL 500
OpName %main "main"
OpName %UAV0 "UAV0"
OpMemberName %UAV0 0 "@data"
OpName %UAV0_0 "UAV0"
OpName %threadId "threadId"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %UAV0 0 Offset 0
OpDecorate %UAV0 BufferBlock
OpDecorate %UAV0_0 DescriptorSet 0
OpDecorate %UAV0_0 Binding 0
OpDecorate %threadId BuiltIn GlobalInvocationId
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v3int = OpTypeVector %int 3
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%UAV0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_UAV0 = OpTypePointer Uniform %UAV0
%UAV0_0 = OpVariable %_ptr_Uniform_UAV0 Uniform
%int_0 = OpConstant %int 0
%float_1 = OpConstant %float 1
%26 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%_ptr_Input_v3int = OpTypePointer Input %v3int
%threadId = OpVariable %_ptr_Input_v3int Input
%main = OpFunction %void None %3
%5 = OpLabel
%38 = OpLoad %v3int %threadId
%43 = OpCompositeExtract %int %38 0
%44 = OpAccessChain %_ptr_Uniform_v4float %UAV0_0 %int_0 %43
OpStore %44 %26
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,54 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 48
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %threadId
OpExecutionMode %main LocalSize 1 1 1
OpSource HLSL 500
OpName %main "main"
OpName %UAV0 "UAV0"
OpMemberName %UAV0 0 "@data"
OpName %UAV0_0 "UAV0"
OpName %UAV1 "UAV1"
OpName %threadId "threadId"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %UAV0 0 Offset 0
OpDecorate %UAV0 BufferBlock
OpDecorate %UAV0_0 DescriptorSet 0
OpDecorate %UAV0_0 Binding 0
OpDecorate %UAV1 DescriptorSet 0
OpDecorate %UAV1 Binding 1
OpDecorate %threadId BuiltIn GlobalInvocationId
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v3int = OpTypeVector %int 3
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%UAV0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_UAV0 = OpTypePointer Uniform %UAV0
%UAV0_0 = OpVariable %_ptr_Uniform_UAV0 Uniform
%int_0 = OpConstant %int 0
%float_1 = OpConstant %float 1
%26 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%UAV1 = OpVariable %_ptr_Uniform_UAV0 Uniform
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%_ptr_Input_v3int = OpTypePointer Input %v3int
%threadId = OpVariable %_ptr_Input_v3int Input
%main = OpFunction %void None %3
%5 = OpLabel
%38 = OpLoad %v3int %threadId
%43 = OpCompositeExtract %int %38 0
%44 = OpAccessChain %_ptr_Uniform_v4float %UAV0_0 %int_0 %43
OpStore %44 %26
%47 = OpAccessChain %_ptr_Uniform_v4float %UAV1 %int_0 %43
OpStore %47 %33
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,52 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 35
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID %_
OpExecutionMode %main LocalSize 1 1 1
OpName %main "main"
OpName %SSBO0 "SSBO0"
OpMemberName %SSBO0 0 "a"
OpName %_ ""
OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %SSBO0 0 Offset 0
OpDecorate %SSBO0 BufferBlock
OpDecorate %_ DescriptorSet 0
OpDecorate %_ Binding 0
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
OpDecorate %_runtimearr_v4float_0 ArrayStride 16
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%SSBO0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_SSBO0 = OpTypePointer Uniform %SSBO0
%_ = OpVariable %_ptr_Uniform_SSBO0 Uniform
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%uint = OpTypeInt 32 0
%v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
%uint_0 = OpConstant %uint 0
%_ptr_Input_uint = OpTypePointer Input %uint
%float_1 = OpConstant %float 1
%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%_runtimearr_v4float_0 = OpTypeRuntimeArray %v4float
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%main = OpFunction %void None %3
%5 = OpLabel
%20 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
%21 = OpLoad %uint %20
%25 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %21
OpStore %25 %23
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,64 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 35
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
OpExecutionMode %main LocalSize 1 1 1
OpName %main "main"
OpName %SSBO0 "SSBO0"
OpMemberName %SSBO0 0 "a"
OpName %_ ""
OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
OpName %SSBO1 "SSBO1"
OpMemberName %SSBO1 0 "b"
OpName %__0 ""
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %SSBO0 0 Offset 0
OpDecorate %SSBO0 BufferBlock
OpDecorate %_ DescriptorSet 0
OpDecorate %_ Binding 0
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
OpDecorate %_runtimearr_v4float_0 ArrayStride 16
OpMemberDecorate %SSBO1 0 Offset 0
OpDecorate %SSBO1 BufferBlock
OpDecorate %__0 DescriptorSet 0
OpDecorate %__0 Binding 1
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%SSBO0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_SSBO0 = OpTypePointer Uniform %SSBO0
%_ = OpVariable %_ptr_Uniform_SSBO0 Uniform
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%uint = OpTypeInt 32 0
%v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
%uint_0 = OpConstant %uint 0
%_ptr_Input_uint = OpTypePointer Input %uint
%float_1 = OpConstant %float 1
%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%_runtimearr_v4float_0 = OpTypeRuntimeArray %v4float
%SSBO1 = OpTypeStruct %_runtimearr_v4float_0
%_ptr_Uniform_SSBO1 = OpTypePointer Uniform %SSBO1
%__0 = OpVariable %_ptr_Uniform_SSBO1 Uniform
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%main = OpFunction %void None %3
%5 = OpLabel
%20 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
%21 = OpLoad %uint %20
%25 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %21
OpStore %25 %23
%34 = OpAccessChain %_ptr_Uniform_v4float %__0 %int_0 %21
OpStore %34 %33
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,47 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 48
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %threadId
OpExecutionMode %main LocalSize 1 1 1
OpName %main "main"
OpName %UAV0 "UAV0"
OpMemberName %UAV0 0 "@data"
OpName %UAV0_0 "UAV0"
OpName %threadId "threadId"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %UAV0 0 Offset 0
OpDecorate %UAV0 BufferBlock
OpDecorate %UAV0_0 DescriptorSet 0
OpDecorate %UAV0_0 Binding 0
OpDecorate %threadId BuiltIn GlobalInvocationId
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v3int = OpTypeVector %int 3
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%UAV0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_UAV0 = OpTypePointer Uniform %UAV0
%UAV0_0 = OpVariable %_ptr_Uniform_UAV0 Uniform
%int_0 = OpConstant %int 0
%float_1 = OpConstant %float 1
%26 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%_ptr_Input_v3int = OpTypePointer Input %v3int
%threadId = OpVariable %_ptr_Input_v3int Input
%main = OpFunction %void None %3
%5 = OpLabel
%38 = OpLoad %v3int %threadId
%43 = OpCompositeExtract %int %38 0
%44 = OpAccessChain %_ptr_Uniform_v4float %UAV0_0 %int_0 %43
OpStore %44 %26
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,53 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 48
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %threadId
OpExecutionMode %main LocalSize 1 1 1
OpName %main "main"
OpName %UAV0 "UAV0"
OpMemberName %UAV0 0 "@data"
OpName %UAV0_0 "UAV0"
OpName %UAV1 "UAV1"
OpName %threadId "threadId"
OpDecorate %_runtimearr_v4float ArrayStride 16
OpMemberDecorate %UAV0 0 Offset 0
OpDecorate %UAV0 BufferBlock
OpDecorate %UAV0_0 DescriptorSet 0
OpDecorate %UAV0_0 Binding 0
OpDecorate %UAV1 DescriptorSet 0
OpDecorate %UAV1 Binding 1
OpDecorate %threadId BuiltIn GlobalInvocationId
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v3int = OpTypeVector %int 3
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
%UAV0 = OpTypeStruct %_runtimearr_v4float
%_ptr_Uniform_UAV0 = OpTypePointer Uniform %UAV0
%UAV0_0 = OpVariable %_ptr_Uniform_UAV0 Uniform
%int_0 = OpConstant %int 0
%float_1 = OpConstant %float 1
%26 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%UAV1 = OpVariable %_ptr_Uniform_UAV0 Uniform
%float_2 = OpConstant %float 2
%33 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%_ptr_Input_v3int = OpTypePointer Input %v3int
%threadId = OpVariable %_ptr_Input_v3int Input
%main = OpFunction %void None %3
%5 = OpLabel
%38 = OpLoad %v3int %threadId
%43 = OpCompositeExtract %int %38 0
%44 = OpAccessChain %_ptr_Uniform_v4float %UAV0_0 %int_0 %43
OpStore %44 %26
%47 = OpAccessChain %_ptr_Uniform_v4float %UAV1 %int_0 %43
OpStore %47 %33
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,11 @@
#version 450
#extension GL_ARB_shader_stencil_export : require
layout(location = 0) out vec4 MRT0;
layout(location = 1) out vec4 MRT1;
void main()
{
MRT0 = vec4(1.0);
MRT1 = vec4(1.0, 0.0, 1.0, 1.0);
gl_FragStencilRefARB = 100;
}

View File

@ -755,6 +755,8 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
{ {
ShaderResources res; ShaderResources res;
bool ssbo_instance_name = reflection_ssbo_instance_name_is_significant();
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) { ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) {
auto &type = this->get<SPIRType>(var.basetype); auto &type = this->get<SPIRType>(var.basetype);
@ -772,7 +774,7 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
if (has_decoration(type.self, DecorationBlock)) if (has_decoration(type.self, DecorationBlock))
{ {
res.stage_inputs.push_back( res.stage_inputs.push_back(
{ var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self, false) });
} }
else else
res.stage_inputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); res.stage_inputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
@ -788,7 +790,7 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
if (has_decoration(type.self, DecorationBlock)) if (has_decoration(type.self, DecorationBlock))
{ {
res.stage_outputs.push_back( res.stage_outputs.push_back(
{ var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self, false) });
} }
else else
res.stage_outputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) }); res.stage_outputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
@ -797,19 +799,19 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBlock)) else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBlock))
{ {
res.uniform_buffers.push_back( res.uniform_buffers.push_back(
{ var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self, false) });
} }
// Old way to declare SSBOs. // Old way to declare SSBOs.
else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBufferBlock)) else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBufferBlock))
{ {
res.storage_buffers.push_back( res.storage_buffers.push_back(
{ var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self, ssbo_instance_name) });
} }
// Modern way to declare SSBOs. // Modern way to declare SSBOs.
else if (type.storage == StorageClassStorageBuffer) else if (type.storage == StorageClassStorageBuffer)
{ {
res.storage_buffers.push_back( res.storage_buffers.push_back(
{ var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) }); { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self, ssbo_instance_name) });
} }
// Push constant blocks // Push constant blocks
else if (type.storage == StorageClassPushConstant) else if (type.storage == StorageClassPushConstant)
@ -4139,21 +4141,70 @@ const SmallVector<std::string> &Compiler::get_declared_extensions() const
} }
std::string Compiler::get_remapped_declared_block_name(uint32_t id) const std::string Compiler::get_remapped_declared_block_name(uint32_t id) const
{
return get_remapped_declared_block_name(id, false);
}
std::string Compiler::get_remapped_declared_block_name(uint32_t id, bool fallback_prefer_instance_name) const
{ {
auto itr = declared_block_names.find(id); auto itr = declared_block_names.find(id);
if (itr != end(declared_block_names)) if (itr != end(declared_block_names))
{
return itr->second; return itr->second;
}
else else
{ {
auto &var = get<SPIRVariable>(id); auto &var = get<SPIRVariable>(id);
auto &type = get<SPIRType>(var.basetype);
auto *type_meta = ir.find_meta(type.self); if (fallback_prefer_instance_name)
auto *block_name = type_meta ? &type_meta->decoration.alias : nullptr; {
return (!block_name || block_name->empty()) ? get_block_fallback_name(id) : *block_name; return to_name(var.self);
}
else
{
auto &type = get<SPIRType>(var.basetype);
auto *type_meta = ir.find_meta(type.self);
auto *block_name = type_meta ? &type_meta->decoration.alias : nullptr;
return (!block_name || block_name->empty()) ? get_block_fallback_name(id) : *block_name;
}
} }
} }
bool Compiler::reflection_ssbo_instance_name_is_significant() const
{
if (ir.source.known)
{
// UAVs from HLSL source tend to be declared in a way where the type is reused
// but the instance name is significant, and that's the name we should report.
// For GLSL, SSBOs each have their own block type as that's how GLSL is written.
return ir.source.hlsl;
}
unordered_set<uint32_t> ssbo_type_ids;
bool aliased_ssbo_types = false;
// If we don't have any OpSource information, we need to perform some shaky heuristics.
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) {
auto &type = this->get<SPIRType>(var.basetype);
if (!type.pointer || var.storage == StorageClassFunction)
return;
bool ssbo = var.storage == StorageClassStorageBuffer ||
(var.storage == StorageClassUniform && has_decoration(type.self, DecorationBufferBlock));
if (ssbo)
{
if (ssbo_type_ids.count(type.self))
aliased_ssbo_types = true;
else
ssbo_type_ids.insert(type.self);
}
});
// If the block name is aliased, assume we have HLSL-style UAV declarations.
return aliased_ssbo_types;
}
bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &result_id, spv::Op op, const uint32_t *args, bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &result_id, spv::Op op, const uint32_t *args,
uint32_t length) uint32_t length)
{ {

View File

@ -976,6 +976,9 @@ protected:
bool type_is_block_like(const SPIRType &type) const; bool type_is_block_like(const SPIRType &type) const;
bool type_is_opaque_value(const SPIRType &type) const; bool type_is_opaque_value(const SPIRType &type) const;
bool reflection_ssbo_instance_name_is_significant() const;
std::string get_remapped_declared_block_name(uint32_t id, bool fallback_prefer_instance_name) const;
private: private:
// Used only to implement the old deprecated get_entry_point() interface. // Used only to implement the old deprecated get_entry_point() interface.
const SPIREntryPoint &get_first_entry_point(const std::string &name) const; const SPIREntryPoint &get_first_entry_point(const std::string &name) const;

View File

@ -941,18 +941,9 @@ spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler, SpvExecutio
#endif #endif
} }
spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, spvc_variable_id id,
const spvc_msl_constexpr_sampler *sampler)
{
#if SPIRV_CROSS_C_API_MSL #if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL) static void spvc_convert_msl_sampler(MSLConstexprSampler &samp, const spvc_msl_constexpr_sampler *sampler)
{ {
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
MSLConstexprSampler samp;
samp.s_address = static_cast<MSLSamplerAddress>(sampler->s_address); samp.s_address = static_cast<MSLSamplerAddress>(sampler->s_address);
samp.t_address = static_cast<MSLSamplerAddress>(sampler->t_address); samp.t_address = static_cast<MSLSamplerAddress>(sampler->t_address);
samp.r_address = static_cast<MSLSamplerAddress>(sampler->r_address); samp.r_address = static_cast<MSLSamplerAddress>(sampler->r_address);
@ -968,6 +959,22 @@ spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, sp
samp.compare_func = static_cast<MSLSamplerCompareFunc>(sampler->compare_func); samp.compare_func = static_cast<MSLSamplerCompareFunc>(sampler->compare_func);
samp.coord = static_cast<MSLSamplerCoord>(sampler->coord); samp.coord = static_cast<MSLSamplerCoord>(sampler->coord);
samp.border_color = static_cast<MSLSamplerBorderColor>(sampler->border_color); samp.border_color = static_cast<MSLSamplerBorderColor>(sampler->border_color);
}
#endif
spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, spvc_variable_id id,
const spvc_msl_constexpr_sampler *sampler)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
MSLConstexprSampler samp;
spvc_convert_msl_sampler(samp, sampler);
msl.remap_constexpr_sampler(id, samp); msl.remap_constexpr_sampler(id, samp);
return SPVC_SUCCESS; return SPVC_SUCCESS;
#else #else
@ -978,6 +985,31 @@ spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, sp
#endif #endif
} }
spvc_result spvc_compiler_msl_remap_constexpr_sampler_by_binding(spvc_compiler compiler,
unsigned desc_set, unsigned binding,
const spvc_msl_constexpr_sampler *sampler)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
MSLConstexprSampler samp;
spvc_convert_msl_sampler(samp, sampler);
msl.remap_constexpr_sampler_by_binding(desc_set, binding, samp);
return SPVC_SUCCESS;
#else
(void)desc_set;
(void)binding;
(void)sampler;
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
#endif
}
spvc_result spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler, unsigned location, spvc_result spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler, unsigned location,
unsigned components) unsigned components)
{ {

View File

@ -33,7 +33,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */ /* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0 #define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */ /* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 12 #define SPVC_C_API_VERSION_MINOR 13
/* Bumped if internal implementation details change. */ /* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0 #define SPVC_C_API_VERSION_PATCH 0
@ -548,6 +548,7 @@ SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compi
unsigned set, unsigned set,
unsigned binding); unsigned binding);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, spvc_variable_id id, const spvc_msl_constexpr_sampler *sampler); SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, spvc_variable_id id, const spvc_msl_constexpr_sampler *sampler);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler_by_binding(spvc_compiler compiler, unsigned desc_set, unsigned binding, const spvc_msl_constexpr_sampler *sampler);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler, unsigned location, unsigned components); SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler, unsigned location, unsigned components);
/* /*

View File

@ -6156,6 +6156,17 @@ string CompilerGLSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
case BuiltInIncomingRayFlagsNV: case BuiltInIncomingRayFlagsNV:
return "gl_IncomingRayFlagsNV"; return "gl_IncomingRayFlagsNV";
case BuiltInFragStencilRefEXT:
{
if (!options.es)
{
require_extension_internal("GL_ARB_shader_stencil_export");
return "gl_FragStencilRefARB";
}
else
SPIRV_CROSS_THROW("Stencil export not supported in GLES.");
}
default: default:
return join("gl_BuiltIn_", convert_to_string(builtin)); return join("gl_BuiltIn_", convert_to_string(builtin));
} }
@ -10649,6 +10660,14 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
end_scope(); end_scope();
processing_entry_point = false; processing_entry_point = false;
statement(""); statement("");
// Make sure deferred declaration state for local variables is cleared when we are done with function.
// We risk declaring Private/Workgroup variables in places we are not supposed to otherwise.
for (auto &v : func.local_variables)
{
auto &var = get<SPIRVariable>(v);
var.deferred_declaration = false;
}
} }
void CompilerGLSL::emit_fixup() void CompilerGLSL::emit_fixup()
@ -11825,6 +11844,7 @@ void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &ex
case BuiltInBaseVertex: case BuiltInBaseVertex:
case BuiltInBaseInstance: case BuiltInBaseInstance:
case BuiltInDrawIndex: case BuiltInDrawIndex:
case BuiltInFragStencilRefEXT:
expected_type = SPIRType::Int; expected_type = SPIRType::Int;
break; break;
@ -11860,6 +11880,7 @@ void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &exp
case BuiltInLayer: case BuiltInLayer:
case BuiltInPrimitiveId: case BuiltInPrimitiveId:
case BuiltInViewportIndex: case BuiltInViewportIndex:
case BuiltInFragStencilRefEXT:
expected_type = SPIRType::Int; expected_type = SPIRType::Int;
break; break;

View File

@ -57,7 +57,8 @@ void CompilerMSL::add_msl_vertex_attribute(const MSLVertexAttr &va)
void CompilerMSL::add_msl_resource_binding(const MSLResourceBinding &binding) void CompilerMSL::add_msl_resource_binding(const MSLResourceBinding &binding)
{ {
resource_bindings.push_back({ binding, false }); StageSetBinding tuple = { binding.stage, binding.desc_set, binding.binding };
resource_bindings[tuple] = { binding, false };
} }
void CompilerMSL::add_discrete_descriptor_set(uint32_t desc_set) void CompilerMSL::add_discrete_descriptor_set(uint32_t desc_set)
@ -73,12 +74,9 @@ bool CompilerMSL::is_msl_vertex_attribute_used(uint32_t location)
bool CompilerMSL::is_msl_resource_binding_used(ExecutionModel model, uint32_t desc_set, uint32_t binding) bool CompilerMSL::is_msl_resource_binding_used(ExecutionModel model, uint32_t desc_set, uint32_t binding)
{ {
auto itr = find_if(begin(resource_bindings), end(resource_bindings), StageSetBinding tuple = { model, desc_set, binding };
[&](const std::pair<MSLResourceBinding, bool> &resource) -> bool { auto itr = resource_bindings.find(tuple);
return model == resource.first.stage && desc_set == resource.first.desc_set && return itr != end(resource_bindings) && itr->second.second;
binding == resource.first.binding;
});
return itr != end(resource_bindings) && itr->second;
} }
void CompilerMSL::set_fragment_output_components(uint32_t location, uint32_t components) void CompilerMSL::set_fragment_output_components(uint32_t location, uint32_t components)
@ -528,7 +526,7 @@ void CompilerMSL::emit_entry_point_declarations()
// FIXME: Get test coverage here ... // FIXME: Get test coverage here ...
// Emit constexpr samplers here. // Emit constexpr samplers here.
for (auto &samp : constexpr_samplers) for (auto &samp : constexpr_samplers_by_id)
{ {
auto &var = get<SPIRVariable>(samp.first); auto &var = get<SPIRVariable>(samp.first);
auto &type = get<SPIRType>(var.basetype); auto &type = get<SPIRType>(var.basetype);
@ -1958,7 +1956,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
bool is_interface_block_builtin = bool is_interface_block_builtin =
(bi_type == BuiltInPosition || bi_type == BuiltInPointSize || bi_type == BuiltInClipDistance || (bi_type == BuiltInPosition || bi_type == BuiltInPointSize || bi_type == BuiltInClipDistance ||
bi_type == BuiltInCullDistance || bi_type == BuiltInLayer || bi_type == BuiltInViewportIndex || bi_type == BuiltInCullDistance || bi_type == BuiltInLayer || bi_type == BuiltInViewportIndex ||
bi_type == BuiltInFragDepth || bi_type == BuiltInSampleMask) || bi_type == BuiltInFragDepth || bi_type == BuiltInFragStencilRefEXT || bi_type == BuiltInSampleMask) ||
(get_execution_model() == ExecutionModelTessellationEvaluation && (get_execution_model() == ExecutionModelTessellationEvaluation &&
(bi_type == BuiltInTessLevelOuter || bi_type == BuiltInTessLevelInner)); (bi_type == BuiltInTessLevelOuter || bi_type == BuiltInTessLevelInner));
@ -2092,7 +2090,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
set_name(ib_type_id, to_name(ir.default_entry_point) + "_" + ib_var_ref); set_name(ib_type_id, to_name(ir.default_entry_point) + "_" + ib_var_ref);
set_name(ib_var_id, ib_var_ref); set_name(ib_var_id, ib_var_ref);
for (auto p_var : vars) for (auto *p_var : vars)
{ {
bool strip_array = bool strip_array =
(get_execution_model() == ExecutionModelTessellationControl || (get_execution_model() == ExecutionModelTessellationControl ||
@ -2190,7 +2188,8 @@ uint32_t CompilerMSL::ensure_correct_builtin_type(uint32_t type_id, BuiltIn buil
auto &type = get<SPIRType>(type_id); auto &type = get<SPIRType>(type_id);
if ((builtin == BuiltInSampleMask && is_array(type)) || if ((builtin == BuiltInSampleMask && is_array(type)) ||
((builtin == BuiltInLayer || builtin == BuiltInViewportIndex) && type.basetype != SPIRType::UInt)) ((builtin == BuiltInLayer || builtin == BuiltInViewportIndex || builtin == BuiltInFragStencilRefEXT) &&
type.basetype != SPIRType::UInt))
{ {
uint32_t next_id = ir.increase_bound_by(type.pointer ? 2 : 1); uint32_t next_id = ir.increase_bound_by(type.pointer ? 2 : 1);
uint32_t base_type_id = next_id++; uint32_t base_type_id = next_id++;
@ -5634,6 +5633,11 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
{ {
switch (builtin) switch (builtin)
{ {
case BuiltInFragStencilRefEXT:
if (!msl_options.supports_msl_version(2, 1))
SPIRV_CROSS_THROW("Stencil export only supported in MSL 2.1 and up.");
return string(" [[") + builtin_qualifier(builtin) + "]]";
case BuiltInSampleMask: case BuiltInSampleMask:
case BuiltInFragDepth: case BuiltInFragDepth:
return string(" [[") + builtin_qualifier(builtin) + "]]"; return string(" [[") + builtin_qualifier(builtin) + "]]";
@ -6034,6 +6038,28 @@ string CompilerMSL::entry_point_args_argument_buffer(bool append_comma)
return ep_args; return ep_args;
} }
const MSLConstexprSampler *CompilerMSL::find_constexpr_sampler(uint32_t id) const
{
// Try by ID.
{
auto itr = constexpr_samplers_by_id.find(id);
if (itr != end(constexpr_samplers_by_id))
return &itr->second;
}
// Try by binding.
{
uint32_t desc_set = get_decoration(id, DecorationDescriptorSet);
uint32_t binding = get_decoration(id, DecorationBinding);
auto itr = constexpr_samplers_by_binding.find({ desc_set, binding });
if (itr != end(constexpr_samplers_by_binding))
return &itr->second;
}
return nullptr;
}
void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args) void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
{ {
// Output resources, sorted by resource index & type // Output resources, sorted by resource index & type
@ -6064,19 +6090,30 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
return; return;
} }
const MSLConstexprSampler *constexpr_sampler = nullptr;
if (type.basetype == SPIRType::SampledImage || type.basetype == SPIRType::Sampler)
{
constexpr_sampler = find_constexpr_sampler(var_id);
if (constexpr_sampler)
{
// Mark this ID as a constexpr sampler for later in case it came from set/bindings.
constexpr_samplers_by_id[var_id] = *constexpr_sampler;
}
}
if (type.basetype == SPIRType::SampledImage) if (type.basetype == SPIRType::SampledImage)
{ {
add_resource_name(var_id); add_resource_name(var_id);
resources.push_back( resources.push_back(
{ &var, to_name(var_id), SPIRType::Image, get_metal_resource_index(var, SPIRType::Image) }); { &var, to_name(var_id), SPIRType::Image, get_metal_resource_index(var, SPIRType::Image) });
if (type.image.dim != DimBuffer && constexpr_samplers.count(var_id) == 0) if (type.image.dim != DimBuffer && !constexpr_sampler)
{ {
resources.push_back({ &var, to_sampler_expression(var_id), SPIRType::Sampler, resources.push_back({ &var, to_sampler_expression(var_id), SPIRType::Sampler,
get_metal_resource_index(var, SPIRType::Sampler) }); get_metal_resource_index(var, SPIRType::Sampler) });
} }
} }
else if (constexpr_samplers.count(var_id) == 0) else if (!constexpr_sampler)
{ {
// constexpr samplers are not declared as resources. // constexpr samplers are not declared as resources.
add_resource_name(var_id); add_resource_name(var_id);
@ -6384,24 +6421,21 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base
uint32_t var_desc_set = (var.storage == StorageClassPushConstant) ? kPushConstDescSet : var_dec.set; uint32_t var_desc_set = (var.storage == StorageClassPushConstant) ? kPushConstDescSet : var_dec.set;
uint32_t var_binding = (var.storage == StorageClassPushConstant) ? kPushConstBinding : var_dec.binding; uint32_t var_binding = (var.storage == StorageClassPushConstant) ? kPushConstBinding : var_dec.binding;
// If a matching binding has been specified, find and use it // If a matching binding has been specified, find and use it.
auto itr = find_if(begin(resource_bindings), end(resource_bindings), auto itr = resource_bindings.find({ execution.model, var_desc_set, var_binding });
[&](const pair<MSLResourceBinding, bool> &resource) -> bool {
return var_desc_set == resource.first.desc_set && var_binding == resource.first.binding &&
execution.model == resource.first.stage;
});
if (itr != end(resource_bindings)) if (itr != end(resource_bindings))
{ {
itr->second = true; auto &remap = itr->second;
remap.second = true;
switch (basetype) switch (basetype)
{ {
case SPIRType::Image: case SPIRType::Image:
return itr->first.msl_texture; return remap.first.msl_texture;
case SPIRType::Sampler: case SPIRType::Sampler:
return itr->first.msl_sampler; return remap.first.msl_sampler;
default: default:
return itr->first.msl_buffer; return remap.first.msl_buffer;
} }
} }
@ -7498,6 +7532,7 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
case BuiltInCullDistance: case BuiltInCullDistance:
case BuiltInLayer: case BuiltInLayer:
case BuiltInFragDepth: case BuiltInFragDepth:
case BuiltInFragStencilRefEXT:
case BuiltInSampleMask: case BuiltInSampleMask:
if (get_execution_model() == ExecutionModelTessellationControl) if (get_execution_model() == ExecutionModelTessellationControl)
break; break;
@ -7570,7 +7605,14 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
case BuiltInPointSize: case BuiltInPointSize:
return "point_size"; return "point_size";
case BuiltInPosition: case BuiltInPosition:
return "position"; if (position_invariant)
{
if (!msl_options.supports_msl_version(2, 1))
SPIRV_CROSS_THROW("Invariant position is only supported on MSL 2.1 and up.");
return "position, invariant";
}
else
return "position";
case BuiltInLayer: case BuiltInLayer:
return "render_target_array_index"; return "render_target_array_index";
case BuiltInViewportIndex: case BuiltInViewportIndex:
@ -7629,6 +7671,9 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
else else
return "depth(any)"; return "depth(any)";
case BuiltInFragStencilRefEXT:
return "stencil";
// Compute function in // Compute function in
case BuiltInGlobalInvocationId: case BuiltInGlobalInvocationId:
return "thread_position_in_grid"; return "thread_position_in_grid";
@ -7752,6 +7797,9 @@ string CompilerMSL::builtin_type_decl(BuiltIn builtin)
case BuiltInFragDepth: case BuiltInFragDepth:
return "float"; return "float";
case BuiltInFragStencilRefEXT:
return "uint";
// Compute function in // Compute function in
case BuiltInGlobalInvocationId: case BuiltInGlobalInvocationId:
case BuiltInLocalInvocationId: case BuiltInLocalInvocationId:
@ -8281,7 +8329,12 @@ void CompilerMSL::remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler
SPIRV_CROSS_THROW("Can only remap SampledImage and Sampler type."); SPIRV_CROSS_THROW("Can only remap SampledImage and Sampler type.");
if (!type.array.empty()) if (!type.array.empty())
SPIRV_CROSS_THROW("Can not remap array of samplers."); SPIRV_CROSS_THROW("Can not remap array of samplers.");
constexpr_samplers[id] = sampler; constexpr_samplers_by_id[id] = sampler;
}
void CompilerMSL::remap_constexpr_sampler_by_binding(uint32_t desc_set, uint32_t binding, const MSLConstexprSampler &sampler)
{
constexpr_samplers_by_binding[{ desc_set, binding }] = sampler;
} }
void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
@ -8306,6 +8359,7 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
case BuiltInNumWorkgroups: case BuiltInNumWorkgroups:
case BuiltInLayer: case BuiltInLayer:
case BuiltInViewportIndex: case BuiltInViewportIndex:
case BuiltInFragStencilRefEXT:
expected_type = SPIRType::UInt; expected_type = SPIRType::UInt;
break; break;
@ -8346,6 +8400,7 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr
{ {
case BuiltInLayer: case BuiltInLayer:
case BuiltInViewportIndex: case BuiltInViewportIndex:
case BuiltInFragStencilRefEXT:
expected_type = SPIRType::UInt; expected_type = SPIRType::UInt;
break; break;
@ -8439,6 +8494,17 @@ void CompilerMSL::analyze_argument_buffers()
if (desc_set >= kMaxArgumentBuffers) if (desc_set >= kMaxArgumentBuffers)
SPIRV_CROSS_THROW("Descriptor set index is out of range."); SPIRV_CROSS_THROW("Descriptor set index is out of range.");
const MSLConstexprSampler *constexpr_sampler = nullptr;
if (type.basetype == SPIRType::SampledImage || type.basetype == SPIRType::Sampler)
{
constexpr_sampler = find_constexpr_sampler(var_id);
if (constexpr_sampler)
{
// Mark this ID as a constexpr sampler for later in case it came from set/bindings.
constexpr_samplers_by_id[var_id] = *constexpr_sampler;
}
}
if (type.basetype == SPIRType::SampledImage) if (type.basetype == SPIRType::SampledImage)
{ {
add_resource_name(var_id); add_resource_name(var_id);
@ -8453,13 +8519,13 @@ void CompilerMSL::analyze_argument_buffers()
resources_in_set[desc_set].push_back({ &var, to_name(var_id), SPIRType::Image, image_resource_index }); resources_in_set[desc_set].push_back({ &var, to_name(var_id), SPIRType::Image, image_resource_index });
if (type.image.dim != DimBuffer && constexpr_samplers.count(var_id) == 0) if (type.image.dim != DimBuffer && !constexpr_sampler)
{ {
resources_in_set[desc_set].push_back( resources_in_set[desc_set].push_back(
{ &var, to_sampler_expression(var_id), SPIRType::Sampler, sampler_resource_index }); { &var, to_sampler_expression(var_id), SPIRType::Sampler, sampler_resource_index });
} }
} }
else if (constexpr_samplers.count(var_id) == 0) else if (!constexpr_sampler)
{ {
// constexpr samplers are not declared as resources. // constexpr samplers are not declared as resources.
add_resource_name(var_id); add_resource_name(var_id);
@ -8625,3 +8691,31 @@ void CompilerMSL::analyze_argument_buffers()
} }
} }
} }
bool CompilerMSL::SetBindingPair::operator==(const SetBindingPair &other) const
{
return desc_set == other.desc_set && binding == other.binding;
}
bool CompilerMSL::StageSetBinding::operator==(const StageSetBinding &other) const
{
return model == other.model && desc_set == other.desc_set && binding == other.binding;
}
size_t CompilerMSL::InternalHasher::operator()(const SetBindingPair &value) const
{
// Quality of hash doesn't really matter here.
auto hash_set = std::hash<uint32_t>()(value.desc_set);
auto hash_binding = std::hash<uint32_t>()(value.binding);
return (hash_set * 0x10001b31) ^ hash_binding;
}
size_t CompilerMSL::InternalHasher::operator()(const StageSetBinding &value) const
{
// Quality of hash doesn't really matter here.
auto hash_model = std::hash<uint32_t>()(value.model);
auto hash_set = std::hash<uint32_t>()(value.desc_set);
auto tmp_hash = (hash_model * 0x10001b31) ^ hash_set;
return (tmp_hash * 0x10001b31) ^ value.binding;
}

View File

@ -22,6 +22,7 @@
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <stddef.h>
namespace SPIRV_CROSS_NAMESPACE namespace SPIRV_CROSS_NAMESPACE
{ {
@ -306,6 +307,11 @@ public:
// Query after compilation is done. This allows you to check if a location or set/binding combination was used by the shader. // Query after compilation is done. This allows you to check if a location or set/binding combination was used by the shader.
bool is_msl_vertex_attribute_used(uint32_t location); bool is_msl_vertex_attribute_used(uint32_t location);
// NOTE: Only resources which are remapped using add_msl_resource_binding will be reported here.
// Constexpr samplers are always assumed to be emitted.
// No specific MSLResourceBinding remapping is required for constexpr samplers as long as they are remapped
// by remap_constexpr_sampler(_by_binding).
bool is_msl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding); bool is_msl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding);
// Compiles the SPIR-V code into Metal Shading Language. // Compiles the SPIR-V code into Metal Shading Language.
@ -317,8 +323,13 @@ public:
// The sampler will not consume a binding, but be declared in the entry point as a constexpr sampler. // The sampler will not consume a binding, but be declared in the entry point as a constexpr sampler.
// This can be used on both combined image/samplers (sampler2D) or standalone samplers. // This can be used on both combined image/samplers (sampler2D) or standalone samplers.
// The remapped sampler must not be an array of samplers. // The remapped sampler must not be an array of samplers.
// Prefer remap_constexpr_sampler_by_binding unless you're also doing reflection anyways.
void remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler); void remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler);
// Same as remap_constexpr_sampler, except you provide set/binding, rather than variable ID.
// Remaps based on ID take priority over set/binding remaps.
void remap_constexpr_sampler_by_binding(uint32_t desc_set, uint32_t binding, const MSLConstexprSampler &sampler);
// If using CompilerMSL::Options::pad_fragment_output_components, override the number of components we expect // If using CompilerMSL::Options::pad_fragment_output_components, override the number of components we expect
// to use for a particular location. The default is 4 if number of components is not overridden. // to use for a particular location. The default is 4 if number of components is not overridden.
void set_fragment_output_components(uint32_t location, uint32_t components); void set_fragment_output_components(uint32_t location, uint32_t components);
@ -525,7 +536,28 @@ protected:
std::set<std::string> typedef_lines; std::set<std::string> typedef_lines;
SmallVector<uint32_t> vars_needing_early_declaration; SmallVector<uint32_t> vars_needing_early_declaration;
SmallVector<std::pair<MSLResourceBinding, bool>> resource_bindings; struct SetBindingPair
{
uint32_t desc_set;
uint32_t binding;
bool operator==(const SetBindingPair &other) const;
};
struct StageSetBinding
{
spv::ExecutionModel model;
uint32_t desc_set;
uint32_t binding;
bool operator==(const StageSetBinding &other) const;
};
struct InternalHasher
{
size_t operator()(const SetBindingPair &value) const;
size_t operator()(const StageSetBinding &value) const;
};
std::unordered_map<StageSetBinding, std::pair<MSLResourceBinding, bool>, InternalHasher> resource_bindings;
uint32_t next_metal_resource_index_buffer = 0; uint32_t next_metal_resource_index_buffer = 0;
uint32_t next_metal_resource_index_texture = 0; uint32_t next_metal_resource_index_texture = 0;
uint32_t next_metal_resource_index_sampler = 0; uint32_t next_metal_resource_index_sampler = 0;
@ -559,7 +591,11 @@ protected:
std::string tess_factor_buffer_var_name = "spvTessLevel"; std::string tess_factor_buffer_var_name = "spvTessLevel";
spv::Op previous_instruction_opcode = spv::OpNop; spv::Op previous_instruction_opcode = spv::OpNop;
std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers; // Must be ordered since declaration is in a specific order.
std::map<uint32_t, MSLConstexprSampler> constexpr_samplers_by_id;
std::unordered_map<SetBindingPair, MSLConstexprSampler, InternalHasher> constexpr_samplers_by_binding;
const MSLConstexprSampler *find_constexpr_sampler(uint32_t id) const;
std::unordered_set<uint32_t> buffers_requiring_array_length; std::unordered_set<uint32_t> buffers_requiring_array_length;
SmallVector<uint32_t> buffer_arrays; SmallVector<uint32_t> buffer_arrays;

View File

@ -97,6 +97,8 @@ def path_to_msl_standard(shader):
return '-std=ios-metal2.0' return '-std=ios-metal2.0'
elif '.msl21.' in shader: elif '.msl21.' in shader:
return '-std=ios-metal2.1' return '-std=ios-metal2.1'
elif '.msl22.' in shader:
return '-std=ios-metal2.2'
elif '.msl11.' in shader: elif '.msl11.' in shader:
return '-std=ios-metal1.1' return '-std=ios-metal1.1'
elif '.msl10.' in shader: elif '.msl10.' in shader:
@ -108,6 +110,8 @@ def path_to_msl_standard(shader):
return '-std=macos-metal2.0' return '-std=macos-metal2.0'
elif '.msl21.' in shader: elif '.msl21.' in shader:
return '-std=macos-metal2.1' return '-std=macos-metal2.1'
elif '.msl22.' in shader:
return '-std=macos-metal2.2'
elif '.msl11.' in shader: elif '.msl11.' in shader:
return '-std=macos-metal1.1' return '-std=macos-metal1.1'
else: else:
@ -118,6 +122,8 @@ def path_to_msl_standard_cli(shader):
return '20000' return '20000'
elif '.msl21.' in shader: elif '.msl21.' in shader:
return '20100' return '20100'
elif '.msl22.' in shader:
return '20200'
elif '.msl11.' in shader: elif '.msl11.' in shader:
return '10100' return '10100'
else: else:

View File

@ -0,0 +1,133 @@
// Testbench for MSL constexpr samplers.
// It does not validate output, but it's useful for ad-hoc testing.
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <spirv_cross_c.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#define SPVC_CHECKED_CALL(x) do { \
if ((x) != SPVC_SUCCESS) { \
fprintf(stderr, "Failed at line %d.\n", __LINE__); \
exit(1); \
} \
} while(0)
#define SPVC_CHECKED_CALL_NEGATIVE(x) do { \
g_fail_on_error = SPVC_FALSE; \
if ((x) == SPVC_SUCCESS) { \
fprintf(stderr, "Failed at line %d.\n", __LINE__); \
exit(1); \
} \
g_fail_on_error = SPVC_TRUE; \
} while(0)
static std::vector<SpvId> read_file(const char *path)
{
long len;
FILE *file = fopen(path, "rb");
if (!file)
return {};
fseek(file, 0, SEEK_END);
len = ftell(file);
rewind(file);
std::vector<SpvId> buffer(len / sizeof(SpvId));
if (fread(buffer.data(), 1, len, file) != (size_t)len)
{
fclose(file);
return {};
}
fclose(file);
return buffer;
}
int main(int argc, char **argv)
{
if (argc != 2)
return EXIT_FAILURE;
auto buffer = read_file(argv[1]);
if (buffer.empty())
return EXIT_FAILURE;
spvc_context ctx;
spvc_parsed_ir parsed_ir;
spvc_compiler compiler;
SPVC_CHECKED_CALL(spvc_context_create(&ctx));
SPVC_CHECKED_CALL(spvc_context_parse_spirv(ctx, buffer.data(), buffer.size(), &parsed_ir));
SPVC_CHECKED_CALL(spvc_context_create_compiler(ctx, SPVC_BACKEND_MSL, parsed_ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler));
spvc_msl_resource_binding binding;
spvc_msl_resource_binding_init(&binding);
binding.desc_set = 1;
binding.binding = 2;
binding.stage = SpvExecutionModelFragment;
binding.msl_texture = 0;
binding.msl_sampler = 0;
SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
binding.binding = 3;
binding.msl_texture = 1;
binding.msl_sampler = 1000; // Will be remapped anyways, sanity check.
SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
binding.desc_set = 2;
binding.binding = 2;
binding.msl_texture = 2;
SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
binding.binding = 3;
binding.msl_texture = 3;
SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
spvc_msl_constexpr_sampler samp;
spvc_msl_constexpr_sampler_init(&samp);
samp.s_address = SPVC_MSL_SAMPLER_ADDRESS_REPEAT;
samp.t_address = SPVC_MSL_SAMPLER_ADDRESS_REPEAT;
samp.r_address = SPVC_MSL_SAMPLER_ADDRESS_REPEAT;
SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding(compiler, 1, 3, &samp));
samp.s_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
samp.t_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
samp.r_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding(compiler, 2, 4, &samp));
samp.compare_enable = SPVC_TRUE;
samp.compare_func = SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS;
samp.s_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
samp.t_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
samp.r_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding(compiler, 2, 5, &samp));
const char *str;
SPVC_CHECKED_CALL(spvc_compiler_compile(compiler, &str));
// Should not be marked as used.
if (spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 4))
return EXIT_FAILURE;
// Should not be marked as used.
if (spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 5))
return EXIT_FAILURE;
// Should be marked, as a sanity check.
if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 1, 2))
return EXIT_FAILURE;
if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 1, 3))
return EXIT_FAILURE;
if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 2))
return EXIT_FAILURE;
if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 3))
return EXIT_FAILURE;
fprintf(stderr, "Output:\n%s\n", str);
}

Binary file not shown.