Vulkan 1.4 support (#5899)

* Add a Vulkan 1.4 environment

* Fix test: Vulkan 1.3 accepts SPIR-V 1.6

* Fix comments about Vulkan 1.4

* Add test cases for Vulkan 1.4, optimizer ir_context tests

---------

Co-authored-by: Faith Ekstrand <faith.ekstrand@collabora.com>
diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h
index 70931cb..100e61e 100644
--- a/include/spirv-tools/libspirv.h
+++ b/include/spirv-tools/libspirv.h
@@ -540,6 +540,7 @@
 //    SPV_ENV_VULKAN_1_1_SPIRV_1_4 ->  SPIR-V 1.4
 //    SPV_ENV_VULKAN_1_2           ->  SPIR-V 1.5
 //    SPV_ENV_VULKAN_1_3           ->  SPIR-V 1.6
+//    SPV_ENV_VULKAN_1_4           ->  SPIR-V 1.6
 // Consult the description of API entry points for specific rules.
 typedef enum {
   SPV_ENV_UNIVERSAL_1_0,  // SPIR-V 1.0 latest revision, no other restrictions.
@@ -577,6 +578,7 @@
 
   SPV_ENV_UNIVERSAL_1_6,  // SPIR-V 1.6 latest revision, no other restrictions.
   SPV_ENV_VULKAN_1_3,     // Vulkan 1.3 latest revision.
+  SPV_ENV_VULKAN_1_4,     // Vulkan 1.4 latest revision.
 
   SPV_ENV_MAX  // Keep this as the last enum value.
 } spv_target_env;
diff --git a/source/ext_inst.cpp b/source/ext_inst.cpp
index 9a5ba84..f2ff63f 100644
--- a/source/ext_inst.cpp
+++ b/source/ext_inst.cpp
@@ -102,6 +102,7 @@
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       *pExtInstTable = &kTable_1_0;
       return SPV_SUCCESS;
     default:
diff --git a/source/spirv_target_env.cpp b/source/spirv_target_env.cpp
index a787481..8e1b2dd 100644
--- a/source/spirv_target_env.cpp
+++ b/source/spirv_target_env.cpp
@@ -79,6 +79,8 @@
       return "SPIR-V 1.6";
     case SPV_ENV_VULKAN_1_3:
       return "SPIR-V 1.6 (under Vulkan 1.3 semantics)";
+    case SPV_ENV_VULKAN_1_4:
+      return "SPIR-V 1.6 (under Vulkan 1.4 semantics)";
     case SPV_ENV_MAX:
       assert(false && "Invalid target environment value.");
       break;
@@ -122,6 +124,7 @@
       return SPV_SPIRV_VERSION_WORD(1, 5);
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return SPV_SPIRV_VERSION_WORD(1, 6);
     case SPV_ENV_MAX:
       assert(false && "Invalid target environment value.");
@@ -147,6 +150,7 @@
         {"vulkan1.1", SPV_ENV_VULKAN_1_1},
         {"vulkan1.2", SPV_ENV_VULKAN_1_2},
         {"vulkan1.3", SPV_ENV_VULKAN_1_3},
+        {"vulkan1.4", SPV_ENV_VULKAN_1_4},
         {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
         {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
         {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
@@ -254,7 +258,8 @@
     {SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)},
     {SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)},
     {SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)},
-    {SPV_ENV_VULKAN_1_3, VULKAN_VER(1, 3), SPIRV_VER(1, 6)}};
+    {SPV_ENV_VULKAN_1_3, VULKAN_VER(1, 3), SPIRV_VER(1, 6)},
+    {SPV_ENV_VULKAN_1_4, VULKAN_VER(1, 4), SPIRV_VER(1, 6)}};
 
 bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver,
                        spv_target_env* env) {
@@ -295,6 +300,7 @@
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return true;
     case SPV_ENV_WEBGPU_0:
       assert(false && "Deprecated target environment value.");
@@ -325,6 +331,7 @@
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return false;
     case SPV_ENV_OPENCL_1_2:
     case SPV_ENV_OPENCL_EMBEDDED_1_2:
@@ -367,6 +374,7 @@
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return false;
     case SPV_ENV_OPENGL_4_0:
     case SPV_ENV_OPENGL_4_1:
@@ -406,6 +414,7 @@
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
     case SPV_ENV_OPENGL_4_0:
     case SPV_ENV_OPENGL_4_1:
     case SPV_ENV_OPENGL_4_2:
@@ -442,7 +451,8 @@
     case SPV_ENV_VULKAN_1_1:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_VULKAN_1_2:
-    case SPV_ENV_VULKAN_1_3: {
+    case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4: {
       return "Vulkan";
     }
     case SPV_ENV_UNIVERSAL_1_0:
diff --git a/source/table.cpp b/source/table.cpp
index 822cefe..01df1bc 100644
--- a/source/table.cpp
+++ b/source/table.cpp
@@ -43,6 +43,7 @@
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       break;
     default:
       return nullptr;
diff --git a/test/opt/ir_context_test.cpp b/test/opt/ir_context_test.cpp
index ce02191..d499506 100644
--- a/test/opt/ir_context_test.cpp
+++ b/test/opt/ir_context_test.cpp
@@ -1155,10 +1155,7 @@
 
 using TargetEnvCompareTest = ::testing::TestWithParam<TargetEnvCompareTestData>;
 
-TEST_P(TargetEnvCompareTest, Case) {
-  // If new environments are added, then we must update the list of tests.
-  ASSERT_EQ(SPV_ENV_VULKAN_1_3 + 1, SPV_ENV_MAX);
-
+TEST_P(TargetEnvCompareTest, IsTargetEnvAtLeast) {
   const auto& tc = GetParam();
 
   std::unique_ptr<Module> module(new Module());
@@ -1422,6 +1419,8 @@
             1);
 }
 
+// If new environments are added, then we must update the list of tests.
+static_assert(SPV_ENV_VULKAN_1_4 + 1 == SPV_ENV_MAX);
 INSTANTIATE_TEST_SUITE_P(
     TestCase, TargetEnvCompareTest,
     ::testing::Values(
@@ -1464,6 +1463,7 @@
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_1},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_2},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_3},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_0},
         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_1},
         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_1},
         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_1},
@@ -1473,6 +1473,7 @@
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_3},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_4},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_5},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_1},
         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_2},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_0},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_1},
@@ -1480,7 +1481,16 @@
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_3},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_4},
         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_5},
-        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_6}));
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_6},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_VULKAN_1_2},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_0},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_1},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_2},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_3},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_4},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_5},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_6},
+        TargetEnvCompareTestData{SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_3}));
 
 }  // namespace
 }  // namespace opt
diff --git a/test/val/val_version_test.cpp b/test/val/val_version_test.cpp
index 6b7c4fe..743567c 100644
--- a/test/val/val_version_test.cpp
+++ b/test/val/val_version_test.cpp
@@ -79,6 +79,7 @@
       return "1.5";
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return "1.6";
     default:
       return "0";
@@ -117,6 +118,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_1_SPIRV_1_4,vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_0,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_1,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_2,    vulkan_spirv, true),
@@ -135,6 +137,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -153,6 +156,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -171,6 +175,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -189,6 +194,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_4, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -207,6 +213,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_5, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -225,6 +232,7 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_2,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_6, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -248,6 +256,7 @@
     std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_1,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_2,    vulkan_spirv, true),
@@ -266,6 +275,7 @@
     std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -284,6 +294,7 @@
     std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -302,6 +313,7 @@
     std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_2, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
@@ -320,11 +332,33 @@
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_VULKAN_1_2,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
-    std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false)
+    std::make_tuple(SPV_ENV_VULKAN_1_3, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false),
+
+    // Assembling for Vulkan 1.4 produces SPIR-V 1.6
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_4, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_5, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_UNIVERSAL_1_6, vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_0,    vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_1,    vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_1_SPIRV_1_4, vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_2,    vulkan_spirv, false),
+    // Vulkan 1.3 accepts SPIR-V 1.6
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_3,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_VULKAN_1_4,    vulkan_spirv, true),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
+    std::make_tuple(SPV_ENV_VULKAN_1_4, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false)
   )
 );