Fixes #1433. Validate binary version

* Validates SPIR-V binary version against target environment
diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h
index de5f16c..d6cb60c 100644
--- a/include/spirv-tools/libspirv.h
+++ b/include/spirv-tools/libspirv.h
@@ -411,7 +411,7 @@
   SPV_ENV_OPENCL_EMBEDDED_2_1,  // OpenCL Embedded Profile 2.1 latest revision.
   SPV_ENV_OPENCL_EMBEDDED_2_2,  // OpenCL Embedded Profile 2.2 latest revision.
   SPV_ENV_UNIVERSAL_1_3,  // SPIR-V 1.3 latest revision, no other restrictions.
-  SPV_ENV_VULKAN_1_1,     // Vulkan 1.0 latest revision.
+  SPV_ENV_VULKAN_1_1,     // Vulkan 1.1 latest revision.
 } spv_target_env;
 
 // SPIR-V Validator can be parameterized with the following Universal Limits.
diff --git a/source/opcode.cpp b/source/opcode.cpp
index c8b0055..c73f14d 100644
--- a/source/opcode.cpp
+++ b/source/opcode.cpp
@@ -25,6 +25,7 @@
 #include "spirv-tools/libspirv.h"
 #include "spirv_constant.h"
 #include "spirv_endian.h"
+#include "spirv_target_env.h"
 
 namespace {
 struct OpcodeDescPtrLen {
diff --git a/source/operand.cpp b/source/operand.cpp
index 38db2a5..4a2a2d6 100644
--- a/source/operand.cpp
+++ b/source/operand.cpp
@@ -20,6 +20,7 @@
 
 #include "macro.h"
 #include "spirv_constant.h"
+#include "spirv_target_env.h"
 
 // For now, assume unified1 contains up to SPIR-V 1.3 and no later
 // SPIR-V version.
diff --git a/source/spirv_constant.h b/source/spirv_constant.h
index 92ccd15..8eb6572 100644
--- a/source/spirv_constant.h
+++ b/source/spirv_constant.h
@@ -29,9 +29,6 @@
 // Returns the minor version extracted from a version header word.
 #define SPV_SPIRV_VERSION_MINOR_PART(WORD) ((uint32_t(WORD) >> 8) & 0xff)
 
-// Returns the version number for the given SPIR-V target environment.
-uint32_t spvVersionForTargetEnv(spv_target_env env);
-
 // Header indices
 
 #define SPV_INDEX_MAGIC_NUMBER 0u
diff --git a/source/spirv_target_env.cpp b/source/spirv_target_env.cpp
index efeff5a..cc99228 100644
--- a/source/spirv_target_env.cpp
+++ b/source/spirv_target_env.cpp
@@ -43,15 +43,15 @@
     case SPV_ENV_OPENCL_EMBEDDED_2_2:
       return "SPIR-V 1.2 (under OpenCL 2.2 Embedded Profile semantics)";
     case SPV_ENV_OPENGL_4_0:
-      return "SPIR-V 1.0 (under OpenCL 4.0 semantics)";
+      return "SPIR-V 1.0 (under OpenGL 4.0 semantics)";
     case SPV_ENV_OPENGL_4_1:
-      return "SPIR-V 1.0 (under OpenCL 4.1 semantics)";
+      return "SPIR-V 1.0 (under OpenGL 4.1 semantics)";
     case SPV_ENV_OPENGL_4_2:
-      return "SPIR-V 1.0 (under OpenCL 4.2 semantics)";
+      return "SPIR-V 1.0 (under OpenGL 4.2 semantics)";
     case SPV_ENV_OPENGL_4_3:
-      return "SPIR-V 1.0 (under OpenCL 4.3 semantics)";
+      return "SPIR-V 1.0 (under OpenGL 4.3 semantics)";
     case SPV_ENV_OPENGL_4_5:
-      return "SPIR-V 1.0 (under OpenCL 4.5 semantics)";
+      return "SPIR-V 1.0 (under OpenGL 4.5 semantics)";
     case SPV_ENV_UNIVERSAL_1_2:
       return "SPIR-V 1.2";
     case SPV_ENV_UNIVERSAL_1_3:
diff --git a/source/spirv_target_env.h b/source/spirv_target_env.h
index 8ce1a04..315dbbe 100644
--- a/source/spirv_target_env.h
+++ b/source/spirv_target_env.h
@@ -24,4 +24,7 @@
 // Returns true if |env| is a VULKAN environment, false otherwise.
 bool spvIsVulkanEnv(spv_target_env env);
 
+// Returns the version number for the given SPIR-V target environment.
+uint32_t spvVersionForTargetEnv(spv_target_env env);
+
 #endif  // LIBSPIRV_SPIRV_TARGET_ENV_H_
diff --git a/source/text.cpp b/source/text.cpp
index bf18bcc..ac4f8a1 100644
--- a/source/text.cpp
+++ b/source/text.cpp
@@ -36,6 +36,7 @@
 #include "operand.h"
 #include "spirv-tools/libspirv.h"
 #include "spirv_constant.h"
+#include "spirv_target_env.h"
 #include "table.h"
 #include "text_handler.h"
 #include "util/bitutils.h"
diff --git a/source/validate.cpp b/source/validate.cpp
index aa8335c..2c3386c 100644
--- a/source/validate.cpp
+++ b/source/validate.cpp
@@ -35,6 +35,7 @@
 #include "spirv-tools/libspirv.h"
 #include "spirv_constant.h"
 #include "spirv_endian.h"
+#include "spirv_target_env.h"
 #include "spirv_validator_options.h"
 #include "val/construct.h"
 #include "val/function.h"
@@ -255,6 +256,16 @@
            << "Invalid SPIR-V header.";
   }
 
+  if (header.version > spvVersionForTargetEnv(context.target_env)) {
+    return libspirv::DiagnosticStream(position, context.consumer,
+                                      SPV_ERROR_WRONG_VERSION)
+           << "Invalid SPIR-V binary version "
+           << SPV_SPIRV_VERSION_MAJOR_PART(header.version) << "."
+           << SPV_SPIRV_VERSION_MINOR_PART(header.version)
+           << " for target environment "
+           << spvTargetEnvDescription(context.target_env) << ".";
+  }
+
   // Look for OpExtension instructions and register extensions.
   // Diagnostics if any will be produced in the next pass (ProcessInstruction).
   spvBinaryParse(&context, vstate, words, num_words,
diff --git a/test/val/CMakeLists.txt b/test/val/CMakeLists.txt
index 7e47bb6..093a04a 100644
--- a/test/val/CMakeLists.txt
+++ b/test/val/CMakeLists.txt
@@ -180,3 +180,9 @@
        ${VAL_TEST_COMMON_SRCS}
   LIBS ${SPIRV_TOOLS}
 )
+
+add_spvtools_unittest(TARGET val_version
+        SRCS val_version_test.cpp
+       ${VAL_TEST_COMMON_SRCS}
+  LIBS ${SPIRV_TOOLS}
+)
diff --git a/test/val/val_layout_test.cpp b/test/val/val_layout_test.cpp
index 06ecdc7..b91454c 100644
--- a/test/val/val_layout_test.cpp
+++ b/test/val/val_layout_test.cpp
@@ -504,11 +504,12 @@
 )";
 
   CompileSuccessfully(str, SPV_ENV_UNIVERSAL_1_1);
-  ASSERT_EQ(SPV_ERROR_INVALID_BINARY,
+  ASSERT_EQ(SPV_ERROR_WRONG_VERSION,
             ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
-  // In a 1.0 environment the binary parse fails before we even get to
-  // validation.  This occurs no matter where the OpModuleProcessed is placed.
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Invalid opcode: 330"));
+  // In a 1.0 environment the version check fails.
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Invalid SPIR-V binary version 1.1 for target "
+                        "environment SPIR-V 1.0."));
 }
 
 TEST_F(ValidateLayout, ModuleProcessedValidIn11) {
diff --git a/test/val/val_version_test.cpp b/test/val/val_version_test.cpp
new file mode 100644
index 0000000..c9fbba7
--- /dev/null
+++ b/test/val/val_version_test.cpp
@@ -0,0 +1,207 @@
+// Copyright (c) 2018 Google LLC.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gmock/gmock.h"
+#include "val_fixtures.h"
+
+using namespace spvtest;
+using ::testing::HasSubstr;
+using std::make_tuple;
+
+using ValidateVersion =
+    ValidateBase<std::tuple<spv_target_env, spv_target_env, std::string, bool>>;
+
+const std::string vulkan_spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+%void = OpTypeVoid
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+const std::string opencl_spirv = R"(
+OpCapability Kernel
+OpCapability Linkage
+OpMemoryModel Logical OpenCL
+)";
+
+std::string version(spv_target_env env) {
+  switch (env) {
+    case SPV_ENV_UNIVERSAL_1_0:
+    case SPV_ENV_VULKAN_1_0:
+    case SPV_ENV_OPENGL_4_0:
+    case SPV_ENV_OPENGL_4_1:
+    case SPV_ENV_OPENGL_4_2:
+    case SPV_ENV_OPENGL_4_3:
+    case SPV_ENV_OPENGL_4_5:
+    case SPV_ENV_OPENCL_2_0:
+    case SPV_ENV_OPENCL_EMBEDDED_2_0:
+      return "1.0";
+    case SPV_ENV_UNIVERSAL_1_1:
+    case SPV_ENV_OPENCL_2_1:
+    case SPV_ENV_OPENCL_EMBEDDED_2_1:
+      return "1.1";
+    case SPV_ENV_UNIVERSAL_1_2:
+    case SPV_ENV_OPENCL_2_2:
+    case SPV_ENV_OPENCL_EMBEDDED_2_2:
+      return "1.2";
+    case SPV_ENV_UNIVERSAL_1_3:
+    case SPV_ENV_VULKAN_1_1:
+      return "1.3";
+    default:
+      return "0";
+  }
+}
+
+TEST_P(ValidateVersion, version) {
+  CompileSuccessfully(std::get<2>(GetParam()), std::get<0>(GetParam()));
+  spv_result_t res = ValidateInstructions(std::get<1>(GetParam()));
+  if (std::get<3>(GetParam())) {
+    ASSERT_EQ(SPV_SUCCESS, res);
+  } else {
+    ASSERT_EQ(SPV_ERROR_WRONG_VERSION, res);
+
+    std::string msg = "Invalid SPIR-V binary version ";
+    msg += version(std::get<0>(GetParam()));
+    msg += " for target environment ";
+    msg += spvTargetEnvDescription(std::get<1>(GetParam()));
+    EXPECT_THAT(getDiagnosticString(), HasSubstr(msg));
+  }
+}
+
+// clang-format off
+INSTANTIATE_TEST_CASE_P(Universal, ValidateVersion,
+  ::testing::Values(
+    //         Binary version,        Target environment
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_0,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_VULKAN_1_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_0,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_2,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_3,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_5,    vulkan_spirv, true),
+
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false),
+
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false),
+
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false)
+  )
+);
+
+INSTANTIATE_TEST_CASE_P(Vulkan, ValidateVersion,
+  ::testing::Values(
+    //         Binary version,        Target environment
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_0,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_2,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_3,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_5,    vulkan_spirv, true),
+
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_2, vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_3, vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1,    vulkan_spirv, true),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_0,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_1,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
+    make_tuple(SPV_ENV_VULKAN_1_1, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false)
+  )
+);
+
+INSTANTIATE_TEST_CASE_P(OpenCL, ValidateVersion,
+  ::testing::Values(
+    //         Binary version,     Target environment
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_0,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_1,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_2,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_UNIVERSAL_1_3,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_2_0,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_2_1,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_2_2,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true),
+
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_0,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_1,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_2,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_UNIVERSAL_1_3,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_2_0,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_2_1,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_2_2,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true),
+
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_0,       opencl_spirv, false),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_1,       opencl_spirv, false),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_2,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_UNIVERSAL_1_3,       opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_2_0,          opencl_spirv, false),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_2_1,          opencl_spirv, false),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_2_2,          opencl_spirv, true),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_0, opencl_spirv, false),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_1, opencl_spirv, false),
+    make_tuple(SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2, opencl_spirv, true)
+  )
+);
+// clang-format on