Răsfoiți Sursa

Updated spirv-cross.

Бранимир Караџић 7 ani în urmă
părinte
comite
3c8b3c81ef
100 a modificat fișierele cu 2664 adăugiri și 1401 ștergeri
  1. 1 1
      3rdparty/spirv-cross/README.md
  2. 9 0
      3rdparty/spirv-cross/main.cpp
  3. 1 1
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/asm/vert/spec-constant-op-composite.asm.vert
  4. 9 9
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/comp/composite-array-initialization.comp
  5. 10 9
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/comp/spec-constant-op-member-array.comp
  6. 1 2
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/frag/constant-composites.frag
  7. 23 0
      3rdparty/spirv-cross/reference/opt/shaders-hlsl/frag/dual-source-blending.frag
  8. 5 5
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/specialization-constant-workgroup.asm.comp
  9. 5 5
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/storage-buffer-basic.invalid.asm.comp
  10. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/vector-builtin-type-cast-func.asm.comp
  11. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/vector-builtin-type-cast.asm.comp
  12. 5 5
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/frag/vector-shuffle-oom.asm.frag
  13. 1 1
      3rdparty/spirv-cross/reference/opt/shaders-msl/asm/vert/spec-constant-op-composite.asm.vert
  14. 11 11
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/composite-array-initialization.comp
  15. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/culling.comp
  16. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/packing-test-1.comp
  17. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/packing-test-2.comp
  18. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/shared-array-of-arrays.comp
  19. 2 2
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/shared.comp
  20. 9 7
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/spec-constant-op-member-array.comp
  21. 6 5
      3rdparty/spirv-cross/reference/opt/shaders-msl/comp/spec-constant-work-group-size.comp
  22. 1 17
      3rdparty/spirv-cross/reference/opt/shaders-msl/frag/constant-array.frag
  23. 1 17
      3rdparty/spirv-cross/reference/opt/shaders-msl/frag/constant-composites.frag
  24. 35 0
      3rdparty/spirv-cross/reference/opt/shaders-msl/frag/fragment-component-padding.pad-fragment.frag
  25. 5 5
      3rdparty/spirv-cross/reference/opt/shaders-msl/vert/resource-arrays-leaf.ios.vert
  26. 5 5
      3rdparty/spirv-cross/reference/opt/shaders-msl/vert/resource-arrays.ios.vert
  27. 1 1
      3rdparty/spirv-cross/reference/opt/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert
  28. 1 1
      3rdparty/spirv-cross/reference/opt/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert.vk
  29. 8 8
      3rdparty/spirv-cross/reference/opt/shaders/comp/composite-array-initialization.comp
  30. 5 5
      3rdparty/spirv-cross/reference/opt/shaders/frag/constant-array.frag
  31. 3 2
      3rdparty/spirv-cross/reference/opt/shaders/frag/constant-composites.frag
  32. 10 9
      3rdparty/spirv-cross/reference/opt/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp
  33. 4 3
      3rdparty/spirv-cross/reference/opt/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp.vk
  34. 48 0
      3rdparty/spirv-cross/reference/shaders-hlsl-no-opt/vert/pass-array-by-value.vert
  35. 5 5
      3rdparty/spirv-cross/reference/shaders-hlsl/asm/vert/spec-constant-op-composite.asm.vert
  36. 7 6
      3rdparty/spirv-cross/reference/shaders-hlsl/comp/composite-array-initialization.comp
  37. 10 9
      3rdparty/spirv-cross/reference/shaders-hlsl/comp/spec-constant-op-member-array.comp
  38. 23 0
      3rdparty/spirv-cross/reference/shaders-hlsl/frag/dual-source-blending.frag
  39. 49 39
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/asm/frag/texture-access.swizzle.asm.frag
  40. 34 28
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access-int.swizzle.frag
  41. 51 41
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access-leaf.swizzle.frag
  42. 34 28
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access-uint.swizzle.frag
  43. 49 39
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag
  44. 60 0
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/vert/pass-array-by-value.vert
  45. 207 0
      3rdparty/spirv-cross/reference/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag
  46. 5 5
      3rdparty/spirv-cross/reference/shaders-msl/asm/comp/specialization-constant-workgroup.asm.comp
  47. 5 5
      3rdparty/spirv-cross/reference/shaders-msl/asm/comp/storage-buffer-basic.invalid.asm.comp
  48. 2 2
      3rdparty/spirv-cross/reference/shaders-msl/asm/comp/vector-builtin-type-cast-func.asm.comp
  49. 2 2
      3rdparty/spirv-cross/reference/shaders-msl/asm/comp/vector-builtin-type-cast.asm.comp
  50. 4 4
      3rdparty/spirv-cross/reference/shaders-msl/asm/frag/extract-packed-from-composite.asm.frag
  51. 5 5
      3rdparty/spirv-cross/reference/shaders-msl/asm/frag/vector-shuffle-oom.asm.frag
  52. 3 3
      3rdparty/spirv-cross/reference/shaders-msl/asm/vert/spec-constant-op-composite.asm.vert
  53. 15 14
      3rdparty/spirv-cross/reference/shaders-msl/comp/composite-array-initialization.comp
  54. 2 2
      3rdparty/spirv-cross/reference/shaders-msl/comp/culling.comp
  55. 6 6
      3rdparty/spirv-cross/reference/shaders-msl/comp/packing-test-1.comp
  56. 2 2
      3rdparty/spirv-cross/reference/shaders-msl/comp/packing-test-2.comp
  57. 2 2
      3rdparty/spirv-cross/reference/shaders-msl/comp/shared-array-of-arrays.comp
  58. 2 2
      3rdparty/spirv-cross/reference/shaders-msl/comp/shared.comp
  59. 9 7
      3rdparty/spirv-cross/reference/shaders-msl/comp/spec-constant-op-member-array.comp
  60. 6 5
      3rdparty/spirv-cross/reference/shaders-msl/comp/spec-constant-work-group-size.comp
  61. 6 6
      3rdparty/spirv-cross/reference/shaders-msl/comp/struct-nested.comp
  62. 13 13
      3rdparty/spirv-cross/reference/shaders-msl/comp/type-alias.comp
  63. 1 15
      3rdparty/spirv-cross/reference/shaders-msl/frag/constant-array.frag
  64. 42 0
      3rdparty/spirv-cross/reference/shaders-msl/frag/fragment-component-padding.pad-fragment.frag
  65. 4 4
      3rdparty/spirv-cross/reference/shaders-msl/frag/packing-test-3.frag
  66. 5 5
      3rdparty/spirv-cross/reference/shaders-msl/vert/resource-arrays-leaf.ios.vert
  67. 5 5
      3rdparty/spirv-cross/reference/shaders-msl/vert/resource-arrays.ios.vert
  68. 25 0
      3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/out-of-order-struct-id.asm.frag
  69. 27 0
      3rdparty/spirv-cross/reference/shaders-no-opt/vert/pass-array-by-value.vert
  70. 2 2
      3rdparty/spirv-cross/reference/shaders/asm/frag/op-constant-null.asm.frag
  71. 5 5
      3rdparty/spirv-cross/reference/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert
  72. 2 2
      3rdparty/spirv-cross/reference/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert.vk
  73. 5 5
      3rdparty/spirv-cross/reference/shaders/comp/composite-array-initialization.comp
  74. 2 1
      3rdparty/spirv-cross/reference/shaders/comp/composite-construct.comp
  75. 5 5
      3rdparty/spirv-cross/reference/shaders/frag/constant-array.frag
  76. 10 9
      3rdparty/spirv-cross/reference/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp
  77. 4 3
      3rdparty/spirv-cross/reference/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp.vk
  78. 26 0
      3rdparty/spirv-cross/shaders-hlsl-no-opt/vert/pass-array-by-value.vert
  79. 10 0
      3rdparty/spirv-cross/shaders-hlsl/frag/dual-source-blending.frag
  80. 26 0
      3rdparty/spirv-cross/shaders-msl-no-opt/vert/pass-array-by-value.vert
  81. 90 0
      3rdparty/spirv-cross/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag
  82. 18 0
      3rdparty/spirv-cross/shaders-msl/frag/fragment-component-padding.pad-fragment.frag
  83. 54 0
      3rdparty/spirv-cross/shaders-no-opt/asm/frag/out-of-order-struct-id.asm.frag
  84. 26 0
      3rdparty/spirv-cross/shaders-no-opt/vert/pass-array-by-value.vert
  85. 11 14
      3rdparty/spirv-cross/spirv_cfg.cpp
  86. 39 9
      3rdparty/spirv-cross/spirv_cfg.hpp
  87. 13 8
      3rdparty/spirv-cross/spirv_common.hpp
  88. 166 130
      3rdparty/spirv-cross/spirv_cross.cpp
  89. 6 5
      3rdparty/spirv-cross/spirv_cross.hpp
  90. 134 38
      3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp
  91. 58 1
      3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp
  92. 141 196
      3rdparty/spirv-cross/spirv_glsl.cpp
  93. 1 0
      3rdparty/spirv-cross/spirv_glsl.hpp
  94. 223 244
      3rdparty/spirv-cross/spirv_hlsl.cpp
  95. 7 1
      3rdparty/spirv-cross/spirv_hlsl.hpp
  96. 576 244
      3rdparty/spirv-cross/spirv_msl.cpp
  97. 15 1
      3rdparty/spirv-cross/spirv_msl.hpp
  98. 4 1
      3rdparty/spirv-cross/spirv_parser.cpp
  99. 6 5
      3rdparty/spirv-cross/spirv_parser.hpp
  100. 15 15
      3rdparty/spirv-cross/spirv_reflect.cpp

+ 1 - 1
3rdparty/spirv-cross/README.md

@@ -3,7 +3,7 @@
 SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader languages.
 SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader languages.
 
 
 [![Build Status](https://travis-ci.org/KhronosGroup/SPIRV-Cross.svg?branch=master)](https://travis-ci.org/KhronosGroup/SPIRV-Cross)
 [![Build Status](https://travis-ci.org/KhronosGroup/SPIRV-Cross.svg?branch=master)](https://travis-ci.org/KhronosGroup/SPIRV-Cross)
-[![Build Status](https://ci.appveyor.com/api/projects/status/github/KhronosGroup/SPIRV-Cross?svg=true&branch=master)](https://ci.appveyor.com/project/HansKristian-ARM/SPIRV-Cross)
+[![Build Status](https://ci.appveyor.com/api/projects/status/github/KhronosGroup/SPIRV-Cross?svg=true&branch=master)](https://ci.appveyor.com/project/HansKristian-Work/SPIRV-Cross)
 
 
 ## Features
 ## Features
 
 

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

@@ -492,6 +492,7 @@ struct CLIArguments
 	bool support_nonzero_baseinstance = true;
 	bool support_nonzero_baseinstance = true;
 	bool msl_swizzle_texture_samples = false;
 	bool msl_swizzle_texture_samples = false;
 	bool msl_ios = false;
 	bool msl_ios = false;
+	bool msl_pad_fragment_output = false;
 	vector<PLSArg> pls_in;
 	vector<PLSArg> pls_in;
 	vector<PLSArg> pls_out;
 	vector<PLSArg> pls_out;
 	vector<Remap> remaps;
 	vector<Remap> remaps;
@@ -516,6 +517,7 @@ struct CLIArguments
 	bool msl = false;
 	bool msl = false;
 	bool hlsl = false;
 	bool hlsl = false;
 	bool hlsl_compat = false;
 	bool hlsl_compat = false;
+	bool hlsl_support_nonzero_base = false;
 	bool vulkan_semantics = false;
 	bool vulkan_semantics = false;
 	bool flatten_multidimensional_arrays = false;
 	bool flatten_multidimensional_arrays = false;
 	bool use_420pack_extension = true;
 	bool use_420pack_extension = true;
@@ -545,10 +547,12 @@ static void print_help()
 	                "\t[--msl-version <MMmmpp>]\n"
 	                "\t[--msl-version <MMmmpp>]\n"
 	                "\t[--msl-swizzle-texture-samples]\n"
 	                "\t[--msl-swizzle-texture-samples]\n"
 	                "\t[--msl-ios]\n"
 	                "\t[--msl-ios]\n"
+	                "\t[--msl-pad-fragment-output]\n"
 	                "\t[--hlsl]\n"
 	                "\t[--hlsl]\n"
 	                "\t[--reflect]\n"
 	                "\t[--reflect]\n"
 	                "\t[--shader-model]\n"
 	                "\t[--shader-model]\n"
 	                "\t[--hlsl-enable-compat]\n"
 	                "\t[--hlsl-enable-compat]\n"
+	                "\t[--hlsl-support-nonzero-basevertex-baseinstance]\n"
 	                "\t[--separate-shader-objects]\n"
 	                "\t[--separate-shader-objects]\n"
 	                "\t[--pls-in format input-name]\n"
 	                "\t[--pls-in format input-name]\n"
 	                "\t[--pls-out format output-name]\n"
 	                "\t[--pls-out format output-name]\n"
@@ -705,11 +709,14 @@ static int main_inner(int argc, char *argv[])
 	cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
 	cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
 	cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
 	cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
 	cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
 	cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
+	cbs.add("--hlsl-support-nonzero-basevertex-baseinstance",
+	        [&args](CLIParser &) { args.hlsl_support_nonzero_base = true; });
 	cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
 	cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
 	cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
 	cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
 	cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
 	cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
 	cbs.add("--msl-swizzle-texture-samples", [&args](CLIParser &) { args.msl_swizzle_texture_samples = true; });
 	cbs.add("--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-ios", [&args](CLIParser &) { args.msl_ios = true; });
+	cbs.add("--msl-pad-fragment-output", [&args](CLIParser &) { args.msl_pad_fragment_output = true; });
 	cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
 	cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
 	cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
 	cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
 		auto old_name = parser.next_string();
 		auto old_name = parser.next_string();
@@ -839,6 +846,7 @@ static int main_inner(int argc, char *argv[])
 		msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
 		msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
 		if (args.msl_ios)
 		if (args.msl_ios)
 			msl_opts.platform = CompilerMSL::Options::iOS;
 			msl_opts.platform = CompilerMSL::Options::iOS;
+		msl_opts.pad_fragment_output_components = args.msl_pad_fragment_output;
 		msl_comp->set_msl_options(msl_opts);
 		msl_comp->set_msl_options(msl_opts);
 	}
 	}
 	else if (args.hlsl)
 	else if (args.hlsl)
@@ -991,6 +999,7 @@ static int main_inner(int argc, char *argv[])
 			build_dummy_sampler = true;
 			build_dummy_sampler = true;
 		}
 		}
 
 
+		hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
 		hlsl->set_hlsl_options(hlsl_opts);
 		hlsl->set_hlsl_options(hlsl_opts);
 	}
 	}
 
 

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders-hlsl/asm/vert/spec-constant-op-composite.asm.vert

@@ -2,11 +2,11 @@
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #endif
 #endif
 static const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
 static const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
+static const int _20 = (_7 + 2);
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #endif
 #endif
 static const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
 static const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
-static const int _20 = (_7 + 2);
 static const uint _25 = (_8 % 5u);
 static const uint _25 = (_8 % 5u);
 #ifndef SPIRV_CROSS_CONSTANT_ID_0
 #ifndef SPIRV_CROSS_CONSTANT_ID_0
 #define SPIRV_CROSS_CONSTANT_ID_0 int4(20, 30, _20, _20)
 #define SPIRV_CROSS_CONSTANT_ID_0 int4(20, 30, _20, _20)

+ 9 - 9
3rdparty/spirv-cross/reference/opt/shaders-hlsl/comp/composite-array-initialization.comp

@@ -1,15 +1,16 @@
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 4.0f
-#endif
-static const float X = SPIRV_CROSS_CONSTANT_ID_0;
-static const uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
-
 struct Data
 struct Data
 {
 {
     float a;
     float a;
     float b;
     float b;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 4.0f
+#endif
+static const float X = SPIRV_CROSS_CONSTANT_ID_0;
+
+static const uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
+
 static const Data _21 = { 1.0f, 2.0f };
 static const Data _21 = { 1.0f, 2.0f };
 static const Data _24 = { 3.0f, 4.0f };
 static const Data _24 = { 3.0f, 4.0f };
 static const Data _25[2] = { { 1.0f, 2.0f }, { 3.0f, 4.0f } };
 static const Data _25[2] = { { 1.0f, 2.0f }, { 3.0f, 4.0f } };
@@ -29,14 +30,13 @@ struct SPIRV_Cross_Input
 
 
 void comp_main()
 void comp_main()
 {
 {
-    Data data[2] = _25;
     Data _28 = { X, 2.0f };
     Data _28 = { X, 2.0f };
     Data _31[2] = { _28, _30 };
     Data _31[2] = { _28, _30 };
     Data data2[2] = _31;
     Data data2[2] = _31;
     if (gl_LocalInvocationIndex == 0u)
     if (gl_LocalInvocationIndex == 0u)
     {
     {
-        _61.Store(gl_WorkGroupID.x * 8 + 0, asuint(data[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a));
-        _61.Store(gl_WorkGroupID.x * 8 + 4, asuint(data[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b));
+        _61.Store(gl_WorkGroupID.x * 8 + 0, asuint(_25[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a));
+        _61.Store(gl_WorkGroupID.x * 8 + 4, asuint(_25[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b));
     }
     }
 }
 }
 
 

+ 10 - 9
3rdparty/spirv-cross/reference/opt/shaders-hlsl/comp/spec-constant-op-member-array.comp

@@ -6,15 +6,6 @@ static const int a = SPIRV_CROSS_CONSTANT_ID_0;
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #endif
 #endif
 static const int b = SPIRV_CROSS_CONSTANT_ID_1;
 static const int b = SPIRV_CROSS_CONSTANT_ID_1;
-#ifndef SPIRV_CROSS_CONSTANT_ID_2
-#define SPIRV_CROSS_CONSTANT_ID_2 300
-#endif
-static const int c = SPIRV_CROSS_CONSTANT_ID_2;
-static const int _18 = (c + 50);
-#ifndef SPIRV_CROSS_CONSTANT_ID_3
-#define SPIRV_CROSS_CONSTANT_ID_3 400
-#endif
-static const int e = SPIRV_CROSS_CONSTANT_ID_3;
 
 
 struct A
 struct A
 {
 {
@@ -28,6 +19,16 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_2
+#define SPIRV_CROSS_CONSTANT_ID_2 300
+#endif
+static const int c = SPIRV_CROSS_CONSTANT_ID_2;
+static const int _18 = (c + 50);
+#ifndef SPIRV_CROSS_CONSTANT_ID_3
+#define SPIRV_CROSS_CONSTANT_ID_3 400
+#endif
+static const int e = SPIRV_CROSS_CONSTANT_ID_3;
+
 RWByteAddressBuffer _22 : register(u0);
 RWByteAddressBuffer _22 : register(u0);
 
 
 static uint3 gl_GlobalInvocationID;
 static uint3 gl_GlobalInvocationID;

+ 1 - 2
3rdparty/spirv-cross/reference/opt/shaders-hlsl/frag/constant-composites.frag

@@ -24,9 +24,8 @@ struct SPIRV_Cross_Output
 
 
 void frag_main()
 void frag_main()
 {
 {
-    Foo foos[2] = _28;
     FragColor = _16[_line].xxxx;
     FragColor = _16[_line].xxxx;
-    FragColor += (foos[_line].a * foos[1 - _line].a).xxxx;
+    FragColor += (_28[_line].a * _28[1 - _line].a).xxxx;
 }
 }
 
 
 SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
 SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)

+ 23 - 0
3rdparty/spirv-cross/reference/opt/shaders-hlsl/frag/dual-source-blending.frag

@@ -0,0 +1,23 @@
+static float4 FragColor0;
+static float4 FragColor1;
+
+struct SPIRV_Cross_Output
+{
+    float4 FragColor0 : SV_Target0;
+    float4 FragColor1 : SV_Target1;
+};
+
+void frag_main()
+{
+    FragColor0 = 1.0f.xxxx;
+    FragColor1 = 2.0f.xxxx;
+}
+
+SPIRV_Cross_Output main()
+{
+    frag_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.FragColor0 = FragColor0;
+    stage_output.FragColor1 = FragColor1;
+    return stage_output;
+}

+ 5 - 5
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/specialization-constant-workgroup.asm.comp

@@ -3,17 +3,17 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
+struct SSBO
+{
+    float a;
+};
+
 constant uint _5_tmp [[function_constant(10)]];
 constant uint _5_tmp [[function_constant(10)]];
 constant uint _5 = is_function_constant_defined(_5_tmp) ? _5_tmp : 9u;
 constant uint _5 = is_function_constant_defined(_5_tmp) ? _5_tmp : 9u;
 constant uint _6_tmp [[function_constant(12)]];
 constant uint _6_tmp [[function_constant(12)]];
 constant uint _6 = is_function_constant_defined(_6_tmp) ? _6_tmp : 4u;
 constant uint _6 = is_function_constant_defined(_6_tmp) ? _6_tmp : 4u;
 constant uint3 gl_WorkGroupSize = uint3(_5, 20u, _6);
 constant uint3 gl_WorkGroupSize = uint3(_5, 20u, _6);
 
 
-struct SSBO
-{
-    float a;
-};
-
 kernel void main0(device SSBO& _4 [[buffer(0)]])
 kernel void main0(device SSBO& _4 [[buffer(0)]])
 {
 {
     _4.a += 1.0;
     _4.a += 1.0;

+ 5 - 5
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/storage-buffer-basic.invalid.asm.comp

@@ -3,17 +3,17 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
+struct _6
+{
+    float _m0[1];
+};
+
 constant uint _3_tmp [[function_constant(0)]];
 constant uint _3_tmp [[function_constant(0)]];
 constant uint _3 = is_function_constant_defined(_3_tmp) ? _3_tmp : 1u;
 constant uint _3 = is_function_constant_defined(_3_tmp) ? _3_tmp : 1u;
 constant uint _4_tmp [[function_constant(2)]];
 constant uint _4_tmp [[function_constant(2)]];
 constant uint _4 = is_function_constant_defined(_4_tmp) ? _4_tmp : 3u;
 constant uint _4 = is_function_constant_defined(_4_tmp) ? _4_tmp : 3u;
 constant uint3 gl_WorkGroupSize = uint3(_3, 2u, _4);
 constant uint3 gl_WorkGroupSize = uint3(_3, 2u, _4);
 
 
-struct _6
-{
-    float _m0[1];
-};
-
 kernel void main0(device _6& _8 [[buffer(0)]], device _6& _9 [[buffer(1)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
 kernel void main0(device _6& _8 [[buffer(0)]], device _6& _9 [[buffer(1)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
 {
 {
     _8._m0[gl_WorkGroupID.x] = _9._m0[gl_WorkGroupID.x] + _8._m0[gl_WorkGroupID.x];
     _8._m0[gl_WorkGroupID.x] = _9._m0[gl_WorkGroupID.x] + _8._m0[gl_WorkGroupID.x];

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/vector-builtin-type-cast-func.asm.comp

@@ -3,13 +3,13 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
-
 struct cb1_struct
 struct cb1_struct
 {
 {
     float4 _m0[1];
     float4 _m0[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
+
 kernel void main0(constant cb1_struct& cb0_1 [[buffer(0)]], texture2d<float, access::write> u0 [[texture(1)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 kernel void main0(constant cb1_struct& cb0_1 [[buffer(0)]], texture2d<float, access::write> u0 [[texture(1)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 {
 {
     int2 _46 = int2(u0.get_width(), u0.get_height()) >> int2(uint2(4u));
     int2 _46 = int2(u0.get_width(), u0.get_height()) >> int2(uint2(4u));

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/comp/vector-builtin-type-cast.asm.comp

@@ -3,13 +3,13 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
-
 struct cb1_struct
 struct cb1_struct
 {
 {
     float4 _m0[1];
     float4 _m0[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
+
 kernel void main0(constant cb1_struct& cb0_1 [[buffer(0)]], texture2d<float, access::write> u0 [[texture(1)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 kernel void main0(constant cb1_struct& cb0_1 [[buffer(0)]], texture2d<float, access::write> u0 [[texture(1)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 {
 {
     int2 _40 = int2(u0.get_width(), u0.get_height()) >> int2(uint2(4u));
     int2 _40 = int2(u0.get_width(), u0.get_height()) >> int2(uint2(4u));

+ 5 - 5
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/frag/vector-shuffle-oom.asm.frag

@@ -3,6 +3,11 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
+struct _28
+{
+    float4 _m0;
+};
+
 struct _6
 struct _6
 {
 {
     float4 _m0;
     float4 _m0;
@@ -83,11 +88,6 @@ struct _18
     float4 _m38[2];
     float4 _m38[2];
 };
 };
 
 
-struct _28
-{
-    float4 _m0;
-};
-
 constant _28 _74 = {};
 constant _28 _74 = {};
 
 
 struct main0_out
 struct main0_out

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders-msl/asm/vert/spec-constant-op-composite.asm.vert

@@ -5,9 +5,9 @@ using namespace metal;
 
 
 constant int _7_tmp [[function_constant(201)]];
 constant int _7_tmp [[function_constant(201)]];
 constant int _7 = is_function_constant_defined(_7_tmp) ? _7_tmp : -10;
 constant int _7 = is_function_constant_defined(_7_tmp) ? _7_tmp : -10;
+constant int _20 = (_7 + 2);
 constant uint _8_tmp [[function_constant(202)]];
 constant uint _8_tmp [[function_constant(202)]];
 constant uint _8 = is_function_constant_defined(_8_tmp) ? _8_tmp : 100u;
 constant uint _8 = is_function_constant_defined(_8_tmp) ? _8_tmp : 100u;
-constant int _20 = (_7 + 2);
 constant uint _25 = (_8 % 5u);
 constant uint _25 = (_8 % 5u);
 constant int4 _30 = int4(20, 30, _20, _20);
 constant int4 _30 = int4(20, 30, _20, _20);
 constant int2 _32 = int2(_30.y, _30.x);
 constant int2 _32 = int2(_30.y, _30.x);

+ 11 - 11
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/composite-array-initialization.comp

@@ -5,10 +5,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant float X_tmp [[function_constant(0)]];
-constant float X = is_function_constant_defined(X_tmp) ? X_tmp : 4.0;
-constant uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
-
 struct Data
 struct Data
 {
 {
     float a;
     float a;
@@ -21,12 +17,17 @@ struct Data_1
     float b;
     float b;
 };
 };
 
 
+constant float X_tmp [[function_constant(0)]];
+constant float X = is_function_constant_defined(X_tmp) ? X_tmp : 4.0;
+
 struct SSBO
 struct SSBO
 {
 {
-    Data_1 outdata[1];
+    Data outdata[1];
 };
 };
 
 
-constant Data _25[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
+constant uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
+
+constant Data_1 _25[2] = { Data_1{ 1.0, 2.0 }, Data_1{ 3.0, 4.0 } };
 
 
 // Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
 // Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
 template<typename T, uint N>
 template<typename T, uint N>
@@ -43,11 +44,10 @@ void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
 
 
 kernel void main0(device SSBO& _53 [[buffer(0)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 kernel void main0(device SSBO& _53 [[buffer(0)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 {
 {
-    Data data[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
-    Data _31[2] = { Data{ X, 2.0 }, Data{ 3.0, 5.0 } };
-    Data data2[2];
+    Data_1 _31[2] = { Data_1{ X, 2.0 }, Data_1{ 3.0, 5.0 } };
+    Data_1 data2[2];
     spvArrayCopyFromStack1(data2, _31);
     spvArrayCopyFromStack1(data2, _31);
-    _53.outdata[gl_WorkGroupID.x].a = data[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a;
-    _53.outdata[gl_WorkGroupID.x].b = data[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b;
+    _53.outdata[gl_WorkGroupID.x].a = _25[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a;
+    _53.outdata[gl_WorkGroupID.x].b = _25[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b;
 }
 }
 
 

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/culling.comp

@@ -6,8 +6,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
-
 struct SSBO
 struct SSBO
 {
 {
     float in_data[1];
     float in_data[1];
@@ -23,6 +21,8 @@ struct SSBO3
     uint count;
     uint count;
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
+
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _38 [[buffer(1)]], device SSBO3& _41 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _38 [[buffer(1)]], device SSBO3& _41 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     float _28 = _22.in_data[gl_GlobalInvocationID.x];
     float _28 = _22.in_data[gl_GlobalInvocationID.x];

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/packing-test-1.comp

@@ -3,8 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
-
 struct T1
 struct T1
 {
 {
     packed_float3 a;
     packed_float3 a;
@@ -21,6 +19,8 @@ struct Buffer1
     float buf1[1];
     float buf1[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
+
 kernel void main0(device Buffer0& _15 [[buffer(1)]], device Buffer1& _34 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device Buffer0& _15 [[buffer(1)]], device Buffer1& _34 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     _34.buf1[gl_GlobalInvocationID.x] = _15.buf0[0].b;
     _34.buf1[gl_GlobalInvocationID.x] = _15.buf0[0].b;

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/packing-test-2.comp

@@ -3,8 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
-
 struct T1
 struct T1
 {
 {
     packed_float3 a;
     packed_float3 a;
@@ -21,6 +19,8 @@ struct Buffer1
     float buf1[1];
     float buf1[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
+
 kernel void main0(device Buffer0& _14 [[buffer(1)]], device Buffer1& _24 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device Buffer0& _14 [[buffer(1)]], device Buffer1& _24 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     _24.buf1[gl_GlobalInvocationID.x] = _14.buf0[0].b;
     _24.buf1[gl_GlobalInvocationID.x] = _14.buf0[0].b;

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/shared-array-of-arrays.comp

@@ -3,13 +3,13 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(4u, 4u, 1u);
-
 struct SSBO
 struct SSBO
 {
 {
     float out_data[1];
     float out_data[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(4u, 4u, 1u);
+
 kernel void main0(device SSBO& _67 [[buffer(0)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device SSBO& _67 [[buffer(0)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     threadgroup float foo[4][4];
     threadgroup float foo[4][4];

+ 2 - 2
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/shared.comp

@@ -3,8 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
-
 struct SSBO
 struct SSBO
 {
 {
     float in_data[1];
     float in_data[1];
@@ -15,6 +13,8 @@ struct SSBO2
     float out_data[1];
     float out_data[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
+
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _44 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _44 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
 {
 {
     threadgroup float sShared[4];
     threadgroup float sShared[4];

+ 9 - 7
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/spec-constant-op-member-array.comp

@@ -11,13 +11,6 @@ constant int a = SPIRV_CROSS_CONSTANT_ID_0;
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #endif
 #endif
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
-#ifndef SPIRV_CROSS_CONSTANT_ID_2
-#define SPIRV_CROSS_CONSTANT_ID_2 300
-#endif
-constant int c = SPIRV_CROSS_CONSTANT_ID_2;
-constant int _18 = (c + 50);
-constant int e_tmp [[function_constant(3)]];
-constant int e = is_function_constant_defined(e_tmp) ? e_tmp : 400;
 
 
 struct A
 struct A
 {
 {
@@ -31,6 +24,12 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_2
+#define SPIRV_CROSS_CONSTANT_ID_2 300
+#endif
+constant int c = SPIRV_CROSS_CONSTANT_ID_2;
+constant int _18 = (c + 50);
+
 struct SSBO
 struct SSBO
 {
 {
     A member_a;
     A member_a;
@@ -39,6 +38,9 @@ struct SSBO
     int w[_18];
     int w[_18];
 };
 };
 
 
+constant int e_tmp [[function_constant(3)]];
+constant int e = is_function_constant_defined(e_tmp) ? e_tmp : 400;
+
 kernel void main0(device SSBO& _22 [[buffer(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device SSBO& _22 [[buffer(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     _22.w[gl_GlobalInvocationID.x] += (_22.v[gl_GlobalInvocationID.x] + e);
     _22.w[gl_GlobalInvocationID.x] += (_22.v[gl_GlobalInvocationID.x] + e);

+ 6 - 5
3rdparty/spirv-cross/reference/opt/shaders-msl/comp/spec-constant-work-group-size.comp

@@ -9,6 +9,12 @@ using namespace metal;
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
 constant int a_tmp [[function_constant(0)]];
 constant int a_tmp [[function_constant(0)]];
 constant int a = is_function_constant_defined(a_tmp) ? a_tmp : 1;
 constant int a = is_function_constant_defined(a_tmp) ? a_tmp : 1;
+
+struct SSBO
+{
+    int v[1];
+};
+
 constant uint _21 = (uint(a) + 0u);
 constant uint _21 = (uint(a) + 0u);
 constant uint _22_tmp [[function_constant(10)]];
 constant uint _22_tmp [[function_constant(10)]];
 constant uint _22 = is_function_constant_defined(_22_tmp) ? _22_tmp : 1u;
 constant uint _22 = is_function_constant_defined(_22_tmp) ? _22_tmp : 1u;
@@ -19,11 +25,6 @@ constant uint _29 = gl_WorkGroupSize.y;
 constant uint _30 = (_28 + _29);
 constant uint _30 = (_28 + _29);
 constant int _32 = (1 - a);
 constant int _32 = (1 - a);
 
 
-struct SSBO
-{
-    int v[1];
-};
-
 kernel void main0(device SSBO& _17 [[buffer(0)]])
 kernel void main0(device SSBO& _17 [[buffer(0)]])
 {
 {
     int spec_const_array_size[b];
     int spec_const_array_size[b];

+ 1 - 17
3rdparty/spirv-cross/reference/opt/shaders-msl/frag/constant-array.frag

@@ -1,5 +1,3 @@
-#pragma clang diagnostic ignored "-Wmissing-prototypes"
-
 #include <metal_stdlib>
 #include <metal_stdlib>
 #include <simd/simd.h>
 #include <simd/simd.h>
 
 
@@ -27,24 +25,10 @@ struct main0_in
     int index [[user(locn0)]];
     int index [[user(locn0)]];
 };
 };
 
 
-// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
-template<typename T, uint N>
-void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
-{
-    for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
-template<typename T, uint N>
-void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
-{
-    for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
 fragment main0_out main0(main0_in in [[stage_in]])
 fragment main0_out main0(main0_in in [[stage_in]])
 {
 {
     main0_out out = {};
     main0_out out = {};
-    Foobar indexable[2] = { Foobar{ 10.0, 40.0 }, Foobar{ 90.0, 70.0 } };
-    out.FragColor = ((_37[in.index] + _55[in.index][in.index + 1]) + float4(30.0)) + float4(indexable[in.index].a + indexable[in.index].b);
+    out.FragColor = ((_37[in.index] + _55[in.index][in.index + 1]) + float4(30.0)) + float4(_75[in.index].a + _75[in.index].b);
     return out;
     return out;
 }
 }
 
 

+ 1 - 17
3rdparty/spirv-cross/reference/opt/shaders-msl/frag/constant-composites.frag

@@ -1,5 +1,3 @@
-#pragma clang diagnostic ignored "-Wmissing-prototypes"
-
 #include <metal_stdlib>
 #include <metal_stdlib>
 #include <simd/simd.h>
 #include <simd/simd.h>
 
 
@@ -24,25 +22,11 @@ struct main0_in
     int line [[user(locn0)]];
     int line [[user(locn0)]];
 };
 };
 
 
-// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
-template<typename T, uint N>
-void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
-{
-    for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
-template<typename T, uint N>
-void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
-{
-    for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
 fragment main0_out main0(main0_in in [[stage_in]])
 fragment main0_out main0(main0_in in [[stage_in]])
 {
 {
     main0_out out = {};
     main0_out out = {};
-    Foo foos[2] = { Foo{ 10.0, 20.0 }, Foo{ 30.0, 40.0 } };
     out.FragColor = float4(_16[in.line]);
     out.FragColor = float4(_16[in.line]);
-    out.FragColor += float4(foos[in.line].a * foos[1 - in.line].a);
+    out.FragColor += float4(_28[in.line].a * _28[1 - in.line].a);
     return out;
     return out;
 }
 }
 
 

+ 35 - 0
3rdparty/spirv-cross/reference/opt/shaders-msl/frag/fragment-component-padding.pad-fragment.frag

@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 FragColors_0 [[color(0)]];
+    float4 FragColors_1 [[color(1)]];
+    float4 FragColor2 [[color(2)]];
+    float4 FragColor3 [[color(3)]];
+};
+
+struct main0_in
+{
+    float3 vColor [[user(locn0)]];
+};
+
+fragment main0_out main0(main0_in in [[stage_in]])
+{
+    main0_out out = {};
+    float FragColors[2] = {};
+    float2 FragColor2 = {};
+    float3 FragColor3 = {};
+    FragColors[0] = in.vColor.x;
+    FragColors[1] = in.vColor.y;
+    FragColor2 = in.vColor.xz;
+    FragColor3 = in.vColor.zzz;
+    out.FragColors_0 = float4(FragColors[0]);
+    out.FragColors_1 = float4(FragColors[1]);
+    out.FragColor2 = FragColor2.xyyy;
+    out.FragColor3 = FragColor3.xyzz;
+    return out;
+}
+

+ 5 - 5
3rdparty/spirv-cross/reference/opt/shaders-msl/vert/resource-arrays-leaf.ios.vert

@@ -3,11 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 3
-#endif
-constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
-
 struct storage_block
 struct storage_block
 {
 {
     uint4 baz;
     uint4 baz;
@@ -20,6 +15,11 @@ struct constant_block
     int bar;
     int bar;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 3
+#endif
+constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
+
 vertex void main0(device storage_block* storage_0 [[buffer(0)]], device storage_block* storage_1 [[buffer(1)]], constant constant_block* constants_0 [[buffer(2)]], constant constant_block* constants_1 [[buffer(3)]], constant constant_block* constants_2 [[buffer(4)]], constant constant_block* constants_3 [[buffer(5)]], array<texture2d<int>, 3> images [[texture(0)]])
 vertex void main0(device storage_block* storage_0 [[buffer(0)]], device storage_block* storage_1 [[buffer(1)]], constant constant_block* constants_0 [[buffer(2)]], constant constant_block* constants_1 [[buffer(3)]], constant constant_block* constants_2 [[buffer(4)]], constant constant_block* constants_3 [[buffer(5)]], array<texture2d<int>, 3> images [[texture(0)]])
 {
 {
     device storage_block* storage[] =
     device storage_block* storage[] =

+ 5 - 5
3rdparty/spirv-cross/reference/opt/shaders-msl/vert/resource-arrays.ios.vert

@@ -3,11 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 3
-#endif
-constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
-
 struct storage_block
 struct storage_block
 {
 {
     uint4 baz;
     uint4 baz;
@@ -20,6 +15,11 @@ struct constant_block
     int bar;
     int bar;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 3
+#endif
+constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
+
 vertex void main0(device storage_block* storage_0 [[buffer(0)]], device storage_block* storage_1 [[buffer(1)]], constant constant_block* constants_0 [[buffer(2)]], constant constant_block* constants_1 [[buffer(3)]], constant constant_block* constants_2 [[buffer(4)]], constant constant_block* constants_3 [[buffer(5)]], array<texture2d<int>, 3> images [[texture(0)]])
 vertex void main0(device storage_block* storage_0 [[buffer(0)]], device storage_block* storage_1 [[buffer(1)]], constant constant_block* constants_0 [[buffer(2)]], constant constant_block* constants_1 [[buffer(3)]], constant constant_block* constants_2 [[buffer(4)]], constant constant_block* constants_3 [[buffer(5)]], array<texture2d<int>, 3> images [[texture(0)]])
 {
 {
     device storage_block* storage[] =
     device storage_block* storage[] =

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert

@@ -4,11 +4,11 @@
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #endif
 #endif
 const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
 const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
+const int _20 = (_7 + 2);
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #endif
 #endif
 const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
 const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
-const int _20 = (_7 + 2);
 const uint _25 = (_8 % 5u);
 const uint _25 = (_8 % 5u);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec2 _32 = ivec2(_30.y, _30.x);
 const ivec2 _32 = ivec2(_30.y, _30.x);

+ 1 - 1
3rdparty/spirv-cross/reference/opt/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert.vk

@@ -1,8 +1,8 @@
 #version 450
 #version 450
 
 
 layout(constant_id = 201) const int _7 = -10;
 layout(constant_id = 201) const int _7 = -10;
-layout(constant_id = 202) const uint _8 = 100u;
 const int _20 = (_7 + 2);
 const int _20 = (_7 + 2);
+layout(constant_id = 202) const uint _8 = 100u;
 const uint _25 = (_8 % 5u);
 const uint _25 = (_8 % 5u);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec2 _32 = ivec2(_30.y, _30.x);
 const ivec2 _32 = ivec2(_30.y, _30.x);

+ 8 - 8
3rdparty/spirv-cross/reference/opt/shaders/comp/composite-array-initialization.comp

@@ -1,17 +1,18 @@
 #version 310 es
 #version 310 es
 layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
 layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
 
 
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 4.0
-#endif
-const float X = SPIRV_CROSS_CONSTANT_ID_0;
-
 struct Data
 struct Data
 {
 {
     float a;
     float a;
     float b;
     float b;
 };
 };
 
 
+const Data _25[2] = Data[](Data(1.0, 2.0), Data(3.0, 4.0));
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 4.0
+#endif
+const float X = SPIRV_CROSS_CONSTANT_ID_0;
+
 layout(binding = 0, std430) buffer SSBO
 layout(binding = 0, std430) buffer SSBO
 {
 {
     Data outdata[];
     Data outdata[];
@@ -19,9 +20,8 @@ layout(binding = 0, std430) buffer SSBO
 
 
 void main()
 void main()
 {
 {
-    Data data[2] = Data[](Data(1.0, 2.0), Data(3.0, 4.0));
     Data data2[2] = Data[](Data(X, 2.0), Data(3.0, 5.0));
     Data data2[2] = Data[](Data(X, 2.0), Data(3.0, 5.0));
-    _53.outdata[gl_WorkGroupID.x].a = data[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a;
-    _53.outdata[gl_WorkGroupID.x].b = data[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b;
+    _53.outdata[gl_WorkGroupID.x].a = _25[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a;
+    _53.outdata[gl_WorkGroupID.x].b = _25[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b;
 }
 }
 
 

+ 5 - 5
3rdparty/spirv-cross/reference/opt/shaders/frag/constant-array.frag

@@ -2,21 +2,21 @@
 precision mediump float;
 precision mediump float;
 precision highp int;
 precision highp int;
 
 
-const vec4 _37[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
-const vec4 _55[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
-
 struct Foobar
 struct Foobar
 {
 {
     float a;
     float a;
     float b;
     float b;
 };
 };
 
 
+const vec4 _37[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
+const vec4 _55[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
+const Foobar _75[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
+
 layout(location = 0) out vec4 FragColor;
 layout(location = 0) out vec4 FragColor;
 layout(location = 0) flat in mediump int index;
 layout(location = 0) flat in mediump int index;
 
 
 void main()
 void main()
 {
 {
-    Foobar indexable[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
-    FragColor = ((_37[index] + _55[index][index + 1]) + vec4(30.0)) + vec4(indexable[index].a + indexable[index].b);
+    FragColor = ((_37[index] + _55[index][index + 1]) + vec4(30.0)) + vec4(_75[index].a + _75[index].b);
 }
 }
 
 

+ 3 - 2
3rdparty/spirv-cross/reference/opt/shaders/frag/constant-composites.frag

@@ -10,13 +10,14 @@ struct Foo
     float b;
     float b;
 };
 };
 
 
+const Foo _28[2] = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
+
 layout(location = 0) out vec4 FragColor;
 layout(location = 0) out vec4 FragColor;
 layout(location = 0) flat in mediump int line;
 layout(location = 0) flat in mediump int line;
 
 
 void main()
 void main()
 {
 {
-    Foo foos[2] = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
     FragColor = vec4(_16[line]);
     FragColor = vec4(_16[line]);
-    FragColor += vec4(foos[line].a * foos[1 - line].a);
+    FragColor += vec4(_28[line].a * _28[1 - line].a);
 }
 }
 
 

+ 10 - 9
3rdparty/spirv-cross/reference/opt/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp

@@ -9,15 +9,6 @@ const int a = SPIRV_CROSS_CONSTANT_ID_0;
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #endif
 #endif
 const int b = SPIRV_CROSS_CONSTANT_ID_1;
 const int b = SPIRV_CROSS_CONSTANT_ID_1;
-#ifndef SPIRV_CROSS_CONSTANT_ID_2
-#define SPIRV_CROSS_CONSTANT_ID_2 300
-#endif
-const int c = SPIRV_CROSS_CONSTANT_ID_2;
-const int _18 = (c + 50);
-#ifndef SPIRV_CROSS_CONSTANT_ID_3
-#define SPIRV_CROSS_CONSTANT_ID_3 400
-#endif
-const int e = SPIRV_CROSS_CONSTANT_ID_3;
 
 
 struct A
 struct A
 {
 {
@@ -31,6 +22,16 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_2
+#define SPIRV_CROSS_CONSTANT_ID_2 300
+#endif
+const int c = SPIRV_CROSS_CONSTANT_ID_2;
+const int _18 = (c + 50);
+#ifndef SPIRV_CROSS_CONSTANT_ID_3
+#define SPIRV_CROSS_CONSTANT_ID_3 400
+#endif
+const int e = SPIRV_CROSS_CONSTANT_ID_3;
+
 layout(binding = 0, std430) buffer SSBO
 layout(binding = 0, std430) buffer SSBO
 {
 {
     A member_a;
     A member_a;

+ 4 - 3
3rdparty/spirv-cross/reference/opt/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp.vk

@@ -3,9 +3,6 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
 
 layout(constant_id = 0) const int a = 100;
 layout(constant_id = 0) const int a = 100;
 layout(constant_id = 1) const int b = 200;
 layout(constant_id = 1) const int b = 200;
-layout(constant_id = 2) const int c = 300;
-const int _18 = (c + 50);
-layout(constant_id = 3) const int e = 400;
 
 
 struct A
 struct A
 {
 {
@@ -19,6 +16,10 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+layout(constant_id = 2) const int c = 300;
+const int _18 = (c + 50);
+layout(constant_id = 3) const int e = 400;
+
 layout(set = 1, binding = 0, std430) buffer SSBO
 layout(set = 1, binding = 0, std430) buffer SSBO
 {
 {
     A member_a;
     A member_a;

+ 48 - 0
3rdparty/spirv-cross/reference/shaders-hlsl-no-opt/vert/pass-array-by-value.vert

@@ -0,0 +1,48 @@
+static const float4 _68[4] = { 0.0f.xxxx, 1.0f.xxxx, 2.0f.xxxx, 3.0f.xxxx };
+
+static float4 gl_Position;
+static int Index1;
+static int Index2;
+
+struct SPIRV_Cross_Input
+{
+    int Index1 : TEXCOORD0;
+    int Index2 : TEXCOORD1;
+};
+
+struct SPIRV_Cross_Output
+{
+    float4 gl_Position : SV_Position;
+};
+
+float4 consume_constant_arrays2(float4 positions[4], float4 positions2[4])
+{
+    float4 indexable[4] = positions;
+    float4 indexable_1[4] = positions2;
+    return indexable[Index1] + indexable_1[Index2];
+}
+
+float4 consume_constant_arrays(float4 positions[4], float4 positions2[4])
+{
+    return consume_constant_arrays2(positions, positions2);
+}
+
+void vert_main()
+{
+    float4 LUT2[4];
+    LUT2[0] = 10.0f.xxxx;
+    LUT2[1] = 11.0f.xxxx;
+    LUT2[2] = 12.0f.xxxx;
+    LUT2[3] = 13.0f.xxxx;
+    gl_Position = consume_constant_arrays(_68, LUT2);
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+    Index1 = stage_input.Index1;
+    Index2 = stage_input.Index2;
+    vert_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.gl_Position = gl_Position;
+    return stage_output;
+}

+ 5 - 5
3rdparty/spirv-cross/reference/shaders-hlsl/asm/vert/spec-constant-op-composite.asm.vert

@@ -2,15 +2,11 @@
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #endif
 #endif
 static const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
 static const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
+static const int _20 = (_7 + 2);
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #endif
 #endif
 static const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
 static const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
-#ifndef SPIRV_CROSS_CONSTANT_ID_200
-#define SPIRV_CROSS_CONSTANT_ID_200 3.141590118408203125f
-#endif
-static const float _9 = SPIRV_CROSS_CONSTANT_ID_200;
-static const int _20 = (_7 + 2);
 static const uint _25 = (_8 % 5u);
 static const uint _25 = (_8 % 5u);
 #ifndef SPIRV_CROSS_CONSTANT_ID_0
 #ifndef SPIRV_CROSS_CONSTANT_ID_0
 #define SPIRV_CROSS_CONSTANT_ID_0 int4(20, 30, _20, _20)
 #define SPIRV_CROSS_CONSTANT_ID_0 int4(20, 30, _20, _20)
@@ -18,6 +14,10 @@ static const uint _25 = (_8 % 5u);
 static const int4 _30 = SPIRV_CROSS_CONSTANT_ID_0;
 static const int4 _30 = SPIRV_CROSS_CONSTANT_ID_0;
 static const int2 _32 = int2(_30.y, _30.x);
 static const int2 _32 = int2(_30.y, _30.x);
 static const int _33 = _30.y;
 static const int _33 = _30.y;
+#ifndef SPIRV_CROSS_CONSTANT_ID_200
+#define SPIRV_CROSS_CONSTANT_ID_200 3.141590118408203125f
+#endif
+static const float _9 = SPIRV_CROSS_CONSTANT_ID_200;
 
 
 static float4 gl_Position;
 static float4 gl_Position;
 static int _4;
 static int _4;

+ 7 - 6
3rdparty/spirv-cross/reference/shaders-hlsl/comp/composite-array-initialization.comp

@@ -1,15 +1,16 @@
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 4.0f
-#endif
-static const float X = SPIRV_CROSS_CONSTANT_ID_0;
-static const uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
-
 struct Data
 struct Data
 {
 {
     float a;
     float a;
     float b;
     float b;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 4.0f
+#endif
+static const float X = SPIRV_CROSS_CONSTANT_ID_0;
+
+static const uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
+
 static const Data _21 = { 1.0f, 2.0f };
 static const Data _21 = { 1.0f, 2.0f };
 static const Data _24 = { 3.0f, 4.0f };
 static const Data _24 = { 3.0f, 4.0f };
 static const Data _25[2] = { { 1.0f, 2.0f }, { 3.0f, 4.0f } };
 static const Data _25[2] = { { 1.0f, 2.0f }, { 3.0f, 4.0f } };

+ 10 - 9
3rdparty/spirv-cross/reference/shaders-hlsl/comp/spec-constant-op-member-array.comp

@@ -6,15 +6,6 @@ static const int a = SPIRV_CROSS_CONSTANT_ID_0;
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #endif
 #endif
 static const int b = SPIRV_CROSS_CONSTANT_ID_1;
 static const int b = SPIRV_CROSS_CONSTANT_ID_1;
-#ifndef SPIRV_CROSS_CONSTANT_ID_2
-#define SPIRV_CROSS_CONSTANT_ID_2 300
-#endif
-static const int c = SPIRV_CROSS_CONSTANT_ID_2;
-static const int _18 = (c + 50);
-#ifndef SPIRV_CROSS_CONSTANT_ID_3
-#define SPIRV_CROSS_CONSTANT_ID_3 400
-#endif
-static const int e = SPIRV_CROSS_CONSTANT_ID_3;
 
 
 struct A
 struct A
 {
 {
@@ -28,6 +19,16 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_2
+#define SPIRV_CROSS_CONSTANT_ID_2 300
+#endif
+static const int c = SPIRV_CROSS_CONSTANT_ID_2;
+static const int _18 = (c + 50);
+#ifndef SPIRV_CROSS_CONSTANT_ID_3
+#define SPIRV_CROSS_CONSTANT_ID_3 400
+#endif
+static const int e = SPIRV_CROSS_CONSTANT_ID_3;
+
 RWByteAddressBuffer _22 : register(u0);
 RWByteAddressBuffer _22 : register(u0);
 
 
 static uint3 gl_GlobalInvocationID;
 static uint3 gl_GlobalInvocationID;

+ 23 - 0
3rdparty/spirv-cross/reference/shaders-hlsl/frag/dual-source-blending.frag

@@ -0,0 +1,23 @@
+static float4 FragColor0;
+static float4 FragColor1;
+
+struct SPIRV_Cross_Output
+{
+    float4 FragColor0 : SV_Target0;
+    float4 FragColor1 : SV_Target1;
+};
+
+void frag_main()
+{
+    FragColor0 = 1.0f.xxxx;
+    FragColor1 = 2.0f.xxxx;
+}
+
+SPIRV_Cross_Output main()
+{
+    frag_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.FragColor0 = FragColor0;
+    stage_output.FragColor1 = FragColor1;
+    return stage_output;
+}

+ 49 - 39
3rdparty/spirv-cross/reference/shaders-msl-no-opt/asm/frag/texture-access.swizzle.asm.frag

@@ -78,7 +78,7 @@ inline T spvTextureSwizzle(T x, uint s)
 
 
 // Wrapper function that swizzles texture gathers.
 // Wrapper function that swizzles texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -115,7 +115,7 @@ inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, compon
 
 
 // Wrapper function that swizzles depth texture gathers.
 // Wrapper function that swizzles depth texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params, uint sw) 
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) 
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -138,47 +138,57 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params,
 
 
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSamp [[sampler(0)]], sampler tex2dSamp [[sampler(1)]], sampler tex3dSamp [[sampler(2)]], sampler texCubeSamp [[sampler(3)]], sampler tex2dArraySamp [[sampler(4)]], sampler texCubeArraySamp [[sampler(5)]], sampler depth2dSamp [[sampler(7)]], sampler depthCubeSamp [[sampler(8)]], sampler depth2dArraySamp [[sampler(9)]], sampler depthCubeArraySamp [[sampler(10)]])
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSamp [[sampler(0)]], sampler tex2dSamp [[sampler(1)]], sampler tex3dSamp [[sampler(2)]], sampler texCubeSamp [[sampler(3)]], sampler tex2dArraySamp [[sampler(4)]], sampler texCubeArraySamp [[sampler(5)]], sampler depth2dSamp [[sampler(7)]], sampler depthCubeSamp [[sampler(8)]], sampler depth2dArraySamp [[sampler(9)]], sampler depthCubeArraySamp [[sampler(10)]])
 {
 {
-    float4 c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0)), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(texCube.sample(texCubeSamp, float3(0.0)), spvAuxBuffer.swizzleConst[3]);
-    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]);
-    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]);
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
-    c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSamp, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[8]);
-    c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySamp, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[9]);
-    c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvAuxBuffer.swizzleConst[10]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSamp, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]);
+    constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
+    constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
+    constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2];
+    constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3];
+    constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4];
+    constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5];
+    constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7];
+    constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8];
+    constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9];
+    constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[10];
+    float4 c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0)), tex3dSwzl);
+    c = spvTextureSwizzle(texCube.sample(texCubeSamp, float3(0.0)), texCubeSwzl);
+    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z))), tex2dArraySwzl);
+    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w))), texCubeArraySwzl);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), depth2dSwzl);
+    c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSamp, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), depthCubeSwzl);
+    c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySamp, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), depth2dArraySwzl);
+    c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), depthCubeArraySwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSamp, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), tex3dSwzl);
     float4 _152 = float4(0.0, 0.0, 1.0, 1.0);
     float4 _152 = float4(0.0, 0.0, 1.0, 1.0);
     _152.z = float4(0.0, 0.0, 1.0, 1.0).w;
     _152.z = float4(0.0, 0.0, 1.0, 1.0).w;
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, _152.xy / _152.z, float4(0.0, 0.0, 1.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(texCube.sample(texCubeSamp, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]);
-    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]);
-    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]);
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSamp, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, _152.xy / _152.z, float4(0.0, 0.0, 1.0, 1.0).z), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSamp, 0.0), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float2(0.0), level(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float3(0.0), level(0.0)), tex3dSwzl);
+    c = spvTextureSwizzle(texCube.sample(texCubeSamp, float3(0.0), level(0.0)), texCubeSwzl);
+    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySamp, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), tex2dArraySwzl);
+    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySamp, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), texCubeArraySwzl);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSamp, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSamp, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSamp, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), tex3dSwzl);
     float4 _202 = float4(0.0, 0.0, 1.0, 1.0);
     float4 _202 = float4(0.0, 0.0, 1.0, 1.0);
     _202.z = float4(0.0, 0.0, 1.0, 1.0).w;
     _202.z = float4(0.0, 0.0, 1.0, 1.0).w;
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, _202.xy / _202.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSamp, _202.xy / _202.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.read(uint(0)), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), tex3dSwzl);
+    c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), tex2dArraySwzl);
     c = texBuffer.read(spvTexelBufferCoord(0));
     c = texBuffer.read(spvTexelBufferCoord(0));
-    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(tex2dSamp, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]);
-    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(texCubeSamp, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]);
-    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(tex2dArraySamp, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]);
-    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(texCubeArraySamp, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]);
-    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(depth2dSamp, depth2d, float2(0.0), 1.0, spvAuxBuffer.swizzleConst[7]);
-    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(depthCubeSamp, depthCube, float3(0.0), 1.0, spvAuxBuffer.swizzleConst[8]);
-    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(depth2dArraySamp, depth2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, spvAuxBuffer.swizzleConst[9]);
-    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(depthCubeArraySamp, depthCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, spvAuxBuffer.swizzleConst[10]);
+    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(tex2dSamp, tex2d, float2(0.0), int2(0), component::x, tex2dSwzl);
+    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(texCubeSamp, texCube, float3(0.0), component::y, texCubeSwzl);
+    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(tex2dArraySamp, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, tex2dArraySwzl);
+    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(texCubeArraySamp, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, texCubeArraySwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(depth2dSamp, depth2d, float2(0.0), 1.0, depth2dSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(depthCubeSamp, depthCube, float3(0.0), 1.0, depthCubeSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(depth2dArraySamp, depth2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, depth2dArraySwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(depthCubeArraySamp, depthCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, depthCubeArraySwzl);
 }
 }
 
 

+ 34 - 28
3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access-int.swizzle.frag

@@ -78,7 +78,7 @@ inline T spvTextureSwizzle(T x, uint s)
 
 
 // Wrapper function that swizzles texture gathers.
 // Wrapper function that swizzles texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -115,7 +115,7 @@ inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, compon
 
 
 // Wrapper function that swizzles depth texture gathers.
 // Wrapper function that swizzles depth texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params, uint sw) 
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) 
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -138,32 +138,38 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params,
 
 
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<int> tex1d [[texture(0)]], texture2d<int> tex2d [[texture(1)]], texture3d<int> tex3d [[texture(2)]], texturecube<int> texCube [[texture(3)]], texture2d_array<int> tex2dArray [[texture(4)]], texturecube_array<int> texCubeArray [[texture(5)]], texture2d<int> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<int> tex1d [[texture(0)]], texture2d<int> tex2d [[texture(1)]], texture3d<int> tex3d [[texture(2)]], texturecube<int> texCube [[texture(3)]], texture2d_array<int> tex2dArray [[texture(4)]], texturecube_array<int> texCubeArray [[texture(5)]], texture2d<int> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
 {
 {
-    float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]));
-    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]));
-    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]));
-    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]));
-    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]));
-    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]));
-    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]));
+    constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
+    constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
+    constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2];
+    constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3];
+    constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4];
+    constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5];
+    float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl));
+    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), texCubeSwzl));
+    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), tex2dArraySwzl));
+    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), texCubeArraySwzl));
+    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), tex3dSwzl));
+    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), tex3dSwzl));
+    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), texCubeSwzl));
+    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), tex2dArraySwzl));
+    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), texCubeArraySwzl));
+    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), tex3dSwzl));
+    c = float4(spvTextureSwizzle(tex1d.read(uint(0)), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), tex3dSwzl));
+    c = float4(spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), tex2dArraySwzl));
     c = float4(texBuffer.read(spvTexelBufferCoord(0)));
     c = float4(texBuffer.read(spvTexelBufferCoord(0)));
-    c = float4(spvGatherSwizzle<int, metal::texture2d<int>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvGatherSwizzle<int, metal::texturecube<int>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]));
-    c = float4(spvGatherSwizzle<int, metal::texture2d_array<int>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]));
-    c = float4(spvGatherSwizzle<int, metal::texturecube_array<int>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]));
+    c = float4(spvGatherSwizzle<int, metal::texture2d<int>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, tex2dSwzl));
+    c = float4(spvGatherSwizzle<int, metal::texturecube<int>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, texCubeSwzl));
+    c = float4(spvGatherSwizzle<int, metal::texture2d_array<int>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, tex2dArraySwzl));
+    c = float4(spvGatherSwizzle<int, metal::texturecube_array<int>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, texCubeArraySwzl));
 }
 }
 
 

+ 51 - 41
3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access-leaf.swizzle.frag

@@ -78,7 +78,7 @@ inline T spvTextureSwizzle(T x, uint s)
 
 
 // Wrapper function that swizzles texture gathers.
 // Wrapper function that swizzles texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -115,7 +115,7 @@ inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, compon
 
 
 // Wrapper function that swizzles depth texture gathers.
 // Wrapper function that swizzles depth texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params, uint sw) 
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) 
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -136,55 +136,65 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params,
     return t.gather_compare(s, spvForward<Ts>(params)...);
     return t.gather_compare(s, spvForward<Ts>(params)...);
 }
 }
 
 
-float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr, thread texture2d<float> tex2d, thread const sampler tex2dSmplr, thread texture3d<float> tex3d, thread const sampler tex3dSmplr, thread texturecube<float> texCube, thread const sampler texCubeSmplr, thread texture2d_array<float> tex2dArray, thread const sampler tex2dArraySmplr, thread texturecube_array<float> texCubeArray, thread const sampler texCubeArraySmplr, thread depth2d<float> depth2d, thread const sampler depth2dSmplr, thread depthcube<float> depthCube, thread const sampler depthCubeSmplr, thread depth2d_array<float> depth2dArray, thread const sampler depth2dArraySmplr, thread depthcube_array<float> depthCubeArray, thread const sampler depthCubeArraySmplr, thread texture2d<float> texBuffer, constant spvAux& spvAuxBuffer)
+float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr, constant uint32_t& tex1dSwzl, thread texture2d<float> tex2d, thread const sampler tex2dSmplr, constant uint32_t& tex2dSwzl, thread texture3d<float> tex3d, thread const sampler tex3dSmplr, constant uint32_t& tex3dSwzl, thread texturecube<float> texCube, thread const sampler texCubeSmplr, constant uint32_t& texCubeSwzl, thread texture2d_array<float> tex2dArray, thread const sampler tex2dArraySmplr, constant uint32_t& tex2dArraySwzl, thread texturecube_array<float> texCubeArray, thread const sampler texCubeArraySmplr, constant uint32_t& texCubeArraySwzl, thread depth2d<float> depth2d, thread const sampler depth2dSmplr, constant uint32_t& depth2dSwzl, thread depthcube<float> depthCube, thread const sampler depthCubeSmplr, constant uint32_t& depthCubeSwzl, thread depth2d_array<float> depth2dArray, thread const sampler depth2dArraySmplr, constant uint32_t& depth2dArraySwzl, thread depthcube_array<float> depthCubeArray, thread const sampler depthCubeArraySmplr, constant uint32_t& depthCubeArraySwzl, thread texture2d<float> texBuffer, constant spvAux& spvAuxBuffer)
 {
 {
-    float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]);
-    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]);
-    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]);
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
-    c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[8]);
-    c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[9]);
-    c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvAuxBuffer.swizzleConst[10]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]);
+    float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl);
+    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), texCubeSwzl);
+    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), tex2dArraySwzl);
+    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), texCubeArraySwzl);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), depth2dSwzl);
+    c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), depthCubeSwzl);
+    c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), depth2dArraySwzl);
+    c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), depthCubeArraySwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), tex3dSwzl);
     float4 _103 = float4(0.0, 0.0, 1.0, 1.0);
     float4 _103 = float4(0.0, 0.0, 1.0, 1.0);
     _103.z = float4(0.0, 0.0, 1.0, 1.0).w;
     _103.z = float4(0.0, 0.0, 1.0, 1.0).w;
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _103.xy / _103.z, float4(0.0, 0.0, 1.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]);
-    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]);
-    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]);
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _103.xy / _103.z, float4(0.0, 0.0, 1.0, 1.0).z), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), tex3dSwzl);
+    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), texCubeSwzl);
+    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), tex2dArraySwzl);
+    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), texCubeArraySwzl);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), tex3dSwzl);
     float4 _131 = float4(0.0, 0.0, 1.0, 1.0);
     float4 _131 = float4(0.0, 0.0, 1.0, 1.0);
     _131.z = float4(0.0, 0.0, 1.0, 1.0).w;
     _131.z = float4(0.0, 0.0, 1.0, 1.0).w;
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _131.xy / _131.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _131.xy / _131.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.read(uint(0)), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), tex3dSwzl);
+    c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), tex2dArraySwzl);
     c = texBuffer.read(spvTexelBufferCoord(0));
     c = texBuffer.read(spvTexelBufferCoord(0));
-    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]);
-    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]);
-    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]);
-    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]);
-    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(depth2dSmplr, depth2d, float2(0.0), 1.0, spvAuxBuffer.swizzleConst[7]);
-    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(depthCubeSmplr, depthCube, float3(0.0), 1.0, spvAuxBuffer.swizzleConst[8]);
-    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(depth2dArraySmplr, depth2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, spvAuxBuffer.swizzleConst[9]);
-    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(depthCubeArraySmplr, depthCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, spvAuxBuffer.swizzleConst[10]);
+    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, tex2dSwzl);
+    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, texCubeSwzl);
+    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, tex2dArraySwzl);
+    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, texCubeArraySwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(depth2dSmplr, depth2d, float2(0.0), 1.0, depth2dSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(depthCubeSmplr, depthCube, float3(0.0), 1.0, depthCubeSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(depth2dArraySmplr, depth2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, depth2dArraySwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(depthCubeArraySmplr, depthCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, depthCubeArraySwzl);
     return c;
     return c;
 }
 }
 
 
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
 {
 {
-    float4 c = doSwizzle(tex1d, tex1dSmplr, tex2d, tex2dSmplr, tex3d, tex3dSmplr, texCube, texCubeSmplr, tex2dArray, tex2dArraySmplr, texCubeArray, texCubeArraySmplr, depth2d, depth2dSmplr, depthCube, depthCubeSmplr, depth2dArray, depth2dArraySmplr, depthCubeArray, depthCubeArraySmplr, texBuffer, spvAuxBuffer);
+    constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
+    constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
+    constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2];
+    constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3];
+    constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4];
+    constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5];
+    constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7];
+    constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8];
+    constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9];
+    constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[10];
+    float4 c = doSwizzle(tex1d, tex1dSmplr, tex1dSwzl, tex2d, tex2dSmplr, tex2dSwzl, tex3d, tex3dSmplr, tex3dSwzl, texCube, texCubeSmplr, texCubeSwzl, tex2dArray, tex2dArraySmplr, tex2dArraySwzl, texCubeArray, texCubeArraySmplr, texCubeArraySwzl, depth2d, depth2dSmplr, depth2dSwzl, depthCube, depthCubeSmplr, depthCubeSwzl, depth2dArray, depth2dArraySmplr, depth2dArraySwzl, depthCubeArray, depthCubeArraySmplr, depthCubeArraySwzl, texBuffer, spvAuxBuffer);
 }
 }
 
 

+ 34 - 28
3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access-uint.swizzle.frag

@@ -78,7 +78,7 @@ inline T spvTextureSwizzle(T x, uint s)
 
 
 // Wrapper function that swizzles texture gathers.
 // Wrapper function that swizzles texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -115,7 +115,7 @@ inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, compon
 
 
 // Wrapper function that swizzles depth texture gathers.
 // Wrapper function that swizzles depth texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params, uint sw) 
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) 
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -138,32 +138,38 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params,
 
 
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<uint> tex1d [[texture(0)]], texture2d<uint> tex2d [[texture(1)]], texture3d<uint> tex3d [[texture(2)]], texturecube<uint> texCube [[texture(3)]], texture2d_array<uint> tex2dArray [[texture(4)]], texturecube_array<uint> texCubeArray [[texture(5)]], texture2d<uint> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<uint> tex1d [[texture(0)]], texture2d<uint> tex2d [[texture(1)]], texture3d<uint> tex3d [[texture(2)]], texturecube<uint> texCube [[texture(3)]], texture2d_array<uint> tex2dArray [[texture(4)]], texturecube_array<uint> texCubeArray [[texture(5)]], texture2d<uint> texBuffer [[texture(6)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]])
 {
 {
-    float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]));
-    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]));
-    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]));
-    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]));
-    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]));
-    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]));
-    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]));
-    c = float4(spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]));
-    c = float4(spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]));
+    constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
+    constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
+    constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2];
+    constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3];
+    constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4];
+    constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5];
+    float4 c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl));
+    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), texCubeSwzl));
+    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), tex2dArraySwzl));
+    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), texCubeArraySwzl));
+    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), tex3dSwzl));
+    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), tex3dSwzl));
+    c = float4(spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), texCubeSwzl));
+    c = float4(spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), tex2dArraySwzl));
+    c = float4(spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), texCubeArraySwzl));
+    c = float4(spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), tex3dSwzl));
+    c = float4(spvTextureSwizzle(tex1d.read(uint(0)), tex1dSwzl));
+    c = float4(spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), tex2dSwzl));
+    c = float4(spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), tex3dSwzl));
+    c = float4(spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), tex2dArraySwzl));
     c = float4(texBuffer.read(spvTexelBufferCoord(0)));
     c = float4(texBuffer.read(spvTexelBufferCoord(0)));
-    c = float4(spvGatherSwizzle<uint, metal::texture2d<uint>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]));
-    c = float4(spvGatherSwizzle<uint, metal::texturecube<uint>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]));
-    c = float4(spvGatherSwizzle<uint, metal::texture2d_array<uint>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]));
-    c = float4(spvGatherSwizzle<uint, metal::texturecube_array<uint>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]));
+    c = float4(spvGatherSwizzle<uint, metal::texture2d<uint>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, tex2dSwzl));
+    c = float4(spvGatherSwizzle<uint, metal::texturecube<uint>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, texCubeSwzl));
+    c = float4(spvGatherSwizzle<uint, metal::texture2d_array<uint>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, tex2dArraySwzl));
+    c = float4(spvGatherSwizzle<uint, metal::texturecube_array<uint>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, texCubeArraySwzl));
 }
 }
 
 

+ 49 - 39
3rdparty/spirv-cross/reference/shaders-msl-no-opt/frag/texture-access.swizzle.frag

@@ -78,7 +78,7 @@ inline T spvTextureSwizzle(T x, uint s)
 
 
 // Wrapper function that swizzles texture gathers.
 // Wrapper function that swizzles texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -115,7 +115,7 @@ inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, compon
 
 
 // Wrapper function that swizzles depth texture gathers.
 // Wrapper function that swizzles depth texture gathers.
 template<typename T, typename Tex, typename... Ts>
 template<typename T, typename Tex, typename... Ts>
-inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params, uint sw) 
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) 
 {
 {
     if (sw)
     if (sw)
     {
     {
@@ -138,47 +138,57 @@ inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params,
 
 
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
 fragment void main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]])
 {
 {
-    float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvAuxBuffer.swizzleConst[3]);
-    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvAuxBuffer.swizzleConst[4]);
-    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvAuxBuffer.swizzleConst[5]);
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
-    c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[8]);
-    c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[9]);
-    c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvAuxBuffer.swizzleConst[10]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), spvAuxBuffer.swizzleConst[2]);
+    constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
+    constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
+    constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2];
+    constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3];
+    constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4];
+    constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5];
+    constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7];
+    constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8];
+    constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9];
+    constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[10];
+    float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl);
+    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), texCubeSwzl);
+    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), tex2dArraySwzl);
+    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), texCubeArraySwzl);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), depth2dSwzl);
+    c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), depthCubeSwzl);
+    c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), depth2dArraySwzl);
+    c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), depthCubeArraySwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), tex3dSwzl);
     float4 _100 = float4(0.0, 0.0, 1.0, 1.0);
     float4 _100 = float4(0.0, 0.0, 1.0, 1.0);
     _100.z = float4(0.0, 0.0, 1.0, 1.0).w;
     _100.z = float4(0.0, 0.0, 1.0, 1.0).w;
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _100.xy / _100.z, float4(0.0, 0.0, 1.0, 1.0).z), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvAuxBuffer.swizzleConst[3]);
-    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvAuxBuffer.swizzleConst[4]);
-    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvAuxBuffer.swizzleConst[5]);
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), spvAuxBuffer.swizzleConst[2]);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _100.xy / _100.z, float4(0.0, 0.0, 1.0, 1.0).z), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), tex3dSwzl);
+    c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), texCubeSwzl);
+    c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), tex2dArraySwzl);
+    c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), texCubeArraySwzl);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), tex3dSwzl);
     float4 _128 = float4(0.0, 0.0, 1.0, 1.0);
     float4 _128 = float4(0.0, 0.0, 1.0, 1.0);
     _128.z = float4(0.0, 0.0, 1.0, 1.0).w;
     _128.z = float4(0.0, 0.0, 1.0, 1.0).w;
-    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _128.xy / _128.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvAuxBuffer.swizzleConst[7]);
-    c = spvTextureSwizzle(tex1d.read(uint(0)), spvAuxBuffer.swizzleConst[0]);
-    c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvAuxBuffer.swizzleConst[1]);
-    c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvAuxBuffer.swizzleConst[2]);
-    c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvAuxBuffer.swizzleConst[4]);
+    c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _128.xy / _128.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), depth2dSwzl);
+    c = spvTextureSwizzle(tex1d.read(uint(0)), tex1dSwzl);
+    c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), tex2dSwzl);
+    c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), tex3dSwzl);
+    c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), tex2dArraySwzl);
     c = texBuffer.read(spvTexelBufferCoord(0));
     c = texBuffer.read(spvTexelBufferCoord(0));
-    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvAuxBuffer.swizzleConst[1]);
-    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvAuxBuffer.swizzleConst[3]);
-    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvAuxBuffer.swizzleConst[4]);
-    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvAuxBuffer.swizzleConst[5]);
-    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(depth2dSmplr, depth2d, float2(0.0), 1.0, spvAuxBuffer.swizzleConst[7]);
-    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(depthCubeSmplr, depthCube, float3(0.0), 1.0, spvAuxBuffer.swizzleConst[8]);
-    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(depth2dArraySmplr, depth2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, spvAuxBuffer.swizzleConst[9]);
-    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(depthCubeArraySmplr, depthCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, spvAuxBuffer.swizzleConst[10]);
+    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, tex2dSwzl);
+    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(texCubeSmplr, texCube, float3(0.0), component::y, texCubeSwzl);
+    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, tex2dArraySwzl);
+    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, texCubeArraySwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(depth2dSmplr, depth2d, float2(0.0), 1.0, depth2dSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(depthCubeSmplr, depthCube, float3(0.0), 1.0, depthCubeSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(depth2dArraySmplr, depth2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, depth2dArraySwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(depthCubeArraySmplr, depthCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, depthCubeArraySwzl);
 }
 }
 
 

+ 60 - 0
3rdparty/spirv-cross/reference/shaders-msl-no-opt/vert/pass-array-by-value.vert

@@ -0,0 +1,60 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+constant float4 _68[4] = { float4(0.0), float4(1.0), float4(2.0), float4(3.0) };
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_in
+{
+    int Index1 [[attribute(0)]];
+    int Index2 [[attribute(1)]];
+};
+
+// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
+template<typename T, uint N>
+void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
+{
+    for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+template<typename T, uint N>
+void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
+{
+    for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+float4 consume_constant_arrays2(thread const float4 (&positions)[4], thread const float4 (&positions2)[4], thread int& Index1, thread int& Index2)
+{
+    float4 indexable[4];
+    spvArrayCopyFromStack1(indexable, positions);
+    float4 indexable_1[4];
+    spvArrayCopyFromStack1(indexable_1, positions2);
+    return indexable[Index1] + indexable_1[Index2];
+}
+
+float4 consume_constant_arrays(thread const float4 (&positions)[4], thread const float4 (&positions2)[4], thread int& Index1, thread int& Index2)
+{
+    return consume_constant_arrays2(positions, positions2, Index1, Index2);
+}
+
+vertex main0_out main0(main0_in in [[stage_in]])
+{
+    float4 _68_array_copy[4] = { float4(0.0), float4(1.0), float4(2.0), float4(3.0) };
+    main0_out out = {};
+    float4 LUT2[4];
+    LUT2[0] = float4(10.0);
+    LUT2[1] = float4(11.0);
+    LUT2[2] = float4(12.0);
+    LUT2[3] = float4(13.0);
+    out.gl_Position = consume_constant_arrays(_68_array_copy, LUT2, in.Index1, in.Index2);
+    return out;
+}
+

+ 207 - 0
3rdparty/spirv-cross/reference/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag

@@ -0,0 +1,207 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct spvAux
+{
+    uint swizzleConst[1];
+};
+
+struct main0_out
+{
+    float4 fragColor [[color(0)]];
+};
+
+// Returns 2D texture coords corresponding to 1D texel buffer coords
+uint2 spvTexelBufferCoord(uint tc)
+{
+    return uint2(tc % 4096, tc / 4096);
+}
+
+enum class spvSwizzle : uint
+{
+    none = 0,
+    zero,
+    one,
+    red,
+    green,
+    blue,
+    alpha
+};
+
+template<typename T> struct spvRemoveReference { typedef T type; };
+template<typename T> struct spvRemoveReference<thread T&> { typedef T type; };
+template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; };
+template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type& x)
+{
+    return static_cast<thread T&&>(x);
+}
+template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type&& x)
+{
+    return static_cast<thread T&&>(x);
+}
+
+template<typename T>
+inline T spvGetSwizzle(vec<T, 4> x, T c, spvSwizzle s)
+{
+    switch (s)
+    {
+        case spvSwizzle::none:
+            return c;
+        case spvSwizzle::zero:
+            return 0;
+        case spvSwizzle::one:
+            return 1;
+        case spvSwizzle::red:
+            return x.r;
+        case spvSwizzle::green:
+            return x.g;
+        case spvSwizzle::blue:
+            return x.b;
+        case spvSwizzle::alpha:
+            return x.a;
+    }
+}
+
+// Wrapper function that swizzles texture samples and fetches.
+template<typename T>
+inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s)
+{
+    if (!s)
+        return x;
+    return vec<T, 4>(spvGetSwizzle(x, x.r, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, x.g, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, x.b, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, x.a, spvSwizzle((s >> 24) & 0xFF)));
+}
+
+template<typename T>
+inline T spvTextureSwizzle(T x, uint s)
+{
+    return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x;
+}
+
+// Wrapper function that swizzles texture gathers.
+template<typename T, typename Tex, typename... Ts>
+inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c)
+{
+    if (sw)
+    {
+        switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF))
+        {
+            case spvSwizzle::none:
+                break;
+            case spvSwizzle::zero:
+                return vec<T, 4>(0, 0, 0, 0);
+            case spvSwizzle::one:
+                return vec<T, 4>(1, 1, 1, 1);
+            case spvSwizzle::red:
+                return t.gather(s, spvForward<Ts>(params)..., component::x);
+            case spvSwizzle::green:
+                return t.gather(s, spvForward<Ts>(params)..., component::y);
+            case spvSwizzle::blue:
+                return t.gather(s, spvForward<Ts>(params)..., component::z);
+            case spvSwizzle::alpha:
+                return t.gather(s, spvForward<Ts>(params)..., component::w);
+        }
+    }
+    switch (c)
+    {
+        case component::x:
+            return t.gather(s, spvForward<Ts>(params)..., component::x);
+        case component::y:
+            return t.gather(s, spvForward<Ts>(params)..., component::y);
+        case component::z:
+            return t.gather(s, spvForward<Ts>(params)..., component::z);
+        case component::w:
+            return t.gather(s, spvForward<Ts>(params)..., component::w);
+    }
+}
+
+// Wrapper function that swizzles depth texture gathers.
+template<typename T, typename Tex, typename... Ts>
+inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) 
+{
+    if (sw)
+    {
+        switch (spvSwizzle(sw & 0xFF))
+        {
+            case spvSwizzle::none:
+            case spvSwizzle::red:
+                break;
+            case spvSwizzle::zero:
+            case spvSwizzle::green:
+            case spvSwizzle::blue:
+            case spvSwizzle::alpha:
+                return vec<T, 4>(0, 0, 0, 0);
+            case spvSwizzle::one:
+                return vec<T, 4>(1, 1, 1, 1);
+        }
+    }
+    return t.gather_compare(s, spvForward<Ts>(params)...);
+}
+
+float4 do_samples(thread const texture1d<float> t1, thread const sampler t1Smplr, constant uint32_t& t1Swzl, thread const texture2d<float> t2, constant uint32_t& t2Swzl, thread const texture3d<float> t3, thread const sampler t3Smplr, constant uint32_t& t3Swzl, thread const texturecube<float> tc, constant uint32_t& tcSwzl, thread const texture2d_array<float> t2a, thread const sampler t2aSmplr, constant uint32_t& t2aSwzl, thread const texturecube_array<float> tca, thread const sampler tcaSmplr, constant uint32_t& tcaSwzl, thread const texture2d<float> tb, thread const depth2d<float> d2, thread const sampler d2Smplr, constant uint32_t& d2Swzl, thread const depthcube<float> dc, thread const sampler dcSmplr, constant uint32_t& dcSwzl, thread const depth2d_array<float> d2a, constant uint32_t& d2aSwzl, thread const depthcube_array<float> dca, thread const sampler dcaSmplr, constant uint32_t& dcaSwzl, thread sampler defaultSampler, thread sampler shadowSampler, constant spvAux& spvAuxBuffer)
+{
+    float4 c = spvTextureSwizzle(t1.sample(t1Smplr, 0.0), t1Swzl);
+    c = spvTextureSwizzle(t2.sample(defaultSampler, float2(0.0)), t2Swzl);
+    c = spvTextureSwizzle(t3.sample(t3Smplr, float3(0.0)), t3Swzl);
+    c = spvTextureSwizzle(tc.sample(defaultSampler, float3(0.0)), tcSwzl);
+    c = spvTextureSwizzle(t2a.sample(t2aSmplr, float3(0.0).xy, uint(round(float3(0.0).z))), t2aSwzl);
+    c = spvTextureSwizzle(tca.sample(tcaSmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), tcaSwzl);
+    c.x = spvTextureSwizzle(d2.sample_compare(d2Smplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), d2Swzl);
+    c.x = spvTextureSwizzle(dc.sample_compare(dcSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), dcSwzl);
+    c.x = spvTextureSwizzle(d2a.sample_compare(shadowSampler, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), float4(0.0, 0.0, 0.0, 1.0).w), d2aSwzl);
+    c.x = spvTextureSwizzle(dca.sample_compare(dcaSmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), dcaSwzl);
+    c = spvTextureSwizzle(t1.sample(t1Smplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), t1Swzl);
+    c = spvTextureSwizzle(t2.sample(defaultSampler, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), t2Swzl);
+    c = spvTextureSwizzle(t3.sample(t3Smplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), t3Swzl);
+    float4 _119 = float4(0.0, 0.0, 1.0, 1.0);
+    _119.z = float4(0.0, 0.0, 1.0, 1.0).w;
+    c.x = spvTextureSwizzle(d2.sample_compare(d2Smplr, _119.xy / _119.z, float4(0.0, 0.0, 1.0, 1.0).z), d2Swzl);
+    c = spvTextureSwizzle(t1.sample(t1Smplr, 0.0), t1Swzl);
+    c = spvTextureSwizzle(t2.sample(defaultSampler, float2(0.0), level(0.0)), t2Swzl);
+    c = spvTextureSwizzle(t3.sample(t3Smplr, float3(0.0), level(0.0)), t3Swzl);
+    c = spvTextureSwizzle(tc.sample(defaultSampler, float3(0.0), level(0.0)), tcSwzl);
+    c = spvTextureSwizzle(t2a.sample(t2aSmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), t2aSwzl);
+    c = spvTextureSwizzle(tca.sample(tcaSmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), tcaSwzl);
+    c.x = spvTextureSwizzle(d2.sample_compare(d2Smplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), d2Swzl);
+    c = spvTextureSwizzle(t1.sample(t1Smplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), t1Swzl);
+    c = spvTextureSwizzle(t2.sample(defaultSampler, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), t2Swzl);
+    c = spvTextureSwizzle(t3.sample(t3Smplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), t3Swzl);
+    float4 _153 = float4(0.0, 0.0, 1.0, 1.0);
+    _153.z = float4(0.0, 0.0, 1.0, 1.0).w;
+    c.x = spvTextureSwizzle(d2.sample_compare(d2Smplr, _153.xy / _153.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), d2Swzl);
+    c = spvTextureSwizzle(t1.read(uint(0)), t1Swzl);
+    c = spvTextureSwizzle(t2.read(uint2(int2(0)), 0), t2Swzl);
+    c = spvTextureSwizzle(t3.read(uint3(int3(0)), 0), t3Swzl);
+    c = spvTextureSwizzle(t2a.read(uint2(int3(0).xy), uint(int3(0).z), 0), t2aSwzl);
+    c = tb.read(spvTexelBufferCoord(0));
+    c = spvGatherSwizzle<float, metal::texture2d<float>, float2, int2>(defaultSampler, t2, float2(0.0), int2(0), component::x, t2Swzl);
+    c = spvGatherSwizzle<float, metal::texturecube<float>, float3>(defaultSampler, tc, float3(0.0), component::y, tcSwzl);
+    c = spvGatherSwizzle<float, metal::texture2d_array<float>, float2, uint, int2>(t2aSmplr, t2a, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, t2aSwzl);
+    c = spvGatherSwizzle<float, metal::texturecube_array<float>, float3, uint>(tcaSmplr, tca, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, tcaSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d<float>, float2, float>(d2Smplr, d2, float2(0.0), 1.0, d2Swzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube<float>, float3, float>(dcSmplr, dc, float3(0.0), 1.0, dcSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depth2d_array<float>, float2, uint, float>(shadowSampler, d2a, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0, d2aSwzl);
+    c = spvGatherCompareSwizzle<float, metal::depthcube_array<float>, float3, uint, float>(dcaSmplr, dca, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0, dcaSwzl);
+    return c;
+}
+
+fragment main0_out main0(constant spvAux& spvAuxBuffer [[buffer(0)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], texture2d<float> texBuffer [[texture(6)]], depth2d<float> depth2d [[texture(7)]], depthcube<float> depthCube [[texture(8)]], depth2d_array<float> depth2dArray [[texture(9)]], depthcube_array<float> depthCubeArray [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex3dSmplr [[sampler(2)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depthCubeArraySmplr [[sampler(10)]], sampler defaultSampler [[sampler(11)]], sampler shadowSampler [[sampler(12)]])
+{
+    main0_out out = {};
+    constant uint32_t& tex1dSwzl = spvAuxBuffer.swizzleConst[0];
+    constant uint32_t& tex2dSwzl = spvAuxBuffer.swizzleConst[1];
+    constant uint32_t& tex3dSwzl = spvAuxBuffer.swizzleConst[2];
+    constant uint32_t& texCubeSwzl = spvAuxBuffer.swizzleConst[3];
+    constant uint32_t& tex2dArraySwzl = spvAuxBuffer.swizzleConst[4];
+    constant uint32_t& texCubeArraySwzl = spvAuxBuffer.swizzleConst[5];
+    constant uint32_t& depth2dSwzl = spvAuxBuffer.swizzleConst[7];
+    constant uint32_t& depthCubeSwzl = spvAuxBuffer.swizzleConst[8];
+    constant uint32_t& depth2dArraySwzl = spvAuxBuffer.swizzleConst[9];
+    constant uint32_t& depthCubeArraySwzl = spvAuxBuffer.swizzleConst[10];
+    out.fragColor = do_samples(tex1d, tex1dSmplr, tex1dSwzl, tex2d, tex2dSwzl, tex3d, tex3dSmplr, tex3dSwzl, texCube, texCubeSwzl, tex2dArray, tex2dArraySmplr, tex2dArraySwzl, texCubeArray, texCubeArraySmplr, texCubeArraySwzl, texBuffer, depth2d, depth2dSmplr, depth2dSwzl, depthCube, depthCubeSmplr, depthCubeSwzl, depth2dArray, depth2dArraySwzl, depthCubeArray, depthCubeArraySmplr, depthCubeArraySwzl, defaultSampler, shadowSampler, spvAuxBuffer);
+    return out;
+}
+

+ 5 - 5
3rdparty/spirv-cross/reference/shaders-msl/asm/comp/specialization-constant-workgroup.asm.comp

@@ -3,17 +3,17 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
+struct SSBO
+{
+    float a;
+};
+
 constant uint _5_tmp [[function_constant(10)]];
 constant uint _5_tmp [[function_constant(10)]];
 constant uint _5 = is_function_constant_defined(_5_tmp) ? _5_tmp : 9u;
 constant uint _5 = is_function_constant_defined(_5_tmp) ? _5_tmp : 9u;
 constant uint _6_tmp [[function_constant(12)]];
 constant uint _6_tmp [[function_constant(12)]];
 constant uint _6 = is_function_constant_defined(_6_tmp) ? _6_tmp : 4u;
 constant uint _6 = is_function_constant_defined(_6_tmp) ? _6_tmp : 4u;
 constant uint3 gl_WorkGroupSize = uint3(_5, 20u, _6);
 constant uint3 gl_WorkGroupSize = uint3(_5, 20u, _6);
 
 
-struct SSBO
-{
-    float a;
-};
-
 kernel void main0(device SSBO& _4 [[buffer(0)]])
 kernel void main0(device SSBO& _4 [[buffer(0)]])
 {
 {
     _4.a += 1.0;
     _4.a += 1.0;

+ 5 - 5
3rdparty/spirv-cross/reference/shaders-msl/asm/comp/storage-buffer-basic.invalid.asm.comp

@@ -3,17 +3,17 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
+struct _6
+{
+    float _m0[1];
+};
+
 constant uint _3_tmp [[function_constant(0)]];
 constant uint _3_tmp [[function_constant(0)]];
 constant uint _3 = is_function_constant_defined(_3_tmp) ? _3_tmp : 1u;
 constant uint _3 = is_function_constant_defined(_3_tmp) ? _3_tmp : 1u;
 constant uint _4_tmp [[function_constant(2)]];
 constant uint _4_tmp [[function_constant(2)]];
 constant uint _4 = is_function_constant_defined(_4_tmp) ? _4_tmp : 3u;
 constant uint _4 = is_function_constant_defined(_4_tmp) ? _4_tmp : 3u;
 constant uint3 gl_WorkGroupSize = uint3(_3, 2u, _4);
 constant uint3 gl_WorkGroupSize = uint3(_3, 2u, _4);
 
 
-struct _6
-{
-    float _m0[1];
-};
-
 kernel void main0(device _6& _8 [[buffer(0)]], device _6& _9 [[buffer(1)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
 kernel void main0(device _6& _8 [[buffer(0)]], device _6& _9 [[buffer(1)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]])
 {
 {
     _8._m0[gl_WorkGroupID.x] = _9._m0[gl_WorkGroupID.x] + _8._m0[gl_WorkGroupID.x];
     _8._m0[gl_WorkGroupID.x] = _9._m0[gl_WorkGroupID.x] + _8._m0[gl_WorkGroupID.x];

+ 2 - 2
3rdparty/spirv-cross/reference/shaders-msl/asm/comp/vector-builtin-type-cast-func.asm.comp

@@ -5,13 +5,13 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
-
 struct cb1_struct
 struct cb1_struct
 {
 {
     float4 _m0[1];
     float4 _m0[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
+
 int2 get_texcoord(thread const int2& base, thread const int2& index, thread uint3& gl_LocalInvocationID)
 int2 get_texcoord(thread const int2& base, thread const int2& index, thread uint3& gl_LocalInvocationID)
 {
 {
     return (base * int3(gl_LocalInvocationID).xy) + index;
     return (base * int3(gl_LocalInvocationID).xy) + index;

+ 2 - 2
3rdparty/spirv-cross/reference/shaders-msl/asm/comp/vector-builtin-type-cast.asm.comp

@@ -3,13 +3,13 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
-
 struct cb1_struct
 struct cb1_struct
 {
 {
     float4 _m0[1];
     float4 _m0[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(16u, 16u, 1u);
+
 kernel void main0(constant cb1_struct& cb0_1 [[buffer(0)]], texture2d<float, access::write> u0 [[texture(1)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 kernel void main0(constant cb1_struct& cb0_1 [[buffer(0)]], texture2d<float, access::write> u0 [[texture(1)]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 {
 {
     int2 r0 = int2(int2(u0.get_width(), u0.get_height()) >> int2(uint2(4u)));
     int2 r0 = int2(int2(u0.get_width(), u0.get_height()) >> int2(uint2(4u)));

+ 4 - 4
3rdparty/spirv-cross/reference/shaders-msl/asm/frag/extract-packed-from-composite.asm.frag

@@ -7,19 +7,19 @@ using namespace metal;
 
 
 struct Foo
 struct Foo
 {
 {
-    float3 a;
+    packed_float3 a;
     float b;
     float b;
 };
 };
 
 
 struct Foo_1
 struct Foo_1
 {
 {
-    packed_float3 a;
+    float3 a;
     float b;
     float b;
 };
 };
 
 
 struct buf
 struct buf
 {
 {
-    Foo_1 results[16];
+    Foo results[16];
     float4 bar;
     float4 bar;
 };
 };
 
 
@@ -31,7 +31,7 @@ struct main0_out
 float4 _main(thread const float4& pos, constant buf& v_11)
 float4 _main(thread const float4& pos, constant buf& v_11)
 {
 {
     int _46 = int(pos.x) % 16;
     int _46 = int(pos.x) % 16;
-    Foo foo;
+    Foo_1 foo;
     foo.a = v_11.results[_46].a;
     foo.a = v_11.results[_46].a;
     foo.b = v_11.results[_46].b;
     foo.b = v_11.results[_46].b;
     return float4(dot(foo.a, v_11.bar.xyz), foo.b, 0.0, 0.0);
     return float4(dot(foo.a, v_11.bar.xyz), foo.b, 0.0, 0.0);

+ 5 - 5
3rdparty/spirv-cross/reference/shaders-msl/asm/frag/vector-shuffle-oom.asm.frag

@@ -3,6 +3,11 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
+struct _28
+{
+    float4 _m0;
+};
+
 struct _6
 struct _6
 {
 {
     float4 _m0;
     float4 _m0;
@@ -113,11 +118,6 @@ struct _21
     float4 _m0;
     float4 _m0;
 };
 };
 
 
-struct _28
-{
-    float4 _m0;
-};
-
 constant _28 _74 = {};
 constant _28 _74 = {};
 
 
 struct main0_out
 struct main0_out

+ 3 - 3
3rdparty/spirv-cross/reference/shaders-msl/asm/vert/spec-constant-op-composite.asm.vert

@@ -5,15 +5,15 @@ using namespace metal;
 
 
 constant int _7_tmp [[function_constant(201)]];
 constant int _7_tmp [[function_constant(201)]];
 constant int _7 = is_function_constant_defined(_7_tmp) ? _7_tmp : -10;
 constant int _7 = is_function_constant_defined(_7_tmp) ? _7_tmp : -10;
+constant int _20 = (_7 + 2);
 constant uint _8_tmp [[function_constant(202)]];
 constant uint _8_tmp [[function_constant(202)]];
 constant uint _8 = is_function_constant_defined(_8_tmp) ? _8_tmp : 100u;
 constant uint _8 = is_function_constant_defined(_8_tmp) ? _8_tmp : 100u;
-constant float _9_tmp [[function_constant(200)]];
-constant float _9 = is_function_constant_defined(_9_tmp) ? _9_tmp : 3.141590118408203125;
-constant int _20 = (_7 + 2);
 constant uint _25 = (_8 % 5u);
 constant uint _25 = (_8 % 5u);
 constant int4 _30 = int4(20, 30, _20, _20);
 constant int4 _30 = int4(20, 30, _20, _20);
 constant int2 _32 = int2(_30.y, _30.x);
 constant int2 _32 = int2(_30.y, _30.x);
 constant int _33 = _30.y;
 constant int _33 = _30.y;
+constant float _9_tmp [[function_constant(200)]];
+constant float _9 = is_function_constant_defined(_9_tmp) ? _9_tmp : 3.141590118408203125;
 
 
 struct main0_out
 struct main0_out
 {
 {

+ 15 - 14
3rdparty/spirv-cross/reference/shaders-msl/comp/composite-array-initialization.comp

@@ -5,10 +5,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant float X_tmp [[function_constant(0)]];
-constant float X = is_function_constant_defined(X_tmp) ? X_tmp : 4.0;
-constant uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
-
 struct Data
 struct Data
 {
 {
     float a;
     float a;
@@ -21,12 +17,17 @@ struct Data_1
     float b;
     float b;
 };
 };
 
 
+constant float X_tmp [[function_constant(0)]];
+constant float X = is_function_constant_defined(X_tmp) ? X_tmp : 4.0;
+
 struct SSBO
 struct SSBO
 {
 {
-    Data_1 outdata[1];
+    Data outdata[1];
 };
 };
 
 
-constant Data _25[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
+constant uint3 gl_WorkGroupSize = uint3(2u, 1u, 1u);
+
+constant Data_1 _25[2] = { Data_1{ 1.0, 2.0 }, Data_1{ 3.0, 4.0 } };
 
 
 // Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
 // Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
 template<typename T, uint N>
 template<typename T, uint N>
@@ -41,20 +42,20 @@ void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
     for (uint i = 0; i < N; dst[i] = src[i], i++);
     for (uint i = 0; i < N; dst[i] = src[i], i++);
 }
 }
 
 
-Data combine(thread const Data& a, thread const Data& b)
+Data_1 combine(thread const Data_1& a, thread const Data_1& b)
 {
 {
-    return Data{ a.a + b.a, a.b + b.b };
+    return Data_1{ a.a + b.a, a.b + b.b };
 }
 }
 
 
 kernel void main0(device SSBO& _53 [[buffer(0)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 kernel void main0(device SSBO& _53 [[buffer(0)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
 {
 {
-    Data data[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
-    Data _31[2] = { Data{ X, 2.0 }, Data{ 3.0, 5.0 } };
-    Data data2[2];
+    Data_1 data[2] = { Data_1{ 1.0, 2.0 }, Data_1{ 3.0, 4.0 } };
+    Data_1 _31[2] = { Data_1{ X, 2.0 }, Data_1{ 3.0, 5.0 } };
+    Data_1 data2[2];
     spvArrayCopyFromStack1(data2, _31);
     spvArrayCopyFromStack1(data2, _31);
-    Data param = data[gl_LocalInvocationID.x];
-    Data param_1 = data2[gl_LocalInvocationID.x];
-    Data _73 = combine(param, param_1);
+    Data_1 param = data[gl_LocalInvocationID.x];
+    Data_1 param_1 = data2[gl_LocalInvocationID.x];
+    Data_1 _73 = combine(param, param_1);
     _53.outdata[gl_WorkGroupID.x].a = _73.a;
     _53.outdata[gl_WorkGroupID.x].a = _73.a;
     _53.outdata[gl_WorkGroupID.x].b = _73.b;
     _53.outdata[gl_WorkGroupID.x].b = _73.b;
 }
 }

+ 2 - 2
3rdparty/spirv-cross/reference/shaders-msl/comp/culling.comp

@@ -6,8 +6,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
-
 struct SSBO
 struct SSBO
 {
 {
     float in_data[1];
     float in_data[1];
@@ -23,6 +21,8 @@ struct SSBO3
     uint count;
     uint count;
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
+
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _38 [[buffer(1)]], device SSBO3& _41 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _38 [[buffer(1)]], device SSBO3& _41 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     uint ident = gl_GlobalInvocationID.x;
     uint ident = gl_GlobalInvocationID.x;

+ 6 - 6
3rdparty/spirv-cross/reference/shaders-msl/comp/packing-test-1.comp

@@ -3,23 +3,21 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
-
 struct T1
 struct T1
 {
 {
-    float3 a;
+    packed_float3 a;
     float b;
     float b;
 };
 };
 
 
 struct T1_1
 struct T1_1
 {
 {
-    packed_float3 a;
+    float3 a;
     float b;
     float b;
 };
 };
 
 
 struct Buffer0
 struct Buffer0
 {
 {
-    T1_1 buf0[1];
+    T1 buf0[1];
 };
 };
 
 
 struct Buffer1
 struct Buffer1
@@ -27,9 +25,11 @@ struct Buffer1
     float buf1[1];
     float buf1[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
+
 kernel void main0(device Buffer0& _15 [[buffer(1)]], device Buffer1& _34 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device Buffer0& _15 [[buffer(1)]], device Buffer1& _34 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
-    T1 v;
+    T1_1 v;
     v.a = _15.buf0[0].a;
     v.a = _15.buf0[0].a;
     v.b = _15.buf0[0].b;
     v.b = _15.buf0[0].b;
     float x = v.b;
     float x = v.b;

+ 2 - 2
3rdparty/spirv-cross/reference/shaders-msl/comp/packing-test-2.comp

@@ -3,8 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
-
 struct T1
 struct T1
 {
 {
     packed_float3 a;
     packed_float3 a;
@@ -21,6 +19,8 @@ struct Buffer1
     float buf1[1];
     float buf1[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(32u, 1u, 1u);
+
 kernel void main0(device Buffer0& _14 [[buffer(1)]], device Buffer1& _24 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device Buffer0& _14 [[buffer(1)]], device Buffer1& _24 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     float x = _14.buf0[0].b;
     float x = _14.buf0[0].b;

+ 2 - 2
3rdparty/spirv-cross/reference/shaders-msl/comp/shared-array-of-arrays.comp

@@ -5,13 +5,13 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(4u, 4u, 1u);
-
 struct SSBO
 struct SSBO
 {
 {
     float out_data[1];
     float out_data[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(4u, 4u, 1u);
+
 void work(threadgroup float (&foo)[4][4], thread uint3& gl_LocalInvocationID, thread uint& gl_LocalInvocationIndex, device SSBO& v_67, thread uint3& gl_GlobalInvocationID)
 void work(threadgroup float (&foo)[4][4], thread uint3& gl_LocalInvocationID, thread uint& gl_LocalInvocationIndex, device SSBO& v_67, thread uint3& gl_GlobalInvocationID)
 {
 {
     foo[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = float(gl_LocalInvocationIndex);
     foo[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = float(gl_LocalInvocationIndex);

+ 2 - 2
3rdparty/spirv-cross/reference/shaders-msl/comp/shared.comp

@@ -3,8 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
-
 struct SSBO
 struct SSBO
 {
 {
     float in_data[1];
     float in_data[1];
@@ -15,6 +13,8 @@ struct SSBO2
     float out_data[1];
     float out_data[1];
 };
 };
 
 
+constant uint3 gl_WorkGroupSize = uint3(4u, 1u, 1u);
+
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _44 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
 kernel void main0(const device SSBO& _22 [[buffer(0)]], device SSBO2& _44 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
 {
 {
     threadgroup float sShared[4];
     threadgroup float sShared[4];

+ 9 - 7
3rdparty/spirv-cross/reference/shaders-msl/comp/spec-constant-op-member-array.comp

@@ -11,13 +11,6 @@ constant int a = SPIRV_CROSS_CONSTANT_ID_0;
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #endif
 #endif
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
-#ifndef SPIRV_CROSS_CONSTANT_ID_2
-#define SPIRV_CROSS_CONSTANT_ID_2 300
-#endif
-constant int c = SPIRV_CROSS_CONSTANT_ID_2;
-constant int _18 = (c + 50);
-constant int e_tmp [[function_constant(3)]];
-constant int e = is_function_constant_defined(e_tmp) ? e_tmp : 400;
 
 
 struct A
 struct A
 {
 {
@@ -31,6 +24,12 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_2
+#define SPIRV_CROSS_CONSTANT_ID_2 300
+#endif
+constant int c = SPIRV_CROSS_CONSTANT_ID_2;
+constant int _18 = (c + 50);
+
 struct SSBO
 struct SSBO
 {
 {
     A member_a;
     A member_a;
@@ -39,6 +38,9 @@ struct SSBO
     int w[_18];
     int w[_18];
 };
 };
 
 
+constant int e_tmp [[function_constant(3)]];
+constant int e = is_function_constant_defined(e_tmp) ? e_tmp : 400;
+
 kernel void main0(device SSBO& _22 [[buffer(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device SSBO& _22 [[buffer(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
     _22.w[gl_GlobalInvocationID.x] += (_22.v[gl_GlobalInvocationID.x] + e);
     _22.w[gl_GlobalInvocationID.x] += (_22.v[gl_GlobalInvocationID.x] + e);

+ 6 - 5
3rdparty/spirv-cross/reference/shaders-msl/comp/spec-constant-work-group-size.comp

@@ -9,6 +9,12 @@ using namespace metal;
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
 constant int b = SPIRV_CROSS_CONSTANT_ID_1;
 constant int a_tmp [[function_constant(0)]];
 constant int a_tmp [[function_constant(0)]];
 constant int a = is_function_constant_defined(a_tmp) ? a_tmp : 1;
 constant int a = is_function_constant_defined(a_tmp) ? a_tmp : 1;
+
+struct SSBO
+{
+    int v[1];
+};
+
 constant uint _21 = (uint(a) + 0u);
 constant uint _21 = (uint(a) + 0u);
 constant uint _22_tmp [[function_constant(10)]];
 constant uint _22_tmp [[function_constant(10)]];
 constant uint _22 = is_function_constant_defined(_22_tmp) ? _22_tmp : 1u;
 constant uint _22 = is_function_constant_defined(_22_tmp) ? _22_tmp : 1u;
@@ -19,11 +25,6 @@ constant uint _29 = gl_WorkGroupSize.y;
 constant uint _30 = (_28 + _29);
 constant uint _30 = (_28 + _29);
 constant int _32 = (1 - a);
 constant int _32 = (1 - a);
 
 
-struct SSBO
-{
-    int v[1];
-};
-
 kernel void main0(device SSBO& _17 [[buffer(0)]])
 kernel void main0(device SSBO& _17 [[buffer(0)]])
 {
 {
     int spec_const_array_size[b];
     int spec_const_array_size[b];

+ 6 - 6
3rdparty/spirv-cross/reference/shaders-msl/comp/struct-nested.comp

@@ -13,24 +13,24 @@ struct s2
     s1 b;
     s1 b;
 };
 };
 
 
-struct s1_1
+struct s2_1
 {
 {
-    int a;
+    s1 b;
 };
 };
 
 
-struct s2_1
+struct s1_1
 {
 {
-    s1_1 b;
+    int a;
 };
 };
 
 
 struct dstbuffer
 struct dstbuffer
 {
 {
-    s2_1 test[1];
+    s2 test[1];
 };
 };
 
 
 kernel void main0(device dstbuffer& _19 [[buffer(1)]])
 kernel void main0(device dstbuffer& _19 [[buffer(1)]])
 {
 {
-    s2 testVal;
+    s2_1 testVal;
     testVal.b.a = 0;
     testVal.b.a = 0;
     _19.test[0].b.a = testVal.b.a;
     _19.test[0].b.a = testVal.b.a;
 }
 }

+ 13 - 13
3rdparty/spirv-cross/reference/shaders-msl/comp/type-alias.comp

@@ -10,29 +10,29 @@ struct S0
     float4 a;
     float4 a;
 };
 };
 
 
-struct S1
+struct S0_1
 {
 {
     float4 a;
     float4 a;
 };
 };
 
 
-struct S0_1
+struct S1
 {
 {
     float4 a;
     float4 a;
 };
 };
 
 
-struct SSBO0
+struct S1_1
 {
 {
-    S0_1 s0s[1];
+    float4 a;
 };
 };
 
 
-struct S1_1
+struct SSBO0
 {
 {
-    float4 a;
+    S0 s0s[1];
 };
 };
 
 
 struct SSBO1
 struct SSBO1
 {
 {
-    S1_1 s1s[1];
+    S1 s1s[1];
 };
 };
 
 
 struct SSBO2
 struct SSBO2
@@ -40,24 +40,24 @@ struct SSBO2
     float4 outputs[1];
     float4 outputs[1];
 };
 };
 
 
-float4 overload(thread const S0& s0)
+float4 overload(thread const S0_1& s0)
 {
 {
     return s0.a;
     return s0.a;
 }
 }
 
 
-float4 overload(thread const S1& s1)
+float4 overload(thread const S1_1& s1)
 {
 {
     return s1.a;
     return s1.a;
 }
 }
 
 
 kernel void main0(device SSBO0& _36 [[buffer(0)]], device SSBO1& _55 [[buffer(1)]], device SSBO2& _66 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 kernel void main0(device SSBO0& _36 [[buffer(0)]], device SSBO1& _55 [[buffer(1)]], device SSBO2& _66 [[buffer(2)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]])
 {
 {
-    S0 s0;
+    S0_1 s0;
     s0.a = _36.s0s[gl_GlobalInvocationID.x].a;
     s0.a = _36.s0s[gl_GlobalInvocationID.x].a;
-    S1 s1;
+    S1_1 s1;
     s1.a = _55.s1s[gl_GlobalInvocationID.x].a;
     s1.a = _55.s1s[gl_GlobalInvocationID.x].a;
-    S0 param = s0;
-    S1 param_1 = s1;
+    S0_1 param = s0;
+    S1_1 param_1 = s1;
     _66.outputs[gl_GlobalInvocationID.x] = overload(param) + overload(param_1);
     _66.outputs[gl_GlobalInvocationID.x] = overload(param) + overload(param_1);
 }
 }
 
 

+ 1 - 15
3rdparty/spirv-cross/reference/shaders-msl/frag/constant-array.frag

@@ -27,19 +27,6 @@ struct main0_in
     int index [[user(locn0)]];
     int index [[user(locn0)]];
 };
 };
 
 
-// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
-template<typename T, uint N>
-void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
-{
-    for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
-template<typename T, uint N>
-void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
-{
-    for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
 float4 resolve(thread const Foobar& f)
 float4 resolve(thread const Foobar& f)
 {
 {
     return float4(f.a + f.b);
     return float4(f.a + f.b);
@@ -49,8 +36,7 @@ fragment main0_out main0(main0_in in [[stage_in]])
 {
 {
     main0_out out = {};
     main0_out out = {};
     Foobar param = Foobar{ 10.0, 20.0 };
     Foobar param = Foobar{ 10.0, 20.0 };
-    Foobar indexable[2] = { Foobar{ 10.0, 40.0 }, Foobar{ 90.0, 70.0 } };
-    Foobar param_1 = indexable[in.index];
+    Foobar param_1 = _75[in.index];
     out.FragColor = ((_37[in.index] + _55[in.index][in.index + 1]) + resolve(param)) + resolve(param_1);
     out.FragColor = ((_37[in.index] + _55[in.index][in.index + 1]) + resolve(param)) + resolve(param_1);
     return out;
     return out;
 }
 }

+ 42 - 0
3rdparty/spirv-cross/reference/shaders-msl/frag/fragment-component-padding.pad-fragment.frag

@@ -0,0 +1,42 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 FragColors_0 [[color(0)]];
+    float4 FragColors_1 [[color(1)]];
+    float4 FragColor2 [[color(2)]];
+    float4 FragColor3 [[color(3)]];
+};
+
+struct main0_in
+{
+    float3 vColor [[user(locn0)]];
+};
+
+void set_globals(thread float (&FragColors)[2], thread float3& vColor, thread float2& FragColor2, thread float3& FragColor3)
+{
+    FragColors[0] = vColor.x;
+    FragColors[1] = vColor.y;
+    FragColor2 = vColor.xz;
+    FragColor3 = vColor.zzz;
+}
+
+fragment main0_out main0(main0_in in [[stage_in]])
+{
+    main0_out out = {};
+    float FragColors[2] = {};
+    float2 FragColor2 = {};
+    float3 FragColor3 = {};
+    set_globals(FragColors, in.vColor, FragColor2, FragColor3);
+    out.FragColors_0 = float4(FragColors[0]);
+    out.FragColors_1 = float4(FragColors[1]);
+    out.FragColor2 = FragColor2.xyyy;
+    out.FragColor3 = FragColor3.xyzz;
+    return out;
+}
+

+ 4 - 4
3rdparty/spirv-cross/reference/shaders-msl/frag/packing-test-3.frag

@@ -12,19 +12,19 @@ struct VertexOutput
 
 
 struct TestStruct
 struct TestStruct
 {
 {
-    float3 position;
+    packed_float3 position;
     float radius;
     float radius;
 };
 };
 
 
 struct TestStruct_1
 struct TestStruct_1
 {
 {
-    packed_float3 position;
+    float3 position;
     float radius;
     float radius;
 };
 };
 
 
 struct CB0
 struct CB0
 {
 {
-    TestStruct_1 CB0[16];
+    TestStruct CB0[16];
 };
 };
 
 
 struct main0_out
 struct main0_out
@@ -34,7 +34,7 @@ struct main0_out
 
 
 float4 _main(thread const VertexOutput& IN, constant CB0& v_26)
 float4 _main(thread const VertexOutput& IN, constant CB0& v_26)
 {
 {
-    TestStruct st;
+    TestStruct_1 st;
     st.position = v_26.CB0[1].position;
     st.position = v_26.CB0[1].position;
     st.radius = v_26.CB0[1].radius;
     st.radius = v_26.CB0[1].radius;
     float4 col = float4(st.position, st.radius);
     float4 col = float4(st.position, st.radius);

+ 5 - 5
3rdparty/spirv-cross/reference/shaders-msl/vert/resource-arrays-leaf.ios.vert

@@ -5,11 +5,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 3
-#endif
-constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
-
 struct storage_block
 struct storage_block
 {
 {
     uint4 baz;
     uint4 baz;
@@ -22,6 +17,11 @@ struct constant_block
     int bar;
     int bar;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 3
+#endif
+constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
+
 void doWork(device storage_block* (&storage)[2], constant constant_block* (&constants)[4], thread const array<texture2d<int>, 3> images)
 void doWork(device storage_block* (&storage)[2], constant constant_block* (&constants)[4], thread const array<texture2d<int>, 3> images)
 {
 {
     storage[0]->baz = uint4(constants[3]->foo);
     storage[0]->baz = uint4(constants[3]->foo);

+ 5 - 5
3rdparty/spirv-cross/reference/shaders-msl/vert/resource-arrays.ios.vert

@@ -3,11 +3,6 @@
 
 
 using namespace metal;
 using namespace metal;
 
 
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 3
-#endif
-constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
-
 struct storage_block
 struct storage_block
 {
 {
     uint4 baz;
     uint4 baz;
@@ -20,6 +15,11 @@ struct constant_block
     int bar;
     int bar;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 3
+#endif
+constant int arraySize = SPIRV_CROSS_CONSTANT_ID_0;
+
 vertex void main0(device storage_block* storage_0 [[buffer(0)]], device storage_block* storage_1 [[buffer(1)]], constant constant_block* constants_0 [[buffer(2)]], constant constant_block* constants_1 [[buffer(3)]], constant constant_block* constants_2 [[buffer(4)]], constant constant_block* constants_3 [[buffer(5)]], array<texture2d<int>, 3> images [[texture(0)]])
 vertex void main0(device storage_block* storage_0 [[buffer(0)]], device storage_block* storage_1 [[buffer(1)]], constant constant_block* constants_0 [[buffer(2)]], constant constant_block* constants_1 [[buffer(3)]], constant constant_block* constants_2 [[buffer(4)]], constant constant_block* constants_3 [[buffer(5)]], array<texture2d<int>, 3> images [[texture(0)]])
 {
 {
     device storage_block* storage[] =
     device storage_block* storage[] =

+ 25 - 0
3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/out-of-order-struct-id.asm.frag

@@ -0,0 +1,25 @@
+#version 450
+
+struct Foo
+{
+    vec4 a;
+};
+
+struct Bar
+{
+    Foo foo;
+    Foo foo2;
+};
+
+layout(binding = 0, std140) uniform UBO
+{
+    Bar bar;
+} _7;
+
+layout(location = 0) out vec4 FragColor;
+
+void main()
+{
+    FragColor = _7.bar.foo.a + _7.bar.foo2.a;
+}
+

+ 27 - 0
3rdparty/spirv-cross/reference/shaders-no-opt/vert/pass-array-by-value.vert

@@ -0,0 +1,27 @@
+#version 310 es
+
+layout(location = 0) in int Index1;
+layout(location = 1) in int Index2;
+
+vec4 consume_constant_arrays2(vec4 positions[4], vec4 positions2[4])
+{
+    vec4 indexable[4] = positions;
+    vec4 indexable_1[4] = positions2;
+    return indexable[Index1] + indexable_1[Index2];
+}
+
+vec4 consume_constant_arrays(vec4 positions[4], vec4 positions2[4])
+{
+    return consume_constant_arrays2(positions, positions2);
+}
+
+void main()
+{
+    vec4 LUT2[4];
+    LUT2[0] = vec4(10.0);
+    LUT2[1] = vec4(11.0);
+    LUT2[2] = vec4(12.0);
+    LUT2[3] = vec4(13.0);
+    gl_Position = consume_constant_arrays(vec4[](vec4(0.0), vec4(1.0), vec4(2.0), vec4(3.0)), LUT2);
+}
+

+ 2 - 2
3rdparty/spirv-cross/reference/shaders/asm/frag/op-constant-null.asm.frag

@@ -2,14 +2,14 @@
 precision mediump float;
 precision mediump float;
 precision highp int;
 precision highp int;
 
 
-const vec4 _14[4] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
-
 struct D
 struct D
 {
 {
     vec4 a;
     vec4 a;
     float b;
     float b;
 };
 };
 
 
+const vec4 _14[4] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
+
 layout(location = 0) out float FragColor;
 layout(location = 0) out float FragColor;
 
 
 void main()
 void main()

+ 5 - 5
3rdparty/spirv-cross/reference/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert

@@ -4,19 +4,19 @@
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #define SPIRV_CROSS_CONSTANT_ID_201 -10
 #endif
 #endif
 const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
 const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
+const int _20 = (_7 + 2);
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #ifndef SPIRV_CROSS_CONSTANT_ID_202
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #define SPIRV_CROSS_CONSTANT_ID_202 100u
 #endif
 #endif
 const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
 const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
-#ifndef SPIRV_CROSS_CONSTANT_ID_200
-#define SPIRV_CROSS_CONSTANT_ID_200 3.141590118408203125
-#endif
-const float _9 = SPIRV_CROSS_CONSTANT_ID_200;
-const int _20 = (_7 + 2);
 const uint _25 = (_8 % 5u);
 const uint _25 = (_8 % 5u);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec2 _32 = ivec2(_30.y, _30.x);
 const ivec2 _32 = ivec2(_30.y, _30.x);
 const int _33 = _30.y;
 const int _33 = _30.y;
+#ifndef SPIRV_CROSS_CONSTANT_ID_200
+#define SPIRV_CROSS_CONSTANT_ID_200 3.141590118408203125
+#endif
+const float _9 = SPIRV_CROSS_CONSTANT_ID_200;
 
 
 layout(location = 0) flat out int _4;
 layout(location = 0) flat out int _4;
 
 

+ 2 - 2
3rdparty/spirv-cross/reference/shaders/asm/vert/spec-constant-op-composite.asm.vk.vert.vk

@@ -1,13 +1,13 @@
 #version 450
 #version 450
 
 
 layout(constant_id = 201) const int _7 = -10;
 layout(constant_id = 201) const int _7 = -10;
-layout(constant_id = 202) const uint _8 = 100u;
-layout(constant_id = 200) const float _9 = 3.141590118408203125;
 const int _20 = (_7 + 2);
 const int _20 = (_7 + 2);
+layout(constant_id = 202) const uint _8 = 100u;
 const uint _25 = (_8 % 5u);
 const uint _25 = (_8 % 5u);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec4 _30 = ivec4(20, 30, _20, _20);
 const ivec2 _32 = ivec2(_30.y, _30.x);
 const ivec2 _32 = ivec2(_30.y, _30.x);
 const int _33 = _30.y;
 const int _33 = _30.y;
+layout(constant_id = 200) const float _9 = 3.141590118408203125;
 
 
 layout(location = 0) flat out int _4;
 layout(location = 0) flat out int _4;
 
 

+ 5 - 5
3rdparty/spirv-cross/reference/shaders/comp/composite-array-initialization.comp

@@ -1,17 +1,17 @@
 #version 310 es
 #version 310 es
 layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
 layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
 
 
-#ifndef SPIRV_CROSS_CONSTANT_ID_0
-#define SPIRV_CROSS_CONSTANT_ID_0 4.0
-#endif
-const float X = SPIRV_CROSS_CONSTANT_ID_0;
-
 struct Data
 struct Data
 {
 {
     float a;
     float a;
     float b;
     float b;
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_0
+#define SPIRV_CROSS_CONSTANT_ID_0 4.0
+#endif
+const float X = SPIRV_CROSS_CONSTANT_ID_0;
+
 layout(binding = 0, std430) buffer SSBO
 layout(binding = 0, std430) buffer SSBO
 {
 {
     Data outdata[];
     Data outdata[];

+ 2 - 1
3rdparty/spirv-cross/reference/shaders/comp/composite-construct.comp

@@ -2,7 +2,6 @@
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
 
 const vec4 _66[2] = vec4[](vec4(10.0), vec4(30.0));
 const vec4 _66[2] = vec4[](vec4(10.0), vec4(30.0));
-const float _94[2][3] = float[][](float[](1.0, 1.0, 1.0), float[](2.0, 2.0, 2.0));
 
 
 struct Composite
 struct Composite
 {
 {
@@ -10,6 +9,8 @@ struct Composite
     vec4 b[2];
     vec4 b[2];
 };
 };
 
 
+const float _94[2][3] = float[][](float[](1.0, 1.0, 1.0), float[](2.0, 2.0, 2.0));
+
 layout(binding = 0, std430) buffer SSBO0
 layout(binding = 0, std430) buffer SSBO0
 {
 {
     vec4 as[];
     vec4 as[];

+ 5 - 5
3rdparty/spirv-cross/reference/shaders/frag/constant-array.frag

@@ -2,15 +2,16 @@
 precision mediump float;
 precision mediump float;
 precision highp int;
 precision highp int;
 
 
-const vec4 _37[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
-const vec4 _55[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
-
 struct Foobar
 struct Foobar
 {
 {
     float a;
     float a;
     float b;
     float b;
 };
 };
 
 
+const vec4 _37[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
+const vec4 _55[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
+const Foobar _75[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
+
 layout(location = 0) out vec4 FragColor;
 layout(location = 0) out vec4 FragColor;
 layout(location = 0) flat in mediump int index;
 layout(location = 0) flat in mediump int index;
 
 
@@ -22,8 +23,7 @@ vec4 resolve(Foobar f)
 void main()
 void main()
 {
 {
     Foobar param = Foobar(10.0, 20.0);
     Foobar param = Foobar(10.0, 20.0);
-    Foobar indexable[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
-    Foobar param_1 = indexable[index];
+    Foobar param_1 = _75[index];
     FragColor = ((_37[index] + _55[index][index + 1]) + resolve(param)) + resolve(param_1);
     FragColor = ((_37[index] + _55[index][index + 1]) + resolve(param)) + resolve(param_1);
 }
 }
 
 

+ 10 - 9
3rdparty/spirv-cross/reference/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp

@@ -9,15 +9,6 @@ const int a = SPIRV_CROSS_CONSTANT_ID_0;
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #define SPIRV_CROSS_CONSTANT_ID_1 200
 #endif
 #endif
 const int b = SPIRV_CROSS_CONSTANT_ID_1;
 const int b = SPIRV_CROSS_CONSTANT_ID_1;
-#ifndef SPIRV_CROSS_CONSTANT_ID_2
-#define SPIRV_CROSS_CONSTANT_ID_2 300
-#endif
-const int c = SPIRV_CROSS_CONSTANT_ID_2;
-const int _18 = (c + 50);
-#ifndef SPIRV_CROSS_CONSTANT_ID_3
-#define SPIRV_CROSS_CONSTANT_ID_3 400
-#endif
-const int e = SPIRV_CROSS_CONSTANT_ID_3;
 
 
 struct A
 struct A
 {
 {
@@ -31,6 +22,16 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+#ifndef SPIRV_CROSS_CONSTANT_ID_2
+#define SPIRV_CROSS_CONSTANT_ID_2 300
+#endif
+const int c = SPIRV_CROSS_CONSTANT_ID_2;
+const int _18 = (c + 50);
+#ifndef SPIRV_CROSS_CONSTANT_ID_3
+#define SPIRV_CROSS_CONSTANT_ID_3 400
+#endif
+const int e = SPIRV_CROSS_CONSTANT_ID_3;
+
 layout(binding = 0, std430) buffer SSBO
 layout(binding = 0, std430) buffer SSBO
 {
 {
     A member_a;
     A member_a;

+ 4 - 3
3rdparty/spirv-cross/reference/shaders/vulkan/comp/spec-constant-op-member-array.vk.comp.vk

@@ -3,9 +3,6 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
 
 layout(constant_id = 0) const int a = 100;
 layout(constant_id = 0) const int a = 100;
 layout(constant_id = 1) const int b = 200;
 layout(constant_id = 1) const int b = 200;
-layout(constant_id = 2) const int c = 300;
-const int _18 = (c + 50);
-layout(constant_id = 3) const int e = 400;
 
 
 struct A
 struct A
 {
 {
@@ -19,6 +16,10 @@ struct B
     int member1[a];
     int member1[a];
 };
 };
 
 
+layout(constant_id = 2) const int c = 300;
+const int _18 = (c + 50);
+layout(constant_id = 3) const int e = 400;
+
 layout(set = 1, binding = 0, std430) buffer SSBO
 layout(set = 1, binding = 0, std430) buffer SSBO
 {
 {
     A member_a;
     A member_a;

+ 26 - 0
3rdparty/spirv-cross/shaders-hlsl-no-opt/vert/pass-array-by-value.vert

@@ -0,0 +1,26 @@
+#version 310 es
+
+layout(location = 0) in int Index1;
+layout(location = 1) in int Index2;
+
+vec4 consume_constant_arrays2(const vec4 positions[4], const vec4 positions2[4])
+{
+	return positions[Index1] + positions2[Index2];
+}
+
+vec4 consume_constant_arrays(const vec4 positions[4], const vec4 positions2[4])
+{
+	return consume_constant_arrays2(positions, positions2);
+}
+
+const vec4 LUT1[] = vec4[](vec4(0.0), vec4(1.0), vec4(2.0), vec4(3.0));
+
+void main()
+{
+	vec4 LUT2[4];
+	LUT2[0] = vec4(10.0);
+	LUT2[1] = vec4(11.0);
+	LUT2[2] = vec4(12.0);
+	LUT2[3] = vec4(13.0);
+	gl_Position = consume_constant_arrays(LUT1, LUT2);
+}

+ 10 - 0
3rdparty/spirv-cross/shaders-hlsl/frag/dual-source-blending.frag

@@ -0,0 +1,10 @@
+#version 450
+
+layout(location = 0, index = 0) out vec4 FragColor0;
+layout(location = 0, index = 1) out vec4 FragColor1;
+
+void main()
+{
+	FragColor0 = vec4(1.0);
+	FragColor1 = vec4(2.0);
+}

+ 26 - 0
3rdparty/spirv-cross/shaders-msl-no-opt/vert/pass-array-by-value.vert

@@ -0,0 +1,26 @@
+#version 310 es
+
+layout(location = 0) in int Index1;
+layout(location = 1) in int Index2;
+
+vec4 consume_constant_arrays2(const vec4 positions[4], const vec4 positions2[4])
+{
+	return positions[Index1] + positions2[Index2];
+}
+
+vec4 consume_constant_arrays(const vec4 positions[4], const vec4 positions2[4])
+{
+	return consume_constant_arrays2(positions, positions2);
+}
+
+const vec4 LUT1[] = vec4[](vec4(0.0), vec4(1.0), vec4(2.0), vec4(3.0));
+
+void main()
+{
+	vec4 LUT2[4];
+	LUT2[0] = vec4(10.0);
+	LUT2[1] = vec4(11.0);
+	LUT2[2] = vec4(12.0);
+	LUT2[3] = vec4(13.0);
+	gl_Position = consume_constant_arrays(LUT1, LUT2);
+}

+ 90 - 0
3rdparty/spirv-cross/shaders-msl-no-opt/vulkan/frag/texture-access-function.swizzle.vk.frag

@@ -0,0 +1,90 @@
+#version 450
+
+layout(binding = 0) uniform sampler1D tex1d;
+layout(binding = 1) uniform texture2D tex2d;
+layout(binding = 2) uniform sampler3D tex3d;
+layout(binding = 3) uniform textureCube texCube;
+layout(binding = 4) uniform sampler2DArray tex2dArray;
+layout(binding = 5) uniform samplerCubeArray texCubeArray;
+layout(binding = 6) uniform samplerBuffer texBuffer;
+
+layout(binding = 7) uniform sampler2DShadow depth2d;
+layout(binding = 8) uniform samplerCubeShadow depthCube;
+layout(binding = 9) uniform texture2DArray depth2dArray;
+layout(binding = 10) uniform samplerCubeArrayShadow depthCubeArray;
+
+layout(binding = 11) uniform sampler defaultSampler;
+layout(binding = 12) uniform samplerShadow shadowSampler;
+
+layout(location = 0) out vec4 fragColor;
+
+vec4 do_samples(sampler1D t1, texture2D t2, sampler3D t3, textureCube tc, sampler2DArray t2a, samplerCubeArray tca, samplerBuffer tb, sampler2DShadow d2, samplerCubeShadow dc, texture2DArray d2a, samplerCubeArrayShadow dca)
+{
+	// OpImageSampleImplicitLod
+	vec4 c = texture(t1, 0.0);
+	c = texture(sampler2D(t2, defaultSampler), vec2(0.0, 0.0));
+	c = texture(t3, vec3(0.0, 0.0, 0.0));
+	c = texture(samplerCube(tc, defaultSampler), vec3(0.0, 0.0, 0.0));
+	c = texture(t2a, vec3(0.0, 0.0, 0.0));
+	c = texture(tca, vec4(0.0, 0.0, 0.0, 0.0));
+
+	// OpImageSampleDrefImplicitLod
+	c.r = texture(d2, vec3(0.0, 0.0, 1.0));
+	c.r = texture(dc, vec4(0.0, 0.0, 0.0, 1.0));
+	c.r = texture(sampler2DArrayShadow(d2a, shadowSampler), vec4(0.0, 0.0, 0.0, 1.0));
+	c.r = texture(dca, vec4(0.0, 0.0, 0.0, 0.0), 1.0);
+
+	// OpImageSampleProjImplicitLod
+	c = textureProj(t1, vec2(0.0, 1.0));
+	c = textureProj(sampler2D(t2, defaultSampler), vec3(0.0, 0.0, 1.0));
+	c = textureProj(t3, vec4(0.0, 0.0, 0.0, 1.0));
+
+	// OpImageSampleProjDrefImplicitLod
+	c.r = textureProj(d2, vec4(0.0, 0.0, 1.0, 1.0));
+
+	// OpImageSampleExplicitLod
+	c = textureLod(t1, 0.0, 0.0);
+	c = textureLod(sampler2D(t2, defaultSampler), vec2(0.0, 0.0), 0.0);
+	c = textureLod(t3, vec3(0.0, 0.0, 0.0), 0.0);
+	c = textureLod(samplerCube(tc, defaultSampler), vec3(0.0, 0.0, 0.0), 0.0);
+	c = textureLod(t2a, vec3(0.0, 0.0, 0.0), 0.0);
+	c = textureLod(tca, vec4(0.0, 0.0, 0.0, 0.0), 0.0);
+
+	// OpImageSampleDrefExplicitLod
+	c.r = textureLod(d2, vec3(0.0, 0.0, 1.0), 0.0);
+
+	// OpImageSampleProjExplicitLod
+	c = textureProjLod(t1, vec2(0.0, 1.0), 0.0);
+	c = textureProjLod(sampler2D(t2, defaultSampler), vec3(0.0, 0.0, 1.0), 0.0);
+	c = textureProjLod(t3, vec4(0.0, 0.0, 0.0, 1.0), 0.0);
+
+	// OpImageSampleProjDrefExplicitLod
+	c.r = textureProjLod(d2, vec4(0.0, 0.0, 1.0, 1.0), 0.0);
+
+	// OpImageFetch
+	c = texelFetch(t1, 0, 0);
+	c = texelFetch(sampler2D(t2, defaultSampler), ivec2(0, 0), 0);
+	c = texelFetch(t3, ivec3(0, 0, 0), 0);
+	c = texelFetch(t2a, ivec3(0, 0, 0), 0);
+
+	// Show that this transformation doesn't apply to Buffer images.
+	c = texelFetch(tb, 0);
+
+	// OpImageGather
+	c = textureGather(sampler2D(t2, defaultSampler), vec2(0.0, 0.0), 0);
+	c = textureGather(samplerCube(tc, defaultSampler), vec3(0.0, 0.0, 0.0), 1);
+	c = textureGather(t2a, vec3(0.0, 0.0, 0.0), 2);
+	c = textureGather(tca, vec4(0.0, 0.0, 0.0, 0.0), 3);
+
+	// OpImageDrefGather
+	c = textureGather(d2, vec2(0.0, 0.0), 1.0);
+	c = textureGather(dc, vec3(0.0, 0.0, 0.0), 1.0);
+	c = textureGather(sampler2DArrayShadow(d2a, shadowSampler), vec3(0.0, 0.0, 0.0), 1.0);
+	c = textureGather(dca, vec4(0.0, 0.0, 0.0, 0.0), 1.0);
+	return c;
+}
+
+void main()
+{
+	fragColor = do_samples(tex1d, tex2d, tex3d, texCube, tex2dArray, texCubeArray, texBuffer, depth2d, depthCube, depth2dArray, depthCubeArray);
+}

+ 18 - 0
3rdparty/spirv-cross/shaders-msl/frag/fragment-component-padding.pad-fragment.frag

@@ -0,0 +1,18 @@
+#version 450
+layout(location = 0) out float FragColors[2];
+layout(location = 2) out vec2 FragColor2;
+layout(location = 3) out vec3 FragColor3;
+layout(location = 0) in vec3 vColor;
+
+void set_globals()
+{
+	FragColors[0] = vColor.x;
+	FragColors[1] = vColor.y;
+	FragColor2 = vColor.xz;
+	FragColor3 = vColor.zzz;
+}
+
+void main()
+{
+	set_globals();
+}

+ 54 - 0
3rdparty/spirv-cross/shaders-no-opt/asm/frag/out-of-order-struct-id.asm.frag

@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 24
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %FragColor
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %FragColor "FragColor"
+               OpName %80 "Foo"
+               OpMemberName %80 0 "a"
+               OpName %79 "Bar"
+               OpMemberName %79 0 "foo"
+               OpMemberName %79 1 "foo2"
+               OpName %UBO "UBO"
+               OpMemberName %UBO 0 "bar"
+               OpName %_ ""
+               OpDecorate %FragColor Location 0
+               OpMemberDecorate %80 0 Offset 0
+               OpMemberDecorate %79 0 Offset 0
+               OpMemberDecorate %79 1 Offset 16
+               OpMemberDecorate %UBO 0 Offset 0
+               OpDecorate %UBO Block
+               OpDecorate %_ DescriptorSet 0
+               OpDecorate %_ Binding 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
+        %80 = OpTypeStruct %v4float
+        %79 = OpTypeStruct %80 %80
+        %UBO = OpTypeStruct %79
+%_ptr_Uniform_UBO = OpTypePointer Uniform %UBO
+          %_ = OpVariable %_ptr_Uniform_UBO Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+      %int_1 = OpConstant %int 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %int_0 %int_0
+         %19 = OpLoad %v4float %18
+         %21 = OpAccessChain %_ptr_Uniform_v4float %_ %int_0 %int_1 %int_0
+         %22 = OpLoad %v4float %21
+         %23 = OpFAdd %v4float %19 %22
+               OpStore %FragColor %23
+               OpReturn
+               OpFunctionEnd

+ 26 - 0
3rdparty/spirv-cross/shaders-no-opt/vert/pass-array-by-value.vert

@@ -0,0 +1,26 @@
+#version 310 es
+
+layout(location = 0) in int Index1;
+layout(location = 1) in int Index2;
+
+vec4 consume_constant_arrays2(const vec4 positions[4], const vec4 positions2[4])
+{
+	return positions[Index1] + positions2[Index2];
+}
+
+vec4 consume_constant_arrays(const vec4 positions[4], const vec4 positions2[4])
+{
+	return consume_constant_arrays2(positions, positions2);
+}
+
+const vec4 LUT1[] = vec4[](vec4(0.0), vec4(1.0), vec4(2.0), vec4(3.0));
+
+void main()
+{
+	vec4 LUT2[4];
+	LUT2[0] = vec4(10.0);
+	LUT2[1] = vec4(11.0);
+	LUT2[2] = vec4(12.0);
+	LUT2[3] = vec4(13.0);
+	gl_Position = consume_constant_arrays(LUT1, LUT2);
+}

+ 11 - 14
3rdparty/spirv-cross/spirv_cfg.cpp

@@ -27,11 +27,6 @@ CFG::CFG(Compiler &compiler_, const SPIRFunction &func_)
     : compiler(compiler_)
     : compiler(compiler_)
     , func(func_)
     , func(func_)
 {
 {
-	preceding_edges.resize(compiler.get_current_id_bound());
-	succeeding_edges.resize(compiler.get_current_id_bound());
-	visit_order.resize(compiler.get_current_id_bound());
-	immediate_dominators.resize(compiler.get_current_id_bound());
-
 	build_post_order_visit_order();
 	build_post_order_visit_order();
 	build_immediate_dominators();
 	build_immediate_dominators();
 }
 }
@@ -40,10 +35,10 @@ uint32_t CFG::find_common_dominator(uint32_t a, uint32_t b) const
 {
 {
 	while (a != b)
 	while (a != b)
 	{
 	{
-		if (visit_order[a] < visit_order[b])
-			a = immediate_dominators[a];
+		if (get_visit_order(a) < get_visit_order(b))
+			a = get_immediate_dominator(a);
 		else
 		else
-			b = immediate_dominators[b];
+			b = get_immediate_dominator(b);
 	}
 	}
 	return a;
 	return a;
 }
 }
@@ -51,7 +46,7 @@ uint32_t CFG::find_common_dominator(uint32_t a, uint32_t b) const
 void CFG::build_immediate_dominators()
 void CFG::build_immediate_dominators()
 {
 {
 	// Traverse the post-order in reverse and build up the immediate dominator tree.
 	// Traverse the post-order in reverse and build up the immediate dominator tree.
-	fill(begin(immediate_dominators), end(immediate_dominators), 0);
+	immediate_dominators.clear();
 	immediate_dominators[func.entry_block] = func.entry_block;
 	immediate_dominators[func.entry_block] = func.entry_block;
 
 
 	for (auto i = post_order.size(); i; i--)
 	for (auto i = post_order.size(); i; i--)
@@ -78,7 +73,9 @@ bool CFG::is_back_edge(uint32_t to) const
 {
 {
 	// We have a back edge if the visit order is set with the temporary magic value 0.
 	// We have a back edge if the visit order is set with the temporary magic value 0.
 	// Crossing edges will have already been recorded with a visit order.
 	// Crossing edges will have already been recorded with a visit order.
-	return visit_order[to] == 0;
+	auto itr = visit_order.find(to);
+	assert(itr != end(visit_order));
+	return itr->second.get() == 0;
 }
 }
 
 
 bool CFG::post_order_visit(uint32_t block_id)
 bool CFG::post_order_visit(uint32_t block_id)
@@ -86,11 +83,11 @@ bool CFG::post_order_visit(uint32_t block_id)
 	// If we have already branched to this block (back edge), stop recursion.
 	// If we have already branched to this block (back edge), stop recursion.
 	// If our branches are back-edges, we do not record them.
 	// If our branches are back-edges, we do not record them.
 	// We have to record crossing edges however.
 	// We have to record crossing edges however.
-	if (visit_order[block_id] >= 0)
+	if (visit_order[block_id].get() >= 0)
 		return !is_back_edge(block_id);
 		return !is_back_edge(block_id);
 
 
 	// Block back-edges from recursively revisiting ourselves.
 	// Block back-edges from recursively revisiting ourselves.
-	visit_order[block_id] = 0;
+	visit_order[block_id].get() = 0;
 
 
 	// First visit our branch targets.
 	// First visit our branch targets.
 	auto &block = compiler.get<SPIRBlock>(block_id);
 	auto &block = compiler.get<SPIRBlock>(block_id);
@@ -130,7 +127,7 @@ bool CFG::post_order_visit(uint32_t block_id)
 		add_branch(block_id, block.merge_block);
 		add_branch(block_id, block.merge_block);
 
 
 	// Then visit ourselves. Start counting at one, to let 0 be a magic value for testing back vs. crossing edges.
 	// Then visit ourselves. Start counting at one, to let 0 be a magic value for testing back vs. crossing edges.
-	visit_order[block_id] = ++visit_count;
+	visit_order[block_id].get() = ++visit_count;
 	post_order.push_back(block_id);
 	post_order.push_back(block_id);
 	return true;
 	return true;
 }
 }
@@ -139,7 +136,7 @@ void CFG::build_post_order_visit_order()
 {
 {
 	uint32_t block = func.entry_block;
 	uint32_t block = func.entry_block;
 	visit_count = 0;
 	visit_count = 0;
-	fill(begin(visit_order), end(visit_order), -1);
+	visit_order.clear();
 	post_order.clear();
 	post_order.clear();
 	post_order_visit(block);
 	post_order_visit(block);
 }
 }

+ 39 - 9
3rdparty/spirv-cross/spirv_cfg.hpp

@@ -45,12 +45,18 @@ public:
 
 
 	uint32_t get_immediate_dominator(uint32_t block) const
 	uint32_t get_immediate_dominator(uint32_t block) const
 	{
 	{
-		return immediate_dominators[block];
+		auto itr = immediate_dominators.find(block);
+		if (itr != std::end(immediate_dominators))
+			return itr->second;
+		else
+			return 0;
 	}
 	}
 
 
 	uint32_t get_visit_order(uint32_t block) const
 	uint32_t get_visit_order(uint32_t block) const
 	{
 	{
-		int v = visit_order[block];
+		auto itr = visit_order.find(block);
+		assert(itr != std::end(visit_order));
+		int v = itr->second.get();
 		assert(v > 0);
 		assert(v > 0);
 		return uint32_t(v);
 		return uint32_t(v);
 	}
 	}
@@ -59,12 +65,20 @@ public:
 
 
 	const std::vector<uint32_t> &get_preceding_edges(uint32_t block) const
 	const std::vector<uint32_t> &get_preceding_edges(uint32_t block) const
 	{
 	{
-		return preceding_edges[block];
+		auto itr = preceding_edges.find(block);
+		if (itr != std::end(preceding_edges))
+			return itr->second;
+		else
+			return empty_vector;
 	}
 	}
 
 
 	const std::vector<uint32_t> &get_succeeding_edges(uint32_t block) const
 	const std::vector<uint32_t> &get_succeeding_edges(uint32_t block) const
 	{
 	{
-		return succeeding_edges[block];
+		auto itr = succeeding_edges.find(block);
+		if (itr != std::end(succeeding_edges))
+			return itr->second;
+		else
+			return empty_vector;
 	}
 	}
 
 
 	template <typename Op>
 	template <typename Op>
@@ -75,18 +89,34 @@ public:
 		seen_blocks.insert(block);
 		seen_blocks.insert(block);
 
 
 		op(block);
 		op(block);
-		for (auto b : succeeding_edges[block])
+		for (auto b : get_succeeding_edges(block))
 			walk_from(seen_blocks, b, op);
 			walk_from(seen_blocks, b, op);
 	}
 	}
 
 
 private:
 private:
+	struct VisitOrder
+	{
+		int &get()
+		{
+			return v;
+		}
+
+		const int &get() const
+		{
+			return v;
+		}
+
+		int v = -1;
+	};
+
 	Compiler &compiler;
 	Compiler &compiler;
 	const SPIRFunction &func;
 	const SPIRFunction &func;
-	std::vector<std::vector<uint32_t>> preceding_edges;
-	std::vector<std::vector<uint32_t>> succeeding_edges;
-	std::vector<uint32_t> immediate_dominators;
-	std::vector<int> visit_order;
+	std::unordered_map<uint32_t, std::vector<uint32_t>> preceding_edges;
+	std::unordered_map<uint32_t, std::vector<uint32_t>> succeeding_edges;
+	std::unordered_map<uint32_t, uint32_t> immediate_dominators;
+	std::unordered_map<uint32_t, VisitOrder> visit_order;
 	std::vector<uint32_t> post_order;
 	std::vector<uint32_t> post_order;
+	std::vector<uint32_t> empty_vector;
 
 
 	void add_branch(uint32_t from, uint32_t to);
 	void add_branch(uint32_t from, uint32_t to);
 	void build_post_order_visit_order();
 	void build_post_order_visit_order();

+ 13 - 8
3rdparty/spirv-cross/spirv_common.hpp

@@ -322,14 +322,14 @@ enum Types
 	TypeConstant,
 	TypeConstant,
 	TypeFunction,
 	TypeFunction,
 	TypeFunctionPrototype,
 	TypeFunctionPrototype,
-	TypePointer,
 	TypeBlock,
 	TypeBlock,
 	TypeExtension,
 	TypeExtension,
 	TypeExpression,
 	TypeExpression,
 	TypeConstantOp,
 	TypeConstantOp,
 	TypeCombinedImageSampler,
 	TypeCombinedImageSampler,
 	TypeAccessChain,
 	TypeAccessChain,
-	TypeUndef
+	TypeUndef,
+	TypeCount
 };
 };
 
 
 struct SPIRUndef : IVariant
 struct SPIRUndef : IVariant
@@ -812,6 +812,11 @@ struct SPIRFunction : IVariant
 	// Need to defer this, because they might rely on things which change during compilation.
 	// Need to defer this, because they might rely on things which change during compilation.
 	std::vector<std::function<void()>> fixup_hooks_in;
 	std::vector<std::function<void()>> fixup_hooks_in;
 
 
+	// On function entry, make sure to copy a constant array into thread addr space to work around
+	// the case where we are passing a constant array by value to a function on backends which do not
+	// consider arrays value types.
+	std::vector<uint32_t> constant_arrays_needed_on_stack;
+
 	bool active = false;
 	bool active = false;
 	bool flush_undeclared = true;
 	bool flush_undeclared = true;
 	bool do_combined_parameters = true;
 	bool do_combined_parameters = true;
@@ -1250,7 +1255,7 @@ public:
 		return *this;
 		return *this;
 	}
 	}
 
 
-	void set(std::unique_ptr<IVariant> val, uint32_t new_type)
+	void set(std::unique_ptr<IVariant> val, Types new_type)
 	{
 	{
 		holder = std::move(val);
 		holder = std::move(val);
 		if (!allow_type_rewrite && type != TypeNone && type != new_type)
 		if (!allow_type_rewrite && type != TypeNone && type != new_type)
@@ -1264,7 +1269,7 @@ public:
 	{
 	{
 		if (!holder)
 		if (!holder)
 			SPIRV_CROSS_THROW("nullptr");
 			SPIRV_CROSS_THROW("nullptr");
-		if (T::type != type)
+		if (static_cast<Types>(T::type) != type)
 			SPIRV_CROSS_THROW("Bad cast");
 			SPIRV_CROSS_THROW("Bad cast");
 		return *static_cast<T *>(holder.get());
 		return *static_cast<T *>(holder.get());
 	}
 	}
@@ -1274,12 +1279,12 @@ public:
 	{
 	{
 		if (!holder)
 		if (!holder)
 			SPIRV_CROSS_THROW("nullptr");
 			SPIRV_CROSS_THROW("nullptr");
-		if (T::type != type)
+		if (static_cast<Types>(T::type) != type)
 			SPIRV_CROSS_THROW("Bad cast");
 			SPIRV_CROSS_THROW("Bad cast");
 		return *static_cast<const T *>(holder.get());
 		return *static_cast<const T *>(holder.get());
 	}
 	}
 
 
-	uint32_t get_type() const
+	Types get_type() const
 	{
 	{
 		return type;
 		return type;
 	}
 	}
@@ -1307,7 +1312,7 @@ public:
 
 
 private:
 private:
 	std::unique_ptr<IVariant> holder;
 	std::unique_ptr<IVariant> holder;
-	uint32_t type = TypeNone;
+	Types type = TypeNone;
 	bool allow_type_rewrite = false;
 	bool allow_type_rewrite = false;
 };
 };
 
 
@@ -1328,7 +1333,7 @@ T &variant_set(Variant &var, P &&... args)
 {
 {
 	auto uptr = std::unique_ptr<T>(new T(std::forward<P>(args)...));
 	auto uptr = std::unique_ptr<T>(new T(std::forward<P>(args)...));
 	auto ptr = uptr.get();
 	auto ptr = uptr.get();
-	var.set(std::move(uptr), T::type);
+	var.set(std::move(uptr), static_cast<Types>(T::type));
 	return *ptr;
 	return *ptr;
 }
 }
 
 

+ 166 - 130
3rdparty/spirv-cross/spirv_cross.cpp

@@ -158,7 +158,7 @@ bool Compiler::block_is_pure(const SPIRBlock &block)
 
 
 string Compiler::to_name(uint32_t id, bool allow_alias) const
 string Compiler::to_name(uint32_t id, bool allow_alias) const
 {
 {
-	if (allow_alias && ir.ids.at(id).get_type() == TypeType)
+	if (allow_alias && ir.ids[id].get_type() == TypeType)
 	{
 	{
 		// If this type is a simple alias, emit the
 		// If this type is a simple alias, emit the
 		// name of the original type instead.
 		// name of the original type instead.
@@ -174,10 +174,11 @@ string Compiler::to_name(uint32_t id, bool allow_alias) const
 		}
 		}
 	}
 	}
 
 
-	if (ir.meta[id].decoration.alias.empty())
+	auto &alias = ir.get_name(id);
+	if (alias.empty())
 		return join("_", id);
 		return join("_", id);
 	else
 	else
-		return ir.meta[id].decoration.alias;
+		return alias;
 }
 }
 
 
 bool Compiler::function_is_pure(const SPIRFunction &func)
 bool Compiler::function_is_pure(const SPIRFunction &func)
@@ -473,17 +474,22 @@ bool Compiler::is_hidden_variable(const SPIRVariable &var, bool include_builtins
 
 
 bool Compiler::is_builtin_type(const SPIRType &type) const
 bool Compiler::is_builtin_type(const SPIRType &type) const
 {
 {
+	auto *type_meta = ir.find_meta(type.self);
+
 	// We can have builtin structs as well. If one member of a struct is builtin, the struct must also be builtin.
 	// We can have builtin structs as well. If one member of a struct is builtin, the struct must also be builtin.
-	for (auto &m : ir.meta[type.self].members)
-		if (m.builtin)
-			return true;
+	if (type_meta)
+		for (auto &m : type_meta->members)
+			if (m.builtin)
+				return true;
 
 
 	return false;
 	return false;
 }
 }
 
 
 bool Compiler::is_builtin_variable(const SPIRVariable &var) const
 bool Compiler::is_builtin_variable(const SPIRVariable &var) const
 {
 {
-	if (var.compat_builtin || ir.meta[var.self].decoration.builtin)
+	auto *m = ir.find_meta(var.self);
+
+	if (var.compat_builtin || (m && m->decoration.builtin))
 		return true;
 		return true;
 	else
 	else
 		return is_builtin_type(get<SPIRType>(var.basetype));
 		return is_builtin_type(get<SPIRType>(var.basetype));
@@ -491,12 +497,17 @@ bool Compiler::is_builtin_variable(const SPIRVariable &var) const
 
 
 bool Compiler::is_member_builtin(const SPIRType &type, uint32_t index, BuiltIn *builtin) const
 bool Compiler::is_member_builtin(const SPIRType &type, uint32_t index, BuiltIn *builtin) const
 {
 {
-	auto &memb = ir.meta[type.self].members;
-	if (index < memb.size() && memb[index].builtin)
+	auto *type_meta = ir.find_meta(type.self);
+
+	if (type_meta)
 	{
 	{
-		if (builtin)
-			*builtin = memb[index].builtin_type;
-		return true;
+		auto &memb = type_meta->members;
+		if (index < memb.size() && memb[index].builtin)
+		{
+			if (builtin)
+				*builtin = memb[index].builtin_type;
+			return true;
+		}
 	}
 	}
 
 
 	return false;
 	return false;
@@ -707,55 +718,52 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
 {
 {
 	ShaderResources res;
 	ShaderResources res;
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() != TypeVariable)
-			continue;
-
-		auto &var = id.get<SPIRVariable>();
-		auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
 		// It is possible for uniform storage classes to be passed as function parameters, so detect
 		// It is possible for uniform storage classes to be passed as function parameters, so detect
 		// that. To detect function parameters, check of StorageClass of variable is function scope.
 		// that. To detect function parameters, check of StorageClass of variable is function scope.
 		if (var.storage == StorageClassFunction || !type.pointer || is_builtin_variable(var))
 		if (var.storage == StorageClassFunction || !type.pointer || is_builtin_variable(var))
-			continue;
+			return;
 
 
 		if (active_variables && active_variables->find(var.self) == end(*active_variables))
 		if (active_variables && active_variables->find(var.self) == end(*active_variables))
-			continue;
+			return;
 
 
 		// Input
 		// Input
 		if (var.storage == StorageClassInput && interface_variable_exists_in_entry_point(var.self))
 		if (var.storage == StorageClassInput && interface_variable_exists_in_entry_point(var.self))
 		{
 		{
-			if (ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock))
+			if (has_decoration(type.self, DecorationBlock))
+			{
 				res.stage_inputs.push_back(
 				res.stage_inputs.push_back(
 				    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
 				    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
+			}
 			else
 			else
-				res.stage_inputs.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+				res.stage_inputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Subpass inputs
 		// Subpass inputs
 		else if (var.storage == StorageClassUniformConstant && type.image.dim == DimSubpassData)
 		else if (var.storage == StorageClassUniformConstant && type.image.dim == DimSubpassData)
 		{
 		{
-			res.subpass_inputs.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.subpass_inputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Outputs
 		// Outputs
 		else if (var.storage == StorageClassOutput && interface_variable_exists_in_entry_point(var.self))
 		else if (var.storage == StorageClassOutput && interface_variable_exists_in_entry_point(var.self))
 		{
 		{
-			if (ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock))
+			if (has_decoration(type.self, DecorationBlock))
+			{
 				res.stage_outputs.push_back(
 				res.stage_outputs.push_back(
 				    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
 				    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
+			}
 			else
 			else
-				res.stage_outputs.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+				res.stage_outputs.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// UBOs
 		// UBOs
-		else if (type.storage == StorageClassUniform &&
-		         (ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock)))
+		else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBlock))
 		{
 		{
 			res.uniform_buffers.push_back(
 			res.uniform_buffers.push_back(
 			    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
 			    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
 		}
 		}
 		// Old way to declare SSBOs.
 		// Old way to declare SSBOs.
-		else if (type.storage == StorageClassUniform &&
-		         (ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock)))
+		else if (type.storage == StorageClassUniform && has_decoration(type.self, DecorationBufferBlock))
 		{
 		{
 			res.storage_buffers.push_back(
 			res.storage_buffers.push_back(
 			    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
 			    { var.self, var.basetype, type.self, get_remapped_declared_block_name(var.self) });
@@ -771,37 +779,36 @@ ShaderResources Compiler::get_shader_resources(const unordered_set<uint32_t> *ac
 		{
 		{
 			// There can only be one push constant block, but keep the vector in case this restriction is lifted
 			// There can only be one push constant block, but keep the vector in case this restriction is lifted
 			// in the future.
 			// in the future.
-			res.push_constant_buffers.push_back(
-			    { var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.push_constant_buffers.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Images
 		// Images
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image &&
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image &&
 		         type.image.sampled == 2)
 		         type.image.sampled == 2)
 		{
 		{
-			res.storage_images.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.storage_images.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Separate images
 		// Separate images
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image &&
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Image &&
 		         type.image.sampled == 1)
 		         type.image.sampled == 1)
 		{
 		{
-			res.separate_images.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.separate_images.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Separate samplers
 		// Separate samplers
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Sampler)
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::Sampler)
 		{
 		{
-			res.separate_samplers.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.separate_samplers.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Textures
 		// Textures
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::SampledImage)
 		else if (type.storage == StorageClassUniformConstant && type.basetype == SPIRType::SampledImage)
 		{
 		{
-			res.sampled_images.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.sampled_images.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
 		// Atomic counters
 		// Atomic counters
 		else if (type.storage == StorageClassAtomicCounter)
 		else if (type.storage == StorageClassAtomicCounter)
 		{
 		{
-			res.atomic_counters.push_back({ var.self, var.basetype, type.self, ir.meta[var.self].decoration.alias });
+			res.atomic_counters.push_back({ var.self, var.basetype, type.self, get_name(var.self) });
 		}
 		}
-	}
+	});
 
 
 	return res;
 	return res;
 }
 }
@@ -829,52 +836,67 @@ void Compiler::fixup_type_alias()
 	// Due to how some backends work, the "master" type of type_alias must be a block-like type if it exists.
 	// Due to how some backends work, the "master" type of type_alias must be a block-like type if it exists.
 	// FIXME: Multiple alias types which are both block-like will be awkward, for now, it's best to just drop the type
 	// FIXME: Multiple alias types which are both block-like will be awkward, for now, it's best to just drop the type
 	// alias if the slave type is a block type.
 	// alias if the slave type is a block type.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() != TypeType)
-			continue;
-
-		auto &type = id.get<SPIRType>();
-
+	ir.for_each_typed_id<SPIRType>([&](uint32_t self, SPIRType &type) {
 		if (type.type_alias && type_is_block_like(type))
 		if (type.type_alias && type_is_block_like(type))
 		{
 		{
 			// Become the master.
 			// Become the master.
-			for (auto &other_id : ir.ids)
-			{
-				if (other_id.get_type() != TypeType)
-					continue;
-				if (other_id.get_id() == type.self)
-					continue;
+			ir.for_each_typed_id<SPIRType>([&](uint32_t other_id, SPIRType &other_type) {
+				if (other_id == type.self)
+					return;
 
 
-				auto &other_type = other_id.get<SPIRType>();
 				if (other_type.type_alias == type.type_alias)
 				if (other_type.type_alias == type.type_alias)
 					other_type.type_alias = type.self;
 					other_type.type_alias = type.self;
-			}
+			});
 
 
-			get<SPIRType>(type.type_alias).type_alias = id.get_id();
+			this->get<SPIRType>(type.type_alias).type_alias = self;
 			type.type_alias = 0;
 			type.type_alias = 0;
 		}
 		}
-	}
+	});
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() != TypeType)
-			continue;
-
-		auto &type = id.get<SPIRType>();
+	ir.for_each_typed_id<SPIRType>([&](uint32_t, SPIRType &type) {
 		if (type.type_alias && type_is_block_like(type))
 		if (type.type_alias && type_is_block_like(type))
 		{
 		{
 			// This is not allowed, drop the type_alias.
 			// This is not allowed, drop the type_alias.
 			type.type_alias = 0;
 			type.type_alias = 0;
 		}
 		}
+	});
+
+	// Reorder declaration of types so that the master of the type alias is always emitted first.
+	// We need this in case a type B depends on type A (A must come before in the vector), but A is an alias of a type Abuffer, which
+	// means declaration of A doesn't happen (yet), and order would be B, ABuffer and not ABuffer, B. Fix this up here.
+	auto &type_ids = ir.ids_for_type[TypeType];
+	for (auto alias_itr = begin(type_ids); alias_itr != end(type_ids); ++alias_itr)
+	{
+		auto &type = get<SPIRType>(*alias_itr);
+		if (type.type_alias != 0 && !has_decoration(type.type_alias, DecorationCPacked))
+		{
+			// We will skip declaring this type, so make sure the type_alias type comes before.
+			auto master_itr = find(begin(type_ids), end(type_ids), type.type_alias);
+			assert(master_itr != end(type_ids));
+
+			if (alias_itr < master_itr)
+			{
+				// Must also swap the type order for the constant-type joined array.
+				auto &joined_types = ir.ids_for_constant_or_type;
+				auto alt_alias_itr = find(begin(joined_types), end(joined_types), *alias_itr);
+				auto alt_master_itr = find(begin(joined_types), end(joined_types), *master_itr);
+				assert(alt_alias_itr != end(joined_types));
+				assert(alt_master_itr != end(joined_types));
+
+				swap(*alias_itr, *master_itr);
+				swap(*alt_alias_itr, *alt_master_itr);
+			}
+		}
 	}
 	}
 }
 }
 
 
 void Compiler::parse_fixup()
 void Compiler::parse_fixup()
 {
 {
 	// Figure out specialization constants for work group sizes.
 	// Figure out specialization constants for work group sizes.
-	for (auto &id : ir.ids)
+	for (auto id_ : ir.ids_for_constant_or_variable)
 	{
 	{
+		auto &id = ir.ids[id_];
+
 		if (id.get_type() == TypeConstant)
 		if (id.get_type() == TypeConstant)
 		{
 		{
 			auto &c = id.get<SPIRConstant>();
 			auto &c = id.get<SPIRConstant>();
@@ -909,7 +931,7 @@ void Compiler::flatten_interface_block(uint32_t id)
 {
 {
 	auto &var = get<SPIRVariable>(id);
 	auto &var = get<SPIRVariable>(id);
 	auto &type = get<SPIRType>(var.basetype);
 	auto &type = get<SPIRType>(var.basetype);
-	auto &flags = ir.meta.at(type.self).decoration.decoration_flags;
+	auto &flags = ir.meta[type.self].decoration.decoration_flags;
 
 
 	if (!type.array.empty())
 	if (!type.array.empty())
 		SPIRV_CROSS_THROW("Type is array of UBOs.");
 		SPIRV_CROSS_THROW("Type is array of UBOs.");
@@ -932,7 +954,7 @@ void Compiler::flatten_interface_block(uint32_t id)
 		SPIRV_CROSS_THROW("Member type cannot be struct.");
 		SPIRV_CROSS_THROW("Member type cannot be struct.");
 
 
 	// Inherit variable name from interface block name.
 	// Inherit variable name from interface block name.
-	ir.meta.at(var.self).decoration.alias = ir.meta.at(type.self).decoration.alias;
+	ir.meta[var.self].decoration.alias = ir.meta[type.self].decoration.alias;
 
 
 	auto storage = var.storage;
 	auto storage = var.storage;
 	if (storage == StorageClassUniform)
 	if (storage == StorageClassUniform)
@@ -1095,19 +1117,17 @@ const std::string &Compiler::get_member_name(uint32_t id, uint32_t index) const
 
 
 void Compiler::set_member_qualified_name(uint32_t type_id, uint32_t index, const std::string &name)
 void Compiler::set_member_qualified_name(uint32_t type_id, uint32_t index, const std::string &name)
 {
 {
-	ir.meta.at(type_id).members.resize(max(ir.meta[type_id].members.size(), size_t(index) + 1));
-	ir.meta.at(type_id).members[index].qualified_alias = name;
+	ir.meta[type_id].members.resize(max(ir.meta[type_id].members.size(), size_t(index) + 1));
+	ir.meta[type_id].members[index].qualified_alias = name;
 }
 }
 
 
-const std::string &Compiler::get_member_qualified_name(uint32_t type_id, uint32_t index) const
+const string &Compiler::get_member_qualified_name(uint32_t type_id, uint32_t index) const
 {
 {
-	const static string empty;
-
-	auto &m = ir.meta.at(type_id);
-	if (index < m.members.size())
-		return m.members[index].qualified_alias;
+	auto *m = ir.find_meta(type_id);
+	if (m && index < m->members.size())
+		return m->members[index].qualified_alias;
 	else
 	else
-		return empty;
+		return ir.get_empty_string();
 }
 }
 
 
 uint32_t Compiler::get_member_decoration(uint32_t id, uint32_t index, Decoration decoration) const
 uint32_t Compiler::get_member_decoration(uint32_t id, uint32_t index, Decoration decoration) const
@@ -1152,7 +1172,7 @@ StorageClass Compiler::get_storage_class(uint32_t id) const
 
 
 const std::string &Compiler::get_name(uint32_t id) const
 const std::string &Compiler::get_name(uint32_t id) const
 {
 {
-	return ir.meta.at(id).decoration.alias;
+	return ir.get_name(id);
 }
 }
 
 
 const std::string Compiler::get_fallback_name(uint32_t id) const
 const std::string Compiler::get_fallback_name(uint32_t id) const
@@ -1206,7 +1226,11 @@ void Compiler::unset_decoration(uint32_t id, Decoration decoration)
 
 
 bool Compiler::get_binary_offset_for_decoration(uint32_t id, spv::Decoration decoration, uint32_t &word_offset) const
 bool Compiler::get_binary_offset_for_decoration(uint32_t id, spv::Decoration decoration, uint32_t &word_offset) const
 {
 {
-	auto &word_offsets = ir.meta.at(id).decoration_word_offset;
+	auto *m = ir.find_meta(id);
+	if (!m)
+		return false;
+
+	auto &word_offsets = m->decoration_word_offset;
 	auto itr = word_offsets.find(decoration);
 	auto itr = word_offsets.find(decoration);
 	if (itr == end(word_offsets))
 	if (itr == end(word_offsets))
 		return false;
 		return false;
@@ -1435,32 +1459,50 @@ bool Compiler::traverse_all_reachable_opcodes(const SPIRFunction &func, OpcodeHa
 
 
 uint32_t Compiler::type_struct_member_offset(const SPIRType &type, uint32_t index) const
 uint32_t Compiler::type_struct_member_offset(const SPIRType &type, uint32_t index) const
 {
 {
-	// Decoration must be set in valid SPIR-V, otherwise throw.
-	auto &dec = ir.meta[type.self].members.at(index);
-	if (dec.decoration_flags.get(DecorationOffset))
-		return dec.offset;
+	auto *type_meta = ir.find_meta(type.self);
+	if (type_meta)
+	{
+		// Decoration must be set in valid SPIR-V, otherwise throw.
+		auto &dec = type_meta->members[index];
+		if (dec.decoration_flags.get(DecorationOffset))
+			return dec.offset;
+		else
+			SPIRV_CROSS_THROW("Struct member does not have Offset set.");
+	}
 	else
 	else
 		SPIRV_CROSS_THROW("Struct member does not have Offset set.");
 		SPIRV_CROSS_THROW("Struct member does not have Offset set.");
 }
 }
 
 
 uint32_t Compiler::type_struct_member_array_stride(const SPIRType &type, uint32_t index) const
 uint32_t Compiler::type_struct_member_array_stride(const SPIRType &type, uint32_t index) const
 {
 {
-	// Decoration must be set in valid SPIR-V, otherwise throw.
-	// ArrayStride is part of the array type not OpMemberDecorate.
-	auto &dec = ir.meta[type.member_types[index]].decoration;
-	if (dec.decoration_flags.get(DecorationArrayStride))
-		return dec.array_stride;
+	auto *type_meta = ir.find_meta(type.member_types[index]);
+	if (type_meta)
+	{
+		// Decoration must be set in valid SPIR-V, otherwise throw.
+		// ArrayStride is part of the array type not OpMemberDecorate.
+		auto &dec = type_meta->decoration;
+		if (dec.decoration_flags.get(DecorationArrayStride))
+			return dec.array_stride;
+		else
+			SPIRV_CROSS_THROW("Struct member does not have ArrayStride set.");
+	}
 	else
 	else
-		SPIRV_CROSS_THROW("Struct member does not have ArrayStride set.");
+		SPIRV_CROSS_THROW("Struct member does not have Offset set.");
 }
 }
 
 
 uint32_t Compiler::type_struct_member_matrix_stride(const SPIRType &type, uint32_t index) const
 uint32_t Compiler::type_struct_member_matrix_stride(const SPIRType &type, uint32_t index) const
 {
 {
-	// Decoration must be set in valid SPIR-V, otherwise throw.
-	// MatrixStride is part of OpMemberDecorate.
-	auto &dec = ir.meta[type.self].members[index];
-	if (dec.decoration_flags.get(DecorationMatrixStride))
-		return dec.matrix_stride;
+	auto *type_meta = ir.find_meta(type.self);
+	if (type_meta)
+	{
+		// Decoration must be set in valid SPIR-V, otherwise throw.
+		// MatrixStride is part of OpMemberDecorate.
+		auto &dec = type_meta->members[index];
+		if (dec.decoration_flags.get(DecorationMatrixStride))
+			return dec.matrix_stride;
+		else
+			SPIRV_CROSS_THROW("Struct member does not have MatrixStride set.");
+	}
 	else
 	else
 		SPIRV_CROSS_THROW("Struct member does not have MatrixStride set.");
 		SPIRV_CROSS_THROW("Struct member does not have MatrixStride set.");
 }
 }
@@ -1557,7 +1599,7 @@ bool Compiler::BufferAccessHandler::handle(Op opcode, const uint32_t *args, uint
 	bool ptr_chain = (opcode == OpPtrAccessChain);
 	bool ptr_chain = (opcode == OpPtrAccessChain);
 
 
 	// Invalid SPIR-V.
 	// Invalid SPIR-V.
-	if (length < (ptr_chain ? 5 : 4))
+	if (length < (ptr_chain ? 5u : 4u))
 		return false;
 		return false;
 
 
 	if (args[2] != id)
 	if (args[2] != id)
@@ -2433,16 +2475,11 @@ uint32_t Compiler::build_dummy_sampler_for_combined_images()
 
 
 void Compiler::build_combined_image_samplers()
 void Compiler::build_combined_image_samplers()
 {
 {
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeFunction)
-		{
-			auto &func = id.get<SPIRFunction>();
-			func.combined_parameters.clear();
-			func.shadow_arguments.clear();
-			func.do_combined_parameters = true;
-		}
-	}
+	ir.for_each_typed_id<SPIRFunction>([&](uint32_t, SPIRFunction &func) {
+		func.combined_parameters.clear();
+		func.shadow_arguments.clear();
+		func.do_combined_parameters = true;
+	});
 
 
 	combined_image_samplers.clear();
 	combined_image_samplers.clear();
 	CombinedImageSamplerHandler handler(*this);
 	CombinedImageSamplerHandler handler(*this);
@@ -2452,15 +2489,10 @@ void Compiler::build_combined_image_samplers()
 vector<SpecializationConstant> Compiler::get_specialization_constants() const
 vector<SpecializationConstant> Compiler::get_specialization_constants() const
 {
 {
 	vector<SpecializationConstant> spec_consts;
 	vector<SpecializationConstant> spec_consts;
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeConstant)
-		{
-			auto &c = id.get<SPIRConstant>();
-			if (c.specialization && has_decoration(c.self, DecorationSpecId))
-				spec_consts.push_back({ c.self, get_decoration(c.self, DecorationSpecId) });
-		}
-	}
+	ir.for_each_typed_id<SPIRConstant>([&](uint32_t, const SPIRConstant &c) {
+		if (c.specialization && has_decoration(c.self, DecorationSpecId))
+			spec_consts.push_back({ c.self, get_decoration(c.self, DecorationSpecId) });
+	});
 	return spec_consts;
 	return spec_consts;
 }
 }
 
 
@@ -2892,12 +2924,6 @@ void Compiler::find_function_local_luts(SPIRFunction &entry, const AnalyzeVariab
 		if (type.array.empty())
 		if (type.array.empty())
 			continue;
 			continue;
 
 
-		// HACK: Do not consider structs. This is a quirk with how types are currently being emitted.
-		// Structs are emitted after specialization constants and composite constants.
-		// FIXME: Fix declaration order so declared constants can have struct types.
-		if (type.basetype == SPIRType::Struct)
-			continue;
-
 		// If the variable has an initializer, make sure it is a constant expression.
 		// If the variable has an initializer, make sure it is a constant expression.
 		uint32_t static_constant_expression = 0;
 		uint32_t static_constant_expression = 0;
 		if (var.initializer)
 		if (var.initializer)
@@ -3616,15 +3642,18 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
 
 
 bool Compiler::buffer_is_hlsl_counter_buffer(uint32_t id) const
 bool Compiler::buffer_is_hlsl_counter_buffer(uint32_t id) const
 {
 {
-	return ir.meta.at(id).hlsl_is_magic_counter_buffer;
+	auto *m = ir.find_meta(id);
+	return m && m->hlsl_is_magic_counter_buffer;
 }
 }
 
 
 bool Compiler::buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const
 bool Compiler::buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const
 {
 {
+	auto *m = ir.find_meta(id);
+
 	// First, check for the proper decoration.
 	// First, check for the proper decoration.
-	if (ir.meta[id].hlsl_magic_counter_buffer != 0)
+	if (m && m->hlsl_magic_counter_buffer != 0)
 	{
 	{
-		counter_id = ir.meta[id].hlsl_magic_counter_buffer;
+		counter_id = m->hlsl_magic_counter_buffer;
 		return true;
 		return true;
 	}
 	}
 	else
 	else
@@ -3691,8 +3720,10 @@ std::string Compiler::get_remapped_declared_block_name(uint32_t id) const
 	{
 	{
 		auto &var = get<SPIRVariable>(id);
 		auto &var = get<SPIRVariable>(id);
 		auto &type = get<SPIRType>(var.basetype);
 		auto &type = get<SPIRType>(var.basetype);
-		auto &block_name = ir.meta[type.self].decoration.alias;
-		return block_name.empty() ? get_block_fallback_name(id) : block_name;
+
+		auto *type_meta = ir.find_meta(type.self);
+		auto *block_name = type_meta ? &type_meta->decoration.alias : nullptr;
+		return (!block_name || block_name->empty()) ? get_block_fallback_name(id) : *block_name;
 	}
 	}
 }
 }
 
 
@@ -3739,15 +3770,20 @@ bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &resul
 Bitset Compiler::combined_decoration_for_member(const SPIRType &type, uint32_t index) const
 Bitset Compiler::combined_decoration_for_member(const SPIRType &type, uint32_t index) const
 {
 {
 	Bitset flags;
 	Bitset flags;
-	auto &memb = ir.meta[type.self].members;
-	if (index >= memb.size())
-		return flags;
-	auto &dec = memb[index];
-
-	// If our type is a struct, traverse all the members as well recursively.
-	flags.merge_or(dec.decoration_flags);
-	for (uint32_t i = 0; i < type.member_types.size(); i++)
-		flags.merge_or(combined_decoration_for_member(get<SPIRType>(type.member_types[i]), i));
+	auto *type_meta = ir.find_meta(type.self);
+
+	if (type_meta)
+	{
+		auto &memb = type_meta->members;
+		if (index >= memb.size())
+			return flags;
+		auto &dec = memb[index];
+
+		// If our type is a struct, traverse all the members as well recursively.
+		flags.merge_or(dec.decoration_flags);
+		for (uint32_t i = 0; i < type.member_types.size(); i++)
+			flags.merge_or(combined_decoration_for_member(get<SPIRType>(type.member_types[i]), i));
+	}
 
 
 	return flags;
 	return flags;
 }
 }

+ 6 - 5
3rdparty/spirv-cross/spirv_cross.hpp

@@ -561,7 +561,8 @@ protected:
 	template <typename T, typename... P>
 	template <typename T, typename... P>
 	T &set(uint32_t id, P &&... args)
 	T &set(uint32_t id, P &&... args)
 	{
 	{
-		auto &var = variant_set<T>(ir.ids.at(id), std::forward<P>(args)...);
+		ir.add_typed_id(static_cast<Types>(T::type), id);
+		auto &var = variant_set<T>(ir.ids[id], std::forward<P>(args)...);
 		var.self = id;
 		var.self = id;
 		return var;
 		return var;
 	}
 	}
@@ -569,13 +570,13 @@ protected:
 	template <typename T>
 	template <typename T>
 	T &get(uint32_t id)
 	T &get(uint32_t id)
 	{
 	{
-		return variant_get<T>(ir.ids.at(id));
+		return variant_get<T>(ir.ids[id]);
 	}
 	}
 
 
 	template <typename T>
 	template <typename T>
 	T *maybe_get(uint32_t id)
 	T *maybe_get(uint32_t id)
 	{
 	{
-		if (ir.ids.at(id).get_type() == T::type)
+		if (ir.ids[id].get_type() == static_cast<Types>(T::type))
 			return &get<T>(id);
 			return &get<T>(id);
 		else
 		else
 			return nullptr;
 			return nullptr;
@@ -584,13 +585,13 @@ protected:
 	template <typename T>
 	template <typename T>
 	const T &get(uint32_t id) const
 	const T &get(uint32_t id) const
 	{
 	{
-		return variant_get<T>(ir.ids.at(id));
+		return variant_get<T>(ir.ids[id]);
 	}
 	}
 
 
 	template <typename T>
 	template <typename T>
 	const T *maybe_get(uint32_t id) const
 	const T *maybe_get(uint32_t id) const
 	{
 	{
-		if (ir.ids.at(id).get_type() == T::type)
+		if (ir.ids[id].get_type() == static_cast<Types>(T::type))
 			return &get<T>(id);
 			return &get<T>(id);
 		else
 		else
 			return nullptr;
 			return nullptr;

+ 134 - 38
3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp

@@ -15,6 +15,7 @@
  */
  */
 
 
 #include "spirv_cross_parsed_ir.hpp"
 #include "spirv_cross_parsed_ir.hpp"
+#include <algorithm>
 #include <assert.h>
 #include <assert.h>
 
 
 using namespace std;
 using namespace std;
@@ -25,7 +26,6 @@ namespace spirv_cross
 void ParsedIR::set_id_bounds(uint32_t bounds)
 void ParsedIR::set_id_bounds(uint32_t bounds)
 {
 {
 	ids.resize(bounds);
 	ids.resize(bounds);
-	meta.resize(bounds);
 	block_meta.resize(bounds);
 	block_meta.resize(bounds);
 }
 }
 
 
@@ -65,19 +65,24 @@ static string ensure_valid_identifier(const string &name, bool member)
 
 
 const string &ParsedIR::get_name(uint32_t id) const
 const string &ParsedIR::get_name(uint32_t id) const
 {
 {
-	return meta[id].decoration.alias;
+	auto *m = find_meta(id);
+	if (m)
+		return m->decoration.alias;
+	else
+		return empty_string;
 }
 }
 
 
 const string &ParsedIR::get_member_name(uint32_t id, uint32_t index) const
 const string &ParsedIR::get_member_name(uint32_t id, uint32_t index) const
 {
 {
-	auto &m = meta[id];
-	if (index >= m.members.size())
+	auto *m = find_meta(id);
+	if (m)
 	{
 	{
-		static string empty;
-		return empty;
+		if (index >= m->members.size())
+			return empty_string;
+		return m->members[index].alias;
 	}
 	}
-
-	return m.members[index].alias;
+	else
+		return empty_string;
 }
 }
 
 
 void ParsedIR::set_name(uint32_t id, const string &name)
 void ParsedIR::set_name(uint32_t id, const string &name)
@@ -273,7 +278,10 @@ Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
 	// Some flags like non-writable, non-readable are actually found
 	// Some flags like non-writable, non-readable are actually found
 	// as member decorations. If all members have a decoration set, propagate
 	// as member decorations. If all members have a decoration set, propagate
 	// the decoration up as a regular variable decoration.
 	// the decoration up as a regular variable decoration.
-	Bitset base_flags = meta[var.self].decoration.decoration_flags;
+	Bitset base_flags;
+	auto *m = find_meta(var.self);
+	if (m)
+		base_flags = m->decoration.decoration_flags;
 
 
 	if (type.member_types.empty())
 	if (type.member_types.empty())
 		return base_flags;
 		return base_flags;
@@ -288,14 +296,15 @@ Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
 
 
 const Bitset &ParsedIR::get_member_decoration_bitset(uint32_t id, uint32_t index) const
 const Bitset &ParsedIR::get_member_decoration_bitset(uint32_t id, uint32_t index) const
 {
 {
-	auto &m = meta[id];
-	if (index >= m.members.size())
+	auto *m = find_meta(id);
+	if (m)
 	{
 	{
-		static const Bitset cleared = {};
-		return cleared;
+		if (index >= m->members.size())
+			return cleared_bitset;
+		return m->members[index].decoration_flags;
 	}
 	}
-
-	return m.members[index].decoration_flags;
+	else
+		return cleared_bitset;
 }
 }
 
 
 bool ParsedIR::has_decoration(uint32_t id, Decoration decoration) const
 bool ParsedIR::has_decoration(uint32_t id, Decoration decoration) const
@@ -305,7 +314,11 @@ bool ParsedIR::has_decoration(uint32_t id, Decoration decoration) const
 
 
 uint32_t ParsedIR::get_decoration(uint32_t id, Decoration decoration) const
 uint32_t ParsedIR::get_decoration(uint32_t id, Decoration decoration) const
 {
 {
-	auto &dec = meta[id].decoration;
+	auto *m = find_meta(id);
+	if (!m)
+		return 0;
+
+	auto &dec = m->decoration;
 	if (!dec.decoration_flags.get(decoration))
 	if (!dec.decoration_flags.get(decoration))
 		return 0;
 		return 0;
 
 
@@ -342,11 +355,14 @@ uint32_t ParsedIR::get_decoration(uint32_t id, Decoration decoration) const
 
 
 const string &ParsedIR::get_decoration_string(uint32_t id, Decoration decoration) const
 const string &ParsedIR::get_decoration_string(uint32_t id, Decoration decoration) const
 {
 {
-	auto &dec = meta[id].decoration;
-	static const string empty;
+	auto *m = find_meta(id);
+	if (!m)
+		return empty_string;
+
+	auto &dec = m->decoration;
 
 
 	if (!dec.decoration_flags.get(decoration))
 	if (!dec.decoration_flags.get(decoration))
-		return empty;
+		return empty_string;
 
 
 	switch (decoration)
 	switch (decoration)
 	{
 	{
@@ -354,7 +370,7 @@ const string &ParsedIR::get_decoration_string(uint32_t id, Decoration decoration
 		return dec.hlsl_semantic;
 		return dec.hlsl_semantic;
 
 
 	default:
 	default:
-		return empty;
+		return empty_string;
 	}
 	}
 }
 }
 
 
@@ -427,11 +443,14 @@ bool ParsedIR::has_member_decoration(uint32_t id, uint32_t index, Decoration dec
 
 
 uint32_t ParsedIR::get_member_decoration(uint32_t id, uint32_t index, Decoration decoration) const
 uint32_t ParsedIR::get_member_decoration(uint32_t id, uint32_t index, Decoration decoration) const
 {
 {
-	auto &m = meta[id];
-	if (index >= m.members.size())
+	auto *m = find_meta(id);
+	if (!m)
 		return 0;
 		return 0;
 
 
-	auto &dec = m.members[index];
+	if (index >= m->members.size())
+		return 0;
+
+	auto &dec = m->members[index];
 	if (!dec.decoration_flags.get(decoration))
 	if (!dec.decoration_flags.get(decoration))
 		return 0;
 		return 0;
 
 
@@ -458,8 +477,14 @@ uint32_t ParsedIR::get_member_decoration(uint32_t id, uint32_t index, Decoration
 
 
 const Bitset &ParsedIR::get_decoration_bitset(uint32_t id) const
 const Bitset &ParsedIR::get_decoration_bitset(uint32_t id) const
 {
 {
-	auto &dec = meta[id].decoration;
-	return dec.decoration_flags;
+	auto *m = find_meta(id);
+	if (m)
+	{
+		auto &dec = m->decoration;
+		return dec.decoration_flags;
+	}
+	else
+		return cleared_bitset;
 }
 }
 
 
 void ParsedIR::set_member_decoration_string(uint32_t id, uint32_t index, Decoration decoration, const string &argument)
 void ParsedIR::set_member_decoration_string(uint32_t id, uint32_t index, Decoration decoration, const string &argument)
@@ -481,22 +506,25 @@ void ParsedIR::set_member_decoration_string(uint32_t id, uint32_t index, Decorat
 
 
 const string &ParsedIR::get_member_decoration_string(uint32_t id, uint32_t index, Decoration decoration) const
 const string &ParsedIR::get_member_decoration_string(uint32_t id, uint32_t index, Decoration decoration) const
 {
 {
-	static const string empty;
-	auto &m = meta[id];
-
-	if (!has_member_decoration(id, index, decoration))
-		return empty;
+	auto *m = find_meta(id);
+	if (m)
+	{
+		if (!has_member_decoration(id, index, decoration))
+			return empty_string;
 
 
-	auto &dec = m.members[index];
+		auto &dec = m->members[index];
 
 
-	switch (decoration)
-	{
-	case DecorationHlslSemanticGOOGLE:
-		return dec.hlsl_semantic;
+		switch (decoration)
+		{
+		case DecorationHlslSemanticGOOGLE:
+			return dec.hlsl_semantic;
 
 
-	default:
-		return empty;
+		default:
+			return empty_string;
+		}
 	}
 	}
+	else
+		return empty_string;
 }
 }
 
 
 void ParsedIR::unset_member_decoration(uint32_t id, uint32_t index, Decoration decoration)
 void ParsedIR::unset_member_decoration(uint32_t id, uint32_t index, Decoration decoration)
@@ -544,9 +572,77 @@ uint32_t ParsedIR::increase_bound_by(uint32_t incr_amount)
 	auto curr_bound = ids.size();
 	auto curr_bound = ids.size();
 	auto new_bound = curr_bound + incr_amount;
 	auto new_bound = curr_bound + incr_amount;
 	ids.resize(new_bound);
 	ids.resize(new_bound);
-	meta.resize(new_bound);
 	block_meta.resize(new_bound);
 	block_meta.resize(new_bound);
 	return uint32_t(curr_bound);
 	return uint32_t(curr_bound);
 }
 }
 
 
+void ParsedIR::remove_typed_id(Types type, uint32_t id)
+{
+	auto &type_ids = ids_for_type[type];
+	type_ids.erase(remove(begin(type_ids), end(type_ids), id), end(type_ids));
+}
+
+void ParsedIR::reset_all_of_type(Types type)
+{
+	for (auto &id : ids_for_type[type])
+		if (ids[id].get_type() == type)
+			ids[id].reset();
+
+	ids_for_type[type].clear();
+}
+
+void ParsedIR::add_typed_id(Types type, uint32_t id)
+{
+	if (loop_iteration_depth)
+		SPIRV_CROSS_THROW("Cannot add typed ID while looping over it.");
+
+	switch (type)
+	{
+	case TypeConstant:
+		ids_for_constant_or_variable.push_back(id);
+		ids_for_constant_or_type.push_back(id);
+		break;
+
+	case TypeVariable:
+		ids_for_constant_or_variable.push_back(id);
+		break;
+
+	case TypeType:
+	case TypeConstantOp:
+		ids_for_constant_or_type.push_back(id);
+		break;
+
+	default:
+		break;
+	}
+
+	if (ids[id].empty())
+	{
+		ids_for_type[type].push_back(id);
+	}
+	else if (ids[id].get_type() != type)
+	{
+		remove_typed_id(ids[id].get_type(), id);
+		ids_for_type[type].push_back(id);
+	}
+}
+
+const Meta *ParsedIR::find_meta(uint32_t id) const
+{
+	auto itr = meta.find(id);
+	if (itr != end(meta))
+		return &itr->second;
+	else
+		return nullptr;
+}
+
+Meta *ParsedIR::find_meta(uint32_t id)
+{
+	auto itr = meta.find(id);
+	if (itr != end(meta))
+		return &itr->second;
+	else
+		return nullptr;
+}
+
 } // namespace spirv_cross
 } // namespace spirv_cross

+ 58 - 1
3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp

@@ -43,7 +43,19 @@ public:
 	std::vector<Variant> ids;
 	std::vector<Variant> ids;
 
 
 	// Various meta data for IDs, decorations, names, etc.
 	// Various meta data for IDs, decorations, names, etc.
-	std::vector<Meta> meta;
+	std::unordered_map<uint32_t, Meta> meta;
+
+	// Holds all IDs which have a certain type.
+	// This is needed so we can iterate through a specific kind of resource quickly,
+	// and in-order of module declaration.
+	std::vector<uint32_t> ids_for_type[TypeCount];
+
+	// Special purpose lists which contain a union of types.
+	// This is needed so we can declare specialization constants and structs in an interleaved fashion,
+	// among other things.
+	// Constants can be of struct type, and struct array sizes can use specialization constants.
+	std::vector<uint32_t> ids_for_constant_or_type;
+	std::vector<uint32_t> ids_for_constant_or_variable;
 
 
 	// Declared capabilities and extensions in the SPIR-V module.
 	// Declared capabilities and extensions in the SPIR-V module.
 	// Not really used except for reflection at the moment.
 	// Not really used except for reflection at the moment.
@@ -111,6 +123,47 @@ public:
 	uint32_t increase_bound_by(uint32_t count);
 	uint32_t increase_bound_by(uint32_t count);
 	Bitset get_buffer_block_flags(const SPIRVariable &var) const;
 	Bitset get_buffer_block_flags(const SPIRVariable &var) const;
 
 
+	void add_typed_id(Types type, uint32_t id);
+	void remove_typed_id(Types type, uint32_t id);
+
+	template <typename T, typename Op>
+	void for_each_typed_id(const Op &op)
+	{
+		loop_iteration_depth++;
+		for (auto &id : ids_for_type[T::type])
+		{
+			if (ids[id].get_type() == static_cast<Types>(T::type))
+				op(id, get<T>(id));
+		}
+		loop_iteration_depth--;
+	}
+
+	template <typename T, typename Op>
+	void for_each_typed_id(const Op &op) const
+	{
+		for (auto &id : ids_for_type[T::type])
+		{
+			if (ids[id].get_type() == static_cast<Types>(T::type))
+				op(id, get<T>(id));
+		}
+	}
+
+	template <typename T>
+	void reset_all_of_type()
+	{
+		reset_all_of_type(static_cast<Types>(T::type));
+	}
+
+	void reset_all_of_type(Types type);
+
+	Meta *find_meta(uint32_t id);
+	const Meta *find_meta(uint32_t id) const;
+
+	const std::string &get_empty_string() const
+	{
+		return empty_string;
+	}
+
 private:
 private:
 	template <typename T>
 	template <typename T>
 	T &get(uint32_t id)
 	T &get(uint32_t id)
@@ -123,6 +176,10 @@ private:
 	{
 	{
 		return variant_get<T>(ids[id]);
 		return variant_get<T>(ids[id]);
 	}
 	}
+
+	uint32_t loop_iteration_depth = 0;
+	std::string empty_string;
+	Bitset cleared_bitset;
 };
 };
 } // namespace spirv_cross
 } // namespace spirv_cross
 
 

+ 141 - 196
3rdparty/spirv-cross/spirv_glsl.cpp

@@ -291,25 +291,15 @@ void CompilerGLSL::reset()
 	block_names.clear();
 	block_names.clear();
 	function_overloads.clear();
 	function_overloads.clear();
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			// Clear unflushed dependees.
-			id.get<SPIRVariable>().dependees.clear();
-		}
-		else if (id.get_type() == TypeExpression)
-		{
-			// And remove all expressions.
-			id.reset();
-		}
-		else if (id.get_type() == TypeFunction)
-		{
-			// Reset active state for all functions.
-			id.get<SPIRFunction>().active = false;
-			id.get<SPIRFunction>().flush_undeclared = true;
-		}
-	}
+	ir.for_each_typed_id<SPIRFunction>([&](uint32_t, SPIRFunction &func) {
+		func.active = false;
+		func.flush_undeclared = true;
+	});
+
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) { var.dependees.clear(); });
+
+	ir.reset_all_of_type<SPIRExpression>();
+	ir.reset_all_of_type<SPIRAccessChain>();
 
 
 	statement_count = 0;
 	statement_count = 0;
 	indent = 0;
 	indent = 0;
@@ -344,37 +334,32 @@ void CompilerGLSL::remap_pls_variables()
 
 
 void CompilerGLSL::find_static_extensions()
 void CompilerGLSL::find_static_extensions()
 {
 {
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeType)
+	ir.for_each_typed_id<SPIRType>([&](uint32_t, const SPIRType &type) {
+		if (type.basetype == SPIRType::Double)
 		{
 		{
-			auto &type = id.get<SPIRType>();
-			if (type.basetype == SPIRType::Double)
-			{
-				if (options.es)
-					SPIRV_CROSS_THROW("FP64 not supported in ES profile.");
-				if (!options.es && options.version < 400)
-					require_extension_internal("GL_ARB_gpu_shader_fp64");
-			}
+			if (options.es)
+				SPIRV_CROSS_THROW("FP64 not supported in ES profile.");
+			if (!options.es && options.version < 400)
+				require_extension_internal("GL_ARB_gpu_shader_fp64");
+		}
 
 
-			if (type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64)
-			{
-				if (options.es)
-					SPIRV_CROSS_THROW("64-bit integers not supported in ES profile.");
-				if (!options.es)
-					require_extension_internal("GL_ARB_gpu_shader_int64");
-			}
+		if (type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64)
+		{
+			if (options.es)
+				SPIRV_CROSS_THROW("64-bit integers not supported in ES profile.");
+			if (!options.es)
+				require_extension_internal("GL_ARB_gpu_shader_int64");
+		}
 
 
-			if (type.basetype == SPIRType::Half)
-				require_extension_internal("GL_AMD_gpu_shader_half_float");
+		if (type.basetype == SPIRType::Half)
+			require_extension_internal("GL_AMD_gpu_shader_half_float");
 
 
-			if (type.basetype == SPIRType::SByte || type.basetype == SPIRType::UByte)
-				require_extension_internal("GL_EXT_shader_8bit_storage");
+		if (type.basetype == SPIRType::SByte || type.basetype == SPIRType::UByte)
+			require_extension_internal("GL_EXT_shader_8bit_storage");
 
 
-			if (type.basetype == SPIRType::Short || type.basetype == SPIRType::UShort)
-				require_extension_internal("GL_AMD_gpu_shader_int16");
-		}
-	}
+		if (type.basetype == SPIRType::Short || type.basetype == SPIRType::UShort)
+			require_extension_internal("GL_AMD_gpu_shader_int16");
+	});
 
 
 	auto &execution = get_entry_point();
 	auto &execution = get_entry_point();
 	switch (execution.model)
 	switch (execution.model)
@@ -978,7 +963,7 @@ uint32_t CompilerGLSL::type_to_packed_alignment(const SPIRType &type, const Bits
 		uint32_t alignment = 0;
 		uint32_t alignment = 0;
 		for (uint32_t i = 0; i < type.member_types.size(); i++)
 		for (uint32_t i = 0; i < type.member_types.size(); i++)
 		{
 		{
-			auto member_flags = ir.meta[type.self].members.at(i).decoration_flags;
+			auto member_flags = ir.meta[type.self].members[i].decoration_flags;
 			alignment =
 			alignment =
 			    max(alignment, type_to_packed_alignment(get<SPIRType>(type.member_types[i]), member_flags, packing));
 			    max(alignment, type_to_packed_alignment(get<SPIRType>(type.member_types[i]), member_flags, packing));
 		}
 		}
@@ -1082,7 +1067,7 @@ uint32_t CompilerGLSL::type_to_packed_size(const SPIRType &type, const Bitset &f
 
 
 		for (uint32_t i = 0; i < type.member_types.size(); i++)
 		for (uint32_t i = 0; i < type.member_types.size(); i++)
 		{
 		{
-			auto member_flags = ir.meta[type.self].members.at(i).decoration_flags;
+			auto member_flags = ir.meta[type.self].members[i].decoration_flags;
 			auto &member_type = get<SPIRType>(type.member_types[i]);
 			auto &member_type = get<SPIRType>(type.member_types[i]);
 
 
 			uint32_t packed_alignment = type_to_packed_alignment(member_type, member_flags, packing);
 			uint32_t packed_alignment = type_to_packed_alignment(member_type, member_flags, packing);
@@ -1155,7 +1140,7 @@ bool CompilerGLSL::buffer_is_packing_standard(const SPIRType &type, BufferPackin
 	for (uint32_t i = 0; i < type.member_types.size(); i++)
 	for (uint32_t i = 0; i < type.member_types.size(); i++)
 	{
 	{
 		auto &memb_type = get<SPIRType>(type.member_types[i]);
 		auto &memb_type = get<SPIRType>(type.member_types[i]);
-		auto member_flags = ir.meta[type.self].members.at(i).decoration_flags;
+		auto member_flags = ir.meta[type.self].members[i].decoration_flags;
 
 
 		// Verify alignment rules.
 		// Verify alignment rules.
 		uint32_t packed_alignment = type_to_packed_alignment(memb_type, member_flags, packing);
 		uint32_t packed_alignment = type_to_packed_alignment(memb_type, member_flags, packing);
@@ -1902,19 +1887,14 @@ void CompilerGLSL::replace_illegal_names()
 	};
 	};
 	// clang-format on
 	// clang-format on
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) {
+		if (!is_hidden_variable(var))
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			if (!is_hidden_variable(var))
-			{
-				auto &m = ir.meta[var.self].decoration;
-				if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords))
-					m.alias = join("_", m.alias);
-			}
+			auto &m = ir.meta[var.self].decoration;
+			if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords))
+				m.alias = join("_", m.alias);
 		}
 		}
-	}
+	});
 }
 }
 
 
 void CompilerGLSL::replace_fragment_output(SPIRVariable &var)
 void CompilerGLSL::replace_fragment_output(SPIRVariable &var)
@@ -1957,18 +1937,12 @@ void CompilerGLSL::replace_fragment_output(SPIRVariable &var)
 
 
 void CompilerGLSL::replace_fragment_outputs()
 void CompilerGLSL::replace_fragment_outputs()
 {
 {
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
-			if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
-			    var.storage == StorageClassOutput)
-				replace_fragment_output(var);
-		}
-	}
+		if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer && var.storage == StorageClassOutput)
+			replace_fragment_output(var);
+	});
 }
 }
 
 
 string CompilerGLSL::remap_swizzle(const SPIRType &out_type, uint32_t input_components, const string &expr)
 string CompilerGLSL::remap_swizzle(const SPIRType &out_type, uint32_t input_components, const string &expr)
@@ -2027,12 +2001,7 @@ void CompilerGLSL::emit_pls()
 
 
 void CompilerGLSL::fixup_image_load_store_access()
 void CompilerGLSL::fixup_image_load_store_access()
 {
 {
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() != TypeVariable)
-			continue;
-
-		uint32_t var = id.get<SPIRVariable>().self;
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t var, const SPIRVariable &) {
 		auto &vartype = expression_type(var);
 		auto &vartype = expression_type(var);
 		if (vartype.basetype == SPIRType::Image)
 		if (vartype.basetype == SPIRType::Image)
 		{
 		{
@@ -2040,14 +2009,14 @@ void CompilerGLSL::fixup_image_load_store_access()
 			// Solve this by making the image access as restricted as possible and loosen up if we need to.
 			// Solve this by making the image access as restricted as possible and loosen up if we need to.
 			// If any no-read/no-write flags are actually set, assume that the compiler knows what it's doing.
 			// If any no-read/no-write flags are actually set, assume that the compiler knows what it's doing.
 
 
-			auto &flags = ir.meta.at(var).decoration.decoration_flags;
+			auto &flags = ir.meta[var].decoration.decoration_flags;
 			if (!flags.get(DecorationNonWritable) && !flags.get(DecorationNonReadable))
 			if (!flags.get(DecorationNonWritable) && !flags.get(DecorationNonReadable))
 			{
 			{
 				flags.set(DecorationNonWritable);
 				flags.set(DecorationNonWritable);
 				flags.set(DecorationNonReadable);
 				flags.set(DecorationNonReadable);
 			}
 			}
 		}
 		}
-	}
+	});
 }
 }
 
 
 void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionModel model)
 void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionModel model)
@@ -2063,13 +2032,8 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
 	uint32_t cull_distance_size = 0;
 	uint32_t cull_distance_size = 0;
 	uint32_t clip_distance_size = 0;
 	uint32_t clip_distance_size = 0;
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() != TypeVariable)
-			continue;
-
-		auto &var = id.get<SPIRVariable>();
-		auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 		bool block = has_decoration(type.self, DecorationBlock);
 		bool block = has_decoration(type.self, DecorationBlock);
 		Bitset builtins;
 		Bitset builtins;
 
 
@@ -2082,9 +2046,9 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
 				{
 				{
 					builtins.set(m.builtin_type);
 					builtins.set(m.builtin_type);
 					if (m.builtin_type == BuiltInCullDistance)
 					if (m.builtin_type == BuiltInCullDistance)
-						cull_distance_size = get<SPIRType>(type.member_types[index]).array.front();
+						cull_distance_size = this->get<SPIRType>(type.member_types[index]).array.front();
 					else if (m.builtin_type == BuiltInClipDistance)
 					else if (m.builtin_type == BuiltInClipDistance)
-						clip_distance_size = get<SPIRType>(type.member_types[index]).array.front();
+						clip_distance_size = this->get<SPIRType>(type.member_types[index]).array.front();
 				}
 				}
 				index++;
 				index++;
 			}
 			}
@@ -2104,7 +2068,7 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
 		}
 		}
 
 
 		if (builtins.empty())
 		if (builtins.empty())
-			continue;
+			return;
 
 
 		if (emitted_block)
 		if (emitted_block)
 			SPIRV_CROSS_THROW("Cannot use more than one builtin I/O block.");
 			SPIRV_CROSS_THROW("Cannot use more than one builtin I/O block.");
@@ -2113,7 +2077,7 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
 		emitted_block = true;
 		emitted_block = true;
 		builtin_array = !type.array.empty();
 		builtin_array = !type.array.empty();
 		block_var = &var;
 		block_var = &var;
-	}
+	});
 
 
 	global_builtins =
 	global_builtins =
 	    Bitset(global_builtins.get_lower() & ((1ull << BuiltInPosition) | (1ull << BuiltInPointSize) |
 	    Bitset(global_builtins.get_lower() & ((1ull << BuiltInPosition) | (1ull << BuiltInPointSize) |
@@ -2164,15 +2128,10 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
 void CompilerGLSL::declare_undefined_values()
 void CompilerGLSL::declare_undefined_values()
 {
 {
 	bool emitted = false;
 	bool emitted = false;
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() != TypeUndef)
-			continue;
-
-		auto &undef = id.get<SPIRUndef>();
-		statement(variable_decl(get<SPIRType>(undef.basetype), to_name(undef.self), undef.self), ";");
+	ir.for_each_typed_id<SPIRUndef>([&](uint32_t, const SPIRUndef &undef) {
+		statement(variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self), ";");
 		emitted = true;
 		emitted = true;
-	}
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
@@ -2238,10 +2197,10 @@ void CompilerGLSL::emit_resources()
 	// emit specialization constants as actual floats,
 	// emit specialization constants as actual floats,
 	// spec op expressions will redirect to the constant name.
 	// spec op expressions will redirect to the constant name.
 	//
 	//
-	// TODO: If we have the fringe case that we create a spec constant which depends on a struct type,
-	// we'll have to deal with that, but there's currently no known way to express that.
-	for (auto &id : ir.ids)
+	for (auto &id_ : ir.ids_for_constant_or_type)
 	{
 	{
+		auto &id = ir.ids[id_];
+
 		if (id.get_type() == TypeConstant)
 		if (id.get_type() == TypeConstant)
 		{
 		{
 			auto &c = id.get<SPIRConstant>();
 			auto &c = id.get<SPIRConstant>();
@@ -2264,6 +2223,20 @@ void CompilerGLSL::emit_resources()
 			emit_specialization_constant_op(id.get<SPIRConstantOp>());
 			emit_specialization_constant_op(id.get<SPIRConstantOp>());
 			emitted = true;
 			emitted = true;
 		}
 		}
+		else if (id.get_type() == TypeType)
+		{
+			auto &type = id.get<SPIRType>();
+			if (type.basetype == SPIRType::Struct && type.array.empty() && !type.pointer &&
+			    (!ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) &&
+			     !ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock)))
+			{
+				if (emitted)
+					statement("");
+				emitted = false;
+
+				emit_struct(type);
+			}
+		}
 	}
 	}
 
 
 	if (emitted)
 	if (emitted)
@@ -2289,120 +2262,84 @@ void CompilerGLSL::emit_resources()
 
 
 	emitted = false;
 	emitted = false;
 
 
-	// Output all basic struct types which are not Block or BufferBlock as these are declared inplace
-	// when such variables are instantiated.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeType)
-		{
-			auto &type = id.get<SPIRType>();
-			if (type.basetype == SPIRType::Struct && type.array.empty() && !type.pointer &&
-			    (!ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) &&
-			     !ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock)))
-			{
-				emit_struct(type);
-			}
-		}
-	}
-
 	// Output UBOs and SSBOs
 	// Output UBOs and SSBOs
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
-			bool is_block_storage = type.storage == StorageClassStorageBuffer || type.storage == StorageClassUniform;
-			bool has_block_flags = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) ||
-			                       ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
+		bool is_block_storage = type.storage == StorageClassStorageBuffer || type.storage == StorageClassUniform;
+		bool has_block_flags = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) ||
+		                       ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
 
 
-			if (var.storage != StorageClassFunction && type.pointer && is_block_storage && !is_hidden_variable(var) &&
-			    has_block_flags)
-			{
-				emit_buffer_block(var);
-			}
+		if (var.storage != StorageClassFunction && type.pointer && is_block_storage && !is_hidden_variable(var) &&
+		    has_block_flags)
+		{
+			emit_buffer_block(var);
 		}
 		}
-	}
+	});
 
 
 	// Output push constant blocks
 	// Output push constant blocks
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassPushConstant &&
+		    !is_hidden_variable(var))
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassPushConstant &&
-			    !is_hidden_variable(var))
-			{
-				emit_push_constant_block(var);
-			}
+			emit_push_constant_block(var);
 		}
 		}
-	}
+	});
 
 
 	bool skip_separate_image_sampler = !combined_image_samplers.empty() || !options.vulkan_semantics;
 	bool skip_separate_image_sampler = !combined_image_samplers.empty() || !options.vulkan_semantics;
 
 
 	// Output Uniform Constants (values, samplers, images, etc).
 	// Output Uniform Constants (values, samplers, images, etc).
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
-			// If we're remapping separate samplers and images, only emit the combined samplers.
-			if (skip_separate_image_sampler)
-			{
-				// Sampler buffers are always used without a sampler, and they will also work in regular GL.
-				bool sampler_buffer = type.basetype == SPIRType::Image && type.image.dim == DimBuffer;
-				bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
-				bool separate_sampler = type.basetype == SPIRType::Sampler;
-				if (!sampler_buffer && (separate_image || separate_sampler))
-					continue;
-			}
+		// If we're remapping separate samplers and images, only emit the combined samplers.
+		if (skip_separate_image_sampler)
+		{
+			// Sampler buffers are always used without a sampler, and they will also work in regular GL.
+			bool sampler_buffer = type.basetype == SPIRType::Image && type.image.dim == DimBuffer;
+			bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
+			bool separate_sampler = type.basetype == SPIRType::Sampler;
+			if (!sampler_buffer && (separate_image || separate_sampler))
+				return;
+		}
 
 
-			if (var.storage != StorageClassFunction && type.pointer &&
-			    (type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter) &&
-			    !is_hidden_variable(var))
-			{
-				emit_uniform(var);
-				emitted = true;
-			}
+		if (var.storage != StorageClassFunction && type.pointer &&
+		    (type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter) &&
+		    !is_hidden_variable(var))
+		{
+			emit_uniform(var);
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
 	emitted = false;
 	emitted = false;
 
 
 	// Output in/out interfaces.
 	// Output in/out interfaces.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
-			if (var.storage != StorageClassFunction && type.pointer &&
-			    (var.storage == StorageClassInput || var.storage == StorageClassOutput) &&
-			    interface_variable_exists_in_entry_point(var.self) && !is_hidden_variable(var))
+		if (var.storage != StorageClassFunction && type.pointer &&
+		    (var.storage == StorageClassInput || var.storage == StorageClassOutput) &&
+		    interface_variable_exists_in_entry_point(var.self) && !is_hidden_variable(var))
+		{
+			emit_interface_block(var);
+			emitted = true;
+		}
+		else if (is_builtin_variable(var))
+		{
+			// For gl_InstanceIndex emulation on GLES, the API user needs to
+			// supply this uniform.
+			if (options.vertex.support_nonzero_base_instance &&
+			    ir.meta[var.self].decoration.builtin_type == BuiltInInstanceIndex && !options.vulkan_semantics)
 			{
 			{
-				emit_interface_block(var);
+				statement("uniform int SPIRV_Cross_BaseInstance;");
 				emitted = true;
 				emitted = true;
 			}
 			}
-			else if (is_builtin_variable(var))
-			{
-				// For gl_InstanceIndex emulation on GLES, the API user needs to
-				// supply this uniform.
-				if (options.vertex.support_nonzero_base_instance &&
-				    ir.meta[var.self].decoration.builtin_type == BuiltInInstanceIndex && !options.vulkan_semantics)
-				{
-					statement("uniform int SPIRV_Cross_BaseInstance;");
-					emitted = true;
-				}
-			}
 		}
 		}
-	}
+	});
 
 
 	// Global variables.
 	// Global variables.
 	for (auto global : global_variables)
 	for (auto global : global_variables)
@@ -2526,7 +2463,7 @@ string CompilerGLSL::dereference_expression(const std::string &expr)
 	// If this expression starts with an address-of operator ('&'), then
 	// If this expression starts with an address-of operator ('&'), then
 	// just return the part after the operator.
 	// just return the part after the operator.
 	// TODO: Strip parens if unnecessary?
 	// TODO: Strip parens if unnecessary?
-	if (expr.at(0) == '&')
+	if (expr.front() == '&')
 		return expr.substr(1);
 		return expr.substr(1);
 	else
 	else
 		return join('*', expr);
 		return join('*', expr);
@@ -2537,7 +2474,7 @@ string CompilerGLSL::address_of_expression(const std::string &expr)
 	// If this expression starts with a dereference operator ('*'), then
 	// If this expression starts with a dereference operator ('*'), then
 	// just return the part after the operator.
 	// just return the part after the operator.
 	// TODO: Strip parens if unnecessary?
 	// TODO: Strip parens if unnecessary?
-	if (expr.at(0) == '*')
+	if (expr.front() == '*')
 		return expr.substr(1);
 		return expr.substr(1);
 	else
 	else
 		return join('&', expr);
 		return join('&', expr);
@@ -8135,7 +8072,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
 		auto *var = maybe_get_backing_variable(ops[2]);
 		auto *var = maybe_get_backing_variable(ops[2]);
 		if (var)
 		if (var)
 		{
 		{
-			auto &flags = ir.meta.at(var->self).decoration.decoration_flags;
+			auto &flags = ir.meta[var->self].decoration.decoration_flags;
 			if (flags.get(DecorationNonReadable))
 			if (flags.get(DecorationNonReadable))
 			{
 			{
 				flags.clear(DecorationNonReadable);
 				flags.clear(DecorationNonReadable);
@@ -8283,7 +8220,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
 		auto *var = maybe_get_backing_variable(ops[0]);
 		auto *var = maybe_get_backing_variable(ops[0]);
 		if (var)
 		if (var)
 		{
 		{
-			auto &flags = ir.meta.at(var->self).decoration.decoration_flags;
+			auto &flags = ir.meta[var->self].decoration.decoration_flags;
 			if (flags.get(DecorationNonWritable))
 			if (flags.get(DecorationNonWritable))
 			{
 			{
 				flags.clear(DecorationNonWritable);
 				flags.clear(DecorationNonWritable);
@@ -9473,7 +9410,7 @@ void CompilerGLSL::flatten_buffer_block(uint32_t id)
 	auto &var = get<SPIRVariable>(id);
 	auto &var = get<SPIRVariable>(id);
 	auto &type = get<SPIRType>(var.basetype);
 	auto &type = get<SPIRType>(var.basetype);
 	auto name = to_name(type.self, false);
 	auto name = to_name(type.self, false);
-	auto &flags = ir.meta.at(type.self).decoration.decoration_flags;
+	auto &flags = ir.meta[type.self].decoration.decoration_flags;
 
 
 	if (!type.array.empty())
 	if (!type.array.empty())
 		SPIRV_CROSS_THROW(name + " is an array of UBOs.");
 		SPIRV_CROSS_THROW(name + " is an array of UBOs.");
@@ -9498,7 +9435,7 @@ bool CompilerGLSL::check_atomic_image(uint32_t id)
 		auto *var = maybe_get_backing_variable(id);
 		auto *var = maybe_get_backing_variable(id);
 		if (var)
 		if (var)
 		{
 		{
-			auto &flags = ir.meta.at(var->self).decoration.decoration_flags;
+			auto &flags = ir.meta[var->self].decoration.decoration_flags;
 			if (flags.get(DecorationNonWritable) || flags.get(DecorationNonReadable))
 			if (flags.get(DecorationNonWritable) || flags.get(DecorationNonReadable))
 			{
 			{
 				flags.clear(DecorationNonWritable);
 				flags.clear(DecorationNonWritable);
@@ -9668,6 +9605,14 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
 	current_function = &func;
 	current_function = &func;
 	auto &entry_block = get<SPIRBlock>(func.entry_block);
 	auto &entry_block = get<SPIRBlock>(func.entry_block);
 
 
+	sort(begin(func.constant_arrays_needed_on_stack), end(func.constant_arrays_needed_on_stack));
+	for (auto &array : func.constant_arrays_needed_on_stack)
+	{
+		auto &c = get<SPIRConstant>(array);
+		auto &type = get<SPIRType>(c.constant_type);
+		statement(variable_decl(type, join("_", array, "_array_copy")), " = ", constant_expression(c), ";");
+	}
+
 	for (auto &v : func.local_variables)
 	for (auto &v : func.local_variables)
 	{
 	{
 		auto &var = get<SPIRVariable>(v);
 		auto &var = get<SPIRVariable>(v);
@@ -10607,7 +10552,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
 			{
 			{
 				// If we cannot return arrays, we will have a special out argument we can write to instead.
 				// If we cannot return arrays, we will have a special out argument we can write to instead.
 				// The backend is responsible for setting this up, and redirection the return values as appropriate.
 				// The backend is responsible for setting this up, and redirection the return values as appropriate.
-				if (ir.ids.at(block.return_value).get_type() != TypeUndef)
+				if (ir.ids[block.return_value].get_type() != TypeUndef)
 					emit_array_copy("SPIRV_Cross_return_value", block.return_value);
 					emit_array_copy("SPIRV_Cross_return_value", block.return_value);
 
 
 				if (!block_is_outside_flow_control_from_block(get<SPIRBlock>(current_function->entry_block), block) ||
 				if (!block_is_outside_flow_control_from_block(get<SPIRBlock>(current_function->entry_block), block) ||
@@ -10619,7 +10564,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
 			else
 			else
 			{
 			{
 				// OpReturnValue can return Undef, so don't emit anything for this case.
 				// OpReturnValue can return Undef, so don't emit anything for this case.
-				if (ir.ids.at(block.return_value).get_type() != TypeUndef)
+				if (ir.ids[block.return_value].get_type() != TypeUndef)
 					statement("return ", to_expression(block.return_value), ";");
 					statement("return ", to_expression(block.return_value), ";");
 			}
 			}
 		}
 		}

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

@@ -105,6 +105,7 @@ public:
 			// Inverts gl_Position.y or equivalent.
 			// Inverts gl_Position.y or equivalent.
 			bool flip_vert_y = false;
 			bool flip_vert_y = false;
 
 
+			// GLSL only, for HLSL version of this option, see CompilerHLSL.
 			// If true, the backend will assume that InstanceIndex will need to apply
 			// If true, the backend will assume that InstanceIndex will need to apply
 			// a base instance offset. Set to false if you know you will never use base instance
 			// a base instance offset. Set to false if you know you will never use base instance
 			// functionality as it might remove some internal uniforms.
 			// functionality as it might remove some internal uniforms.

+ 223 - 244
3rdparty/spirv-cross/spirv_hlsl.cpp

@@ -805,7 +805,14 @@ void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, unord
 	bool legacy = hlsl_options.shader_model <= 30;
 	bool legacy = hlsl_options.shader_model <= 30;
 	if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput)
 	if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput)
 	{
 	{
-		binding = join(legacy ? "COLOR" : "SV_Target", get_decoration(var.self, DecorationLocation));
+		// Dual-source blending is achieved in HLSL by emitting to SV_Target0 and 1.
+		uint32_t index = get_decoration(var.self, DecorationIndex);
+		uint32_t location = get_decoration(var.self, DecorationLocation);
+
+		if (index != 0 && location != 0)
+			SPIRV_CROSS_THROW("Dual-source blending is only supported on MRT #0 in HLSL.");
+
+		binding = join(legacy ? "COLOR" : "SV_Target", location + index);
 		use_location_number = false;
 		use_location_number = false;
 		if (legacy) // COLOR must be a four-component vector on legacy shader model targets (HLSL ERR_COLOR_4COMP)
 		if (legacy) // COLOR must be a four-component vector on legacy shader model targets (HLSL ERR_COLOR_4COMP)
 			type.vecsize = 4;
 			type.vecsize = 4;
@@ -902,6 +909,8 @@ void CompilerHLSL::emit_builtin_variables()
 	Bitset builtins = active_input_builtins;
 	Bitset builtins = active_input_builtins;
 	builtins.merge_or(active_output_builtins);
 	builtins.merge_or(active_output_builtins);
 
 
+	bool need_base_vertex_info = false;
+
 	// Emit global variables for the interface variables which are statically used by the shader.
 	// Emit global variables for the interface variables which are statically used by the shader.
 	builtins.for_each_bit([&](uint32_t i) {
 	builtins.for_each_bit([&](uint32_t i) {
 		const char *type = nullptr;
 		const char *type = nullptr;
@@ -921,8 +930,13 @@ void CompilerHLSL::emit_builtin_variables()
 
 
 		case BuiltInVertexId:
 		case BuiltInVertexId:
 		case BuiltInVertexIndex:
 		case BuiltInVertexIndex:
-		case BuiltInInstanceId:
 		case BuiltInInstanceIndex:
 		case BuiltInInstanceIndex:
+			type = "int";
+			if (hlsl_options.support_nonzero_base_vertex_base_instance)
+				need_base_vertex_info = true;
+			break;
+
+		case BuiltInInstanceId:
 		case BuiltInSampleId:
 		case BuiltInSampleId:
 			type = "int";
 			type = "int";
 			break;
 			break;
@@ -998,6 +1012,16 @@ void CompilerHLSL::emit_builtin_variables()
 				statement("static ", type, " ", builtin_to_glsl(builtin, storage), ";");
 				statement("static ", type, " ", builtin_to_glsl(builtin, storage), ";");
 		}
 		}
 	});
 	});
+
+	if (need_base_vertex_info)
+	{
+		statement("cbuffer SPIRV_Cross_VertexInfo");
+		begin_scope();
+		statement("int SPIRV_Cross_BaseVertex;");
+		statement("int SPIRV_Cross_BaseInstance;");
+		end_scope_decl();
+		statement("");
+	}
 }
 }
 
 
 void CompilerHLSL::emit_composite_constants()
 void CompilerHLSL::emit_composite_constants()
@@ -1006,36 +1030,33 @@ void CompilerHLSL::emit_composite_constants()
 	// global constants directly.
 	// global constants directly.
 	bool emitted = false;
 	bool emitted = false;
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeConstant)
-		{
-			auto &c = id.get<SPIRConstant>();
-			if (c.specialization)
-				continue;
+	ir.for_each_typed_id<SPIRConstant>([&](uint32_t, SPIRConstant &c) {
+		if (c.specialization)
+			return;
 
 
-			auto &type = get<SPIRType>(c.constant_type);
-			if (type.basetype == SPIRType::Struct || !type.array.empty())
-			{
-				auto name = to_name(c.self);
-				statement("static const ", variable_decl(type, name), " = ", constant_expression(c), ";");
-				emitted = true;
-			}
+		auto &type = this->get<SPIRType>(c.constant_type);
+		if (type.basetype == SPIRType::Struct || !type.array.empty())
+		{
+			auto name = to_name(c.self);
+			statement("static const ", variable_decl(type, name), " = ", constant_expression(c), ";");
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
 }
 }
 
 
-void CompilerHLSL::emit_specialization_constants()
+void CompilerHLSL::emit_specialization_constants_and_structs()
 {
 {
 	bool emitted = false;
 	bool emitted = false;
 	SpecializationConstant wg_x, wg_y, wg_z;
 	SpecializationConstant wg_x, wg_y, wg_z;
 	uint32_t workgroup_size_id = get_work_group_size_specialization_constants(wg_x, wg_y, wg_z);
 	uint32_t workgroup_size_id = get_work_group_size_specialization_constants(wg_x, wg_y, wg_z);
 
 
-	for (auto &id : ir.ids)
+	for (auto &id_ : ir.ids_for_constant_or_type)
 	{
 	{
+		auto &id = ir.ids[id_];
+
 		if (id.get_type() == TypeConstant)
 		if (id.get_type() == TypeConstant)
 		{
 		{
 			auto &c = id.get<SPIRConstant>();
 			auto &c = id.get<SPIRConstant>();
@@ -1070,6 +1091,20 @@ void CompilerHLSL::emit_specialization_constants()
 			statement("static const ", variable_decl(type, name), " = ", constant_op_expression(c), ";");
 			statement("static const ", variable_decl(type, name), " = ", constant_op_expression(c), ";");
 			emitted = true;
 			emitted = true;
 		}
 		}
+		else if (id.get_type() == TypeType)
+		{
+			auto &type = id.get<SPIRType>();
+			if (type.basetype == SPIRType::Struct && type.array.empty() && !type.pointer &&
+			    (!ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) &&
+			     !ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock)))
+			{
+				if (emitted)
+					statement("");
+				emitted = false;
+
+				emit_struct(type);
+			}
+		}
 	}
 	}
 
 
 	if (emitted)
 	if (emitted)
@@ -1083,19 +1118,14 @@ void CompilerHLSL::replace_illegal_names()
 		"line", "linear", "matrix", "point", "row_major", "sampler",
 		"line", "linear", "matrix", "point", "row_major", "sampler",
 	};
 	};
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		if (!is_hidden_variable(var))
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			if (!is_hidden_variable(var))
-			{
-				auto &m = ir.meta[var.self].decoration;
-				if (keywords.find(m.alias) != end(keywords))
-					m.alias = join("_", m.alias);
-			}
+			auto &m = ir.meta[var.self].decoration;
+			if (keywords.find(m.alias) != end(keywords))
+				m.alias = join("_", m.alias);
 		}
 		}
-	}
+	});
 
 
 	CompilerGLSL::replace_illegal_names();
 	CompilerGLSL::replace_illegal_names();
 }
 }
@@ -1106,64 +1136,37 @@ void CompilerHLSL::emit_resources()
 
 
 	replace_illegal_names();
 	replace_illegal_names();
 
 
-	emit_specialization_constants();
-
-	// Output all basic struct types which are not Block or BufferBlock as these are declared inplace
-	// when such variables are instantiated.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeType)
-		{
-			auto &type = id.get<SPIRType>();
-			if (type.basetype == SPIRType::Struct && type.array.empty() && !type.pointer &&
-			    (!ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) &&
-			     !ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock)))
-			{
-				emit_struct(type);
-			}
-		}
-	}
-
+	emit_specialization_constants_and_structs();
 	emit_composite_constants();
 	emit_composite_constants();
 
 
 	bool emitted = false;
 	bool emitted = false;
 
 
 	// Output UBOs and SSBOs
 	// Output UBOs and SSBOs
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
-			bool is_block_storage = type.storage == StorageClassStorageBuffer || type.storage == StorageClassUniform;
-			bool has_block_flags = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) ||
-			                       ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
+		bool is_block_storage = type.storage == StorageClassStorageBuffer || type.storage == StorageClassUniform;
+		bool has_block_flags = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) ||
+		                       ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
 
 
-			if (var.storage != StorageClassFunction && type.pointer && is_block_storage && !is_hidden_variable(var) &&
-			    has_block_flags)
-			{
-				emit_buffer_block(var);
-				emitted = true;
-			}
+		if (var.storage != StorageClassFunction && type.pointer && is_block_storage && !is_hidden_variable(var) &&
+		    has_block_flags)
+		{
+			emit_buffer_block(var);
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	// Output push constant blocks
 	// Output push constant blocks
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassPushConstant &&
+		    !is_hidden_variable(var))
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassPushConstant &&
-			    !is_hidden_variable(var))
-			{
-				emit_push_constant_block(var);
-				emitted = true;
-			}
+			emit_push_constant_block(var);
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	if (execution.model == ExecutionModelVertex && hlsl_options.shader_model <= 30)
 	if (execution.model == ExecutionModelVertex && hlsl_options.shader_model <= 30)
 	{
 	{
@@ -1174,33 +1177,27 @@ void CompilerHLSL::emit_resources()
 	bool skip_separate_image_sampler = !combined_image_samplers.empty() || hlsl_options.shader_model <= 30;
 	bool skip_separate_image_sampler = !combined_image_samplers.empty() || hlsl_options.shader_model <= 30;
 
 
 	// Output Uniform Constants (values, samplers, images, etc).
 	// Output Uniform Constants (values, samplers, images, etc).
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
 
 
-			// If we're remapping separate samplers and images, only emit the combined samplers.
-			if (skip_separate_image_sampler)
-			{
-				// Sampler buffers are always used without a sampler, and they will also work in regular D3D.
-				bool sampler_buffer = type.basetype == SPIRType::Image && type.image.dim == DimBuffer;
-				bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
-				bool separate_sampler = type.basetype == SPIRType::Sampler;
-				if (!sampler_buffer && (separate_image || separate_sampler))
-					continue;
-			}
+		// If we're remapping separate samplers and images, only emit the combined samplers.
+		if (skip_separate_image_sampler)
+		{
+			// Sampler buffers are always used without a sampler, and they will also work in regular D3D.
+			bool sampler_buffer = type.basetype == SPIRType::Image && type.image.dim == DimBuffer;
+			bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
+			bool separate_sampler = type.basetype == SPIRType::Sampler;
+			if (!sampler_buffer && (separate_image || separate_sampler))
+				return;
+		}
 
 
-			if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
-			    type.pointer &&
-			    (type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
-			{
-				emit_uniform(var);
-				emitted = true;
-			}
+		if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
+		    type.pointer && (type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
+		{
+			emit_uniform(var);
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
@@ -1209,27 +1206,22 @@ void CompilerHLSL::emit_resources()
 	// Emit builtin input and output variables here.
 	// Emit builtin input and output variables here.
 	emit_builtin_variables();
 	emit_builtin_variables();
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
 
 
-			// Do not emit I/O blocks here.
-			// I/O blocks can be arrayed, so we must deal with them separately to support geometry shaders
-			// and tessellation down the line.
-			if (!block && var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
-			    (var.storage == StorageClassInput || var.storage == StorageClassOutput) && !is_builtin_variable(var) &&
-			    interface_variable_exists_in_entry_point(var.self))
-			{
-				// Only emit non-builtins which are not blocks here. Builtin variables are handled separately.
-				emit_interface_block_globally(var);
-				emitted = true;
-			}
+		// Do not emit I/O blocks here.
+		// I/O blocks can be arrayed, so we must deal with them separately to support geometry shaders
+		// and tessellation down the line.
+		if (!block && var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
+		    (var.storage == StorageClassInput || var.storage == StorageClassOutput) && !is_builtin_variable(var) &&
+		    interface_variable_exists_in_entry_point(var.self))
+		{
+			// Only emit non-builtins which are not blocks here. Builtin variables are handled separately.
+			emit_interface_block_globally(var);
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
@@ -1241,47 +1233,42 @@ void CompilerHLSL::emit_resources()
 	unordered_set<uint32_t> active_outputs;
 	unordered_set<uint32_t> active_outputs;
 	vector<SPIRVariable *> input_variables;
 	vector<SPIRVariable *> input_variables;
 	vector<SPIRVariable *> output_variables;
 	vector<SPIRVariable *> output_variables;
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
+
+		if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
+			return;
+
+		// Do not emit I/O blocks here.
+		// I/O blocks can be arrayed, so we must deal with them separately to support geometry shaders
+		// and tessellation down the line.
+		if (!block && !var.remapped_variable && type.pointer && !is_builtin_variable(var) &&
+		    interface_variable_exists_in_entry_point(var.self))
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
-
-			if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
-				continue;
-
-			// Do not emit I/O blocks here.
-			// I/O blocks can be arrayed, so we must deal with them separately to support geometry shaders
-			// and tessellation down the line.
-			if (!block && !var.remapped_variable && type.pointer && !is_builtin_variable(var) &&
-			    interface_variable_exists_in_entry_point(var.self))
-			{
-				if (var.storage == StorageClassInput)
-					input_variables.push_back(&var);
-				else
-					output_variables.push_back(&var);
-			}
+			if (var.storage == StorageClassInput)
+				input_variables.push_back(&var);
+			else
+				output_variables.push_back(&var);
+		}
 
 
-			// Reserve input and output locations for block variables as necessary.
-			if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+		// Reserve input and output locations for block variables as necessary.
+		if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+		{
+			auto &active = var.storage == StorageClassInput ? active_inputs : active_outputs;
+			for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
 			{
 			{
-				auto &active = var.storage == StorageClassInput ? active_inputs : active_outputs;
-				for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
+				if (has_member_decoration(type.self, i, DecorationLocation))
 				{
 				{
-					if (has_member_decoration(type.self, i, DecorationLocation))
-					{
-						uint32_t location = get_member_decoration(type.self, i, DecorationLocation);
-						active.insert(location);
-					}
+					uint32_t location = get_member_decoration(type.self, i, DecorationLocation);
+					active.insert(location);
 				}
 				}
-
-				// Emit the block struct and a global variable here.
-				emit_io_block(var);
 			}
 			}
+
+			// Emit the block struct and a global variable here.
+			emit_io_block(var);
 		}
 		}
-	}
+	});
 
 
 	const auto variable_compare = [&](const SPIRVariable *a, const SPIRVariable *b) -> bool {
 	const auto variable_compare = [&](const SPIRVariable *a, const SPIRVariable *b) -> bool {
 		// Sort input and output variables based on, from more robust to less robust:
 		// Sort input and output variables based on, from more robust to less robust:
@@ -2169,30 +2156,25 @@ void CompilerHLSL::emit_hlsl_entry_point()
 		arguments.push_back("SPIRV_Cross_Input stage_input");
 		arguments.push_back("SPIRV_Cross_Input stage_input");
 
 
 	// Add I/O blocks as separate arguments with appropriate storage qualifier.
 	// Add I/O blocks as separate arguments with appropriate storage qualifier.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
 
 
-			if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
-				continue;
+		if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
+			return;
 
 
-			if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+		if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+		{
+			if (var.storage == StorageClassInput)
 			{
 			{
-				if (var.storage == StorageClassInput)
-				{
-					arguments.push_back(join("in ", variable_decl(type, join("stage_input", to_name(var.self)))));
-				}
-				else if (var.storage == StorageClassOutput)
-				{
-					arguments.push_back(join("out ", variable_decl(type, join("stage_output", to_name(var.self)))));
-				}
+				arguments.push_back(join("in ", variable_decl(type, join("stage_input", to_name(var.self)))));
+			}
+			else if (var.storage == StorageClassOutput)
+			{
+				arguments.push_back(join("out ", variable_decl(type, join("stage_output", to_name(var.self)))));
 			}
 			}
 		}
 		}
-	}
+	});
 
 
 	auto &execution = get_entry_point();
 	auto &execution = get_entry_point();
 
 
@@ -2243,8 +2225,20 @@ void CompilerHLSL::emit_hlsl_entry_point()
 
 
 		case BuiltInVertexId:
 		case BuiltInVertexId:
 		case BuiltInVertexIndex:
 		case BuiltInVertexIndex:
-		case BuiltInInstanceId:
 		case BuiltInInstanceIndex:
 		case BuiltInInstanceIndex:
+			// D3D semantics are uint, but shader wants int.
+			if (hlsl_options.support_nonzero_base_vertex_base_instance)
+			{
+				if (static_cast<BuiltIn>(i) == BuiltInInstanceIndex)
+					statement(builtin, " = int(stage_input.", builtin, ") + SPIRV_Cross_BaseInstance;");
+				else
+					statement(builtin, " = int(stage_input.", builtin, ") + SPIRV_Cross_BaseVertex;");
+			}
+			else
+				statement(builtin, " = int(stage_input.", builtin, ");");
+			break;
+
+		case BuiltInInstanceId:
 			// D3D semantics are uint, but shader wants int.
 			// D3D semantics are uint, but shader wants int.
 			statement(builtin, " = int(stage_input.", builtin, ");");
 			statement(builtin, " = int(stage_input.", builtin, ");");
 			break;
 			break;
@@ -2336,44 +2330,39 @@ void CompilerHLSL::emit_hlsl_entry_point()
 	});
 	});
 
 
 	// Copy from stage input struct to globals.
 	// Copy from stage input struct to globals.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
 
 
-			if (var.storage != StorageClassInput)
-				continue;
+		if (var.storage != StorageClassInput)
+			return;
 
 
-			bool need_matrix_unroll = var.storage == StorageClassInput && execution.model == ExecutionModelVertex;
+		bool need_matrix_unroll = var.storage == StorageClassInput && execution.model == ExecutionModelVertex;
 
 
-			if (!block && !var.remapped_variable && type.pointer && !is_builtin_variable(var) &&
-			    interface_variable_exists_in_entry_point(var.self))
+		if (!block && !var.remapped_variable && type.pointer && !is_builtin_variable(var) &&
+		    interface_variable_exists_in_entry_point(var.self))
+		{
+			auto name = to_name(var.self);
+			auto &mtype = this->get<SPIRType>(var.basetype);
+			if (need_matrix_unroll && mtype.columns > 1)
 			{
 			{
-				auto name = to_name(var.self);
-				auto &mtype = get<SPIRType>(var.basetype);
-				if (need_matrix_unroll && mtype.columns > 1)
-				{
-					// Unroll matrices.
-					for (uint32_t col = 0; col < mtype.columns; col++)
-						statement(name, "[", col, "] = stage_input.", name, "_", col, ";");
-				}
-				else
-				{
-					statement(name, " = stage_input.", name, ";");
-				}
+				// Unroll matrices.
+				for (uint32_t col = 0; col < mtype.columns; col++)
+					statement(name, "[", col, "] = stage_input.", name, "_", col, ";");
 			}
 			}
-
-			// I/O blocks don't use the common stage input/output struct, but separate outputs.
-			if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+			else
 			{
 			{
-				auto name = to_name(var.self);
-				statement(name, " = stage_input", name, ";");
+				statement(name, " = stage_input.", name, ";");
 			}
 			}
 		}
 		}
-	}
+
+		// I/O blocks don't use the common stage input/output struct, but separate outputs.
+		if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+		{
+			auto name = to_name(var.self);
+			statement(name, " = stage_input", name, ";");
+		}
+	});
 
 
 	// Run the shader.
 	// Run the shader.
 	if (execution.model == ExecutionModelVertex)
 	if (execution.model == ExecutionModelVertex)
@@ -2386,25 +2375,20 @@ void CompilerHLSL::emit_hlsl_entry_point()
 		SPIRV_CROSS_THROW("Unsupported shader stage.");
 		SPIRV_CROSS_THROW("Unsupported shader stage.");
 
 
 	// Copy block outputs.
 	// Copy block outputs.
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
 
 
-			if (var.storage != StorageClassOutput)
-				continue;
+		if (var.storage != StorageClassOutput)
+			return;
 
 
-			// I/O blocks don't use the common stage input/output struct, but separate outputs.
-			if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
-			{
-				auto name = to_name(var.self);
-				statement("stage_output", name, " = ", name, ";");
-			}
+		// I/O blocks don't use the common stage input/output struct, but separate outputs.
+		if (block && !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+		{
+			auto name = to_name(var.self);
+			statement("stage_output", name, " = ", name, ";");
 		}
 		}
-	}
+	});
 
 
 	// Copy stage outputs.
 	// Copy stage outputs.
 	if (require_output)
 	if (require_output)
@@ -2440,37 +2424,32 @@ void CompilerHLSL::emit_hlsl_entry_point()
 			}
 			}
 		});
 		});
 
 
-		for (auto &id : ir.ids)
-		{
-			if (id.get_type() == TypeVariable)
-			{
-				auto &var = id.get<SPIRVariable>();
-				auto &type = get<SPIRType>(var.basetype);
-				bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
+		ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+			auto &type = this->get<SPIRType>(var.basetype);
+			bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
 
 
-				if (var.storage != StorageClassOutput)
-					continue;
+			if (var.storage != StorageClassOutput)
+				return;
 
 
-				if (!block && var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
-				    !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
-				{
-					auto name = to_name(var.self);
+			if (!block && var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
+			    !is_builtin_variable(var) && interface_variable_exists_in_entry_point(var.self))
+			{
+				auto name = to_name(var.self);
 
 
-					if (legacy && execution.model == ExecutionModelFragment)
-					{
-						string output_filler;
-						for (uint32_t size = type.vecsize; size < 4; ++size)
-							output_filler += ", 0.0";
+				if (legacy && execution.model == ExecutionModelFragment)
+				{
+					string output_filler;
+					for (uint32_t size = type.vecsize; size < 4; ++size)
+						output_filler += ", 0.0";
 
 
-						statement("stage_output.", name, " = float4(", name, output_filler, ");");
-					}
-					else
-					{
-						statement("stage_output.", name, " = ", name, ";");
-					}
+					statement("stage_output.", name, " = float4(", name, output_filler, ");");
+				}
+				else
+				{
+					statement("stage_output.", name, " = ", name, ";");
 				}
 				}
 			}
 			}
-		}
+		});
 
 
 		statement("return stage_output;");
 		statement("return stage_output;");
 	}
 	}

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

@@ -54,6 +54,12 @@ public:
 
 
 		// Allows the PointCoord builtin, returns float2(0.5, 0.5), as PointCoord is not supported in HLSL.
 		// Allows the PointCoord builtin, returns float2(0.5, 0.5), as PointCoord is not supported in HLSL.
 		bool point_coord_compat = false;
 		bool point_coord_compat = false;
+
+		// If true, the backend will assume that VertexIndex and InstanceIndex will need to apply
+		// a base offset, and you will need to fill in a cbuffer with offsets.
+		// Set to false if you know you will never use base instance or base vertex
+		// functionality as it might remove an internal cbuffer.
+		bool support_nonzero_base_vertex_base_instance = false;
 	};
 	};
 
 
 	explicit CompilerHLSL(std::vector<uint32_t> spirv_)
 	explicit CompilerHLSL(std::vector<uint32_t> spirv_)
@@ -148,7 +154,7 @@ private:
 	void emit_uniform(const SPIRVariable &var) override;
 	void emit_uniform(const SPIRVariable &var) override;
 	void emit_modern_uniform(const SPIRVariable &var);
 	void emit_modern_uniform(const SPIRVariable &var);
 	void emit_legacy_uniform(const SPIRVariable &var);
 	void emit_legacy_uniform(const SPIRVariable &var);
-	void emit_specialization_constants();
+	void emit_specialization_constants_and_structs();
 	void emit_composite_constants();
 	void emit_composite_constants();
 	void emit_fixup() override;
 	void emit_fixup() override;
 	std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
 	std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;

+ 576 - 244
3rdparty/spirv-cross/spirv_msl.cpp

@@ -82,6 +82,11 @@ CompilerMSL::CompilerMSL(ParsedIR &&ir_, MSLVertexAttr *p_vtx_attrs, size_t vtx_
 			resource_bindings.push_back(&p_res_bindings[i]);
 			resource_bindings.push_back(&p_res_bindings[i]);
 }
 }
 
 
+void CompilerMSL::set_fragment_output_components(uint32_t location, uint32_t components)
+{
+	fragment_output_components[location] = components;
+}
+
 void CompilerMSL::build_implicit_builtins()
 void CompilerMSL::build_implicit_builtins()
 {
 {
 	bool need_sample_pos = active_input_builtins.get(BuiltInSamplePosition);
 	bool need_sample_pos = active_input_builtins.get(BuiltInSamplePosition);
@@ -90,19 +95,12 @@ void CompilerMSL::build_implicit_builtins()
 		bool has_frag_coord = false;
 		bool has_frag_coord = false;
 		bool has_sample_id = false;
 		bool has_sample_id = false;
 
 
-		for (auto &id : ir.ids)
-		{
-			if (id.get_type() != TypeVariable)
-				continue;
-
-			auto &var = id.get<SPIRVariable>();
-
+		ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
 			if (need_subpass_input && var.storage == StorageClassInput && ir.meta[var.self].decoration.builtin &&
 			if (need_subpass_input && var.storage == StorageClassInput && ir.meta[var.self].decoration.builtin &&
 			    ir.meta[var.self].decoration.builtin_type == BuiltInFragCoord)
 			    ir.meta[var.self].decoration.builtin_type == BuiltInFragCoord)
 			{
 			{
 				builtin_frag_coord_id = var.self;
 				builtin_frag_coord_id = var.self;
 				has_frag_coord = true;
 				has_frag_coord = true;
-				break;
 			}
 			}
 
 
 			if (need_sample_pos && var.storage == StorageClassInput && ir.meta[var.self].decoration.builtin &&
 			if (need_sample_pos && var.storage == StorageClassInput && ir.meta[var.self].decoration.builtin &&
@@ -110,9 +108,8 @@ void CompilerMSL::build_implicit_builtins()
 			{
 			{
 				builtin_sample_id_id = var.self;
 				builtin_sample_id_id = var.self;
 				has_sample_id = true;
 				has_sample_id = true;
-				break;
 			}
 			}
-		}
+		});
 
 
 		if (!has_frag_coord && need_subpass_input)
 		if (!has_frag_coord && need_subpass_input)
 		{
 		{
@@ -464,7 +461,7 @@ string CompilerMSL::compile()
 		buffer = unique_ptr<ostringstream>(new ostringstream());
 		buffer = unique_ptr<ostringstream>(new ostringstream());
 
 
 		emit_header();
 		emit_header();
-		emit_specialization_constants();
+		emit_specialization_constants_and_structs();
 		emit_resources();
 		emit_resources();
 		emit_custom_functions();
 		emit_custom_functions();
 		emit_function(get<SPIRFunction>(ir.default_entry_point), Bitset());
 		emit_function(get<SPIRFunction>(ir.default_entry_point), Bitset());
@@ -547,19 +544,14 @@ void CompilerMSL::extract_global_variables_from_functions()
 {
 {
 	// Uniforms
 	// Uniforms
 	unordered_set<uint32_t> global_var_ids;
 	unordered_set<uint32_t> global_var_ids;
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		if (var.storage == StorageClassInput || var.storage == StorageClassOutput ||
+		    var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
+		    var.storage == StorageClassPushConstant || var.storage == StorageClassStorageBuffer)
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			if (var.storage == StorageClassInput || var.storage == StorageClassOutput ||
-			    var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
-			    var.storage == StorageClassPushConstant || var.storage == StorageClassStorageBuffer)
-			{
-				global_var_ids.insert(var.self);
-			}
+			global_var_ids.insert(var.self);
 		}
 		}
-	}
+	});
 
 
 	// Local vars that are declared in the main function and accessed directly by a function
 	// Local vars that are declared in the main function and accessed directly by a function
 	auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
 	auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
@@ -739,22 +731,17 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
 // that are recursively contained within the type referenced by that variable should be packed tightly.
 // that are recursively contained within the type referenced by that variable should be packed tightly.
 void CompilerMSL::mark_packable_structs()
 void CompilerMSL::mark_packable_structs()
 {
 {
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		if (var.storage != StorageClassFunction && !is_hidden_variable(var))
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			if (var.storage != StorageClassFunction && !is_hidden_variable(var))
-			{
-				auto &type = get<SPIRType>(var.basetype);
-				if (type.pointer &&
-				    (type.storage == StorageClassUniform || type.storage == StorageClassUniformConstant ||
-				     type.storage == StorageClassPushConstant || type.storage == StorageClassStorageBuffer) &&
-				    (has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock)))
-					mark_as_packable(type);
-			}
+			auto &type = this->get<SPIRType>(var.basetype);
+			if (type.pointer &&
+			    (type.storage == StorageClassUniform || type.storage == StorageClassUniformConstant ||
+			     type.storage == StorageClassPushConstant || type.storage == StorageClassStorageBuffer) &&
+			    (has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock)))
+				mark_as_packable(type);
 		}
 		}
-	}
+	});
 }
 }
 
 
 // If the specified type is a struct, it and any nested structs
 // If the specified type is a struct, it and any nested structs
@@ -797,6 +784,27 @@ void CompilerMSL::mark_location_as_used_by_shader(uint32_t location, StorageClas
 		p_va->used_by_shader = true;
 		p_va->used_by_shader = true;
 }
 }
 
 
+uint32_t CompilerMSL::get_target_components_for_fragment_location(uint32_t location) const
+{
+	auto itr = fragment_output_components.find(location);
+	if (itr == end(fragment_output_components))
+		return 4;
+	else
+		return itr->second;
+}
+
+uint32_t CompilerMSL::build_extended_vector_type(uint32_t type_id, uint32_t components)
+{
+	uint32_t new_type_id = ir.increase_bound_by(1);
+	auto &type = set<SPIRType>(new_type_id, get<SPIRType>(type_id));
+	type.vecsize = components;
+	type.self = new_type_id;
+	type.parent_type = 0;
+	type.pointer = false;
+
+	return new_type_id;
+}
+
 void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, const string &ib_var_ref,
 void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, const string &ib_var_ref,
                                                         SPIRType &ib_type, SPIRVariable &var)
                                                         SPIRType &ib_type, SPIRVariable &var)
 {
 {
@@ -811,6 +819,26 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
 	uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
 	uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
 	uint32_t type_id = ensure_correct_builtin_type(var.basetype, builtin);
 	uint32_t type_id = ensure_correct_builtin_type(var.basetype, builtin);
 	var.basetype = type_id;
 	var.basetype = type_id;
+
+	auto &type = get<SPIRType>(type_id);
+	uint32_t target_components = 0;
+	uint32_t type_components = type.vecsize;
+	bool padded_output = false;
+
+	// Check if we need to pad fragment output to match a certain number of components.
+	if (get_decoration_bitset(var.self).get(DecorationLocation) && msl_options.pad_fragment_output_components &&
+	    get_entry_point().model == ExecutionModelFragment && storage == StorageClassOutput)
+	{
+		uint32_t locn = get_decoration(var.self, DecorationLocation);
+		target_components = get_target_components_for_fragment_location(locn);
+		if (type_components < target_components)
+		{
+			// Make a new type here.
+			type_id = build_extended_vector_type(type_id, target_components);
+			padded_output = true;
+		}
+	}
+
 	ib_type.member_types.push_back(get_pointee_type_id(type_id));
 	ib_type.member_types.push_back(get_pointee_type_id(type_id));
 
 
 	// Give the member a name
 	// Give the member a name
@@ -819,7 +847,20 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
 
 
 	// Update the original variable reference to include the structure reference
 	// Update the original variable reference to include the structure reference
 	string qual_var_name = ib_var_ref + "." + mbr_name;
 	string qual_var_name = ib_var_ref + "." + mbr_name;
-	ir.meta[var.self].decoration.qualified_alias = qual_var_name;
+
+	if (padded_output)
+	{
+		auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
+		entry_func.add_local_variable(var.self);
+		vars_needing_early_declaration.push_back(var.self);
+
+		entry_func.fixup_hooks_out.push_back([=, &var]() {
+			SPIRType &padded_type = this->get<SPIRType>(type_id);
+			statement(qual_var_name, " = ", remap_swizzle(padded_type, type_components, to_name(var.self)), ";");
+		});
+	}
+	else
+		ir.meta[var.self].decoration.qualified_alias = qual_var_name;
 
 
 	// Copy the variable location from the original variable to the member
 	// Copy the variable location from the original variable to the member
 	if (get_decoration_bitset(var.self).get(DecorationLocation))
 	if (get_decoration_bitset(var.self).get(DecorationLocation))
@@ -908,7 +949,26 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 	{
 	{
 		// Add a reference to the variable type to the interface struct.
 		// Add a reference to the variable type to the interface struct.
 		uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
 		uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
-		ib_type.member_types.push_back(usable_type->self);
+
+		uint32_t target_components = 0;
+		bool padded_output = false;
+		uint32_t type_id = usable_type->self;
+
+		// Check if we need to pad fragment output to match a certain number of components.
+		if (get_decoration_bitset(var.self).get(DecorationLocation) && msl_options.pad_fragment_output_components &&
+		    get_entry_point().model == ExecutionModelFragment && storage == StorageClassOutput)
+		{
+			uint32_t locn = get_decoration(var.self, DecorationLocation) + i;
+			target_components = get_target_components_for_fragment_location(locn);
+			if (usable_type->vecsize < target_components)
+			{
+				// Make a new type here.
+				type_id = build_extended_vector_type(usable_type->self, target_components);
+				padded_output = true;
+			}
+		}
+
+		ib_type.member_types.push_back(get_pointee_type_id(type_id));
 
 
 		// Give the member a name
 		// Give the member a name
 		string mbr_name = ensure_valid_name(join(to_expression(var.self), "_", i), "m");
 		string mbr_name = ensure_valid_name(join(to_expression(var.self), "_", i), "m");
@@ -948,12 +1008,21 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
 		{
 		{
 		case StorageClassInput:
 		case StorageClassInput:
 			entry_func.fixup_hooks_in.push_back(
 			entry_func.fixup_hooks_in.push_back(
-			    [=]() { statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, ";"); });
+			    [=, &var]() { statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, ";"); });
 			break;
 			break;
 
 
 		case StorageClassOutput:
 		case StorageClassOutput:
-			entry_func.fixup_hooks_out.push_back(
-			    [=]() { statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), "[", i, "];"); });
+			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;
 			break;
 
 
 		default:
 		default:
@@ -1071,14 +1140,14 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
 		switch (storage)
 		switch (storage)
 		{
 		{
 		case StorageClassInput:
 		case StorageClassInput:
-			entry_func.fixup_hooks_in.push_back([=]() {
+			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, ".",
 				statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref, ".",
 				          mbr_name, ";");
 				          mbr_name, ";");
 			});
 			});
 			break;
 			break;
 
 
 		case StorageClassOutput:
 		case StorageClassOutput:
-			entry_func.fixup_hooks_out.push_back([=]() {
+			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),
 				statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), ".", to_member_name(var_type, mbr_idx),
 				          "[", i, "];");
 				          "[", i, "];");
 			});
 			});
@@ -1133,13 +1202,13 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
 		switch (storage)
 		switch (storage)
 		{
 		{
 		case StorageClassInput:
 		case StorageClassInput:
-			entry_func.fixup_hooks_in.push_back([=]() {
+			entry_func.fixup_hooks_in.push_back([=, &var, &var_type]() {
 				statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), " = ", qual_var_name, ";");
 				statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), " = ", qual_var_name, ";");
 			});
 			});
 			break;
 			break;
 
 
 		case StorageClassOutput:
 		case StorageClassOutput:
-			entry_func.fixup_hooks_out.push_back([=]() {
+			entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() {
 				statement(qual_var_name, " = ", to_name(var.self), ".", to_member_name(var_type, mbr_idx), ";");
 				statement(qual_var_name, " = ", to_name(var.self), ".", to_member_name(var_type, mbr_idx), ";");
 			});
 			});
 			break;
 			break;
@@ -1273,19 +1342,15 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
 	// Accumulate the variables that should appear in the interface struct
 	// Accumulate the variables that should appear in the interface struct
 	vector<SPIRVariable *> vars;
 	vector<SPIRVariable *> vars;
 	bool incl_builtins = (storage == StorageClassOutput);
 	bool incl_builtins = (storage == StorageClassOutput);
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
+
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		if (var.storage == storage && interface_variable_exists_in_entry_point(var.self) &&
+		    !is_hidden_variable(var, incl_builtins) && type.pointer)
 		{
 		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get<SPIRType>(var.basetype);
-			if (var.storage == storage && interface_variable_exists_in_entry_point(var.self) &&
-			    !is_hidden_variable(var, incl_builtins) && type.pointer)
-			{
-				vars.push_back(&var);
-			}
+			vars.push_back(&var);
 		}
 		}
-	}
+	});
 
 
 	// If no variables qualify, leave
 	// If no variables qualify, leave
 	if (vars.empty())
 	if (vars.empty())
@@ -2044,7 +2109,7 @@ void CompilerMSL::emit_custom_functions()
 			statement("");
 			statement("");
 			statement("// Wrapper function that swizzles texture gathers.");
 			statement("// Wrapper function that swizzles texture gathers.");
 			statement("template<typename T, typename Tex, typename... Ts>");
 			statement("template<typename T, typename Tex, typename... Ts>");
-			statement("inline vec<T, 4> spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) "
+			statement("inline vec<T, 4> spvGatherSwizzle(sampler s, const thread Tex& t, Ts... params, component c, uint sw) "
 			          "METAL_CONST_ARG(c)");
 			          "METAL_CONST_ARG(c)");
 			begin_scope();
 			begin_scope();
 			statement("if (sw)");
 			statement("if (sw)");
@@ -2084,7 +2149,7 @@ void CompilerMSL::emit_custom_functions()
 			statement("");
 			statement("");
 			statement("// Wrapper function that swizzles depth texture gathers.");
 			statement("// Wrapper function that swizzles depth texture gathers.");
 			statement("template<typename T, typename Tex, typename... Ts>");
 			statement("template<typename T, typename Tex, typename... Ts>");
-			statement("inline vec<T, 4> spvGatherCompareSwizzle(sampler s, thread Tex& t, Ts... params, uint sw) ");
+			statement("inline vec<T, 4> spvGatherCompareSwizzle(sampler s, const thread Tex& t, Ts... params, uint sw) ");
 			begin_scope();
 			begin_scope();
 			statement("if (sw)");
 			statement("if (sw)");
 			begin_scope();
 			begin_scope();
@@ -2117,16 +2182,11 @@ void CompilerMSL::emit_custom_functions()
 void CompilerMSL::declare_undefined_values()
 void CompilerMSL::declare_undefined_values()
 {
 {
 	bool emitted = false;
 	bool emitted = false;
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeUndef)
-		{
-			auto &undef = id.get<SPIRUndef>();
-			auto &type = get<SPIRType>(undef.basetype);
-			statement("constant ", variable_decl(type, to_name(undef.self), undef.self), " = {};");
-			emitted = true;
-		}
-	}
+	ir.for_each_typed_id<SPIRUndef>([&](uint32_t, SPIRUndef &undef) {
+		auto &type = this->get<SPIRType>(undef.basetype);
+		statement("constant ", variable_decl(type, to_name(undef.self), undef.self), " = {};");
+		emitted = true;
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
@@ -2138,23 +2198,18 @@ void CompilerMSL::declare_constant_arrays()
 	// global constants directly, so we are able to use constants as variable expressions.
 	// global constants directly, so we are able to use constants as variable expressions.
 	bool emitted = false;
 	bool emitted = false;
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeConstant)
-		{
-			auto &c = id.get<SPIRConstant>();
-			if (c.specialization)
-				continue;
+	ir.for_each_typed_id<SPIRConstant>([&](uint32_t, SPIRConstant &c) {
+		if (c.specialization)
+			return;
 
 
-			auto &type = get<SPIRType>(c.constant_type);
-			if (!type.array.empty())
-			{
-				auto name = to_name(c.self);
-				statement("constant ", variable_decl(type, name), " = ", constant_expression(c), ";");
-				emitted = true;
-			}
+		auto &type = this->get<SPIRType>(c.constant_type);
+		if (!type.array.empty())
+		{
+			auto name = to_name(c.self);
+			statement("constant ", variable_decl(type, name), " = ", constant_expression(c), ";");
+			emitted = true;
 		}
 		}
-	}
+	});
 
 
 	if (emitted)
 	if (emitted)
 		statement("");
 		statement("");
@@ -2162,42 +2217,6 @@ void CompilerMSL::declare_constant_arrays()
 
 
 void CompilerMSL::emit_resources()
 void CompilerMSL::emit_resources()
 {
 {
-	// Output non-builtin interface structs. These include local function structs
-	// and structs nested within uniform and read-write buffers.
-	unordered_set<uint32_t> declared_structs;
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeType)
-		{
-			auto &type = id.get<SPIRType>();
-			uint32_t type_id = type.self;
-
-			bool is_struct = (type.basetype == SPIRType::Struct) && type.array.empty();
-			bool is_block =
-			    has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock);
-
-			bool is_builtin_block = is_block && is_builtin_type(type);
-			bool is_declarable_struct = is_struct && !is_builtin_block;
-
-			// We'll declare this later.
-			if (stage_out_var_id && get<SPIRVariable>(stage_out_var_id).basetype == type_id)
-				is_declarable_struct = false;
-			if (stage_in_var_id && get<SPIRVariable>(stage_in_var_id).basetype == 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)
-			{
-				declared_structs.insert(type_id);
-
-				if (has_decoration(type_id, DecorationCPacked))
-					align_struct(type);
-
-				emit_struct(type);
-			}
-		}
-	}
-
 	declare_constant_arrays();
 	declare_constant_arrays();
 	declare_undefined_values();
 	declare_undefined_values();
 
 
@@ -2207,14 +2226,18 @@ void CompilerMSL::emit_resources()
 }
 }
 
 
 // Emit declarations for the specialization Metal function constants
 // Emit declarations for the specialization Metal function constants
-void CompilerMSL::emit_specialization_constants()
+void CompilerMSL::emit_specialization_constants_and_structs()
 {
 {
 	SpecializationConstant wg_x, wg_y, wg_z;
 	SpecializationConstant wg_x, wg_y, wg_z;
 	uint32_t workgroup_size_id = get_work_group_size_specialization_constants(wg_x, wg_y, wg_z);
 	uint32_t workgroup_size_id = get_work_group_size_specialization_constants(wg_x, wg_y, wg_z);
 	bool emitted = false;
 	bool emitted = false;
 
 
-	for (auto &id : ir.ids)
+	unordered_set<uint32_t> declared_structs;
+
+	for (auto &id_ : ir.ids_for_constant_or_type)
 	{
 	{
+		auto &id = ir.ids[id_];
+
 		if (id.get_type() == TypeConstant)
 		if (id.get_type() == TypeConstant)
 		{
 		{
 			auto &c = id.get<SPIRConstant>();
 			auto &c = id.get<SPIRConstant>();
@@ -2278,6 +2301,42 @@ void CompilerMSL::emit_specialization_constants()
 			statement("constant ", variable_decl(type, name), " = ", constant_op_expression(c), ";");
 			statement("constant ", variable_decl(type, name), " = ", constant_op_expression(c), ";");
 			emitted = true;
 			emitted = true;
 		}
 		}
+		else if (id.get_type() == TypeType)
+		{
+			// Output non-builtin interface structs. These include local function structs
+			// and structs nested within uniform and read-write buffers.
+			auto &type = id.get<SPIRType>();
+			uint32_t type_id = type.self;
+
+			bool is_struct = (type.basetype == SPIRType::Struct) && type.array.empty();
+			bool is_block =
+			    has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock);
+
+			bool is_builtin_block = is_block && is_builtin_type(type);
+			bool is_declarable_struct = is_struct && !is_builtin_block;
+
+			// We'll declare this later.
+			if (stage_out_var_id && get<SPIRVariable>(stage_out_var_id).basetype == type_id)
+				is_declarable_struct = false;
+			if (stage_in_var_id && get<SPIRVariable>(stage_in_var_id).basetype == 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)
+			{
+				if (emitted)
+					statement("");
+				emitted = false;
+
+				declared_structs.insert(type_id);
+
+				if (has_decoration(type_id, DecorationCPacked))
+					align_struct(type);
+
+				// Make sure we declare the underlying struct type, and not the "decorated" type with pointers, etc.
+				emit_struct(get<SPIRType>(type_id));
+			}
+		}
 	}
 	}
 
 
 	if (emitted)
 	if (emitted)
@@ -3279,6 +3338,10 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
 		if (arg_type.basetype == SPIRType::SampledImage && arg_type.image.dim != DimBuffer)
 		if (arg_type.basetype == SPIRType::SampledImage && arg_type.image.dim != DimBuffer)
 			decl += join(", thread const ", sampler_type(arg_type), " ", to_sampler_expression(arg.id));
 			decl += join(", thread const ", sampler_type(arg_type), " ", to_sampler_expression(arg.id));
 
 
+		// Manufacture automatic swizzle arg.
+		if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(arg_type))
+			decl += join(", constant uint32_t& ", to_swizzle_expression(arg.id));
+
 		if (&arg != &func.arguments.back())
 		if (&arg != &func.arguments.back())
 			decl += ", ";
 			decl += ", ";
 	}
 	}
@@ -3654,22 +3717,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
 		// Add the swizzle constant from the swizzle buffer.
 		// Add the swizzle constant from the swizzle buffer.
 		if (!is_gather)
 		if (!is_gather)
 			farg_str += ")";
 			farg_str += ")";
-		// Get the original input variable for this image.
-		uint32_t img_var = img;
-
-		auto *combined = maybe_get<SPIRCombinedImageSampler>(img_var);
-		if (combined)
-			img_var = combined->image;
-
-		if (auto *var = maybe_get_backing_variable(img_var))
-		{
-			if (var->parameter && !var->parameter->alias_global_variable)
-				SPIRV_CROSS_THROW("Cannot yet map non-aliased parameter to Metal resource!");
-			img_var = var->self;
-		}
-		auto &aux_type = expression_type(aux_buffer_id);
-		farg_str += ", " + to_name(aux_buffer_id) + "." + to_member_name(aux_type, k_aux_mbr_idx_swizzle_const) + "[" +
-		            convert_to_string(get_metal_resource_index(get<SPIRVariable>(img_var), SPIRType::Image)) + "]";
+		farg_str += ", " + to_swizzle_expression(img);
 		used_aux_buffer = true;
 		used_aux_buffer = true;
 	}
 	}
 
 
@@ -3723,12 +3771,38 @@ void CompilerMSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_id
 // Manufacture automatic sampler arg for SampledImage texture.
 // Manufacture automatic sampler arg for SampledImage texture.
 string CompilerMSL::to_func_call_arg(uint32_t id)
 string CompilerMSL::to_func_call_arg(uint32_t id)
 {
 {
-	string arg_str = CompilerGLSL::to_func_call_arg(id);
+	string arg_str;
+
+	auto *c = maybe_get<SPIRConstant>(id);
+	if (c && !get<SPIRType>(c->constant_type).array.empty())
+	{
+		// If we are passing a constant array directly to a function for some reason,
+		// the callee will expect an argument in thread const address space
+		// (since we can only bind to arrays with references in MSL).
+		// To resolve this, we must emit a copy in this address space.
+		// This kind of code gen should be rare enough that performance is not a real concern.
+		// Inline the SPIR-V to avoid this kind of suboptimal codegen.
+		//
+		// We risk calling this inside a continue block (invalid code),
+		// so just create a thread local copy in the current function.
+		arg_str = join("_", id, "_array_copy");
+		auto &constants = current_function->constant_arrays_needed_on_stack;
+		auto itr = find(begin(constants), end(constants), id);
+		if (itr == end(constants))
+		{
+			force_recompile = true;
+			constants.push_back(id);
+		}
+	}
+	else
+		arg_str = CompilerGLSL::to_func_call_arg(id);
 
 
 	// Manufacture automatic sampler arg if the arg is a SampledImage texture.
 	// Manufacture automatic sampler arg if the arg is a SampledImage texture.
 	auto &type = expression_type(id);
 	auto &type = expression_type(id);
 	if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
 	if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
 		arg_str += ", " + to_sampler_expression(id);
 		arg_str += ", " + to_sampler_expression(id);
+	if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
+		arg_str += ", " + to_swizzle_expression(id);
 
 
 	return arg_str;
 	return arg_str;
 }
 }
@@ -3756,6 +3830,22 @@ string CompilerMSL::to_sampler_expression(uint32_t id)
 	}
 	}
 }
 }
 
 
+string CompilerMSL::to_swizzle_expression(uint32_t id)
+{
+	auto *combined = maybe_get<SPIRCombinedImageSampler>(id);
+	auto expr = to_expression(combined ? combined->image : id);
+	auto index = expr.find_first_of('[');
+
+	if (index == string::npos)
+		return expr + swizzle_name_suffix;
+	else
+	{
+		auto image_expr = expr.substr(0, index);
+		auto array_expr = expr.substr(index);
+		return image_expr + swizzle_name_suffix + array_expr;
+	}
+}
+
 // Checks whether the ID is a row_major matrix that requires conversion before use
 // 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)
 bool CompilerMSL::is_non_native_row_major_matrix(uint32_t id)
 {
 {
@@ -4099,7 +4189,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
 // index as the location.
 // index as the location.
 uint32_t CompilerMSL::get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp)
 uint32_t CompilerMSL::get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp)
 {
 {
-	auto &m = ir.meta.at(type_id);
+	auto &m = ir.meta[type_id];
 	if (index < m.members.size())
 	if (index < m.members.size())
 	{
 	{
 		auto &dec = m.members[index];
 		auto &dec = m.members[index];
@@ -4270,39 +4360,46 @@ string CompilerMSL::entry_point_args(bool append_comma)
 
 
 	vector<Resource> resources;
 	vector<Resource> resources;
 
 
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-			auto &type = get_variable_data_type(var);
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t self, SPIRVariable &var) {
+		auto &id = ir.ids[self];
+		auto &type = get_variable_data_type(var);
 
 
-			uint32_t var_id = var.self;
+		uint32_t var_id = var.self;
 
 
-			if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
-			     var.storage == StorageClassPushConstant || var.storage == StorageClassStorageBuffer) &&
-			    !is_hidden_variable(var))
+		if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
+		     var.storage == StorageClassPushConstant || var.storage == StorageClassStorageBuffer) &&
+		    !is_hidden_variable(var))
+		{
+			if (type.basetype == SPIRType::SampledImage)
 			{
 			{
-				if (type.basetype == SPIRType::SampledImage)
-				{
-					resources.push_back(
-					    { &id, to_name(var_id), SPIRType::Image, get_metal_resource_index(var, SPIRType::Image) });
+				resources.push_back(
+				    { &id, to_name(var_id), SPIRType::Image, get_metal_resource_index(var, SPIRType::Image) });
 
 
-					if (type.image.dim != DimBuffer && constexpr_samplers.count(var_id) == 0)
-					{
-						resources.push_back({ &id, to_sampler_expression(var_id), SPIRType::Sampler,
-						                      get_metal_resource_index(var, SPIRType::Sampler) });
-					}
-				}
-				else if (constexpr_samplers.count(var_id) == 0)
+				if (type.image.dim != DimBuffer && constexpr_samplers.count(var_id) == 0)
 				{
 				{
-					// constexpr samplers are not declared as resources.
-					resources.push_back(
-					    { &id, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype) });
+					resources.push_back({ &id, to_sampler_expression(var_id), SPIRType::Sampler,
+					                      get_metal_resource_index(var, SPIRType::Sampler) });
 				}
 				}
 			}
 			}
+			else if (constexpr_samplers.count(var_id) == 0)
+			{
+				// constexpr samplers are not declared as resources.
+				resources.push_back(
+				    { &id, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype) });
+			}
+
+			if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
+			{
+				auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
+				entry_func.fixup_hooks_in.push_back([this, &var, var_id]() {
+					auto &aux_type = expression_type(aux_buffer_id);
+					statement("constant uint32_t& ", to_swizzle_expression(var_id), " = ", to_name(aux_buffer_id), ".",
+					          to_member_name(aux_type, k_aux_mbr_idx_swizzle_const), "[",
+					          convert_to_string(get_metal_resource_index(var, SPIRType::Image)), "];");
+				});
+			}
 		}
 		}
-	}
+	});
 
 
 	std::sort(resources.begin(), resources.end(), [](const Resource &lhs, const Resource &rhs) {
 	std::sort(resources.begin(), resources.end(), [](const Resource &lhs, const Resource &rhs) {
 		return tie(lhs.basetype, lhs.index) < tie(rhs.basetype, rhs.index);
 		return tie(lhs.basetype, lhs.index) < tie(rhs.basetype, rhs.index);
@@ -4319,7 +4416,7 @@ string CompilerMSL::entry_point_args(bool append_comma)
 		{
 		{
 		case SPIRType::Struct:
 		case SPIRType::Struct:
 		{
 		{
-			auto &m = ir.meta.at(type.self);
+			auto &m = ir.meta[type.self];
 			if (m.members.size() == 0)
 			if (m.members.size() == 0)
 				break;
 				break;
 			if (!type.array.empty())
 			if (!type.array.empty())
@@ -4373,51 +4470,44 @@ string CompilerMSL::entry_point_args(bool append_comma)
 	}
 	}
 
 
 	// Builtin variables
 	// Builtin variables
-	for (auto &id : ir.ids)
-	{
-		if (id.get_type() == TypeVariable)
-		{
-			auto &var = id.get<SPIRVariable>();
-
-			uint32_t var_id = var.self;
-			BuiltIn bi_type = ir.meta[var_id].decoration.builtin_type;
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		uint32_t var_id = var.self;
+		BuiltIn bi_type = ir.meta[var_id].decoration.builtin_type;
 
 
-			// 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))
+		// 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))
+		{
+			if (bi_type == BuiltInSamplePosition)
 			{
 			{
-				if (bi_type == BuiltInSamplePosition)
-				{
-					auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
-					entry_func.fixup_hooks_in.push_back([=]() {
-						statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = get_sample_position(",
-						          to_expression(builtin_sample_id_id), ");");
-					});
-				}
-				else if (bi_type == BuiltInHelperInvocation)
-				{
-					if (msl_options.is_ios())
-						SPIRV_CROSS_THROW("simd_is_helper_thread() is only supported on macOS.");
-					else if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 1))
-						SPIRV_CROSS_THROW("simd_is_helper_thread() requires version 2.1 on macOS.");
-
-					auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
-					entry_func.fixup_hooks_in.push_back([=]() {
-						statement(builtin_type_decl(bi_type), " ", to_expression(var_id),
-						          " = simd_is_helper_thread();");
-					});
-				}
-				else
-				{
-					if (!ep_args.empty())
-						ep_args += ", ";
+				auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
+				entry_func.fixup_hooks_in.push_back([=]() {
+					statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = get_sample_position(",
+					          to_expression(builtin_sample_id_id), ");");
+				});
+			}
+			else if (bi_type == BuiltInHelperInvocation)
+			{
+				if (msl_options.is_ios())
+					SPIRV_CROSS_THROW("simd_is_helper_thread() is only supported on macOS.");
+				else if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 1))
+					SPIRV_CROSS_THROW("simd_is_helper_thread() requires version 2.1 on macOS.");
+
+				auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
+				entry_func.fixup_hooks_in.push_back([=]() {
+					statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = simd_is_helper_thread();");
+				});
+			}
+			else
+			{
+				if (!ep_args.empty())
+					ep_args += ", ";
 
 
-					ep_args += builtin_type_decl(bi_type) + " " + to_expression(var_id);
-					ep_args += " [[" + builtin_qualifier(bi_type) + "]]";
-				}
+				ep_args += builtin_type_decl(bi_type) + " " + to_expression(var_id);
+				ep_args += " [[" + builtin_qualifier(bi_type) + "]]";
 			}
 			}
 		}
 		}
-	}
+	});
 
 
 	// Vertex and instance index built-ins
 	// Vertex and instance index built-ins
 	if (needs_vertex_idx_arg)
 	if (needs_vertex_idx_arg)
@@ -4535,8 +4625,26 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
 	    (storage == StorageClassFunction || storage == StorageClassGeneric))
 	    (storage == StorageClassFunction || storage == StorageClassGeneric))
 	{
 	{
 		// If the argument is a pure value and not an opaque type, we will pass by value.
 		// If the argument is a pure value and not an opaque type, we will pass by value.
-		decl += " ";
-		decl += to_expression(name_id);
+		if (is_array(type))
+		{
+			// We are receiving an array by value. This is problematic.
+			// We cannot be sure of the target address space since we are supposed to receive a copy,
+			// but this is not possible with MSL without some extra work.
+			// We will have to assume we're getting a reference in thread address space.
+			// If we happen to get a reference in constant address space, the caller must emit a copy and pass that.
+			// Thread const therefore becomes the only logical choice, since we cannot "create" a constant array from
+			// non-constant arrays, but we can create thread const from constant.
+			decl = string("thread const ") + decl;
+			decl += " (&";
+			decl += to_expression(name_id);
+			decl += ")";
+			decl += type_to_array_glsl(type);
+		}
+		else
+		{
+			decl += " ";
+			decl += to_expression(name_id);
+		}
 	}
 	}
 	else if (is_array(type) && !type_is_image)
 	else if (is_array(type) && !type_is_image)
 	{
 	{
@@ -4567,9 +4675,9 @@ string CompilerMSL::to_name(uint32_t id, bool allow_alias) const
 {
 {
 	if (current_function && (current_function->self == ir.default_entry_point))
 	if (current_function && (current_function->self == ir.default_entry_point))
 	{
 	{
-		string qual_name = ir.meta.at(id).decoration.qualified_alias;
-		if (!qual_name.empty())
-			return qual_name;
+		auto *m = ir.find_meta(id);
+		if (m && !m->decoration.qualified_alias.empty())
+			return m->decoration.qualified_alias;
 	}
 	}
 	return Compiler::to_name(id, allow_alias);
 	return Compiler::to_name(id, allow_alias);
 }
 }
@@ -4602,49 +4710,273 @@ void CompilerMSL::replace_illegal_names()
 	// FIXME: MSL and GLSL are doing two different things here.
 	// FIXME: MSL and GLSL are doing two different things here.
 	// Agree on convention and remove this override.
 	// Agree on convention and remove this override.
 	static const unordered_set<string> keywords = {
 	static const unordered_set<string> keywords = {
-		"kernel", "vertex", "fragment", "compute", "bias",
+		"kernel",
+		"vertex",
+		"fragment",
+		"compute",
+		"bias",
+		"assert",
+		"VARIABLE_TRACEPOINT",
+		"STATIC_DATA_TRACEPOINT",
+		"STATIC_DATA_TRACEPOINT_V",
+		"METAL_ALIGN",
+		"METAL_ASM",
+		"METAL_CONST",
+		"METAL_DEPRECATED",
+		"METAL_ENABLE_IF",
+		"METAL_FUNC",
+		"METAL_INTERNAL",
+		"METAL_NON_NULL_RETURN",
+		"METAL_NORETURN",
+		"METAL_NOTHROW",
+		"METAL_PURE",
+		"METAL_UNAVAILABLE",
+		"METAL_IMPLICIT",
+		"METAL_EXPLICIT",
+		"METAL_CONST_ARG",
+		"METAL_ARG_UNIFORM",
+		"METAL_ZERO_ARG",
+		"METAL_VALID_LOD_ARG",
+		"METAL_VALID_LEVEL_ARG",
+		"METAL_VALID_STORE_ORDER",
+		"METAL_VALID_LOAD_ORDER",
+		"METAL_VALID_COMPARE_EXCHANGE_FAILURE_ORDER",
+		"METAL_COMPATIBLE_COMPARE_EXCHANGE_ORDERS",
+		"METAL_VALID_RENDER_TARGET",
+		"is_function_constant_defined",
+		"CHAR_BIT",
+		"SCHAR_MAX",
+		"SCHAR_MIN",
+		"UCHAR_MAX",
+		"CHAR_MAX",
+		"CHAR_MIN",
+		"USHRT_MAX",
+		"SHRT_MAX",
+		"SHRT_MIN",
+		"UINT_MAX",
+		"INT_MAX",
+		"INT_MIN",
+		"FLT_DIG",
+		"FLT_MANT_DIG",
+		"FLT_MAX_10_EXP",
+		"FLT_MAX_EXP",
+		"FLT_MIN_10_EXP",
+		"FLT_MIN_EXP",
+		"FLT_RADIX",
+		"FLT_MAX",
+		"FLT_MIN",
+		"FLT_EPSILON",
+		"FP_ILOGB0",
+		"FP_ILOGBNAN",
+		"MAXFLOAT",
+		"HUGE_VALF",
+		"INFINITY",
+		"NAN",
+		"M_E_F",
+		"M_LOG2E_F",
+		"M_LOG10E_F",
+		"M_LN2_F",
+		"M_LN10_F",
+		"M_PI_F",
+		"M_PI_2_F",
+		"M_PI_4_F",
+		"M_1_PI_F",
+		"M_2_PI_F",
+		"M_2_SQRTPI_F",
+		"M_SQRT2_F",
+		"M_SQRT1_2_F",
+		"HALF_DIG",
+		"HALF_MANT_DIG",
+		"HALF_MAX_10_EXP",
+		"HALF_MAX_EXP",
+		"HALF_MIN_10_EXP",
+		"HALF_MIN_EXP",
+		"HALF_RADIX",
+		"HALF_MAX",
+		"HALF_MIN",
+		"HALF_EPSILON",
+		"MAXHALF",
+		"HUGE_VALH",
+		"M_E_H",
+		"M_LOG2E_H",
+		"M_LOG10E_H",
+		"M_LN2_H",
+		"M_LN10_H",
+		"M_PI_H",
+		"M_PI_2_H",
+		"M_PI_4_H",
+		"M_1_PI_H",
+		"M_2_PI_H",
+		"M_2_SQRTPI_H",
+		"M_SQRT2_H",
+		"M_SQRT1_2_H",
+		"DBL_DIG",
+		"DBL_MANT_DIG",
+		"DBL_MAX_10_EXP",
+		"DBL_MAX_EXP",
+		"DBL_MIN_10_EXP",
+		"DBL_MIN_EXP",
+		"DBL_RADIX",
+		"DBL_MAX",
+		"DBL_MIN",
+		"DBL_EPSILON",
+		"HUGE_VAL",
+		"M_E",
+		"M_LOG2E",
+		"M_LOG10E",
+		"M_LN2",
+		"M_LN10",
+		"M_PI",
+		"M_PI_2",
+		"M_PI_4",
+		"M_1_PI",
+		"M_2_PI",
+		"M_2_SQRTPI",
+		"M_SQRT2",
+		"M_SQRT1_2",
 	};
 	};
 
 
 	static const unordered_set<string> illegal_func_names = {
 	static const unordered_set<string> illegal_func_names = {
 		"main",
 		"main",
 		"saturate",
 		"saturate",
+		"assert",
+		"VARIABLE_TRACEPOINT",
+		"STATIC_DATA_TRACEPOINT",
+		"STATIC_DATA_TRACEPOINT_V",
+		"METAL_ALIGN",
+		"METAL_ASM",
+		"METAL_CONST",
+		"METAL_DEPRECATED",
+		"METAL_ENABLE_IF",
+		"METAL_FUNC",
+		"METAL_INTERNAL",
+		"METAL_NON_NULL_RETURN",
+		"METAL_NORETURN",
+		"METAL_NOTHROW",
+		"METAL_PURE",
+		"METAL_UNAVAILABLE",
+		"METAL_IMPLICIT",
+		"METAL_EXPLICIT",
+		"METAL_CONST_ARG",
+		"METAL_ARG_UNIFORM",
+		"METAL_ZERO_ARG",
+		"METAL_VALID_LOD_ARG",
+		"METAL_VALID_LEVEL_ARG",
+		"METAL_VALID_STORE_ORDER",
+		"METAL_VALID_LOAD_ORDER",
+		"METAL_VALID_COMPARE_EXCHANGE_FAILURE_ORDER",
+		"METAL_COMPATIBLE_COMPARE_EXCHANGE_ORDERS",
+		"METAL_VALID_RENDER_TARGET",
+		"is_function_constant_defined",
+		"CHAR_BIT",
+		"SCHAR_MAX",
+		"SCHAR_MIN",
+		"UCHAR_MAX",
+		"CHAR_MAX",
+		"CHAR_MIN",
+		"USHRT_MAX",
+		"SHRT_MAX",
+		"SHRT_MIN",
+		"UINT_MAX",
+		"INT_MAX",
+		"INT_MIN",
+		"FLT_DIG",
+		"FLT_MANT_DIG",
+		"FLT_MAX_10_EXP",
+		"FLT_MAX_EXP",
+		"FLT_MIN_10_EXP",
+		"FLT_MIN_EXP",
+		"FLT_RADIX",
+		"FLT_MAX",
+		"FLT_MIN",
+		"FLT_EPSILON",
+		"FP_ILOGB0",
+		"FP_ILOGBNAN",
+		"MAXFLOAT",
+		"HUGE_VALF",
+		"INFINITY",
+		"NAN",
+		"M_E_F",
+		"M_LOG2E_F",
+		"M_LOG10E_F",
+		"M_LN2_F",
+		"M_LN10_F",
+		"M_PI_F",
+		"M_PI_2_F",
+		"M_PI_4_F",
+		"M_1_PI_F",
+		"M_2_PI_F",
+		"M_2_SQRTPI_F",
+		"M_SQRT2_F",
+		"M_SQRT1_2_F",
+		"HALF_DIG",
+		"HALF_MANT_DIG",
+		"HALF_MAX_10_EXP",
+		"HALF_MAX_EXP",
+		"HALF_MIN_10_EXP",
+		"HALF_MIN_EXP",
+		"HALF_RADIX",
+		"HALF_MAX",
+		"HALF_MIN",
+		"HALF_EPSILON",
+		"MAXHALF",
+		"HUGE_VALH",
+		"M_E_H",
+		"M_LOG2E_H",
+		"M_LOG10E_H",
+		"M_LN2_H",
+		"M_LN10_H",
+		"M_PI_H",
+		"M_PI_2_H",
+		"M_PI_4_H",
+		"M_1_PI_H",
+		"M_2_PI_H",
+		"M_2_SQRTPI_H",
+		"M_SQRT2_H",
+		"M_SQRT1_2_H",
+		"DBL_DIG",
+		"DBL_MANT_DIG",
+		"DBL_MAX_10_EXP",
+		"DBL_MAX_EXP",
+		"DBL_MIN_10_EXP",
+		"DBL_MIN_EXP",
+		"DBL_RADIX",
+		"DBL_MAX",
+		"DBL_MIN",
+		"DBL_EPSILON",
+		"HUGE_VAL",
+		"M_E",
+		"M_LOG2E",
+		"M_LOG10E",
+		"M_LN2",
+		"M_LN10",
+		"M_PI",
+		"M_PI_2",
+		"M_PI_4",
+		"M_1_PI",
+		"M_2_PI",
+		"M_2_SQRTPI",
+		"M_SQRT2",
+		"M_SQRT1_2",
 	};
 	};
 
 
-	for (auto &id : ir.ids)
-	{
-		switch (id.get_type())
-		{
-		case TypeVariable:
-		{
-			auto &dec = ir.meta[id.get_id()].decoration;
-			if (keywords.find(dec.alias) != end(keywords))
-				dec.alias += "0";
-
-			break;
-		}
-
-		case TypeFunction:
-		{
-			auto &dec = ir.meta[id.get_id()].decoration;
-			if (illegal_func_names.find(dec.alias) != end(illegal_func_names))
-				dec.alias += "0";
-
-			break;
-		}
-
-		case TypeType:
-		{
-			for (auto &mbr_dec : ir.meta[id.get_id()].members)
-				if (keywords.find(mbr_dec.alias) != end(keywords))
-					mbr_dec.alias += "0";
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t self, SPIRVariable &) {
+		auto &dec = ir.meta[self].decoration;
+		if (keywords.find(dec.alias) != end(keywords))
+			dec.alias += "0";
+	});
 
 
-			break;
-		}
+	ir.for_each_typed_id<SPIRFunction>([&](uint32_t self, SPIRFunction &) {
+		auto &dec = ir.meta[self].decoration;
+		if (illegal_func_names.find(dec.alias) != end(illegal_func_names))
+			dec.alias += "0";
+	});
 
 
-		default:
-			break;
-		}
-	}
+	ir.for_each_typed_id<SPIRType>([&](uint32_t self, SPIRType &) {
+		for (auto &mbr_dec : ir.meta[self].members)
+			if (keywords.find(mbr_dec.alias) != end(keywords))
+				mbr_dec.alias += "0";
+	});
 
 
 	for (auto &entry : ir.entry_points)
 	for (auto &entry : ir.entry_points)
 	{
 	{

+ 15 - 1
3rdparty/spirv-cross/spirv_msl.hpp

@@ -168,6 +168,10 @@ public:
 		bool disable_rasterization = false;
 		bool disable_rasterization = false;
 		bool swizzle_texture_samples = false;
 		bool swizzle_texture_samples = false;
 
 
+		// Fragment output in MSL must have at least as many components as the render pass.
+		// Add support to explicit pad out components.
+		bool pad_fragment_output_components = false;
+
 		bool is_ios()
 		bool is_ios()
 		{
 		{
 			return platform == iOS;
 			return platform == iOS;
@@ -312,6 +316,10 @@ public:
 	// The remapped sampler must not be an array of samplers.
 	// The remapped sampler must not be an array of samplers.
 	void remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler);
 	void remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler);
 
 
+	// If using CompilerMSL::Options::pad_fragment_output_components, override the number of components we expect
+	// to use for a particular location. The default is 4 if number of components is not overridden.
+	void set_fragment_output_components(uint32_t location, uint32_t components);
+
 protected:
 protected:
 	void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
 	void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
 	void emit_instruction(const Instruction &instr) override;
 	void emit_instruction(const Instruction &instr) override;
@@ -380,7 +388,7 @@ protected:
 
 
 	void emit_custom_functions();
 	void emit_custom_functions();
 	void emit_resources();
 	void emit_resources();
-	void emit_specialization_constants();
+	void emit_specialization_constants_and_structs();
 	void emit_interface_block(uint32_t ib_var_id);
 	void emit_interface_block(uint32_t ib_var_id);
 	bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
 	bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
 	void add_convert_row_major_matrix_function(uint32_t cols, uint32_t rows);
 	void add_convert_row_major_matrix_function(uint32_t cols, uint32_t rows);
@@ -390,6 +398,7 @@ protected:
 	std::string to_qualified_member_name(const SPIRType &type, uint32_t index);
 	std::string to_qualified_member_name(const SPIRType &type, uint32_t index);
 	std::string ensure_valid_name(std::string name, std::string pfx);
 	std::string ensure_valid_name(std::string name, std::string pfx);
 	std::string to_sampler_expression(uint32_t id);
 	std::string to_sampler_expression(uint32_t id);
+	std::string to_swizzle_expression(uint32_t id);
 	std::string builtin_qualifier(spv::BuiltIn builtin);
 	std::string builtin_qualifier(spv::BuiltIn builtin);
 	std::string builtin_type_decl(spv::BuiltIn builtin);
 	std::string builtin_type_decl(spv::BuiltIn builtin);
 	std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
 	std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
@@ -427,6 +436,7 @@ protected:
 	Options msl_options;
 	Options msl_options;
 	std::set<SPVFuncImpl> spv_function_implementations;
 	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_location;
+	std::unordered_map<uint32_t, uint32_t> fragment_output_components;
 	std::unordered_map<MSLStructMemberKey, uint32_t> struct_member_padding;
 	std::unordered_map<MSLStructMemberKey, uint32_t> struct_member_padding;
 	std::set<std::string> pragma_lines;
 	std::set<std::string> pragma_lines;
 	std::set<std::string> typedef_lines;
 	std::set<std::string> typedef_lines;
@@ -444,11 +454,15 @@ protected:
 	std::string stage_in_var_name = "in";
 	std::string stage_in_var_name = "in";
 	std::string stage_out_var_name = "out";
 	std::string stage_out_var_name = "out";
 	std::string sampler_name_suffix = "Smplr";
 	std::string sampler_name_suffix = "Smplr";
+	std::string swizzle_name_suffix = "Swzl";
 	spv::Op previous_instruction_opcode = spv::OpNop;
 	spv::Op previous_instruction_opcode = spv::OpNop;
 
 
 	std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers;
 	std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers;
 	std::vector<uint32_t> buffer_arrays;
 	std::vector<uint32_t> buffer_arrays;
 
 
+	uint32_t get_target_components_for_fragment_location(uint32_t location) const;
+	uint32_t build_extended_vector_type(uint32_t type_id, uint32_t components);
+
 	// OpcodeHandler that handles several MSL preprocessing operations.
 	// OpcodeHandler that handles several MSL preprocessing operations.
 	struct OpCodePreprocessor : OpcodeHandler
 	struct OpCodePreprocessor : OpcodeHandler
 	{
 	{

+ 4 - 1
3rdparty/spirv-cross/spirv_parser.cpp

@@ -1063,8 +1063,11 @@ bool Parser::types_are_logically_equivalent(const SPIRType &a, const SPIRType &b
 bool Parser::variable_storage_is_aliased(const SPIRVariable &v) const
 bool Parser::variable_storage_is_aliased(const SPIRVariable &v) const
 {
 {
 	auto &type = get<SPIRType>(v.basetype);
 	auto &type = get<SPIRType>(v.basetype);
+
+	auto *type_meta = ir.find_meta(type.self);
+
 	bool ssbo = v.storage == StorageClassStorageBuffer ||
 	bool ssbo = v.storage == StorageClassStorageBuffer ||
-	            ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
+	            (type_meta && type_meta->decoration.decoration_flags.get(DecorationBufferBlock));
 	bool image = type.basetype == SPIRType::Image;
 	bool image = type.basetype == SPIRType::Image;
 	bool counter = type.basetype == SPIRType::AtomicCounter;
 	bool counter = type.basetype == SPIRType::AtomicCounter;
 
 

+ 6 - 5
3rdparty/spirv-cross/spirv_parser.hpp

@@ -47,7 +47,8 @@ private:
 	template <typename T, typename... P>
 	template <typename T, typename... P>
 	T &set(uint32_t id, P &&... args)
 	T &set(uint32_t id, P &&... args)
 	{
 	{
-		auto &var = variant_set<T>(ir.ids.at(id), std::forward<P>(args)...);
+		ir.add_typed_id(static_cast<Types>(T::type), id);
+		auto &var = variant_set<T>(ir.ids[id], std::forward<P>(args)...);
 		var.self = id;
 		var.self = id;
 		return var;
 		return var;
 	}
 	}
@@ -55,13 +56,13 @@ private:
 	template <typename T>
 	template <typename T>
 	T &get(uint32_t id)
 	T &get(uint32_t id)
 	{
 	{
-		return variant_get<T>(ir.ids.at(id));
+		return variant_get<T>(ir.ids[id]);
 	}
 	}
 
 
 	template <typename T>
 	template <typename T>
 	T *maybe_get(uint32_t id)
 	T *maybe_get(uint32_t id)
 	{
 	{
-		if (ir.ids.at(id).get_type() == T::type)
+		if (ir.ids[id].get_type() == static_cast<Types>(T::type))
 			return &get<T>(id);
 			return &get<T>(id);
 		else
 		else
 			return nullptr;
 			return nullptr;
@@ -70,13 +71,13 @@ private:
 	template <typename T>
 	template <typename T>
 	const T &get(uint32_t id) const
 	const T &get(uint32_t id) const
 	{
 	{
-		return variant_get<T>(ir.ids.at(id));
+		return variant_get<T>(ir.ids[id]);
 	}
 	}
 
 
 	template <typename T>
 	template <typename T>
 	const T *maybe_get(uint32_t id) const
 	const T *maybe_get(uint32_t id) const
 	{
 	{
-		if (ir.ids.at(id).get_type() == T::type)
+		if (ir.ids[id].get_type() == T::type)
 			return &get<T>(id);
 			return &get<T>(id);
 		else
 		else
 			return nullptr;
 			return nullptr;

+ 15 - 15
3rdparty/spirv-cross/spirv_reflect.cpp

@@ -264,18 +264,11 @@ string CompilerReflection::compile()
 void CompilerReflection::emit_types()
 void CompilerReflection::emit_types()
 {
 {
 	bool emitted_open_tag = false;
 	bool emitted_open_tag = false;
-	for (auto &id : ir.ids)
-	{
-		auto idType = id.get_type();
-		if (idType == TypeType)
-		{
-			auto &type = id.get<SPIRType>();
-			if (type.basetype == SPIRType::Struct && !type.pointer && type.array.empty())
-			{
-				emit_type(type, emitted_open_tag);
-			}
-		}
-	}
+
+	ir.for_each_typed_id<SPIRType>([&](uint32_t, SPIRType &type) {
+		if (type.basetype == SPIRType::Struct && !type.pointer && type.array.empty())
+			emit_type(type, emitted_open_tag);
+	});
 
 
 	if (emitted_open_tag)
 	if (emitted_open_tag)
 	{
 	{
@@ -565,9 +558,16 @@ void CompilerReflection::emit_specialization_constants()
 
 
 string CompilerReflection::to_member_name(const SPIRType &type, uint32_t index) const
 string CompilerReflection::to_member_name(const SPIRType &type, uint32_t index) const
 {
 {
-	auto &memb = ir.meta[type.self].members;
-	if (index < memb.size() && !memb[index].alias.empty())
-		return memb[index].alias;
+	auto *type_meta = ir.find_meta(type.self);
+
+	if (type_meta)
+	{
+		auto &memb = type_meta->members;
+		if (index < memb.size() && !memb[index].alias.empty())
+			return memb[index].alias;
+		else
+			return join("_m", index);
+	}
 	else
 	else
 		return join("_m", index);
 		return join("_m", index);
 }
 }

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff