Browse Source

Updated spirv-cross.

Бранимир Караџић 6 years ago
parent
commit
51cf3115fb
74 changed files with 2993 additions and 212 deletions
  1. 4 0
      3rdparty/spirv-cross/main.cpp
  2. 30 0
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/asm/frag/sample-and-compare.asm.frag
  3. 45 0
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  4. 22 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/frag/sample-and-compare.asm.frag
  5. 23 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/tesc/tess-level-overrun.asm.tesc
  6. 35 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/tese/unnamed-builtin-array.asm.tese
  7. 35 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  8. 1 1
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/bitcast-16bit-1.invalid.comp
  9. 27 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/desktop-only/tese/triangle.desktop.sso.tese
  10. 1 1
      3rdparty/spirv-cross/reference/opt/shaders-msl/frag/16bit-constants.frag
  11. 28 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/input-array.tese
  12. 80 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/input-types.tese
  13. 36 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/quad.domain.tese
  14. 35 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/quad.tese
  15. 55 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/set-from-function.tese
  16. 17 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/triangle.tese
  17. 45 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/tese/water_tess.tese
  18. 13 0
      3rdparty/spirv-cross/reference/opt/shaders/asm/frag/sample-and-compare.asm.frag
  19. 23 0
      3rdparty/spirv-cross/reference/opt/shaders/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  20. 1 1
      3rdparty/spirv-cross/reference/opt/shaders/comp/bitcast-16bit-1.invalid.comp
  21. 10 10
      3rdparty/spirv-cross/reference/opt/shaders/desktop-only/frag/fp16.invalid.desktop.frag
  22. 1 1
      3rdparty/spirv-cross/reference/opt/shaders/frag/16bit-constants.frag
  23. 30 0
      3rdparty/spirv-cross/reference/shaders-hlsl/asm/frag/sample-and-compare.asm.frag
  24. 67 0
      3rdparty/spirv-cross/reference/shaders-hlsl/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  25. 22 0
      3rdparty/spirv-cross/reference/shaders-msl/asm/frag/sample-and-compare.asm.frag
  26. 23 0
      3rdparty/spirv-cross/reference/shaders-msl/asm/tesc/tess-level-overrun.asm.tesc
  27. 35 0
      3rdparty/spirv-cross/reference/shaders-msl/asm/tese/unnamed-builtin-array.asm.tese
  28. 65 0
      3rdparty/spirv-cross/reference/shaders-msl/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  29. 1 1
      3rdparty/spirv-cross/reference/shaders-msl/comp/bitcast-16bit-1.invalid.comp
  30. 27 0
      3rdparty/spirv-cross/reference/shaders-msl/desktop-only/tese/triangle.desktop.sso.tese
  31. 1 1
      3rdparty/spirv-cross/reference/shaders-msl/frag/16bit-constants.frag
  32. 10 10
      3rdparty/spirv-cross/reference/shaders-msl/frag/fp16.desktop.invalid.frag
  33. 35 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/input-array.tese
  34. 90 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/input-types.tese
  35. 36 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/quad.domain.tese
  36. 35 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/quad.tese
  37. 62 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/set-from-function.tese
  38. 17 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/triangle.tese
  39. 72 0
      3rdparty/spirv-cross/reference/shaders-msl/tese/water_tess.tese
  40. 20 0
      3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/opaque-id-literal-alias.preserve.asm.frag
  41. 4 4
      3rdparty/spirv-cross/reference/shaders-reflection/asm/aliased-entry-point-names.asm.multi.json
  42. 13 0
      3rdparty/spirv-cross/reference/shaders/asm/frag/sample-and-compare.asm.frag
  43. 45 0
      3rdparty/spirv-cross/reference/shaders/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  44. 1 1
      3rdparty/spirv-cross/reference/shaders/comp/bitcast-16bit-1.invalid.comp
  45. 10 10
      3rdparty/spirv-cross/reference/shaders/desktop-only/frag/fp16.invalid.desktop.frag
  46. 1 1
      3rdparty/spirv-cross/reference/shaders/frag/16bit-constants.frag
  47. 61 0
      3rdparty/spirv-cross/shaders-hlsl/asm/frag/sample-and-compare.asm.frag
  48. 141 0
      3rdparty/spirv-cross/shaders-hlsl/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  49. 61 0
      3rdparty/spirv-cross/shaders-msl/asm/frag/sample-and-compare.asm.frag
  50. 102 0
      3rdparty/spirv-cross/shaders-msl/asm/tesc/tess-level-overrun.asm.tesc
  51. 96 0
      3rdparty/spirv-cross/shaders-msl/asm/tese/unnamed-builtin-array.asm.tese
  52. 141 0
      3rdparty/spirv-cross/shaders-msl/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  53. 22 0
      3rdparty/spirv-cross/shaders-msl/desktop-only/tese/triangle.desktop.sso.tese
  54. 15 0
      3rdparty/spirv-cross/shaders-msl/tese/input-array.tese
  55. 75 0
      3rdparty/spirv-cross/shaders-msl/tese/input-types.tese
  56. 12 0
      3rdparty/spirv-cross/shaders-msl/tese/quad.domain.tese
  57. 12 0
      3rdparty/spirv-cross/shaders-msl/tese/quad.tese
  58. 36 0
      3rdparty/spirv-cross/shaders-msl/tese/set-from-function.tese
  59. 10 0
      3rdparty/spirv-cross/shaders-msl/tese/triangle.tese
  60. 65 0
      3rdparty/spirv-cross/shaders-msl/tese/water_tess.tese
  61. 78 0
      3rdparty/spirv-cross/shaders-no-opt/asm/frag/opaque-id-literal-alias.preserve.asm.frag
  62. 2 2
      3rdparty/spirv-cross/shaders-reflection/asm/aliased-entry-point-names.asm.multi
  63. 61 0
      3rdparty/spirv-cross/shaders/asm/frag/sample-and-compare.asm.frag
  64. 141 0
      3rdparty/spirv-cross/shaders/asm/vert/extract-transposed-matrix-from-struct.asm.vert
  65. 3 2
      3rdparty/spirv-cross/spirv_common.hpp
  66. 72 2
      3rdparty/spirv-cross/spirv_cross.cpp
  67. 7 1
      3rdparty/spirv-cross/spirv_cross.hpp
  68. 64 41
      3rdparty/spirv-cross/spirv_glsl.cpp
  69. 1 1
      3rdparty/spirv-cross/spirv_glsl.hpp
  70. 0 1
      3rdparty/spirv-cross/spirv_hlsl.cpp
  71. 383 114
      3rdparty/spirv-cross/spirv_msl.cpp
  72. 11 2
      3rdparty/spirv-cross/spirv_msl.hpp
  73. 10 0
      3rdparty/spirv-cross/spirv_reflect.cpp
  74. 22 4
      3rdparty/spirv-cross/test_shaders.py

+ 4 - 0
3rdparty/spirv-cross/main.cpp

@@ -494,6 +494,7 @@ struct CLIArguments
 	bool msl_swizzle_texture_samples = false;
 	bool msl_ios = false;
 	bool msl_pad_fragment_output = false;
+	bool msl_domain_lower_left = false;
 	vector<PLSArg> pls_in;
 	vector<PLSArg> pls_out;
 	vector<Remap> remaps;
@@ -550,6 +551,7 @@ static void print_help()
 	                "\t[--msl-swizzle-texture-samples]\n"
 	                "\t[--msl-ios]\n"
 	                "\t[--msl-pad-fragment-output]\n"
+	                "\t[--msl-domain-lower-left]\n"
 	                "\t[--hlsl]\n"
 	                "\t[--reflect]\n"
 	                "\t[--shader-model]\n"
@@ -720,6 +722,7 @@ static int main_inner(int argc, char *argv[])
 	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; });
+	cbs.add("--msl-domain-lower-left", [&args](CLIParser &) { args.msl_domain_lower_left = true; });
 	cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
 	cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
 		auto old_name = parser.next_string();
@@ -851,6 +854,7 @@ static int main_inner(int argc, char *argv[])
 		if (args.msl_ios)
 			msl_opts.platform = CompilerMSL::Options::iOS;
 		msl_opts.pad_fragment_output_components = args.msl_pad_fragment_output;
+		msl_opts.tess_domain_origin_lower_left = args.msl_domain_lower_left;
 		msl_comp->set_msl_options(msl_opts);
 	}
 	else if (args.hlsl)

+ 30 - 0
3rdparty/spirv-cross/reference/opt/shaders-hlsl/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,30 @@
+Texture2D<float4> g_Texture : register(t0);
+SamplerState g_Sampler : register(s0);
+SamplerComparisonState g_CompareSampler : register(s1);
+
+static float2 in_var_TEXCOORD0;
+static float out_var_SV_Target;
+
+struct SPIRV_Cross_Input
+{
+    float2 in_var_TEXCOORD0 : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+    float out_var_SV_Target : SV_Target0;
+};
+
+void frag_main()
+{
+    out_var_SV_Target = g_Texture.Sample(g_Sampler, in_var_TEXCOORD0).x + g_Texture.SampleCmpLevelZero(g_CompareSampler, in_var_TEXCOORD0, 0.5f);
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+    in_var_TEXCOORD0 = stage_input.in_var_TEXCOORD0;
+    frag_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.out_var_SV_Target = out_var_SV_Target;
+    return stage_output;
+}

+ 45 - 0
3rdparty/spirv-cross/reference/opt/shaders-hlsl/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,45 @@
+struct InstanceData
+{
+    column_major float4x4 MATRIX_MVP;
+    float4 Color;
+};
+
+cbuffer gInstanceData : register(b0)
+{
+    InstanceData gInstanceData_1_data[32] : packoffset(c0);
+};
+
+
+static float4 gl_Position;
+static int gl_InstanceIndex;
+static float3 PosL;
+static float4 _entryPointOutput_Color;
+
+struct SPIRV_Cross_Input
+{
+    float3 PosL : TEXCOORD0;
+    uint gl_InstanceIndex : SV_InstanceID;
+};
+
+struct SPIRV_Cross_Output
+{
+    float4 _entryPointOutput_Color : TEXCOORD0;
+    float4 gl_Position : SV_Position;
+};
+
+void vert_main()
+{
+    gl_Position = mul(float4(PosL, 1.0f), gInstanceData_1_data[uint(gl_InstanceIndex)].MATRIX_MVP);
+    _entryPointOutput_Color = gInstanceData_1_data[uint(gl_InstanceIndex)].Color;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+    gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
+    PosL = stage_input.PosL;
+    vert_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.gl_Position = gl_Position;
+    stage_output._entryPointOutput_Color = _entryPointOutput_Color;
+    return stage_output;
+}

+ 22 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float out_var_SV_Target [[color(0)]];
+};
+
+struct main0_in
+{
+    float2 in_var_TEXCOORD0 [[user(locn0)]];
+};
+
+fragment main0_out main0(main0_in in [[stage_in]], depth2d<float> g_Texture [[texture(0)]], sampler g_Sampler [[sampler(0)]], sampler g_CompareSampler [[sampler(1)]])
+{
+    main0_out out = {};
+    out.out_var_SV_Target = float4(g_Texture.sample(g_Sampler, in.in_var_TEXCOORD0)).x + g_Texture.sample_compare(g_CompareSampler, in.in_var_TEXCOORD0, 0.5, level(0.0));
+    return out;
+}
+

+ 23 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/tesc/tess-level-overrun.asm.tesc

@@ -0,0 +1,23 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct TessLevels
+{
+    float inner0;
+    float inner1;
+    float outer0;
+    float outer1;
+    float outer2;
+    float outer3;
+};
+
+kernel void main0(const device TessLevels& sb_levels [[buffer(0)]], uint gl_InvocationID [[thread_index_in_threadgroup]], uint gl_PrimitiveID [[threadgroup_position_in_grid]], device uint* spvIndirectParams [[buffer(29)]], device MTLTriangleTessellationFactorsHalf* spvTessLevel [[buffer(26)]])
+{
+    spvTessLevel[gl_PrimitiveID].insideTessellationFactor = half(sb_levels.inner0);
+    spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(sb_levels.outer0);
+    spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(sb_levels.outer1);
+    spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[2] = half(sb_levels.outer2);
+}
+

+ 35 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/tese/unnamed-builtin-array.asm.tese

@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float gl_TessLevelInner_0 [[attribute(0)]];
+    float gl_TessLevelInner_1 [[attribute(1)]];
+    float gl_TessLevelOuter_0 [[attribute(2)]];
+    float gl_TessLevelOuter_1 [[attribute(3)]];
+    float gl_TessLevelOuter_2 [[attribute(4)]];
+    float gl_TessLevelOuter_3 [[attribute(5)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelInner[0] = patchIn.gl_TessLevelInner_0;
+    gl_TessLevelInner[1] = patchIn.gl_TessLevelInner_1;
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter_0;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter_1;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter_2;
+    gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter_3;
+    out.gl_Position = float4(((gl_TessCoord.x * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[0])) + (((1.0 - gl_TessCoord.x) * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[2])), ((gl_TessCoord.y * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[1])) + (((1.0 - gl_TessCoord.y) * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[3])), 0.0, 1.0);
+    return out;
+}
+

+ 35 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct InstanceData
+{
+    float4x4 MATRIX_MVP;
+    float4 Color;
+};
+
+struct gInstanceData
+{
+    InstanceData _data[1];
+};
+
+struct main0_out
+{
+    float4 _entryPointOutput_Color [[user(locn0)]];
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float3 PosL [[attribute(0)]];
+};
+
+vertex main0_out main0(main0_in in [[stage_in]], const device gInstanceData& gInstanceData_1 [[buffer(0)]], uint gl_InstanceIndex [[instance_id]])
+{
+    main0_out out = {};
+    out.gl_Position = float4(in.PosL, 1.0) * gInstanceData_1._data[gl_InstanceIndex].MATRIX_MVP;
+    out._entryPointOutput_Color = gInstanceData_1._data[gl_InstanceIndex].Color;
+    return out;
+}
+

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/bitcast-16bit-1.invalid.comp

@@ -15,7 +15,7 @@ struct SSBO1
 
 kernel void main0(device SSBO0& _25 [[buffer(0)]], device SSBO1& _39 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
-    _39.outputs[gl_GlobalInvocationID.x].x = int(as_type<uint>(as_type<half2>(_25.inputs[gl_GlobalInvocationID.x].xy) + half2(1.0h)));
+    _39.outputs[gl_GlobalInvocationID.x].x = int(as_type<uint>(as_type<half2>(_25.inputs[gl_GlobalInvocationID.x].xy) + half2(half(1.0))));
     _39.outputs[gl_GlobalInvocationID.x].y = as_type<int>(_25.inputs[gl_GlobalInvocationID.x].zw);
     _39.outputs[gl_GlobalInvocationID.x].z = int(as_type<uint>(ushort2(_25.inputs[gl_GlobalInvocationID.x].xy)));
 }

+ 27 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/desktop-only/tese/triangle.desktop.sso.tese

@@ -0,0 +1,27 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 gl_Position [[attribute(0)]];
+};
+
+struct main0_patchIn
+{
+    patch_control_point<main0_in> gl_in;
+};
+
+[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float3 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    out.gl_Position = ((patchIn.gl_in[0].gl_Position * gl_TessCoord.x) + (patchIn.gl_in[1].gl_Position * gl_TessCoord.y)) + (patchIn.gl_in[2].gl_Position * gl_TessCoord.z);
+    return out;
+}
+

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders-msl/frag/16bit-constants.frag

@@ -13,7 +13,7 @@ struct main0_out
 fragment main0_out main0()
 {
     main0_out out = {};
-    out.foo = 1.0h;
+    out.foo = half(1.0);
     out.bar = 2;
     out.baz = 3u;
     return out;

+ 28 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/input-array.tese

@@ -0,0 +1,28 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 Floats [[attribute(0)]];
+    float4 Floats2 [[attribute(2)]];
+};
+
+struct main0_patchIn
+{
+    patch_control_point<main0_in> gl_in;
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    out.gl_Position = (patchIn.gl_in[0].Floats * gl_TessCoord.x) + (patchIn.gl_in[1].Floats2 * gl_TessCoord.y);
+    return out;
+}
+

+ 80 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/input-types.tese

@@ -0,0 +1,80 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct Block
+{
+    float4 a;
+    float4 b;
+};
+
+struct PatchBlock
+{
+    float4 a;
+    float4 b;
+};
+
+struct Foo
+{
+    float4 a;
+    float4 b;
+};
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 vColor [[attribute(0)]];
+    float4 Block_a [[attribute(4)]];
+    float4 Block_b [[attribute(5)]];
+    float4 Foo_a [[attribute(14)]];
+    float4 Foo_b [[attribute(15)]];
+};
+
+struct main0_patchIn
+{
+    float4 vColors [[attribute(1)]];
+    float4 PatchBlock_a [[attribute(6)]];
+    float4 PatchBlock_b [[attribute(7)]];
+    float4 Foo_a [[attribute(8)]];
+    float4 Foo_b [[attribute(9)]];
+    patch_control_point<main0_in> gl_in;
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
+{
+    main0_out out = {};
+    PatchBlock patch_block = {};
+    Foo vFoo = {};
+    patch_block.a = patchIn.PatchBlock_a;
+    patch_block.b = patchIn.PatchBlock_b;
+    vFoo.a = patchIn.Foo_a;
+    vFoo.b = patchIn.Foo_b;
+    out.gl_Position = patchIn.gl_in[0].Block_a;
+    out.gl_Position += patchIn.gl_in[0].Block_b;
+    out.gl_Position += patchIn.gl_in[1].Block_a;
+    out.gl_Position += patchIn.gl_in[1].Block_b;
+    out.gl_Position += patch_block.a;
+    out.gl_Position += patch_block.b;
+    out.gl_Position += patchIn.gl_in[0].vColor;
+    out.gl_Position += patchIn.gl_in[1].vColor;
+    out.gl_Position += patchIn.vColors;
+    out.gl_Position += vFoo.a;
+    out.gl_Position += vFoo.b;
+    Foo vFoos_202;
+    vFoos_202.a = patchIn.gl_in[0].Foo_a;
+    vFoos_202.b = patchIn.gl_in[0].Foo_b;
+    out.gl_Position += vFoos_202.a;
+    out.gl_Position += vFoos_202.b;
+    Foo vFoos_216;
+    vFoos_216.a = patchIn.gl_in[1].Foo_a;
+    vFoos_216.b = patchIn.gl_in[1].Foo_b;
+    out.gl_Position += vFoos_216.a;
+    out.gl_Position += vFoos_216.b;
+    return out;
+}
+

+ 36 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/quad.domain.tese

@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float gl_TessLevelInner_0 [[attribute(0)]];
+    float gl_TessLevelInner_1 [[attribute(1)]];
+    float gl_TessLevelOuter_0 [[attribute(2)]];
+    float gl_TessLevelOuter_1 [[attribute(3)]];
+    float gl_TessLevelOuter_2 [[attribute(4)]];
+    float gl_TessLevelOuter_3 [[attribute(5)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelInner[0] = patchIn.gl_TessLevelInner_0;
+    gl_TessLevelInner[1] = patchIn.gl_TessLevelInner_1;
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter_0;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter_1;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter_2;
+    gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter_3;
+    gl_TessCoord.y = 1.0 - gl_TessCoord.y;
+    out.gl_Position = float4(((gl_TessCoord.x * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[0])) + (((1.0 - gl_TessCoord.x) * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[2])), ((gl_TessCoord.y * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[3])) + (((1.0 - gl_TessCoord.y) * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[1])), 0.0, 1.0);
+    return out;
+}
+

+ 35 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/quad.tese

@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float gl_TessLevelInner_0 [[attribute(0)]];
+    float gl_TessLevelInner_1 [[attribute(1)]];
+    float gl_TessLevelOuter_0 [[attribute(2)]];
+    float gl_TessLevelOuter_1 [[attribute(3)]];
+    float gl_TessLevelOuter_2 [[attribute(4)]];
+    float gl_TessLevelOuter_3 [[attribute(5)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelInner[0] = patchIn.gl_TessLevelInner_0;
+    gl_TessLevelInner[1] = patchIn.gl_TessLevelInner_1;
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter_0;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter_1;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter_2;
+    gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter_3;
+    out.gl_Position = float4(((gl_TessCoord.x * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[0])) + (((1.0 - gl_TessCoord.x) * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[2])), ((gl_TessCoord.y * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[1])) + (((1.0 - gl_TessCoord.y) * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[3])), 0.0, 1.0);
+    return out;
+}
+

+ 55 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/set-from-function.tese

@@ -0,0 +1,55 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct Block
+{
+    float4 a;
+    float4 b;
+};
+
+struct Foo
+{
+    float4 a;
+    float4 b;
+};
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 vColor [[attribute(0)]];
+    float4 Block_a [[attribute(2)]];
+    float4 Block_b [[attribute(3)]];
+};
+
+struct main0_patchIn
+{
+    float4 vColors [[attribute(1)]];
+    float4 Foo_a [[attribute(4)]];
+    float4 Foo_b [[attribute(5)]];
+    patch_control_point<main0_in> gl_in;
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
+{
+    main0_out out = {};
+    Foo vFoo = {};
+    vFoo.a = patchIn.Foo_a;
+    vFoo.b = patchIn.Foo_b;
+    out.gl_Position = patchIn.gl_in[0].Block_a;
+    out.gl_Position += patchIn.gl_in[0].Block_b;
+    out.gl_Position += patchIn.gl_in[1].Block_a;
+    out.gl_Position += patchIn.gl_in[1].Block_b;
+    out.gl_Position += patchIn.gl_in[0].vColor;
+    out.gl_Position += patchIn.gl_in[1].vColor;
+    out.gl_Position += patchIn.vColors;
+    out.gl_Position += vFoo.a;
+    out.gl_Position += vFoo.b;
+    return out;
+}
+

+ 17 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/triangle.tese

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

+ 45 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/tese/water_tess.tese

@@ -0,0 +1,45 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct UBO
+{
+    float4x4 uMVP;
+    float4 uScale;
+    float2 uInvScale;
+    float3 uCamPos;
+    float2 uPatchSize;
+    float2 uInvHeightmapSize;
+};
+
+struct main0_out
+{
+    float3 vWorld [[user(locn0)]];
+    float4 vGradNormalTex [[user(locn1)]];
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float2 vOutPatchPosBase [[attribute(0)]];
+    float4 vPatchLods [[attribute(1)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], constant UBO& _31 [[buffer(1)]], texture2d<float> uHeightmapDisplacement [[texture(0)]], sampler uHeightmapDisplacementSmplr [[sampler(0)]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float2 _201 = patchIn.vOutPatchPosBase + (float3(gl_TessCoord, 0).xy * _31.uPatchSize);
+    float2 _214 = mix(patchIn.vPatchLods.yx, patchIn.vPatchLods.zw, float2(float3(gl_TessCoord, 0).x));
+    float _221 = mix(_214.x, _214.y, float3(gl_TessCoord, 0).y);
+    float _223 = floor(_221);
+    float2 _125 = _201 * _31.uInvHeightmapSize;
+    float2 _141 = _31.uInvHeightmapSize * exp2(_223);
+    out.vGradNormalTex = float4(_125 + (_31.uInvHeightmapSize * 0.5), _125 * _31.uScale.zw);
+    float3 _253 = mix(uHeightmapDisplacement.sample(uHeightmapDisplacementSmplr, (_125 + (_141 * 0.5)), level(_223)).xyz, uHeightmapDisplacement.sample(uHeightmapDisplacementSmplr, (_125 + (_141 * 1.0)), level(_223 + 1.0)).xyz, float3(_221 - _223));
+    float2 _171 = (_201 * _31.uScale.xy) + _253.yz;
+    out.vWorld = float3(_171.x, _253.x, _171.y);
+    out.gl_Position = _31.uMVP * float4(out.vWorld, 1.0);
+    return out;
+}
+

+ 13 - 0
3rdparty/spirv-cross/reference/opt/shaders/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,13 @@
+#version 450
+
+uniform sampler2D SPIRV_Cross_Combinedg_Textureg_Sampler;
+uniform sampler2DShadow SPIRV_Cross_Combinedg_Textureg_CompareSampler;
+
+layout(location = 0) in vec2 in_var_TEXCOORD0;
+layout(location = 0) out float out_var_SV_Target;
+
+void main()
+{
+    out_var_SV_Target = texture(SPIRV_Cross_Combinedg_Textureg_Sampler, in_var_TEXCOORD0).x + textureLod(SPIRV_Cross_Combinedg_Textureg_CompareSampler, vec3(in_var_TEXCOORD0, 0.5), 0.0);
+}
+

+ 23 - 0
3rdparty/spirv-cross/reference/opt/shaders/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,23 @@
+#version 450
+
+struct InstanceData
+{
+    mat4 MATRIX_MVP;
+    vec4 Color;
+};
+
+layout(binding = 0, std430) readonly buffer gInstanceData
+{
+    layout(row_major) InstanceData _data[];
+} gInstanceData_1;
+
+layout(location = 0) in vec3 PosL;
+uniform int SPIRV_Cross_BaseInstance;
+layout(location = 0) out vec4 _entryPointOutput_Color;
+
+void main()
+{
+    gl_Position = gInstanceData_1._data[uint((gl_InstanceID + SPIRV_Cross_BaseInstance))].MATRIX_MVP * vec4(PosL, 1.0);
+    _entryPointOutput_Color = gInstanceData_1._data[uint((gl_InstanceID + SPIRV_Cross_BaseInstance))].Color;
+}
+

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders/comp/bitcast-16bit-1.invalid.comp

@@ -27,7 +27,7 @@ void main()
 {
     uint ident = gl_GlobalInvocationID.x;
     f16vec2 a = int16BitsToFloat16(_25.inputs[ident].xy);
-    _39.outputs[ident].x = int(packFloat2x16(a + f16vec2(1.0hf)));
+    _39.outputs[ident].x = int(packFloat2x16(a + f16vec2(float16_t(1.0))));
     _39.outputs[ident].y = packInt2x16(_25.inputs[ident].zw);
     _39.outputs[ident].z = int(packUint2x16(u16vec2(_25.inputs[ident].xy)));
 }

+ 10 - 10
3rdparty/spirv-cross/reference/opt/shaders/desktop-only/frag/fp16.invalid.desktop.frag

@@ -30,19 +30,19 @@ f16mat3 test_mat3(f16vec3 a, f16vec3 b, f16vec3 c, f16vec3 d, f16vec3 e, f16vec3
 
 void test_constants()
 {
-    float16_t a = 1.0hf;
-    float16_t b = 1.5hf;
-    float16_t c = -1.5hf;
-    float16_t d = (0.0hf / 0.0hf);
-    float16_t e = (1.0hf / 0.0hf);
-    float16_t f = (-1.0hf / 0.0hf);
-    float16_t g = 1014.0hf;
-    float16_t h = 9.5367431640625e-07hf;
+    float16_t a = float16_t(1.0);
+    float16_t b = float16_t(1.5);
+    float16_t c = float16_t(-1.5);
+    float16_t d = float16_t(0.0 / 0.0);
+    float16_t e = float16_t(1.0 / 0.0);
+    float16_t f = float16_t(-1.0 / 0.0);
+    float16_t g = float16_t(1014.0);
+    float16_t h = float16_t(9.5367431640625e-07);
 }
 
 float16_t test_result()
 {
-    return 1.0hf;
+    return float16_t(1.0);
 }
 
 void test_conversions()
@@ -50,7 +50,7 @@ void test_conversions()
     float16_t one = test_result();
     int a = int(one);
     uint b = uint(one);
-    bool c = one != 0.0hf;
+    bool c = one != float16_t(0.0);
     float d = float(one);
     double e = double(one);
     float16_t a2 = float16_t(a);

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders/frag/16bit-constants.frag

@@ -18,7 +18,7 @@ layout(location = 2) out uint16_t baz;
 
 void main()
 {
-    foo = 1.0hf;
+    foo = float16_t(1.0);
     bar = 2s;
     baz = 3us;
 }

+ 30 - 0
3rdparty/spirv-cross/reference/shaders-hlsl/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,30 @@
+Texture2D<float4> g_Texture : register(t0);
+SamplerState g_Sampler : register(s0);
+SamplerComparisonState g_CompareSampler : register(s1);
+
+static float2 in_var_TEXCOORD0;
+static float out_var_SV_Target;
+
+struct SPIRV_Cross_Input
+{
+    float2 in_var_TEXCOORD0 : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+    float out_var_SV_Target : SV_Target0;
+};
+
+void frag_main()
+{
+    out_var_SV_Target = g_Texture.Sample(g_Sampler, in_var_TEXCOORD0).x + g_Texture.SampleCmpLevelZero(g_CompareSampler, in_var_TEXCOORD0, 0.5f);
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+    in_var_TEXCOORD0 = stage_input.in_var_TEXCOORD0;
+    frag_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.out_var_SV_Target = out_var_SV_Target;
+    return stage_output;
+}

+ 67 - 0
3rdparty/spirv-cross/reference/shaders-hlsl/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,67 @@
+struct V2F
+{
+    float4 Position;
+    float4 Color;
+};
+
+struct InstanceData
+{
+    column_major float4x4 MATRIX_MVP;
+    float4 Color;
+};
+
+cbuffer gInstanceData : register(b0)
+{
+    InstanceData gInstanceData_1_data[32] : packoffset(c0);
+};
+
+
+static float4 gl_Position;
+static int gl_InstanceIndex;
+static float3 PosL;
+static float4 _entryPointOutput_Color;
+
+struct SPIRV_Cross_Input
+{
+    float3 PosL : TEXCOORD0;
+    uint gl_InstanceIndex : SV_InstanceID;
+};
+
+struct SPIRV_Cross_Output
+{
+    float4 _entryPointOutput_Color : TEXCOORD0;
+    float4 gl_Position : SV_Position;
+};
+
+V2F _VS(float3 PosL_1, uint instanceID)
+{
+    InstanceData instData;
+    instData.MATRIX_MVP = gInstanceData_1_data[instanceID].MATRIX_MVP;
+    instData.Color = gInstanceData_1_data[instanceID].Color;
+    V2F v2f;
+    v2f.Position = mul(float4(PosL_1, 1.0f), instData.MATRIX_MVP);
+    v2f.Color = instData.Color;
+    return v2f;
+}
+
+void vert_main()
+{
+    float3 PosL_1 = PosL;
+    uint instanceID = uint(gl_InstanceIndex);
+    float3 param = PosL_1;
+    uint param_1 = instanceID;
+    V2F flattenTemp = _VS(param, param_1);
+    gl_Position = flattenTemp.Position;
+    _entryPointOutput_Color = flattenTemp.Color;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+    gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
+    PosL = stage_input.PosL;
+    vert_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.gl_Position = gl_Position;
+    stage_output._entryPointOutput_Color = _entryPointOutput_Color;
+    return stage_output;
+}

+ 22 - 0
3rdparty/spirv-cross/reference/shaders-msl/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float out_var_SV_Target [[color(0)]];
+};
+
+struct main0_in
+{
+    float2 in_var_TEXCOORD0 [[user(locn0)]];
+};
+
+fragment main0_out main0(main0_in in [[stage_in]], depth2d<float> g_Texture [[texture(0)]], sampler g_Sampler [[sampler(0)]], sampler g_CompareSampler [[sampler(1)]])
+{
+    main0_out out = {};
+    out.out_var_SV_Target = float4(g_Texture.sample(g_Sampler, in.in_var_TEXCOORD0)).x + g_Texture.sample_compare(g_CompareSampler, in.in_var_TEXCOORD0, 0.5, level(0.0));
+    return out;
+}
+

+ 23 - 0
3rdparty/spirv-cross/reference/shaders-msl/asm/tesc/tess-level-overrun.asm.tesc

@@ -0,0 +1,23 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct TessLevels
+{
+    float inner0;
+    float inner1;
+    float outer0;
+    float outer1;
+    float outer2;
+    float outer3;
+};
+
+kernel void main0(const device TessLevels& sb_levels [[buffer(0)]], uint gl_InvocationID [[thread_index_in_threadgroup]], uint gl_PrimitiveID [[threadgroup_position_in_grid]], device uint* spvIndirectParams [[buffer(29)]], device MTLTriangleTessellationFactorsHalf* spvTessLevel [[buffer(26)]])
+{
+    spvTessLevel[gl_PrimitiveID].insideTessellationFactor = half(sb_levels.inner0);
+    spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(sb_levels.outer0);
+    spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(sb_levels.outer1);
+    spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[2] = half(sb_levels.outer2);
+}
+

+ 35 - 0
3rdparty/spirv-cross/reference/shaders-msl/asm/tese/unnamed-builtin-array.asm.tese

@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float gl_TessLevelInner_0 [[attribute(0)]];
+    float gl_TessLevelInner_1 [[attribute(1)]];
+    float gl_TessLevelOuter_0 [[attribute(2)]];
+    float gl_TessLevelOuter_1 [[attribute(3)]];
+    float gl_TessLevelOuter_2 [[attribute(4)]];
+    float gl_TessLevelOuter_3 [[attribute(5)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelInner[0] = patchIn.gl_TessLevelInner_0;
+    gl_TessLevelInner[1] = patchIn.gl_TessLevelInner_1;
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter_0;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter_1;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter_2;
+    gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter_3;
+    out.gl_Position = float4(((gl_TessCoord.x * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[0])) + (((1.0 - gl_TessCoord.x) * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[2])), ((gl_TessCoord.y * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[1])) + (((1.0 - gl_TessCoord.y) * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[3])), 0.0, 1.0);
+    return out;
+}
+

+ 65 - 0
3rdparty/spirv-cross/reference/shaders-msl/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,65 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct V2F
+{
+    float4 Position;
+    float4 Color;
+};
+
+struct InstanceData
+{
+    float4x4 MATRIX_MVP;
+    float4 Color;
+};
+
+struct InstanceData_1
+{
+    float4x4 MATRIX_MVP;
+    float4 Color;
+};
+
+struct gInstanceData
+{
+    InstanceData _data[1];
+};
+
+struct main0_out
+{
+    float4 _entryPointOutput_Color [[user(locn0)]];
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float3 PosL [[attribute(0)]];
+};
+
+V2F _VS(thread const float3& PosL, thread const uint& instanceID, const device gInstanceData& gInstanceData_1)
+{
+    InstanceData_1 instData;
+    instData.MATRIX_MVP = transpose(gInstanceData_1._data[instanceID].MATRIX_MVP);
+    instData.Color = gInstanceData_1._data[instanceID].Color;
+    V2F v2f;
+    v2f.Position = instData.MATRIX_MVP * float4(PosL, 1.0);
+    v2f.Color = instData.Color;
+    return v2f;
+}
+
+vertex main0_out main0(main0_in in [[stage_in]], const device gInstanceData& gInstanceData_1 [[buffer(0)]], uint gl_InstanceIndex [[instance_id]])
+{
+    main0_out out = {};
+    float3 PosL = in.PosL;
+    uint instanceID = gl_InstanceIndex;
+    float3 param = PosL;
+    uint param_1 = instanceID;
+    V2F flattenTemp = _VS(param, param_1, gInstanceData_1);
+    out.gl_Position = flattenTemp.Position;
+    out._entryPointOutput_Color = flattenTemp.Color;
+    return out;
+}
+

+ 1 - 1
3rdparty/spirv-cross/reference/shaders-msl/comp/bitcast-16bit-1.invalid.comp

@@ -17,7 +17,7 @@ kernel void main0(device SSBO0& _25 [[buffer(0)]], device SSBO1& _39 [[buffer(1)
 {
     uint ident = gl_GlobalInvocationID.x;
     half2 a = as_type<half2>(_25.inputs[ident].xy);
-    _39.outputs[ident].x = int(as_type<uint>(a + half2(1.0h)));
+    _39.outputs[ident].x = int(as_type<uint>(a + half2(half(1.0))));
     _39.outputs[ident].y = as_type<int>(_25.inputs[ident].zw);
     _39.outputs[ident].z = int(as_type<uint>(ushort2(_25.inputs[ident].xy)));
 }

+ 27 - 0
3rdparty/spirv-cross/reference/shaders-msl/desktop-only/tese/triangle.desktop.sso.tese

@@ -0,0 +1,27 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 gl_Position [[attribute(0)]];
+};
+
+struct main0_patchIn
+{
+    patch_control_point<main0_in> gl_in;
+};
+
+[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float3 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    out.gl_Position = ((patchIn.gl_in[0].gl_Position * gl_TessCoord.x) + (patchIn.gl_in[1].gl_Position * gl_TessCoord.y)) + (patchIn.gl_in[2].gl_Position * gl_TessCoord.z);
+    return out;
+}
+

+ 1 - 1
3rdparty/spirv-cross/reference/shaders-msl/frag/16bit-constants.frag

@@ -13,7 +13,7 @@ struct main0_out
 fragment main0_out main0()
 {
     main0_out out = {};
-    out.foo = 1.0h;
+    out.foo = half(1.0);
     out.bar = 2;
     out.baz = 3u;
     return out;

+ 10 - 10
3rdparty/spirv-cross/reference/shaders-msl/frag/fp16.desktop.invalid.frag

@@ -52,19 +52,19 @@ half3x3 test_mat3(thread const half3& a, thread const half3& b, thread const hal
 
 void test_constants()
 {
-    half a = 1.0h;
-    half b = 1.5h;
-    half c = -1.5h;
-    half d = (0.0h / 0.0h);
-    half e = (1.0h / 0.0h);
-    half f = (-1.0h / 0.0h);
-    half g = 1014.0h;
-    half h = 9.5367431640625e-07h;
+    half a = half(1.0);
+    half b = half(1.5);
+    half c = half(-1.5);
+    half d = half(0.0 / 0.0);
+    half e = half(1.0 / 0.0);
+    half f = half(-1.0 / 0.0);
+    half g = half(1014.0);
+    half h = half(9.5367431640625e-07);
 }
 
 half test_result()
 {
-    return 1.0h;
+    return half(1.0);
 }
 
 void test_conversions()
@@ -72,7 +72,7 @@ void test_conversions()
     half one = test_result();
     int a = int(one);
     uint b = uint(one);
-    bool c = one != 0.0h;
+    bool c = one != half(0.0);
     float d = float(one);
     half a2 = half(a);
     half b2 = half(b);

+ 35 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/input-array.tese

@@ -0,0 +1,35 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 Floats [[attribute(0)]];
+    float4 Floats2 [[attribute(2)]];
+};
+
+struct main0_patchIn
+{
+    patch_control_point<main0_in> gl_in;
+};
+
+void set_position(thread float4& gl_Position, thread patch_control_point<main0_in>& gl_in, thread float2& gl_TessCoord)
+{
+    gl_Position = (gl_in[0].Floats * gl_TessCoord.x) + (gl_in[1].Floats2 * gl_TessCoord.y);
+}
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    set_position(out.gl_Position, patchIn.gl_in, gl_TessCoord);
+    return out;
+}
+

+ 90 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/input-types.tese

@@ -0,0 +1,90 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct Block
+{
+    float4 a;
+    float4 b;
+};
+
+struct PatchBlock
+{
+    float4 a;
+    float4 b;
+};
+
+struct Foo
+{
+    float4 a;
+    float4 b;
+};
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 vColor [[attribute(0)]];
+    float4 Block_a [[attribute(4)]];
+    float4 Block_b [[attribute(5)]];
+    float4 Foo_a [[attribute(14)]];
+    float4 Foo_b [[attribute(15)]];
+};
+
+struct main0_patchIn
+{
+    float4 vColors [[attribute(1)]];
+    float4 PatchBlock_a [[attribute(6)]];
+    float4 PatchBlock_b [[attribute(7)]];
+    float4 Foo_a [[attribute(8)]];
+    float4 Foo_b [[attribute(9)]];
+    patch_control_point<main0_in> gl_in;
+};
+
+void set_from_function(thread float4& gl_Position, thread patch_control_point<main0_in>& gl_in, thread PatchBlock& patch_block, thread float4& vColors, thread Foo& vFoo)
+{
+    gl_Position = gl_in[0].Block_a;
+    gl_Position += gl_in[0].Block_b;
+    gl_Position += gl_in[1].Block_a;
+    gl_Position += gl_in[1].Block_b;
+    gl_Position += patch_block.a;
+    gl_Position += patch_block.b;
+    gl_Position += gl_in[0].vColor;
+    gl_Position += gl_in[1].vColor;
+    gl_Position += vColors;
+    Foo foo = vFoo;
+    gl_Position += foo.a;
+    gl_Position += foo.b;
+    Foo vFoos_105;
+    vFoos_105.a = gl_in[0].Foo_a;
+    vFoos_105.b = gl_in[0].Foo_b;
+    foo = vFoos_105;
+    gl_Position += foo.a;
+    gl_Position += foo.b;
+    Foo vFoos_119;
+    vFoos_119.a = gl_in[1].Foo_a;
+    vFoos_119.b = gl_in[1].Foo_b;
+    foo = vFoos_119;
+    gl_Position += foo.a;
+    gl_Position += foo.b;
+}
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
+{
+    main0_out out = {};
+    PatchBlock patch_block = {};
+    Foo vFoo = {};
+    patch_block.a = patchIn.PatchBlock_a;
+    patch_block.b = patchIn.PatchBlock_b;
+    vFoo.a = patchIn.Foo_a;
+    vFoo.b = patchIn.Foo_b;
+    set_from_function(out.gl_Position, patchIn.gl_in, patch_block, patchIn.vColors, vFoo);
+    return out;
+}
+

+ 36 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/quad.domain.tese

@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float gl_TessLevelInner_0 [[attribute(0)]];
+    float gl_TessLevelInner_1 [[attribute(1)]];
+    float gl_TessLevelOuter_0 [[attribute(2)]];
+    float gl_TessLevelOuter_1 [[attribute(3)]];
+    float gl_TessLevelOuter_2 [[attribute(4)]];
+    float gl_TessLevelOuter_3 [[attribute(5)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelInner[0] = patchIn.gl_TessLevelInner_0;
+    gl_TessLevelInner[1] = patchIn.gl_TessLevelInner_1;
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter_0;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter_1;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter_2;
+    gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter_3;
+    gl_TessCoord.y = 1.0 - gl_TessCoord.y;
+    out.gl_Position = float4(((gl_TessCoord.x * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[0])) + (((1.0 - gl_TessCoord.x) * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[2])), ((gl_TessCoord.y * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[3])) + (((1.0 - gl_TessCoord.y) * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[1])), 0.0, 1.0);
+    return out;
+}
+

+ 35 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/quad.tese

@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float gl_TessLevelInner_0 [[attribute(0)]];
+    float gl_TessLevelInner_1 [[attribute(1)]];
+    float gl_TessLevelOuter_0 [[attribute(2)]];
+    float gl_TessLevelOuter_1 [[attribute(3)]];
+    float gl_TessLevelOuter_2 [[attribute(4)]];
+    float gl_TessLevelOuter_3 [[attribute(5)]];
+};
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelInner[0] = patchIn.gl_TessLevelInner_0;
+    gl_TessLevelInner[1] = patchIn.gl_TessLevelInner_1;
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter_0;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter_1;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter_2;
+    gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter_3;
+    out.gl_Position = float4(((gl_TessCoord.x * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[0])) + (((1.0 - gl_TessCoord.x) * as_type<float>(gl_TessLevelInner[0])) * as_type<float>(gl_TessLevelOuter[2])), ((gl_TessCoord.y * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[1])) + (((1.0 - gl_TessCoord.y) * as_type<float>(gl_TessLevelInner[1])) * as_type<float>(gl_TessLevelOuter[3])), 0.0, 1.0);
+    return out;
+}
+

+ 62 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/set-from-function.tese

@@ -0,0 +1,62 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct Block
+{
+    float4 a;
+    float4 b;
+};
+
+struct Foo
+{
+    float4 a;
+    float4 b;
+};
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    float4 vColor [[attribute(0)]];
+    float4 Block_a [[attribute(2)]];
+    float4 Block_b [[attribute(3)]];
+};
+
+struct main0_patchIn
+{
+    float4 vColors [[attribute(1)]];
+    float4 Foo_a [[attribute(4)]];
+    float4 Foo_b [[attribute(5)]];
+    patch_control_point<main0_in> gl_in;
+};
+
+void set_from_function(thread float4& gl_Position, thread patch_control_point<main0_in>& gl_in, thread float4& vColors, thread Foo& vFoo)
+{
+    gl_Position = gl_in[0].Block_a;
+    gl_Position += gl_in[0].Block_b;
+    gl_Position += gl_in[1].Block_a;
+    gl_Position += gl_in[1].Block_b;
+    gl_Position += gl_in[0].vColor;
+    gl_Position += gl_in[1].vColor;
+    gl_Position += vColors;
+    gl_Position += vFoo.a;
+    gl_Position += vFoo.b;
+}
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
+{
+    main0_out out = {};
+    Foo vFoo = {};
+    vFoo.a = patchIn.Foo_a;
+    vFoo.b = patchIn.Foo_b;
+    set_from_function(out.gl_Position, patchIn.gl_in, patchIn.vColors, vFoo);
+    return out;
+}
+

+ 17 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/triangle.tese

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

+ 72 - 0
3rdparty/spirv-cross/reference/shaders-msl/tese/water_tess.tese

@@ -0,0 +1,72 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct UBO
+{
+    float4x4 uMVP;
+    float4 uScale;
+    float2 uInvScale;
+    float3 uCamPos;
+    float2 uPatchSize;
+    float2 uInvHeightmapSize;
+};
+
+struct main0_out
+{
+    float3 vWorld [[user(locn0)]];
+    float4 vGradNormalTex [[user(locn1)]];
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float2 vOutPatchPosBase [[attribute(0)]];
+    float4 vPatchLods [[attribute(1)]];
+};
+
+float2 lerp_vertex(thread const float2& tess_coord, thread float2& vOutPatchPosBase, constant UBO& v_31)
+{
+    return vOutPatchPosBase + (tess_coord * v_31.uPatchSize);
+}
+
+float2 lod_factor(thread const float2& tess_coord, thread float4& vPatchLods)
+{
+    float2 x = mix(vPatchLods.yx, vPatchLods.zw, float2(tess_coord.x));
+    float level = mix(x.x, x.y, tess_coord.y);
+    float floor_level = floor(level);
+    float fract_level = level - floor_level;
+    return float2(floor_level, fract_level);
+}
+
+float3 sample_height_displacement(thread const float2& uv, thread const float2& off, thread const float2& lod, thread texture2d<float> uHeightmapDisplacement, thread const sampler uHeightmapDisplacementSmplr)
+{
+    return mix(uHeightmapDisplacement.sample(uHeightmapDisplacementSmplr, (uv + (off * 0.5)), level(lod.x)).xyz, uHeightmapDisplacement.sample(uHeightmapDisplacementSmplr, (uv + (off * 1.0)), level(lod.x + 1.0)).xyz, float3(lod.y));
+}
+
+[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], constant UBO& v_31 [[buffer(1)]], texture2d<float> uHeightmapDisplacement [[texture(0)]], sampler uHeightmapDisplacementSmplr [[sampler(0)]], float2 gl_TessCoord [[position_in_patch]])
+{
+    main0_out out = {};
+    float2 tess_coord = float3(gl_TessCoord, 0).xy;
+    float2 param = tess_coord;
+    float2 pos = lerp_vertex(param, patchIn.vOutPatchPosBase, v_31);
+    float2 param_1 = tess_coord;
+    float2 lod = lod_factor(param_1, patchIn.vPatchLods);
+    float2 tex = pos * v_31.uInvHeightmapSize;
+    pos *= v_31.uScale.xy;
+    float delta_mod = exp2(lod.x);
+    float2 off = v_31.uInvHeightmapSize * delta_mod;
+    out.vGradNormalTex = float4(tex + (v_31.uInvHeightmapSize * 0.5), tex * v_31.uScale.zw);
+    float2 param_2 = tex;
+    float2 param_3 = off;
+    float2 param_4 = lod;
+    float3 height_displacement = sample_height_displacement(param_2, param_3, param_4, uHeightmapDisplacement, uHeightmapDisplacementSmplr);
+    pos += height_displacement.yz;
+    out.vWorld = float3(pos.x, height_displacement.x, pos.y);
+    out.gl_Position = v_31.uMVP * float4(out.vWorld, 1.0);
+    return out;
+}
+

+ 20 - 0
3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/opaque-id-literal-alias.preserve.asm.frag

@@ -0,0 +1,20 @@
+#version 450
+
+layout(binding = 0) uniform sampler2DMS uSampled;
+
+layout(location = 0) out vec4 FragColor;
+layout(location = 0) in vec2 vUV;
+
+void main()
+{
+    FragColor = vec4(0.0);
+    if (gl_FragCoord.x < 10.0)
+    {
+        FragColor += texelFetch(uSampled, ivec2(vUV), 0);
+    }
+    else
+    {
+        FragColor += texelFetch(uSampled, ivec2(vUV), 1);
+    }
+}
+

+ 4 - 4
3rdparty/spirv-cross/reference/shaders-reflection/asm/aliased-entry-point-names.asm.multi.json

@@ -1,19 +1,19 @@
 {
     "entryPoints" : [
         {
-            "name" : "main",
+            "name" : "maim",
             "mode" : "vert"
         },
         {
-            "name" : "main2",
+            "name" : "main",
             "mode" : "vert"
         },
         {
-            "name" : "main",
+            "name" : "maim",
             "mode" : "frag"
         },
         {
-            "name" : "main2",
+            "name" : "main",
             "mode" : "frag"
         }
     ],

+ 13 - 0
3rdparty/spirv-cross/reference/shaders/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,13 @@
+#version 450
+
+uniform sampler2D SPIRV_Cross_Combinedg_Textureg_Sampler;
+uniform sampler2DShadow SPIRV_Cross_Combinedg_Textureg_CompareSampler;
+
+layout(location = 0) in vec2 in_var_TEXCOORD0;
+layout(location = 0) out float out_var_SV_Target;
+
+void main()
+{
+    out_var_SV_Target = texture(SPIRV_Cross_Combinedg_Textureg_Sampler, in_var_TEXCOORD0).x + textureLod(SPIRV_Cross_Combinedg_Textureg_CompareSampler, vec3(in_var_TEXCOORD0, 0.5), 0.0);
+}
+

+ 45 - 0
3rdparty/spirv-cross/reference/shaders/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,45 @@
+#version 450
+
+struct V2F
+{
+    vec4 Position;
+    vec4 Color;
+};
+
+struct InstanceData
+{
+    mat4 MATRIX_MVP;
+    vec4 Color;
+};
+
+layout(binding = 0, std430) readonly buffer gInstanceData
+{
+    layout(row_major) InstanceData _data[];
+} gInstanceData_1;
+
+layout(location = 0) in vec3 PosL;
+uniform int SPIRV_Cross_BaseInstance;
+layout(location = 0) out vec4 _entryPointOutput_Color;
+
+V2F _VS(vec3 PosL_1, uint instanceID)
+{
+    InstanceData instData;
+    instData.MATRIX_MVP = gInstanceData_1._data[instanceID].MATRIX_MVP;
+    instData.Color = gInstanceData_1._data[instanceID].Color;
+    V2F v2f;
+    v2f.Position = instData.MATRIX_MVP * vec4(PosL_1, 1.0);
+    v2f.Color = instData.Color;
+    return v2f;
+}
+
+void main()
+{
+    vec3 PosL_1 = PosL;
+    uint instanceID = uint((gl_InstanceID + SPIRV_Cross_BaseInstance));
+    vec3 param = PosL_1;
+    uint param_1 = instanceID;
+    V2F flattenTemp = _VS(param, param_1);
+    gl_Position = flattenTemp.Position;
+    _entryPointOutput_Color = flattenTemp.Color;
+}
+

+ 1 - 1
3rdparty/spirv-cross/reference/shaders/comp/bitcast-16bit-1.invalid.comp

@@ -27,7 +27,7 @@ void main()
 {
     uint ident = gl_GlobalInvocationID.x;
     f16vec2 a = int16BitsToFloat16(_25.inputs[ident].xy);
-    _39.outputs[ident].x = int(packFloat2x16(a + f16vec2(1.0hf)));
+    _39.outputs[ident].x = int(packFloat2x16(a + f16vec2(float16_t(1.0))));
     _39.outputs[ident].y = packInt2x16(_25.inputs[ident].zw);
     _39.outputs[ident].z = int(packUint2x16(u16vec2(_25.inputs[ident].xy)));
 }

+ 10 - 10
3rdparty/spirv-cross/reference/shaders/desktop-only/frag/fp16.invalid.desktop.frag

@@ -30,19 +30,19 @@ f16mat3 test_mat3(f16vec3 a, f16vec3 b, f16vec3 c, f16vec3 d, f16vec3 e, f16vec3
 
 void test_constants()
 {
-    float16_t a = 1.0hf;
-    float16_t b = 1.5hf;
-    float16_t c = -1.5hf;
-    float16_t d = (0.0hf / 0.0hf);
-    float16_t e = (1.0hf / 0.0hf);
-    float16_t f = (-1.0hf / 0.0hf);
-    float16_t g = 1014.0hf;
-    float16_t h = 9.5367431640625e-07hf;
+    float16_t a = float16_t(1.0);
+    float16_t b = float16_t(1.5);
+    float16_t c = float16_t(-1.5);
+    float16_t d = float16_t(0.0 / 0.0);
+    float16_t e = float16_t(1.0 / 0.0);
+    float16_t f = float16_t(-1.0 / 0.0);
+    float16_t g = float16_t(1014.0);
+    float16_t h = float16_t(9.5367431640625e-07);
 }
 
 float16_t test_result()
 {
-    return 1.0hf;
+    return float16_t(1.0);
 }
 
 void test_conversions()
@@ -50,7 +50,7 @@ void test_conversions()
     float16_t one = test_result();
     int a = int(one);
     uint b = uint(one);
-    bool c = one != 0.0hf;
+    bool c = one != float16_t(0.0);
     float d = float(one);
     double e = double(one);
     float16_t a2 = float16_t(a);

+ 1 - 1
3rdparty/spirv-cross/reference/shaders/frag/16bit-constants.frag

@@ -18,7 +18,7 @@ layout(location = 2) out uint16_t baz;
 
 void main()
 {
-    foo = 1.0hf;
+    foo = float16_t(1.0);
     bar = 2s;
     baz = 3us;
 }

+ 61 - 0
3rdparty/spirv-cross/shaders-hlsl/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,61 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Google spiregg; 0
+; Bound: 32
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %in_var_TEXCOORD0 %out_var_SV_Target
+               OpExecutionMode %main OriginUpperLeft
+               OpSource HLSL 600
+               OpName %type_2d_image "type.2d.image"
+               OpName %g_Texture "g_Texture"
+               OpName %type_sampler "type.sampler"
+               OpName %g_Sampler "g_Sampler"
+               OpName %g_CompareSampler "g_CompareSampler"
+               OpName %in_var_TEXCOORD0 "in.var.TEXCOORD0"
+               OpName %out_var_SV_Target "out.var.SV_Target"
+               OpName %main "main"
+               OpName %type_sampled_image "type.sampled.image"
+               OpDecorate %in_var_TEXCOORD0 Location 0
+               OpDecorate %out_var_SV_Target Location 0
+               OpDecorate %g_Texture DescriptorSet 0
+               OpDecorate %g_Texture Binding 0
+               OpDecorate %g_Sampler DescriptorSet 0
+               OpDecorate %g_Sampler Binding 0
+               OpDecorate %g_CompareSampler DescriptorSet 0
+               OpDecorate %g_CompareSampler Binding 1
+      %float = OpTypeFloat 32
+  %float_0_5 = OpConstant %float 0.5
+    %float_0 = OpConstant %float 0
+%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
+%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
+%type_sampler = OpTypeSampler
+%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
+    %v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%_ptr_Output_float = OpTypePointer Output %float
+       %void = OpTypeVoid
+         %19 = OpTypeFunction %void
+%type_sampled_image = OpTypeSampledImage %type_2d_image
+    %v4float = OpTypeVector %float 4
+  %g_Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+  %g_Sampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%g_CompareSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%in_var_TEXCOORD0 = OpVariable %_ptr_Input_v2float Input
+%out_var_SV_Target = OpVariable %_ptr_Output_float Output
+       %main = OpFunction %void None %19
+         %21 = OpLabel
+         %22 = OpLoad %v2float %in_var_TEXCOORD0
+         %23 = OpLoad %type_2d_image %g_Texture
+         %24 = OpLoad %type_sampler %g_Sampler
+         %25 = OpSampledImage %type_sampled_image %23 %24
+         %26 = OpImageSampleImplicitLod %v4float %25 %22 None
+         %27 = OpCompositeExtract %float %26 0
+         %28 = OpLoad %type_sampler %g_CompareSampler
+         %29 = OpSampledImage %type_sampled_image %23 %28
+         %30 = OpImageSampleDrefExplicitLod %float %29 %22 %float_0_5 Lod %float_0
+         %31 = OpFAdd %float %27 %30
+               OpStore %out_var_SV_Target %31
+               OpReturn
+               OpFunctionEnd

+ 141 - 0
3rdparty/spirv-cross/shaders-hlsl/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,141 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 79
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %VS "main" %PosL_1 %instanceID_1 %_entryPointOutput_Position %_entryPointOutput_Color
+               OpSource HLSL 500
+               OpName %VS "VS"
+               OpName %V2F "V2F"
+               OpMemberName %V2F 0 "Position"
+               OpMemberName %V2F 1 "Color"
+               OpName %_VS_vf3_u1_ "@VS(vf3;u1;"
+               OpName %PosL "PosL"
+               OpName %instanceID "instanceID"
+               OpName %InstanceData "InstanceData"
+               OpMemberName %InstanceData 0 "MATRIX_MVP"
+               OpMemberName %InstanceData 1 "Color"
+               OpName %instData "instData"
+               OpName %InstanceData_0 "InstanceData"
+               OpMemberName %InstanceData_0 0 "MATRIX_MVP"
+               OpMemberName %InstanceData_0 1 "Color"
+               OpName %gInstanceData "gInstanceData"
+               OpMemberName %gInstanceData 0 "@data"
+               OpName %gInstanceData_0 "gInstanceData"
+               OpName %v2f "v2f"
+               OpName %PosL_0 "PosL"
+               OpName %PosL_1 "PosL"
+               OpName %instanceID_0 "instanceID"
+               OpName %instanceID_1 "instanceID"
+               OpName %flattenTemp "flattenTemp"
+               OpName %param "param"
+               OpName %param_0 "param"
+               OpName %_entryPointOutput_Position "@entryPointOutput.Position"
+               OpName %_entryPointOutput_Color "@entryPointOutput.Color"
+               OpMemberDecorate %InstanceData_0 0 RowMajor
+               OpMemberDecorate %InstanceData_0 0 Offset 0
+               OpMemberDecorate %InstanceData_0 0 MatrixStride 16
+               OpMemberDecorate %InstanceData_0 1 Offset 64
+               OpDecorate %_runtimearr_InstanceData_0 ArrayStride 80
+               OpMemberDecorate %gInstanceData 0 Offset 0
+               OpDecorate %gInstanceData Block
+               OpDecorate %gInstanceData_0 DescriptorSet 1
+               OpDecorate %gInstanceData_0 Binding 0
+               OpDecorate %PosL_1 Location 0
+               OpDecorate %instanceID_1 BuiltIn InstanceIndex
+               OpDecorate %_entryPointOutput_Position BuiltIn Position
+               OpDecorate %_entryPointOutput_Color Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+       %uint = OpTypeInt 32 0
+	   %int_32 = OpConstant %uint 32
+%_ptr_Function_uint = OpTypePointer Function %uint
+    %v4float = OpTypeVector %float 4
+        %V2F = OpTypeStruct %v4float %v4float
+         %13 = OpTypeFunction %V2F %_ptr_Function_v3float %_ptr_Function_uint
+%mat4v4float = OpTypeMatrix %v4float 4
+%InstanceData = OpTypeStruct %mat4v4float %v4float
+%_ptr_Function_InstanceData = OpTypePointer Function %InstanceData
+%InstanceData_0 = OpTypeStruct %mat4v4float %v4float
+%_runtimearr_InstanceData_0 = OpTypeArray %InstanceData_0 %int_32
+%gInstanceData = OpTypeStruct %_runtimearr_InstanceData_0
+%_ptr_Uniform_gInstanceData = OpTypePointer Uniform %gInstanceData
+%gInstanceData_0 = OpVariable %_ptr_Uniform_gInstanceData Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_InstanceData_0 = OpTypePointer Uniform %InstanceData_0
+%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Function_V2F = OpTypePointer Function %V2F
+    %float_1 = OpConstant %float 1
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+     %PosL_1 = OpVariable %_ptr_Input_v3float Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%instanceID_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput_Position = OpVariable %_ptr_Output_v4float Output
+%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
+         %VS = OpFunction %void None %3
+          %5 = OpLabel
+     %PosL_0 = OpVariable %_ptr_Function_v3float Function
+%instanceID_0 = OpVariable %_ptr_Function_uint Function
+%flattenTemp = OpVariable %_ptr_Function_V2F Function
+      %param = OpVariable %_ptr_Function_v3float Function
+    %param_0 = OpVariable %_ptr_Function_uint Function
+         %61 = OpLoad %v3float %PosL_1
+               OpStore %PosL_0 %61
+         %65 = OpLoad %uint %instanceID_1
+               OpStore %instanceID_0 %65
+         %68 = OpLoad %v3float %PosL_0
+               OpStore %param %68
+         %70 = OpLoad %uint %instanceID_0
+               OpStore %param_0 %70
+         %71 = OpFunctionCall %V2F %_VS_vf3_u1_ %param %param_0
+               OpStore %flattenTemp %71
+         %74 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_0
+         %75 = OpLoad %v4float %74
+               OpStore %_entryPointOutput_Position %75
+         %77 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_1
+         %78 = OpLoad %v4float %77
+               OpStore %_entryPointOutput_Color %78
+               OpReturn
+               OpFunctionEnd
+%_VS_vf3_u1_ = OpFunction %V2F None %13
+       %PosL = OpFunctionParameter %_ptr_Function_v3float
+ %instanceID = OpFunctionParameter %_ptr_Function_uint
+         %17 = OpLabel
+   %instData = OpVariable %_ptr_Function_InstanceData Function
+        %v2f = OpVariable %_ptr_Function_V2F Function
+         %29 = OpLoad %uint %instanceID
+         %31 = OpAccessChain %_ptr_Uniform_InstanceData_0 %gInstanceData_0 %int_0 %29
+         %32 = OpLoad %InstanceData_0 %31
+         %33 = OpCompositeExtract %mat4v4float %32 0
+         %35 = OpAccessChain %_ptr_Function_mat4v4float %instData %int_0
+               OpStore %35 %33
+         %36 = OpCompositeExtract %v4float %32 1
+         %39 = OpAccessChain %_ptr_Function_v4float %instData %int_1
+               OpStore %39 %36
+         %42 = OpAccessChain %_ptr_Function_mat4v4float %instData %int_0
+         %43 = OpLoad %mat4v4float %42
+         %44 = OpLoad %v3float %PosL
+         %46 = OpCompositeExtract %float %44 0
+         %47 = OpCompositeExtract %float %44 1
+         %48 = OpCompositeExtract %float %44 2
+         %49 = OpCompositeConstruct %v4float %46 %47 %48 %float_1
+         %50 = OpMatrixTimesVector %v4float %43 %49
+         %51 = OpAccessChain %_ptr_Function_v4float %v2f %int_0
+               OpStore %51 %50
+         %52 = OpAccessChain %_ptr_Function_v4float %instData %int_1
+         %53 = OpLoad %v4float %52
+         %54 = OpAccessChain %_ptr_Function_v4float %v2f %int_1
+               OpStore %54 %53
+         %55 = OpLoad %V2F %v2f
+               OpReturnValue %55
+               OpFunctionEnd

+ 61 - 0
3rdparty/spirv-cross/shaders-msl/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,61 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Google spiregg; 0
+; Bound: 32
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %in_var_TEXCOORD0 %out_var_SV_Target
+               OpExecutionMode %main OriginUpperLeft
+               OpSource HLSL 600
+               OpName %type_2d_image "type.2d.image"
+               OpName %g_Texture "g_Texture"
+               OpName %type_sampler "type.sampler"
+               OpName %g_Sampler "g_Sampler"
+               OpName %g_CompareSampler "g_CompareSampler"
+               OpName %in_var_TEXCOORD0 "in.var.TEXCOORD0"
+               OpName %out_var_SV_Target "out.var.SV_Target"
+               OpName %main "main"
+               OpName %type_sampled_image "type.sampled.image"
+               OpDecorate %in_var_TEXCOORD0 Location 0
+               OpDecorate %out_var_SV_Target Location 0
+               OpDecorate %g_Texture DescriptorSet 0
+               OpDecorate %g_Texture Binding 0
+               OpDecorate %g_Sampler DescriptorSet 0
+               OpDecorate %g_Sampler Binding 0
+               OpDecorate %g_CompareSampler DescriptorSet 0
+               OpDecorate %g_CompareSampler Binding 1
+      %float = OpTypeFloat 32
+  %float_0_5 = OpConstant %float 0.5
+    %float_0 = OpConstant %float 0
+%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
+%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
+%type_sampler = OpTypeSampler
+%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
+    %v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%_ptr_Output_float = OpTypePointer Output %float
+       %void = OpTypeVoid
+         %19 = OpTypeFunction %void
+%type_sampled_image = OpTypeSampledImage %type_2d_image
+    %v4float = OpTypeVector %float 4
+  %g_Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+  %g_Sampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%g_CompareSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%in_var_TEXCOORD0 = OpVariable %_ptr_Input_v2float Input
+%out_var_SV_Target = OpVariable %_ptr_Output_float Output
+       %main = OpFunction %void None %19
+         %21 = OpLabel
+         %22 = OpLoad %v2float %in_var_TEXCOORD0
+         %23 = OpLoad %type_2d_image %g_Texture
+         %24 = OpLoad %type_sampler %g_Sampler
+         %25 = OpSampledImage %type_sampled_image %23 %24
+         %26 = OpImageSampleImplicitLod %v4float %25 %22 None
+         %27 = OpCompositeExtract %float %26 0
+         %28 = OpLoad %type_sampler %g_CompareSampler
+         %29 = OpSampledImage %type_sampled_image %23 %28
+         %30 = OpImageSampleDrefExplicitLod %float %29 %22 %float_0_5 Lod %float_0
+         %31 = OpFAdd %float %27 %30
+               OpStore %out_var_SV_Target %31
+               OpReturn
+               OpFunctionEnd

+ 102 - 0
3rdparty/spirv-cross/shaders-msl/asm/tesc/tess-level-overrun.asm.tesc

@@ -0,0 +1,102 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 46
+; Schema: 0
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationControl %main "main" %gl_TessLevelInner %gl_TessLevelOuter
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main Triangles
+               OpSource ESSL 310
+               OpSourceExtension "GL_EXT_shader_io_blocks"
+               OpSourceExtension "GL_EXT_tessellation_shader"
+               OpName %main "main"
+               OpName %gl_TessLevelInner "gl_TessLevelInner"
+               OpName %TessLevels "TessLevels"
+               OpMemberName %TessLevels 0 "inner0"
+               OpMemberName %TessLevels 1 "inner1"
+               OpMemberName %TessLevels 2 "outer0"
+               OpMemberName %TessLevels 3 "outer1"
+               OpMemberName %TessLevels 4 "outer2"
+               OpMemberName %TessLevels 5 "outer3"
+               OpName %sb_levels "sb_levels"
+               OpName %gl_TessLevelOuter "gl_TessLevelOuter"
+               OpDecorate %gl_TessLevelInner Patch
+               OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
+               OpMemberDecorate %TessLevels 0 Restrict
+               OpMemberDecorate %TessLevels 0 NonWritable
+               OpMemberDecorate %TessLevels 0 Offset 0
+               OpMemberDecorate %TessLevels 1 Restrict
+               OpMemberDecorate %TessLevels 1 NonWritable
+               OpMemberDecorate %TessLevels 1 Offset 4
+               OpMemberDecorate %TessLevels 2 Restrict
+               OpMemberDecorate %TessLevels 2 NonWritable
+               OpMemberDecorate %TessLevels 2 Offset 8
+               OpMemberDecorate %TessLevels 3 Restrict
+               OpMemberDecorate %TessLevels 3 NonWritable
+               OpMemberDecorate %TessLevels 3 Offset 12
+               OpMemberDecorate %TessLevels 4 Restrict
+               OpMemberDecorate %TessLevels 4 NonWritable
+               OpMemberDecorate %TessLevels 4 Offset 16
+               OpMemberDecorate %TessLevels 5 Restrict
+               OpMemberDecorate %TessLevels 5 NonWritable
+               OpMemberDecorate %TessLevels 5 Offset 20
+               OpDecorate %TessLevels Block
+               OpDecorate %sb_levels DescriptorSet 0
+               OpDecorate %sb_levels Binding 0
+               OpDecorate %gl_TessLevelOuter Patch
+               OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+%gl_TessLevelInner = OpVariable %_ptr_Output__arr_float_uint_2 Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+ %TessLevels = OpTypeStruct %float %float %float %float %float %float
+%_ptr_StorageBuffer_TessLevels = OpTypePointer StorageBuffer %TessLevels
+  %sb_levels = OpVariable %_ptr_StorageBuffer_TessLevels StorageBuffer
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+%_ptr_Output_float = OpTypePointer Output %float
+      %int_1 = OpConstant %int 1
+     %uint_4 = OpConstant %uint 4
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+%gl_TessLevelOuter = OpVariable %_ptr_Output__arr_float_uint_4 Output
+      %int_2 = OpConstant %int 2
+      %int_3 = OpConstant %int 3
+      %int_4 = OpConstant %int 4
+      %int_5 = OpConstant %int 5
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %18 = OpAccessChain %_ptr_StorageBuffer_float %sb_levels %int_0
+         %19 = OpLoad %float %18
+         %21 = OpAccessChain %_ptr_Output_float %gl_TessLevelInner %int_0
+               OpStore %21 %19
+         %23 = OpAccessChain %_ptr_StorageBuffer_float %sb_levels %int_1
+         %24 = OpLoad %float %23
+         %25 = OpAccessChain %_ptr_Output_float %gl_TessLevelInner %int_1
+               OpStore %25 %24
+         %31 = OpAccessChain %_ptr_StorageBuffer_float %sb_levels %int_2
+         %32 = OpLoad %float %31
+         %33 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_0
+               OpStore %33 %32
+         %35 = OpAccessChain %_ptr_StorageBuffer_float %sb_levels %int_3
+         %36 = OpLoad %float %35
+         %37 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_1
+               OpStore %37 %36
+         %39 = OpAccessChain %_ptr_StorageBuffer_float %sb_levels %int_4
+         %40 = OpLoad %float %39
+         %41 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_2
+               OpStore %41 %40
+         %43 = OpAccessChain %_ptr_StorageBuffer_float %sb_levels %int_5
+         %44 = OpLoad %float %43
+         %45 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_3
+               OpStore %45 %44
+               OpReturn
+               OpFunctionEnd

+ 96 - 0
3rdparty/spirv-cross/shaders-msl/asm/tese/unnamed-builtin-array.asm.tese

@@ -0,0 +1,96 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 72
+; Schema: 0
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationEvaluation %main "main" %_ %gl_TessCoord %gl_TessLevelInner %gl_TessLevelOuter
+               OpExecutionMode %main Quads
+               OpExecutionMode %main SpacingFractionalEven
+               OpExecutionMode %main VertexOrderCw
+               OpSource ESSL 310
+               OpSourceExtension "GL_EXT_shader_io_blocks"
+               OpSourceExtension "GL_EXT_tessellation_shader"
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpDecorate %gl_PerVertex Block
+               OpDecorate %gl_TessCoord BuiltIn TessCoord
+               OpDecorate %gl_TessLevelInner Patch
+               OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
+               OpDecorate %gl_TessLevelOuter Patch
+               OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%gl_PerVertex = OpTypeStruct %v4float %float
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+    %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%gl_TessCoord = OpVariable %_ptr_Input_v3float Input
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Input__arr_float_uint_2 = OpTypePointer Input %_arr_float_uint_2
+%gl_TessLevelInner = OpVariable %_ptr_Input__arr_float_uint_2 Input
+     %uint_4 = OpConstant %uint 4
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+%_ptr_Input__arr_float_uint_4 = OpTypePointer Input %_arr_float_uint_4
+%gl_TessLevelOuter = OpVariable %_ptr_Input__arr_float_uint_4 Input
+    %float_1 = OpConstant %float 1
+      %int_2 = OpConstant %int 2
+     %uint_1 = OpConstant %uint 1
+      %int_1 = OpConstant %int 1
+      %int_3 = OpConstant %int 3
+    %float_0 = OpConstant %float 0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_0
+         %20 = OpLoad %float %19
+         %25 = OpAccessChain %_ptr_Input_float %gl_TessLevelInner %int_0
+         %26 = OpLoad %float %25
+         %27 = OpFMul %float %20 %26
+         %32 = OpAccessChain %_ptr_Input_float %gl_TessLevelOuter %int_0
+         %33 = OpLoad %float %32
+         %34 = OpFMul %float %27 %33
+         %36 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_0
+         %37 = OpLoad %float %36
+         %38 = OpFSub %float %float_1 %37
+         %39 = OpAccessChain %_ptr_Input_float %gl_TessLevelInner %int_0
+         %40 = OpLoad %float %39
+         %41 = OpFMul %float %38 %40
+         %43 = OpAccessChain %_ptr_Input_float %gl_TessLevelOuter %int_2
+         %44 = OpLoad %float %43
+         %45 = OpFMul %float %41 %44
+         %46 = OpFAdd %float %34 %45
+         %48 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_1
+         %49 = OpLoad %float %48
+         %51 = OpAccessChain %_ptr_Input_float %gl_TessLevelInner %int_1
+         %52 = OpLoad %float %51
+         %53 = OpFMul %float %49 %52
+         %54 = OpAccessChain %_ptr_Input_float %gl_TessLevelOuter %int_1
+         %55 = OpLoad %float %54
+         %56 = OpFMul %float %53 %55
+         %57 = OpAccessChain %_ptr_Input_float %gl_TessCoord %uint_1
+         %58 = OpLoad %float %57
+         %59 = OpFSub %float %float_1 %58
+         %60 = OpAccessChain %_ptr_Input_float %gl_TessLevelInner %int_1
+         %61 = OpLoad %float %60
+         %62 = OpFMul %float %59 %61
+         %64 = OpAccessChain %_ptr_Input_float %gl_TessLevelOuter %int_3
+         %65 = OpLoad %float %64
+         %66 = OpFMul %float %62 %65
+         %67 = OpFAdd %float %56 %66
+         %69 = OpCompositeConstruct %v4float %46 %67 %float_0 %float_1
+         %71 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %71 %69
+               OpReturn
+               OpFunctionEnd

+ 141 - 0
3rdparty/spirv-cross/shaders-msl/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,141 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 79
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %VS "main" %PosL_1 %instanceID_1 %_entryPointOutput_Position %_entryPointOutput_Color
+               OpSource HLSL 500
+               OpName %VS "VS"
+               OpName %V2F "V2F"
+               OpMemberName %V2F 0 "Position"
+               OpMemberName %V2F 1 "Color"
+               OpName %_VS_vf3_u1_ "@VS(vf3;u1;"
+               OpName %PosL "PosL"
+               OpName %instanceID "instanceID"
+               OpName %InstanceData "InstanceData"
+               OpMemberName %InstanceData 0 "MATRIX_MVP"
+               OpMemberName %InstanceData 1 "Color"
+               OpName %instData "instData"
+               OpName %InstanceData_0 "InstanceData"
+               OpMemberName %InstanceData_0 0 "MATRIX_MVP"
+               OpMemberName %InstanceData_0 1 "Color"
+               OpName %gInstanceData "gInstanceData"
+               OpMemberName %gInstanceData 0 "@data"
+               OpName %gInstanceData_0 "gInstanceData"
+               OpName %v2f "v2f"
+               OpName %PosL_0 "PosL"
+               OpName %PosL_1 "PosL"
+               OpName %instanceID_0 "instanceID"
+               OpName %instanceID_1 "instanceID"
+               OpName %flattenTemp "flattenTemp"
+               OpName %param "param"
+               OpName %param_0 "param"
+               OpName %_entryPointOutput_Position "@entryPointOutput.Position"
+               OpName %_entryPointOutput_Color "@entryPointOutput.Color"
+               OpMemberDecorate %InstanceData_0 0 RowMajor
+               OpMemberDecorate %InstanceData_0 0 Offset 0
+               OpMemberDecorate %InstanceData_0 0 MatrixStride 16
+               OpMemberDecorate %InstanceData_0 1 Offset 64
+               OpDecorate %_runtimearr_InstanceData_0 ArrayStride 80
+               OpMemberDecorate %gInstanceData 0 NonWritable
+               OpMemberDecorate %gInstanceData 0 Offset 0
+               OpDecorate %gInstanceData BufferBlock
+               OpDecorate %gInstanceData_0 DescriptorSet 1
+               OpDecorate %gInstanceData_0 Binding 0
+               OpDecorate %PosL_1 Location 0
+               OpDecorate %instanceID_1 BuiltIn InstanceIndex
+               OpDecorate %_entryPointOutput_Position BuiltIn Position
+               OpDecorate %_entryPointOutput_Color Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+       %uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+    %v4float = OpTypeVector %float 4
+        %V2F = OpTypeStruct %v4float %v4float
+         %13 = OpTypeFunction %V2F %_ptr_Function_v3float %_ptr_Function_uint
+%mat4v4float = OpTypeMatrix %v4float 4
+%InstanceData = OpTypeStruct %mat4v4float %v4float
+%_ptr_Function_InstanceData = OpTypePointer Function %InstanceData
+%InstanceData_0 = OpTypeStruct %mat4v4float %v4float
+%_runtimearr_InstanceData_0 = OpTypeRuntimeArray %InstanceData_0
+%gInstanceData = OpTypeStruct %_runtimearr_InstanceData_0
+%_ptr_Uniform_gInstanceData = OpTypePointer Uniform %gInstanceData
+%gInstanceData_0 = OpVariable %_ptr_Uniform_gInstanceData Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_InstanceData_0 = OpTypePointer Uniform %InstanceData_0
+%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Function_V2F = OpTypePointer Function %V2F
+    %float_1 = OpConstant %float 1
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+     %PosL_1 = OpVariable %_ptr_Input_v3float Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%instanceID_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput_Position = OpVariable %_ptr_Output_v4float Output
+%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
+         %VS = OpFunction %void None %3
+          %5 = OpLabel
+     %PosL_0 = OpVariable %_ptr_Function_v3float Function
+%instanceID_0 = OpVariable %_ptr_Function_uint Function
+%flattenTemp = OpVariable %_ptr_Function_V2F Function
+      %param = OpVariable %_ptr_Function_v3float Function
+    %param_0 = OpVariable %_ptr_Function_uint Function
+         %61 = OpLoad %v3float %PosL_1
+               OpStore %PosL_0 %61
+         %65 = OpLoad %uint %instanceID_1
+               OpStore %instanceID_0 %65
+         %68 = OpLoad %v3float %PosL_0
+               OpStore %param %68
+         %70 = OpLoad %uint %instanceID_0
+               OpStore %param_0 %70
+         %71 = OpFunctionCall %V2F %_VS_vf3_u1_ %param %param_0
+               OpStore %flattenTemp %71
+         %74 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_0
+         %75 = OpLoad %v4float %74
+               OpStore %_entryPointOutput_Position %75
+         %77 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_1
+         %78 = OpLoad %v4float %77
+               OpStore %_entryPointOutput_Color %78
+               OpReturn
+               OpFunctionEnd
+%_VS_vf3_u1_ = OpFunction %V2F None %13
+       %PosL = OpFunctionParameter %_ptr_Function_v3float
+ %instanceID = OpFunctionParameter %_ptr_Function_uint
+         %17 = OpLabel
+   %instData = OpVariable %_ptr_Function_InstanceData Function
+        %v2f = OpVariable %_ptr_Function_V2F Function
+         %29 = OpLoad %uint %instanceID
+         %31 = OpAccessChain %_ptr_Uniform_InstanceData_0 %gInstanceData_0 %int_0 %29
+         %32 = OpLoad %InstanceData_0 %31
+         %33 = OpCompositeExtract %mat4v4float %32 0
+         %35 = OpAccessChain %_ptr_Function_mat4v4float %instData %int_0
+               OpStore %35 %33
+         %36 = OpCompositeExtract %v4float %32 1
+         %39 = OpAccessChain %_ptr_Function_v4float %instData %int_1
+               OpStore %39 %36
+         %42 = OpAccessChain %_ptr_Function_mat4v4float %instData %int_0
+         %43 = OpLoad %mat4v4float %42
+         %44 = OpLoad %v3float %PosL
+         %46 = OpCompositeExtract %float %44 0
+         %47 = OpCompositeExtract %float %44 1
+         %48 = OpCompositeExtract %float %44 2
+         %49 = OpCompositeConstruct %v4float %46 %47 %48 %float_1
+         %50 = OpMatrixTimesVector %v4float %43 %49
+         %51 = OpAccessChain %_ptr_Function_v4float %v2f %int_0
+               OpStore %51 %50
+         %52 = OpAccessChain %_ptr_Function_v4float %instData %int_1
+         %53 = OpLoad %v4float %52
+         %54 = OpAccessChain %_ptr_Function_v4float %v2f %int_1
+               OpStore %54 %53
+         %55 = OpLoad %V2F %v2f
+               OpReturnValue %55
+               OpFunctionEnd

+ 22 - 0
3rdparty/spirv-cross/shaders-msl/desktop-only/tese/triangle.desktop.sso.tese

@@ -0,0 +1,22 @@
+#version 450
+
+layout(cw, triangles, fractional_even_spacing) in;
+
+in gl_PerVertex
+{
+   vec4 gl_Position;
+} gl_in[gl_MaxPatchVertices];
+
+out gl_PerVertex
+{
+   vec4 gl_Position;
+};
+
+void main()
+{
+   gl_Position =
+      gl_in[0].gl_Position * gl_TessCoord.x +
+      gl_in[1].gl_Position * gl_TessCoord.y +
+      gl_in[2].gl_Position * gl_TessCoord.z;
+}
+

+ 15 - 0
3rdparty/spirv-cross/shaders-msl/tese/input-array.tese

@@ -0,0 +1,15 @@
+#version 450
+
+layout(ccw, quads, fractional_odd_spacing) in;
+layout(location = 0) in vec4 Floats[];
+layout(location = 2) in vec4 Floats2[gl_MaxPatchVertices];
+
+void set_position()
+{
+	gl_Position = Floats[0] * gl_TessCoord.x + Floats2[1] * gl_TessCoord.y;
+}
+
+void main()
+{
+	set_position();
+}

+ 75 - 0
3rdparty/spirv-cross/shaders-msl/tese/input-types.tese

@@ -0,0 +1,75 @@
+#version 450
+
+layout(ccw, quads, fractional_even_spacing) in;
+
+// Try to use the whole taxonomy of input methods.
+
+// Per-vertex vector.
+layout(location = 0) in vec4 vColor[];
+// Per-patch vector.
+layout(location = 1) patch in vec4 vColors;
+// Per-patch vector array.
+layout(location = 2) patch in vec4 vColorsArray[2];
+
+// I/O blocks, per patch and per control point.
+layout(location = 4) in Block
+{
+        vec4 a;
+        vec4 b;
+} blocks[];
+
+layout(location = 6) patch in PatchBlock
+{
+        vec4 a;
+        vec4 b;
+} patch_block;
+
+// Composites.
+struct Foo
+{
+        vec4 a;
+        vec4 b;
+};
+layout(location = 8) patch in Foo vFoo;
+//layout(location = 10) patch in Foo vFooArray[2];  // FIXME: Handling of array-of-struct input is broken!
+
+// Per-control point struct.
+layout(location = 14) in Foo vFoos[];
+
+void set_from_function()
+{
+        gl_Position = blocks[0].a;
+        gl_Position += blocks[0].b;
+        gl_Position += blocks[1].a;
+        gl_Position += blocks[1].b;
+        gl_Position += patch_block.a;
+        gl_Position += patch_block.b;
+        gl_Position += vColor[0];
+        gl_Position += vColor[1];
+        gl_Position += vColors;
+
+        Foo foo = vFoo;
+        gl_Position += foo.a;
+        gl_Position += foo.b;
+
+        /*foo = vFooArray[0];
+        gl_Position += foo.a;
+        gl_Position += foo.b;
+
+        foo = vFooArray[1];
+        gl_Position += foo.a;
+        gl_Position += foo.b;*/
+
+        foo = vFoos[0];
+        gl_Position += foo.a;
+        gl_Position += foo.b;
+
+        foo = vFoos[1];
+        gl_Position += foo.a;
+        gl_Position += foo.b;
+}
+
+void main()
+{
+        set_from_function();
+}

+ 12 - 0
3rdparty/spirv-cross/shaders-msl/tese/quad.domain.tese

@@ -0,0 +1,12 @@
+#version 310 es
+#extension GL_EXT_tessellation_shader : require
+
+layout(cw, quads, fractional_even_spacing) in;
+
+void main()
+{
+	gl_Position = vec4(gl_TessCoord.x * gl_TessLevelInner[0] * gl_TessLevelOuter[0] + (1.0 - gl_TessCoord.x) * gl_TessLevelInner[0] * gl_TessLevelOuter[2],
+	                   gl_TessCoord.y * gl_TessLevelInner[1] * gl_TessLevelOuter[3] + (1.0 - gl_TessCoord.y) * gl_TessLevelInner[1] * gl_TessLevelOuter[1],
+	                   0, 1);
+}
+

+ 12 - 0
3rdparty/spirv-cross/shaders-msl/tese/quad.tese

@@ -0,0 +1,12 @@
+#version 310 es
+#extension GL_EXT_tessellation_shader : require
+
+layout(cw, quads, fractional_even_spacing) in;
+
+void main()
+{
+	gl_Position = vec4(gl_TessCoord.x * gl_TessLevelInner[0] * gl_TessLevelOuter[0] + (1.0 - gl_TessCoord.x) * gl_TessLevelInner[0] * gl_TessLevelOuter[2],
+	                   gl_TessCoord.y * gl_TessLevelInner[1] * gl_TessLevelOuter[1] + (1.0 - gl_TessCoord.y) * gl_TessLevelInner[1] * gl_TessLevelOuter[3],
+	                   0, 1);
+}
+

+ 36 - 0
3rdparty/spirv-cross/shaders-msl/tese/set-from-function.tese

@@ -0,0 +1,36 @@
+#version 450
+
+layout(ccw, quads, fractional_even_spacing) in;
+
+layout(location = 0) in vec4 vColor[];
+layout(location = 1) patch in vec4 vColors;
+layout(location = 2) in Block
+{
+        vec4 a;
+        vec4 b;
+} blocks[];
+
+struct Foo
+{
+        vec4 a;
+        vec4 b;
+};
+layout(location = 4) patch in Foo vFoo;
+
+void set_from_function()
+{
+        gl_Position = blocks[0].a;
+        gl_Position += blocks[0].b;
+        gl_Position += blocks[1].a;
+        gl_Position += blocks[1].b;
+        gl_Position += vColor[0];
+        gl_Position += vColor[1];
+        gl_Position += vColors;
+        gl_Position += vFoo.a;
+        gl_Position += vFoo.b;
+}
+
+void main()
+{
+        set_from_function();
+}

+ 10 - 0
3rdparty/spirv-cross/shaders-msl/tese/triangle.tese

@@ -0,0 +1,10 @@
+#version 310 es
+#extension GL_EXT_tessellation_shader : require
+
+layout(cw, triangles, fractional_even_spacing) in;
+
+void main()
+{
+   gl_Position = vec4(1.0);
+}
+

+ 65 - 0
3rdparty/spirv-cross/shaders-msl/tese/water_tess.tese

@@ -0,0 +1,65 @@
+#version 310 es
+#extension GL_EXT_tessellation_shader : require
+precision highp int;
+
+layout(cw, quads, fractional_even_spacing) in;
+
+layout(location = 0) patch in vec2 vOutPatchPosBase;
+layout(location = 1) patch in vec4 vPatchLods;
+
+layout(binding = 1, std140) uniform UBO
+{
+    mat4 uMVP;
+    vec4 uScale;
+    vec2 uInvScale;
+    vec3 uCamPos;
+    vec2 uPatchSize;
+    vec2 uInvHeightmapSize;
+};
+layout(binding = 0) uniform mediump sampler2D uHeightmapDisplacement;
+
+layout(location = 0) highp out vec3 vWorld;
+layout(location = 1) highp out vec4 vGradNormalTex;
+
+vec2 lerp_vertex(vec2 tess_coord)
+{
+    return vOutPatchPosBase + tess_coord * uPatchSize;
+}
+
+mediump vec2 lod_factor(vec2 tess_coord)
+{
+    mediump vec2 x = mix(vPatchLods.yx, vPatchLods.zw, tess_coord.x);
+    mediump float level = mix(x.x, x.y, tess_coord.y);
+    mediump float floor_level = floor(level);
+    mediump float fract_level = level - floor_level;
+    return vec2(floor_level, fract_level);
+}
+
+mediump vec3 sample_height_displacement(vec2 uv, vec2 off, mediump vec2 lod)
+{
+    return mix(
+            textureLod(uHeightmapDisplacement, uv + 0.5 * off, lod.x).xyz,
+            textureLod(uHeightmapDisplacement, uv + 1.0 * off, lod.x + 1.0).xyz,
+            lod.y);
+}
+
+void main()
+{
+    vec2 tess_coord = gl_TessCoord.xy;
+    vec2 pos = lerp_vertex(tess_coord);
+    mediump vec2 lod = lod_factor(tess_coord);
+
+    vec2 tex = pos * uInvHeightmapSize.xy;
+    pos *= uScale.xy;
+
+    mediump float delta_mod = exp2(lod.x);
+    vec2 off = uInvHeightmapSize.xy * delta_mod;
+
+    vGradNormalTex = vec4(tex + 0.5 * uInvHeightmapSize.xy, tex * uScale.zw);
+    vec3 height_displacement = sample_height_displacement(tex, off, lod);
+
+    pos += height_displacement.yz;
+    vWorld = vec3(pos.x, height_displacement.x, pos.y);
+    gl_Position = uMVP * vec4(vWorld, 1.0);
+}
+

+ 78 - 0
3rdparty/spirv-cross/shaders-no-opt/asm/frag/opaque-id-literal-alias.preserve.asm.frag

@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 50
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %FragColor %gl_FragCoord %vUV
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %FragColor "FragColor"
+               OpName %gl_FragCoord "gl_FragCoord"
+               OpName %uSampled "uSampled"
+               OpName %vUV "vUV"
+               OpDecorate %FragColor Location 0
+               OpDecorate %gl_FragCoord BuiltIn FragCoord
+               OpDecorate %uSampled DescriptorSet 0
+               OpDecorate %uSampled Binding 0
+               OpDecorate %vUV Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+  %FragColor = OpVariable %_ptr_Output_v4float Output
+    %float_0 = OpConstant %float 0
+         %11 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+   %float_10 = OpConstant %float 10
+       %bool = OpTypeBool
+         %24 = OpTypeImage %float 2D 0 0 1 1 Unknown
+         %25 = OpTypeSampledImage %24
+%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
+   %uSampled = OpVariable %_ptr_UniformConstant_25 UniformConstant
+    %v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+        %vUV = OpVariable %_ptr_Input_v2float Input
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+      %int_0 = OpConstant %int 0
+      %int_1 = OpConstant %int 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpStore %FragColor %11
+         %17 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0
+         %18 = OpLoad %float %17
+         %21 = OpFOrdLessThan %bool %18 %float_10
+               OpSelectionMerge %23 None
+               OpBranchConditional %21 %22 %41
+         %22 = OpLabel
+         %28 = OpLoad %25 %uSampled
+         %32 = OpLoad %v2float %vUV
+         %35 = OpConvertFToS %v2int %32
+         %64 = OpImage %24 %28
+         %38 = OpImageFetch %v4float %64 %35 Sample %int_0
+         %39 = OpLoad %v4float %FragColor
+         %40 = OpFAdd %v4float %39 %38
+               OpStore %FragColor %40
+               OpBranch %23
+         %41 = OpLabel
+         %42 = OpLoad %25 %uSampled
+         %43 = OpLoad %v2float %vUV
+         %44 = OpConvertFToS %v2int %43
+         %46 = OpImage %24 %42
+         %47 = OpImageFetch %v4float %46 %44 Sample %int_1
+         %48 = OpLoad %v4float %FragColor
+         %49 = OpFAdd %v4float %48 %47
+               OpStore %FragColor %49
+               OpBranch %23
+         %23 = OpLabel
+               OpReturn
+               OpFunctionEnd

+ 2 - 2
3rdparty/spirv-cross/shaders-reflection/asm/aliased-entry-point-names.asm.multi

@@ -7,9 +7,9 @@
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %main "main" %_
-               OpEntryPoint Vertex %main2 "main2" %_
+               OpEntryPoint Vertex %main2 "maim" %_
                OpEntryPoint Fragment %main3 "main" %FragColor
-               OpEntryPoint Fragment %main4 "main2" %FragColor
+               OpEntryPoint Fragment %main4 "maim" %FragColor
                OpSource GLSL 450
                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
                OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize

+ 61 - 0
3rdparty/spirv-cross/shaders/asm/frag/sample-and-compare.asm.frag

@@ -0,0 +1,61 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Google spiregg; 0
+; Bound: 32
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %in_var_TEXCOORD0 %out_var_SV_Target
+               OpExecutionMode %main OriginUpperLeft
+               OpSource HLSL 600
+               OpName %type_2d_image "type.2d.image"
+               OpName %g_Texture "g_Texture"
+               OpName %type_sampler "type.sampler"
+               OpName %g_Sampler "g_Sampler"
+               OpName %g_CompareSampler "g_CompareSampler"
+               OpName %in_var_TEXCOORD0 "in.var.TEXCOORD0"
+               OpName %out_var_SV_Target "out.var.SV_Target"
+               OpName %main "main"
+               OpName %type_sampled_image "type.sampled.image"
+               OpDecorate %in_var_TEXCOORD0 Location 0
+               OpDecorate %out_var_SV_Target Location 0
+               OpDecorate %g_Texture DescriptorSet 0
+               OpDecorate %g_Texture Binding 0
+               OpDecorate %g_Sampler DescriptorSet 0
+               OpDecorate %g_Sampler Binding 0
+               OpDecorate %g_CompareSampler DescriptorSet 0
+               OpDecorate %g_CompareSampler Binding 1
+      %float = OpTypeFloat 32
+  %float_0_5 = OpConstant %float 0.5
+    %float_0 = OpConstant %float 0
+%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
+%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
+%type_sampler = OpTypeSampler
+%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
+    %v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%_ptr_Output_float = OpTypePointer Output %float
+       %void = OpTypeVoid
+         %19 = OpTypeFunction %void
+%type_sampled_image = OpTypeSampledImage %type_2d_image
+    %v4float = OpTypeVector %float 4
+  %g_Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+  %g_Sampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%g_CompareSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%in_var_TEXCOORD0 = OpVariable %_ptr_Input_v2float Input
+%out_var_SV_Target = OpVariable %_ptr_Output_float Output
+       %main = OpFunction %void None %19
+         %21 = OpLabel
+         %22 = OpLoad %v2float %in_var_TEXCOORD0
+         %23 = OpLoad %type_2d_image %g_Texture
+         %24 = OpLoad %type_sampler %g_Sampler
+         %25 = OpSampledImage %type_sampled_image %23 %24
+         %26 = OpImageSampleImplicitLod %v4float %25 %22 None
+         %27 = OpCompositeExtract %float %26 0
+         %28 = OpLoad %type_sampler %g_CompareSampler
+         %29 = OpSampledImage %type_sampled_image %23 %28
+         %30 = OpImageSampleDrefExplicitLod %float %29 %22 %float_0_5 Lod %float_0
+         %31 = OpFAdd %float %27 %30
+               OpStore %out_var_SV_Target %31
+               OpReturn
+               OpFunctionEnd

+ 141 - 0
3rdparty/spirv-cross/shaders/asm/vert/extract-transposed-matrix-from-struct.asm.vert

@@ -0,0 +1,141 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 79
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %VS "main" %PosL_1 %instanceID_1 %_entryPointOutput_Position %_entryPointOutput_Color
+               OpSource HLSL 500
+               OpName %VS "VS"
+               OpName %V2F "V2F"
+               OpMemberName %V2F 0 "Position"
+               OpMemberName %V2F 1 "Color"
+               OpName %_VS_vf3_u1_ "@VS(vf3;u1;"
+               OpName %PosL "PosL"
+               OpName %instanceID "instanceID"
+               OpName %InstanceData "InstanceData"
+               OpMemberName %InstanceData 0 "MATRIX_MVP"
+               OpMemberName %InstanceData 1 "Color"
+               OpName %instData "instData"
+               OpName %InstanceData_0 "InstanceData"
+               OpMemberName %InstanceData_0 0 "MATRIX_MVP"
+               OpMemberName %InstanceData_0 1 "Color"
+               OpName %gInstanceData "gInstanceData"
+               OpMemberName %gInstanceData 0 "@data"
+               OpName %gInstanceData_0 "gInstanceData"
+               OpName %v2f "v2f"
+               OpName %PosL_0 "PosL"
+               OpName %PosL_1 "PosL"
+               OpName %instanceID_0 "instanceID"
+               OpName %instanceID_1 "instanceID"
+               OpName %flattenTemp "flattenTemp"
+               OpName %param "param"
+               OpName %param_0 "param"
+               OpName %_entryPointOutput_Position "@entryPointOutput.Position"
+               OpName %_entryPointOutput_Color "@entryPointOutput.Color"
+               OpMemberDecorate %InstanceData_0 0 RowMajor
+               OpMemberDecorate %InstanceData_0 0 Offset 0
+               OpMemberDecorate %InstanceData_0 0 MatrixStride 16
+               OpMemberDecorate %InstanceData_0 1 Offset 64
+               OpDecorate %_runtimearr_InstanceData_0 ArrayStride 80
+               OpMemberDecorate %gInstanceData 0 NonWritable
+               OpMemberDecorate %gInstanceData 0 Offset 0
+               OpDecorate %gInstanceData BufferBlock
+               OpDecorate %gInstanceData_0 DescriptorSet 1
+               OpDecorate %gInstanceData_0 Binding 0
+               OpDecorate %PosL_1 Location 0
+               OpDecorate %instanceID_1 BuiltIn InstanceIndex
+               OpDecorate %_entryPointOutput_Position BuiltIn Position
+               OpDecorate %_entryPointOutput_Color Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+       %uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+    %v4float = OpTypeVector %float 4
+        %V2F = OpTypeStruct %v4float %v4float
+         %13 = OpTypeFunction %V2F %_ptr_Function_v3float %_ptr_Function_uint
+%mat4v4float = OpTypeMatrix %v4float 4
+%InstanceData = OpTypeStruct %mat4v4float %v4float
+%_ptr_Function_InstanceData = OpTypePointer Function %InstanceData
+%InstanceData_0 = OpTypeStruct %mat4v4float %v4float
+%_runtimearr_InstanceData_0 = OpTypeRuntimeArray %InstanceData_0
+%gInstanceData = OpTypeStruct %_runtimearr_InstanceData_0
+%_ptr_Uniform_gInstanceData = OpTypePointer Uniform %gInstanceData
+%gInstanceData_0 = OpVariable %_ptr_Uniform_gInstanceData Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_InstanceData_0 = OpTypePointer Uniform %InstanceData_0
+%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Function_V2F = OpTypePointer Function %V2F
+    %float_1 = OpConstant %float 1
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+     %PosL_1 = OpVariable %_ptr_Input_v3float Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%instanceID_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput_Position = OpVariable %_ptr_Output_v4float Output
+%_entryPointOutput_Color = OpVariable %_ptr_Output_v4float Output
+         %VS = OpFunction %void None %3
+          %5 = OpLabel
+     %PosL_0 = OpVariable %_ptr_Function_v3float Function
+%instanceID_0 = OpVariable %_ptr_Function_uint Function
+%flattenTemp = OpVariable %_ptr_Function_V2F Function
+      %param = OpVariable %_ptr_Function_v3float Function
+    %param_0 = OpVariable %_ptr_Function_uint Function
+         %61 = OpLoad %v3float %PosL_1
+               OpStore %PosL_0 %61
+         %65 = OpLoad %uint %instanceID_1
+               OpStore %instanceID_0 %65
+         %68 = OpLoad %v3float %PosL_0
+               OpStore %param %68
+         %70 = OpLoad %uint %instanceID_0
+               OpStore %param_0 %70
+         %71 = OpFunctionCall %V2F %_VS_vf3_u1_ %param %param_0
+               OpStore %flattenTemp %71
+         %74 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_0
+         %75 = OpLoad %v4float %74
+               OpStore %_entryPointOutput_Position %75
+         %77 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_1
+         %78 = OpLoad %v4float %77
+               OpStore %_entryPointOutput_Color %78
+               OpReturn
+               OpFunctionEnd
+%_VS_vf3_u1_ = OpFunction %V2F None %13
+       %PosL = OpFunctionParameter %_ptr_Function_v3float
+ %instanceID = OpFunctionParameter %_ptr_Function_uint
+         %17 = OpLabel
+   %instData = OpVariable %_ptr_Function_InstanceData Function
+        %v2f = OpVariable %_ptr_Function_V2F Function
+         %29 = OpLoad %uint %instanceID
+         %31 = OpAccessChain %_ptr_Uniform_InstanceData_0 %gInstanceData_0 %int_0 %29
+         %32 = OpLoad %InstanceData_0 %31
+         %33 = OpCompositeExtract %mat4v4float %32 0
+         %35 = OpAccessChain %_ptr_Function_mat4v4float %instData %int_0
+               OpStore %35 %33
+         %36 = OpCompositeExtract %v4float %32 1
+         %39 = OpAccessChain %_ptr_Function_v4float %instData %int_1
+               OpStore %39 %36
+         %42 = OpAccessChain %_ptr_Function_mat4v4float %instData %int_0
+         %43 = OpLoad %mat4v4float %42
+         %44 = OpLoad %v3float %PosL
+         %46 = OpCompositeExtract %float %44 0
+         %47 = OpCompositeExtract %float %44 1
+         %48 = OpCompositeExtract %float %44 2
+         %49 = OpCompositeConstruct %v4float %46 %47 %48 %float_1
+         %50 = OpMatrixTimesVector %v4float %43 %49
+         %51 = OpAccessChain %_ptr_Function_v4float %v2f %int_0
+               OpStore %51 %50
+         %52 = OpAccessChain %_ptr_Function_v4float %instData %int_1
+         %53 = OpLoad %v4float %52
+         %54 = OpAccessChain %_ptr_Function_v4float %v2f %int_1
+               OpStore %54 %53
+         %55 = OpLoad %V2F %v2f
+               OpReturnValue %55
+               OpFunctionEnd

+ 3 - 2
3rdparty/spirv-cross/spirv_common.hpp

@@ -417,7 +417,8 @@ struct SPIRType : IVariant
 		Struct,
 		Image,
 		SampledImage,
-		Sampler
+		Sampler,
+		ControlPointArray
 	};
 
 	// Scalar/vector/matrix support.
@@ -1381,7 +1382,7 @@ struct Meta
 		{
 			uint32_t packed_type = 0;
 			bool packed = false;
-			uint32_t ib_member_index = -1;
+			uint32_t ib_member_index = static_cast<uint32_t>(-1);
 			uint32_t ib_orig_id = 0;
 		} extended;
 	};

+ 72 - 2
3rdparty/spirv-cross/spirv_cross.cpp

@@ -2017,6 +2017,16 @@ ExecutionModel Compiler::get_execution_model() const
 	return execution.model;
 }
 
+bool Compiler::is_tessellation_shader(ExecutionModel model)
+{
+	return model == ExecutionModelTessellationControl || model == ExecutionModelTessellationEvaluation;
+}
+
+bool Compiler::is_tessellation_shader() const
+{
+	return is_tessellation_shader(get_execution_model());
+}
+
 void Compiler::set_remapped_variable_state(uint32_t id, bool remap_enable)
 {
 	get<SPIRVariable>(id).remapped_variable = remap_enable;
@@ -3043,7 +3053,7 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
 	}
 
 	case OpArrayLength:
-		// Uses literals, but cannot be a phi variable, so ignore.
+		// Uses literals, but cannot be a phi variable or temporary, so ignore.
 		break;
 
 		// Atomics shouldn't be able to access function-local variables.
@@ -3062,6 +3072,55 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
 			notify_variable_access(args[i], current_block->self);
 		break;
 
+	case OpImageWrite:
+		for (uint32_t i = 0; i < length; i++)
+		{
+			// Argument 3 is a literal.
+			if (i != 3)
+				notify_variable_access(args[i], current_block->self);
+		}
+		break;
+
+	case OpImageSampleImplicitLod:
+	case OpImageSampleExplicitLod:
+	case OpImageSparseSampleImplicitLod:
+	case OpImageSparseSampleExplicitLod:
+	case OpImageSampleProjImplicitLod:
+	case OpImageSampleProjExplicitLod:
+	case OpImageSparseSampleProjImplicitLod:
+	case OpImageSparseSampleProjExplicitLod:
+	case OpImageFetch:
+	case OpImageSparseFetch:
+	case OpImageRead:
+	case OpImageSparseRead:
+		for (uint32_t i = 1; i < length; i++)
+		{
+			// Argument 4 is a literal.
+			if (i != 4)
+				notify_variable_access(args[i], current_block->self);
+		}
+		break;
+
+	case OpImageSampleDrefImplicitLod:
+	case OpImageSampleDrefExplicitLod:
+	case OpImageSparseSampleDrefImplicitLod:
+	case OpImageSparseSampleDrefExplicitLod:
+	case OpImageSampleProjDrefImplicitLod:
+	case OpImageSampleProjDrefExplicitLod:
+	case OpImageSparseSampleProjDrefImplicitLod:
+	case OpImageSparseSampleProjDrefExplicitLod:
+	case OpImageGather:
+	case OpImageSparseGather:
+	case OpImageDrefGather:
+	case OpImageSparseDrefGather:
+		for (uint32_t i = 1; i < length; i++)
+		{
+			// Argument 5 is a literal.
+			if (i != 5)
+				notify_variable_access(args[i], current_block->self);
+		}
+		break;
+
 	default:
 	{
 		// Rather dirty way of figuring out where Phi variables are used.
@@ -3300,6 +3359,11 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeA
 			continue;
 		}
 
+		// There is no point in doing domination analysis for opaque types.
+		auto &type = get<SPIRType>(itr->second);
+		if (type_is_opaque_value(type))
+			continue;
+
 		DominatorBuilder builder(cfg);
 		bool force_temporary = false;
 
@@ -3986,7 +4050,7 @@ bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &resul
 		return false;
 
 	default:
-		if (length > 1)
+		if (length > 1 && maybe_get<SPIRType>(args[0]) != nullptr)
 		{
 			result_type = args[0];
 			result_id = args[1];
@@ -4055,3 +4119,9 @@ bool Compiler::image_is_comparison(const spirv_cross::SPIRType &type, uint32_t i
 {
 	return type.image.depth || (comparison_ids.count(id) != 0);
 }
+
+bool Compiler::type_is_opaque_value(const spirv_cross::SPIRType &type) const
+{
+	return !type.pointer && (type.basetype == SPIRType::SampledImage || type.basetype == SPIRType::Image ||
+	                         type.basetype == SPIRType::Sampler);
+}

+ 7 - 1
3rdparty/spirv-cross/spirv_cross.hpp

@@ -360,6 +360,8 @@ public:
 	uint32_t get_execution_mode_argument(spv::ExecutionMode mode, uint32_t index = 0) const;
 	spv::ExecutionModel get_execution_model() const;
 
+	bool is_tessellation_shader() const;
+
 	// In SPIR-V, the compute work group size can be represented by a constant vector, in which case
 	// the LocalSize execution mode is ignored.
 	//
@@ -563,7 +565,9 @@ protected:
 	template <typename T>
 	T *maybe_get(uint32_t id)
 	{
-		if (ir.ids[id].get_type() == static_cast<Types>(T::type))
+		if (id >= ir.ids.size())
+			return nullptr;
+		else if (ir.ids[id].get_type() == static_cast<Types>(T::type))
 			return &get<T>(id);
 		else
 			return nullptr;
@@ -613,6 +617,7 @@ protected:
 
 	const SPIREntryPoint &get_entry_point() const;
 	SPIREntryPoint &get_entry_point();
+	static bool is_tessellation_shader(spv::ExecutionModel model);
 
 	virtual std::string to_name(uint32_t id, bool allow_alias = true) const;
 	bool is_builtin_variable(const SPIRVariable &var) const;
@@ -979,6 +984,7 @@ private:
 
 	void fixup_type_alias();
 	bool type_is_block_like(const SPIRType &type) const;
+	bool type_is_opaque_value(const SPIRType &type) const;
 };
 } // namespace spirv_cross
 

+ 64 - 41
3rdparty/spirv-cross/spirv_glsl.cpp

@@ -2961,51 +2961,31 @@ string CompilerGLSL::convert_half_to_string(const SPIRConstant &c, uint32_t col,
 	string res;
 	float float_value = c.scalar_f16(col, row);
 
+	// There is no literal "hf" in GL_NV_gpu_shader5, so to avoid lots
+	// of complicated workarounds, just value-cast to the half type always.
 	if (std::isnan(float_value) || std::isinf(float_value))
 	{
-		if (backend.half_literal_suffix)
-		{
-			// There is no uintBitsToFloat for 16-bit, so have to rely on legacy fallback here.
-			if (float_value == numeric_limits<float>::infinity())
-				res = join("(1.0", backend.half_literal_suffix, " / 0.0", backend.half_literal_suffix, ")");
-			else if (float_value == -numeric_limits<float>::infinity())
-				res = join("(-1.0", backend.half_literal_suffix, " / 0.0", backend.half_literal_suffix, ")");
-			else if (std::isnan(float_value))
-				res = join("(0.0", backend.half_literal_suffix, " / 0.0", backend.half_literal_suffix, ")");
-			else
-				SPIRV_CROSS_THROW("Cannot represent non-finite floating point constant.");
-		}
+		SPIRType type;
+		type.basetype = SPIRType::Half;
+		type.vecsize = 1;
+		type.columns = 1;
+
+		if (float_value == numeric_limits<float>::infinity())
+			res = join(type_to_glsl(type), "(1.0 / 0.0)");
+		else if (float_value == -numeric_limits<float>::infinity())
+			res = join(type_to_glsl(type), "(-1.0 / 0.0)");
+		else if (std::isnan(float_value))
+			res = join(type_to_glsl(type), "(0.0 / 0.0)");
 		else
-		{
-			SPIRType type;
-			type.basetype = SPIRType::Half;
-			type.vecsize = 1;
-			type.columns = 1;
-
-			if (float_value == numeric_limits<float>::infinity())
-				res = join(type_to_glsl(type), "(1.0 / 0.0)");
-			else if (float_value == -numeric_limits<float>::infinity())
-				res = join(type_to_glsl(type), "(-1.0 / 0.0)");
-			else if (std::isnan(float_value))
-				res = join(type_to_glsl(type), "(0.0 / 0.0)");
-			else
-				SPIRV_CROSS_THROW("Cannot represent non-finite floating point constant.");
-		}
+			SPIRV_CROSS_THROW("Cannot represent non-finite floating point constant.");
 	}
 	else
 	{
-		if (backend.half_literal_suffix)
-			res = convert_to_string(float_value) + backend.half_literal_suffix;
-		else
-		{
-			// In HLSL (FXC), it's important to cast the literals to half precision right away.
-			// There is no literal for it.
-			SPIRType type;
-			type.basetype = SPIRType::Half;
-			type.vecsize = 1;
-			type.columns = 1;
-			res = join(type_to_glsl(type), "(", convert_to_string(float_value), ")");
-		}
+		SPIRType type;
+		type.basetype = SPIRType::Half;
+		type.vecsize = 1;
+		type.columns = 1;
+		res = join(type_to_glsl(type), "(", convert_to_string(float_value), ")");
 	}
 
 	return res;
@@ -4150,6 +4130,29 @@ void CompilerGLSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_i
 	}
 }
 
+static inline bool image_opcode_is_sample_no_dref(Op op)
+{
+	switch (op)
+	{
+	case OpImageSampleExplicitLod:
+	case OpImageSampleImplicitLod:
+	case OpImageSampleProjExplicitLod:
+	case OpImageSampleProjImplicitLod:
+	case OpImageFetch:
+	case OpImageRead:
+	case OpImageSparseSampleExplicitLod:
+	case OpImageSparseSampleImplicitLod:
+	case OpImageSparseSampleProjExplicitLod:
+	case OpImageSparseSampleProjImplicitLod:
+	case OpImageSparseFetch:
+	case OpImageSparseRead:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 void CompilerGLSL::emit_texture_op(const Instruction &i)
 {
 	auto *ops = stream(i);
@@ -4304,6 +4307,20 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
 	if (is_legacy() && image_is_comparison(imgtype, img))
 		expr += ".r";
 
+	// Sampling from a texture which was deduced to be a depth image, might actually return 1 component here.
+	// Remap back to 4 components as sampling opcodes expect.
+	bool image_is_depth;
+	const auto *combined = maybe_get<SPIRCombinedImageSampler>(img);
+	if (combined)
+		image_is_depth = image_is_comparison(imgtype, combined->image);
+	else
+		image_is_depth = image_is_comparison(imgtype, img);
+
+	if (image_is_depth && backend.comparison_image_samples_scalar && image_opcode_is_sample_no_dref(op))
+	{
+		expr = remap_swizzle(get<SPIRType>(result_type), 1, expr);
+	}
+
 	// Deals with reads from MSL. We might need to downconvert to fewer components.
 	if (op == OpImageRead)
 		expr = remap_swizzle(get<SPIRType>(result_type), 4, expr);
@@ -5671,6 +5688,12 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
 				append_index();
 			}
 
+			if (type->basetype == SPIRType::ControlPointArray)
+			{
+				type_id = type->parent_type;
+				type = &get<SPIRType>(type_id);
+			}
+
 			access_chain_is_arrayed = true;
 		}
 		// Arrays
@@ -8934,7 +8957,7 @@ bool CompilerGLSL::is_non_native_row_major_matrix(uint32_t id)
 		return false;
 
 	// Non-matrix or column-major matrix types do not need to be converted.
-	if (!ir.meta[id].decoration.decoration_flags.get(DecorationRowMajor))
+	if (!has_decoration(id, DecorationRowMajor))
 		return false;
 
 	// Only square row-major matrices can be converted at this time.
@@ -8955,7 +8978,7 @@ bool CompilerGLSL::member_is_non_native_row_major_matrix(const SPIRType &type, u
 		return false;
 
 	// Non-matrix or column-major matrix types do not need to be converted.
-	if (!combined_decoration_for_member(type, index).get(DecorationRowMajor))
+	if (!has_member_decoration(type.self, index, DecorationRowMajor))
 		return false;
 
 	// Only square row-major matrices can be converted at this time.

+ 1 - 1
3rdparty/spirv-cross/spirv_glsl.hpp

@@ -380,7 +380,6 @@ protected:
 		const char *basic_uint8_type = "uint8_t";
 		const char *basic_int16_type = "int16_t";
 		const char *basic_uint16_type = "uint16_t";
-		const char *half_literal_suffix = "hf";
 		const char *int16_t_literal_suffix = "s";
 		const char *uint16_t_literal_suffix = "us";
 		bool swizzle_is_function = false;
@@ -402,6 +401,7 @@ protected:
 		bool supports_extensions = false;
 		bool supports_empty_struct = false;
 		bool array_is_value_type = true;
+		bool comparison_image_samples_scalar = false;
 	} backend;
 
 	void emit_struct(SPIRType &type);

+ 0 - 1
3rdparty/spirv-cross/spirv_hlsl.cpp

@@ -4618,7 +4618,6 @@ string CompilerHLSL::compile()
 	options.vulkan_semantics = true;
 	backend.float_literal_suffix = true;
 	backend.double_literal_suffix = false;
-	backend.half_literal_suffix = nullptr;
 	backend.long_long_literal_suffix = true;
 	backend.uint32_t_literal_suffix = true;
 	backend.int16_t_literal_suffix = nullptr;

+ 383 - 114
3rdparty/spirv-cross/spirv_msl.cpp

@@ -36,7 +36,11 @@ CompilerMSL::CompilerMSL(vector<uint32_t> spirv_, vector<MSLVertexAttr> *p_vtx_a
 {
 	if (p_vtx_attrs)
 		for (auto &va : *p_vtx_attrs)
+		{
 			vtx_attrs_by_location[va.location] = &va;
+			if (va.builtin != BuiltInMax && !vtx_attrs_by_builtin.count(va.builtin))
+				vtx_attrs_by_builtin[va.builtin] = &va;
+		}
 
 	if (p_res_bindings)
 		for (auto &rb : *p_res_bindings)
@@ -49,7 +53,12 @@ CompilerMSL::CompilerMSL(const uint32_t *ir_, size_t word_count, MSLVertexAttr *
 {
 	if (p_vtx_attrs)
 		for (size_t i = 0; i < vtx_attrs_count; i++)
-			vtx_attrs_by_location[p_vtx_attrs[i].location] = &p_vtx_attrs[i];
+		{
+			auto &va = p_vtx_attrs[i];
+			vtx_attrs_by_location[va.location] = &va;
+			if (va.builtin != BuiltInMax && !vtx_attrs_by_builtin.count(va.builtin))
+				vtx_attrs_by_builtin[va.builtin] = &va;
+		}
 
 	if (p_res_bindings)
 		for (size_t i = 0; i < res_bindings_count; i++)
@@ -62,7 +71,12 @@ CompilerMSL::CompilerMSL(const ParsedIR &ir_, MSLVertexAttr *p_vtx_attrs, size_t
 {
 	if (p_vtx_attrs)
 		for (size_t i = 0; i < vtx_attrs_count; i++)
-			vtx_attrs_by_location[p_vtx_attrs[i].location] = &p_vtx_attrs[i];
+		{
+			auto &va = p_vtx_attrs[i];
+			vtx_attrs_by_location[va.location] = &va;
+			if (va.builtin != BuiltInMax && !vtx_attrs_by_builtin.count(va.builtin))
+				vtx_attrs_by_builtin[va.builtin] = &va;
+		}
 
 	if (p_res_bindings)
 		for (size_t i = 0; i < res_bindings_count; i++)
@@ -75,7 +89,12 @@ CompilerMSL::CompilerMSL(ParsedIR &&ir_, MSLVertexAttr *p_vtx_attrs, size_t vtx_
 {
 	if (p_vtx_attrs)
 		for (size_t i = 0; i < vtx_attrs_count; i++)
-			vtx_attrs_by_location[p_vtx_attrs[i].location] = &p_vtx_attrs[i];
+		{
+			auto &va = p_vtx_attrs[i];
+			vtx_attrs_by_location[va.location] = &va;
+			if (va.builtin != BuiltInMax && !vtx_attrs_by_builtin.count(va.builtin))
+				vtx_attrs_by_builtin[va.builtin] = &va;
+		}
 
 	if (p_res_bindings)
 		for (size_t i = 0; i < res_bindings_count; i++)
@@ -391,6 +410,12 @@ SPIRType &CompilerMSL::get_stage_out_struct_type()
 	return get_variable_data_type(so_var);
 }
 
+SPIRType &CompilerMSL::get_patch_stage_in_struct_type()
+{
+	auto &si_var = get<SPIRVariable>(patch_stage_in_var_id);
+	return get_variable_data_type(si_var);
+}
+
 SPIRType &CompilerMSL::get_patch_stage_out_struct_type()
 {
 	auto &so_var = get<SPIRVariable>(patch_stage_out_var_id);
@@ -558,7 +583,6 @@ string CompilerMSL::compile()
 	options.version = 450;
 	backend.null_pointer_literal = "nullptr";
 	backend.float_literal_suffix = false;
-	backend.half_literal_suffix = "h";
 	backend.uint32_t_literal_suffix = true;
 	backend.int16_t_literal_suffix = nullptr;
 	backend.uint16_t_literal_suffix = "u";
@@ -580,6 +604,7 @@ string CompilerMSL::compile()
 	backend.boolean_mix_support = false;
 	backend.allow_truncated_access_chain = true;
 	backend.array_is_value_type = false;
+	backend.comparison_image_samples_scalar = true;
 
 	capture_output_to_buffer = msl_options.capture_output_to_buffer;
 	is_rasterization_disabled = msl_options.disable_rasterization || capture_output_to_buffer;
@@ -609,12 +634,13 @@ string CompilerMSL::compile()
 	stage_out_var_id = add_interface_block(StorageClassOutput);
 	patch_stage_out_var_id = add_interface_block(StorageClassOutput, true);
 	stage_in_var_id = add_interface_block(StorageClassInput);
+	if (get_execution_model() == ExecutionModelTessellationEvaluation)
+		patch_stage_in_var_id = add_interface_block(StorageClassInput, true);
 
 	if (get_execution_model() == ExecutionModelTessellationControl)
-	{
 		stage_out_ptr_var_id = add_interface_block_pointer(stage_out_var_id, StorageClassOutput);
+	if (is_tessellation_shader())
 		stage_in_ptr_var_id = add_interface_block_pointer(stage_in_var_id, StorageClassInput);
-	}
 
 	// Metal vertex functions that define no output must disable rasterization and return void.
 	if (!stage_out_var_id)
@@ -662,7 +688,11 @@ string CompilerMSL::compile(vector<MSLVertexAttr> *p_vtx_attrs, vector<MSLResour
 	{
 		vtx_attrs_by_location.clear();
 		for (auto &va : *p_vtx_attrs)
+		{
 			vtx_attrs_by_location[va.location] = &va;
+			if (va.builtin != BuiltInMax && !vtx_attrs_by_builtin.count(va.builtin))
+				vtx_attrs_by_builtin[va.builtin] = &va;
+		}
 	}
 
 	if (p_res_bindings)
@@ -869,14 +899,15 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
 			auto *p_type = &get<SPIRType>(type_id);
 			BuiltIn bi_type = BuiltIn(get_decoration(arg_id, DecorationBuiltIn));
 
-			if (get_execution_model() == ExecutionModelTessellationControl &&
-			    (var.storage == StorageClassInput || var.storage == StorageClassOutput) &&
-			    !has_decoration(arg_id, DecorationPatch) &&
+			if (((is_tessellation_shader() && var.storage == StorageClassInput) ||
+			     (get_execution_model() == ExecutionModelTessellationControl && var.storage == StorageClassOutput)) &&
+			    !(has_decoration(arg_id, DecorationPatch) || is_patch_block(*p_type)) &&
 			    (!is_builtin_variable(var) || bi_type == BuiltInPosition || bi_type == BuiltInPointSize ||
 			     bi_type == BuiltInClipDistance || bi_type == BuiltInCullDistance ||
 			     p_type->basetype == SPIRType::Struct))
 			{
 				// Tessellation control shaders see inputs and per-vertex outputs as arrays.
+				// Similarly, tessellation evaluation shaders see per-vertex inputs as arrays.
 				// We collected them into a structure; we must pass the array of this
 				// structure to the function.
 				std::string name;
@@ -1003,8 +1034,8 @@ void CompilerMSL::mark_as_packable(SPIRType &type)
 void CompilerMSL::mark_location_as_used_by_shader(uint32_t location, StorageClass storage)
 {
 	MSLVertexAttr *p_va;
-	if ((get_execution_model() == ExecutionModelVertex || get_execution_model() == ExecutionModelTessellationControl) &&
-	    (storage == StorageClassInput) && (p_va = vtx_attrs_by_location[location]))
+	if ((get_execution_model() == ExecutionModelVertex || is_tessellation_shader()) && (storage == StorageClassInput) &&
+	    (p_va = vtx_attrs_by_location[location]))
 		p_va->used_by_shader = true;
 }
 
@@ -1086,7 +1117,7 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
 			statement(qual_var_name, " = ", remap_swizzle(padded_type, type_components, to_name(var.self)), ";");
 		});
 	}
-	else
+	else if (!strip_array)
 		ir.meta[var.self].decoration.qualified_alias = qual_var_name;
 
 	if (var.storage == StorageClassOutput && var.initializer != 0)
@@ -1099,8 +1130,7 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
 	if (get_decoration_bitset(var.self).get(DecorationLocation))
 	{
 		uint32_t locn = get_decoration(var.self, DecorationLocation);
-		if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex ||
-		                                     get_execution_model() == ExecutionModelTessellationControl))
+		if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex || is_tessellation_shader()))
 		{
 			type_id = ensure_correct_attribute_type(var.basetype, locn);
 			var.basetype = type_id;
@@ -1112,6 +1142,12 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
 		set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
 		mark_location_as_used_by_shader(locn, storage);
 	}
+	else if (is_builtin && is_tessellation_shader() && vtx_attrs_by_builtin.count(builtin))
+	{
+		uint32_t locn = vtx_attrs_by_builtin[builtin]->location;
+		set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
+		mark_location_as_used_by_shader(locn, storage);
+	}
 
 	if (get_decoration_bitset(var.self).get(DecorationComponent))
 	{
@@ -1168,6 +1204,8 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 		elem_cnt = to_array_size_literal(var_type);
 	}
 
+	bool is_builtin = is_builtin_variable(var);
+	BuiltIn builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn));
 	bool is_flat = has_decoration(var.self, DecorationFlat);
 	bool is_noperspective = has_decoration(var.self, DecorationNoPerspective);
 	bool is_centroid = has_decoration(var.self, DecorationCentroid);
@@ -1179,6 +1217,10 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 	while (is_array(*usable_type) || is_matrix(*usable_type))
 		usable_type = &get<SPIRType>(usable_type->parent_type);
 
+	// If a builtin, force it to have the proper name.
+	if (is_builtin)
+		set_name(var.self, builtin_to_glsl(builtin, StorageClassFunction));
+
 	entry_func.add_local_variable(var.self);
 
 	// We need to declare the variable early and at entry-point scope.
@@ -1217,8 +1259,8 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 		if (get_decoration_bitset(var.self).get(DecorationLocation))
 		{
 			uint32_t locn = get_decoration(var.self, DecorationLocation) + i;
-			if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex ||
-			                                     get_execution_model() == ExecutionModelTessellationControl))
+			if (storage == StorageClassInput &&
+			    (get_execution_model() == ExecutionModelVertex || is_tessellation_shader()))
 			{
 				var.basetype = ensure_correct_attribute_type(var.basetype, locn);
 				uint32_t mbr_type_id = ensure_correct_attribute_type(usable_type->self, locn);
@@ -1227,6 +1269,12 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 			set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
 			mark_location_as_used_by_shader(locn, storage);
 		}
+		else if (is_builtin && is_tessellation_shader() && vtx_attrs_by_builtin.count(builtin))
+		{
+			uint32_t locn = vtx_attrs_by_builtin[builtin]->location + i;
+			set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
+			mark_location_as_used_by_shader(locn, storage);
+		}
 
 		if (get_decoration_bitset(var.self).get(DecorationIndex))
 		{
@@ -1246,29 +1294,33 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 
 		set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
 
-		switch (storage)
+		if (!strip_array)
 		{
-		case StorageClassInput:
-			entry_func.fixup_hooks_in.push_back(
-			    [=, &var]() { statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, ";"); });
-			break;
+			switch (storage)
+			{
+			case StorageClassInput:
+				entry_func.fixup_hooks_in.push_back(
+				    [=, &var]() { statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, ";"); });
+				break;
 
-		case StorageClassOutput:
-			entry_func.fixup_hooks_out.push_back([=, &var]() {
-				if (padded_output)
-				{
-					auto &padded_type = this->get<SPIRType>(type_id);
-					statement(ib_var_ref, ".", mbr_name, " = ",
-					          remap_swizzle(padded_type, usable_type->vecsize, join(to_name(var.self), "[", i, "]")),
-					          ";");
-				}
-				else
-					statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), "[", i, "];");
-			});
-			break;
+			case StorageClassOutput:
+				entry_func.fixup_hooks_out.push_back([=, &var]() {
+					if (padded_output)
+					{
+						auto &padded_type = this->get<SPIRType>(type_id);
+						statement(
+						    ib_var_ref, ".", mbr_name, " = ",
+						    remap_swizzle(padded_type, usable_type->vecsize, join(to_name(var.self), "[", i, "]")),
+						    ";");
+					}
+					else
+						statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), "[", i, "];");
+				});
+				break;
 
-		default:
-			break;
+			default:
+				break;
+			}
 		}
 	}
 }
@@ -1308,6 +1360,8 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
 	auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
 	auto &var_type = strip_array ? get_variable_element_type(var) : get_variable_data_type(var);
 
+	BuiltIn builtin;
+	bool is_builtin = is_member_builtin(var_type, mbr_idx, &builtin);
 	bool is_flat =
 	    has_member_decoration(var_type.self, mbr_idx, DecorationFlat) || has_decoration(var.self, DecorationFlat);
 	bool is_noperspective = has_member_decoration(var_type.self, mbr_idx, DecorationNoPerspective) ||
@@ -1364,6 +1418,12 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
 			set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
 			mark_location_as_used_by_shader(locn, storage);
 		}
+		else if (is_builtin && is_tessellation_shader() && vtx_attrs_by_builtin.count(builtin))
+		{
+			uint32_t locn = vtx_attrs_by_builtin[builtin]->location + i;
+			set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
+			mark_location_as_used_by_shader(locn, storage);
+		}
 
 		if (has_member_decoration(var_type.self, mbr_idx, DecorationComponent))
 			SPIRV_CROSS_THROW("DecorationComponent on matrices and arrays make little sense.");
@@ -1382,24 +1442,27 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
 		set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, mbr_idx);
 
 		// Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate.
-		switch (storage)
+		if (!strip_array)
 		{
-		case StorageClassInput:
-			entry_func.fixup_hooks_in.push_back([=, &var, &var_type]() {
-				statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref, ".",
-				          mbr_name, ";");
-			});
-			break;
+			switch (storage)
+			{
+			case StorageClassInput:
+				entry_func.fixup_hooks_in.push_back([=, &var, &var_type]() {
+					statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref,
+					          ".", mbr_name, ";");
+				});
+				break;
 
-		case StorageClassOutput:
-			entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() {
-				statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), ".", to_member_name(var_type, mbr_idx),
-				          "[", i, "];");
-			});
-			break;
+			case StorageClassOutput:
+				entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() {
+					statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), ".",
+					          to_member_name(var_type, mbr_idx), "[", i, "];");
+				});
+				break;
 
-		default:
-			break;
+			default:
+				break;
+			}
 		}
 	}
 }
@@ -1436,13 +1499,13 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
 	// Update the original variable reference to include the structure reference
 	string qual_var_name = ib_var_ref + "." + mbr_name;
 
-	if (is_builtin || get_execution_model() == ExecutionModelTessellationControl)
+	if (is_builtin && !strip_array)
 	{
 		// For the builtin gl_PerVertex, we cannot treat it as a block anyways,
 		// so redirect to qualified name.
 		set_member_qualified_name(var_type.self, mbr_idx, qual_var_name);
 	}
-	else
+	else if (!strip_array)
 	{
 		// Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate.
 		switch (storage)
@@ -1468,8 +1531,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
 	if (has_member_decoration(var_type.self, mbr_idx, DecorationLocation))
 	{
 		uint32_t locn = get_member_decoration(var_type.self, mbr_idx, DecorationLocation);
-		if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex ||
-		                                     get_execution_model() == ExecutionModelTessellationControl))
+		if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex || is_tessellation_shader()))
 		{
 			mbr_type_id = ensure_correct_attribute_type(mbr_type_id, locn);
 			var_type.member_types[mbr_idx] = mbr_type_id;
@@ -1483,8 +1545,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
 		// The block itself might have a location and in this case, all members of the block
 		// receive incrementing locations.
 		uint32_t locn = get_accumulated_member_location(var, mbr_idx, strip_array);
-		if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex ||
-		                                     get_execution_model() == ExecutionModelTessellationControl))
+		if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex || is_tessellation_shader()))
 		{
 			mbr_type_id = ensure_correct_attribute_type(mbr_type_id, locn);
 			var_type.member_types[mbr_idx] = mbr_type_id;
@@ -1493,6 +1554,12 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
 		set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
 		mark_location_as_used_by_shader(locn, storage);
 	}
+	else if (is_builtin && is_tessellation_shader() && vtx_attrs_by_builtin.count(builtin))
+	{
+		uint32_t locn = vtx_attrs_by_builtin[builtin]->location;
+		set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
+		mark_location_as_used_by_shader(locn, storage);
+	}
 
 	// Copy the component location, if present.
 	if (has_member_decoration(var_type.self, mbr_idx, DecorationComponent))
@@ -1566,7 +1633,9 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
 
 				if (!is_builtin || has_active_builtin(builtin, storage))
 				{
-					if (!is_builtin && (storage == StorageClassInput || storage == StorageClassOutput) &&
+					if ((!is_builtin ||
+					     (storage == StorageClassInput && get_execution_model() != ExecutionModelFragment)) &&
+					    (storage == StorageClassInput || storage == StorageClassOutput) &&
 					    (is_matrix(mbr_type) || is_array(mbr_type)))
 					{
 						add_composite_member_variable_to_interface_block(storage, ib_var_ref, ib_type, var, mbr_idx,
@@ -1590,7 +1659,7 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
 		if (!is_builtin || has_active_builtin(builtin, storage))
 		{
 			// MSL does not allow matrices or arrays in input or output variables, so need to handle it specially.
-			if (!is_builtin &&
+			if ((!is_builtin || (storage == StorageClassInput && get_execution_model() != ExecutionModelFragment)) &&
 			    (storage == StorageClassInput || (storage == StorageClassOutput && !capture_output_to_buffer)) &&
 			    (is_matrix(var_type) || is_array(var_type)))
 			{
@@ -1608,8 +1677,9 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
 // for per-vertex variables in a tessellation control shader.
 void CompilerMSL::fix_up_interface_member_indices(StorageClass storage, uint32_t ib_type_id)
 {
-	// Only needed for tessellation control shaders.
-	if (get_execution_model() != ExecutionModelTessellationControl)
+	// Only needed for tessellation shaders.
+	if (get_execution_model() != ExecutionModelTessellationControl &&
+	    !(get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput))
 		return;
 
 	bool in_array = false;
@@ -1672,24 +1742,28 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
 {
 	// Accumulate the variables that should appear in the interface struct
 	vector<SPIRVariable *> vars;
-	bool incl_builtins = (storage == StorageClassOutput || get_execution_model() == ExecutionModelTessellationControl);
+	bool incl_builtins = (storage == StorageClassOutput || is_tessellation_shader());
 
 	ir.for_each_typed_id<SPIRVariable>([&](uint32_t var_id, SPIRVariable &var) {
 		auto &type = this->get<SPIRType>(var.basetype);
 		BuiltIn bi_type = BuiltIn(get_decoration(var_id, DecorationBuiltIn));
 		if (var.storage == storage && interface_variable_exists_in_entry_point(var.self) &&
 		    !is_hidden_variable(var, incl_builtins) && type.pointer &&
-		    has_decoration(var_id, DecorationPatch) == patch &&
+		    (has_decoration(var_id, DecorationPatch) || is_patch_block(type)) == patch &&
 		    (!is_builtin_variable(var) || bi_type == BuiltInPosition || bi_type == BuiltInPointSize ||
 		     bi_type == BuiltInClipDistance || bi_type == BuiltInCullDistance || bi_type == BuiltInLayer ||
-		     bi_type == BuiltInViewportIndex || bi_type == BuiltInFragDepth || bi_type == BuiltInSampleMask))
+		     bi_type == BuiltInViewportIndex || bi_type == BuiltInFragDepth || bi_type == BuiltInSampleMask ||
+		     (get_execution_model() == ExecutionModelTessellationEvaluation &&
+		      (bi_type == BuiltInTessLevelOuter || bi_type == BuiltInTessLevelInner))))
 		{
 			vars.push_back(&var);
 		}
 	});
 
-	// If no variables qualify, leave
-	if (vars.empty())
+	// If no variables qualify, leave.
+	// For patch input in a tessellation evaluation shader, the per-vertex stage inputs
+	// are included in a special patch control point array.
+	if (vars.empty() && !(storage == StorageClassInput && patch && stage_in_var_id))
 		return 0;
 
 	// Add a new typed variable for this interface structure.
@@ -1711,7 +1785,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
 	switch (storage)
 	{
 	case StorageClassInput:
-		ib_var_ref = stage_in_var_name;
+		ib_var_ref = patch ? patch_stage_in_var_name : stage_in_var_name;
 		if (get_execution_model() == ExecutionModelTessellationControl)
 		{
 			// Add a hook to populate the shared workgroup memory containing
@@ -1752,6 +1826,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
 			switch (get_execution_model())
 			{
 			case ExecutionModelVertex:
+			case ExecutionModelTessellationEvaluation:
 				// 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
@@ -1798,7 +1873,10 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
 
 	for (auto p_var : vars)
 	{
-		bool strip_array = get_execution_model() == ExecutionModelTessellationControl && !patch;
+		bool strip_array =
+		    (get_execution_model() == ExecutionModelTessellationControl ||
+		     (get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput)) &&
+		    !patch;
 		add_variable_to_interface_block(storage, ib_var_ref, ib_type, *p_var, strip_array);
 	}
 
@@ -1811,6 +1889,21 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
 	if (!patch)
 		fix_up_interface_member_indices(storage, ib_type_id);
 
+	// For patch inputs, add one more member, holding the array of control point data.
+	if (get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput && patch &&
+	    stage_in_var_id)
+	{
+		uint32_t pcp_type_id = ir.increase_bound_by(1);
+		auto &pcp_type = set<SPIRType>(pcp_type_id, ib_type);
+		pcp_type.basetype = SPIRType::ControlPointArray;
+		pcp_type.parent_type = pcp_type.type_alias = get_stage_in_struct_type().self;
+		pcp_type.storage = storage;
+		ir.meta[pcp_type_id] = ir.meta[ib_type.self];
+		uint32_t mbr_idx = uint32_t(ib_type.member_types.size());
+		ib_type.member_types.push_back(pcp_type_id);
+		set_member_name(ib_type.self, mbr_idx, "gl_in");
+	}
+
 	return ib_var_id;
 }
 
@@ -1819,28 +1912,52 @@ uint32_t CompilerMSL::add_interface_block_pointer(uint32_t ib_var_id, StorageCla
 	if (!ib_var_id)
 		return 0;
 
-	// Tessellation control per-vertex I/O is presented as an array, so we must
-	// do the same with our struct here.
+	uint32_t ib_ptr_var_id;
 	uint32_t next_id = ir.increase_bound_by(3);
-	uint32_t ib_ptr_type_id = next_id++;
 	auto &ib_type = expression_type(ib_var_id);
-	auto &ib_ptr_type = set<SPIRType>(ib_ptr_type_id, ib_type);
-	ib_ptr_type.parent_type = ib_ptr_type.type_alias = ib_type.self;
-	ib_ptr_type.pointer = true;
-	ib_ptr_type.storage = storage == StorageClassInput ? StorageClassWorkgroup : StorageClassStorageBuffer;
-	ir.meta[ib_ptr_type_id] = ir.meta[ib_type.self];
-	// To ensure that get_variable_data_type() doesn't strip off the pointer,
-	// which we need, use another pointer.
-	uint32_t ib_ptr_ptr_type_id = next_id++;
-	auto &ib_ptr_ptr_type = set<SPIRType>(ib_ptr_ptr_type_id, ib_ptr_type);
-	ib_ptr_ptr_type.parent_type = ib_ptr_type_id;
-	ib_ptr_ptr_type.type_alias = ib_type.self;
-	ib_ptr_ptr_type.storage = StorageClassFunction;
-	ir.meta[ib_ptr_ptr_type_id] = ir.meta[ib_type.self];
-
-	uint32_t ib_ptr_var_id = next_id;
-	set<SPIRVariable>(ib_ptr_var_id, ib_ptr_ptr_type_id, StorageClassFunction, 0);
-	set_name(ib_ptr_var_id, storage == StorageClassInput ? input_wg_var_name : "gl_out");
+	if (get_execution_model() == ExecutionModelTessellationControl)
+	{
+		// Tessellation control per-vertex I/O is presented as an array, so we must
+		// do the same with our struct here.
+		uint32_t ib_ptr_type_id = next_id++;
+		auto &ib_ptr_type = set<SPIRType>(ib_ptr_type_id, ib_type);
+		ib_ptr_type.parent_type = ib_ptr_type.type_alias = ib_type.self;
+		ib_ptr_type.pointer = true;
+		ib_ptr_type.storage = storage == StorageClassInput ? StorageClassWorkgroup : StorageClassStorageBuffer;
+		ir.meta[ib_ptr_type_id] = ir.meta[ib_type.self];
+		// To ensure that get_variable_data_type() doesn't strip off the pointer,
+		// which we need, use another pointer.
+		uint32_t ib_ptr_ptr_type_id = next_id++;
+		auto &ib_ptr_ptr_type = set<SPIRType>(ib_ptr_ptr_type_id, ib_ptr_type);
+		ib_ptr_ptr_type.parent_type = ib_ptr_type_id;
+		ib_ptr_ptr_type.type_alias = ib_type.self;
+		ib_ptr_ptr_type.storage = StorageClassFunction;
+		ir.meta[ib_ptr_ptr_type_id] = ir.meta[ib_type.self];
+
+		ib_ptr_var_id = next_id;
+		set<SPIRVariable>(ib_ptr_var_id, ib_ptr_ptr_type_id, StorageClassFunction, 0);
+		set_name(ib_ptr_var_id, storage == StorageClassInput ? input_wg_var_name : "gl_out");
+	}
+	else
+	{
+		// Tessellation evaluation per-vertex inputs are also presented as arrays.
+		// But, in Metal, this array uses a very special type, 'patch_control_point<T>',
+		// which is a container that can be used to access the control point data.
+		// To represent this, a special 'ControlPointArray' type has been added to the
+		// SPIRV-Cross type system. It should only be generated by and seen in the MSL
+		// backend (i.e. this one).
+		uint32_t pcp_type_id = next_id++;
+		auto &pcp_type = set<SPIRType>(pcp_type_id, ib_type);
+		pcp_type.basetype = SPIRType::ControlPointArray;
+		pcp_type.parent_type = pcp_type.type_alias = ib_type.self;
+		pcp_type.storage = storage;
+		ir.meta[pcp_type_id] = ir.meta[ib_type.self];
+
+		ib_ptr_var_id = next_id;
+		set<SPIRVariable>(ib_ptr_var_id, pcp_type_id, storage, 0);
+		set_name(ib_ptr_var_id, "gl_in");
+		ir.meta[ib_ptr_var_id].decoration.qualified_alias = join(patch_stage_in_var_name, ".gl_in");
+	}
 	return ib_ptr_var_id;
 }
 
@@ -2723,6 +2840,7 @@ void CompilerMSL::emit_resources()
 	emit_interface_block(stage_out_var_id);
 	emit_interface_block(patch_stage_out_var_id);
 	emit_interface_block(stage_in_var_id);
+	emit_interface_block(patch_stage_in_var_id);
 }
 
 // Emit declarations for the specialization Metal function constants
@@ -2822,6 +2940,8 @@ void CompilerMSL::emit_specialization_constants_and_structs()
 				is_declarable_struct = false;
 			if (stage_in_var_id && get_stage_in_struct_type().self == type_id)
 				is_declarable_struct = false;
+			if (patch_stage_in_var_id && get_patch_stage_in_struct_type().self == type_id)
+				is_declarable_struct = false;
 
 			// Align and emit declarable structs...but avoid declaring each more than once.
 			if (is_declarable_struct && declared_structs.count(type_id) == 0)
@@ -2859,13 +2979,15 @@ void CompilerMSL::emit_binary_unord_op(uint32_t result_type, uint32_t result_id,
 	inherit_expression_dependencies(result_id, op1);
 }
 
-bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, uint32_t length)
+bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t length)
 {
 	// If this is a per-vertex output, remap it to the I/O array buffer.
 	auto *var = maybe_get<SPIRVariable>(ops[2]);
 	BuiltIn bi_type = BuiltIn(get_decoration(ops[2], DecorationBuiltIn));
-	if (var && (var->storage == StorageClassInput || var->storage == StorageClassOutput) &&
-	    !has_decoration(ops[2], DecorationPatch) &&
+	if (var &&
+	    (var->storage == StorageClassInput ||
+	     (get_execution_model() == ExecutionModelTessellationControl && var->storage == StorageClassOutput)) &&
+	    !(has_decoration(ops[2], DecorationPatch) || is_patch_block(get_variable_data_type(*var))) &&
 	    (!is_builtin_variable(*var) || bi_type == BuiltInPosition || bi_type == BuiltInPointSize ||
 	     bi_type == BuiltInClipDistance || bi_type == BuiltInCullDistance ||
 	     get_variable_data_type(*var).basetype == SPIRType::Struct))
@@ -2934,7 +3056,8 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 							for (uint32_t k = 0; k < mbr_type.columns; k++, index++)
 							{
 								set<SPIRConstant>(const_mbr_id, type_id, index, false);
-								auto e = access_chain(ptr, indices.data(), indices.size(), mbr_type, nullptr, true);
+								auto e = access_chain(ptr, indices.data(), uint32_t(indices.size()), mbr_type, nullptr,
+								                      true);
 								statement(temp_name, ".", to_member_name(*type, j), "[", k, "] = ", e, ";");
 							}
 						}
@@ -2943,14 +3066,16 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 							for (uint32_t k = 0; k < mbr_type.array[0]; k++, index++)
 							{
 								set<SPIRConstant>(const_mbr_id, type_id, index, false);
-								auto e = access_chain(ptr, indices.data(), indices.size(), mbr_type, nullptr, true);
+								auto e = access_chain(ptr, indices.data(), uint32_t(indices.size()), mbr_type, nullptr,
+								                      true);
 								statement(temp_name, ".", to_member_name(*type, j), "[", k, "] = ", e, ";");
 							}
 						}
 						else
 						{
 							set<SPIRConstant>(const_mbr_id, type_id, index, false);
-							auto e = access_chain(ptr, indices.data(), indices.size(), mbr_type, nullptr, true);
+							auto e =
+							    access_chain(ptr, indices.data(), uint32_t(indices.size()), mbr_type, nullptr, true);
 							statement(temp_name, ".", to_member_name(*type, j), " = ", e, ";");
 						}
 					}
@@ -2960,7 +3085,7 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 					for (uint32_t j = 0; j < type->columns; j++, index++)
 					{
 						set<SPIRConstant>(const_mbr_id, type_id, index, false);
-						auto e = access_chain(ptr, indices.data(), indices.size(), *type, nullptr, true);
+						auto e = access_chain(ptr, indices.data(), uint32_t(indices.size()), *type, nullptr, true);
 						statement(temp_name, "[", j, "] = ", e, ";");
 					}
 				}
@@ -2970,7 +3095,7 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 					for (uint32_t j = 0; j < type->array[0]; j++, index++)
 					{
 						set<SPIRConstant>(const_mbr_id, type_id, index, false);
-						auto e = access_chain(ptr, indices.data(), indices.size(), *type, nullptr, true);
+						auto e = access_chain(ptr, indices.data(), uint32_t(indices.size()), *type, nullptr, true);
 						statement(temp_name, "[", j, "] = ", e, ";");
 					}
 				}
@@ -3006,7 +3131,7 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 
 		// We use the pointer to the base of the input/output array here,
 		// so this is always a pointer chain.
-		auto e = access_chain(ptr, indices.data(), indices.size(), get<SPIRType>(ops[0]), &meta, true);
+		auto e = access_chain(ptr, indices.data(), uint32_t(indices.size()), get<SPIRType>(ops[0]), &meta, true);
 		auto &expr = set<SPIRExpression>(ops[1], move(e), ops[0], should_forward(ops[2]));
 		expr.loaded_from = var->self;
 		expr.need_transpose = meta.need_transpose;
@@ -3033,10 +3158,15 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 	// drop the last index. It isn't an array in this case, so we can't have an
 	// array reference here. We need to make this ID a variable instead of an
 	// expression so we don't try to dereference it as a variable pointer.
+	// Don't do this if the index is a constant 1, though. We need to drop stores
+	// to that one.
 	auto *m = ir.find_meta(var ? var->self : 0);
-	if (var && m && m->decoration.builtin_type == BuiltInTessLevelInner &&
-	    get_entry_point().flags.get(ExecutionModeTriangles))
+	if (get_execution_model() == ExecutionModelTessellationControl && var && m &&
+	    m->decoration.builtin_type == BuiltInTessLevelInner && get_entry_point().flags.get(ExecutionModeTriangles))
 	{
+		auto *c = maybe_get<SPIRConstant>(ops[3]);
+		if (c && c->scalar() == 1)
+			return false;
 		auto &dest_var = set<SPIRVariable>(ops[1], *var);
 		dest_var.basetype = ops[0];
 		ir.meta[ops[1]] = ir.meta[ops[2]];
@@ -3047,6 +3177,33 @@ bool CompilerMSL::emit_tessellation_control_access_chain(const uint32_t *ops, ui
 	return false;
 }
 
+bool CompilerMSL::is_out_of_bounds_tessellation_level(uint32_t id_lhs)
+{
+	if (!get_entry_point().flags.get(ExecutionModeTriangles))
+		return false;
+
+	// In SPIR-V, TessLevelInner always has two elements and TessLevelOuter always has
+	// four. This is true even if we are tessellating triangles. This allows clients
+	// to use a single tessellation control shader with multiple tessellation evaluation
+	// shaders.
+	// In Metal, however, only the first element of TessLevelInner and the first three
+	// of TessLevelOuter are accessible. This stems from how in Metal, the tessellation
+	// levels must be stored to a dedicated buffer in a particular format that depends
+	// on the patch type. Therefore, in Triangles mode, any access to the second
+	// inner level or the fourth outer level must be dropped.
+	const auto *e = maybe_get<SPIRExpression>(id_lhs);
+	if (!e || !e->access_chain)
+		return false;
+	BuiltIn builtin = BuiltIn(get_decoration(e->loaded_from, DecorationBuiltIn));
+	if (builtin != BuiltInTessLevelInner && builtin != BuiltInTessLevelOuter)
+		return false;
+	auto *c = maybe_get<SPIRConstant>(e->implied_read_expressions[1]);
+	if (!c)
+		return false;
+	return (builtin == BuiltInTessLevelInner && c->scalar() == 1) ||
+	       (builtin == BuiltInTessLevelOuter && c->scalar() == 3);
+}
+
 // Override for MSL-specific syntax instructions
 void CompilerMSL::emit_instruction(const Instruction &instruction)
 {
@@ -3518,9 +3675,9 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
 	case OpInBoundsAccessChain:
 	case OpAccessChain:
 	case OpPtrAccessChain:
-		if (get_execution_model() == ExecutionModelTessellationControl)
+		if (is_tessellation_shader())
 		{
-			if (!emit_tessellation_control_access_chain(ops, instruction.length))
+			if (!emit_tessellation_access_chain(ops, instruction.length))
 				CompilerGLSL::emit_instruction(instruction);
 		}
 		else
@@ -3528,6 +3685,9 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
 		break;
 
 	case OpStore:
+		if (is_out_of_bounds_tessellation_level(ops[0]))
+			break;
+
 		if (maybe_emit_array_assignment(ops[0], ops[1]))
 			break;
 
@@ -4592,6 +4752,21 @@ string CompilerMSL::to_swizzle_expression(uint32_t id)
 	}
 }
 
+// Checks whether the type is a Block all of whose members have DecorationPatch.
+bool CompilerMSL::is_patch_block(const SPIRType &type)
+{
+	if (!has_decoration(type.self, DecorationBlock))
+		return false;
+
+	for (uint32_t i = 0; i < type.member_types.size(); i++)
+	{
+		if (!has_member_decoration(type.self, i, DecorationPatch))
+			return false;
+	}
+
+	return true;
+}
+
 // Checks whether the ID is a row_major matrix that requires conversion before use
 bool CompilerMSL::is_non_native_row_major_matrix(uint32_t id)
 {
@@ -4600,7 +4775,7 @@ bool CompilerMSL::is_non_native_row_major_matrix(uint32_t id)
 		return false;
 
 	// Non-matrix or column-major matrix types do not need to be converted.
-	if (!ir.meta[id].decoration.decoration_flags.get(DecorationRowMajor))
+	if (!has_decoration(id, DecorationRowMajor))
 		return false;
 
 	// Generate a function that will swap matrix elements from row-major to column-major.
@@ -4622,7 +4797,7 @@ bool CompilerMSL::member_is_non_native_row_major_matrix(const SPIRType &type, ui
 		return false;
 
 	// Non-matrix or column-major matrix types do not need to be converted.
-	if (!combined_decoration_for_member(type, index).get(DecorationRowMajor))
+	if (!has_member_decoration(type.self, index, DecorationRowMajor))
 		return false;
 
 	// Generate a function that will swap matrix elements from row-major to column-major.
@@ -4685,7 +4860,9 @@ string CompilerMSL::convert_row_major_matrix(string exp_str, const SPIRType &exp
 // Called automatically at the end of the entry point function
 void CompilerMSL::emit_fixup()
 {
-	if ((get_entry_point().model == ExecutionModelVertex) && stage_out_var_id && !qual_pos_var_name.empty())
+	if ((get_execution_model() == ExecutionModelVertex ||
+	     get_execution_model() == ExecutionModelTessellationEvaluation) &&
+	    stage_out_var_id && !qual_pos_var_name.empty() && !capture_output_to_buffer)
 	{
 		if (options.vertex.fixup_clipspace)
 			statement(qual_pos_var_name, ".z = (", qual_pos_var_name, ".z + ", qual_pos_var_name,
@@ -4792,8 +4969,9 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
 			return string(" [[attribute(") + convert_to_string(locn) + ")]]";
 	}
 
-	// Vertex function outputs
-	if (execution.model == ExecutionModelVertex && type.storage == StorageClassOutput)
+	// Vertex and tessellation evaluation function outputs
+	if ((execution.model == ExecutionModelVertex || execution.model == ExecutionModelTessellationEvaluation) &&
+	    type.storage == StorageClassOutput)
 	{
 		if (is_builtin)
 		{
@@ -4860,6 +5038,33 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
 		return "";
 	}
 
+	// Tessellation evaluation function inputs
+	if (execution.model == ExecutionModelTessellationEvaluation && type.storage == StorageClassInput)
+	{
+		if (is_builtin)
+		{
+			switch (builtin)
+			{
+			case BuiltInPrimitiveId:
+			case BuiltInTessCoord:
+				return string(" [[") + builtin_qualifier(builtin) + "]]";
+			case BuiltInPatchVertices:
+				return "";
+			// Others come from stage input.
+			default:
+				break;
+			}
+		}
+		// The special control point array must not be marked with an attribute.
+		if (get_type(type.member_types[index]).basetype == SPIRType::ControlPointArray)
+			return "";
+		uint32_t locn = get_ordered_member_location(type.self, index);
+		if (locn != k_unknown_location)
+			return string(" [[attribute(") + convert_to_string(locn) + ")]]";
+	}
+
+	// Tessellation evaluation function outputs were handled above.
+
 	// Fragment function inputs
 	if (execution.model == ExecutionModelFragment && type.storage == StorageClassInput)
 	{
@@ -5028,6 +5233,18 @@ string CompilerMSL::func_type_decl(SPIRType &type)
 	case ExecutionModelVertex:
 		entry_type = "vertex";
 		break;
+	case ExecutionModelTessellationEvaluation:
+		if (!msl_options.supports_msl_version(1, 2))
+			SPIRV_CROSS_THROW("Tessellation requires Metal 1.2.");
+		if (execution.flags.get(ExecutionModeIsolines))
+			SPIRV_CROSS_THROW("Metal does not support isoline tessellation.");
+		if (msl_options.is_ios())
+			entry_type =
+			    join("[[ patch(", execution.flags.get(ExecutionModeTriangles) ? "triangle" : "quad", ") ]] vertex");
+		else
+			entry_type = join("[[ patch(", execution.flags.get(ExecutionModeTriangles) ? "triangle" : "quad", ", ",
+			                  execution.output_vertices, ") ]] vertex");
+		break;
 	case ExecutionModelFragment:
 		entry_type =
 		    execution.flags.get(ExecutionModeEarlyFragmentTests) ? "[[ early_fragment_tests ]] fragment" : "fragment";
@@ -5152,9 +5369,15 @@ string CompilerMSL::entry_point_args(bool append_comma)
 	string ep_args;
 
 	// Stage-in structure
-	if (stage_in_var_id)
+	uint32_t stage_in_id;
+	if (get_execution_model() == ExecutionModelTessellationEvaluation)
+		stage_in_id = patch_stage_in_var_id;
+	else
+		stage_in_id = stage_in_var_id;
+
+	if (stage_in_id)
 	{
-		auto &var = get<SPIRVariable>(stage_in_var_id);
+		auto &var = get<SPIRVariable>(stage_in_id);
 		auto &type = get_variable_data_type(var);
 
 		if (!ep_args.empty())
@@ -5284,7 +5507,8 @@ string CompilerMSL::entry_point_args(bool append_comma)
 		// Don't emit SamplePosition as a separate parameter. In the entry
 		// point, we get that by calling get_sample_position() on the sample ID.
 		if (var.storage == StorageClassInput && is_builtin_variable(var) &&
-		    get_variable_data_type(var).basetype != SPIRType::Struct)
+		    get_variable_data_type(var).basetype != SPIRType::Struct &&
+		    get_variable_data_type(var).basetype != SPIRType::ControlPointArray)
 		{
 			if (bi_type != BuiltInSamplePosition && bi_type != BuiltInHelperInvocation &&
 			    bi_type != BuiltInPatchVertices && bi_type != BuiltInTessLevelInner &&
@@ -5413,9 +5637,24 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
 				});
 				break;
 			case BuiltInPatchVertices:
-				entry_func.fixup_hooks_in.push_back([=]() {
-					statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = spvIndirectParams[0];");
-				});
+				if (get_execution_model() == ExecutionModelTessellationEvaluation)
+					entry_func.fixup_hooks_in.push_back([=]() {
+						statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = ",
+						          to_expression(patch_stage_in_var_id), ".gl_in.size();");
+					});
+				else
+					entry_func.fixup_hooks_in.push_back([=]() {
+						statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = spvIndirectParams[0];");
+					});
+				break;
+			case BuiltInTessCoord:
+				// Emit a fixup to account for the shifted domain. Don't do this for triangles;
+				// MoltenVK will just reverse the winding order instead.
+				if (msl_options.tess_domain_origin_lower_left && !get_entry_point().flags.get(ExecutionModeTriangles))
+				{
+					string tc = to_expression(var_id);
+					entry_func.fixup_hooks_in.push_back([=]() { statement(tc, ".y = 1.0 - ", tc, ".y;"); });
+				}
 				break;
 			default:
 				break;
@@ -5982,6 +6221,9 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
 	case SPIRType::AtomicCounter:
 		return "atomic_uint";
 
+	case SPIRType::ControlPointArray:
+		return join("patch_control_point<", type_to_glsl(get<SPIRType>(type.parent_type), id), ">");
+
 	// Scalars
 	case SPIRType::Boolean:
 		type_name = "bool";
@@ -6263,7 +6505,7 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
 
 	// When used in the entry function, output builtins are qualified with output struct name.
 	// Test storage class as NOT Input, as output builtins might be part of generic type.
-	// Also don't do this for tessellation shaders.
+	// Also don't do this for tessellation control shaders.
 	case BuiltInViewportIndex:
 		if (!msl_options.supports_msl_version(2, 0))
 			SPIRV_CROSS_THROW("ViewportIndex requires Metal 2.0.");
@@ -6283,12 +6525,16 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
 		break;
 
 	case BuiltInTessLevelOuter:
+		if (get_execution_model() == ExecutionModelTessellationEvaluation)
+			break;
 		if (storage != StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
 			return join(tess_factor_buffer_var_name, "[", to_expression(builtin_primitive_id_id),
 			            "].edgeTessellationFactor");
 		break;
 
 	case BuiltInTessLevelInner:
+		if (get_execution_model() == ExecutionModelTessellationEvaluation)
+			break;
 		if (storage != StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
 			return join(tess_factor_buffer_var_name, "[", to_expression(builtin_primitive_id_id),
 			            "].insideTessellationFactor");
@@ -6345,7 +6591,15 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
 		// Shouldn't be reached.
 		SPIRV_CROSS_THROW("PatchVertices is derived from the auxiliary buffer in MSL.");
 	case BuiltInPrimitiveId:
-		return "threadgroup_position_in_grid";
+		switch (execution.model)
+		{
+		case ExecutionModelTessellationControl:
+			return "threadgroup_position_in_grid";
+		case ExecutionModelTessellationEvaluation:
+			return "patch_id";
+		default:
+			SPIRV_CROSS_THROW("PrimitiveId is not supported in this execution model.");
+		}
 
 	// Tess. control function out
 	case BuiltInTessLevelOuter:
@@ -6353,6 +6607,10 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
 		// Shouldn't be reached.
 		SPIRV_CROSS_THROW("Tessellation levels are handled specially in MSL.");
 
+	// Tess. evaluation function in
+	case BuiltInTessCoord:
+		return "position_in_patch";
+
 	// Fragment function in
 	case BuiltInFrontFacing:
 		return "front_facing";
@@ -6447,6 +6705,10 @@ string CompilerMSL::builtin_type_decl(BuiltIn builtin)
 	case BuiltInTessLevelOuter:
 		return "half";
 
+	// Tess. evaluation function in
+	case BuiltInTessCoord:
+		return get_entry_point().flags.get(ExecutionModeTriangles) ? "float3" : "float2";
+
 	// Fragment function in
 	case BuiltInFrontFacing:
 		return "bool";
@@ -6973,6 +7235,13 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
 
 	if (expected_type != expr_type.basetype)
 		expr = bitcast_expression(expr_type, expected_type, expr);
+
+	if (builtin == BuiltInTessCoord && get_entry_point().flags.get(ExecutionModeQuads) && expr_type.vecsize == 3)
+	{
+		// In SPIR-V, this is always a vec3, even for quads. In Metal, though, it's a float2 for quads.
+		// The code is expecting a float3, so we need to widen this.
+		expr = join("float3(", expr, ", 0)");
+	}
 }
 
 void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)

+ 11 - 2
3rdparty/spirv-cross/spirv_msl.hpp

@@ -48,6 +48,7 @@ struct MSLVertexAttr
 	uint32_t msl_stride = 0;
 	bool per_instance = false;
 	MSLVertexFormat format = MSL_VERTEX_FORMAT_OTHER;
+	spv::BuiltIn builtin = spv::BuiltInMax;
 	bool used_by_shader = false;
 };
 
@@ -177,6 +178,7 @@ public:
 		bool disable_rasterization = false;
 		bool capture_output_to_buffer = false;
 		bool swizzle_texture_samples = false;
+		bool tess_domain_origin_lower_left = false;
 
 		// Fragment output in MSL must have at least as many components as the render pass.
 		// Add support to explicit pad out components.
@@ -235,7 +237,8 @@ public:
 	bool get_is_rasterization_disabled() const
 	{
 		return is_rasterization_disabled && (get_entry_point().model == spv::ExecutionModelVertex ||
-		                                     get_entry_point().model == spv::ExecutionModelTessellationControl);
+		                                     get_entry_point().model == spv::ExecutionModelTessellationControl ||
+		                                     get_entry_point().model == spv::ExecutionModelTessellationEvaluation);
 	}
 
 	// Provide feedback to calling API to allow it to pass an auxiliary
@@ -388,6 +391,7 @@ protected:
 	void replace_illegal_names() override;
 	void declare_undefined_values() override;
 	void declare_constant_arrays();
+	bool is_patch_block(const SPIRType &type);
 	bool is_non_native_row_major_matrix(uint32_t id) override;
 	bool member_is_non_native_row_major_matrix(const SPIRType &type, uint32_t index) override;
 	std::string convert_row_major_matrix(std::string exp_str, const SPIRType &exp_type, bool is_packed) override;
@@ -456,6 +460,7 @@ protected:
 	std::string get_type_address_space(const SPIRType &type);
 	SPIRType &get_stage_in_struct_type();
 	SPIRType &get_stage_out_struct_type();
+	SPIRType &get_patch_stage_in_struct_type();
 	SPIRType &get_patch_stage_out_struct_type();
 	std::string get_tess_factor_struct_name();
 	void emit_atomic_func_op(uint32_t result_type, uint32_t result_id, const char *op, uint32_t mem_order_1,
@@ -484,11 +489,13 @@ protected:
 
 	void analyze_sampled_image_usage();
 
-	bool emit_tessellation_control_access_chain(const uint32_t *ops, uint32_t length);
+	bool emit_tessellation_access_chain(const uint32_t *ops, uint32_t length);
+	bool is_out_of_bounds_tessellation_level(uint32_t id_lhs);
 
 	Options msl_options;
 	std::set<SPVFuncImpl> spv_function_implementations;
 	std::unordered_map<uint32_t, MSLVertexAttr *> vtx_attrs_by_location;
+	std::unordered_map<uint32_t, MSLVertexAttr *> vtx_attrs_by_builtin;
 	std::unordered_map<uint32_t, uint32_t> fragment_output_components;
 	std::unordered_map<MSLStructMemberKey, uint32_t> struct_member_padding;
 	std::set<std::string> pragma_lines;
@@ -498,6 +505,7 @@ protected:
 	MSLResourceBinding next_metal_resource_index;
 	uint32_t stage_in_var_id = 0;
 	uint32_t stage_out_var_id = 0;
+	uint32_t patch_stage_in_var_id = 0;
 	uint32_t patch_stage_out_var_id = 0;
 	uint32_t stage_in_ptr_var_id = 0;
 	uint32_t stage_out_ptr_var_id = 0;
@@ -511,6 +519,7 @@ protected:
 	std::string qual_pos_var_name;
 	std::string stage_in_var_name = "in";
 	std::string stage_out_var_name = "out";
+	std::string patch_stage_in_var_name = "patchIn";
 	std::string patch_stage_out_var_name = "patchOut";
 	std::string sampler_name_suffix = "Smplr";
 	std::string swizzle_name_suffix = "Swzl";

+ 10 - 0
3rdparty/spirv-cross/spirv_reflect.cpp

@@ -391,6 +391,16 @@ void CompilerReflection::emit_entry_points()
 	auto entries = get_entry_points_and_stages();
 	if (!entries.empty())
 	{
+		// Needed to make output deterministic.
+		sort(begin(entries), end(entries), [](const EntryPoint &a, const EntryPoint &b) -> bool {
+			if (a.execution_model < b.execution_model)
+				return true;
+			else if (a.execution_model > b.execution_model)
+				return false;
+			else
+				return a.name < b.name;
+		});
+
 		json_stream->emit_json_key_array("entryPoints");
 		for (auto &e : entries)
 		{

+ 22 - 4
3rdparty/spirv-cross/test_shaders.py

@@ -135,8 +135,12 @@ def cross_compile_msl(shader, spirv, opt):
     spirv_path = create_temporary()
     msl_path = create_temporary(os.path.basename(shader))
 
+    spirv_cmd = ['spirv-as', '-o', spirv_path, shader]
+    if '.preserve.' in shader:
+        spirv_cmd.append('--preserve-numeric-ids')
+
     if spirv:
-        subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
+        subprocess.check_call(spirv_cmd)
     else:
         subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', '-o', spirv_path, shader])
 
@@ -156,6 +160,8 @@ def cross_compile_msl(shader, spirv, opt):
         msl_args.append('--msl-pad-fragment-output')
     if '.capture.' in shader:
         msl_args.append('--msl-capture-output')
+    if '.domain.' in shader:
+        msl_args.append('--msl-domain-lower-left')
 
     subprocess.check_call(msl_args)
 
@@ -229,8 +235,12 @@ def cross_compile_hlsl(shader, spirv, opt, force_no_external_validation):
     spirv_path = create_temporary()
     hlsl_path = create_temporary(os.path.basename(shader))
 
+    spirv_cmd = ['spirv-as', '-o', spirv_path, shader]
+    if '.preserve.' in shader:
+        spirv_cmd.append('--preserve-numeric-ids')
+
     if spirv:
-        subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
+        subprocess.check_call(spirv_cmd)
     else:
         subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', '-o', spirv_path, shader])
 
@@ -253,8 +263,12 @@ def cross_compile_reflect(shader, spirv, opt):
     spirv_path = create_temporary()
     reflect_path = create_temporary(os.path.basename(shader))
 
+    spirv_cmd = ['spirv-as', '-o', spirv_path, shader]
+    if '.preserve.' in shader:
+        spirv_cmd.append('--preserve-numeric-ids')
+
     if spirv:
-        subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
+        subprocess.check_call(spirv_cmd)
     else:
         subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', '-o', spirv_path, shader])
 
@@ -280,8 +294,12 @@ def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, fl
     if vulkan or spirv:
         vulkan_glsl_path = create_temporary('vk' + os.path.basename(shader))
 
+    spirv_cmd = ['spirv-as', '-o', spirv_path, shader]
+    if '.preserve.' in shader:
+        spirv_cmd.append('--preserve-numeric-ids')
+
     if spirv:
-        subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
+        subprocess.check_call(spirv_cmd)
     else:
         subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', '-o', spirv_path, shader])