Merge changes I6c21b03d,Ic6136d02,I988c0288,I21d11818,I79fa8162, ...

* changes:
  Update src/Pipeline/SpirvShaderInstructions.inl
  Update SPIR-V Tools to f37547c73
  Squashed 'third_party/SPIRV-Tools/' changes from b0e22d28f5e..f37547c73a9
  Update SPIR-V Headers to 8bb2420b4
  Squashed 'third_party/SPIRV-Headers/' changes from 104ecc356c1..8bb2420b44a
  Mend git merge history for SPIRV-Headers and SPIRV-Tools
  Mend git merge history for SPIRV-Headers and SPIRV-Tools
  Revert 9dff6a3bb5 to mend git merge history for SPIRV-Headers and SPIRV-Tools
  Squashed 'third_party/SPIRV-Tools/' changes from a61d07a7276..b0e22d28f5e
  Squashed 'third_party/SPIRV-Headers/' changes from 7845730cab6..104ecc356c1
diff --git a/src/Pipeline/SpirvShaderInstructions.inl b/src/Pipeline/SpirvShaderInstructions.inl
index f652466..8848b77 100644
--- a/src/Pipeline/SpirvShaderInstructions.inl
+++ b/src/Pipeline/SpirvShaderInstructions.inl
@@ -375,7 +375,6 @@
 DECORATE_OP(T, OpSubgroupAnyKHR)
 DECORATE_OP(T, OpSubgroupAllEqualKHR)
 DECORATE_OP(T, OpSubgroupReadInvocationKHR)
-DECORATE_OP(T, OpTypeRayQueryKHR)
 DECORATE_OP(T, OpRayQueryInitializeKHR)
 DECORATE_OP(T, OpRayQueryTerminateKHR)
 DECORATE_OP(T, OpRayQueryGenerateIntersectionKHR)
@@ -435,7 +434,6 @@
 DECORATE_OP(T, OpUSubSatINTEL)
 DECORATE_OP(T, OpIMul32x16INTEL)
 DECORATE_OP(T, OpUMul32x16INTEL)
-DECORATE_OP(T, OpFunctionPointerINTEL)
 DECORATE_OP(T, OpFunctionPointerCallINTEL)
 DECORATE_OP(F, OpDecorateString)
 DECORATE_OP(F, OpMemberDecorateString)
@@ -584,3 +582,17 @@
 DECORATE_OP(T, OpConvertUToAccelerationStructureKHR)
 DECORATE_OP(T, OpIgnoreIntersectionKHR)
 DECORATE_OP(T, OpTerminateRayKHR)
+DECORATE_OP(T, OpTypeRayQueryKHR)
+DECORATE_OP(T, OpConstFunctionPointerINTEL)
+DECORATE_OP(T, OpAsmTargetINTEL)
+DECORATE_OP(T, OpAsmINTEL)
+DECORATE_OP(T, OpAsmCallINTEL)
+DECORATE_OP(T, OpVariableLengthArrayINTEL)
+DECORATE_OP(T, OpSaveMemoryINTEL)
+DECORATE_OP(T, OpRestoreMemoryINTEL)
+DECORATE_OP(T, OpPtrCastToCrossWorkgroupINTEL)
+DECORATE_OP(T, OpCrossWorkgroupCastToPtrINTEL)
+DECORATE_OP(T, OpTypeBufferSurfaceINTEL)
+DECORATE_OP(T, OpTypeStructContinuedINTEL)
+DECORATE_OP(T, OpConstantCompositeContinuedINTEL)
+DECORATE_OP(T, OpSpecConstantCompositeContinuedINTEL)
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json
index c91540d..265c155 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json
@@ -5123,7 +5123,7 @@
       "version" : "None"
     },
     {
-      "opname" : "OpFunctionPointerINTEL",
+      "opname" : "OpConstFunctionPointerINTEL",
       "class"  : "@exclude",
       "opcode" : 5600,
       "operands" : [
@@ -5149,6 +5149,46 @@
       "version" : "None"
     },
     {
+      "opname" : "OpAsmTargetINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5609,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "LiteralString", "name" : "'Asm target'" }
+      ],
+      "capabilities" : [ "AsmINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpAsmINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5610,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Asm type'" },
+        { "kind" : "IdRef", "name" : "'Target'" },
+        { "kind" : "LiteralString", "name" : "'Asm instructions'" },
+        { "kind" : "LiteralString", "name" : "'Constraints'" }
+      ],
+      "capabilities" : [ "AsmINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpAsmCallINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5611,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Asm'" },
+        { "kind" : "IdRef", "quantifier" : "*", "name" : "'Argument 0'" }
+      ],
+      "capabilities" : [ "AsmINTEL" ],
+      "version" : "None"
+    },
+    {
       "opname" : "OpDecorateString",
       "class"  : "Annotation",
       "opcode" : 5632,
@@ -6712,6 +6752,39 @@
       "version" : "None"
     },
     {
+      "opname" : "OpVariableLengthArrayINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5818,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Lenght'" }
+      ],
+      "capabilities" : [ "VariableLengthArrayINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpSaveMemoryINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5819,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "VariableLengthArrayINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpRestoreMemoryINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5820,
+      "operands" : [
+        { "kind" : "IdRef", "name" : "'Ptr'" }
+      ],
+      "capabilities" : [ "VariableLengthArrayINTEL" ],
+      "version" : "None"
+    },
+    {
       "opname" : "OpLoopControlINTEL",
       "class"  : "Reserved",
       "opcode" : 5887,
@@ -6723,6 +6796,30 @@
       "version" : "None"
     },
     {
+      "opname" : "OpPtrCastToCrossWorkgroupINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5934,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "USMStorageClassesINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpCrossWorkgroupCastToPtrINTEL",
+      "class"  : "@exclude",
+      "opcode" : 5938,
+      "operands" : [
+        { "kind" : "IdResultType" },
+        { "kind" : "IdResult" },
+        { "kind" : "IdRef", "name" : "'Pointer'" }
+      ],
+      "capabilities" : [ "USMStorageClassesINTEL" ],
+      "version" : "None"
+    },
+    {
       "opname" : "OpReadPipeBlockingINTEL",
       "class"  : "Pipe",
       "opcode" : 5946,
@@ -7099,6 +7196,46 @@
       "capabilities" : [ "AtomicFloat32AddEXT", "AtomicFloat64AddEXT" ],
       "extensions" : [ "SPV_EXT_shader_atomic_float_add" ],
       "version" : "None"
+    },
+    {
+      "opname" : "OpTypeBufferSurfaceINTEL",
+      "class"  : "Type-Declaration",
+      "opcode" : 6086,
+      "operands" : [
+        { "kind" : "IdResult" }
+      ],
+      "capabilities" : [ "VectorComputeINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpTypeStructContinuedINTEL",
+      "class"  : "Type-Declaration",
+      "opcode" : 6090,
+      "operands" : [
+        { "kind" : "IdRef",    "quantifier" : "*", "name" : "'Member 0 type', +\n'member 1 type', +\n..." }
+      ],
+      "capabilities" : [ "LongConstantCompositeINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpConstantCompositeContinuedINTEL",
+      "class"  : "Constant-Creation",
+      "opcode" : 6091,
+      "operands" : [
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ],
+      "capabilities" : [ "LongConstantCompositeINTEL" ],
+      "version" : "None"
+    },
+    {
+      "opname" : "OpSpecConstantCompositeContinuedINTEL",
+      "class"  : "Constant-Creation",
+      "opcode" : 6092,
+      "operands" : [
+        { "kind" : "IdRef",        "quantifier" : "*", "name" : "'Constituents'" }
+      ],
+      "capabilities" : [ "LongConstantCompositeINTEL" ],
+      "version" : "None"
     }
   ],
   "operand_kinds" : [
@@ -7279,6 +7416,18 @@
           "enumerant" : "Fast",
           "value" : "0x0010",
           "capabilities" : [ "Kernel" ]
+        },
+        {
+          "enumerant" : "AllowContractFastINTEL",
+          "value" : "0x10000",
+          "capabilities" : [ "FPFastMathModeINTEL" ],
+	  "version" : "None"
+        },
+        {
+          "enumerant" : "AllowReassocINTEL",
+          "value" : "0x20000",
+          "capabilities" : [ "FPFastMathModeINTEL" ],
+	  "version" : "None"
         }
       ]
     },
@@ -7438,6 +7587,16 @@
           "capabilities" : [ "FPGALoopControlsINTEL" ],
           "extensions" : [ "SPV_INTEL_fpga_loop_controls" ],
           "version" : "None"
+        },
+        {
+          "enumerant" : "NoFusionINTEL",
+          "value" : "0x800000",
+          "parameters" : [
+            { "kind" : "LiteralInteger" }
+          ],
+          "capabilities" : [ "FPGALoopControlsINTEL" ],
+          "extensions" : [ "SPV_INTEL_fpga_loop_controls" ],
+          "version" : "None"
         }
       ]
     },
@@ -8365,6 +8524,51 @@
           "version" : "None"
         },
         {
+          "enumerant" : "SharedLocalMemorySizeINTEL",
+          "value" : 5618,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Size'" }
+          ],
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "RoundingModeRTPINTEL",
+          "value" : 5620,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" }
+          ],
+          "capabilities" : [ "RoundToInfinityINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "RoundingModeRTNINTEL",
+          "value" : 5621,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" }
+          ],
+          "capabilities" : [ "RoundToInfinityINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FloatingPointModeALTINTEL",
+          "value" : 5622,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" }
+          ],
+          "capabilities" : [ "RoundToInfinityINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FloatingPointModeIEEEINTEL",
+          "value" : 5623,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" }
+          ],
+          "capabilities" : [ "RoundToInfinityINTEL" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "MaxWorkgroupSizeINTEL",
           "value" : 5893,
           "parameters" : [
@@ -8402,6 +8606,15 @@
           "capabilities" : [ "FPGAKernelAttributesINTEL" ],
           "extensions" : [ "SPV_INTEL_kernel_attributes" ],
           "version" : "None"
+        },
+        {
+          "enumerant" : "SchedulerTargetFmaxMhzINTEL",
+          "value" : 5903,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'target_fmax'" }
+          ],
+          "capabilities" : [ "FPGAKernelAttributesINTEL" ],
+          "version" : "None"
         }
       ]
     },
@@ -8577,6 +8790,24 @@
           "extensions" : [ "SPV_INTEL_function_pointers" ],
           "capabilities" : [ "FunctionPointersINTEL" ],
           "version" : "None"
+        },
+        {
+          "enumerant" : "DeviceOnlyINTEL",
+          "value" : 5936,
+          "extensions" : [
+            "SPV_INTEL_usm_storage_classes"
+          ],
+          "capabilities" : [ "USMStorageClassesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "HostOnlyINTEL",
+          "value" : 5937,
+          "extensions" : [
+            "SPV_INTEL_usm_storage_classes"
+          ],
+          "capabilities" : [ "USMStorageClassesINTEL" ],
+          "version" : "None"
         }
       ]
     },
@@ -9103,6 +9334,42 @@
     },
     {
       "category" : "ValueEnum",
+      "kind" : "FPDenormMode",
+      "enumerants" : [
+        {
+          "enumerant" : "Preserve",
+          "value" : 0,
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FlushToZero",
+          "value" : 1,
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
+      "kind" : "FPOperationMode",
+      "enumerants" : [
+        {
+          "enumerant" : "IEEE",
+          "value" : 0,
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "ALT",
+          "value" : 1,
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        }
+      ]
+    },
+    {
+      "category" : "ValueEnum",
       "kind" : "LinkageType",
       "enumerants" : [
         {
@@ -9608,6 +9875,15 @@
           "version" : "1.5"
         },
         {
+          "enumerant" : "SIMTCallINTEL",
+          "value" : 5599,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'N'" }
+          ],
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "ReferencedIndirectlyINTEL",
           "value" : 5602,
           "capabilities" : [ "IndirectReferencesINTEL" ],
@@ -9615,6 +9891,57 @@
           "version" : "None"
         },
         {
+          "enumerant" : "ClobberINTEL",
+          "value" : 5607,
+          "parameters" : [
+            { "kind" : "LiteralString", "name" : "'Register'" }
+          ],
+          "capabilities" : [ "AsmINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "SideEffectsINTEL",
+          "value" : 5608,
+          "capabilities" : [ "AsmINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "VectorComputeVariableINTEL",
+          "value" : 5624,
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FuncParamIOKindINTEL",
+          "value" : 5625,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Kind'" }
+          ],
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "VectorComputeFunctionINTEL",
+          "value" : 5626,
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "StackCallINTEL",
+          "value" : 5627,
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "GlobalVariableOffsetINTEL",
+          "value" : 5628,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Offset'" }
+          ],
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "CounterBuffer",
           "value" : 5634,
           "parameters" : [
@@ -9658,6 +9985,26 @@
           "version" : "None"
         },
         {
+          "enumerant" : "FunctionRoundingModeINTEL",
+          "value" : 5822,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" },
+            { "kind" : "FPRoundingMode", "name" : "'FP Rounding Mode'" }
+          ],
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FunctionDenormModeINTEL",
+          "value" : 5823,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" },
+            { "kind" : "FPDenormMode", "name" : "'FP Denorm Mode'" }
+          ],
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "RegisterINTEL",
           "value" : 5825,
           "capabilities" : [ "FPGAMemoryAttributesINTEL" ],
@@ -9765,6 +10112,88 @@
           "capabilities" : [ "FPGAMemoryAttributesINTEL" ],
           "extensions" : [ "SPV_INTEL_fpga_memory_attributes" ],
           "version" : "None"
+        },
+        {
+          "enumerant" : "BurstCoalesceINTEL",
+          "value" : 5899,
+          "capabilities" : [ "FPGAMemoryAccessesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "CacheSizeINTEL",
+          "value" : 5900,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Cache Size in bytes'" }
+          ],
+          "capabilities" : [ "FPGAMemoryAccessesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "DontStaticallyCoalesceINTEL",
+          "value" : 5901,
+          "capabilities" : [ "FPGAMemoryAccessesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "PrefetchINTEL",
+          "value" : 5902,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Prefetcher Size in bytes'" }
+          ],
+          "capabilities" : [ "FPGAMemoryAccessesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "StallEnableINTEL",
+          "value" : 5905,
+          "capabilities" : [ "FPGAClusterAttributesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FuseLoopsInFunctionINTEL",
+          "value" : 5907,
+          "capabilities" : [ "LoopFuseINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "BufferLocationINTEL",
+          "value" : 5921,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Buffer Location ID'" }
+          ],
+          "capabilities" : [ "FPGABufferLocationINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "IOPipeStorageINTEL",
+          "value" : 5944,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'IO Pipe ID'" }
+          ],
+          "capabilities" : [ "IOPipesINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FunctionFloatingPointModeINTEL",
+          "value" : 6080,
+          "parameters" : [
+            { "kind" : "LiteralInteger", "name" : "'Target Width'" },
+            { "kind" : "FPOperationMode", "name" : "'FP Operation Mode'" }
+          ],
+          "capabilities" : [ "FunctionFloatControlINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "SingleElementVectorINTEL",
+          "value" : 6085,
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "VectorComputeCallableFunctionINTEL",
+          "value" : 6087,
+          "capabilities" : [ "VectorComputeINTEL" ],
+          "version" : "None"
         }
       ]
     },
@@ -10431,15 +10860,8 @@
         {
           "enumerant" : "HitTNV",
           "value" : 5332,
-          "capabilities" : [ "RayTracingNV" , "RayTracingKHR" ],
-          "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ],
-          "version" : "None"
-        },
-        {
-          "enumerant" : "HitTKHR",
-          "value" : 5332,
-          "capabilities" : [ "RayTracingNV" , "RayTracingKHR" ],
-          "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ],
+          "capabilities" : [ "RayTracingNV" ],
+          "extensions" : [ "SPV_NV_ray_tracing" ],
           "version" : "None"
         },
         {
@@ -11583,6 +12005,18 @@
           "version" : "None"
         },
         {
+          "enumerant" : "RoundToInfinityINTEL",
+          "value" : 5582,
+          "extensions" : [ "SPV_INTEL_float_controls2" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FloatingPointModeINTEL",
+          "value" : 5583,
+          "extensions" : [ "SPV_INTEL_float_controls2" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "IntegerFunctions2INTEL",
           "value" : 5584,
           "capabilities" : [ "Shader" ],
@@ -11602,6 +12036,25 @@
           "version" : "None"
         },
         {
+          "enumerant" : "AsmINTEL",
+          "value" : 5606,
+          "extensions" : [ "SPV_INTEL_inline_assembly" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "VectorComputeINTEL",
+          "value" : 5617,
+          "capabilities" : [ "VectorAnyINTEL" ],
+          "extensions" : [ "SPV_INTEL_vector_compute" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "VectorAnyINTEL",
+          "value" : 5619,
+          "extensions" : [ "SPV_INTEL_vector_compute" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "SubgroupAvcMotionEstimationINTEL",
           "value" : 5696,
           "extensions" : [ "SPV_INTEL_device_side_avc_motion_estimation" ],
@@ -11620,12 +12073,37 @@
           "version" : "None"
         },
         {
+          "enumerant" : "VariableLengthArrayINTEL",
+          "value" : 5817,
+          "extensions" : [ "SPV_INTEL_variable_length_array" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FunctionFloatControlINTEL",
+          "value" : 5821,
+          "extensions" : [ "SPV_INTEL_float_controls2" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "FPGAMemoryAttributesINTEL",
           "value" : 5824,
           "extensions" : [ "SPV_INTEL_fpga_memory_attributes" ],
           "version" : "None"
         },
         {
+          "enumerant" : "FPFastMathModeINTEL",
+          "value" : 5837,
+          "capabilities" : [ "Kernel" ],
+          "extensions" : [ "SPV_INTEL_fp_fast_math_mode" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "ArbitraryPrecisionIntegersINTEL",
+          "value" : 5844,
+          "extensions" : [ "SPV_INTEL_arbitrary_precision_integers" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "UnstructuredLoopControlsINTEL",
           "value" : 5886,
           "extensions" : [ "SPV_INTEL_unstructured_loop_controls" ],
@@ -11650,6 +12128,42 @@
           "version" : "None"
         },
         {
+          "enumerant" : "FPGAMemoryAccessesINTEL",
+          "value" : 5898,
+          "extensions" : [ "SPV_INTEL_fpga_memory_accesses" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FPGAClusterAttributesINTEL",
+          "value" : 5904,
+          "extensions" : [ "SPV_INTEL_fpga_cluster_attributes" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "LoopFuseINTEL",
+          "value" : 5906,
+          "extensions" : [ "SPV_INTEL_loop_fuse" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "FPGABufferLocationINTEL",
+          "value" : 5920,
+          "extensions" : [ "SPV_INTEL_fpga_buffer_location" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "USMStorageClassesINTEL",
+          "value" : 5935,
+          "extensions" : [ "SPV_INTEL_usm_storage_classes" ],
+          "version" : "None"
+        },
+        {
+          "enumerant" : "IOPipesINTEL",
+          "value" : 5943,
+          "extensions" : [ "SPV_INTEL_io_pipes" ],
+          "version" : "None"
+        },
+        {
           "enumerant" : "BlockingPipesINTEL",
           "value" : 5945,
           "extensions" : [ "SPV_INTEL_blocking_pipes" ],
@@ -11674,6 +12188,12 @@
           "capabilities" : [ "Shader" ],
           "extensions" : [ "SPV_EXT_shader_atomic_float_add" ],
           "version" : "None"
+        },
+        {
+          "enumerant" : "LongConstantCompositeINTEL",
+          "value" : 6089,
+          "extensions" : [ "SPV_INTEL_long_constant_composite" ],
+          "version" : "None"
         }
       ]
     },
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.cs b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.cs
index e0ed1e8..03b8803 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.cs
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.cs
@@ -164,10 +164,16 @@
             SampleInterlockUnorderedEXT = 5369,
             ShadingRateInterlockOrderedEXT = 5370,
             ShadingRateInterlockUnorderedEXT = 5371,
+            SharedLocalMemorySizeINTEL = 5618,
+            RoundingModeRTPINTEL = 5620,
+            RoundingModeRTNINTEL = 5621,
+            FloatingPointModeALTINTEL = 5622,
+            FloatingPointModeIEEEINTEL = 5623,
             MaxWorkgroupSizeINTEL = 5893,
             MaxWorkDimINTEL = 5894,
             NoGlobalOffsetINTEL = 5895,
             NumSIMDWorkitemsINTEL = 5896,
+            SchedulerTargetFmaxMhzINTEL = 5903,
         }
 
         public enum StorageClass
@@ -200,6 +206,8 @@
             PhysicalStorageBuffer = 5349,
             PhysicalStorageBufferEXT = 5349,
             CodeSectionINTEL = 5605,
+            DeviceOnlyINTEL = 5936,
+            HostOnlyINTEL = 5937,
         }
 
         public enum Dim
@@ -371,6 +379,8 @@
             NSZ = 2,
             AllowRecip = 3,
             Fast = 4,
+            AllowContractFastINTEL = 16,
+            AllowReassocINTEL = 17,
         }
 
         public enum FPFastMathModeMask
@@ -381,6 +391,8 @@
             NSZ = 0x00000004,
             AllowRecip = 0x00000008,
             Fast = 0x00000010,
+            AllowContractFastINTEL = 0x00010000,
+            AllowReassocINTEL = 0x00020000,
         }
 
         public enum FPRoundingMode
@@ -391,6 +403,18 @@
             RTN = 3,
         }
 
+        public enum FPDenormMode
+        {
+            Preserve = 0,
+            FlushToZero = 1,
+        }
+
+        public enum FPOperationMode
+        {
+            IEEE = 0,
+            ALT = 1,
+        }
+
         public enum LinkageType
         {
             Export = 0,
@@ -482,12 +506,22 @@
             RestrictPointerEXT = 5355,
             AliasedPointer = 5356,
             AliasedPointerEXT = 5356,
+            SIMTCallINTEL = 5599,
             ReferencedIndirectlyINTEL = 5602,
+            ClobberINTEL = 5607,
+            SideEffectsINTEL = 5608,
+            VectorComputeVariableINTEL = 5624,
+            FuncParamIOKindINTEL = 5625,
+            VectorComputeFunctionINTEL = 5626,
+            StackCallINTEL = 5627,
+            GlobalVariableOffsetINTEL = 5628,
             CounterBuffer = 5634,
             HlslCounterBufferGOOGLE = 5634,
             HlslSemanticGOOGLE = 5635,
             UserSemantic = 5635,
             UserTypeGOOGLE = 5636,
+            FunctionRoundingModeINTEL = 5822,
+            FunctionDenormModeINTEL = 5823,
             RegisterINTEL = 5825,
             MemoryINTEL = 5826,
             NumbanksINTEL = 5827,
@@ -500,6 +534,17 @@
             MergeINTEL = 5834,
             BankBitsINTEL = 5835,
             ForcePow2DepthINTEL = 5836,
+            BurstCoalesceINTEL = 5899,
+            CacheSizeINTEL = 5900,
+            DontStaticallyCoalesceINTEL = 5901,
+            PrefetchINTEL = 5902,
+            StallEnableINTEL = 5905,
+            FuseLoopsInFunctionINTEL = 5907,
+            BufferLocationINTEL = 5921,
+            IOPipeStorageINTEL = 5944,
+            FunctionFloatingPointModeINTEL = 6080,
+            SingleElementVectorINTEL = 6085,
+            VectorComputeCallableFunctionINTEL = 6087,
         }
 
         public enum BuiltIn
@@ -612,7 +657,6 @@
             ObjectToWorldNV = 5330,
             WorldToObjectKHR = 5331,
             WorldToObjectNV = 5331,
-            HitTKHR = 5332,
             HitTNV = 5332,
             HitKindKHR = 5333,
             HitKindNV = 5333,
@@ -656,6 +700,7 @@
             LoopCoalesceINTEL = 20,
             MaxInterleavingINTEL = 21,
             SpeculatedIterationsINTEL = 22,
+            NoFusionINTEL = 23,
         }
 
         public enum LoopControlMask
@@ -677,6 +722,7 @@
             LoopCoalesceINTEL = 0x00100000,
             MaxInterleavingINTEL = 0x00200000,
             SpeculatedIterationsINTEL = 0x00400000,
+            NoFusionINTEL = 0x00800000,
         }
 
         public enum FunctionControlShift
@@ -971,21 +1017,37 @@
             SubgroupBufferBlockIOINTEL = 5569,
             SubgroupImageBlockIOINTEL = 5570,
             SubgroupImageMediaBlockIOINTEL = 5579,
+            RoundToInfinityINTEL = 5582,
+            FloatingPointModeINTEL = 5583,
             IntegerFunctions2INTEL = 5584,
             FunctionPointersINTEL = 5603,
             IndirectReferencesINTEL = 5604,
+            AsmINTEL = 5606,
+            VectorComputeINTEL = 5617,
+            VectorAnyINTEL = 5619,
             SubgroupAvcMotionEstimationINTEL = 5696,
             SubgroupAvcMotionEstimationIntraINTEL = 5697,
             SubgroupAvcMotionEstimationChromaINTEL = 5698,
+            VariableLengthArrayINTEL = 5817,
+            FunctionFloatControlINTEL = 5821,
             FPGAMemoryAttributesINTEL = 5824,
+            FPFastMathModeINTEL = 5837,
+            ArbitraryPrecisionIntegersINTEL = 5844,
             UnstructuredLoopControlsINTEL = 5886,
             FPGALoopControlsINTEL = 5888,
             KernelAttributesINTEL = 5892,
             FPGAKernelAttributesINTEL = 5897,
+            FPGAMemoryAccessesINTEL = 5898,
+            FPGAClusterAttributesINTEL = 5904,
+            LoopFuseINTEL = 5906,
+            FPGABufferLocationINTEL = 5920,
+            USMStorageClassesINTEL = 5935,
+            IOPipesINTEL = 5943,
             BlockingPipesINTEL = 5945,
             FPGARegINTEL = 5948,
             AtomicFloat32AddEXT = 6033,
             AtomicFloat64AddEXT = 6034,
+            LongConstantCompositeINTEL = 6089,
         }
 
         public enum RayFlagsShift
@@ -1473,8 +1535,11 @@
             OpUSubSatINTEL = 5596,
             OpIMul32x16INTEL = 5597,
             OpUMul32x16INTEL = 5598,
-            OpFunctionPointerINTEL = 5600,
+            OpConstFunctionPointerINTEL = 5600,
             OpFunctionPointerCallINTEL = 5601,
+            OpAsmTargetINTEL = 5609,
+            OpAsmINTEL = 5610,
+            OpAsmCallINTEL = 5611,
             OpDecorateString = 5632,
             OpDecorateStringGOOGLE = 5632,
             OpMemberDecorateString = 5633,
@@ -1597,7 +1662,12 @@
             OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
             OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
             OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+            OpVariableLengthArrayINTEL = 5818,
+            OpSaveMemoryINTEL = 5819,
+            OpRestoreMemoryINTEL = 5820,
             OpLoopControlINTEL = 5887,
+            OpPtrCastToCrossWorkgroupINTEL = 5934,
+            OpCrossWorkgroupCastToPtrINTEL = 5938,
             OpReadPipeBlockingINTEL = 5946,
             OpWritePipeBlockingINTEL = 5947,
             OpFPGARegINTEL = 5949,
@@ -1619,6 +1689,10 @@
             OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
             OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
             OpAtomicFAddEXT = 6035,
+            OpTypeBufferSurfaceINTEL = 6086,
+            OpTypeStructContinuedINTEL = 6090,
+            OpConstantCompositeContinuedINTEL = 6091,
+            OpSpecConstantCompositeContinuedINTEL = 6092,
         }
     }
 }
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.h b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.h
index fae2a10..e9273d0 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.h
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.h
@@ -172,10 +172,16 @@
     SpvExecutionModeSampleInterlockUnorderedEXT = 5369,
     SpvExecutionModeShadingRateInterlockOrderedEXT = 5370,
     SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371,
+    SpvExecutionModeSharedLocalMemorySizeINTEL = 5618,
+    SpvExecutionModeRoundingModeRTPINTEL = 5620,
+    SpvExecutionModeRoundingModeRTNINTEL = 5621,
+    SpvExecutionModeFloatingPointModeALTINTEL = 5622,
+    SpvExecutionModeFloatingPointModeIEEEINTEL = 5623,
     SpvExecutionModeMaxWorkgroupSizeINTEL = 5893,
     SpvExecutionModeMaxWorkDimINTEL = 5894,
     SpvExecutionModeNoGlobalOffsetINTEL = 5895,
     SpvExecutionModeNumSIMDWorkitemsINTEL = 5896,
+    SpvExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
     SpvExecutionModeMax = 0x7fffffff,
 } SpvExecutionMode;
 
@@ -208,6 +214,8 @@
     SpvStorageClassPhysicalStorageBuffer = 5349,
     SpvStorageClassPhysicalStorageBufferEXT = 5349,
     SpvStorageClassCodeSectionINTEL = 5605,
+    SpvStorageClassDeviceOnlyINTEL = 5936,
+    SpvStorageClassHostOnlyINTEL = 5937,
     SpvStorageClassMax = 0x7fffffff,
 } SpvStorageClass;
 
@@ -378,6 +386,8 @@
     SpvFPFastMathModeNSZShift = 2,
     SpvFPFastMathModeAllowRecipShift = 3,
     SpvFPFastMathModeFastShift = 4,
+    SpvFPFastMathModeAllowContractFastINTELShift = 16,
+    SpvFPFastMathModeAllowReassocINTELShift = 17,
     SpvFPFastMathModeMax = 0x7fffffff,
 } SpvFPFastMathModeShift;
 
@@ -388,6 +398,8 @@
     SpvFPFastMathModeNSZMask = 0x00000004,
     SpvFPFastMathModeAllowRecipMask = 0x00000008,
     SpvFPFastMathModeFastMask = 0x00000010,
+    SpvFPFastMathModeAllowContractFastINTELMask = 0x00010000,
+    SpvFPFastMathModeAllowReassocINTELMask = 0x00020000,
 } SpvFPFastMathModeMask;
 
 typedef enum SpvFPRoundingMode_ {
@@ -398,6 +410,18 @@
     SpvFPRoundingModeMax = 0x7fffffff,
 } SpvFPRoundingMode;
 
+typedef enum SpvFPDenormMode_ {
+    SpvFPDenormModePreserve = 0,
+    SpvFPDenormModeFlushToZero = 1,
+    SpvFPDenormModeMax = 0x7fffffff,
+} SpvFPDenormMode;
+
+typedef enum SpvFPOperationMode_ {
+    SpvFPOperationModeIEEE = 0,
+    SpvFPOperationModeALT = 1,
+    SpvFPOperationModeMax = 0x7fffffff,
+} SpvFPOperationMode;
+
 typedef enum SpvLinkageType_ {
     SpvLinkageTypeExport = 0,
     SpvLinkageTypeImport = 1,
@@ -488,12 +512,22 @@
     SpvDecorationRestrictPointerEXT = 5355,
     SpvDecorationAliasedPointer = 5356,
     SpvDecorationAliasedPointerEXT = 5356,
+    SpvDecorationSIMTCallINTEL = 5599,
     SpvDecorationReferencedIndirectlyINTEL = 5602,
+    SpvDecorationClobberINTEL = 5607,
+    SpvDecorationSideEffectsINTEL = 5608,
+    SpvDecorationVectorComputeVariableINTEL = 5624,
+    SpvDecorationFuncParamIOKindINTEL = 5625,
+    SpvDecorationVectorComputeFunctionINTEL = 5626,
+    SpvDecorationStackCallINTEL = 5627,
+    SpvDecorationGlobalVariableOffsetINTEL = 5628,
     SpvDecorationCounterBuffer = 5634,
     SpvDecorationHlslCounterBufferGOOGLE = 5634,
     SpvDecorationHlslSemanticGOOGLE = 5635,
     SpvDecorationUserSemantic = 5635,
     SpvDecorationUserTypeGOOGLE = 5636,
+    SpvDecorationFunctionRoundingModeINTEL = 5822,
+    SpvDecorationFunctionDenormModeINTEL = 5823,
     SpvDecorationRegisterINTEL = 5825,
     SpvDecorationMemoryINTEL = 5826,
     SpvDecorationNumbanksINTEL = 5827,
@@ -506,6 +540,17 @@
     SpvDecorationMergeINTEL = 5834,
     SpvDecorationBankBitsINTEL = 5835,
     SpvDecorationForcePow2DepthINTEL = 5836,
+    SpvDecorationBurstCoalesceINTEL = 5899,
+    SpvDecorationCacheSizeINTEL = 5900,
+    SpvDecorationDontStaticallyCoalesceINTEL = 5901,
+    SpvDecorationPrefetchINTEL = 5902,
+    SpvDecorationStallEnableINTEL = 5905,
+    SpvDecorationFuseLoopsInFunctionINTEL = 5907,
+    SpvDecorationBufferLocationINTEL = 5921,
+    SpvDecorationIOPipeStorageINTEL = 5944,
+    SpvDecorationFunctionFloatingPointModeINTEL = 6080,
+    SpvDecorationSingleElementVectorINTEL = 6085,
+    SpvDecorationVectorComputeCallableFunctionINTEL = 6087,
     SpvDecorationMax = 0x7fffffff,
 } SpvDecoration;
 
@@ -618,7 +663,6 @@
     SpvBuiltInObjectToWorldNV = 5330,
     SpvBuiltInWorldToObjectKHR = 5331,
     SpvBuiltInWorldToObjectNV = 5331,
-    SpvBuiltInHitTKHR = 5332,
     SpvBuiltInHitTNV = 5332,
     SpvBuiltInHitKindKHR = 5333,
     SpvBuiltInHitKindNV = 5333,
@@ -661,6 +705,7 @@
     SpvLoopControlLoopCoalesceINTELShift = 20,
     SpvLoopControlMaxInterleavingINTELShift = 21,
     SpvLoopControlSpeculatedIterationsINTELShift = 22,
+    SpvLoopControlNoFusionINTELShift = 23,
     SpvLoopControlMax = 0x7fffffff,
 } SpvLoopControlShift;
 
@@ -682,6 +727,7 @@
     SpvLoopControlLoopCoalesceINTELMask = 0x00100000,
     SpvLoopControlMaxInterleavingINTELMask = 0x00200000,
     SpvLoopControlSpeculatedIterationsINTELMask = 0x00400000,
+    SpvLoopControlNoFusionINTELMask = 0x00800000,
 } SpvLoopControlMask;
 
 typedef enum SpvFunctionControlShift_ {
@@ -971,21 +1017,37 @@
     SpvCapabilitySubgroupBufferBlockIOINTEL = 5569,
     SpvCapabilitySubgroupImageBlockIOINTEL = 5570,
     SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579,
+    SpvCapabilityRoundToInfinityINTEL = 5582,
+    SpvCapabilityFloatingPointModeINTEL = 5583,
     SpvCapabilityIntegerFunctions2INTEL = 5584,
     SpvCapabilityFunctionPointersINTEL = 5603,
     SpvCapabilityIndirectReferencesINTEL = 5604,
+    SpvCapabilityAsmINTEL = 5606,
+    SpvCapabilityVectorComputeINTEL = 5617,
+    SpvCapabilityVectorAnyINTEL = 5619,
     SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
+    SpvCapabilityVariableLengthArrayINTEL = 5817,
+    SpvCapabilityFunctionFloatControlINTEL = 5821,
     SpvCapabilityFPGAMemoryAttributesINTEL = 5824,
+    SpvCapabilityFPFastMathModeINTEL = 5837,
+    SpvCapabilityArbitraryPrecisionIntegersINTEL = 5844,
     SpvCapabilityUnstructuredLoopControlsINTEL = 5886,
     SpvCapabilityFPGALoopControlsINTEL = 5888,
     SpvCapabilityKernelAttributesINTEL = 5892,
     SpvCapabilityFPGAKernelAttributesINTEL = 5897,
+    SpvCapabilityFPGAMemoryAccessesINTEL = 5898,
+    SpvCapabilityFPGAClusterAttributesINTEL = 5904,
+    SpvCapabilityLoopFuseINTEL = 5906,
+    SpvCapabilityFPGABufferLocationINTEL = 5920,
+    SpvCapabilityUSMStorageClassesINTEL = 5935,
+    SpvCapabilityIOPipesINTEL = 5943,
     SpvCapabilityBlockingPipesINTEL = 5945,
     SpvCapabilityFPGARegINTEL = 5948,
     SpvCapabilityAtomicFloat32AddEXT = 6033,
     SpvCapabilityAtomicFloat64AddEXT = 6034,
+    SpvCapabilityLongConstantCompositeINTEL = 6089,
     SpvCapabilityMax = 0x7fffffff,
 } SpvCapability;
 
@@ -1471,8 +1533,11 @@
     SpvOpUSubSatINTEL = 5596,
     SpvOpIMul32x16INTEL = 5597,
     SpvOpUMul32x16INTEL = 5598,
-    SpvOpFunctionPointerINTEL = 5600,
+    SpvOpConstFunctionPointerINTEL = 5600,
     SpvOpFunctionPointerCallINTEL = 5601,
+    SpvOpAsmTargetINTEL = 5609,
+    SpvOpAsmINTEL = 5610,
+    SpvOpAsmCallINTEL = 5611,
     SpvOpDecorateString = 5632,
     SpvOpDecorateStringGOOGLE = 5632,
     SpvOpMemberDecorateString = 5633,
@@ -1595,7 +1660,12 @@
     SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    SpvOpVariableLengthArrayINTEL = 5818,
+    SpvOpSaveMemoryINTEL = 5819,
+    SpvOpRestoreMemoryINTEL = 5820,
     SpvOpLoopControlINTEL = 5887,
+    SpvOpPtrCastToCrossWorkgroupINTEL = 5934,
+    SpvOpCrossWorkgroupCastToPtrINTEL = 5938,
     SpvOpReadPipeBlockingINTEL = 5946,
     SpvOpWritePipeBlockingINTEL = 5947,
     SpvOpFPGARegINTEL = 5949,
@@ -1617,6 +1687,10 @@
     SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031,
     SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     SpvOpAtomicFAddEXT = 6035,
+    SpvOpTypeBufferSurfaceINTEL = 6086,
+    SpvOpTypeStructContinuedINTEL = 6090,
+    SpvOpConstantCompositeContinuedINTEL = 6091,
+    SpvOpSpecConstantCompositeContinuedINTEL = 6092,
     SpvOpMax = 0x7fffffff,
 } SpvOp;
 
@@ -2041,8 +2115,11 @@
     case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
-    case SpvOpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpAsmINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpDecorateString: *hasResult = false; *hasResultType = false; break;
     case SpvOpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
     case SpvOpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2163,7 +2240,12 @@
     case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
     case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+    case SpvOpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
+    case SpvOpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case SpvOpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2185,6 +2267,10 @@
     case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
     case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
     case SpvOpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
+    case SpvOpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;
+    case SpvOpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case SpvOpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case SpvOpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
     }
 }
 #endif /* SPV_ENABLE_UTILITY_CODE */
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp
index a5383de..0e7dff8 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp
@@ -168,10 +168,16 @@
     ExecutionModeSampleInterlockUnorderedEXT = 5369,
     ExecutionModeShadingRateInterlockOrderedEXT = 5370,
     ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
+    ExecutionModeSharedLocalMemorySizeINTEL = 5618,
+    ExecutionModeRoundingModeRTPINTEL = 5620,
+    ExecutionModeRoundingModeRTNINTEL = 5621,
+    ExecutionModeFloatingPointModeALTINTEL = 5622,
+    ExecutionModeFloatingPointModeIEEEINTEL = 5623,
     ExecutionModeMaxWorkgroupSizeINTEL = 5893,
     ExecutionModeMaxWorkDimINTEL = 5894,
     ExecutionModeNoGlobalOffsetINTEL = 5895,
     ExecutionModeNumSIMDWorkitemsINTEL = 5896,
+    ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
     ExecutionModeMax = 0x7fffffff,
 };
 
@@ -204,6 +210,8 @@
     StorageClassPhysicalStorageBuffer = 5349,
     StorageClassPhysicalStorageBufferEXT = 5349,
     StorageClassCodeSectionINTEL = 5605,
+    StorageClassDeviceOnlyINTEL = 5936,
+    StorageClassHostOnlyINTEL = 5937,
     StorageClassMax = 0x7fffffff,
 };
 
@@ -374,6 +382,8 @@
     FPFastMathModeNSZShift = 2,
     FPFastMathModeAllowRecipShift = 3,
     FPFastMathModeFastShift = 4,
+    FPFastMathModeAllowContractFastINTELShift = 16,
+    FPFastMathModeAllowReassocINTELShift = 17,
     FPFastMathModeMax = 0x7fffffff,
 };
 
@@ -384,6 +394,8 @@
     FPFastMathModeNSZMask = 0x00000004,
     FPFastMathModeAllowRecipMask = 0x00000008,
     FPFastMathModeFastMask = 0x00000010,
+    FPFastMathModeAllowContractFastINTELMask = 0x00010000,
+    FPFastMathModeAllowReassocINTELMask = 0x00020000,
 };
 
 enum FPRoundingMode {
@@ -394,6 +406,18 @@
     FPRoundingModeMax = 0x7fffffff,
 };
 
+enum FPDenormMode {
+    FPDenormModePreserve = 0,
+    FPDenormModeFlushToZero = 1,
+    FPDenormModeMax = 0x7fffffff,
+};
+
+enum FPOperationMode {
+    FPOperationModeIEEE = 0,
+    FPOperationModeALT = 1,
+    FPOperationModeMax = 0x7fffffff,
+};
+
 enum LinkageType {
     LinkageTypeExport = 0,
     LinkageTypeImport = 1,
@@ -484,12 +508,22 @@
     DecorationRestrictPointerEXT = 5355,
     DecorationAliasedPointer = 5356,
     DecorationAliasedPointerEXT = 5356,
+    DecorationSIMTCallINTEL = 5599,
     DecorationReferencedIndirectlyINTEL = 5602,
+    DecorationClobberINTEL = 5607,
+    DecorationSideEffectsINTEL = 5608,
+    DecorationVectorComputeVariableINTEL = 5624,
+    DecorationFuncParamIOKindINTEL = 5625,
+    DecorationVectorComputeFunctionINTEL = 5626,
+    DecorationStackCallINTEL = 5627,
+    DecorationGlobalVariableOffsetINTEL = 5628,
     DecorationCounterBuffer = 5634,
     DecorationHlslCounterBufferGOOGLE = 5634,
     DecorationHlslSemanticGOOGLE = 5635,
     DecorationUserSemantic = 5635,
     DecorationUserTypeGOOGLE = 5636,
+    DecorationFunctionRoundingModeINTEL = 5822,
+    DecorationFunctionDenormModeINTEL = 5823,
     DecorationRegisterINTEL = 5825,
     DecorationMemoryINTEL = 5826,
     DecorationNumbanksINTEL = 5827,
@@ -502,6 +536,17 @@
     DecorationMergeINTEL = 5834,
     DecorationBankBitsINTEL = 5835,
     DecorationForcePow2DepthINTEL = 5836,
+    DecorationBurstCoalesceINTEL = 5899,
+    DecorationCacheSizeINTEL = 5900,
+    DecorationDontStaticallyCoalesceINTEL = 5901,
+    DecorationPrefetchINTEL = 5902,
+    DecorationStallEnableINTEL = 5905,
+    DecorationFuseLoopsInFunctionINTEL = 5907,
+    DecorationBufferLocationINTEL = 5921,
+    DecorationIOPipeStorageINTEL = 5944,
+    DecorationFunctionFloatingPointModeINTEL = 6080,
+    DecorationSingleElementVectorINTEL = 6085,
+    DecorationVectorComputeCallableFunctionINTEL = 6087,
     DecorationMax = 0x7fffffff,
 };
 
@@ -614,7 +659,6 @@
     BuiltInObjectToWorldNV = 5330,
     BuiltInWorldToObjectKHR = 5331,
     BuiltInWorldToObjectNV = 5331,
-    BuiltInHitTKHR = 5332,
     BuiltInHitTNV = 5332,
     BuiltInHitKindKHR = 5333,
     BuiltInHitKindNV = 5333,
@@ -657,6 +701,7 @@
     LoopControlLoopCoalesceINTELShift = 20,
     LoopControlMaxInterleavingINTELShift = 21,
     LoopControlSpeculatedIterationsINTELShift = 22,
+    LoopControlNoFusionINTELShift = 23,
     LoopControlMax = 0x7fffffff,
 };
 
@@ -678,6 +723,7 @@
     LoopControlLoopCoalesceINTELMask = 0x00100000,
     LoopControlMaxInterleavingINTELMask = 0x00200000,
     LoopControlSpeculatedIterationsINTELMask = 0x00400000,
+    LoopControlNoFusionINTELMask = 0x00800000,
 };
 
 enum FunctionControlShift {
@@ -967,21 +1013,37 @@
     CapabilitySubgroupBufferBlockIOINTEL = 5569,
     CapabilitySubgroupImageBlockIOINTEL = 5570,
     CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
+    CapabilityRoundToInfinityINTEL = 5582,
+    CapabilityFloatingPointModeINTEL = 5583,
     CapabilityIntegerFunctions2INTEL = 5584,
     CapabilityFunctionPointersINTEL = 5603,
     CapabilityIndirectReferencesINTEL = 5604,
+    CapabilityAsmINTEL = 5606,
+    CapabilityVectorComputeINTEL = 5617,
+    CapabilityVectorAnyINTEL = 5619,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
+    CapabilityVariableLengthArrayINTEL = 5817,
+    CapabilityFunctionFloatControlINTEL = 5821,
     CapabilityFPGAMemoryAttributesINTEL = 5824,
+    CapabilityFPFastMathModeINTEL = 5837,
+    CapabilityArbitraryPrecisionIntegersINTEL = 5844,
     CapabilityUnstructuredLoopControlsINTEL = 5886,
     CapabilityFPGALoopControlsINTEL = 5888,
     CapabilityKernelAttributesINTEL = 5892,
     CapabilityFPGAKernelAttributesINTEL = 5897,
+    CapabilityFPGAMemoryAccessesINTEL = 5898,
+    CapabilityFPGAClusterAttributesINTEL = 5904,
+    CapabilityLoopFuseINTEL = 5906,
+    CapabilityFPGABufferLocationINTEL = 5920,
+    CapabilityUSMStorageClassesINTEL = 5935,
+    CapabilityIOPipesINTEL = 5943,
     CapabilityBlockingPipesINTEL = 5945,
     CapabilityFPGARegINTEL = 5948,
     CapabilityAtomicFloat32AddEXT = 6033,
     CapabilityAtomicFloat64AddEXT = 6034,
+    CapabilityLongConstantCompositeINTEL = 6089,
     CapabilityMax = 0x7fffffff,
 };
 
@@ -1467,8 +1529,11 @@
     OpUSubSatINTEL = 5596,
     OpIMul32x16INTEL = 5597,
     OpUMul32x16INTEL = 5598,
-    OpFunctionPointerINTEL = 5600,
+    OpConstFunctionPointerINTEL = 5600,
     OpFunctionPointerCallINTEL = 5601,
+    OpAsmTargetINTEL = 5609,
+    OpAsmINTEL = 5610,
+    OpAsmCallINTEL = 5611,
     OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpMemberDecorateString = 5633,
@@ -1591,7 +1656,12 @@
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpVariableLengthArrayINTEL = 5818,
+    OpSaveMemoryINTEL = 5819,
+    OpRestoreMemoryINTEL = 5820,
     OpLoopControlINTEL = 5887,
+    OpPtrCastToCrossWorkgroupINTEL = 5934,
+    OpCrossWorkgroupCastToPtrINTEL = 5938,
     OpReadPipeBlockingINTEL = 5946,
     OpWritePipeBlockingINTEL = 5947,
     OpFPGARegINTEL = 5949,
@@ -1613,6 +1683,10 @@
     OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
     OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpAtomicFAddEXT = 6035,
+    OpTypeBufferSurfaceINTEL = 6086,
+    OpTypeStructContinuedINTEL = 6090,
+    OpConstantCompositeContinuedINTEL = 6091,
+    OpSpecConstantCompositeContinuedINTEL = 6092,
     OpMax = 0x7fffffff,
 };
 
@@ -2037,8 +2111,11 @@
     case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
     case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
-    case OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
     case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
     case OpDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
     case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2159,7 +2236,12 @@
     case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
     case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
     case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2181,6 +2263,10 @@
     case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
     case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
     case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
+    case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
     }
 }
 #endif /* SPV_ENABLE_UTILITY_CODE */
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp11 b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp11
index aec611f..b3f6792 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp11
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.hpp11
@@ -168,10 +168,16 @@
     SampleInterlockUnorderedEXT = 5369,
     ShadingRateInterlockOrderedEXT = 5370,
     ShadingRateInterlockUnorderedEXT = 5371,
+    SharedLocalMemorySizeINTEL = 5618,
+    RoundingModeRTPINTEL = 5620,
+    RoundingModeRTNINTEL = 5621,
+    FloatingPointModeALTINTEL = 5622,
+    FloatingPointModeIEEEINTEL = 5623,
     MaxWorkgroupSizeINTEL = 5893,
     MaxWorkDimINTEL = 5894,
     NoGlobalOffsetINTEL = 5895,
     NumSIMDWorkitemsINTEL = 5896,
+    SchedulerTargetFmaxMhzINTEL = 5903,
     Max = 0x7fffffff,
 };
 
@@ -204,6 +210,8 @@
     PhysicalStorageBuffer = 5349,
     PhysicalStorageBufferEXT = 5349,
     CodeSectionINTEL = 5605,
+    DeviceOnlyINTEL = 5936,
+    HostOnlyINTEL = 5937,
     Max = 0x7fffffff,
 };
 
@@ -374,6 +382,8 @@
     NSZ = 2,
     AllowRecip = 3,
     Fast = 4,
+    AllowContractFastINTEL = 16,
+    AllowReassocINTEL = 17,
     Max = 0x7fffffff,
 };
 
@@ -384,6 +394,8 @@
     NSZ = 0x00000004,
     AllowRecip = 0x00000008,
     Fast = 0x00000010,
+    AllowContractFastINTEL = 0x00010000,
+    AllowReassocINTEL = 0x00020000,
 };
 
 enum class FPRoundingMode : unsigned {
@@ -394,6 +406,18 @@
     Max = 0x7fffffff,
 };
 
+enum class FPDenormMode : unsigned {
+    Preserve = 0,
+    FlushToZero = 1,
+    Max = 0x7fffffff,
+};
+
+enum class FPOperationMode : unsigned {
+    IEEE = 0,
+    ALT = 1,
+    Max = 0x7fffffff,
+};
+
 enum class LinkageType : unsigned {
     Export = 0,
     Import = 1,
@@ -484,12 +508,22 @@
     RestrictPointerEXT = 5355,
     AliasedPointer = 5356,
     AliasedPointerEXT = 5356,
+    SIMTCallINTEL = 5599,
     ReferencedIndirectlyINTEL = 5602,
+    ClobberINTEL = 5607,
+    SideEffectsINTEL = 5608,
+    VectorComputeVariableINTEL = 5624,
+    FuncParamIOKindINTEL = 5625,
+    VectorComputeFunctionINTEL = 5626,
+    StackCallINTEL = 5627,
+    GlobalVariableOffsetINTEL = 5628,
     CounterBuffer = 5634,
     HlslCounterBufferGOOGLE = 5634,
     HlslSemanticGOOGLE = 5635,
     UserSemantic = 5635,
     UserTypeGOOGLE = 5636,
+    FunctionRoundingModeINTEL = 5822,
+    FunctionDenormModeINTEL = 5823,
     RegisterINTEL = 5825,
     MemoryINTEL = 5826,
     NumbanksINTEL = 5827,
@@ -502,6 +536,17 @@
     MergeINTEL = 5834,
     BankBitsINTEL = 5835,
     ForcePow2DepthINTEL = 5836,
+    BurstCoalesceINTEL = 5899,
+    CacheSizeINTEL = 5900,
+    DontStaticallyCoalesceINTEL = 5901,
+    PrefetchINTEL = 5902,
+    StallEnableINTEL = 5905,
+    FuseLoopsInFunctionINTEL = 5907,
+    BufferLocationINTEL = 5921,
+    IOPipeStorageINTEL = 5944,
+    FunctionFloatingPointModeINTEL = 6080,
+    SingleElementVectorINTEL = 6085,
+    VectorComputeCallableFunctionINTEL = 6087,
     Max = 0x7fffffff,
 };
 
@@ -614,7 +659,6 @@
     ObjectToWorldNV = 5330,
     WorldToObjectKHR = 5331,
     WorldToObjectNV = 5331,
-    HitTKHR = 5332,
     HitTNV = 5332,
     HitKindKHR = 5333,
     HitKindNV = 5333,
@@ -657,6 +701,7 @@
     LoopCoalesceINTEL = 20,
     MaxInterleavingINTEL = 21,
     SpeculatedIterationsINTEL = 22,
+    NoFusionINTEL = 23,
     Max = 0x7fffffff,
 };
 
@@ -678,6 +723,7 @@
     LoopCoalesceINTEL = 0x00100000,
     MaxInterleavingINTEL = 0x00200000,
     SpeculatedIterationsINTEL = 0x00400000,
+    NoFusionINTEL = 0x00800000,
 };
 
 enum class FunctionControlShift : unsigned {
@@ -967,21 +1013,37 @@
     SubgroupBufferBlockIOINTEL = 5569,
     SubgroupImageBlockIOINTEL = 5570,
     SubgroupImageMediaBlockIOINTEL = 5579,
+    RoundToInfinityINTEL = 5582,
+    FloatingPointModeINTEL = 5583,
     IntegerFunctions2INTEL = 5584,
     FunctionPointersINTEL = 5603,
     IndirectReferencesINTEL = 5604,
+    AsmINTEL = 5606,
+    VectorComputeINTEL = 5617,
+    VectorAnyINTEL = 5619,
     SubgroupAvcMotionEstimationINTEL = 5696,
     SubgroupAvcMotionEstimationIntraINTEL = 5697,
     SubgroupAvcMotionEstimationChromaINTEL = 5698,
+    VariableLengthArrayINTEL = 5817,
+    FunctionFloatControlINTEL = 5821,
     FPGAMemoryAttributesINTEL = 5824,
+    FPFastMathModeINTEL = 5837,
+    ArbitraryPrecisionIntegersINTEL = 5844,
     UnstructuredLoopControlsINTEL = 5886,
     FPGALoopControlsINTEL = 5888,
     KernelAttributesINTEL = 5892,
     FPGAKernelAttributesINTEL = 5897,
+    FPGAMemoryAccessesINTEL = 5898,
+    FPGAClusterAttributesINTEL = 5904,
+    LoopFuseINTEL = 5906,
+    FPGABufferLocationINTEL = 5920,
+    USMStorageClassesINTEL = 5935,
+    IOPipesINTEL = 5943,
     BlockingPipesINTEL = 5945,
     FPGARegINTEL = 5948,
     AtomicFloat32AddEXT = 6033,
     AtomicFloat64AddEXT = 6034,
+    LongConstantCompositeINTEL = 6089,
     Max = 0x7fffffff,
 };
 
@@ -1467,8 +1529,11 @@
     OpUSubSatINTEL = 5596,
     OpIMul32x16INTEL = 5597,
     OpUMul32x16INTEL = 5598,
-    OpFunctionPointerINTEL = 5600,
+    OpConstFunctionPointerINTEL = 5600,
     OpFunctionPointerCallINTEL = 5601,
+    OpAsmTargetINTEL = 5609,
+    OpAsmINTEL = 5610,
+    OpAsmCallINTEL = 5611,
     OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpMemberDecorateString = 5633,
@@ -1591,7 +1656,12 @@
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpVariableLengthArrayINTEL = 5818,
+    OpSaveMemoryINTEL = 5819,
+    OpRestoreMemoryINTEL = 5820,
     OpLoopControlINTEL = 5887,
+    OpPtrCastToCrossWorkgroupINTEL = 5934,
+    OpCrossWorkgroupCastToPtrINTEL = 5938,
     OpReadPipeBlockingINTEL = 5946,
     OpWritePipeBlockingINTEL = 5947,
     OpFPGARegINTEL = 5949,
@@ -1613,6 +1683,10 @@
     OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
     OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpAtomicFAddEXT = 6035,
+    OpTypeBufferSurfaceINTEL = 6086,
+    OpTypeStructContinuedINTEL = 6090,
+    OpConstantCompositeContinuedINTEL = 6091,
+    OpSpecConstantCompositeContinuedINTEL = 6092,
     Max = 0x7fffffff,
 };
 
@@ -2037,8 +2111,11 @@
     case Op::OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
-    case Op::OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpDecorateString: *hasResult = false; *hasResultType = false; break;
     case Op::OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
     case Op::OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2159,7 +2236,12 @@
     case Op::OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
     case Op::OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+    case Op::OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
+    case Op::OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
     case Op::OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2181,6 +2263,10 @@
     case Op::OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
     case Op::OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
     case Op::OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
+    case Op::OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;
+    case Op::OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case Op::OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+    case Op::OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
     }
 }
 #endif /* SPV_ENABLE_UTILITY_CODE */
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.json b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.json
index a1fd3b9..32dfe6f 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.json
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.json
@@ -187,10 +187,16 @@
                     "SampleInterlockUnorderedEXT": 5369,
                     "ShadingRateInterlockOrderedEXT": 5370,
                     "ShadingRateInterlockUnorderedEXT": 5371,
+                    "SharedLocalMemorySizeINTEL": 5618,
+                    "RoundingModeRTPINTEL": 5620,
+                    "RoundingModeRTNINTEL": 5621,
+                    "FloatingPointModeALTINTEL": 5622,
+                    "FloatingPointModeIEEEINTEL": 5623,
                     "MaxWorkgroupSizeINTEL": 5893,
                     "MaxWorkDimINTEL": 5894,
                     "NoGlobalOffsetINTEL": 5895,
-                    "NumSIMDWorkitemsINTEL": 5896
+                    "NumSIMDWorkitemsINTEL": 5896,
+                    "SchedulerTargetFmaxMhzINTEL": 5903
                 }
             },
             {
@@ -225,7 +231,9 @@
                     "ShaderRecordBufferNV": 5343,
                     "PhysicalStorageBuffer": 5349,
                     "PhysicalStorageBufferEXT": 5349,
-                    "CodeSectionINTEL": 5605
+                    "CodeSectionINTEL": 5605,
+                    "DeviceOnlyINTEL": 5936,
+                    "HostOnlyINTEL": 5937
                 }
             },
             {
@@ -397,7 +405,9 @@
                     "NotInf": 1,
                     "NSZ": 2,
                     "AllowRecip": 3,
-                    "Fast": 4
+                    "Fast": 4,
+                    "AllowContractFastINTEL": 16,
+                    "AllowReassocINTEL": 17
                 }
             },
             {
@@ -412,6 +422,24 @@
                 }
             },
             {
+                "Name": "FPDenormMode",
+                "Type": "Value",
+                "Values":
+                {
+                    "Preserve": 0,
+                    "FlushToZero": 1
+                }
+            },
+            {
+                "Name": "FPOperationMode",
+                "Type": "Value",
+                "Values":
+                {
+                    "IEEE": 0,
+                    "ALT": 1
+                }
+            },
+            {
                 "Name": "LinkageType",
                 "Type": "Value",
                 "Values":
@@ -514,12 +542,22 @@
                     "RestrictPointerEXT": 5355,
                     "AliasedPointer": 5356,
                     "AliasedPointerEXT": 5356,
+                    "SIMTCallINTEL": 5599,
                     "ReferencedIndirectlyINTEL": 5602,
+                    "ClobberINTEL": 5607,
+                    "SideEffectsINTEL": 5608,
+                    "VectorComputeVariableINTEL": 5624,
+                    "FuncParamIOKindINTEL": 5625,
+                    "VectorComputeFunctionINTEL": 5626,
+                    "StackCallINTEL": 5627,
+                    "GlobalVariableOffsetINTEL": 5628,
                     "CounterBuffer": 5634,
                     "HlslCounterBufferGOOGLE": 5634,
                     "HlslSemanticGOOGLE": 5635,
                     "UserSemantic": 5635,
                     "UserTypeGOOGLE": 5636,
+                    "FunctionRoundingModeINTEL": 5822,
+                    "FunctionDenormModeINTEL": 5823,
                     "RegisterINTEL": 5825,
                     "MemoryINTEL": 5826,
                     "NumbanksINTEL": 5827,
@@ -531,7 +569,18 @@
                     "SimpleDualPortINTEL": 5833,
                     "MergeINTEL": 5834,
                     "BankBitsINTEL": 5835,
-                    "ForcePow2DepthINTEL": 5836
+                    "ForcePow2DepthINTEL": 5836,
+                    "BurstCoalesceINTEL": 5899,
+                    "CacheSizeINTEL": 5900,
+                    "DontStaticallyCoalesceINTEL": 5901,
+                    "PrefetchINTEL": 5902,
+                    "StallEnableINTEL": 5905,
+                    "FuseLoopsInFunctionINTEL": 5907,
+                    "BufferLocationINTEL": 5921,
+                    "IOPipeStorageINTEL": 5944,
+                    "FunctionFloatingPointModeINTEL": 6080,
+                    "SingleElementVectorINTEL": 6085,
+                    "VectorComputeCallableFunctionINTEL": 6087
                 }
             },
             {
@@ -647,7 +696,6 @@
                     "ObjectToWorldNV": 5330,
                     "WorldToObjectKHR": 5331,
                     "WorldToObjectNV": 5331,
-                    "HitTKHR": 5332,
                     "HitTNV": 5332,
                     "HitKindKHR": 5333,
                     "HitKindNV": 5333,
@@ -689,7 +737,8 @@
                     "PipelineEnableINTEL": 19,
                     "LoopCoalesceINTEL": 20,
                     "MaxInterleavingINTEL": 21,
-                    "SpeculatedIterationsINTEL": 22
+                    "SpeculatedIterationsINTEL": 22,
+                    "NoFusionINTEL": 23
                 }
             },
             {
@@ -957,21 +1006,37 @@
                     "SubgroupBufferBlockIOINTEL": 5569,
                     "SubgroupImageBlockIOINTEL": 5570,
                     "SubgroupImageMediaBlockIOINTEL": 5579,
+                    "RoundToInfinityINTEL": 5582,
+                    "FloatingPointModeINTEL": 5583,
                     "IntegerFunctions2INTEL": 5584,
                     "FunctionPointersINTEL": 5603,
                     "IndirectReferencesINTEL": 5604,
+                    "AsmINTEL": 5606,
+                    "VectorComputeINTEL": 5617,
+                    "VectorAnyINTEL": 5619,
                     "SubgroupAvcMotionEstimationINTEL": 5696,
                     "SubgroupAvcMotionEstimationIntraINTEL": 5697,
                     "SubgroupAvcMotionEstimationChromaINTEL": 5698,
+                    "VariableLengthArrayINTEL": 5817,
+                    "FunctionFloatControlINTEL": 5821,
                     "FPGAMemoryAttributesINTEL": 5824,
+                    "FPFastMathModeINTEL": 5837,
+                    "ArbitraryPrecisionIntegersINTEL": 5844,
                     "UnstructuredLoopControlsINTEL": 5886,
                     "FPGALoopControlsINTEL": 5888,
                     "KernelAttributesINTEL": 5892,
                     "FPGAKernelAttributesINTEL": 5897,
+                    "FPGAMemoryAccessesINTEL": 5898,
+                    "FPGAClusterAttributesINTEL": 5904,
+                    "LoopFuseINTEL": 5906,
+                    "FPGABufferLocationINTEL": 5920,
+                    "USMStorageClassesINTEL": 5935,
+                    "IOPipesINTEL": 5943,
                     "BlockingPipesINTEL": 5945,
                     "FPGARegINTEL": 5948,
                     "AtomicFloat32AddEXT": 6033,
-                    "AtomicFloat64AddEXT": 6034
+                    "AtomicFloat64AddEXT": 6034,
+                    "LongConstantCompositeINTEL": 6089
                 }
             },
             {
@@ -1453,8 +1518,11 @@
                     "OpUSubSatINTEL": 5596,
                     "OpIMul32x16INTEL": 5597,
                     "OpUMul32x16INTEL": 5598,
-                    "OpFunctionPointerINTEL": 5600,
+                    "OpConstFunctionPointerINTEL": 5600,
                     "OpFunctionPointerCallINTEL": 5601,
+                    "OpAsmTargetINTEL": 5609,
+                    "OpAsmINTEL": 5610,
+                    "OpAsmCallINTEL": 5611,
                     "OpDecorateString": 5632,
                     "OpDecorateStringGOOGLE": 5632,
                     "OpMemberDecorateString": 5633,
@@ -1577,7 +1645,12 @@
                     "OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL": 5814,
                     "OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL": 5815,
                     "OpSubgroupAvcSicGetInterRawSadsINTEL": 5816,
+                    "OpVariableLengthArrayINTEL": 5818,
+                    "OpSaveMemoryINTEL": 5819,
+                    "OpRestoreMemoryINTEL": 5820,
                     "OpLoopControlINTEL": 5887,
+                    "OpPtrCastToCrossWorkgroupINTEL": 5934,
+                    "OpCrossWorkgroupCastToPtrINTEL": 5938,
                     "OpReadPipeBlockingINTEL": 5946,
                     "OpWritePipeBlockingINTEL": 5947,
                     "OpFPGARegINTEL": 5949,
@@ -1598,7 +1671,11 @@
                     "OpRayQueryGetWorldRayOriginKHR": 6030,
                     "OpRayQueryGetIntersectionObjectToWorldKHR": 6031,
                     "OpRayQueryGetIntersectionWorldToObjectKHR": 6032,
-                    "OpAtomicFAddEXT": 6035
+                    "OpAtomicFAddEXT": 6035,
+                    "OpTypeBufferSurfaceINTEL": 6086,
+                    "OpTypeStructContinuedINTEL": 6090,
+                    "OpConstantCompositeContinuedINTEL": 6091,
+                    "OpSpecConstantCompositeContinuedINTEL": 6092
                 }
             }
         ]
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.lua b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.lua
index 89b0fc8..a1934d5 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.lua
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.lua
@@ -155,10 +155,16 @@
         SampleInterlockUnorderedEXT = 5369,
         ShadingRateInterlockOrderedEXT = 5370,
         ShadingRateInterlockUnorderedEXT = 5371,
+        SharedLocalMemorySizeINTEL = 5618,
+        RoundingModeRTPINTEL = 5620,
+        RoundingModeRTNINTEL = 5621,
+        FloatingPointModeALTINTEL = 5622,
+        FloatingPointModeIEEEINTEL = 5623,
         MaxWorkgroupSizeINTEL = 5893,
         MaxWorkDimINTEL = 5894,
         NoGlobalOffsetINTEL = 5895,
         NumSIMDWorkitemsINTEL = 5896,
+        SchedulerTargetFmaxMhzINTEL = 5903,
     },
 
     StorageClass = {
@@ -190,6 +196,8 @@
         PhysicalStorageBuffer = 5349,
         PhysicalStorageBufferEXT = 5349,
         CodeSectionINTEL = 5605,
+        DeviceOnlyINTEL = 5936,
+        HostOnlyINTEL = 5937,
     },
 
     Dim = {
@@ -352,6 +360,8 @@
         NSZ = 2,
         AllowRecip = 3,
         Fast = 4,
+        AllowContractFastINTEL = 16,
+        AllowReassocINTEL = 17,
     },
 
     FPFastMathModeMask = {
@@ -361,6 +371,8 @@
         NSZ = 0x00000004,
         AllowRecip = 0x00000008,
         Fast = 0x00000010,
+        AllowContractFastINTEL = 0x00010000,
+        AllowReassocINTEL = 0x00020000,
     },
 
     FPRoundingMode = {
@@ -370,6 +382,16 @@
         RTN = 3,
     },
 
+    FPDenormMode = {
+        Preserve = 0,
+        FlushToZero = 1,
+    },
+
+    FPOperationMode = {
+        IEEE = 0,
+        ALT = 1,
+    },
+
     LinkageType = {
         Export = 0,
         Import = 1,
@@ -457,12 +479,22 @@
         RestrictPointerEXT = 5355,
         AliasedPointer = 5356,
         AliasedPointerEXT = 5356,
+        SIMTCallINTEL = 5599,
         ReferencedIndirectlyINTEL = 5602,
+        ClobberINTEL = 5607,
+        SideEffectsINTEL = 5608,
+        VectorComputeVariableINTEL = 5624,
+        FuncParamIOKindINTEL = 5625,
+        VectorComputeFunctionINTEL = 5626,
+        StackCallINTEL = 5627,
+        GlobalVariableOffsetINTEL = 5628,
         CounterBuffer = 5634,
         HlslCounterBufferGOOGLE = 5634,
         HlslSemanticGOOGLE = 5635,
         UserSemantic = 5635,
         UserTypeGOOGLE = 5636,
+        FunctionRoundingModeINTEL = 5822,
+        FunctionDenormModeINTEL = 5823,
         RegisterINTEL = 5825,
         MemoryINTEL = 5826,
         NumbanksINTEL = 5827,
@@ -475,6 +507,17 @@
         MergeINTEL = 5834,
         BankBitsINTEL = 5835,
         ForcePow2DepthINTEL = 5836,
+        BurstCoalesceINTEL = 5899,
+        CacheSizeINTEL = 5900,
+        DontStaticallyCoalesceINTEL = 5901,
+        PrefetchINTEL = 5902,
+        StallEnableINTEL = 5905,
+        FuseLoopsInFunctionINTEL = 5907,
+        BufferLocationINTEL = 5921,
+        IOPipeStorageINTEL = 5944,
+        FunctionFloatingPointModeINTEL = 6080,
+        SingleElementVectorINTEL = 6085,
+        VectorComputeCallableFunctionINTEL = 6087,
     },
 
     BuiltIn = {
@@ -586,7 +629,6 @@
         ObjectToWorldNV = 5330,
         WorldToObjectKHR = 5331,
         WorldToObjectNV = 5331,
-        HitTKHR = 5332,
         HitTNV = 5332,
         HitKindKHR = 5333,
         HitKindNV = 5333,
@@ -627,6 +669,7 @@
         LoopCoalesceINTEL = 20,
         MaxInterleavingINTEL = 21,
         SpeculatedIterationsINTEL = 22,
+        NoFusionINTEL = 23,
     },
 
     LoopControlMask = {
@@ -647,6 +690,7 @@
         LoopCoalesceINTEL = 0x00100000,
         MaxInterleavingINTEL = 0x00200000,
         SpeculatedIterationsINTEL = 0x00400000,
+        NoFusionINTEL = 0x00800000,
     },
 
     FunctionControlShift = {
@@ -929,21 +973,37 @@
         SubgroupBufferBlockIOINTEL = 5569,
         SubgroupImageBlockIOINTEL = 5570,
         SubgroupImageMediaBlockIOINTEL = 5579,
+        RoundToInfinityINTEL = 5582,
+        FloatingPointModeINTEL = 5583,
         IntegerFunctions2INTEL = 5584,
         FunctionPointersINTEL = 5603,
         IndirectReferencesINTEL = 5604,
+        AsmINTEL = 5606,
+        VectorComputeINTEL = 5617,
+        VectorAnyINTEL = 5619,
         SubgroupAvcMotionEstimationINTEL = 5696,
         SubgroupAvcMotionEstimationIntraINTEL = 5697,
         SubgroupAvcMotionEstimationChromaINTEL = 5698,
+        VariableLengthArrayINTEL = 5817,
+        FunctionFloatControlINTEL = 5821,
         FPGAMemoryAttributesINTEL = 5824,
+        FPFastMathModeINTEL = 5837,
+        ArbitraryPrecisionIntegersINTEL = 5844,
         UnstructuredLoopControlsINTEL = 5886,
         FPGALoopControlsINTEL = 5888,
         KernelAttributesINTEL = 5892,
         FPGAKernelAttributesINTEL = 5897,
+        FPGAMemoryAccessesINTEL = 5898,
+        FPGAClusterAttributesINTEL = 5904,
+        LoopFuseINTEL = 5906,
+        FPGABufferLocationINTEL = 5920,
+        USMStorageClassesINTEL = 5935,
+        IOPipesINTEL = 5943,
         BlockingPipesINTEL = 5945,
         FPGARegINTEL = 5948,
         AtomicFloat32AddEXT = 6033,
         AtomicFloat64AddEXT = 6034,
+        LongConstantCompositeINTEL = 6089,
     },
 
     RayFlagsShift = {
@@ -1423,8 +1483,11 @@
         OpUSubSatINTEL = 5596,
         OpIMul32x16INTEL = 5597,
         OpUMul32x16INTEL = 5598,
-        OpFunctionPointerINTEL = 5600,
+        OpConstFunctionPointerINTEL = 5600,
         OpFunctionPointerCallINTEL = 5601,
+        OpAsmTargetINTEL = 5609,
+        OpAsmINTEL = 5610,
+        OpAsmCallINTEL = 5611,
         OpDecorateString = 5632,
         OpDecorateStringGOOGLE = 5632,
         OpMemberDecorateString = 5633,
@@ -1547,7 +1610,12 @@
         OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
         OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
         OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+        OpVariableLengthArrayINTEL = 5818,
+        OpSaveMemoryINTEL = 5819,
+        OpRestoreMemoryINTEL = 5820,
         OpLoopControlINTEL = 5887,
+        OpPtrCastToCrossWorkgroupINTEL = 5934,
+        OpCrossWorkgroupCastToPtrINTEL = 5938,
         OpReadPipeBlockingINTEL = 5946,
         OpWritePipeBlockingINTEL = 5947,
         OpFPGARegINTEL = 5949,
@@ -1569,6 +1637,10 @@
         OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
         OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
         OpAtomicFAddEXT = 6035,
+        OpTypeBufferSurfaceINTEL = 6086,
+        OpTypeStructContinuedINTEL = 6090,
+        OpConstantCompositeContinuedINTEL = 6091,
+        OpSpecConstantCompositeContinuedINTEL = 6092,
     },
 
 }
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.py b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.py
index a9983c0..8fc2a4b 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spirv.py
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spirv.py
@@ -155,10 +155,16 @@
         'SampleInterlockUnorderedEXT' : 5369,
         'ShadingRateInterlockOrderedEXT' : 5370,
         'ShadingRateInterlockUnorderedEXT' : 5371,
+        'SharedLocalMemorySizeINTEL' : 5618,
+        'RoundingModeRTPINTEL' : 5620,
+        'RoundingModeRTNINTEL' : 5621,
+        'FloatingPointModeALTINTEL' : 5622,
+        'FloatingPointModeIEEEINTEL' : 5623,
         'MaxWorkgroupSizeINTEL' : 5893,
         'MaxWorkDimINTEL' : 5894,
         'NoGlobalOffsetINTEL' : 5895,
         'NumSIMDWorkitemsINTEL' : 5896,
+        'SchedulerTargetFmaxMhzINTEL' : 5903,
     },
 
     'StorageClass' : {
@@ -190,6 +196,8 @@
         'PhysicalStorageBuffer' : 5349,
         'PhysicalStorageBufferEXT' : 5349,
         'CodeSectionINTEL' : 5605,
+        'DeviceOnlyINTEL' : 5936,
+        'HostOnlyINTEL' : 5937,
     },
 
     'Dim' : {
@@ -352,6 +360,8 @@
         'NSZ' : 2,
         'AllowRecip' : 3,
         'Fast' : 4,
+        'AllowContractFastINTEL' : 16,
+        'AllowReassocINTEL' : 17,
     },
 
     'FPFastMathModeMask' : {
@@ -361,6 +371,8 @@
         'NSZ' : 0x00000004,
         'AllowRecip' : 0x00000008,
         'Fast' : 0x00000010,
+        'AllowContractFastINTEL' : 0x00010000,
+        'AllowReassocINTEL' : 0x00020000,
     },
 
     'FPRoundingMode' : {
@@ -370,6 +382,16 @@
         'RTN' : 3,
     },
 
+    'FPDenormMode' : {
+        'Preserve' : 0,
+        'FlushToZero' : 1,
+    },
+
+    'FPOperationMode' : {
+        'IEEE' : 0,
+        'ALT' : 1,
+    },
+
     'LinkageType' : {
         'Export' : 0,
         'Import' : 1,
@@ -457,12 +479,22 @@
         'RestrictPointerEXT' : 5355,
         'AliasedPointer' : 5356,
         'AliasedPointerEXT' : 5356,
+        'SIMTCallINTEL' : 5599,
         'ReferencedIndirectlyINTEL' : 5602,
+        'ClobberINTEL' : 5607,
+        'SideEffectsINTEL' : 5608,
+        'VectorComputeVariableINTEL' : 5624,
+        'FuncParamIOKindINTEL' : 5625,
+        'VectorComputeFunctionINTEL' : 5626,
+        'StackCallINTEL' : 5627,
+        'GlobalVariableOffsetINTEL' : 5628,
         'CounterBuffer' : 5634,
         'HlslCounterBufferGOOGLE' : 5634,
         'HlslSemanticGOOGLE' : 5635,
         'UserSemantic' : 5635,
         'UserTypeGOOGLE' : 5636,
+        'FunctionRoundingModeINTEL' : 5822,
+        'FunctionDenormModeINTEL' : 5823,
         'RegisterINTEL' : 5825,
         'MemoryINTEL' : 5826,
         'NumbanksINTEL' : 5827,
@@ -475,6 +507,17 @@
         'MergeINTEL' : 5834,
         'BankBitsINTEL' : 5835,
         'ForcePow2DepthINTEL' : 5836,
+        'BurstCoalesceINTEL' : 5899,
+        'CacheSizeINTEL' : 5900,
+        'DontStaticallyCoalesceINTEL' : 5901,
+        'PrefetchINTEL' : 5902,
+        'StallEnableINTEL' : 5905,
+        'FuseLoopsInFunctionINTEL' : 5907,
+        'BufferLocationINTEL' : 5921,
+        'IOPipeStorageINTEL' : 5944,
+        'FunctionFloatingPointModeINTEL' : 6080,
+        'SingleElementVectorINTEL' : 6085,
+        'VectorComputeCallableFunctionINTEL' : 6087,
     },
 
     'BuiltIn' : {
@@ -586,7 +629,6 @@
         'ObjectToWorldNV' : 5330,
         'WorldToObjectKHR' : 5331,
         'WorldToObjectNV' : 5331,
-        'HitTKHR' : 5332,
         'HitTNV' : 5332,
         'HitKindKHR' : 5333,
         'HitKindNV' : 5333,
@@ -627,6 +669,7 @@
         'LoopCoalesceINTEL' : 20,
         'MaxInterleavingINTEL' : 21,
         'SpeculatedIterationsINTEL' : 22,
+        'NoFusionINTEL' : 23,
     },
 
     'LoopControlMask' : {
@@ -647,6 +690,7 @@
         'LoopCoalesceINTEL' : 0x00100000,
         'MaxInterleavingINTEL' : 0x00200000,
         'SpeculatedIterationsINTEL' : 0x00400000,
+        'NoFusionINTEL' : 0x00800000,
     },
 
     'FunctionControlShift' : {
@@ -929,21 +973,37 @@
         'SubgroupBufferBlockIOINTEL' : 5569,
         'SubgroupImageBlockIOINTEL' : 5570,
         'SubgroupImageMediaBlockIOINTEL' : 5579,
+        'RoundToInfinityINTEL' : 5582,
+        'FloatingPointModeINTEL' : 5583,
         'IntegerFunctions2INTEL' : 5584,
         'FunctionPointersINTEL' : 5603,
         'IndirectReferencesINTEL' : 5604,
+        'AsmINTEL' : 5606,
+        'VectorComputeINTEL' : 5617,
+        'VectorAnyINTEL' : 5619,
         'SubgroupAvcMotionEstimationINTEL' : 5696,
         'SubgroupAvcMotionEstimationIntraINTEL' : 5697,
         'SubgroupAvcMotionEstimationChromaINTEL' : 5698,
+        'VariableLengthArrayINTEL' : 5817,
+        'FunctionFloatControlINTEL' : 5821,
         'FPGAMemoryAttributesINTEL' : 5824,
+        'FPFastMathModeINTEL' : 5837,
+        'ArbitraryPrecisionIntegersINTEL' : 5844,
         'UnstructuredLoopControlsINTEL' : 5886,
         'FPGALoopControlsINTEL' : 5888,
         'KernelAttributesINTEL' : 5892,
         'FPGAKernelAttributesINTEL' : 5897,
+        'FPGAMemoryAccessesINTEL' : 5898,
+        'FPGAClusterAttributesINTEL' : 5904,
+        'LoopFuseINTEL' : 5906,
+        'FPGABufferLocationINTEL' : 5920,
+        'USMStorageClassesINTEL' : 5935,
+        'IOPipesINTEL' : 5943,
         'BlockingPipesINTEL' : 5945,
         'FPGARegINTEL' : 5948,
         'AtomicFloat32AddEXT' : 6033,
         'AtomicFloat64AddEXT' : 6034,
+        'LongConstantCompositeINTEL' : 6089,
     },
 
     'RayFlagsShift' : {
@@ -1423,8 +1483,11 @@
         'OpUSubSatINTEL' : 5596,
         'OpIMul32x16INTEL' : 5597,
         'OpUMul32x16INTEL' : 5598,
-        'OpFunctionPointerINTEL' : 5600,
+        'OpConstFunctionPointerINTEL' : 5600,
         'OpFunctionPointerCallINTEL' : 5601,
+        'OpAsmTargetINTEL' : 5609,
+        'OpAsmINTEL' : 5610,
+        'OpAsmCallINTEL' : 5611,
         'OpDecorateString' : 5632,
         'OpDecorateStringGOOGLE' : 5632,
         'OpMemberDecorateString' : 5633,
@@ -1547,7 +1610,12 @@
         'OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL' : 5814,
         'OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL' : 5815,
         'OpSubgroupAvcSicGetInterRawSadsINTEL' : 5816,
+        'OpVariableLengthArrayINTEL' : 5818,
+        'OpSaveMemoryINTEL' : 5819,
+        'OpRestoreMemoryINTEL' : 5820,
         'OpLoopControlINTEL' : 5887,
+        'OpPtrCastToCrossWorkgroupINTEL' : 5934,
+        'OpCrossWorkgroupCastToPtrINTEL' : 5938,
         'OpReadPipeBlockingINTEL' : 5946,
         'OpWritePipeBlockingINTEL' : 5947,
         'OpFPGARegINTEL' : 5949,
@@ -1569,6 +1637,10 @@
         'OpRayQueryGetIntersectionObjectToWorldKHR' : 6031,
         'OpRayQueryGetIntersectionWorldToObjectKHR' : 6032,
         'OpAtomicFAddEXT' : 6035,
+        'OpTypeBufferSurfaceINTEL' : 6086,
+        'OpTypeStructContinuedINTEL' : 6090,
+        'OpConstantCompositeContinuedINTEL' : 6091,
+        'OpSpecConstantCompositeContinuedINTEL' : 6092,
     },
 
 }
diff --git a/third_party/SPIRV-Headers/include/spirv/unified1/spv.d b/third_party/SPIRV-Headers/include/spirv/unified1/spv.d
index b840139..793b058 100644
--- a/third_party/SPIRV-Headers/include/spirv/unified1/spv.d
+++ b/third_party/SPIRV-Headers/include/spirv/unified1/spv.d
@@ -167,10 +167,16 @@
     SampleInterlockUnorderedEXT = 5369,
     ShadingRateInterlockOrderedEXT = 5370,
     ShadingRateInterlockUnorderedEXT = 5371,
+    SharedLocalMemorySizeINTEL = 5618,
+    RoundingModeRTPINTEL = 5620,
+    RoundingModeRTNINTEL = 5621,
+    FloatingPointModeALTINTEL = 5622,
+    FloatingPointModeIEEEINTEL = 5623,
     MaxWorkgroupSizeINTEL = 5893,
     MaxWorkDimINTEL = 5894,
     NoGlobalOffsetINTEL = 5895,
     NumSIMDWorkitemsINTEL = 5896,
+    SchedulerTargetFmaxMhzINTEL = 5903,
 }
 
 enum StorageClass : uint
@@ -203,6 +209,8 @@
     PhysicalStorageBuffer = 5349,
     PhysicalStorageBufferEXT = 5349,
     CodeSectionINTEL = 5605,
+    DeviceOnlyINTEL = 5936,
+    HostOnlyINTEL = 5937,
 }
 
 enum Dim : uint
@@ -374,6 +382,8 @@
     NSZ = 2,
     AllowRecip = 3,
     Fast = 4,
+    AllowContractFastINTEL = 16,
+    AllowReassocINTEL = 17,
 }
 
 enum FPFastMathModeMask : uint
@@ -384,6 +394,8 @@
     NSZ = 0x00000004,
     AllowRecip = 0x00000008,
     Fast = 0x00000010,
+    AllowContractFastINTEL = 0x00010000,
+    AllowReassocINTEL = 0x00020000,
 }
 
 enum FPRoundingMode : uint
@@ -394,6 +406,18 @@
     RTN = 3,
 }
 
+enum FPDenormMode : uint
+{
+    Preserve = 0,
+    FlushToZero = 1,
+}
+
+enum FPOperationMode : uint
+{
+    IEEE = 0,
+    ALT = 1,
+}
+
 enum LinkageType : uint
 {
     Export = 0,
@@ -485,12 +509,22 @@
     RestrictPointerEXT = 5355,
     AliasedPointer = 5356,
     AliasedPointerEXT = 5356,
+    SIMTCallINTEL = 5599,
     ReferencedIndirectlyINTEL = 5602,
+    ClobberINTEL = 5607,
+    SideEffectsINTEL = 5608,
+    VectorComputeVariableINTEL = 5624,
+    FuncParamIOKindINTEL = 5625,
+    VectorComputeFunctionINTEL = 5626,
+    StackCallINTEL = 5627,
+    GlobalVariableOffsetINTEL = 5628,
     CounterBuffer = 5634,
     HlslCounterBufferGOOGLE = 5634,
     HlslSemanticGOOGLE = 5635,
     UserSemantic = 5635,
     UserTypeGOOGLE = 5636,
+    FunctionRoundingModeINTEL = 5822,
+    FunctionDenormModeINTEL = 5823,
     RegisterINTEL = 5825,
     MemoryINTEL = 5826,
     NumbanksINTEL = 5827,
@@ -503,6 +537,17 @@
     MergeINTEL = 5834,
     BankBitsINTEL = 5835,
     ForcePow2DepthINTEL = 5836,
+    BurstCoalesceINTEL = 5899,
+    CacheSizeINTEL = 5900,
+    DontStaticallyCoalesceINTEL = 5901,
+    PrefetchINTEL = 5902,
+    StallEnableINTEL = 5905,
+    FuseLoopsInFunctionINTEL = 5907,
+    BufferLocationINTEL = 5921,
+    IOPipeStorageINTEL = 5944,
+    FunctionFloatingPointModeINTEL = 6080,
+    SingleElementVectorINTEL = 6085,
+    VectorComputeCallableFunctionINTEL = 6087,
 }
 
 enum BuiltIn : uint
@@ -615,7 +660,6 @@
     ObjectToWorldNV = 5330,
     WorldToObjectKHR = 5331,
     WorldToObjectNV = 5331,
-    HitTKHR = 5332,
     HitTNV = 5332,
     HitKindKHR = 5333,
     HitKindNV = 5333,
@@ -659,6 +703,7 @@
     LoopCoalesceINTEL = 20,
     MaxInterleavingINTEL = 21,
     SpeculatedIterationsINTEL = 22,
+    NoFusionINTEL = 23,
 }
 
 enum LoopControlMask : uint
@@ -680,6 +725,7 @@
     LoopCoalesceINTEL = 0x00100000,
     MaxInterleavingINTEL = 0x00200000,
     SpeculatedIterationsINTEL = 0x00400000,
+    NoFusionINTEL = 0x00800000,
 }
 
 enum FunctionControlShift : uint
@@ -974,21 +1020,37 @@
     SubgroupBufferBlockIOINTEL = 5569,
     SubgroupImageBlockIOINTEL = 5570,
     SubgroupImageMediaBlockIOINTEL = 5579,
+    RoundToInfinityINTEL = 5582,
+    FloatingPointModeINTEL = 5583,
     IntegerFunctions2INTEL = 5584,
     FunctionPointersINTEL = 5603,
     IndirectReferencesINTEL = 5604,
+    AsmINTEL = 5606,
+    VectorComputeINTEL = 5617,
+    VectorAnyINTEL = 5619,
     SubgroupAvcMotionEstimationINTEL = 5696,
     SubgroupAvcMotionEstimationIntraINTEL = 5697,
     SubgroupAvcMotionEstimationChromaINTEL = 5698,
+    VariableLengthArrayINTEL = 5817,
+    FunctionFloatControlINTEL = 5821,
     FPGAMemoryAttributesINTEL = 5824,
+    FPFastMathModeINTEL = 5837,
+    ArbitraryPrecisionIntegersINTEL = 5844,
     UnstructuredLoopControlsINTEL = 5886,
     FPGALoopControlsINTEL = 5888,
     KernelAttributesINTEL = 5892,
     FPGAKernelAttributesINTEL = 5897,
+    FPGAMemoryAccessesINTEL = 5898,
+    FPGAClusterAttributesINTEL = 5904,
+    LoopFuseINTEL = 5906,
+    FPGABufferLocationINTEL = 5920,
+    USMStorageClassesINTEL = 5935,
+    IOPipesINTEL = 5943,
     BlockingPipesINTEL = 5945,
     FPGARegINTEL = 5948,
     AtomicFloat32AddEXT = 6033,
     AtomicFloat64AddEXT = 6034,
+    LongConstantCompositeINTEL = 6089,
 }
 
 enum RayFlagsShift : uint
@@ -1476,8 +1538,11 @@
     OpUSubSatINTEL = 5596,
     OpIMul32x16INTEL = 5597,
     OpUMul32x16INTEL = 5598,
-    OpFunctionPointerINTEL = 5600,
+    OpConstFunctionPointerINTEL = 5600,
     OpFunctionPointerCallINTEL = 5601,
+    OpAsmTargetINTEL = 5609,
+    OpAsmINTEL = 5610,
+    OpAsmCallINTEL = 5611,
     OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
     OpMemberDecorateString = 5633,
@@ -1600,7 +1665,12 @@
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpVariableLengthArrayINTEL = 5818,
+    OpSaveMemoryINTEL = 5819,
+    OpRestoreMemoryINTEL = 5820,
     OpLoopControlINTEL = 5887,
+    OpPtrCastToCrossWorkgroupINTEL = 5934,
+    OpCrossWorkgroupCastToPtrINTEL = 5938,
     OpReadPipeBlockingINTEL = 5946,
     OpWritePipeBlockingINTEL = 5947,
     OpFPGARegINTEL = 5949,
@@ -1622,6 +1692,10 @@
     OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
     OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpAtomicFAddEXT = 6035,
+    OpTypeBufferSurfaceINTEL = 6086,
+    OpTypeStructContinuedINTEL = 6090,
+    OpConstantCompositeContinuedINTEL = 6091,
+    OpSpecConstantCompositeContinuedINTEL = 6092,
 }
 
 
diff --git a/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.cpp b/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.cpp
index 2118678..e5b1e3e 100644
--- a/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.cpp
+++ b/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.cpp
@@ -61,6 +61,8 @@
 EnumValues ImageOperandsParams;
 EnumValues FPFastMathParams;
 EnumValues FPRoundingModeParams;
+EnumValues FPDenormModeParams;
+EnumValues FPOperationModeParams;
 EnumValues LinkageTypeParams;
 EnumValues DecorationParams;
 EnumValues BuiltInParams;
@@ -178,6 +180,10 @@
             type = OperandImageChannelDataType;
         } else if (operandKind == "FPRoundingMode") {
             type = OperandFPRoundingMode;
+        } else if (operandKind == "FPDenormMode") {
+            type = OperandFPDenormMode;
+        } else if (operandKind == "FPOperationMode") {
+            type = OperandFPOperationMode;
         } else if (operandKind == "LinkageType") {
             type = OperandLinkageType;
         } else if (operandKind == "AccessQualifier") {
@@ -452,6 +458,10 @@
             establishOperandClass(enumName, OperandFPFastMath, &FPFastMathParams, operandEnum, category);
         } else if (enumName == "FPRoundingMode") {
             establishOperandClass(enumName, OperandFPRoundingMode, &FPRoundingModeParams, operandEnum, category);
+        } else if (enumName == "FPDenormMode") {
+            establishOperandClass(enumName, OperandFPDenormMode, &FPDenormModeParams, operandEnum, category);
+        } else if (enumName == "FPOperationMode") {
+            establishOperandClass(enumName, OperandFPOperationMode, &FPOperationModeParams, operandEnum, category);
         } else if (enumName == "LinkageType") {
             establishOperandClass(enumName, OperandLinkageType, &LinkageTypeParams, operandEnum, category);
         } else if (enumName == "FunctionParameterAttribute") {
diff --git a/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.h b/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.h
index 72c7cde..572b872 100644
--- a/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.h
+++ b/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.h
@@ -69,6 +69,8 @@
     OperandImageOperands,
     OperandFPFastMath,
     OperandFPRoundingMode,
+    OperandFPDenormMode,
+    OperandFPOperationMode,
     OperandLinkageType,
     OperandAccessQualifier,
     OperandFuncParamAttr,
diff --git a/third_party/SPIRV-Tools/BUILD.gn b/third_party/SPIRV-Tools/BUILD.gn
index 2387fc6..845eb29 100644
--- a/third_party/SPIRV-Tools/BUILD.gn
+++ b/third_party/SPIRV-Tools/BUILD.gn
@@ -539,8 +539,6 @@
     "source/opt/dead_insert_elim_pass.h",
     "source/opt/dead_variable_elimination.cpp",
     "source/opt/dead_variable_elimination.h",
-    "source/opt/decompose_initialized_variables_pass.cpp",
-    "source/opt/decompose_initialized_variables_pass.h",
     "source/opt/decoration_manager.cpp",
     "source/opt/decoration_manager.h",
     "source/opt/debug_info_manager.cpp",
@@ -578,8 +576,6 @@
     "source/opt/freeze_spec_constant_value_pass.h",
     "source/opt/function.cpp",
     "source/opt/function.h",
-    "source/opt/generate_webgpu_initializers_pass.cpp",
-    "source/opt/generate_webgpu_initializers_pass.h",
     "source/opt/graphics_robust_access_pass.cpp",
     "source/opt/graphics_robust_access_pass.h",
     "source/opt/if_conversion.cpp",
@@ -608,8 +604,6 @@
     "source/opt/ir_loader.cpp",
     "source/opt/ir_loader.h",
     "source/opt/iterator.h",
-    "source/opt/legalize_vector_shuffle_pass.cpp",
-    "source/opt/legalize_vector_shuffle_pass.h",
     "source/opt/licm_pass.cpp",
     "source/opt/licm_pass.h",
     "source/opt/local_access_chain_convert_pass.cpp",
@@ -680,14 +674,10 @@
     "source/opt/set_spec_constant_default_value_pass.h",
     "source/opt/simplification_pass.cpp",
     "source/opt/simplification_pass.h",
-    "source/opt/split_invalid_unreachable_pass.cpp",
-    "source/opt/split_invalid_unreachable_pass.h",
     "source/opt/ssa_rewrite_pass.cpp",
     "source/opt/ssa_rewrite_pass.h",
     "source/opt/strength_reduction_pass.cpp",
     "source/opt/strength_reduction_pass.h",
-    "source/opt/strip_atomic_counter_memory_pass.cpp",
-    "source/opt/strip_atomic_counter_memory_pass.h",
     "source/opt/strip_debug_info_pass.cpp",
     "source/opt/strip_debug_info_pass.h",
     "source/opt/strip_reflect_info_pass.cpp",
diff --git a/third_party/SPIRV-Tools/CHANGES b/third_party/SPIRV-Tools/CHANGES
index 3c81249..d7a49f7 100644
--- a/third_party/SPIRV-Tools/CHANGES
+++ b/third_party/SPIRV-Tools/CHANGES
@@ -1,7 +1,96 @@
 Revision history for SPIRV-Tools
 
-v2020.6 2020-09-24
- - Start SPIRV-Tools v2020.6
+v2020.7-dev 2020-12-07
+ - Start v2020.7-dev
+
+v2020.6 2020-12-07
+ - General
+    CMake: Add SPIRV_TOOLS_BUILD_STATIC flag (#3910)
+ - Disassembler
+    Add some context comments to disassembly. (#3847)
+ - Optimizer
+   - Take new (raytracing) termination instructions into account. (#4050)
+   - Do run DCE if SPV_KHR_ray_query is used. (#4047)
+   - Handle 8-bit index in elim dead member (#4043)
+   - Add texel buffer out-of-bounds checking instrumentation (#4038)
+   - Update MeshShadingNV dependencies (and land Ray tracing updates) (#4028)
+   - Fix buffer oob instrumentation for matrix refs (#4025)
+   - Fix SSA re-writing in the presence of variable pointers. (#4010)
+   - Add support to prevent functions from being inlined if they have
+     DontInline flag (#3858)
+   - Add SPV_EXT_shader_image_int64 (#3852)
+   - Support SPV_KHR_fragment_shading_rate (#3943)
+   - Fix use-after-move in val/validate.cpp (#3848)
+ - Debug Info
+   - properly preserve DebugValue indexes operand (#4022)
+   - Add DebugValue for invisible store in single_store_elim (#4002)
+   - Propagate OpLine to all applied instructions in spirv-opt (#3951)
+   - Add DebugValue for DebugDecl invisible to value assignment (#3973)
+   - Add DebugValue for function param regardless of scope (#3923)
+   - Debug info preservation in convert-local-access-chains pass (#3835)
+   - Debug info preservation in redundancy-elimination pass (#3839)
+   - Debug info preservation in if-conversion pass (#3861)
+ - Validator
+   - Add validation support for the ray tracing built-in variables (#4041)
+   - Use less stack space when validating Vulkan builtins (#4019)
+   - Fix SPV_KHR_fragment_shading_rate VUID label (#4014)
+   - Label Layer and ViewportIndex VUIDs (#4013)
+   - Allow the ViewportIndex and Layer built-ins on SPIR-V 1.5 (#3986)
+   - Fix validation of OpPhi instructions (#3919)
+ - Fuzz
+   - Fix facts arising from CompositeConstruct (#4034)
+   - Do not flatten conditionals that create synonyms (#4030)
+   - Add support for reining in rogue fuzzer passes (#3987)
+   - Fix assertion failure in FuzzerPassAddCompositeExtract (#3995)
+   - Fix invalid equation facts (#4009)
+   - Fix bugs in TransformationFlattenConditionalBranch (#4006)
+   - Fix bug related to transformation applicability (#3990)
+   - Add expand vector reduction transformation (#3869)
+   - Add FuzzerPassAddCompositeExtract (#3904)
+   - Fix mismatch with shrinker step limit (#3985)
+   - Fix off-by-one error in replayer (#3982)
+   - Get order right for OpSelect arguments (#3974)
+   - Do not add synonym-creating loops in dead blocks (#3975)
+   - Skip OpTypeSampledImage when propagating up (#3976)
+   - Pass OpUndef in function call if needed (#3978)
+   - Fix off-by-one in TransformationCompositeConstruct (#3979)
+   - Tolerate absent ids in data synonym fact management (#3966)
+   - Fix to id availability (#3971)
+   - Fix operand types (#3962)
+   - Don't flatten conditional if condition is irrelevant (#3944)
+   - Do not produce OpPhis of type OpTypeSampledImage (#3964)
+   - Restrict fuzzer pass to reachable blocks (#3970)
+   - Handle more types when extending OpPhi instructions (#3969)
+   - Skip early terminator wrappers when merging returns (#3968)
+   - Avoid irrelevant constants in synonym-creating loops (#3967)
+   - Skip dead blocks in FuzzerPassAddOpPhiSynonyms (#3965)
+   - Avoid the type manager when looking for struct types (#3963)
+   - Fix to TransformationDuplicateRegionWithSelection (#3941)
+   - Skip OpFunction when replacing irrelevant ids (#3932)
+   - Use component-wise selectors when flattening conditional branches (#3921)
+   - Avoid void struct member when outlining functions (#3936)
+   - Do not allow Block-decorated structs when adding parameters (#3931)
+   - Fix to operand id type (#3937)
+   - Handle dead blocks in TransformationEquationInstruction (#3933)
+   - Do not allow sampled image load when flattening conditionals (#3930)
+   - Take care of OpPhi instructions when inlining (#3939)
+   - Fix to TransformationInlineFunction (#3913)
+   - Wrap early terminators before merging returns (#3925)
+   - Lower probability of adding bit instruction synonyms (#3917)
+   - Fix handling of OpPhi in FlattenConditionalBranch (#3916)
+   - Avoid creating blocks without parents (#3908)
+   - Do not allow creation of constants of block-decorated structs (#3903)
+   - Fixes related to irrelevant ids (#3901)
+   - Fix to transformation that adds a synonym via a loop (#3898)
+   - Fix to duplicate region with selection (#3896)
+   - Do not expose synonym facts for non-existent ids (#3891)
+   - Do not add synonyms involving irrelevant ids (#3890)
+   - Do not replace irrelevant ids that are not in blocks (#3892)
+   - Wrap OpKill and similar in function calls (#3884)
+   - Integrate spirv-reduce with shrinker (#3849)
+   - Report fresh ids in transformations (#3856)
+   - Support OpNot bit instruction case (#3841)
+   - Return IR and transformation context after replay (#3846)
 
 v2020.5 2020-09-22
  - General
diff --git a/third_party/SPIRV-Tools/DEPS b/third_party/SPIRV-Tools/DEPS
index 350cfb4..3762681 100644
--- a/third_party/SPIRV-Tools/DEPS
+++ b/third_party/SPIRV-Tools/DEPS
@@ -6,7 +6,7 @@
   'effcee_revision': '2ec8f8738118cc483b67c04a759fee53496c5659',
   'googletest_revision': '3af06fe1664d30f98de1e78c53a7087e842a2547',
   're2_revision': 'ca11026a032ce2a3de4b3c389ee53d2bdc8794d6',
-  'spirv_headers_revision': '4de110ce1c78fda37932c735ef7f747e6f6cbee8',
+  'spirv_headers_revision': 'f027d53ded7e230e008d37c8b47ede7cd308e19d',
 }
 
 deps = {
diff --git a/third_party/SPIRV-Tools/README.md b/third_party/SPIRV-Tools/README.md
index 44f582f..3637305 100644
--- a/third_party/SPIRV-Tools/README.md
+++ b/third_party/SPIRV-Tools/README.md
@@ -136,7 +136,6 @@
   * Loop-invariant code motion
   * Loop unroll
 * Other
-  * Generate WebGPU initializers
   * Graphics robust access
   * Upgrade memory model to VulkanKHR
 
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp b/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp
index 9c01cb6..2b47a56 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp
+++ b/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp
@@ -171,6 +171,10 @@
 static const int kInstErrorBindlessUninit = 1;
 static const int kInstErrorBuffAddrUnallocRef = 2;
 static const int kInstErrorBindlessBuffOOB = 3;
+static const int kInstErrorBuffOOBUniform = 4;
+static const int kInstErrorBuffOOBStorage = 5;
+static const int kInstErrorBuffOOBUniformTexel = 6;
+static const int kInstErrorBuffOOBStorageTexel = 7;
 
 // Direct Input Buffer Offsets
 //
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
index a0114c3..201ee58 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
+++ b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
@@ -260,6 +260,11 @@
   SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION,                     // Sec 3.6
   SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY,               // Sec 3.7
 
+  // The following are concrete enum types from SPV_INTEL_float_controls2
+  // https://github.com/intel/llvm/blob/39fa9b0cbfbae88327118990a05c5b387b56d2ef/sycl/doc/extensions/SPIRV/SPV_INTEL_float_controls2.asciidoc
+  SPV_OPERAND_TYPE_FPDENORM_MODE,     // Sec 3.17 FP Denorm Mode
+  SPV_OPERAND_TYPE_FPOPERATION_MODE,  // Sec 3.18 FP Operation Mode
+
   // This is a sentinel value, and does not represent an operand type.
   // It should come last.
   SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,
@@ -482,7 +487,7 @@
   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.1 latest revision.
-  SPV_ENV_WEBGPU_0,       // Work in progress WebGPU 1.0.
+  SPV_ENV_WEBGPU_0,       // DEPRECATED, may be removed in the future.
   SPV_ENV_UNIVERSAL_1_4,  // SPIR-V 1.4 latest revision, no other restrictions.
 
   // Vulkan 1.1 with VK_KHR_spirv_1_4, i.e. SPIR-V 1.4 binary.
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp b/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp
index f12774d..1683d07 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp
+++ b/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp
@@ -68,11 +68,6 @@
   // The instance will have an empty message consumer, which ignores all
   // messages from the library. Use SetMessageConsumer() to supply a consumer
   // if messages are of concern.
-  //
-  // For collections of passes that are meant to transform the input into
-  // another execution environment, then the source environment should be
-  // supplied. e.g. for VulkanToWebGPUPasses the environment should be
-  // SPV_ENV_VULKAN_1_1 not SPV_ENV_WEBGPU_0.
   explicit Optimizer(spv_target_env env);
 
   // Disables copy/move constructor/assignment operations.
@@ -106,16 +101,6 @@
   // from time to time.
   Optimizer& RegisterSizePasses();
 
-  // Registers passes that have been prescribed for converting from Vulkan to
-  // WebGPU. This sequence of passes is subject to constant review and will
-  // change from time to time.
-  Optimizer& RegisterVulkanToWebGPUPasses();
-
-  // Registers passes that have been prescribed for converting from WebGPU to
-  // Vulkan. This sequence of passes is subject to constant review and will
-  // change from time to time.
-  Optimizer& RegisterWebGPUToVulkanPasses();
-
   // Registers passes that attempt to legalize the generated code.
   //
   // Note: this recipe is specially designed for legalizing SPIR-V. It should be
@@ -238,13 +223,6 @@
 // A null pass does nothing to the SPIR-V module to be optimized.
 Optimizer::PassToken CreateNullPass();
 
-// Creates a strip-atomic-counter-memory pass.
-// A strip-atomic-counter-memory pass removes all usages of the
-// AtomicCounterMemory bit in Memory Semantics bitmasks. This bit is a no-op in
-// Vulkan, so isn't needed in that env. And the related capability is not
-// allowed in WebGPU, so it is not allowed in that env.
-Optimizer::PassToken CreateStripAtomicCounterMemoryPass();
-
 // Creates a strip-debug-info pass.
 // A strip-debug-info pass removes all debug instructions (as documented in
 // Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.
@@ -747,12 +725,16 @@
 // The instrumentation will read and write buffers in debug
 // descriptor set |desc_set|. It will write |shader_id| in each output record
 // to identify the shader module which generated the record.
-// |input_length_enable| controls instrumentation of runtime descriptor array
-// references, and |input_init_enable| controls instrumentation of descriptor
-// initialization checking, both of which require input buffer support.
+// |desc_length_enable| controls instrumentation of runtime descriptor array
+// references, |desc_init_enable| controls instrumentation of descriptor
+// initialization checking, and |buff_oob_enable| controls instrumentation
+// of storage and uniform buffer bounds checking, all of which require input
+// buffer support. |texbuff_oob_enable| controls instrumentation of texel
+// buffers, which does not require input buffer support.
 Optimizer::PassToken CreateInstBindlessCheckPass(
-    uint32_t desc_set, uint32_t shader_id, bool input_length_enable = false,
-    bool input_init_enable = false, bool input_buff_oob_enable = false);
+    uint32_t desc_set, uint32_t shader_id, bool desc_length_enable = false,
+    bool desc_init_enable = false, bool buff_oob_enable = false,
+    bool texbuff_oob_enable = false);
 
 // Create a pass to instrument physical buffer address checking
 // This pass instruments all physical buffer address references to check that
@@ -798,30 +780,11 @@
 // where an instruction is moved into a more deeply nested construct.
 Optimizer::PassToken CreateCodeSinkingPass();
 
-// Create a pass to adds initializers for OpVariable calls that require them
-// in WebGPU. Currently this pass naively initializes variables that are
-// missing an initializer with a null value. In the future it may initialize
-// variables to the first value stored in them, if that is a constant.
-Optimizer::PassToken CreateGenerateWebGPUInitializersPass();
-
 // Create a pass to fix incorrect storage classes.  In order to make code
 // generation simpler, DXC may generate code where the storage classes do not
 // match up correctly.  This pass will fix the errors that it can.
 Optimizer::PassToken CreateFixStorageClassPass();
 
-// Create a pass to legalize OpVectorShuffle operands going into WebGPU. WebGPU
-// forbids using 0xFFFFFFFF, which indicates an undefined result, so this pass
-// converts those literals to 0.
-Optimizer::PassToken CreateLegalizeVectorShufflePass();
-
-// Create a pass to decompose initialized variables into a seperate variable
-// declaration and an initial store.
-Optimizer::PassToken CreateDecomposeInitializedVariablesPass();
-
-// Create a pass to attempt to split up invalid unreachable merge-blocks and
-// continue-targets to legalize for WebGPU.
-Optimizer::PassToken CreateSplitInvalidUnreachablePass();
-
 // Creates a graphics robust access pass.
 //
 // This pass injects code to clamp indexed accesses to buffers and internal
diff --git a/third_party/SPIRV-Tools/kokoro/android/build.sh b/third_party/SPIRV-Tools/kokoro/android/build.sh
old mode 100644
new mode 100755
index c05c139..22c9117
--- a/third_party/SPIRV-Tools/kokoro/android/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/android/build.sh
@@ -20,33 +20,5 @@
 # Display commands being run.
 set -x
 
-BUILD_ROOT=$PWD
-SRC=$PWD/github/SPIRV-Tools
-TARGET_ARCH="armeabi-v7a with NEON"
-export ANDROID_NDK=/opt/android-ndk-r15c
-
-# Get NINJA.
-wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
-unzip -q ninja-linux.zip
-export PATH="$PWD:$PATH"
-git clone --depth=1 https://github.com/taka-no-me/android-cmake.git android-cmake
-export TOOLCHAIN_PATH=$PWD/android-cmake/android.toolchain.cmake
-
-
-cd $SRC
-git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
-git clone https://github.com/google/googletest          external/googletest
-cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
-git clone --depth=1 https://github.com/google/effcee              external/effcee
-git clone --depth=1 https://github.com/google/re2                 external/re2
-
-mkdir build && cd $SRC/build
-
-# Invoke the build.
-BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
-echo $(date): Starting build...
-cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=android-14 -DANDROID_ABI="armeabi-v7a with NEON" -DSPIRV_SKIP_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_PATH -GNinja -DANDROID_NDK=$ANDROID_NDK ..
-
-echo $(date): Build everything...
-ninja
-echo $(date): Build completed.
+SCRIPT_DIR=`dirname "$BASH_SOURCE"`
+source $SCRIPT_DIR/../scripts/linux/build.sh ASAN clang cmake-android-ndk
diff --git a/third_party/SPIRV-Tools/kokoro/linux-clang-asan/build.sh b/third_party/SPIRV-Tools/kokoro/linux-clang-asan/build.sh
old mode 100644
new mode 100755
index 8f86e6e..5cca362
--- a/third_party/SPIRV-Tools/kokoro/linux-clang-asan/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/linux-clang-asan/build.sh
@@ -21,4 +21,4 @@
 set -x
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
-source $SCRIPT_DIR/../scripts/linux/build.sh ASAN clang
+source $SCRIPT_DIR/../scripts/linux/build.sh ASAN clang cmake
diff --git a/third_party/SPIRV-Tools/kokoro/linux-clang-debug/build.sh b/third_party/SPIRV-Tools/kokoro/linux-clang-debug/build.sh
old mode 100644
new mode 100755
index 11b2968..785a6e3
--- a/third_party/SPIRV-Tools/kokoro/linux-clang-debug/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/linux-clang-debug/build.sh
@@ -21,4 +21,4 @@
 set -x
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
-source $SCRIPT_DIR/../scripts/linux/build.sh DEBUG clang
+source $SCRIPT_DIR/../scripts/linux/build.sh DEBUG clang cmake
diff --git a/third_party/SPIRV-Tools/kokoro/linux-clang-release-bazel/build.sh b/third_party/SPIRV-Tools/kokoro/linux-clang-release-bazel/build.sh
old mode 100644
new mode 100755
index 05a9bbb..238ef52
--- a/third_party/SPIRV-Tools/kokoro/linux-clang-release-bazel/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/linux-clang-release-bazel/build.sh
@@ -20,24 +20,5 @@
 # Display commands being run.
 set -x
 
-CC=clang
-CXX=clang++
-SRC=$PWD/github/SPIRV-Tools
-
-cd $SRC
-git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
-git clone https://github.com/google/googletest          external/googletest
-cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
-git clone --depth=1 https://github.com/google/effcee              external/effcee
-git clone --depth=1 https://github.com/google/re2                 external/re2
-
-gsutil cp gs://bazel/0.29.1/release/bazel-0.29.1-linux-x86_64 .
-chmod +x bazel-0.29.1-linux-x86_64
-
-echo $(date): Build everything...
-./bazel-0.29.1-linux-x86_64 build :all
-echo $(date): Build completed.
-
-echo $(date): Starting bazel test...
-./bazel-0.29.1-linux-x86_64 test :all
-echo $(date): Bazel test completed.
+SCRIPT_DIR=`dirname "$BASH_SOURCE"`
+source $SCRIPT_DIR/../scripts/linux/build.sh RELEASE clang bazel
diff --git a/third_party/SPIRV-Tools/kokoro/linux-clang-release/build.sh b/third_party/SPIRV-Tools/kokoro/linux-clang-release/build.sh
old mode 100644
new mode 100755
index 4764331..6a9e013
--- a/third_party/SPIRV-Tools/kokoro/linux-clang-release/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/linux-clang-release/build.sh
@@ -21,4 +21,4 @@
 set -x
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
-source $SCRIPT_DIR/../scripts/linux/build.sh RELEASE clang
+source $SCRIPT_DIR/../scripts/linux/build.sh RELEASE clang cmake
diff --git a/third_party/SPIRV-Tools/kokoro/linux-gcc-debug/build.sh b/third_party/SPIRV-Tools/kokoro/linux-gcc-debug/build.sh
old mode 100644
new mode 100755
index 3ef1e25..c60447e
--- a/third_party/SPIRV-Tools/kokoro/linux-gcc-debug/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/linux-gcc-debug/build.sh
@@ -21,4 +21,4 @@
 set -x
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
-source $SCRIPT_DIR/../scripts/linux/build.sh DEBUG gcc
+source $SCRIPT_DIR/../scripts/linux/build.sh DEBUG gcc cmake
diff --git a/third_party/SPIRV-Tools/kokoro/linux-gcc-release/build.sh b/third_party/SPIRV-Tools/kokoro/linux-gcc-release/build.sh
old mode 100644
new mode 100755
index 3e97d8d..441ab72
--- a/third_party/SPIRV-Tools/kokoro/linux-gcc-release/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/linux-gcc-release/build.sh
@@ -21,4 +21,4 @@
 set -x
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
-source $SCRIPT_DIR/../scripts/linux/build.sh RELEASE gcc
+source $SCRIPT_DIR/../scripts/linux/build.sh RELEASE gcc cmake
diff --git a/third_party/SPIRV-Tools/kokoro/ndk-build/build.sh b/third_party/SPIRV-Tools/kokoro/ndk-build/build.sh
old mode 100644
new mode 100755
index f1f167d..89c5565
--- a/third_party/SPIRV-Tools/kokoro/ndk-build/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/ndk-build/build.sh
@@ -20,38 +20,5 @@
 # Display commands being run.
 set -x
 
-BUILD_ROOT=$PWD
-SRC=$PWD/github/SPIRV-Tools
-
-# Get NINJA.
-wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
-unzip -q ninja-linux.zip
-export PATH="$PWD:$PATH"
-
-# NDK Path
-export ANDROID_NDK=/opt/android-ndk-r15c
-
-# Get the dependencies.
-cd $SRC
-git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
-git clone https://github.com/google/googletest          external/googletest
-cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
-git clone --depth=1 https://github.com/google/effcee              external/effcee
-git clone --depth=1 https://github.com/google/re2                 external/re2
-
-mkdir build && cd $SRC/build
-mkdir libs
-mkdir app
-
-# Invoke the build.
-BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
-echo $(date): Starting ndk-build ...
-$ANDROID_NDK/ndk-build \
-  -C $SRC/android_test \
-  NDK_PROJECT_PATH=.   \
-  NDK_LIBS_OUT=./libs  \
-  NDK_APP_OUT=./app    \
-  -j8
-
-echo $(date): ndk-build completed.
-
+SCRIPT_DIR=`dirname "$BASH_SOURCE"`
+source $SCRIPT_DIR/../scripts/linux/build.sh ASAN clang android-ndk-build
diff --git a/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh b/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh
new file mode 100755
index 0000000..ba21698
--- /dev/null
+++ b/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh
@@ -0,0 +1,196 @@
+#!/bin/bash
+# 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.
+#
+# Linux Build Script.
+
+# Fail on any error.
+set -e
+# Display commands being run.
+set -x
+
+. /bin/using.sh # Declare the bash `using` function for configuring toolchains.
+
+if [ $COMPILER = "clang" ]; then
+  using clang-10.0.0
+elif [ $COMPILER = "gcc" ]; then
+  using gcc-9
+fi
+
+cd $ROOT_DIR
+
+function clone_if_missing() {
+  url=$1
+  dir=$2
+  if [[ ! -d "$dir" ]]; then
+    git clone ${@:3} "$url" "$dir"
+  fi
+}
+
+function clean_dir() {
+  dir=$1
+  if [[ -d "$dir" ]]; then
+    rm -fr "$dir"
+  fi
+  mkdir "$dir"
+}
+
+clone_if_missing https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers --depth=1
+clone_if_missing https://github.com/google/googletest          external/googletest
+pushd external/googletest; git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7; popd
+clone_if_missing https://github.com/google/effcee              external/effcee        --depth=1
+clone_if_missing https://github.com/google/re2                 external/re2           --depth=1
+clone_if_missing https://github.com/protocolbuffers/protobuf   external/protobuf      --branch v3.13.0
+
+if [ $TOOL = "cmake" ]; then
+  using cmake-3.17.2
+  using ninja-1.10.0
+
+  # Possible configurations are:
+  # ASAN, COVERAGE, RELEASE, DEBUG, DEBUG_EXCEPTION, RELEASE_MINGW
+  BUILD_TYPE="Debug"
+  if [ $CONFIG = "RELEASE" ] || [ $CONFIG = "RELEASE_MINGW" ]; then
+    BUILD_TYPE="RelWithDebInfo"
+  fi
+
+  SKIP_TESTS="False"
+  ADDITIONAL_CMAKE_FLAGS=""
+  if [ $CONFIG = "ASAN" ]; then
+    ADDITIONAL_CMAKE_FLAGS="-DSPIRV_USE_SANITIZER=address,bounds,null"
+    [ $COMPILER = "clang" ] || { echo "$CONFIG requires clang"; exit 1; }
+  elif [ $CONFIG = "COVERAGE" ]; then
+    ADDITIONAL_CMAKE_FLAGS="-DENABLE_CODE_COVERAGE=ON"
+    SKIP_TESTS="True"
+  elif [ $CONFIG = "DEBUG_EXCEPTION" ]; then
+    ADDITIONAL_CMAKE_FLAGS="-DDISABLE_EXCEPTIONS=ON -DDISABLE_RTTI=ON"
+  elif [ $CONFIG = "RELEASE_MINGW" ]; then
+    ADDITIONAL_CMAKE_FLAGS="-Dgtest_disable_pthreads=ON -DCMAKE_TOOLCHAIN_FILE=$SRC/cmake/linux-mingw-toolchain.cmake"
+    SKIP_TESTS="True"
+  fi
+
+  clean_dir "$ROOT_DIR/build"
+  cd "$ROOT_DIR/build"
+
+  # Invoke the build.
+  BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
+  echo $(date): Starting build...
+  cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DRE2_BUILD_TESTING=OFF -DSPIRV_BUILD_FUZZER=ON $ADDITIONAL_CMAKE_FLAGS ..
+
+  echo $(date): Build everything...
+  ninja
+  echo $(date): Build completed.
+
+  if [ $CONFIG = "COVERAGE" ]; then
+    echo $(date): Check coverage...
+    ninja report-coverage
+    echo $(date): Check coverage completed.
+  fi
+
+  echo $(date): Starting ctest...
+  if [ $SKIP_TESTS = "False" ]; then
+    ctest -j4 --output-on-failure --timeout 300
+  fi
+  echo $(date): ctest completed.
+
+  # Package the build.
+  ninja install
+  cd $KOKORO_ARTIFACTS_DIR
+  tar czf install.tgz install
+elif [ $TOOL = "cmake-smoketest" ]; then
+  using cmake-3.17.2
+  using ninja-1.10.0
+
+  # Get shaderc.
+  SHADERC_DIR=/tmp/shaderc
+  clean_dir "$SHADERC_DIR"
+  cd $SHADERC_DIR
+  git clone https://github.com/google/shaderc.git .
+  cd $SHADERC_DIR/third_party
+
+  # Get shaderc dependencies. Link the appropriate SPIRV-Tools.
+  git clone https://github.com/google/googletest.git
+  git clone https://github.com/KhronosGroup/glslang.git
+  ln -s $ROOT_DIR spirv-tools
+  git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers
+  git clone https://github.com/google/re2
+  git clone https://github.com/google/effcee
+
+  cd $SHADERC_DIR
+  mkdir build
+  cd $SHADERC_DIR/build
+
+  # Invoke the build.
+  echo $(date): Starting build...
+  cmake -GNinja -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE="Release" ..
+
+  echo $(date): Build glslang...
+  ninja glslangValidator
+
+  echo $(date): Build everything...
+  ninja
+  echo $(date): Build completed.
+
+  echo $(date): Check Shaderc for copyright notices...
+  ninja check-copyright
+
+  echo $(date): Starting ctest...
+  ctest --output-on-failure -j4
+  echo $(date): ctest completed.
+elif [ $TOOL = "cmake-android-ndk" ]; then
+  using cmake-3.17.2
+  using ndk-r21d
+  using ninja-1.10.0
+
+  clean_dir "$ROOT_DIR/build"
+  cd "$ROOT_DIR/build"
+
+  echo $(date): Starting build...
+  cmake -DCMAKE_BUILD_TYPE=Release \
+        -DANDROID_NATIVE_API_LEVEL=android-16 \
+        -DANDROID_ABI="armeabi-v7a with NEON" \
+        -DSPIRV_SKIP_TESTS=ON \
+        -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
+        -GNinja \
+        -DANDROID_NDK=$ANDROID_NDK \
+        ..
+
+  echo $(date): Build everything...
+  ninja
+  echo $(date): Build completed.
+elif [ $TOOL = "android-ndk-build" ]; then
+  using ndk-r21d
+
+  clean_dir "$ROOT_DIR/build"
+  cd "$ROOT_DIR/build"
+
+  echo $(date): Starting ndk-build ...
+  $ANDROID_NDK_HOME/ndk-build \
+    -C $ROOT_DIR/android_test \
+    NDK_PROJECT_PATH=. \
+    NDK_LIBS_OUT=./libs \
+    NDK_APP_OUT=./app \
+    -j4
+
+  echo $(date): ndk-build completed.
+elif [ $TOOL = "bazel" ]; then
+  using bazel-3.1.0
+
+  echo $(date): Build everything...
+  bazel build :all
+  echo $(date): Build completed.
+
+  echo $(date): Starting bazel test...
+  bazel test :all
+  echo $(date): Bazel test completed.
+fi
diff --git a/third_party/SPIRV-Tools/kokoro/scripts/linux/build.sh b/third_party/SPIRV-Tools/kokoro/scripts/linux/build.sh
index 347f353..4731ebd 100644
--- a/third_party/SPIRV-Tools/kokoro/scripts/linux/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/scripts/linux/build.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright (c) 2018 Google LLC.
+# Copyright (c) 2021 Google LLC.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -17,89 +17,38 @@
 
 # Fail on any error.
 set -e
-# Display commands being run.
-set -x
 
-BUILD_ROOT=$PWD
-SRC=$PWD/github/SPIRV-Tools
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )"
+ROOT_DIR="$( cd "${SCRIPT_DIR}/../../.." >/dev/null 2>&1 && pwd )"
+
 CONFIG=$1
 COMPILER=$2
-
-SKIP_TESTS="False"
-BUILD_TYPE="Debug"
-
-CMAKE_C_CXX_COMPILER=""
-if [ $COMPILER = "clang" ]
-then
-  PATH=/usr/lib/llvm-3.8/bin:$PATH
-  CMAKE_C_CXX_COMPILER="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
-fi
-
-# Possible configurations are:
-# ASAN, COVERAGE, RELEASE, DEBUG, DEBUG_EXCEPTION, RELEASE_MINGW
-
-if [ $CONFIG = "RELEASE" ] || [ $CONFIG = "RELEASE_MINGW" ]
-then
-  BUILD_TYPE="RelWithDebInfo"
-fi
-
-ADDITIONAL_CMAKE_FLAGS=""
-if [ $CONFIG = "ASAN" ]
-then
-  ADDITIONAL_CMAKE_FLAGS="-DSPIRV_USE_SANITIZER=address,bounds,null"
-  [ $COMPILER = "clang" ] || { echo "$CONFIG requires clang"; exit 1; }
-elif [ $CONFIG = "COVERAGE" ]
-then
-  ADDITIONAL_CMAKE_FLAGS="-DENABLE_CODE_COVERAGE=ON"
-  SKIP_TESTS="True"
-elif [ $CONFIG = "DEBUG_EXCEPTION" ]
-then
-  ADDITIONAL_CMAKE_FLAGS="-DDISABLE_EXCEPTIONS=ON -DDISABLE_RTTI=ON"
-elif [ $CONFIG = "RELEASE_MINGW" ]
-then
-  ADDITIONAL_CMAKE_FLAGS="-Dgtest_disable_pthreads=ON -DCMAKE_TOOLCHAIN_FILE=$SRC/cmake/linux-mingw-toolchain.cmake"
-  SKIP_TESTS="True"
-fi
-
-# Get NINJA.
-wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
-unzip -q ninja-linux.zip
-export PATH="$PWD:$PATH"
-
-cd $SRC
-git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
-git clone https://github.com/google/googletest          external/googletest
-cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
-git clone --depth=1 https://github.com/google/effcee              external/effcee
-git clone --depth=1 https://github.com/google/re2                 external/re2
-git clone --depth=1 --branch v3.13.0 https://github.com/protocolbuffers/protobuf external/protobuf
-
-mkdir build && cd $SRC/build
-
-# Invoke the build.
+TOOL=$3
 BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
-echo $(date): Starting build...
-cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DRE2_BUILD_TESTING=OFF -DSPIRV_BUILD_FUZZER=ON $ADDITIONAL_CMAKE_FLAGS $CMAKE_C_CXX_COMPILER ..
 
-echo $(date): Build everything...
-ninja
-echo $(date): Build completed.
+docker run --rm -i \
+  --volume "${ROOT_DIR}:${ROOT_DIR}" \
+  --volume "${KOKORO_ARTIFACTS_DIR}:${KOKORO_ARTIFACTS_DIR}" \
+  --workdir "${ROOT_DIR}" \
+  --env SCRIPT_DIR=${SCRIPT_DIR} \
+  --env ROOT_DIR=${ROOT_DIR} \
+  --env CONFIG=${CONFIG} \
+  --env COMPILER=${COMPILER} \
+  --env TOOL=${TOOL} \
+  --env KOKORO_ARTIFACTS_DIR="${KOKORO_ARTIFACTS_DIR}" \
+  --env BUILD_SHA="${BUILD_SHA}" \
+  --entrypoint "${SCRIPT_DIR}/build-docker.sh" \
+  "gcr.io/shaderc-build/radial-build:latest"
 
-if [ $CONFIG = "COVERAGE" ]
-then
-  echo $(date): Check coverage...
-  ninja report-coverage
-  echo $(date): Check coverage completed.
-fi
 
-echo $(date): Starting ctest...
-if [ $SKIP_TESTS = "False" ]
-then
-  ctest -j4 --output-on-failure --timeout 300
-fi
-echo $(date): ctest completed.
+# chown the given directory to the current user, if it exists.
+# Docker creates files with the root user - this can upset the Kokoro artifact copier.
+function chown_dir() {
+  dir=$1
+  if [[ -d "$dir" ]]; then
+    sudo chown -R "$(id -u):$(id -g)" "$dir"
+  fi
+}
 
-# Package the build.
-ninja install
-cd $KOKORO_ARTIFACTS_DIR
-tar czf install.tgz install
+chown_dir "${ROOT_DIR}/build"
+chown_dir "${ROOT_DIR}/external"
diff --git a/third_party/SPIRV-Tools/kokoro/shaderc-smoketest/build.sh b/third_party/SPIRV-Tools/kokoro/shaderc-smoketest/build.sh
old mode 100644
new mode 100755
index 0856c9b..60c816d
--- a/third_party/SPIRV-Tools/kokoro/shaderc-smoketest/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/shaderc-smoketest/build.sh
@@ -18,54 +18,5 @@
 # Display commands being run.
 set -x
 
-BUILD_ROOT=$PWD
-GITHUB_DIR=$BUILD_ROOT/github
-
-SKIP_TESTS="False"
-BUILD_TYPE="Release"
-
-# Get NINJA.
-wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
-unzip -q ninja-linux.zip
-export PATH="$PWD:$PATH"
-
-# Get shaderc.
-cd $GITHUB_DIR
-git clone https://github.com/google/shaderc.git
-SHADERC_DIR=$GITHUB_DIR/shaderc
-cd $SHADERC_DIR/third_party
-
-# Get shaderc dependencies. Link the appropriate SPIRV-Tools.
-git clone https://github.com/google/googletest.git
-git clone https://github.com/KhronosGroup/glslang.git
-ln -s $GITHUB_DIR/SPIRV-Tools spirv-tools
-git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers
-git clone https://github.com/google/re2
-git clone https://github.com/google/effcee
-
-cd $SHADERC_DIR
-mkdir build
-cd $SHADERC_DIR/build
-
-# Invoke the build.
-BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
-echo $(date): Starting build...
-cmake -GNinja -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
-
-echo $(date): Build glslang...
-ninja glslangValidator
-
-echo $(date): Build everything...
-ninja
-echo $(date): Build completed.
-
-echo $(date): Check Shaderc for copyright notices...
-ninja check-copyright
-
-echo $(date): Starting ctest...
-if [ $SKIP_TESTS = "False" ]
-then
-  ctest --output-on-failure -j4
-fi
-echo $(date): ctest completed.
-
+SCRIPT_DIR=`dirname "$BASH_SOURCE"`
+source $SCRIPT_DIR/../scripts/linux/build.sh RELEASE gcc cmake-smoketest
diff --git a/third_party/SPIRV-Tools/source/binary.cpp b/third_party/SPIRV-Tools/source/binary.cpp
index 75a997d..7448721 100644
--- a/third_party/SPIRV-Tools/source/binary.cpp
+++ b/third_party/SPIRV-Tools/source/binary.cpp
@@ -655,7 +655,9 @@
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
-    case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: {
+    case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
+    case SPV_OPERAND_TYPE_FPDENORM_MODE:
+    case SPV_OPERAND_TYPE_FPOPERATION_MODE: {
       // A single word that is a plain enum value.
 
       // Map an optional operand type to its corresponding concrete type.
diff --git a/third_party/SPIRV-Tools/source/disassemble.cpp b/third_party/SPIRV-Tools/source/disassemble.cpp
index e763251..966a59c 100644
--- a/third_party/SPIRV-Tools/source/disassemble.cpp
+++ b/third_party/SPIRV-Tools/source/disassemble.cpp
@@ -326,7 +326,9 @@
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
-    case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: {
+    case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
+    case SPV_OPERAND_TYPE_FPDENORM_MODE:
+    case SPV_OPERAND_TYPE_FPOPERATION_MODE: {
       spv_operand_desc entry;
       if (grammar_.lookupOperand(operand.type, word, &entry))
         assert(false && "should have caught this earlier");
diff --git a/third_party/SPIRV-Tools/source/ext_inst.cpp b/third_party/SPIRV-Tools/source/ext_inst.cpp
index 3471ebe..795cb0f 100644
--- a/third_party/SPIRV-Tools/source/ext_inst.cpp
+++ b/third_party/SPIRV-Tools/source/ext_inst.cpp
@@ -89,7 +89,6 @@
     case SPV_ENV_UNIVERSAL_1_3:
     case SPV_ENV_VULKAN_1_1:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
-    case SPV_ENV_WEBGPU_0:
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_UNIVERSAL_1_5:
     case SPV_ENV_VULKAN_1_2:
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp
index 07758cd..2ac6259 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp
@@ -209,7 +209,7 @@
         return false;
       }
     } else {
-      auto duplicate_label = original_label_to_duplicate_label[block->id()];
+      auto duplicate_label = original_label_to_duplicate_label.at(block->id());
       // Each id assigned to labels in the region must be distinct and fresh.
       if (!duplicate_label ||
           !CheckIdIsFreshAndNotUsedByThisTransformation(
@@ -217,7 +217,7 @@
         return false;
       }
     }
-    for (auto instr : *block) {
+    for (auto& instr : *block) {
       if (!instr.HasResultId()) {
         continue;
       }
@@ -228,7 +228,7 @@
           return false;
         }
       } else {
-        auto duplicate_id = original_id_to_duplicate_id[instr.result_id()];
+        auto duplicate_id = original_id_to_duplicate_id.at(instr.result_id());
         // Id assigned to this result id in the region must be distinct and
         // fresh.
         if (!duplicate_id ||
@@ -237,43 +237,48 @@
           return false;
         }
       }
-      if (&instr == &*exit_block->tail() ||
-          fuzzerutil::IdIsAvailableBeforeInstruction(
-              ir_context, &*exit_block->tail(), instr.result_id())) {
-        // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3787):
-        //     Consider not adding OpPhi instructions for the pointers and
-        //     sampled images which are unused after the region, so that the
-        //     transformation could be still applicable.
-
-        // Using pointers with OpPhi requires capability VariablePointers.
-        if (ir_context->get_def_use_mgr()->GetDef(instr.type_id())->opcode() ==
-                SpvOpTypePointer &&
-            !ir_context->get_feature_mgr()->HasCapability(
-                SpvCapabilityVariablePointers)) {
-          return false;
-        }
-
-        // OpTypeSampledImage cannot be the result type of an OpPhi instruction.
-        if (ir_context->get_def_use_mgr()->GetDef(instr.type_id())->opcode() ==
-            SpvOpTypeSampledImage) {
-          return false;
-        }
-
-        // Every instruction with a result id available at the end of the region
-        // must be present in the map |original_id_to_phi_id|, unless overflow
-        // ids are present.
-        if (original_id_to_phi_id.count(instr.result_id()) == 0) {
-          if (!transformation_context.GetOverflowIdSource()->HasOverflowIds()) {
+      // If the instruction is available at the end of the region then we would
+      // like to be able to add an OpPhi instruction at the merge point of the
+      // duplicated region to capture the values computed by both duplicates of
+      // the instruction, so that this is also available after the region.  We
+      // do this not just for instructions that are already used after the
+      // region, but for all instructions so that the phi is available to future
+      // transformations.
+      if (AvailableAfterRegion(instr, exit_block, ir_context)) {
+        if (!ValidOpPhiArgument(instr, ir_context)) {
+          // The instruction cannot be used as an OpPhi argument.  This is a
+          // blocker if there are uses of the instruction after the region.
+          // Otherwise we can simply avoid generating an OpPhi for this
+          // instruction and its duplicate.
+          if (!ir_context->get_def_use_mgr()->WhileEachUser(
+                  &instr,
+                  [ir_context,
+                   &region_set](opt::Instruction* use_instr) -> bool {
+                    opt::BasicBlock* use_block =
+                        ir_context->get_instr_block(use_instr);
+                    return use_block == nullptr ||
+                           region_set.count(use_block) > 0;
+                  })) {
             return false;
           }
         } else {
-          auto phi_id = original_id_to_phi_id[instr.result_id()];
-          // Id assigned to this result id in the region must be distinct and
-          // fresh.
-          if (!phi_id ||
-              !CheckIdIsFreshAndNotUsedByThisTransformation(
-                  phi_id, ir_context, &ids_used_by_this_transformation)) {
-            return false;
+          // Every instruction with a result id available at the end of the
+          // region must be present in the map |original_id_to_phi_id|, unless
+          // overflow ids are present.
+          if (original_id_to_phi_id.count(instr.result_id()) == 0) {
+            if (!transformation_context.GetOverflowIdSource()
+                     ->HasOverflowIds()) {
+              return false;
+            }
+          } else {
+            auto phi_id = original_id_to_phi_id.at(instr.result_id());
+            // Id assigned to this result id in the region must be distinct and
+            // fresh.
+            if (!phi_id ||
+                !CheckIdIsFreshAndNotUsedByThisTransformation(
+                    phi_id, ir_context, &ids_used_by_this_transformation)) {
+              return false;
+            }
           }
         }
       }
@@ -329,7 +334,7 @@
           {block->id(),
            transformation_context->GetOverflowIdSource()->GetNextOverflowId()});
     }
-    for (auto instr : *block) {
+    for (auto& instr : *block) {
       if (!instr.HasResultId()) {
         continue;
       }
@@ -338,9 +343,8 @@
             {instr.result_id(), transformation_context->GetOverflowIdSource()
                                     ->GetNextOverflowId()});
       }
-      if (&instr == &*exit_block->tail() ||
-          fuzzerutil::IdIsAvailableBeforeInstruction(
-              ir_context, &*exit_block->tail(), instr.result_id())) {
+      if (AvailableAfterRegion(instr, exit_block, ir_context) &&
+          ValidOpPhiArgument(instr, ir_context)) {
         if (original_id_to_phi_id.count(instr.result_id()) == 0) {
           original_id_to_phi_id.insert(
               {instr.result_id(), transformation_context->GetOverflowIdSource()
@@ -414,12 +418,12 @@
     }
 
     fuzzerutil::UpdateModuleIdBound(
-        ir_context, original_label_to_duplicate_label[block->id()]);
+        ir_context, original_label_to_duplicate_label.at(block->id()));
 
     std::unique_ptr<opt::BasicBlock> duplicated_block =
         MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
             ir_context, SpvOpLabel, 0,
-            original_label_to_duplicate_label[block->id()],
+            original_label_to_duplicate_label.at(block->id()),
             opt::Instruction::OperandList()));
 
     for (auto& instr : *block) {
@@ -444,8 +448,10 @@
       duplicated_block->AddInstruction(
           std::unique_ptr<opt::Instruction>(cloned_instr));
 
-      fuzzerutil::UpdateModuleIdBound(
-          ir_context, original_id_to_duplicate_id[instr.result_id()]);
+      if (instr.HasResultId()) {
+        fuzzerutil::UpdateModuleIdBound(
+            ir_context, original_id_to_duplicate_id.at(instr.result_id()));
+      }
 
       // If an id from the original region was used in this instruction,
       // replace it with the value from |original_id_to_duplicate_id|.
@@ -456,8 +462,7 @@
            original_label_to_duplicate_label](uint32_t* op) {
             if (original_id_to_duplicate_id.count(*op) != 0) {
               *op = original_id_to_duplicate_id.at(*op);
-            }
-            if (original_label_to_duplicate_label.count(*op) != 0) {
+            } else if (original_label_to_duplicate_label.count(*op) != 0) {
               *op = original_label_to_duplicate_label.at(*op);
             }
           });
@@ -484,26 +489,27 @@
 
   for (auto& block : region_blocks) {
     for (auto& instr : *block) {
-      if (instr.result_id() != 0 &&
-          (&instr == &*exit_block->tail() ||
-           fuzzerutil::IdIsAvailableBeforeInstruction(
-               ir_context, &*exit_block->tail(), instr.result_id()))) {
-        // Add the OpPhi instruction for every result id that is
-        // available at the end of the region (the last instruction
-        // of the |exit_block|)
+      if (instr.result_id() == 0) {
+        continue;
+      }
+      if (AvailableAfterRegion(instr, exit_block, ir_context) &&
+          ValidOpPhiArgument(instr, ir_context)) {
+        // Add an OpPhi instruction for every result id that is available at
+        // the end of the region, as long as the result id is valid for use
+        // with OpPhi.
         merge_block->AddInstruction(MakeUnique<opt::Instruction>(
             ir_context, SpvOpPhi, instr.type_id(),
-            original_id_to_phi_id[instr.result_id()],
+            original_id_to_phi_id.at(instr.result_id()),
             opt::Instruction::OperandList({
                 {SPV_OPERAND_TYPE_ID, {instr.result_id()}},
                 {SPV_OPERAND_TYPE_ID, {exit_block->id()}},
                 {SPV_OPERAND_TYPE_ID,
-                 {original_id_to_duplicate_id[instr.result_id()]}},
+                 {original_id_to_duplicate_id.at(instr.result_id())}},
                 {SPV_OPERAND_TYPE_ID, {duplicated_exit_block->id()}},
             })));
 
         fuzzerutil::UpdateModuleIdBound(
-            ir_context, original_id_to_phi_id[instr.result_id()]);
+            ir_context, original_id_to_phi_id.at(instr.result_id()));
 
         // If the instruction has been remapped by an OpPhi, look
         // for all its uses outside of the region and outside of the
@@ -544,7 +550,8 @@
           {{SPV_OPERAND_TYPE_ID, {message_.condition_id()}},
            {SPV_OPERAND_TYPE_ID, {message_.entry_block_id()}},
            {SPV_OPERAND_TYPE_ID,
-            {original_label_to_duplicate_label[message_.entry_block_id()]}}})));
+            {original_label_to_duplicate_label.at(
+                message_.entry_block_id())}}})));
 
   // Move the terminator of |exit_block| to the end of
   // |merge_block|.
@@ -678,5 +685,38 @@
   return result;
 }
 
+bool TransformationDuplicateRegionWithSelection::AvailableAfterRegion(
+    const opt::Instruction& instr, opt::BasicBlock* exit_block,
+    opt::IRContext* ir_context) {
+  opt::Instruction* final_instruction_in_region = &*exit_block->tail();
+  return &instr == final_instruction_in_region ||
+         fuzzerutil::IdIsAvailableBeforeInstruction(
+             ir_context, final_instruction_in_region, instr.result_id());
+}
+
+bool TransformationDuplicateRegionWithSelection::ValidOpPhiArgument(
+    const opt::Instruction& instr, opt::IRContext* ir_context) {
+  opt::Instruction* instr_type =
+      ir_context->get_def_use_mgr()->GetDef(instr.type_id());
+
+  // It is invalid to apply OpPhi to void-typed values.
+  if (instr_type->opcode() == SpvOpTypeVoid) {
+    return false;
+  }
+
+  // Using pointers with OpPhi requires capability VariablePointers.
+  if (instr_type->opcode() == SpvOpTypePointer &&
+      !ir_context->get_feature_mgr()->HasCapability(
+          SpvCapabilityVariablePointers)) {
+    return false;
+  }
+
+  // OpTypeSampledImage cannot be the result type of an OpPhi instruction.
+  if (instr_type->opcode() == SpvOpTypeSampledImage) {
+    return false;
+  }
+  return true;
+}
+
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.h b/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.h
index d6f0ad9..a2b9a43 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.h
@@ -66,6 +66,17 @@
       opt::IRContext* ir_context, opt::BasicBlock* entry_block,
       opt::BasicBlock* exit_block);
 
+  // Returns true if and only if |instr| is available at the end of the region
+  // for which |exit_block| is the final block.
+  static bool AvailableAfterRegion(const opt::Instruction& instr,
+                                   opt::BasicBlock* exit_block,
+                                   opt::IRContext* ir_context);
+
+  // Returns true if and only if |instr| is valid as an argument to an OpPhi
+  // instruction.
+  static bool ValidOpPhiArgument(const opt::Instruction& instr,
+                                 opt::IRContext* ir_context);
+
   std::unordered_set<uint32_t> GetFreshIds() const override;
 
   protobufs::Transformation ToMessage() const override;
diff --git a/third_party/SPIRV-Tools/source/libspirv.cpp b/third_party/SPIRV-Tools/source/libspirv.cpp
index a1ed11d..0bc0935 100644
--- a/third_party/SPIRV-Tools/source/libspirv.cpp
+++ b/third_party/SPIRV-Tools/source/libspirv.cpp
@@ -14,8 +14,8 @@
 
 #include "spirv-tools/libspirv.hpp"
 
+#include <cassert>
 #include <iostream>
-
 #include <string>
 #include <utility>
 #include <vector>
@@ -60,7 +60,9 @@
   spv_context context;  // C interface context object.
 };
 
-SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) {}
+SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) {
+  assert(env != SPV_ENV_WEBGPU_0);
+}
 
 SpirvTools::~SpirvTools() {}
 
diff --git a/third_party/SPIRV-Tools/source/link/linker.cpp b/third_party/SPIRV-Tools/source/link/linker.cpp
index da6f0a7..8da4a98 100644
--- a/third_party/SPIRV-Tools/source/link/linker.cpp
+++ b/third_party/SPIRV-Tools/source/link/linker.cpp
@@ -676,14 +676,15 @@
     if (schema != 0u) {
       position.index = 4u;
       return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
-             << "Schema is non-zero for module " << i << ".";
+             << "Schema is non-zero for module " << i + 1 << ".";
     }
 
     std::unique_ptr<IRContext> ir_context = BuildModule(
         c_context->target_env, consumer, binaries[i], binary_sizes[i]);
     if (ir_context == nullptr)
       return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
-             << "Failed to build a module out of " << ir_contexts.size() << ".";
+             << "Failed to build module " << i + 1 << " out of " << num_binaries
+             << ".";
     modules.push_back(ir_context->module());
     ir_contexts.push_back(std::move(ir_context));
   }
diff --git a/third_party/SPIRV-Tools/source/opcode.cpp b/third_party/SPIRV-Tools/source/opcode.cpp
index c80e3a0..d87e828 100644
--- a/third_party/SPIRV-Tools/source/opcode.cpp
+++ b/third_party/SPIRV-Tools/source/opcode.cpp
@@ -444,15 +444,32 @@
   }
 }
 
+bool spvOpcodeIsAbort(SpvOp opcode) {
+  switch (opcode) {
+    case SpvOpKill:
+    case SpvOpUnreachable:
+    case SpvOpTerminateInvocation:
+    case SpvOpTerminateRayKHR:
+    case SpvOpIgnoreIntersectionKHR:
+      return true;
+    default:
+      return false;
+  }
+}
+
 bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
-  return spvOpcodeIsReturn(opcode) || opcode == SpvOpKill ||
-         opcode == SpvOpUnreachable || opcode == SpvOpTerminateInvocation;
+  return spvOpcodeIsReturn(opcode) || spvOpcodeIsAbort(opcode);
 }
 
 bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
   return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
 }
 
+bool spvOpcodeTerminatesExecution(SpvOp opcode) {
+  return opcode == SpvOpKill || opcode == SpvOpTerminateInvocation ||
+         opcode == SpvOpTerminateRayKHR || opcode == SpvOpIgnoreIntersectionKHR;
+}
+
 bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
   switch (opcode) {
     case SpvOpTypeImage:
diff --git a/third_party/SPIRV-Tools/source/opcode.h b/third_party/SPIRV-Tools/source/opcode.h
index 3702cb3..c8525a2 100644
--- a/third_party/SPIRV-Tools/source/opcode.h
+++ b/third_party/SPIRV-Tools/source/opcode.h
@@ -110,10 +110,18 @@
 // Returns true if the given opcode is a return instruction.
 bool spvOpcodeIsReturn(SpvOp opcode);
 
+// Returns true if the given opcode aborts execution.
+bool spvOpcodeIsAbort(SpvOp opcode);
+
 // Returns true if the given opcode is a return instruction or it aborts
 // execution.
 bool spvOpcodeIsReturnOrAbort(SpvOp opcode);
 
+// Returns true if the given opcode is a kill instruction or it terminates
+// execution. Note that branches, returns, and unreachables do not terminate
+// execution.
+bool spvOpcodeTerminatesExecution(SpvOp opcode);
+
 // Returns true if the given opcode is a basic block terminator.
 bool spvOpcodeIsBlockTerminator(SpvOp opcode);
 
diff --git a/third_party/SPIRV-Tools/source/operand.cpp b/third_party/SPIRV-Tools/source/operand.cpp
index d4b64a8..5a69fb2 100644
--- a/third_party/SPIRV-Tools/source/operand.cpp
+++ b/third_party/SPIRV-Tools/source/operand.cpp
@@ -24,6 +24,7 @@
 #include "DebugInfo.h"
 #include "OpenCLDebugInfo100.h"
 #include "source/macro.h"
+#include "source/opcode.h"
 #include "source/spirv_constant.h"
 #include "source/spirv_target_env.h"
 
@@ -264,6 +265,11 @@
     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
       return "image channel data type";
 
+    case SPV_OPERAND_TYPE_FPDENORM_MODE:
+      return "FP denorm mode";
+    case SPV_OPERAND_TYPE_FPOPERATION_MODE:
+      return "FP operation mode";
+
     case SPV_OPERAND_TYPE_NONE:
       return "NONE";
     default:
@@ -347,6 +353,8 @@
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
+    case SPV_OPERAND_TYPE_FPDENORM_MODE:
+    case SPV_OPERAND_TYPE_FPOPERATION_MODE:
       return true;
     default:
       break;
@@ -491,6 +499,11 @@
 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
     SpvOp opcode) {
   std::function<bool(unsigned index)> out;
+  if (spvOpcodeGeneratesType(opcode)) {
+    // All types can use forward pointers.
+    out = [](unsigned) { return true; };
+    return out;
+  }
   switch (opcode) {
     case SpvOpExecutionMode:
     case SpvOpExecutionModeId:
@@ -503,7 +516,6 @@
     case SpvOpDecorateId:
     case SpvOpDecorateStringGOOGLE:
     case SpvOpMemberDecorateStringGOOGLE:
-    case SpvOpTypeStruct:
     case SpvOpBranch:
     case SpvOpLoopMerge:
       out = [](unsigned) { return true; };
diff --git a/third_party/SPIRV-Tools/source/opt/CMakeLists.txt b/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
index f3ac590..14a6bee 100644
--- a/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
@@ -32,7 +32,6 @@
   dead_branch_elim_pass.h
   dead_insert_elim_pass.h
   dead_variable_elimination.h
-  decompose_initialized_variables_pass.h
   decoration_manager.h
   debug_info_manager.h
   def_use_manager.h
@@ -52,7 +51,6 @@
   fold_spec_constant_op_and_composite_pass.h
   freeze_spec_constant_value_pass.h
   function.h
-  generate_webgpu_initializers_pass.h
   graphics_robust_access_pass.h
   if_conversion.h
   inline_exhaustive_pass.h
@@ -103,10 +101,8 @@
   scalar_replacement_pass.h
   set_spec_constant_default_value_pass.h
   simplification_pass.h
-  split_invalid_unreachable_pass.h
   ssa_rewrite_pass.h
   strength_reduction_pass.h
-  strip_atomic_counter_memory_pass.h
   strip_debug_info_pass.h
   strip_reflect_info_pass.h
   struct_cfg_analysis.h
@@ -140,7 +136,6 @@
   dead_branch_elim_pass.cpp
   dead_insert_elim_pass.cpp
   dead_variable_elimination.cpp
-  decompose_initialized_variables_pass.cpp
   decoration_manager.cpp
   debug_info_manager.cpp
   def_use_manager.cpp
@@ -160,7 +155,6 @@
   freeze_spec_constant_value_pass.cpp
   function.cpp
   graphics_robust_access_pass.cpp
-  generate_webgpu_initializers_pass.cpp
   if_conversion.cpp
   inline_exhaustive_pass.cpp
   inline_opaque_pass.cpp
@@ -173,7 +167,6 @@
   instrument_pass.cpp
   ir_context.cpp
   ir_loader.cpp
-  legalize_vector_shuffle_pass.cpp
   licm_pass.cpp
   local_access_chain_convert_pass.cpp
   local_redundancy_elimination.cpp
@@ -208,10 +201,8 @@
   scalar_replacement_pass.cpp
   set_spec_constant_default_value_pass.cpp
   simplification_pass.cpp
-  split_invalid_unreachable_pass.cpp
   ssa_rewrite_pass.cpp
   strength_reduction_pass.cpp
-  strip_atomic_counter_memory_pass.cpp
   strip_debug_info_pass.cpp
   strip_reflect_info_pass.cpp
   struct_cfg_analysis.cpp
diff --git a/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp b/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp
index 39d468f..81b2232 100644
--- a/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp
@@ -991,9 +991,11 @@
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
       "SPV_KHR_ray_tracing",
+      "SPV_KHR_ray_query",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_physical_storage_buffer",
       "SPV_KHR_terminate_invocation",
+      "SPV_KHR_shader_clock",
   });
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/basic_block.cpp b/third_party/SPIRV-Tools/source/opt/basic_block.cpp
index b7e122c..e82a744 100644
--- a/third_party/SPIRV-Tools/source/opt/basic_block.cpp
+++ b/third_party/SPIRV-Tools/source/opt/basic_block.cpp
@@ -230,7 +230,7 @@
   std::ostringstream str;
   ForEachInst([&str, options](const Instruction* inst) {
     str << inst->PrettyPrint(options);
-    if (!IsTerminatorInst(inst->opcode())) {
+    if (!spvOpcodeIsBlockTerminator(inst->opcode())) {
       str << std::endl;
     }
   });
diff --git a/third_party/SPIRV-Tools/source/opt/build_module.cpp b/third_party/SPIRV-Tools/source/opt/build_module.cpp
index fc76a3c..3b606dc 100644
--- a/third_party/SPIRV-Tools/source/opt/build_module.cpp
+++ b/third_party/SPIRV-Tools/source/opt/build_module.cpp
@@ -50,11 +50,20 @@
                                             MessageConsumer consumer,
                                             const uint32_t* binary,
                                             const size_t size) {
+  return BuildModule(env, consumer, binary, size, true);
+}
+
+std::unique_ptr<opt::IRContext> BuildModule(spv_target_env env,
+                                            MessageConsumer consumer,
+                                            const uint32_t* binary,
+                                            const size_t size,
+                                            bool extra_line_tracking) {
   auto context = spvContextCreate(env);
   SetContextMessageConsumer(context, consumer);
 
   auto irContext = MakeUnique<opt::IRContext>(env, consumer);
   opt::IrLoader loader(consumer, irContext->module());
+  loader.SetExtraLineTracking(extra_line_tracking);
 
   spv_result_t status = spvBinaryParse(context, &loader, binary, size,
                                        SetSpvHeader, SetSpvInst, nullptr);
diff --git a/third_party/SPIRV-Tools/source/opt/build_module.h b/third_party/SPIRV-Tools/source/opt/build_module.h
index c9d1cf2..29eaf66 100644
--- a/third_party/SPIRV-Tools/source/opt/build_module.h
+++ b/third_party/SPIRV-Tools/source/opt/build_module.h
@@ -27,7 +27,15 @@
 // Builds an Module returns the owning IRContext from the given SPIR-V
 // |binary|. |size| specifies number of words in |binary|. The |binary| will be
 // decoded according to the given target |env|. Returns nullptr if errors occur
-// and sends the errors to |consumer|.
+// and sends the errors to |consumer|.  When |extra_line_tracking| is true,
+// extra OpLine instructions are injected to better presere line numbers while
+// later transforms mutate the module.
+std::unique_ptr<opt::IRContext> BuildModule(spv_target_env env,
+                                            MessageConsumer consumer,
+                                            const uint32_t* binary, size_t size,
+                                            bool extra_line_tracking);
+
+// Like above, with extra line tracking turned on.
 std::unique_ptr<opt::IRContext> BuildModule(spv_target_env env,
                                             MessageConsumer consumer,
                                             const uint32_t* binary,
diff --git a/third_party/SPIRV-Tools/source/opt/decompose_initialized_variables_pass.cpp b/third_party/SPIRV-Tools/source/opt/decompose_initialized_variables_pass.cpp
deleted file mode 100644
index 875bf7e..0000000
--- a/third_party/SPIRV-Tools/source/opt/decompose_initialized_variables_pass.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2019 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 "source/opt/decompose_initialized_variables_pass.h"
-
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-using inst_iterator = InstructionList::iterator;
-
-namespace {
-
-bool HasInitializer(Instruction* inst) {
-  if (inst->opcode() != SpvOpVariable) return false;
-  if (inst->NumOperands() < 4) return false;
-
-  return true;
-}
-
-}  // namespace
-
-Pass::Status DecomposeInitializedVariablesPass::Process() {
-  auto* module = context()->module();
-  std::unordered_set<Instruction*> changed;
-
-  std::vector<std::tuple<uint32_t, uint32_t>> global_stores;
-  for (auto iter = module->types_values_begin();
-       iter != module->types_values_end(); ++iter) {
-    Instruction* inst = &(*iter);
-    if (!HasInitializer(inst)) continue;
-
-    auto var_id = inst->result_id();
-    auto val_id = inst->GetOperand(3).words[0];
-    global_stores.push_back(std::make_tuple(var_id, val_id));
-    iter->RemoveOperand(3);
-    changed.insert(&*iter);
-  }
-
-  std::unordered_set<uint32_t> entry_ids;
-  for (auto entry = module->entry_points().begin();
-       entry != module->entry_points().end(); ++entry) {
-    entry_ids.insert(entry->GetSingleWordInOperand(1));
-  }
-
-  for (auto func = module->begin(); func != module->end(); ++func) {
-    std::vector<Instruction*> function_stores;
-    auto first_block = func->entry().get();
-    inst_iterator insert_point = first_block->begin();
-    for (auto iter = first_block->begin();
-         iter != first_block->end() && iter->opcode() == SpvOpVariable;
-         ++iter) {
-      // For valid SPIRV-V, there is guaranteed to be at least one instruction
-      // after the OpVariable instructions.
-      insert_point = (*iter).NextNode();
-      Instruction* inst = &(*iter);
-      if (!HasInitializer(inst)) continue;
-
-      auto var_id = inst->result_id();
-      auto val_id = inst->GetOperand(3).words[0];
-      Instruction* store_inst = new Instruction(
-          context(), SpvOpStore, 0, 0,
-          {{SPV_OPERAND_TYPE_ID, {var_id}}, {SPV_OPERAND_TYPE_ID, {val_id}}});
-      function_stores.push_back(store_inst);
-      iter->RemoveOperand(3);
-      changed.insert(&*iter);
-    }
-
-    if (entry_ids.find(func->result_id()) != entry_ids.end()) {
-      for (auto store_ids : global_stores) {
-        uint32_t var_id;
-        uint32_t val_id;
-        std::tie(var_id, val_id) = store_ids;
-        auto* store_inst = new Instruction(
-            context(), SpvOpStore, 0, 0,
-            {{SPV_OPERAND_TYPE_ID, {var_id}}, {SPV_OPERAND_TYPE_ID, {val_id}}});
-        context()->set_instr_block(store_inst, &*first_block);
-        first_block->AddInstruction(std::unique_ptr<Instruction>(store_inst));
-        store_inst->InsertBefore(&*insert_point);
-        changed.insert(store_inst);
-      }
-    }
-
-    for (auto store = function_stores.begin(); store != function_stores.end();
-         ++store) {
-      context()->set_instr_block(*store, first_block);
-      (*store)->InsertBefore(&*insert_point);
-      changed.insert(*store);
-    }
-  }
-
-  auto* def_use_mgr = get_def_use_mgr();
-  for (auto* inst : changed) def_use_mgr->UpdateDefUse(inst);
-
-  return !changed.empty() ? Pass::Status::SuccessWithChange
-                          : Pass::Status::SuccessWithoutChange;
-}
-
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/decompose_initialized_variables_pass.h b/third_party/SPIRV-Tools/source/opt/decompose_initialized_variables_pass.h
deleted file mode 100644
index c0bd35e..0000000
--- a/third_party/SPIRV-Tools/source/opt/decompose_initialized_variables_pass.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2019 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.
-
-#ifndef SOURCE_OPT_DECOMPOSE_INITALIZED_VAIRABLES_PASS_H_
-#define SOURCE_OPT_DECOMPOSE_INITALIZED_VAIRABLES_PASS_H_
-
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// Converts variable declartions with initializers into seperate declaration and
-// assignment statements. This is done due to known issues with some Vulkan
-// implementations' handling of initialized variables.
-//
-// Only decomposes variables with storage classes that are valid in Vulkan
-// execution environments; Output, Private, and Function.
-// Currently only Function is implemented.
-class DecomposeInitializedVariablesPass : public Pass {
- public:
-  const char* name() const override {
-    return "decompose-initialized-variables";
-  }
-  Status Process() override;
-
-  IRContext::Analysis GetPreservedAnalyses() override {
-    return IRContext::kAnalysisInstrToBlockMapping |
-           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
-           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
-           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
-           IRContext::kAnalysisScalarEvolution |
-           IRContext::kAnalysisRegisterPressure |
-           IRContext::kAnalysisValueNumberTable |
-           IRContext::kAnalysisStructuredCFG |
-           IRContext::kAnalysisBuiltinVarId |
-           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
-           IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
-  }
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_DECOMPOSE_INITALIZED_VAIRABLES_PASS_H_
diff --git a/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp b/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp
index b68549a..5e95006 100644
--- a/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp
+++ b/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp
@@ -63,16 +63,7 @@
 
   // All structures with descriptor assignments must be replaced by variables,
   // one for each of their members - with the exceptions of buffers.
-  // Buffers are represented as structures, but we shouldn't replace a buffer
-  // with its elements. All buffers have offset decorations for members of their
-  // structure types.
-  bool has_offset_decoration = false;
-  context()->get_decoration_mgr()->ForEachDecoration(
-      var_type_inst->result_id(), SpvDecorationOffset,
-      [&has_offset_decoration](const Instruction&) {
-        has_offset_decoration = true;
-      });
-  if (has_offset_decoration) {
+  if (IsTypeOfStructuredBuffer(var_type_inst)) {
     return false;
   }
 
@@ -99,6 +90,23 @@
   return true;
 }
 
+bool DescriptorScalarReplacement::IsTypeOfStructuredBuffer(
+    const Instruction* type) const {
+  if (type->opcode() != SpvOpTypeStruct) {
+    return false;
+  }
+
+  // All buffers have offset decorations for members of their structure types.
+  // This is how we distinguish it from a structure of descriptors.
+  bool has_offset_decoration = false;
+  context()->get_decoration_mgr()->ForEachDecoration(
+      type->result_id(), SpvDecorationOffset,
+      [&has_offset_decoration](const Instruction&) {
+        has_offset_decoration = true;
+      });
+  return has_offset_decoration;
+}
+
 bool DescriptorScalarReplacement::ReplaceCandidate(Instruction* var) {
   std::vector<Instruction*> access_chain_work_list;
   std::vector<Instruction*> load_work_list;
@@ -368,7 +376,8 @@
 
   // The number of bindings consumed by a structure is the sum of the bindings
   // used by its members.
-  if (type_inst->opcode() == SpvOpTypeStruct) {
+  if (type_inst->opcode() == SpvOpTypeStruct &&
+      !IsTypeOfStructuredBuffer(type_inst)) {
     uint32_t sum = 0;
     for (uint32_t i = 0; i < type_inst->NumInOperands(); i++)
       sum += GetNumBindingsUsedByType(type_inst->GetSingleWordInOperand(i));
diff --git a/third_party/SPIRV-Tools/source/opt/desc_sroa.h b/third_party/SPIRV-Tools/source/opt/desc_sroa.h
index c3aa0ea..cd72fd3 100644
--- a/third_party/SPIRV-Tools/source/opt/desc_sroa.h
+++ b/third_party/SPIRV-Tools/source/opt/desc_sroa.h
@@ -93,6 +93,11 @@
   // bindings used by its members.
   uint32_t GetNumBindingsUsedByType(uint32_t type_id);
 
+  // Returns true if |type| is a type that could be used for a structured buffer
+  // as opposed to a type that would be used for a structure of resource
+  // descriptors.
+  bool IsTypeOfStructuredBuffer(const Instruction* type) const;
+
   // A map from an OpVariable instruction to the set of variables that will be
   // used to replace it. The entry |replacement_variables_[var][i]| is the id of
   // a variable that will be used in the place of the the ith element of the
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp
index ab28932..173df62 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp
@@ -228,15 +228,10 @@
             const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
                 ->AsIntConstant();
         assert(member_idx);
-        if (member_idx->type()->AsInteger()->width() == 32) {
-          used_members_[type_id].insert(member_idx->GetU32());
-          type_id = type_inst->GetSingleWordInOperand(member_idx->GetU32());
-        } else {
-          used_members_[type_id].insert(
-              static_cast<uint32_t>(member_idx->GetU64()));
-          type_id = type_inst->GetSingleWordInOperand(
-              static_cast<uint32_t>(member_idx->GetU64()));
-        }
+        uint32_t index =
+            static_cast<uint32_t>(member_idx->GetZeroExtendedValue());
+        used_members_[type_id].insert(index);
+        type_id = type_inst->GetSingleWordInOperand(index);
       } break;
       case SpvOpTypeArray:
       case SpvOpTypeRuntimeArray:
@@ -477,12 +472,8 @@
             const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
                 ->AsIntConstant();
         assert(member_idx);
-        uint32_t orig_member_idx;
-        if (member_idx->type()->AsInteger()->width() == 32) {
-          orig_member_idx = member_idx->GetU32();
-        } else {
-          orig_member_idx = static_cast<uint32_t>(member_idx->GetU64());
-        }
+        uint32_t orig_member_idx =
+            static_cast<uint32_t>(member_idx->GetZeroExtendedValue());
         uint32_t new_member_idx = GetNewMemberIndex(type_id, orig_member_idx);
         assert(new_member_idx != kRemovedMember);
         if (orig_member_idx != new_member_idx) {
diff --git a/third_party/SPIRV-Tools/source/opt/generate_webgpu_initializers_pass.cpp b/third_party/SPIRV-Tools/source/opt/generate_webgpu_initializers_pass.cpp
deleted file mode 100644
index eaed3c2..0000000
--- a/third_party/SPIRV-Tools/source/opt/generate_webgpu_initializers_pass.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2019 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 "source/opt/generate_webgpu_initializers_pass.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-using inst_iterator = InstructionList::iterator;
-
-namespace {
-
-bool NeedsWebGPUInitializer(Instruction* inst) {
-  if (inst->opcode() != SpvOpVariable) return false;
-
-  auto storage_class = inst->GetSingleWordOperand(2);
-  if (storage_class != SpvStorageClassOutput &&
-      storage_class != SpvStorageClassPrivate &&
-      storage_class != SpvStorageClassFunction) {
-    return false;
-  }
-
-  if (inst->NumOperands() > 3) return false;
-
-  return true;
-}
-
-}  // namespace
-
-Pass::Status GenerateWebGPUInitializersPass::Process() {
-  auto* module = context()->module();
-  bool changed = false;
-
-  // Handle global/module scoped variables
-  for (auto iter = module->types_values_begin();
-       iter != module->types_values_end(); ++iter) {
-    Instruction* inst = &(*iter);
-
-    if (inst->opcode() == SpvOpConstantNull) {
-      null_constant_type_map_[inst->type_id()] = inst;
-      seen_null_constants_.insert(inst);
-      continue;
-    }
-
-    if (!NeedsWebGPUInitializer(inst)) continue;
-
-    changed = true;
-
-    auto* constant_inst = GetNullConstantForVariable(inst);
-    if (!constant_inst) return Status::Failure;
-
-    if (seen_null_constants_.find(constant_inst) ==
-        seen_null_constants_.end()) {
-      constant_inst->InsertBefore(inst);
-      null_constant_type_map_[inst->type_id()] = inst;
-      seen_null_constants_.insert(inst);
-    }
-    AddNullInitializerToVariable(constant_inst, inst);
-  }
-
-  // Handle local/function scoped variables
-  for (auto func = module->begin(); func != module->end(); ++func) {
-    auto block = func->entry().get();
-    for (auto iter = block->begin();
-         iter != block->end() && iter->opcode() == SpvOpVariable; ++iter) {
-      Instruction* inst = &(*iter);
-      if (!NeedsWebGPUInitializer(inst)) continue;
-
-      changed = true;
-      auto* constant_inst = GetNullConstantForVariable(inst);
-      if (!constant_inst) return Status::Failure;
-
-      AddNullInitializerToVariable(constant_inst, inst);
-    }
-  }
-
-  return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
-}
-
-Instruction* GenerateWebGPUInitializersPass::GetNullConstantForVariable(
-    Instruction* variable_inst) {
-  auto constant_mgr = context()->get_constant_mgr();
-  auto* def_use_mgr = get_def_use_mgr();
-
-  auto* ptr_inst = def_use_mgr->GetDef(variable_inst->type_id());
-  auto type_id = ptr_inst->GetInOperand(1).words[0];
-  if (null_constant_type_map_.find(type_id) == null_constant_type_map_.end()) {
-    auto* constant_type = context()->get_type_mgr()->GetType(type_id);
-    auto* constant = constant_mgr->GetConstant(constant_type, {});
-    return constant_mgr->GetDefiningInstruction(constant, type_id);
-  } else {
-    return null_constant_type_map_[type_id];
-  }
-}
-
-void GenerateWebGPUInitializersPass::AddNullInitializerToVariable(
-    Instruction* constant_inst, Instruction* variable_inst) {
-  auto constant_id = constant_inst->result_id();
-  variable_inst->AddOperand(Operand(SPV_OPERAND_TYPE_ID, {constant_id}));
-  get_def_use_mgr()->AnalyzeInstUse(variable_inst);
-}
-
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/generate_webgpu_initializers_pass.h b/third_party/SPIRV-Tools/source/opt/generate_webgpu_initializers_pass.h
deleted file mode 100644
index f95e84c..0000000
--- a/third_party/SPIRV-Tools/source/opt/generate_webgpu_initializers_pass.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2019 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.
-
-#ifndef SOURCE_OPT_GENERATE_WEBGPU_INITIALIZERS_PASS_H_
-#define SOURCE_OPT_GENERATE_WEBGPU_INITIALIZERS_PASS_H_
-
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// Adds initializers to variables with storage classes Output, Private, and
-// Function if they are missing. In the WebGPU environment these storage classes
-// require that the variables are initialized. Currently they are initialized to
-// NULL, though in the future some of them may be initialized to the first value
-// that is stored in them, if that was a constant.
-class GenerateWebGPUInitializersPass : public Pass {
- public:
-  const char* name() const override { return "generate-webgpu-initializers"; }
-  Status Process() override;
-
-  IRContext::Analysis GetPreservedAnalyses() override {
-    return IRContext::kAnalysisInstrToBlockMapping |
-           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
-           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
-           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
-           IRContext::kAnalysisScalarEvolution |
-           IRContext::kAnalysisRegisterPressure |
-           IRContext::kAnalysisValueNumberTable |
-           IRContext::kAnalysisStructuredCFG |
-           IRContext::kAnalysisBuiltinVarId |
-           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
-           IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
-  }
-
- private:
-  using NullConstantTypeMap = std::unordered_map<uint32_t, Instruction*>;
-  NullConstantTypeMap null_constant_type_map_;
-  std::unordered_set<Instruction*> seen_null_constants_;
-
-  Instruction* GetNullConstantForVariable(Instruction* variable_inst);
-  void AddNullInitializerToVariable(Instruction* constant_inst,
-                                    Instruction* variable_inst);
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_GENERATE_WEBGPU_INITIALIZERS_PASS_H_
diff --git a/third_party/SPIRV-Tools/source/opt/inline_exhaustive_pass.cpp b/third_party/SPIRV-Tools/source/opt/inline_exhaustive_pass.cpp
index 24f4e73..f24f744 100644
--- a/third_party/SPIRV-Tools/source/opt/inline_exhaustive_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inline_exhaustive_pass.cpp
@@ -38,11 +38,6 @@
         if (newBlocks.size() > 1) UpdateSucceedingPhis(newBlocks);
         // Replace old calling block with new block(s).
 
-        // We need to kill the name and decorations for the call, which
-        // will be deleted.  Other instructions in the block will be moved to
-        // newBlocks.  We don't need to do anything with those.
-        context()->KillNamesAndDecorates(&*ii);
-
         bi = bi.Erase();
 
         for (auto& bb : newBlocks) {
diff --git a/third_party/SPIRV-Tools/source/opt/inline_pass.cpp b/third_party/SPIRV-Tools/source/opt/inline_pass.cpp
index eaf29aa..8159ebf 100644
--- a/third_party/SPIRV-Tools/source/opt/inline_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inline_pass.cpp
@@ -383,9 +383,7 @@
   uint32_t returnLabelId = 0;
   for (auto callee_block_itr = calleeFn->begin();
        callee_block_itr != calleeFn->end(); ++callee_block_itr) {
-    if (callee_block_itr->tail()->opcode() == SpvOpUnreachable ||
-        callee_block_itr->tail()->opcode() == SpvOpKill ||
-        callee_block_itr->tail()->opcode() == SpvOpTerminateInvocation) {
+    if (spvOpcodeIsAbort(callee_block_itr->tail()->opcode())) {
       returnLabelId = context()->TakeNextId();
       break;
     }
@@ -619,14 +617,6 @@
     assert(resId != 0);
     AddLoad(calleeTypeId, resId, returnVarId, &new_blk_ptr,
             call_inst_itr->dbg_line_inst(), call_inst_itr->GetDebugScope());
-  } else {
-    // Even though it is very unlikely, it is possible that the result id of
-    // the void-function call is used, so we need to generate an instruction
-    // with that result id.
-    std::unique_ptr<Instruction> undef_inst(
-        new Instruction(context(), SpvOpUndef, call_inst_itr->type_id(),
-                        call_inst_itr->result_id(), {}));
-    context()->AddGlobalValue(std::move(undef_inst));
   }
 
   // Move instructions of original caller block after call instruction.
@@ -645,6 +635,11 @@
   for (auto& blk : *new_blocks) {
     id2block_[blk->id()] = &*blk;
   }
+
+  // We need to kill the name and decorations for the call, which will be
+  // deleted.
+  context()->KillNamesAndDecorates(&*call_inst_itr);
+
   return true;
 }
 
@@ -762,8 +757,7 @@
 
 bool InlinePass::ContainsKillOrTerminateInvocation(Function* func) const {
   return !func->WhileEachInst([](Instruction* inst) {
-    const auto opcode = inst->opcode();
-    return (opcode != SpvOpKill) && (opcode != SpvOpTerminateInvocation);
+    return !spvOpcodeTerminatesExecution(inst->opcode());
   });
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
index 7eb2d1b..0085734 100644
--- a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
@@ -23,13 +23,17 @@
 static const int kSpvSampledImageImageIdInIdx = 0;
 static const int kSpvSampledImageSamplerIdInIdx = 1;
 static const int kSpvImageSampledImageIdInIdx = 0;
+static const int kSpvCopyObjectOperandIdInIdx = 0;
 static const int kSpvLoadPtrIdInIdx = 0;
 static const int kSpvAccessChainBaseIdInIdx = 0;
 static const int kSpvAccessChainIndex0IdInIdx = 1;
 static const int kSpvTypeArrayLengthIdInIdx = 1;
 static const int kSpvConstantValueInIdx = 0;
 static const int kSpvVariableStorageClassInIdx = 0;
-
+static const int kSpvTypeImageDim = 1;
+static const int kSpvTypeImageDepth = 2;
+static const int kSpvTypeImageArrayed = 3;
+static const int kSpvTypeImageMS = 4;
 }  // anonymous namespace
 
 // Avoid unused variable warning/error on Linux
@@ -75,42 +79,51 @@
   }
 }
 
+uint32_t InstBindlessCheckPass::CloneOriginalImage(
+    uint32_t old_image_id, InstructionBuilder* builder) {
+  Instruction* new_image_inst;
+  Instruction* old_image_inst = get_def_use_mgr()->GetDef(old_image_id);
+  if (old_image_inst->opcode() == SpvOpLoad) {
+    new_image_inst = builder->AddLoad(
+        old_image_inst->type_id(),
+        old_image_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx));
+  } else if (old_image_inst->opcode() == SpvOp::SpvOpSampledImage) {
+    uint32_t clone_id = CloneOriginalImage(
+        old_image_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx),
+        builder);
+    new_image_inst = builder->AddBinaryOp(
+        old_image_inst->type_id(), SpvOpSampledImage, clone_id,
+        old_image_inst->GetSingleWordInOperand(kSpvSampledImageSamplerIdInIdx));
+  } else if (old_image_inst->opcode() == SpvOp::SpvOpImage) {
+    uint32_t clone_id = CloneOriginalImage(
+        old_image_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx),
+        builder);
+    new_image_inst =
+        builder->AddUnaryOp(old_image_inst->type_id(), SpvOpImage, clone_id);
+  } else {
+    assert(old_image_inst->opcode() == SpvOp::SpvOpCopyObject &&
+           "expecting OpCopyObject");
+    uint32_t clone_id = CloneOriginalImage(
+        old_image_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx),
+        builder);
+    // Since we are cloning, no need to create new copy
+    new_image_inst = get_def_use_mgr()->GetDef(clone_id);
+  }
+  uid2offset_[new_image_inst->unique_id()] =
+      uid2offset_[old_image_inst->unique_id()];
+  uint32_t new_image_id = new_image_inst->result_id();
+  get_decoration_mgr()->CloneDecorations(old_image_id, new_image_id);
+  return new_image_id;
+}
+
 uint32_t InstBindlessCheckPass::CloneOriginalReference(
-    ref_analysis* ref, InstructionBuilder* builder) {
+    RefAnalysis* ref, InstructionBuilder* builder) {
   // If original is image based, start by cloning descriptor load
   uint32_t new_image_id = 0;
   if (ref->desc_load_id != 0) {
-    Instruction* desc_load_inst = get_def_use_mgr()->GetDef(ref->desc_load_id);
-    Instruction* new_load_inst = builder->AddLoad(
-        desc_load_inst->type_id(),
-        desc_load_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx));
-    uid2offset_[new_load_inst->unique_id()] =
-        uid2offset_[desc_load_inst->unique_id()];
-    uint32_t new_load_id = new_load_inst->result_id();
-    get_decoration_mgr()->CloneDecorations(desc_load_inst->result_id(),
-                                           new_load_id);
-    new_image_id = new_load_id;
-    // Clone Image/SampledImage with new load, if needed
-    if (ref->image_id != 0) {
-      Instruction* image_inst = get_def_use_mgr()->GetDef(ref->image_id);
-      if (image_inst->opcode() == SpvOp::SpvOpSampledImage) {
-        Instruction* new_image_inst = builder->AddBinaryOp(
-            image_inst->type_id(), SpvOpSampledImage, new_load_id,
-            image_inst->GetSingleWordInOperand(kSpvSampledImageSamplerIdInIdx));
-        uid2offset_[new_image_inst->unique_id()] =
-            uid2offset_[image_inst->unique_id()];
-        new_image_id = new_image_inst->result_id();
-      } else {
-        assert(image_inst->opcode() == SpvOp::SpvOpImage &&
-               "expecting OpImage");
-        Instruction* new_image_inst =
-            builder->AddUnaryOp(image_inst->type_id(), SpvOpImage, new_load_id);
-        uid2offset_[new_image_inst->unique_id()] =
-            uid2offset_[image_inst->unique_id()];
-        new_image_id = new_image_inst->result_id();
-      }
-      get_decoration_mgr()->CloneDecorations(ref->image_id, new_image_id);
-    }
+    uint32_t old_image_id =
+        ref->ref_inst->GetSingleWordInOperand(kSpvImageSampleImageIdInIdx);
+    new_image_id = CloneOriginalImage(old_image_id, builder);
   }
   // Clone original reference
   std::unique_ptr<Instruction> new_ref_inst(ref->ref_inst->Clone(context()));
@@ -179,7 +192,7 @@
 }
 
 bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
-                                                       ref_analysis* ref) {
+                                                       RefAnalysis* ref) {
   ref->ref_inst = ref_inst;
   if (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) {
     ref->desc_load_id = 0;
@@ -220,25 +233,28 @@
   // Reference is not load or store. If not an image-based reference, return.
   ref->image_id = GetImageId(ref_inst);
   if (ref->image_id == 0) return false;
-  Instruction* image_inst = get_def_use_mgr()->GetDef(ref->image_id);
-  Instruction* desc_load_inst = nullptr;
-  if (image_inst->opcode() == SpvOp::SpvOpSampledImage) {
-    ref->desc_load_id =
-        image_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx);
-    desc_load_inst = get_def_use_mgr()->GetDef(ref->desc_load_id);
-  } else if (image_inst->opcode() == SpvOp::SpvOpImage) {
-    ref->desc_load_id =
-        image_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx);
-    desc_load_inst = get_def_use_mgr()->GetDef(ref->desc_load_id);
-  } else {
-    ref->desc_load_id = ref->image_id;
-    desc_load_inst = image_inst;
-    ref->image_id = 0;
+  // Search for descriptor load
+  uint32_t desc_load_id = ref->image_id;
+  Instruction* desc_load_inst;
+  for (;;) {
+    desc_load_inst = get_def_use_mgr()->GetDef(desc_load_id);
+    if (desc_load_inst->opcode() == SpvOp::SpvOpSampledImage)
+      desc_load_id =
+          desc_load_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx);
+    else if (desc_load_inst->opcode() == SpvOp::SpvOpImage)
+      desc_load_id =
+          desc_load_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx);
+    else if (desc_load_inst->opcode() == SpvOp::SpvOpCopyObject)
+      desc_load_id =
+          desc_load_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx);
+    else
+      break;
   }
   if (desc_load_inst->opcode() != SpvOp::SpvOpLoad) {
     // TODO(greg-lunarg): Handle additional possibilities?
     return false;
   }
+  ref->desc_load_id = desc_load_id;
   ref->ptr_id = desc_load_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
   Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
   if (ptr_inst->opcode() == SpvOp::SpvOpVariable) {
@@ -322,7 +338,7 @@
   return size;
 }
 
-uint32_t InstBindlessCheckPass::GenLastByteIdx(ref_analysis* ref,
+uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
                                                InstructionBuilder* builder) {
   // Find outermost buffer type and its access chain index
   Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
@@ -474,7 +490,7 @@
 
 void InstBindlessCheckPass::GenCheckCode(
     uint32_t check_id, uint32_t error_id, uint32_t offset_id,
-    uint32_t length_id, uint32_t stage_idx, ref_analysis* ref,
+    uint32_t length_id, uint32_t stage_idx, RefAnalysis* ref,
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   BasicBlock* back_blk_ptr = &*new_blocks->back();
   InstructionBuilder builder(
@@ -508,7 +524,7 @@
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
                         {error_id, u_index_id, u_offset_id, u_length_id},
                         &builder);
-  } else if (buffer_bounds_enabled_) {
+  } else if (buffer_bounds_enabled_ || texel_buffer_enabled_) {
     // Uninitialized Descriptor - Return additional unused zero so all error
     // modes will use same debug stream write function
     uint32_t u_length_id = GenUintCastCode(length_id, &builder);
@@ -551,7 +567,7 @@
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   // Look for reference through indexed descriptor. If found, analyze and
   // save components. If not, return.
-  ref_analysis ref;
+  RefAnalysis ref;
   if (!AnalyzeDescriptorReference(&*ref_inst_itr, &ref)) return;
   Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
   if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return;
@@ -610,7 +626,7 @@
     UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   // Look for reference through descriptor. If not, return.
-  ref_analysis ref;
+  RefAnalysis ref;
   if (!AnalyzeDescriptorReference(&*ref_inst_itr, &ref)) return;
   // Determine if we can only do initialization check
   bool init_check = false;
@@ -661,12 +677,77 @@
   MovePostludeCode(ref_block_itr, back_blk_ptr);
 }
 
+void InstBindlessCheckPass::GenTexBuffCheckCode(
+    BasicBlock::iterator ref_inst_itr,
+    UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
+    std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
+  // Only process OpImageRead and OpImageWrite with no optional operands
+  Instruction* ref_inst = &*ref_inst_itr;
+  SpvOp op = ref_inst->opcode();
+  uint32_t num_in_oprnds = ref_inst->NumInOperands();
+  if (!((op == SpvOpImageRead && num_in_oprnds == 2) ||
+        (op == SpvOpImageFetch && num_in_oprnds == 2) ||
+        (op == SpvOpImageWrite && num_in_oprnds == 3)))
+    return;
+  // Pull components from descriptor reference
+  RefAnalysis ref;
+  if (!AnalyzeDescriptorReference(ref_inst, &ref)) return;
+  // Only process if image is texel buffer
+  Instruction* image_inst = get_def_use_mgr()->GetDef(ref.image_id);
+  uint32_t image_ty_id = image_inst->type_id();
+  Instruction* image_ty_inst = get_def_use_mgr()->GetDef(image_ty_id);
+  if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim) != SpvDimBuffer)
+    return;
+  if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDepth) != 0) return;
+  if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageArrayed) != 0) return;
+  if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageMS) != 0) return;
+  // Enable ImageQuery Capability if not yet enabled
+  if (!get_feature_mgr()->HasCapability(SpvCapabilityImageQuery)) {
+    std::unique_ptr<Instruction> cap_image_query_inst(new Instruction(
+        context(), SpvOpCapability, 0, 0,
+        std::initializer_list<Operand>{
+            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}}));
+    get_def_use_mgr()->AnalyzeInstDefUse(&*cap_image_query_inst);
+    context()->AddCapability(std::move(cap_image_query_inst));
+  }
+  // Move original block's preceding instructions into first new block
+  std::unique_ptr<BasicBlock> new_blk_ptr;
+  MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr);
+  InstructionBuilder builder(
+      context(), &*new_blk_ptr,
+      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
+  new_blocks->push_back(std::move(new_blk_ptr));
+  // Get texel coordinate
+  uint32_t coord_id =
+      GenUintCastCode(ref_inst->GetSingleWordInOperand(1), &builder);
+  // If index id not yet set, binding is single descriptor, so set index to
+  // constant 0.
+  if (ref.desc_idx_id == 0) ref.desc_idx_id = builder.GetUintConstantId(0u);
+  // Get texel buffer size.
+  Instruction* size_inst =
+      builder.AddUnaryOp(GetUintId(), SpvOpImageQuerySize, ref.image_id);
+  uint32_t size_id = size_inst->result_id();
+  // Generate runtime initialization/bounds test code with true branch
+  // being full reference and false branch being debug output and zero
+  // for the referenced value.
+  Instruction* ult_inst =
+      builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, coord_id, size_id);
+  uint32_t error_id = builder.GetUintConstantId(kInstErrorBindlessBuffOOB);
+  GenCheckCode(ult_inst->result_id(), error_id, coord_id, size_id, stage_idx,
+               &ref, new_blocks);
+  // Move original block's remaining code into remainder/merge block and add
+  // to new blocks
+  BasicBlock* back_blk_ptr = &*new_blocks->back();
+  MovePostludeCode(ref_block_itr, back_blk_ptr);
+}
+
 void InstBindlessCheckPass::InitializeInstBindlessCheck() {
   // Initialize base class
   InitializeInstrument();
-  // If runtime array length support enabled, create variable mappings. Length
-  // support is always enabled if descriptor init check is enabled.
-  if (desc_idx_enabled_ || buffer_bounds_enabled_)
+  // If runtime array length support or buffer bounds checking are enabled,
+  // create variable mappings. Length support is always enabled if descriptor
+  // init check is enabled.
+  if (desc_idx_enabled_ || buffer_bounds_enabled_ || texel_buffer_enabled_)
     for (auto& anno : get_module()->annotations())
       if (anno.opcode() == SpvOpDecorate) {
         if (anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet)
@@ -689,8 +770,8 @@
       };
   bool modified = InstProcessEntryPointCallTree(pfn);
   if (desc_init_enabled_ || buffer_bounds_enabled_) {
-    // Perform descriptor initialization check on each entry point function in
-    // module
+    // Perform descriptor initialization and/or buffer bounds check on each
+    // entry point function in module
     pfn = [this](BasicBlock::iterator ref_inst_itr,
                  UptrVectorIterator<BasicBlock> ref_block_itr,
                  uint32_t stage_idx,
@@ -700,6 +781,18 @@
     };
     modified |= InstProcessEntryPointCallTree(pfn);
   }
+  if (texel_buffer_enabled_) {
+    // Perform texel buffer bounds check on each entry point function in
+    // module. Generate after descriptor bounds and initialization checks.
+    pfn = [this](BasicBlock::iterator ref_inst_itr,
+                 UptrVectorIterator<BasicBlock> ref_block_itr,
+                 uint32_t stage_idx,
+                 std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
+      return GenTexBuffCheckCode(ref_inst_itr, ref_block_itr, stage_idx,
+                                 new_blocks);
+    };
+    modified |= InstProcessEntryPointCallTree(pfn);
+  }
   return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.h b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.h
index 29da6f3..a7dff75 100644
--- a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.h
@@ -28,24 +28,16 @@
 // external design may change as the layer evolves.
 class InstBindlessCheckPass : public InstrumentPass {
  public:
-  // Old interface to support testing pre-buffer-overrun capability
-  InstBindlessCheckPass(uint32_t desc_set, uint32_t shader_id,
-                        bool desc_idx_enable, bool desc_init_enable)
-      : InstrumentPass(desc_set, shader_id, kInstValidationIdBindless, false),
-        desc_idx_enabled_(desc_idx_enable),
-        desc_init_enabled_(desc_init_enable),
-        buffer_bounds_enabled_(false) {}
-
-  // New interface supporting buffer overrun checking
   InstBindlessCheckPass(uint32_t desc_set, uint32_t shader_id,
                         bool desc_idx_enable, bool desc_init_enable,
-                        bool buffer_bounds_enable)
-      : InstrumentPass(
-            desc_set, shader_id, kInstValidationIdBindless,
-            desc_idx_enable || desc_init_enable || buffer_bounds_enable),
+                        bool buffer_bounds_enable, bool texel_buffer_enable,
+                        bool opt_direct_reads)
+      : InstrumentPass(desc_set, shader_id, kInstValidationIdBindless,
+                       opt_direct_reads),
         desc_idx_enabled_(desc_idx_enable),
         desc_init_enabled_(desc_init_enable),
-        buffer_bounds_enabled_(buffer_bounds_enable) {}
+        buffer_bounds_enabled_(buffer_bounds_enable),
+        texel_buffer_enabled_(texel_buffer_enable) {}
 
   ~InstBindlessCheckPass() override = default;
 
@@ -63,6 +55,10 @@
   // checks that the referenced descriptor has been initialized, if the
   // SPV_EXT_descriptor_indexing extension is enabled, and initialized large
   // enough to handle the reference, if RobustBufferAccess is disabled.
+  // GenDescInitCheckCode checks for uniform and storage buffer overrun.
+  // GenTexBuffCheckCode checks for texel buffer overrun and should be
+  // run after GenDescInitCheckCode to first make sure that the descriptor
+  // is initialized because it uses OpImageQuerySize on the descriptor.
   //
   // The functions are designed to be passed to
   // InstrumentPass::InstProcessEntryPointCallTree(), which applies the
@@ -109,6 +105,11 @@
       UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
       std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
 
+  void GenTexBuffCheckCode(
+      BasicBlock::iterator ref_inst_itr,
+      UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
+      std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
+
   // Generate instructions into |builder| to read length of runtime descriptor
   // array |var_id| from debug input buffer and return id of value.
   uint32_t GenDebugReadLength(uint32_t var_id, InstructionBuilder* builder);
@@ -122,7 +123,7 @@
   // Analysis data for descriptor reference components, generated by
   // AnalyzeDescriptorReference. It is necessary and sufficient for further
   // analysis and regeneration of the reference.
-  typedef struct ref_analysis {
+  typedef struct RefAnalysis {
     uint32_t desc_load_id;
     uint32_t image_id;
     uint32_t load_id;
@@ -130,7 +131,7 @@
     uint32_t var_id;
     uint32_t desc_idx_id;
     Instruction* ref_inst;
-  } ref_analysis;
+  } RefAnalysis;
 
   // Return size of type |ty_id| in bytes. Use |matrix_stride| and |col_major|
   // for matrix type, or for vector type if vector is |in_matrix|.
@@ -142,11 +143,15 @@
   uint32_t FindStride(uint32_t ty_id, uint32_t stride_deco);
 
   // Generate index of last byte referenced by buffer reference |ref|
-  uint32_t GenLastByteIdx(ref_analysis* ref, InstructionBuilder* builder);
+  uint32_t GenLastByteIdx(RefAnalysis* ref, InstructionBuilder* builder);
+
+  // Clone original image computation starting at |image_id| into |builder|.
+  // This may generate more than one instruction if neccessary.
+  uint32_t CloneOriginalImage(uint32_t image_id, InstructionBuilder* builder);
 
   // Clone original original reference encapsulated by |ref| into |builder|.
   // This may generate more than one instruction if neccessary.
-  uint32_t CloneOriginalReference(ref_analysis* ref,
+  uint32_t CloneOriginalReference(RefAnalysis* ref,
                                   InstructionBuilder* builder);
 
   // If |inst| references through an image, return the id of the image it
@@ -158,7 +163,7 @@
 
   // Analyze descriptor reference |ref_inst| and save components into |ref|.
   // Return true if |ref_inst| is a descriptor reference, false otherwise.
-  bool AnalyzeDescriptorReference(Instruction* ref_inst, ref_analysis* ref);
+  bool AnalyzeDescriptorReference(Instruction* ref_inst, RefAnalysis* ref);
 
   // Generate instrumentation code for generic test result |check_id|, starting
   // with |builder| of block |new_blk_ptr|, adding new blocks to |new_blocks|.
@@ -168,7 +173,7 @@
   // |stage_idx|. Generate merge block for valid and invalid branches. Kill
   // original reference.
   void GenCheckCode(uint32_t check_id, uint32_t error_id, uint32_t offset_id,
-                    uint32_t length_id, uint32_t stage_idx, ref_analysis* ref,
+                    uint32_t length_id, uint32_t stage_idx, RefAnalysis* ref,
                     std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
 
   // Initialize state for instrumenting bindless checking
@@ -184,9 +189,12 @@
   // Enable instrumentation of descriptor initialization checking
   bool desc_init_enabled_;
 
-  // Enable instrumentation of buffer overrun checking
+  // Enable instrumentation of uniform and storage buffer overrun checking
   bool buffer_bounds_enabled_;
 
+  // Enable instrumentation of texel buffer overrun checking
+  bool texel_buffer_enabled_;
+
   // Mapping from variable to descriptor set
   std::unordered_map<uint32_t, uint32_t> var2desc_set_;
 
diff --git a/third_party/SPIRV-Tools/source/opt/instruction.h b/third_party/SPIRV-Tools/source/opt/instruction.h
index 252e8cb..4743221 100644
--- a/third_party/SPIRV-Tools/source/opt/instruction.h
+++ b/third_party/SPIRV-Tools/source/opt/instruction.h
@@ -97,10 +97,14 @@
     assert(type == SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER);
     assert(1 <= words.size());
     assert(words.size() <= 2);
-    // Load the low word.
-    uint64_t result = uint64_t(words[0]);
+    uint64_t result = 0;
+    if (words.size() > 0) {  // Needed to avoid maybe-uninitialized GCC warning
+      uint32_t low = words[0];
+      result = uint64_t(low);
+    }
     if (words.size() > 1) {
-      result = result | (uint64_t(words[1]) << 32);
+      uint32_t high = words[1];
+      result = result | (uint64_t(high) << 32);
     }
     return result;
   }
diff --git a/third_party/SPIRV-Tools/source/opt/ir_loader.cpp b/third_party/SPIRV-Tools/source/opt/ir_loader.cpp
index 4a44309..e443ebb 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_loader.cpp
+++ b/third_party/SPIRV-Tools/source/opt/ir_loader.cpp
@@ -41,6 +41,7 @@
   ++inst_index_;
   const auto opcode = static_cast<SpvOp>(inst->opcode);
   if (IsDebugLineInst(opcode)) {
+    module()->SetContainsDebugInfo();
     last_line_inst_.reset();
     dbg_line_info_.push_back(
         Instruction(module()->context(), *inst, last_dbg_scope_));
@@ -61,12 +62,12 @@
           inlined_at = inst->words[kInlinedAtIndex];
         last_dbg_scope_ =
             DebugScope(inst->words[kLexicalScopeIndex], inlined_at);
-        module()->SetContainsDebugScope();
+        module()->SetContainsDebugInfo();
         return true;
       }
       if (ext_inst_key == OpenCLDebugInfo100DebugNoScope) {
         last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
-        module()->SetContainsDebugScope();
+        module()->SetContainsDebugInfo();
         return true;
       }
     } else {
@@ -78,12 +79,12 @@
           inlined_at = inst->words[kInlinedAtIndex];
         last_dbg_scope_ =
             DebugScope(inst->words[kLexicalScopeIndex], inlined_at);
-        module()->SetContainsDebugScope();
+        module()->SetContainsDebugInfo();
         return true;
       }
       if (ext_inst_key == DebugInfoDebugNoScope) {
         last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
-        module()->SetContainsDebugScope();
+        module()->SetContainsDebugInfo();
         return true;
       }
     }
@@ -92,7 +93,8 @@
   std::unique_ptr<Instruction> spv_inst(
       new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
   if (!spv_inst->dbg_line_insts().empty()) {
-    if (spv_inst->dbg_line_insts().back().opcode() != SpvOpNoLine) {
+    if (extra_line_tracking_ &&
+        (spv_inst->dbg_line_insts().back().opcode() != SpvOpNoLine)) {
       last_line_inst_ = std::unique_ptr<Instruction>(
           spv_inst->dbg_line_insts().back().Clone(module()->context()));
     }
@@ -136,7 +138,7 @@
       return false;
     }
     block_ = MakeUnique<BasicBlock>(std::move(spv_inst));
-  } else if (IsTerminatorInst(opcode)) {
+  } else if (spvOpcodeIsBlockTerminator(opcode)) {
     if (function_ == nullptr) {
       Error(consumer_, src, loc, "terminator instruction outside function");
       return false;
diff --git a/third_party/SPIRV-Tools/source/opt/ir_loader.h b/third_party/SPIRV-Tools/source/opt/ir_loader.h
index d0610f1..16bc2c7 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_loader.h
+++ b/third_party/SPIRV-Tools/source/opt/ir_loader.h
@@ -63,6 +63,10 @@
   // or a missing OpFunctionEnd.  Resolves internal bookkeeping.
   void EndModule();
 
+  // Sets whether extra OpLine instructions should be injected to better
+  // track line information.
+  void SetExtraLineTracking(bool flag) { extra_line_tracking_ = flag; }
+
  private:
   // Consumer for communicating messages to outside.
   const MessageConsumer& consumer_;
@@ -78,11 +82,17 @@
   std::unique_ptr<BasicBlock> block_;
   // Line related debug instructions accumulated thus far.
   std::vector<Instruction> dbg_line_info_;
-  // Line instruction that should be applied to the next instruction.
+  // If doing extra line tracking, this is the line instruction that should be
+  // applied to the next instruction.  Otherwise it always contains null.
   std::unique_ptr<Instruction> last_line_inst_;
 
   // The last DebugScope information that IrLoader::AddInstruction() handled.
   DebugScope last_dbg_scope_;
+
+  // When true, do extra line information tracking: Additional OpLine
+  // instructions will be injected to help track line info more robustly during
+  // transformations.
+  bool extra_line_tracking_ = true;
 };
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/legalize_vector_shuffle_pass.cpp b/third_party/SPIRV-Tools/source/opt/legalize_vector_shuffle_pass.cpp
deleted file mode 100644
index b5d5d59..0000000
--- a/third_party/SPIRV-Tools/source/opt/legalize_vector_shuffle_pass.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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 "source/opt/legalize_vector_shuffle_pass.h"
-
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-Pass::Status LegalizeVectorShufflePass::Process() {
-  bool changed = false;
-  context()->module()->ForEachInst([&changed](Instruction* inst) {
-    if (inst->opcode() != SpvOpVectorShuffle) return;
-
-    for (uint32_t idx = 2; idx < inst->NumInOperands(); ++idx) {
-      auto literal = inst->GetSingleWordInOperand(idx);
-      if (literal != 0xFFFFFFFF) continue;
-      changed = true;
-      inst->SetInOperand(idx, {0});
-    }
-  });
-
-  return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
-}
-
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/legalize_vector_shuffle_pass.h b/third_party/SPIRV-Tools/source/opt/legalize_vector_shuffle_pass.h
deleted file mode 100644
index ca6e1df..0000000
--- a/third_party/SPIRV-Tools/source/opt/legalize_vector_shuffle_pass.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2019 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.
-
-#ifndef SOURCE_OPT_LEGALIZE_VECTOR_SHUFFLE_PASS_H_
-#define SOURCE_OPT_LEGALIZE_VECTOR_SHUFFLE_PASS_H_
-
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// Converts any usages of 0xFFFFFFFF for the literals in OpVectorShuffle to a
-// literal 0. This is needed because using OxFFFFFFFF is forbidden by the WebGPU
-// spec. 0xFFFFFFFF in the main spec indicates that the result for this
-// component has no source, thus is undefined. Since this is undefined
-// behaviour we are free to use 0.
-class LegalizeVectorShufflePass : public Pass {
- public:
-  const char* name() const override { return "legalize-vector-shuffle"; }
-  Status Process() override;
-
-  IRContext::Analysis GetPreservedAnalyses() override {
-    return IRContext::kAnalysisInstrToBlockMapping |
-           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
-           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
-           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
-           IRContext::kAnalysisScalarEvolution |
-           IRContext::kAnalysisRegisterPressure |
-           IRContext::kAnalysisValueNumberTable |
-           IRContext::kAnalysisStructuredCFG |
-           IRContext::kAnalysisBuiltinVarId |
-           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
-           IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
-  }
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_LEGALIZE_VECTOR_SHUFFLE_PASS_H_
diff --git a/third_party/SPIRV-Tools/source/opt/module.cpp b/third_party/SPIRV-Tools/source/opt/module.cpp
index 9d3b0ed..0c88601 100644
--- a/third_party/SPIRV-Tools/source/opt/module.cpp
+++ b/third_party/SPIRV-Tools/source/opt/module.cpp
@@ -188,7 +188,7 @@
       i->ToBinaryWithoutAttachedDebugInsts(binary);
     }
     // Update the last line instruction.
-    if (IsTerminatorInst(opcode) || opcode == SpvOpNoLine) {
+    if (spvOpcodeIsBlockTerminator(opcode) || opcode == SpvOpNoLine) {
       last_line_inst = nullptr;
     } else if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
       between_merge_and_branch = true;
diff --git a/third_party/SPIRV-Tools/source/opt/module.h b/third_party/SPIRV-Tools/source/opt/module.h
index 75da870..d609b60 100644
--- a/third_party/SPIRV-Tools/source/opt/module.h
+++ b/third_party/SPIRV-Tools/source/opt/module.h
@@ -49,7 +49,7 @@
   using const_inst_iterator = InstructionList::const_iterator;
 
   // Creates an empty module with zero'd header.
-  Module() : header_({}), contains_debug_scope_(false) {}
+  Module() : header_({}), contains_debug_info_(false) {}
 
   // Sets the header to the given |header|.
   void SetHeader(const ModuleHeader& header) { header_ = header; }
@@ -119,9 +119,9 @@
   // Appends a function to this module.
   inline void AddFunction(std::unique_ptr<Function> f);
 
-  // Sets |contains_debug_scope_| as true.
-  inline void SetContainsDebugScope();
-  inline bool ContainsDebugScope() { return contains_debug_scope_; }
+  // Sets |contains_debug_info_| as true.
+  inline void SetContainsDebugInfo();
+  inline bool ContainsDebugInfo() { return contains_debug_info_; }
 
   // Returns a vector of pointers to type-declaration instructions in this
   // module.
@@ -246,12 +246,6 @@
   // If |skip_nop| is true and this is a OpNop, do nothing.
   void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
 
-  // Pushes the binary segments for this instruction into the back of *|binary|
-  // including all OpLine and OpNoLine even if we can skip emitting some line
-  // instructions. If |skip_nop| is true and this is a OpNop, do nothing.
-  void ToBinaryWithAllOpLines(std::vector<uint32_t>* binary,
-                              bool skip_nop) const;
-
   // Returns 1 more than the maximum Id value mentioned in the module.
   uint32_t ComputeIdBound() const;
 
@@ -307,8 +301,8 @@
   // any instruction.  We record them here, so they will not be lost.
   std::vector<Instruction> trailing_dbg_line_info_;
 
-  // This module contains DebugScope or DebugNoScope.
-  bool contains_debug_scope_;
+  // This module contains DebugScope/DebugNoScope or OpLine/OpNoLine.
+  bool contains_debug_info_;
 };
 
 // Pretty-prints |module| to |str|. Returns |str|.
@@ -370,7 +364,7 @@
   functions_.emplace_back(std::move(f));
 }
 
-inline void Module::SetContainsDebugScope() { contains_debug_scope_ = true; }
+inline void Module::SetContainsDebugInfo() { contains_debug_info_ = true; }
 
 inline Module::inst_iterator Module::capability_begin() {
   return capabilities_.begin();
diff --git a/third_party/SPIRV-Tools/source/opt/optimizer.cpp b/third_party/SPIRV-Tools/source/opt/optimizer.cpp
index 1ded2ee..909442c 100644
--- a/third_party/SPIRV-Tools/source/opt/optimizer.cpp
+++ b/third_party/SPIRV-Tools/source/opt/optimizer.cpp
@@ -62,7 +62,9 @@
   opt::PassManager pass_manager;  // Internal implementation pass manager.
 };
 
-Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {}
+Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {
+  assert(env != SPV_ENV_WEBGPU_0);
+}
 
 Optimizer::~Optimizer() {}
 
@@ -239,23 +241,6 @@
       .RegisterPass(CreateCFGCleanupPass());
 }
 
-Optimizer& Optimizer::RegisterVulkanToWebGPUPasses() {
-  return RegisterPass(CreateStripAtomicCounterMemoryPass())
-      .RegisterPass(CreateGenerateWebGPUInitializersPass())
-      .RegisterPass(CreateLegalizeVectorShufflePass())
-      .RegisterPass(CreateSplitInvalidUnreachablePass())
-      .RegisterPass(CreateEliminateDeadConstantPass())
-      .RegisterPass(CreateFlattenDecorationPass())
-      .RegisterPass(CreateAggressiveDCEPass())
-      .RegisterPass(CreateDeadBranchElimPass())
-      .RegisterPass(CreateCompactIdsPass());
-}
-
-Optimizer& Optimizer::RegisterWebGPUToVulkanPasses() {
-  return RegisterPass(CreateDecomposeInitializedVariablesPass())
-      .RegisterPass(CreateCompactIdsPass());
-}
-
 bool Optimizer::RegisterPassesFromFlags(const std::vector<std::string>& flags) {
   for (const auto& flag : flags) {
     if (!RegisterPassFromFlag(flag)) {
@@ -298,9 +283,7 @@
   //
   // Both Pass::name() and Pass::desc() should be static class members so they
   // can be invoked without creating a pass instance.
-  if (pass_name == "strip-atomic-counter-memory") {
-    RegisterPass(CreateStripAtomicCounterMemoryPass());
-  } else if (pass_name == "strip-debug") {
+  if (pass_name == "strip-debug") {
     RegisterPass(CreateStripDebugInfoPass());
   } else if (pass_name == "strip-reflect") {
     RegisterPass(CreateStripReflectInfoPass());
@@ -425,7 +408,7 @@
     RegisterPass(CreateBlockMergePass());
     RegisterPass(CreateAggressiveDCEPass());
   } else if (pass_name == "inst-buff-oob-check") {
-    RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false, true));
+    RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false, true, true));
     RegisterPass(CreateSimplificationPass());
     RegisterPass(CreateDeadBranchElimPass());
     RegisterPass(CreateBlockMergePass());
@@ -505,14 +488,6 @@
     RegisterSizePasses();
   } else if (pass_name == "legalize-hlsl") {
     RegisterLegalizationPasses();
-  } else if (pass_name == "generate-webgpu-initializers") {
-    RegisterPass(CreateGenerateWebGPUInitializersPass());
-  } else if (pass_name == "legalize-vector-shuffle") {
-    RegisterPass(CreateLegalizeVectorShufflePass());
-  } else if (pass_name == "split-invalid-unreachable") {
-    RegisterPass(CreateSplitInvalidUnreachablePass());
-  } else if (pass_name == "decompose-initialized-variables") {
-    RegisterPass(CreateDecomposeInitializedVariablesPass());
   } else if (pass_name == "graphics-robust-access") {
     RegisterPass(CreateGraphicsRobustAccessPass());
   } else if (pass_name == "wrap-opkill") {
@@ -583,10 +558,12 @@
 #ifndef NDEBUG
   // We do not keep the result id of DebugScope in struct DebugScope.
   // Instead, we assign random ids for them, which results in integrity
+  // check failures. In addition, propagating the OpLine/OpNoLine to preserve
+  // the debug information through transformations results in integrity
   // check failures. We want to skip the integrity check when the module
-  // contains DebugScope instructions.
+  // contains DebugScope or OpLine/OpNoLine instructions.
   if (status == opt::Pass::Status::SuccessWithoutChange &&
-      !context->module()->ContainsDebugScope()) {
+      !context->module()->ContainsDebugInfo()) {
     std::vector<uint32_t> optimized_binary_with_nop;
     context->module()->ToBinary(&optimized_binary_with_nop,
                                 /* skip_nop = */ false);
@@ -627,11 +604,6 @@
   return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
 }
 
-Optimizer::PassToken CreateStripAtomicCounterMemoryPass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::StripAtomicCounterMemoryPass>());
-}
-
 Optimizer::PassToken CreateStripDebugInfoPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::StripDebugInfoPass>());
@@ -892,15 +864,14 @@
       MakeUnique<opt::UpgradeMemoryModel>());
 }
 
-Optimizer::PassToken CreateInstBindlessCheckPass(uint32_t desc_set,
-                                                 uint32_t shader_id,
-                                                 bool input_length_enable,
-                                                 bool input_init_enable,
-                                                 bool input_buff_oob_enable) {
+Optimizer::PassToken CreateInstBindlessCheckPass(
+    uint32_t desc_set, uint32_t shader_id, bool desc_length_enable,
+    bool desc_init_enable, bool buff_oob_enable, bool texbuff_oob_enable) {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::InstBindlessCheckPass>(
-          desc_set, shader_id, input_length_enable, input_init_enable,
-          input_buff_oob_enable));
+          desc_set, shader_id, desc_length_enable, desc_init_enable,
+          buff_oob_enable, texbuff_oob_enable,
+          desc_length_enable || desc_init_enable || buff_oob_enable));
 }
 
 Optimizer::PassToken CreateInstDebugPrintfPass(uint32_t desc_set,
@@ -930,31 +901,11 @@
       MakeUnique<opt::CodeSinkingPass>());
 }
 
-Optimizer::PassToken CreateGenerateWebGPUInitializersPass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::GenerateWebGPUInitializersPass>());
-}
-
 Optimizer::PassToken CreateFixStorageClassPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::FixStorageClass>());
 }
 
-Optimizer::PassToken CreateLegalizeVectorShufflePass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::LegalizeVectorShufflePass>());
-}
-
-Optimizer::PassToken CreateDecomposeInitializedVariablesPass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::DecomposeInitializedVariablesPass>());
-}
-
-Optimizer::PassToken CreateSplitInvalidUnreachablePass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::SplitInvalidUnreachablePass>());
-}
-
 Optimizer::PassToken CreateGraphicsRobustAccessPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::GraphicsRobustAccessPass>());
diff --git a/third_party/SPIRV-Tools/source/opt/passes.h b/third_party/SPIRV-Tools/source/opt/passes.h
index d47cc1c..1bc94c7 100644
--- a/third_party/SPIRV-Tools/source/opt/passes.h
+++ b/third_party/SPIRV-Tools/source/opt/passes.h
@@ -30,7 +30,6 @@
 #include "source/opt/dead_branch_elim_pass.h"
 #include "source/opt/dead_insert_elim_pass.h"
 #include "source/opt/dead_variable_elimination.h"
-#include "source/opt/decompose_initialized_variables_pass.h"
 #include "source/opt/desc_sroa.h"
 #include "source/opt/eliminate_dead_constant_pass.h"
 #include "source/opt/eliminate_dead_functions_pass.h"
@@ -40,7 +39,6 @@
 #include "source/opt/flatten_decoration_pass.h"
 #include "source/opt/fold_spec_constant_op_and_composite_pass.h"
 #include "source/opt/freeze_spec_constant_value_pass.h"
-#include "source/opt/generate_webgpu_initializers_pass.h"
 #include "source/opt/graphics_robust_access_pass.h"
 #include "source/opt/if_conversion.h"
 #include "source/opt/inline_exhaustive_pass.h"
@@ -48,7 +46,6 @@
 #include "source/opt/inst_bindless_check_pass.h"
 #include "source/opt/inst_buff_addr_check_pass.h"
 #include "source/opt/inst_debug_printf_pass.h"
-#include "source/opt/legalize_vector_shuffle_pass.h"
 #include "source/opt/licm_pass.h"
 #include "source/opt/local_access_chain_convert_pass.h"
 #include "source/opt/local_redundancy_elimination.h"
@@ -70,10 +67,8 @@
 #include "source/opt/scalar_replacement_pass.h"
 #include "source/opt/set_spec_constant_default_value_pass.h"
 #include "source/opt/simplification_pass.h"
-#include "source/opt/split_invalid_unreachable_pass.h"
 #include "source/opt/ssa_rewrite_pass.h"
 #include "source/opt/strength_reduction_pass.h"
-#include "source/opt/strip_atomic_counter_memory_pass.h"
 #include "source/opt/strip_debug_info_pass.h"
 #include "source/opt/strip_reflect_info_pass.h"
 #include "source/opt/unify_const_pass.h"
diff --git a/third_party/SPIRV-Tools/source/opt/reflect.h b/third_party/SPIRV-Tools/source/opt/reflect.h
index d374e68..c7d46df 100644
--- a/third_party/SPIRV-Tools/source/opt/reflect.h
+++ b/third_party/SPIRV-Tools/source/opt/reflect.h
@@ -59,10 +59,6 @@
 inline bool IsSpecConstantInst(SpvOp opcode) {
   return opcode >= SpvOpSpecConstantTrue && opcode <= SpvOpSpecConstantOp;
 }
-inline bool IsTerminatorInst(SpvOp opcode) {
-  return (opcode >= SpvOpBranch && opcode <= SpvOpUnreachable) ||
-         (opcode == SpvOpTerminateInvocation);
-}
 
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/split_invalid_unreachable_pass.cpp b/third_party/SPIRV-Tools/source/opt/split_invalid_unreachable_pass.cpp
deleted file mode 100644
index 31cfbc3..0000000
--- a/third_party/SPIRV-Tools/source/opt/split_invalid_unreachable_pass.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2019 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 "source/opt/split_invalid_unreachable_pass.h"
-
-#include "source/opt/ir_builder.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-Pass::Status SplitInvalidUnreachablePass::Process() {
-  bool changed = false;
-  std::unordered_set<uint32_t> entry_points;
-  for (auto entry_point : context()->module()->entry_points()) {
-    entry_points.insert(entry_point.GetSingleWordOperand(1));
-  }
-
-  for (auto func = context()->module()->begin();
-       func != context()->module()->end(); ++func) {
-    if (entry_points.find(func->result_id()) == entry_points.end()) continue;
-    std::unordered_set<uint32_t> continue_targets;
-    std::unordered_set<uint32_t> merge_blocks;
-    std::unordered_set<BasicBlock*> unreachable_blocks;
-    for (auto block = func->begin(); block != func->end(); ++block) {
-      unreachable_blocks.insert(&*block);
-      uint32_t continue_target = block->ContinueBlockIdIfAny();
-      if (continue_target != 0) continue_targets.insert(continue_target);
-      uint32_t merge_block = block->MergeBlockIdIfAny();
-      if (merge_block != 0) merge_blocks.insert(merge_block);
-    }
-
-    cfg()->ForEachBlockInPostOrder(
-        func->entry().get(), [&unreachable_blocks](BasicBlock* inner_block) {
-          unreachable_blocks.erase(inner_block);
-        });
-
-    for (auto unreachable : unreachable_blocks) {
-      uint32_t block_id = unreachable->id();
-      if (continue_targets.find(block_id) == continue_targets.end() ||
-          merge_blocks.find(block_id) == merge_blocks.end()) {
-        continue;
-      }
-
-      std::vector<std::tuple<Instruction*, uint32_t>> usages;
-      context()->get_def_use_mgr()->ForEachUse(
-          unreachable->GetLabelInst(),
-          [&usages](Instruction* use, uint32_t idx) {
-            if ((use->opcode() == SpvOpLoopMerge && idx == 0) ||
-                use->opcode() == SpvOpSelectionMerge) {
-              usages.push_back(std::make_pair(use, idx));
-            }
-          });
-
-      for (auto usage : usages) {
-        Instruction* use;
-        uint32_t idx;
-        std::tie(use, idx) = usage;
-        uint32_t new_id = context()->TakeNextId();
-        std::unique_ptr<Instruction> new_label(
-            new Instruction(context(), SpvOpLabel, 0, new_id, {}));
-        get_def_use_mgr()->AnalyzeInstDefUse(new_label.get());
-        std::unique_ptr<BasicBlock> new_block(
-            new BasicBlock(std::move(new_label)));
-        auto* block_ptr = new_block.get();
-        InstructionBuilder builder(context(), new_block.get(),
-                                   IRContext::kAnalysisDefUse |
-                                       IRContext::kAnalysisInstrToBlockMapping);
-        builder.AddUnreachable();
-        cfg()->RegisterBlock(block_ptr);
-        (&*func)->InsertBasicBlockBefore(std::move(new_block), unreachable);
-        use->SetInOperand(0, {new_id});
-        get_def_use_mgr()->UpdateDefUse(use);
-        cfg()->AddEdges(block_ptr);
-        changed = true;
-      }
-    }
-  }
-
-  return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
-}
-
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/split_invalid_unreachable_pass.h b/third_party/SPIRV-Tools/source/opt/split_invalid_unreachable_pass.h
deleted file mode 100644
index a561344..0000000
--- a/third_party/SPIRV-Tools/source/opt/split_invalid_unreachable_pass.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2019 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.
-
-#ifndef SOURCE_OPT_SPLIT_INVALID_UNREACHABLE_PASS_H_
-#define SOURCE_OPT_SPLIT_INVALID_UNREACHABLE_PASS_H_
-
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// Attempts to legalize for WebGPU by splitting up invalid unreachable blocks.
-// Specifically, looking for cases of unreachable merge-blocks and
-// continue-targets that are used more then once, which is illegal in WebGPU.
-class SplitInvalidUnreachablePass : public Pass {
- public:
-  const char* name() const override { return "split-invalid-unreachable"; }
-  Status Process() override;
-
-  IRContext::Analysis GetPreservedAnalyses() override {
-    return IRContext::kAnalysisInstrToBlockMapping |
-           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
-           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
-           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
-           IRContext::kAnalysisScalarEvolution |
-           IRContext::kAnalysisRegisterPressure |
-           IRContext::kAnalysisValueNumberTable |
-           IRContext::kAnalysisStructuredCFG |
-           IRContext::kAnalysisBuiltinVarId |
-           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
-           IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
-  }
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_SPLIT_INVALID_UNREACHABLE_PASS_H_
diff --git a/third_party/SPIRV-Tools/source/opt/strip_atomic_counter_memory_pass.cpp b/third_party/SPIRV-Tools/source/opt/strip_atomic_counter_memory_pass.cpp
deleted file mode 100644
index 47714b7..0000000
--- a/third_party/SPIRV-Tools/source/opt/strip_atomic_counter_memory_pass.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2019 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 "source/opt/strip_atomic_counter_memory_pass.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-Pass::Status StripAtomicCounterMemoryPass::Process() {
-  bool changed = false;
-  context()->module()->ForEachInst([this, &changed](Instruction* inst) {
-    auto indices = spvOpcodeMemorySemanticsOperandIndices(inst->opcode());
-    if (indices.empty()) return;
-
-    for (auto idx : indices) {
-      auto mem_sem_id = inst->GetSingleWordOperand(idx);
-      const auto& mem_sem_inst =
-          context()->get_def_use_mgr()->GetDef(mem_sem_id);
-      // The spec explicitly says that this id must be an OpConstant
-      auto mem_sem_val = mem_sem_inst->GetSingleWordOperand(2);
-      if (!(mem_sem_val & SpvMemorySemanticsAtomicCounterMemoryMask)) {
-        continue;
-      }
-      mem_sem_val &= ~SpvMemorySemanticsAtomicCounterMemoryMask;
-
-      analysis::Integer int_type(32, false);
-      const analysis::Type* uint32_type =
-          context()->get_type_mgr()->GetRegisteredType(&int_type);
-      auto* new_const = context()->get_constant_mgr()->GetConstant(
-          uint32_type, {mem_sem_val});
-      auto* new_const_inst =
-          context()->get_constant_mgr()->GetDefiningInstruction(new_const);
-      auto new_const_id = new_const_inst->result_id();
-
-      inst->SetOperand(idx, {new_const_id});
-      context()->UpdateDefUse(inst);
-      changed = true;
-    }
-  });
-
-  return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
-}
-
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/strip_atomic_counter_memory_pass.h b/third_party/SPIRV-Tools/source/opt/strip_atomic_counter_memory_pass.h
deleted file mode 100644
index 62e274a..0000000
--- a/third_party/SPIRV-Tools/source/opt/strip_atomic_counter_memory_pass.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2019 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.
-
-#ifndef SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
-#define SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
-
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// Removes the AtomicCounterMemory bit from the value being passed into memory
-// semantics. This bit being set is ignored in Vulkan environments and
-// forbidden WebGPU ones.
-class StripAtomicCounterMemoryPass : public Pass {
- public:
-  const char* name() const override { return "strip-atomic-counter-memory"; }
-  Status Process() override;
-
-  IRContext::Analysis GetPreservedAnalyses() override {
-    return IRContext::kAnalysisInstrToBlockMapping |
-           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
-           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
-           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
-           IRContext::kAnalysisScalarEvolution |
-           IRContext::kAnalysisRegisterPressure |
-           IRContext::kAnalysisValueNumberTable |
-           IRContext::kAnalysisStructuredCFG |
-           IRContext::kAnalysisBuiltinVarId |
-           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
-           IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
-  }
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
diff --git a/third_party/SPIRV-Tools/source/spirv_target_env.cpp b/third_party/SPIRV-Tools/source/spirv_target_env.cpp
index e2ff99c..f20ebb4 100644
--- a/third_party/SPIRV-Tools/source/spirv_target_env.cpp
+++ b/third_party/SPIRV-Tools/source/spirv_target_env.cpp
@@ -14,6 +14,7 @@
 
 #include "source/spirv_target_env.h"
 
+#include <cassert>
 #include <cstring>
 #include <string>
 
@@ -61,7 +62,8 @@
     case SPV_ENV_VULKAN_1_1:
       return "SPIR-V 1.3 (under Vulkan 1.1 semantics)";
     case SPV_ENV_WEBGPU_0:
-      return "SPIR-V 1.3 (under WIP WebGPU semantics)";
+      assert(false);
+      break;
     case SPV_ENV_UNIVERSAL_1_4:
       return "SPIR-V 1.4";
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
@@ -98,8 +100,10 @@
       return SPV_SPIRV_VERSION_WORD(1, 2);
     case SPV_ENV_UNIVERSAL_1_3:
     case SPV_ENV_VULKAN_1_1:
-    case SPV_ENV_WEBGPU_0:
       return SPV_SPIRV_VERSION_WORD(1, 3);
+    case SPV_ENV_WEBGPU_0:
+      assert(false);
+      break;
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
       return SPV_SPIRV_VERSION_WORD(1, 4);
@@ -134,7 +138,6 @@
     {"opengl4.2", SPV_ENV_OPENGL_4_2},
     {"opengl4.3", SPV_ENV_OPENGL_4_3},
     {"opengl4.5", SPV_ENV_OPENGL_4_5},
-    {"webgpu0", SPV_ENV_WEBGPU_0},
 };
 
 bool spvParseTargetEnv(const char* s, spv_target_env* env) {
@@ -200,7 +203,6 @@
     case SPV_ENV_OPENCL_2_2:
     case SPV_ENV_OPENCL_EMBEDDED_2_2:
     case SPV_ENV_UNIVERSAL_1_3:
-    case SPV_ENV_WEBGPU_0:
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_UNIVERSAL_1_5:
       return false;
@@ -209,6 +211,9 @@
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_VULKAN_1_2:
       return true;
+    case SPV_ENV_WEBGPU_0:
+      assert(false);
+      break;
   }
   return false;
 }
@@ -226,7 +231,6 @@
     case SPV_ENV_UNIVERSAL_1_2:
     case SPV_ENV_UNIVERSAL_1_3:
     case SPV_ENV_VULKAN_1_1:
-    case SPV_ENV_WEBGPU_0:
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_UNIVERSAL_1_5:
@@ -241,38 +245,9 @@
     case SPV_ENV_OPENCL_2_1:
     case SPV_ENV_OPENCL_2_2:
       return true;
-  }
-  return false;
-}
-
-bool spvIsWebGPUEnv(spv_target_env env) {
-  switch (env) {
-    case SPV_ENV_UNIVERSAL_1_0:
-    case SPV_ENV_VULKAN_1_0:
-    case SPV_ENV_UNIVERSAL_1_1:
-    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_UNIVERSAL_1_2:
-    case SPV_ENV_UNIVERSAL_1_3:
-    case SPV_ENV_VULKAN_1_1:
-    case SPV_ENV_OPENCL_1_2:
-    case SPV_ENV_OPENCL_EMBEDDED_1_2:
-    case SPV_ENV_OPENCL_2_0:
-    case SPV_ENV_OPENCL_EMBEDDED_2_0:
-    case SPV_ENV_OPENCL_EMBEDDED_2_1:
-    case SPV_ENV_OPENCL_EMBEDDED_2_2:
-    case SPV_ENV_OPENCL_2_1:
-    case SPV_ENV_OPENCL_2_2:
-    case SPV_ENV_UNIVERSAL_1_4:
-    case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
-    case SPV_ENV_UNIVERSAL_1_5:
-    case SPV_ENV_VULKAN_1_2:
-      return false;
     case SPV_ENV_WEBGPU_0:
-      return true;
+      assert(false);
+      break;
   }
   return false;
 }
@@ -293,7 +268,6 @@
     case SPV_ENV_OPENCL_EMBEDDED_2_2:
     case SPV_ENV_OPENCL_2_1:
     case SPV_ENV_OPENCL_2_2:
-    case SPV_ENV_WEBGPU_0:
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_UNIVERSAL_1_5:
@@ -305,14 +279,13 @@
     case SPV_ENV_OPENGL_4_3:
     case SPV_ENV_OPENGL_4_5:
       return true;
+    case SPV_ENV_WEBGPU_0:
+      assert(false);
+      break;
   }
   return false;
 }
 
-bool spvIsVulkanOrWebGPUEnv(spv_target_env env) {
-  return spvIsVulkanEnv(env) || spvIsWebGPUEnv(env);
-}
-
 std::string spvLogStringForEnv(spv_target_env env) {
   switch (env) {
     case SPV_ENV_OPENCL_1_2:
@@ -338,9 +311,6 @@
       case SPV_ENV_VULKAN_1_2:
         return "Vulkan";
     }
-    case SPV_ENV_WEBGPU_0: {
-      return "WebGPU";
-    }
     case SPV_ENV_UNIVERSAL_1_0:
     case SPV_ENV_UNIVERSAL_1_1:
     case SPV_ENV_UNIVERSAL_1_2:
@@ -349,6 +319,9 @@
     case SPV_ENV_UNIVERSAL_1_5: {
       return "Universal";
     }
+    case SPV_ENV_WEBGPU_0:
+      assert(false);
+      break;
   }
   return "Unknown";
 }
diff --git a/third_party/SPIRV-Tools/source/spirv_target_env.h b/third_party/SPIRV-Tools/source/spirv_target_env.h
index 1bdedf9..a804d61 100644
--- a/third_party/SPIRV-Tools/source/spirv_target_env.h
+++ b/third_party/SPIRV-Tools/source/spirv_target_env.h
@@ -25,20 +25,14 @@
 // Returns true if |env| is an OPENCL environment, false otherwise.
 bool spvIsOpenCLEnv(spv_target_env env);
 
-// Returns true if |env| is an WEBGPU environment, false otherwise.
-bool spvIsWebGPUEnv(spv_target_env env);
-
 // Returns true if |env| is an OPENGL environment, false otherwise.
 bool spvIsOpenGLEnv(spv_target_env env);
 
-// Returns true if |env| is a VULKAN or WEBGPU environment, false otherwise.
-bool spvIsVulkanOrWebGPUEnv(spv_target_env env);
-
 // Returns the version number for the given SPIR-V target environment.
 uint32_t spvVersionForTargetEnv(spv_target_env env);
 
 // Returns a string to use in logging messages that indicates the class of
-// environment, i.e. "Vulkan", "WebGPU", "OpenCL", etc.
+// environment, i.e. "Vulkan", "OpenCL", etc.
 std::string spvLogStringForEnv(spv_target_env env);
 
 // Returns a formatted list of all SPIR-V target environment names that
diff --git a/third_party/SPIRV-Tools/source/table.cpp b/third_party/SPIRV-Tools/source/table.cpp
index 8340e8e..d4a2d7e 100644
--- a/third_party/SPIRV-Tools/source/table.cpp
+++ b/third_party/SPIRV-Tools/source/table.cpp
@@ -38,7 +38,6 @@
     case SPV_ENV_UNIVERSAL_1_3:
     case SPV_ENV_VULKAN_1_1:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
-    case SPV_ENV_WEBGPU_0:
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_UNIVERSAL_1_5:
     case SPV_ENV_VULKAN_1_2:
diff --git a/third_party/SPIRV-Tools/source/val/validate.cpp b/third_party/SPIRV-Tools/source/val/validate.cpp
index d6e992b..a2e116b 100644
--- a/third_party/SPIRV-Tools/source/val/validate.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate.cpp
@@ -111,57 +111,6 @@
          << id_str.substr(0, id_str.size() - 1);
 }
 
-std::vector<std::string> CalculateNamesForEntryPoint(ValidationState_t& _,
-                                                     const uint32_t id) {
-  auto id_descriptions = _.entry_point_descriptions(id);
-  auto id_names = std::vector<std::string>();
-  id_names.reserve((id_descriptions.size()));
-
-  for (auto description : id_descriptions) id_names.push_back(description.name);
-
-  return id_names;
-}
-
-spv_result_t ValidateEntryPointNameUnique(ValidationState_t& _,
-                                          const uint32_t id) {
-  auto id_names = CalculateNamesForEntryPoint(_, id);
-  const auto names =
-      std::unordered_set<std::string>(id_names.begin(), id_names.end());
-
-  if (id_names.size() != names.size()) {
-    std::sort(id_names.begin(), id_names.end());
-    for (size_t i = 0; i < id_names.size() - 1; i++) {
-      if (id_names[i] == id_names[i + 1]) {
-        return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(id))
-               << "Entry point name \"" << id_names[i]
-               << "\" is not unique, which is not allow in WebGPU env.";
-      }
-    }
-  }
-
-  for (const auto other_id : _.entry_points()) {
-    if (other_id == id) continue;
-    const auto other_id_names = CalculateNamesForEntryPoint(_, other_id);
-    for (const auto& other_id_name : other_id_names) {
-      if (names.find(other_id_name) != names.end()) {
-        return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(id))
-               << "Entry point name \"" << other_id_name
-               << "\" is not unique, which is not allow in WebGPU env.";
-      }
-    }
-  }
-
-  return SPV_SUCCESS;
-}
-
-spv_result_t ValidateEntryPointNamesUnique(ValidationState_t& _) {
-  for (const auto id : _.entry_points()) {
-    auto result = ValidateEntryPointNameUnique(_, id);
-    if (result != SPV_SUCCESS) return result;
-  }
-  return SPV_SUCCESS;
-}
-
 // Entry point validation. Based on 2.16.1 (Universal Validation Rules) of the
 // SPIRV spec:
 // * There is at least one OpEntryPoint instruction, unless the Linkage
@@ -169,8 +118,7 @@
 // * No function can be targeted by both an OpEntryPoint instruction and an
 //   OpFunctionCall instruction.
 //
-// Additionally enforces that entry points for Vulkan and WebGPU should not have
-// recursion. And that entry names should be unique for WebGPU.
+// Additionally enforces that entry points for Vulkan should not have recursion.
 spv_result_t ValidateEntryPoints(ValidationState_t& _) {
   _.ComputeFunctionToEntryPointMapping();
   _.ComputeRecursiveEntryPoints();
@@ -189,21 +137,15 @@
                 "an OpFunctionCall instruction.";
     }
 
-    // For Vulkan and WebGPU, the static function-call graph for an entry point
+    // For Vulkan, the static function-call graph for an entry point
     // must not contain cycles.
-    if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+    if (spvIsVulkanEnv(_.context()->target_env)) {
       if (_.recursive_entry_points().find(entry_point) !=
           _.recursive_entry_points().end()) {
         return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(entry_point))
                << "Entry points may not have a call graph with cycles.";
       }
     }
-
-    // For WebGPU all entry point names must be unique.
-    if (spvIsWebGPUEnv(_.context()->target_env)) {
-      const auto result = ValidateEntryPointNamesUnique(_);
-      if (result != SPV_SUCCESS) return result;
-    }
   }
 
   return SPV_SUCCESS;
@@ -223,12 +165,6 @@
            << "Invalid SPIR-V magic number.";
   }
 
-  if (spvIsWebGPUEnv(context.target_env) && endian != SPV_ENDIANNESS_LITTLE) {
-    return DiagnosticStream(position, context.consumer, "",
-                            SPV_ERROR_INVALID_BINARY)
-           << "WebGPU requires SPIR-V to be little endian.";
-  }
-
   spv_header_t header;
   if (spvBinaryHeaderGet(binary.get(), endian, &header)) {
     return DiagnosticStream(position, context.consumer, "",
@@ -321,13 +257,6 @@
         }
 
         const auto called_id = inst->GetOperandAs<uint32_t>(2);
-        if (spvIsWebGPUEnv(context.target_env) &&
-            !vstate->IsFunctionCallDefined(called_id)) {
-          return vstate->diag(SPV_ERROR_INVALID_LAYOUT, &instruction)
-                 << "For WebGPU, functions need to be defined before being "
-                    "called.";
-        }
-
         vstate->AddFunctionCallTarget(called_id);
       }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_annotation.cpp b/third_party/SPIRV-Tools/source/val/validate_annotation.cpp
index df38f1b..85d2b75 100644
--- a/third_party/SPIRV-Tools/source/val/validate_annotation.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_annotation.cpp
@@ -22,36 +22,6 @@
 namespace val {
 namespace {
 
-bool IsValidWebGPUDecoration(uint32_t decoration) {
-  switch (decoration) {
-    case SpvDecorationSpecId:
-    case SpvDecorationBlock:
-    case SpvDecorationRowMajor:
-    case SpvDecorationColMajor:
-    case SpvDecorationArrayStride:
-    case SpvDecorationMatrixStride:
-    case SpvDecorationBuiltIn:
-    case SpvDecorationNoPerspective:
-    case SpvDecorationFlat:
-    case SpvDecorationCentroid:
-    case SpvDecorationRestrict:
-    case SpvDecorationAliased:
-    case SpvDecorationNonWritable:
-    case SpvDecorationNonReadable:
-    case SpvDecorationUniform:
-    case SpvDecorationLocation:
-    case SpvDecorationComponent:
-    case SpvDecorationIndex:
-    case SpvDecorationBinding:
-    case SpvDecorationDescriptorSet:
-    case SpvDecorationOffset:
-    case SpvDecorationNoContraction:
-      return true;
-    default:
-      return false;
-  }
-}
-
 std::string LogStringForDecoration(uint32_t decoration) {
   switch (decoration) {
     case SpvDecorationRelaxedPrecision:
@@ -212,11 +182,14 @@
     }
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env) &&
-      !IsValidWebGPUDecoration(decoration)) {
-    return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpDecorate decoration '" << LogStringForDecoration(decoration)
-           << "' is not valid for the WebGPU execution environment.";
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((decoration == SpvDecorationGLSLShared) ||
+        (decoration == SpvDecorationGLSLPacked)) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << _.VkErrorID(4669) << "OpDecorate decoration '"
+             << LogStringForDecoration(decoration)
+             << "' is not valid for the Vulkan execution environment.";
+    }
   }
 
   if (DecorationTakesIdParameters(decoration)) {
@@ -261,25 +234,11 @@
            << " members. Largest valid index is " << member_count - 1 << ".";
   }
 
-  const auto decoration = inst->GetOperandAs<uint32_t>(2);
-  if (spvIsWebGPUEnv(_.context()->target_env) &&
-      !IsValidWebGPUDecoration(decoration)) {
-    return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpMemberDecorate decoration  '" << _.getIdName(decoration)
-           << "' is not valid for the WebGPU execution environment.";
-  }
-
   return SPV_SUCCESS;
 }
 
 spv_result_t ValidateDecorationGroup(ValidationState_t& _,
                                      const Instruction* inst) {
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    return _.diag(SPV_ERROR_INVALID_BINARY, inst)
-           << "OpDecorationGroup is not allowed in the WebGPU execution "
-           << "environment.";
-  }
-
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   const auto decoration_group = _.FindDef(decoration_group_id);
   for (auto pair : decoration_group->uses()) {
@@ -299,12 +258,6 @@
 
 spv_result_t ValidateGroupDecorate(ValidationState_t& _,
                                    const Instruction* inst) {
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    return _.diag(SPV_ERROR_INVALID_BINARY, inst)
-           << "OpGroupDecorate is not allowed in the WebGPU execution "
-           << "environment.";
-  }
-
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   auto decoration_group = _.FindDef(decoration_group_id);
   if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) {
@@ -327,12 +280,6 @@
 
 spv_result_t ValidateGroupMemberDecorate(ValidationState_t& _,
                                          const Instruction* inst) {
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    return _.diag(SPV_ERROR_INVALID_BINARY, inst)
-           << "OpGroupMemberDecorate is not allowed in the WebGPU execution "
-           << "environment.";
-  }
-
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   const auto decoration_group = _.FindDef(decoration_group_id);
   if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) {
diff --git a/third_party/SPIRV-Tools/source/val/validate_atomics.cpp b/third_party/SPIRV-Tools/source/val/validate_atomics.cpp
index 3f1f561..dd263a7 100644
--- a/third_party/SPIRV-Tools/source/val/validate_atomics.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_atomics.cpp
@@ -213,7 +213,19 @@
 
       // Then Shader rules
       if (_.HasCapability(SpvCapabilityShader)) {
-        if (storage_class == SpvStorageClassFunction) {
+        if (spvIsVulkanEnv(_.context()->target_env)) {
+          if ((storage_class != SpvStorageClassUniform) &&
+              (storage_class != SpvStorageClassStorageBuffer) &&
+              (storage_class != SpvStorageClassWorkgroup) &&
+              (storage_class != SpvStorageClassImage) &&
+              (storage_class != SpvStorageClassPhysicalStorageBuffer)) {
+            return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                   << _.VkErrorID(4686) << spvOpcodeString(opcode)
+                   << ": Vulkan spec only allows storage classes for atomic to "
+                      "be: Uniform, Workgroup, Image, StorageBuffer, or "
+                      "PhysicalStorageBuffer.";
+          }
+        } else if (storage_class == SpvStorageClassFunction) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": Function storage class forbidden when the Shader "
diff --git a/third_party/SPIRV-Tools/source/val/validate_builtins.cpp b/third_party/SPIRV-Tools/source/val/validate_builtins.cpp
index d9e0666..3c9df9f 100644
--- a/third_party/SPIRV-Tools/source/val/validate_builtins.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_builtins.cpp
@@ -16,6 +16,7 @@
 
 // Validates correctness of built-in variables.
 
+#include <array>
 #include <functional>
 #include <list>
 #include <map>
@@ -112,25 +113,128 @@
   return SpvStorageClassMax;
 }
 
-bool IsBuiltInValidForWebGPU(SpvBuiltIn label) {
-  switch (label) {
-    case SpvBuiltInPosition:
-    case SpvBuiltInVertexIndex:
-    case SpvBuiltInInstanceIndex:
-    case SpvBuiltInFrontFacing:
-    case SpvBuiltInFragCoord:
-    case SpvBuiltInFragDepth:
-    case SpvBuiltInNumWorkgroups:
-    case SpvBuiltInWorkgroupSize:
-    case SpvBuiltInLocalInvocationId:
-    case SpvBuiltInGlobalInvocationId:
-    case SpvBuiltInLocalInvocationIndex: {
-      return true;
+typedef enum VUIDError_ {
+  VUIDErrorExecutionModel = 0,
+  VUIDErrorStorageClass = 1,
+  VUIDErrorType = 2,
+  VUIDErrorMax,
+} VUIDError;
+
+const static uint32_t NumVUIDBuiltins = 33;
+
+typedef struct {
+  SpvBuiltIn builtIn;
+  uint32_t vuid[VUIDErrorMax];  // execution mode, storage class, type VUIDs
+} BuiltinVUIDMapping;
+
+std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
+    // clang-format off
+    {SpvBuiltInSubgroupEqMask,            {0,    4370, 4371}},
+    {SpvBuiltInSubgroupGeMask,            {0,    4372, 4373}},
+    {SpvBuiltInSubgroupGtMask,            {0,    4374, 4375}},
+    {SpvBuiltInSubgroupLeMask,            {0,    4376, 4377}},
+    {SpvBuiltInSubgroupLtMask,            {0,    4378, 4379}},
+    {SpvBuiltInSubgroupLocalInvocationId, {0,    4380, 4381}},
+    {SpvBuiltInSubgroupSize,              {0,    4382, 4383}},
+    {SpvBuiltInGlobalInvocationId,        {4236, 4237, 4238}},
+    {SpvBuiltInLocalInvocationId,         {4281, 4282, 4283}},
+    {SpvBuiltInNumWorkgroups,             {4296, 4297, 4298}},
+    {SpvBuiltInNumSubgroups,              {4293, 4294, 4295}},
+    {SpvBuiltInSubgroupId,                {4367, 4368, 4369}},
+    {SpvBuiltInWorkgroupId,               {4422, 4423, 4424}},
+    {SpvBuiltInHitKindKHR,                {4242, 4243, 4244}},
+    {SpvBuiltInHitTNV,                    {4245, 4246, 4247}},
+    {SpvBuiltInInstanceCustomIndexKHR,    {4251, 4252, 4253}},
+    {SpvBuiltInInstanceId,                {4254, 4255, 4256}},
+    {SpvBuiltInRayGeometryIndexKHR,       {4345, 4346, 4347}},
+    {SpvBuiltInObjectRayDirectionKHR,     {4299, 4300, 4301}},
+    {SpvBuiltInObjectRayOriginKHR,        {4302, 4303, 4304}},
+    {SpvBuiltInObjectToWorldKHR,          {4305, 4306, 4307}},
+    {SpvBuiltInWorldToObjectKHR,          {4434, 4435, 4436}},
+    {SpvBuiltInIncomingRayFlagsKHR,       {4248, 4249, 4250}},
+    {SpvBuiltInRayTminKHR,                {4351, 4352, 4353}},
+    {SpvBuiltInRayTmaxKHR,                {4348, 4349, 4350}},
+    {SpvBuiltInWorldRayDirectionKHR,      {4428, 4429, 4430}},
+    {SpvBuiltInWorldRayOriginKHR,         {4431, 4432, 4433}},
+    {SpvBuiltInLaunchIdKHR,               {4266, 4267, 4268}},
+    {SpvBuiltInLaunchSizeKHR,             {4269, 4270, 4271}},
+    {SpvBuiltInFragInvocationCountEXT,    {4217, 4218, 4219}},
+    {SpvBuiltInFragSizeEXT,               {4220, 4221, 4222}},
+    {SpvBuiltInFragStencilRefEXT,         {4223, 4224, 4225}},
+    {SpvBuiltInFullyCoveredEXT,           {4232, 4233, 4234}},
+    // clang-format off
+} };
+
+uint32_t GetVUIDForBuiltin(SpvBuiltIn builtIn, VUIDError type) {
+  uint32_t vuid = 0;
+  for (const auto& iter: builtinVUIDInfo) {
+    if (iter.builtIn == builtIn) {
+      assert(type < VUIDErrorMax);
+      vuid = iter.vuid[type];
+      break;
     }
+  }
+  return vuid;
+}
+
+bool IsExecutionModelValidForRtBuiltIn(SpvBuiltIn builtin,
+                                       SpvExecutionModel stage) {
+  switch (builtin) {
+    case SpvBuiltInHitKindKHR:
+    case SpvBuiltInHitTNV:
+      if (stage == SpvExecutionModelAnyHitKHR ||
+          stage == SpvExecutionModelClosestHitKHR) {
+        return true;
+      }
+      break;
+    case SpvBuiltInInstanceCustomIndexKHR:
+    case SpvBuiltInInstanceId:
+    case SpvBuiltInRayGeometryIndexKHR:
+    case SpvBuiltInObjectRayDirectionKHR:
+    case SpvBuiltInObjectRayOriginKHR:
+    case SpvBuiltInObjectToWorldKHR:
+    case SpvBuiltInWorldToObjectKHR:
+      switch (stage) {
+        case SpvExecutionModelIntersectionKHR:
+        case SpvExecutionModelAnyHitKHR:
+        case SpvExecutionModelClosestHitKHR:
+          return true;
+        default:
+          return false;
+      }
+      break;
+    case SpvBuiltInIncomingRayFlagsKHR:
+    case SpvBuiltInRayTminKHR:
+    case SpvBuiltInRayTmaxKHR:
+    case SpvBuiltInWorldRayDirectionKHR:
+    case SpvBuiltInWorldRayOriginKHR:
+      switch (stage) {
+        case SpvExecutionModelIntersectionKHR:
+        case SpvExecutionModelAnyHitKHR:
+        case SpvExecutionModelClosestHitKHR:
+        case SpvExecutionModelMissKHR:
+          return true;
+        default:
+          return false;
+      }
+      break;
+    case SpvBuiltInLaunchIdKHR:
+    case SpvBuiltInLaunchSizeKHR:
+      switch (stage) {
+        case SpvExecutionModelRayGenerationKHR:
+        case SpvExecutionModelIntersectionKHR:
+        case SpvExecutionModelAnyHitKHR:
+        case SpvExecutionModelClosestHitKHR:
+        case SpvExecutionModelMissKHR:
+        case SpvExecutionModelCallableKHR:
+          return true;
+        default:
+          return false;
+      }
+      break;
     default:
       break;
   }
-
   return false;
 }
 
@@ -200,8 +304,8 @@
                                                   const Instruction& inst);
   spv_result_t ValidateVertexIndexAtDefinition(const Decoration& decoration,
                                                const Instruction& inst);
-  spv_result_t ValidateVertexIdOrInstanceIdAtDefinition(
-      const Decoration& decoration, const Instruction& inst);
+  spv_result_t ValidateVertexIdAtDefinition(const Decoration& decoration,
+                                            const Instruction& inst);
   spv_result_t ValidateLocalInvocationIndexAtDefinition(
       const Decoration& decoration, const Instruction& inst);
   spv_result_t ValidateWorkgroupSizeAtDefinition(const Decoration& decoration,
@@ -214,6 +318,14 @@
                                              const Instruction& inst);
   spv_result_t ValidateDeviceIndexAtDefinition(const Decoration& decoration,
                                                const Instruction& inst);
+  spv_result_t ValidateFragInvocationCountAtDefinition(const Decoration& decoration,
+                                               const Instruction& inst);
+  spv_result_t ValidateFragSizeAtDefinition(const Decoration& decoration,
+                                               const Instruction& inst);
+  spv_result_t ValidateFragStencilRefAtDefinition(const Decoration& decoration,
+                                               const Instruction& inst);
+  spv_result_t ValidateFullyCoveredAtDefinition(const Decoration& decoration,
+                                               const Instruction& inst);
   // Used for GlobalInvocationId, LocalInvocationId, NumWorkgroups, WorkgroupId.
   spv_result_t ValidateComputeShaderI32Vec3InputAtDefinition(
       const Decoration& decoration, const Instruction& inst);
@@ -237,6 +349,9 @@
   spv_result_t ValidateShadingRateAtDefinition(const Decoration& decoration,
                                                const Instruction& inst);
 
+  spv_result_t ValidateRayTracingBuiltinsAtDefinition(
+      const Decoration& decoration, const Instruction& inst);
+
   // The following section contains functions which are called when id defined
   // by |referenced_inst| is
   // 1. referenced by |referenced_from_inst|
@@ -269,11 +384,6 @@
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
 
-  spv_result_t ValidateInstanceIdAtReference(
-      const Decoration& decoration, const Instruction& built_in_inst,
-      const Instruction& referenced_inst,
-      const Instruction& referenced_from_inst);
-
   spv_result_t ValidateInstanceIndexAtReference(
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
@@ -374,6 +484,26 @@
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
 
+  spv_result_t ValidateFragInvocationCountAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
+  spv_result_t ValidateFragSizeAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
+  spv_result_t ValidateFragStencilRefAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
+  spv_result_t ValidateFullyCoveredAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
   // Used for GlobalInvocationId, LocalInvocationId, NumWorkgroups, WorkgroupId.
   spv_result_t ValidateComputeShaderI32Vec3InputAtReference(
       const Decoration& decoration, const Instruction& built_in_inst,
@@ -400,6 +530,11 @@
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
 
+  spv_result_t ValidateRayTracingBuiltinsAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
   // Validates that |built_in_inst| is not (even indirectly) referenced from
   // within a function which can be called with |execution_model|.
   //
@@ -422,6 +557,9 @@
   spv_result_t ValidateBool(
       const Decoration& decoration, const Instruction& inst,
       const std::function<spv_result_t(const std::string& message)>& diag);
+  spv_result_t ValidateI(
+      const Decoration& decoration, const Instruction& inst,
+      const std::function<spv_result_t(const std::string& message)>& diag);
   spv_result_t ValidateI32(
       const Decoration& decoration, const Instruction& inst,
       const std::function<spv_result_t(const std::string& message)>& diag);
@@ -476,6 +614,10 @@
       uint32_t num_components,
       const std::function<spv_result_t(const std::string& message)>& diag,
       uint32_t underlying_type);
+  spv_result_t ValidateF32Mat(
+      const Decoration& decoration, const Instruction& inst,
+      uint32_t req_num_rows, uint32_t req_num_columns,
+      const std::function<spv_result_t(const std::string& message)>& diag);
 
   // Generates strings like "Member #0 of struct ID <2>".
   std::string GetDefinitionDesc(const Decoration& decoration,
@@ -610,6 +752,22 @@
   return SPV_SUCCESS;
 }
 
+spv_result_t BuiltInsValidator::ValidateI(
+    const Decoration& decoration, const Instruction& inst,
+    const std::function<spv_result_t(const std::string& message)>& diag) {
+  uint32_t underlying_type = 0;
+  if (spv_result_t error =
+          GetUnderlyingType(_, decoration, inst, &underlying_type)) {
+    return error;
+  }
+
+  if (!_.IsIntScalarType(underlying_type)) {
+    return diag(GetDefinitionDesc(decoration, inst) + " is not an int scalar.");
+  }
+
+  return SPV_SUCCESS;
+}
+
 spv_result_t BuiltInsValidator::ValidateI32(
     const Decoration& decoration, const Instruction& inst,
     const std::function<spv_result_t(const std::string& message)>& diag) {
@@ -909,6 +1067,32 @@
   return SPV_SUCCESS;
 }
 
+spv_result_t BuiltInsValidator::ValidateF32Mat(
+    const Decoration& decoration, const Instruction& inst,
+    uint32_t req_num_rows, uint32_t req_num_columns,
+    const std::function<spv_result_t(const std::string& message)>& diag) {
+  uint32_t underlying_type = 0;
+  uint32_t num_rows = 0;
+  uint32_t num_cols = 0;
+  uint32_t col_type = 0;
+  uint32_t component_type = 0;
+  if (spv_result_t error =
+          GetUnderlyingType(_, decoration, inst, &underlying_type)) {
+    return error;
+  }
+  if (!_.GetMatrixTypeInfo(underlying_type, &num_rows, &num_cols, &col_type,
+                           &component_type) ||
+      num_rows != req_num_rows || num_cols != req_num_columns) {
+    std::ostringstream ss;
+    ss << GetDefinitionDesc(decoration, inst) << " has columns " << num_cols
+       << " and rows " << num_rows << " not equal to expected "
+       << req_num_columns << "x" << req_num_rows << ".";
+    return diag(ss.str());
+  }
+
+  return ValidateF32VecHelper(decoration, inst, req_num_rows, diag, col_type);
+}
+
 spv_result_t BuiltInsValidator::ValidateNotCalledWithExecutionModel(
     int vuid, const char* comment, SpvExecutionModel execution_model,
     const Decoration& decoration, const Instruction& built_in_inst,
@@ -956,8 +1140,9 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput &&
         storage_class != SpvStorageClassOutput) {
+      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4190 : 4199;
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << "Vulkan spec allows BuiltIn "
+             << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                                               operand)
              << " to be only used for variables with Input or Output storage "
@@ -969,19 +1154,28 @@
 
     if (storage_class == SpvStorageClassInput) {
       assert(function_id_ == 0);
+      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4188 : 4197;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, -1,
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Input storage class if execution model is "
           "Vertex.",
           SpvExecutionModelVertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
+          "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
+          "used for variables with Input storage class if execution model is "
+          "Vertex.",
+          SpvExecutionModelMeshNV, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
     }
 
     if (storage_class == SpvStorageClassOutput) {
       assert(function_id_ == 0);
+      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4189 : 4198;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, -1,
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Output storage class if execution model is "
           "Fragment.",
@@ -1095,7 +1289,7 @@
 
 spv_result_t BuiltInsValidator::ValidateFragCoordAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spv_result_t error = ValidateF32Vec(
             decoration, inst, 4,
             [this, &inst](const std::string& message) -> spv_result_t {
@@ -1119,7 +1313,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
@@ -1157,7 +1351,7 @@
 
 spv_result_t BuiltInsValidator::ValidateFragDepthAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spv_result_t error = ValidateF32(
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
@@ -1180,7 +1374,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassOutput) {
@@ -1233,7 +1427,7 @@
 
 spv_result_t BuiltInsValidator::ValidateFrontFacingAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spv_result_t error = ValidateBool(
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
@@ -1256,7 +1450,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
@@ -1414,7 +1608,7 @@
 
 spv_result_t BuiltInsValidator::ValidateInstanceIndexAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spv_result_t error = ValidateI32(
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
@@ -1437,7 +1631,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
@@ -1727,7 +1921,7 @@
         storage_class != SpvStorageClassInput &&
         storage_class != SpvStorageClassOutput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << "Vulkan spec allows BuiltIn Position to be only used for "
+             << _.VkErrorID(4320) << "Vulkan spec allows BuiltIn Position to be only used for "
                 "variables with Input or Output storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
@@ -1737,12 +1931,19 @@
     if (storage_class == SpvStorageClassInput) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4320,
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
           "Vulkan spec doesn't allow BuiltIn Position to be used "
           "for variables "
           "with Input storage class if execution model is Vertex.",
           SpvExecutionModelVertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
+          "Vulkan spec doesn't allow BuiltIn Position to be used "
+          "for variables "
+          "with Input storage class if execution model is MeshNV.",
+          SpvExecutionModelMeshNV, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
     }
 
     for (const SpvExecutionModel execution_model : execution_models_) {
@@ -1820,46 +2021,6 @@
     }
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
-      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << "WebGPU spec allows BuiltIn Position to be only used for "
-                "variables with Output storage class. "
-             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
-                                 referenced_from_inst)
-             << " " << GetStorageClassDesc(referenced_from_inst);
-    }
-
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      switch (execution_model) {
-        case SpvExecutionModelVertex: {
-          if (spv_result_t error = ValidateF32Vec(
-                  decoration, built_in_inst, 4,
-                  [this, &referenced_from_inst](
-                      const std::string& message) -> spv_result_t {
-                    return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-                           << "According to the WebGPU spec BuiltIn Position "
-                              "variable needs to be a 4-component 32-bit float "
-                              "vector. "
-                           << message;
-                  })) {
-            return error;
-          }
-          break;
-        }
-        default: {
-          return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-                 << "WebGPU spec allows BuiltIn Position to be used only "
-                    "with the Vertex execution model. "
-                 << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
-                                     referenced_from_inst, execution_model);
-        }
-      }
-    }
-  }
-
   if (function_id_ == 0) {
     // Propagate this rule to all dependant ids in the global scope.
     id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
@@ -1947,6 +2108,27 @@
           "Fragment.",
           SpvExecutionModelFragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
+          "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
+          "variables with Output storage class if execution model is "
+          "IntersectionKHR.",
+          SpvExecutionModelIntersectionKHR, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
+          "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
+          "variables with Output storage class if execution model is "
+          "AnyHitKHR.",
+          SpvExecutionModelAnyHitKHR, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
+          "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
+          "variables with Output storage class if execution model is "
+          "ClosestHitKHR.",
+          SpvExecutionModelClosestHitKHR, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
     }
 
     for (const SpvExecutionModel execution_model : execution_models_) {
@@ -1956,12 +2138,9 @@
         case SpvExecutionModelTessellationEvaluation:
         case SpvExecutionModelGeometry:
         case SpvExecutionModelMeshNV:
-        case SpvExecutionModelRayGenerationNV:
-        case SpvExecutionModelIntersectionNV:
-        case SpvExecutionModelAnyHitNV:
-        case SpvExecutionModelClosestHitNV:
-        case SpvExecutionModelMissNV:
-        case SpvExecutionModelCallableNV: {
+        case SpvExecutionModelIntersectionKHR:
+        case SpvExecutionModelAnyHitKHR:
+        case SpvExecutionModelClosestHitKHR: {
           // Ok.
           break;
         }
@@ -1971,7 +2150,9 @@
                  << _.VkErrorID(4330)
                  << "Vulkan spec allows BuiltIn PrimitiveId to be used only "
                     "with Fragment, TessellationControl, "
-                    "TessellationEvaluation or Geometry execution models. "
+                    "TessellationEvaluation, Geometry, MeshNV, "
+                    "IntersectionKHR, "
+                    "AnyHitKHR, and ClosestHitKHR execution models. "
                  << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                      referenced_from_inst, execution_model);
         }
@@ -2296,8 +2477,9 @@
 
     if (storage_class == SpvStorageClassInput) {
       assert(function_id_ == 0);
+      uint32_t vuid = (decoration.params()[0] == SpvBuiltInTessLevelOuter) ? 4391 : 4395;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, -1,
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
           "used "
           "for variables with Input storage class if execution model is "
@@ -2308,8 +2490,9 @@
 
     if (storage_class == SpvStorageClassOutput) {
       assert(function_id_ == 0);
+      uint32_t vuid = (decoration.params()[0] == SpvBuiltInTessLevelOuter) ? 4392 : 4396;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, -1,
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
           "used "
           "for variables with Output storage class if execution model is "
@@ -2353,7 +2536,7 @@
 
 spv_result_t BuiltInsValidator::ValidateVertexIndexAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spv_result_t error = ValidateI32(
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
@@ -2372,54 +2555,13 @@
   return ValidateVertexIndexAtReference(decoration, inst, inst, inst);
 }
 
-spv_result_t BuiltInsValidator::ValidateVertexIdOrInstanceIdAtDefinition(
+spv_result_t BuiltInsValidator::ValidateVertexIdAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
-  bool allow_instance_id = (_.HasCapability(SpvCapabilityRayTracingNV) ||
-                            _.HasCapability(SpvCapabilityRayTracingKHR)) &&
-                           label == SpvBuiltInInstanceId;
-
-  if (spvIsVulkanEnv(_.context()->target_env) && !allow_instance_id) {
-    return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-           << "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId "
-              "to be used.";
-  }
-
-  if (label == SpvBuiltInInstanceId) {
-    return ValidateInstanceIdAtReference(decoration, inst, inst, inst);
-  }
-  return SPV_SUCCESS;
-}
-
-spv_result_t BuiltInsValidator::ValidateInstanceIdAtReference(
-    const Decoration& decoration, const Instruction& built_in_inst,
-    const Instruction& referenced_inst,
-    const Instruction& referenced_from_inst) {
+  (void)decoration;
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      switch (execution_model) {
-        case SpvExecutionModelIntersectionNV:
-        case SpvExecutionModelClosestHitNV:
-        case SpvExecutionModelAnyHitNV:
-          // Do nothing, valid stages
-          break;
-        default:
-          return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-                 << "Vulkan spec allows BuiltIn InstanceId to be used "
-                    "only with IntersectionNV, ClosestHitNV and AnyHitNV "
-                    "execution models. "
-                 << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
-                                     referenced_from_inst);
-          break;
-      }
-    }
-  }
-
-  if (function_id_ == 0) {
-    // Propagate this rule to all dependant ids in the global scope.
-    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-        &BuiltInsValidator::ValidateInstanceIdAtReference, this, decoration,
-        built_in_inst, referenced_from_inst, std::placeholders::_1));
+    return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+           << "Vulkan spec doesn't allow BuiltIn VertexId "
+              "to be used.";
   }
 
   return SPV_SUCCESS;
@@ -2427,51 +2569,14 @@
 
 spv_result_t BuiltInsValidator::ValidateLocalInvocationIndexAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    if (spv_result_t error = ValidateI32(
-            decoration, inst,
-            [this, &inst](const std::string& message) -> spv_result_t {
-              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the WebGPU spec BuiltIn "
-                        "LocalInvocationIndex variable needs to be a 32-bit "
-                        "int."
-                     << message;
-            })) {
-      return error;
-    }
-  }
-
   // Seed at reference checks with this built-in.
   return ValidateLocalInvocationIndexAtReference(decoration, inst, inst, inst);
 }
 
 spv_result_t BuiltInsValidator::ValidateLocalInvocationIndexAtReference(
     const Decoration& decoration, const Instruction& built_in_inst,
-    const Instruction& referenced_inst,
+    const Instruction&,
     const Instruction& referenced_from_inst) {
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
-      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << "WebGPU spec allows BuiltIn LocalInvocationIndex to be only "
-                "used for variables with Input storage class. "
-             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
-                                 referenced_from_inst)
-             << " " << GetStorageClassDesc(referenced_from_inst);
-    }
-
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelGLCompute) {
-        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-               << "WebGPU spec allows BuiltIn VertexIndex to be used only "
-                  "with GLCompute execution model. "
-               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
-                                   referenced_from_inst, execution_model);
-      }
-    }
-  }
-
   if (function_id_ == 0) {
     // Propagate this rule to all dependant ids in the global scope.
     id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
@@ -2487,7 +2592,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
@@ -2647,8 +2752,9 @@
             if (operand == SpvBuiltInLayer)
               capability = "ShaderViewportIndexLayerEXT or ShaderLayer";
 
+            uint32_t vuid = (operand == SpvBuiltInLayer) ? 4273 : 4405;
             return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-                   << "Using BuiltIn "
+                   << _.VkErrorID(vuid) << "Using BuiltIn "
                    << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                                                     operand)
                    << " in Vertex or Tessellation execution model requires the "
@@ -2684,33 +2790,18 @@
 
 spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 3,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
-              uint32_t operand = decoration.params()[0];
-              uint32_t vuid = 0;
-              switch (operand) {
-                case SpvBuiltInGlobalInvocationId:
-                  vuid = 4238;
-                  break;
-                case SpvBuiltInLocalInvocationId:
-                  vuid = 4283;
-                  break;
-                case SpvBuiltInNumWorkgroups:
-                  vuid = 4298;
-                  break;
-                case SpvBuiltInWorkgroupId:
-                  vuid = 4424;
-                  break;
-              };
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                      << _.VkErrorID(vuid) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      operand)
+                                                      builtin)
                      << " variable needs to be a 3-component 32-bit int "
                         "vector. "
                      << message;
@@ -2728,31 +2819,16 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  uint32_t operand = decoration.params()[0];
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
-      uint32_t vuid = 0;
-      switch (operand) {
-        case SpvBuiltInGlobalInvocationId:
-          vuid = 4237;
-          break;
-        case SpvBuiltInLocalInvocationId:
-          vuid = 4282;
-          break;
-        case SpvBuiltInNumWorkgroups:
-          vuid = 4297;
-          break;
-        case SpvBuiltInWorkgroupId:
-          vuid = 4423;
-          break;
-      };
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
@@ -2763,30 +2839,13 @@
       bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute ||
                               execution_model == SpvExecutionModelTaskNV ||
                               execution_model == SpvExecutionModelMeshNV;
-      bool has_webgpu_model = execution_model == SpvExecutionModelGLCompute;
-      if ((spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) ||
-          (spvIsWebGPUEnv(_.context()->target_env) && !has_webgpu_model)) {
-        uint32_t vuid = 0;
-        switch (operand) {
-          case SpvBuiltInGlobalInvocationId:
-            vuid = 4236;
-            break;
-          case SpvBuiltInLocalInvocationId:
-            vuid = 4281;
-            break;
-          case SpvBuiltInNumWorkgroups:
-            vuid = 4296;
-            break;
-          case SpvBuiltInWorkgroupId:
-            vuid = 4422;
-            break;
-        };
+      if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                decoration.params()[0])
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                << " to be used only with GLCompute execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -2808,23 +2867,23 @@
 spv_result_t BuiltInsValidator::ValidateComputeI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
             decoration, inst,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid)
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                      << " variable needs to be a 32-bit int "
                         "vector. "
                      << message;
@@ -2842,14 +2901,16 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
@@ -2861,11 +2922,12 @@
                               execution_model == SpvExecutionModelTaskNV ||
                               execution_model == SpvExecutionModelMeshNV;
       if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                decoration.params()[0])
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                << " to be used only with GLCompute execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -2887,23 +2949,23 @@
 spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
             decoration, inst,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid)
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                      << " variable needs to be a 32-bit int. " << message;
             })) {
       return error;
@@ -2912,11 +2974,12 @@
     const SpvStorageClass storage_class = GetStorageClass(inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+             << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -2929,23 +2992,23 @@
 spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 4,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid)
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                      << " variable needs to be a 4-component 32-bit int "
                         "vector. "
                      << message;
@@ -2956,11 +3019,12 @@
     const SpvStorageClass storage_class = GetStorageClass(inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+             << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -2972,7 +3036,7 @@
 
 spv_result_t BuiltInsValidator::ValidateWorkgroupSizeAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spvIsVulkanEnv(_.context()->target_env) &&
         !spvOpcodeIsConstant(inst.opcode())) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -3004,7 +3068,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelGLCompute) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -3283,6 +3347,287 @@
   return SPV_SUCCESS;
 }
 
+spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtDefinition(const Decoration& decoration,
+                                            const Instruction& inst) {
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    if (spv_result_t error = ValidateI32(
+            decoration, inst,
+            [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid) << "According to the "
+                     << spvLogStringForEnv(_.context()->target_env)
+                     << " spec BuiltIn "
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                      builtin)
+                     << " variable needs to be a 32-bit int scalar. "
+                     << message;
+            })) {
+      return error;
+    }
+  }
+
+  return ValidateFragInvocationCountAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+             << " spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << " to be only used for variables with Input storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      if (execution_model != SpvExecutionModelFragment) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid)
+               << spvLogStringForEnv(_.context()->target_env)
+               << " spec allows BuiltIn "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << " to be used only with Fragment execution model. "
+               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                   referenced_from_inst, execution_model);
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+        &BuiltInsValidator::ValidateFragInvocationCountAtReference, this, decoration,
+        built_in_inst, referenced_from_inst, std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateFragSizeAtDefinition(const Decoration& decoration,
+                                            const Instruction& inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    if (spv_result_t error = ValidateI32Vec(
+            decoration, inst, 2,
+            [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid) << "According to the "
+                     << spvLogStringForEnv(_.context()->target_env)
+                     << " spec BuiltIn "
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                      builtin)
+                     << " variable needs to be a 2-component 32-bit int vector. "
+                     << message;
+            })) {
+      return error;
+    }
+  }
+
+  return ValidateFragSizeAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFragSizeAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+             << " spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << " to be only used for variables with Input storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      if (execution_model != SpvExecutionModelFragment) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid)
+               << spvLogStringForEnv(_.context()->target_env)
+               << " spec allows BuiltIn "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << " to be used only with Fragment execution model. "
+               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                   referenced_from_inst, execution_model);
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+        &BuiltInsValidator::ValidateFragSizeAtReference, this, decoration,
+        built_in_inst, referenced_from_inst, std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateFragStencilRefAtDefinition(const Decoration& decoration,
+                                            const Instruction& inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    if (spv_result_t error = ValidateI(
+            decoration, inst,
+            [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid) << "According to the "
+                     << spvLogStringForEnv(_.context()->target_env)
+                     << " spec BuiltIn "
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                      builtin)
+                     << " variable needs to be a int scalar. "
+                     << message;
+            })) {
+      return error;
+    }
+  }
+
+  return ValidateFragStencilRefAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFragStencilRefAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassOutput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+             << " spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << " to be only used for variables with Output storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      if (execution_model != SpvExecutionModelFragment) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid)
+               << spvLogStringForEnv(_.context()->target_env)
+               << " spec allows BuiltIn "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << " to be used only with Fragment execution model. "
+               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                   referenced_from_inst, execution_model);
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+        &BuiltInsValidator::ValidateFragStencilRefAtReference, this, decoration,
+        built_in_inst, referenced_from_inst, std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateFullyCoveredAtDefinition(const Decoration& decoration,
+                                               const Instruction& inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    if (spv_result_t error = ValidateBool(
+            decoration, inst,
+            [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid) << "According to the "
+                     << spvLogStringForEnv(_.context()->target_env)
+                     << " spec BuiltIn "
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                      builtin)
+                     << " variable needs to be a bool scalar. "
+                     << message;
+            })) {
+      return error;
+    }
+  }
+
+  return ValidateFullyCoveredAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFullyCoveredAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+             << " spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << " to be only used for variables with Input storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      if (execution_model != SpvExecutionModelFragment) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid)
+               << spvLogStringForEnv(_.context()->target_env)
+               << " spec allows BuiltIn "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << " to be used only with Fragment execution model. "
+               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                   referenced_from_inst, execution_model);
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+        &BuiltInsValidator::ValidateFullyCoveredAtReference, this, decoration,
+        built_in_inst, referenced_from_inst, std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
 spv_result_t BuiltInsValidator::ValidateSMBuiltinsAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
@@ -3474,6 +3819,174 @@
   return SPV_SUCCESS;
 }
 
+spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
+    const Decoration& decoration, const Instruction& inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    switch (builtin) {
+      case SpvBuiltInHitTNV:
+      case SpvBuiltInRayTminKHR:
+      case SpvBuiltInRayTmaxKHR:
+        // f32 scalar
+        if (spv_result_t error = ValidateF32(
+                decoration, inst,
+                [this, &inst,
+                 builtin](const std::string& message) -> spv_result_t {
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+                  return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                         << _.VkErrorID(vuid)
+                         << "According to the Vulkan spec BuiltIn "
+                         << _.grammar().lookupOperandName(
+                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                         << " variable needs to be a 32-bit float scalar. "
+                         << message;
+                })) {
+          return error;
+        }
+        break;
+      case SpvBuiltInHitKindKHR:
+      case SpvBuiltInInstanceCustomIndexKHR:
+      case SpvBuiltInInstanceId:
+      case SpvBuiltInRayGeometryIndexKHR:
+      case SpvBuiltInIncomingRayFlagsKHR:
+        // i32 scalar
+        if (spv_result_t error = ValidateI32(
+                decoration, inst,
+                [this, &inst,
+                 builtin](const std::string& message) -> spv_result_t {
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+                  return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                         << _.VkErrorID(vuid)
+                         << "According to the Vulkan spec BuiltIn "
+                         << _.grammar().lookupOperandName(
+                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                         << " variable needs to be a 32-bit int scalar. "
+                         << message;
+                })) {
+          return error;
+        }
+        break;
+      case SpvBuiltInObjectRayDirectionKHR:
+      case SpvBuiltInObjectRayOriginKHR:
+      case SpvBuiltInWorldRayDirectionKHR:
+      case SpvBuiltInWorldRayOriginKHR:
+        // f32 vec3
+        if (spv_result_t error = ValidateF32Vec(
+                decoration, inst, 3,
+                [this, &inst,
+                 builtin](const std::string& message) -> spv_result_t {
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+                  return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                         << _.VkErrorID(vuid)
+                         << "According to the Vulkan spec BuiltIn "
+                         << _.grammar().lookupOperandName(
+                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                         << " variable needs to be a 3-component 32-bit float "
+                            "vector. "
+                         << message;
+                })) {
+          return error;
+        }
+        break;
+      case SpvBuiltInLaunchIdKHR:
+      case SpvBuiltInLaunchSizeKHR:
+        // i32 vec3
+        if (spv_result_t error = ValidateI32Vec(
+                decoration, inst, 3,
+                [this, &inst,
+                 builtin](const std::string& message) -> spv_result_t {
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+                  return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                         << _.VkErrorID(vuid)
+                         << "According to the Vulkan spec BuiltIn "
+                         << _.grammar().lookupOperandName(
+                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                         << " variable needs to be a 3-component 32-bit int "
+                            "vector. "
+                         << message;
+                })) {
+          return error;
+        }
+        break;
+      case SpvBuiltInObjectToWorldKHR:
+      case SpvBuiltInWorldToObjectKHR:
+        // f32 mat4x3
+        if (spv_result_t error = ValidateF32Mat(
+                decoration, inst, 3, 4,
+                [this, &inst,
+                 builtin](const std::string& message) -> spv_result_t {
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+                  return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                         << _.VkErrorID(vuid)
+                         << "According to the Vulkan spec BuiltIn "
+                         << _.grammar().lookupOperandName(
+                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                         << " variable needs to be a matrix with"
+                         << " 4 columns of 3-component vectors of 32-bit "
+                            "floats. "
+                         << message;
+                })) {
+          return error;
+        }
+        break;
+      default:
+        assert(0 && "Unexpected ray tracing builtin");
+        break;
+    }
+  }
+
+  // Seed at reference checks with this built-in.
+  return ValidateRayTracingBuiltinsAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                              decoration.params()[0])
+             << " to be only used for variables with Input storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      if (!IsExecutionModelValidForRtBuiltIn(builtin, execution_model)) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid) << "Vulkan spec does not allow BuiltIn "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                decoration.params()[0])
+               << " to be used with the execution model "
+               << _.grammar().lookupOperandName(
+                      SPV_OPERAND_TYPE_EXECUTION_MODEL, execution_model)
+               << ".\n"
+               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                   referenced_from_inst, execution_model);
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
+        std::bind(&BuiltInsValidator::ValidateRayTracingBuiltinsAtReference,
+                  this, decoration, built_in_inst, referenced_from_inst,
+                  std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
 spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
@@ -3486,26 +3999,17 @@
            << "BuiltIns can only target variables, structs or constants";
   }
 
-  if (!spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
-    // Early return. All currently implemented rules are based on Vulkan or
-    // WebGPU spec.
+  if (!spvIsVulkanEnv(_.context()->target_env)) {
+    // Early return. All currently implemented rules are based on Vulkan spec.
     //
     // TODO: If you are adding validation rules for environments other than
-    // Vulkan or WebGPU (or general rules which are not environment
-    // independent), then you need to modify or remove this condition. Consider
-    // also adding early returns into BuiltIn-specific rules, so that the system
-    // doesn't spawn new rules which don't do anything.
+    // Vulkan (or general rules which are not environment independent), then
+    // you need to modify or remove this condition. Consider also adding early
+    // returns into BuiltIn-specific rules, so that the system doesn't spawn new
+    // rules which don't do anything.
     return SPV_SUCCESS;
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env) &&
-      !IsBuiltInValidForWebGPU(label)) {
-    return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-           << "WebGPU does not allow BuiltIn "
-           << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                            decoration.params()[0]);
-  }
-
   // If you are adding a new BuiltIn enum, please register it here.
   // If the newly added enum has validation rules associated with it
   // consider leaving a TODO and/or creating an issue.
@@ -3596,9 +4100,8 @@
     case SpvBuiltInWorkgroupSize: {
       return ValidateWorkgroupSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInVertexId:
-    case SpvBuiltInInstanceId: {
-      return ValidateVertexIdOrInstanceIdAtDefinition(decoration, inst);
+    case SpvBuiltInVertexId: {
+      return ValidateVertexIdAtDefinition(decoration, inst);
     }
     case SpvBuiltInLocalInvocationIndex: {
       return ValidateLocalInvocationIndexAtDefinition(decoration, inst);
@@ -3622,6 +4125,41 @@
     case SpvBuiltInDeviceIndex: {
       return ValidateDeviceIndexAtDefinition(decoration, inst);
     }
+    case SpvBuiltInFragInvocationCountEXT: {
+      // alias SpvBuiltInInvocationsPerPixelNV
+      return ValidateFragInvocationCountAtDefinition(decoration, inst);
+    }
+    case SpvBuiltInFragSizeEXT: {
+      // alias SpvBuiltInFragmentSizeNV
+      return ValidateFragSizeAtDefinition(decoration, inst);
+    }
+    case SpvBuiltInFragStencilRefEXT: {
+      return ValidateFragStencilRefAtDefinition(decoration, inst);
+    }
+    case SpvBuiltInFullyCoveredEXT:{
+      return ValidateFullyCoveredAtDefinition(decoration, inst);
+    }
+    // Ray tracing builtins
+    case SpvBuiltInHitKindKHR:  // alias SpvBuiltInHitKindNV
+    case SpvBuiltInHitTNV:      // NOT present in KHR
+    case SpvBuiltInInstanceId:
+    case SpvBuiltInLaunchIdKHR:           // alias SpvBuiltInLaunchIdNV
+    case SpvBuiltInLaunchSizeKHR:         // alias SpvBuiltInLaunchSizeNV
+    case SpvBuiltInWorldRayOriginKHR:     // alias SpvBuiltInWorldRayOriginNV
+    case SpvBuiltInWorldRayDirectionKHR:  // alias SpvBuiltInWorldRayDirectionNV
+    case SpvBuiltInObjectRayOriginKHR:    // alias SpvBuiltInObjectRayOriginNV
+    case SpvBuiltInObjectRayDirectionKHR:   // alias
+                                            // SpvBuiltInObjectRayDirectionNV
+    case SpvBuiltInRayTminKHR:              // alias SpvBuiltInRayTminNV
+    case SpvBuiltInRayTmaxKHR:              // alias SpvBuiltInRayTmaxNV
+    case SpvBuiltInInstanceCustomIndexKHR:  // alias
+                                            // SpvBuiltInInstanceCustomIndexNV
+    case SpvBuiltInObjectToWorldKHR:        // alias SpvBuiltInObjectToWorldNV
+    case SpvBuiltInWorldToObjectKHR:        // alias SpvBuiltInWorldToObjectNV
+    case SpvBuiltInIncomingRayFlagsKHR:    // alias SpvBuiltInIncomingRayFlagsNV
+    case SpvBuiltInRayGeometryIndexKHR: {  // NOT present in NV
+      return ValidateRayTracingBuiltinsAtDefinition(decoration, inst);
+    }
     case SpvBuiltInWorkDim:
     case SpvBuiltInGlobalSize:
     case SpvBuiltInEnqueuedWorkgroupSize:
@@ -3636,13 +4174,11 @@
     case SpvBuiltInBaryCoordSmoothCentroidAMD:
     case SpvBuiltInBaryCoordSmoothSampleAMD:
     case SpvBuiltInBaryCoordPullModelAMD:
-    case SpvBuiltInFragStencilRefEXT:
     case SpvBuiltInViewportMaskNV:
     case SpvBuiltInSecondaryPositionNV:
     case SpvBuiltInSecondaryViewportMaskNV:
     case SpvBuiltInPositionPerViewNV:
     case SpvBuiltInViewportMaskPerViewNV:
-    case SpvBuiltInFullyCoveredEXT:
     case SpvBuiltInMax:
     case SpvBuiltInTaskCountNV:
     case SpvBuiltInPrimitiveCountNV:
@@ -3654,31 +4190,14 @@
     case SpvBuiltInMeshViewIndicesNV:
     case SpvBuiltInBaryCoordNV:
     case SpvBuiltInBaryCoordNoPerspNV:
-    case SpvBuiltInFragmentSizeNV:         // alias SpvBuiltInFragSizeEXT
-    case SpvBuiltInInvocationsPerPixelNV:  // alias
-                                           // SpvBuiltInFragInvocationCountEXT
-    case SpvBuiltInLaunchIdNV:
-    case SpvBuiltInLaunchSizeNV:
-    case SpvBuiltInWorldRayOriginNV:
-    case SpvBuiltInWorldRayDirectionNV:
-    case SpvBuiltInObjectRayOriginNV:
-    case SpvBuiltInObjectRayDirectionNV:
-    case SpvBuiltInRayTminNV:
-    case SpvBuiltInRayTmaxNV:
-    case SpvBuiltInInstanceCustomIndexNV:
-    case SpvBuiltInObjectToWorldNV:
-    case SpvBuiltInWorldToObjectNV:
-    case SpvBuiltInHitTNV:
-    case SpvBuiltInHitKindNV:
-    case SpvBuiltInIncomingRayFlagsNV:
-    case SpvBuiltInRayGeometryIndexKHR: {
       // No validation rules (for the moment).
       break;
 
-      case SpvBuiltInPrimitiveShadingRateKHR:
-        return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
-      case SpvBuiltInShadingRateKHR:
-        return ValidateShadingRateAtDefinition(decoration, inst);
+    case SpvBuiltInPrimitiveShadingRateKHR: {
+      return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
+    }
+    case SpvBuiltInShadingRateKHR: {
+      return ValidateShadingRateAtDefinition(decoration, inst);
     }
   }
   return SPV_SUCCESS;
diff --git a/third_party/SPIRV-Tools/source/val/validate_capability.cpp b/third_party/SPIRV-Tools/source/val/validate_capability.cpp
index 4b98bc1..8efd554 100644
--- a/third_party/SPIRV-Tools/source/val/validate_capability.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_capability.cpp
@@ -260,19 +260,6 @@
   return false;
 }
 
-bool IsSupportGuaranteedWebGPU(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityMatrix:
-    case SpvCapabilityShader:
-    case SpvCapabilitySampled1D:
-    case SpvCapabilityImage1D:
-    case SpvCapabilityDerivativeControl:
-    case SpvCapabilityImageQuery:
-      return true;
-  }
-  return false;
-}
-
 }  // namespace
 
 // Validates that capability declarations use operands allowed in the current
@@ -365,14 +352,6 @@
              << " Profile specification"
              << " (or requires extension or capability)";
     }
-  } else if (env == SPV_ENV_WEBGPU_0) {
-    if (!IsSupportGuaranteedWebGPU(capability) &&
-        !IsEnabledByExtension(_, capability)) {
-      return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
-             << "Capability " << capability_str()
-             << " is not allowed by WebGPU specification"
-             << " (or requires extension)";
-    }
   }
 
   return SPV_SUCCESS;
diff --git a/third_party/SPIRV-Tools/source/val/validate_cfg.cpp b/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
index 45edd0c..a5f6e6a 100644
--- a/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
@@ -48,11 +48,11 @@
               "basic blocks.";
   }
 
-  const Instruction* type_inst = _.FindDef(inst->type_id());
-  assert(type_inst);
-
-  const SpvOp type_opcode = type_inst->opcode();
-  if (type_opcode == SpvOpTypePointer &&
+  if (_.IsVoidType(inst->type_id())) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "OpPhi must not have void result type";
+  }
+  if (_.IsPointerType(inst->type_id()) &&
       _.addressing_model() == SpvAddressingModelLogical) {
     if (!_.features().variable_pointers &&
         !_.features().variable_pointers_storage_buffer) {
@@ -62,6 +62,10 @@
     }
   }
 
+  const Instruction* type_inst = _.FindDef(inst->type_id());
+  assert(type_inst);
+  const SpvOp type_opcode = type_inst->opcode();
+
   if (!_.options()->before_hlsl_legalization) {
     if (type_opcode == SpvOpTypeSampledImage ||
         (_.HasCapability(SpvCapabilityShader) &&
@@ -816,120 +820,6 @@
   return SPV_SUCCESS;
 }
 
-spv_result_t PerformWebGPUCfgChecks(ValidationState_t& _, Function* function) {
-  for (auto& block : function->ordered_blocks()) {
-    if (block->reachable()) continue;
-    if (block->is_type(kBlockTypeMerge)) {
-      // 1. Find the referencing merge and confirm that it is reachable.
-      BasicBlock* merge_header = function->GetMergeHeader(block);
-      assert(merge_header != nullptr);
-      if (!merge_header->reachable()) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable merge-blocks must be referenced by "
-                  "a reachable merge instruction.";
-      }
-
-      // 2. Check that the only instructions are OpLabel and OpUnreachable.
-      auto* label_inst = block->label();
-      auto* terminator_inst = block->terminator();
-      assert(label_inst != nullptr);
-      assert(terminator_inst != nullptr);
-
-      if (terminator_inst->opcode() != SpvOpUnreachable) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable merge-blocks must terminate with "
-                  "OpUnreachable.";
-      }
-
-      auto label_idx = label_inst - &_.ordered_instructions()[0];
-      auto terminator_idx = terminator_inst - &_.ordered_instructions()[0];
-      if (label_idx + 1 != terminator_idx) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable merge-blocks must only contain an "
-                  "OpLabel and OpUnreachable instruction.";
-      }
-
-      // 3. Use label instruction to confirm there is no uses by branches.
-      for (auto use : label_inst->uses()) {
-        const auto* use_inst = use.first;
-        if (spvOpcodeIsBranch(use_inst->opcode())) {
-          return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-                 << "For WebGPU, unreachable merge-blocks cannot be the target "
-                    "of a branch.";
-        }
-      }
-    } else if (block->is_type(kBlockTypeContinue)) {
-      // 1. Find referencing loop and confirm that it is reachable.
-      std::vector<BasicBlock*> continue_headers =
-          function->GetContinueHeaders(block);
-      if (continue_headers.empty()) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable continue-target must be referenced "
-                  "by a loop instruction.";
-      }
-
-      std::vector<BasicBlock*> reachable_headers(continue_headers.size());
-      auto iter =
-          std::copy_if(continue_headers.begin(), continue_headers.end(),
-                       reachable_headers.begin(),
-                       [](BasicBlock* header) { return header->reachable(); });
-      reachable_headers.resize(std::distance(reachable_headers.begin(), iter));
-
-      if (reachable_headers.empty()) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable continue-target must be referenced "
-                  "by a reachable loop instruction.";
-      }
-
-      // 2. Check that the only instructions are OpLabel and OpBranch.
-      auto* label_inst = block->label();
-      auto* terminator_inst = block->terminator();
-      assert(label_inst != nullptr);
-      assert(terminator_inst != nullptr);
-
-      if (terminator_inst->opcode() != SpvOpBranch) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable continue-target must terminate with "
-                  "OpBranch.";
-      }
-
-      auto label_idx = label_inst - &_.ordered_instructions()[0];
-      auto terminator_idx = terminator_inst - &_.ordered_instructions()[0];
-      if (label_idx + 1 != terminator_idx) {
-        return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-               << "For WebGPU, unreachable continue-target must only contain "
-                  "an OpLabel and an OpBranch instruction.";
-      }
-
-      // 3. Use label instruction to confirm there is no uses by branches.
-      for (auto use : label_inst->uses()) {
-        const auto* use_inst = use.first;
-        if (spvOpcodeIsBranch(use_inst->opcode())) {
-          return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-                 << "For WebGPU, unreachable continue-target cannot be the "
-                    "target of a branch.";
-        }
-      }
-
-      // 4. Confirm that continue-target has a back edge to a reachable loop
-      //    header block.
-      auto branch_target = terminator_inst->GetOperandAs<uint32_t>(0);
-      for (auto* continue_header : reachable_headers) {
-        if (branch_target != continue_header->id()) {
-          return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-                 << "For WebGPU, unreachable continue-target must only have a "
-                    "back edge to a single reachable loop instruction.";
-        }
-      }
-    } else {
-      return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id()))
-             << "For WebGPU, all blocks must be reachable, unless they are "
-             << "degenerate cases of merge-block or continue-target.";
-    }
-  }
-  return SPV_SUCCESS;
-}
-
 spv_result_t PerformCfgChecks(ValidationState_t& _) {
   for (auto& function : _.functions()) {
     // Check all referenced blocks are defined within a function
@@ -1010,13 +900,6 @@
                    << _.getIdName(idom->id());
           }
         }
-
-        // For WebGPU check that all unreachable blocks are degenerate cases for
-        // merge-block or continue-target.
-        if (spvIsWebGPUEnv(_.context()->target_env)) {
-          spv_result_t result = PerformWebGPUCfgChecks(_, &function);
-          if (result != SPV_SUCCESS) return result;
-        }
       }
       // If we have structed control flow, check that no block has a control
       // flow nesting depth larger than the limit.
diff --git a/third_party/SPIRV-Tools/source/val/validate_composites.cpp b/third_party/SPIRV-Tools/source/val/validate_composites.cpp
index eb8a324..5d6c5e3 100644
--- a/third_party/SPIRV-Tools/source/val/validate_composites.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_composites.cpp
@@ -437,6 +437,10 @@
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type and Operand type to be the same";
   }
+  if (_.IsVoidType(result_type)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "OpCopyObject cannot have void result type";
+  }
   return SPV_SUCCESS;
 }
 
@@ -531,12 +535,10 @@
   }
 
   // All Component literals must either be FFFFFFFF or in [0, N - 1].
-  // For WebGPU specifically, Component literals cannot be FFFFFFFF.
   auto vector1ComponentCount = vector1Type->GetOperandAs<uint32_t>(2);
   auto vector2ComponentCount = vector2Type->GetOperandAs<uint32_t>(2);
   auto N = vector1ComponentCount + vector2ComponentCount;
   auto firstLiteralIndex = 4;
-  const auto is_webgpu_env = spvIsWebGPUEnv(_.context()->target_env);
   for (size_t i = firstLiteralIndex; i < inst->operands().size(); ++i) {
     auto literal = inst->GetOperandAs<uint32_t>(i);
     if (literal != 0xFFFFFFFF && literal >= N) {
@@ -544,12 +546,6 @@
              << "Component index " << literal << " is out of bounds for "
              << "combined (Vector1 + Vector2) size of " << N << ".";
     }
-
-    if (is_webgpu_env && literal == 0xFFFFFFFF) {
-      return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Component literal at operand " << i - firstLiteralIndex
-             << " cannot be 0xFFFFFFFF in WebGPU execution environment.";
-    }
   }
 
   if (_.HasCapability(SpvCapabilityShader) &&
diff --git a/third_party/SPIRV-Tools/source/val/validate_decorations.cpp b/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
index d381276..01b0eca 100644
--- a/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
@@ -1260,7 +1260,8 @@
 // decorations.  Otherwise emits a diagnostic and returns something other than
 // SPV_SUCCESS.
 spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate,
-                                           const Instruction& inst) {
+                                           const Instruction& inst,
+                                           const Decoration& decoration) {
   // Validates width-only conversion instruction for floating-point object
   // i.e., OpFConvert
   if (inst.opcode() != SpvOpFConvert) {
@@ -1270,6 +1271,15 @@
               "object.";
   }
 
+  if (spvIsVulkanEnv(vstate.context()->target_env)) {
+    const auto mode = decoration.params()[0];
+    if ((mode != SpvFPRoundingModeRTE) && (mode != SpvFPRoundingModeRTZ)) {
+      return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+             << vstate.VkErrorID(4675)
+             << "In Vulkan, the FPRoundingMode mode must only by RTE or RTZ.";
+    }
+  }
+
   // Validates Object operand of an OpStore
   for (const auto& use : inst.uses()) {
     const auto store = use.first;
@@ -1588,7 +1598,8 @@
           break;
         case SpvDecorationFPRoundingMode:
           if (is_shader)
-            PASS_OR_BAIL(CheckFPRoundingModeForShaders(vstate, *inst));
+            PASS_OR_BAIL(
+                CheckFPRoundingModeForShaders(vstate, *inst, decoration));
           break;
         case SpvDecorationNonWritable:
           PASS_OR_BAIL(CheckNonWritableDecoration(vstate, *inst, decoration));
diff --git a/third_party/SPIRV-Tools/source/val/validate_extensions.cpp b/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
index 17b0446..af6ae2b 100644
--- a/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
@@ -685,34 +685,9 @@
 
 }  // anonymous namespace
 
-spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    std::string extension = GetExtensionString(&(inst->c_inst()));
-
-    if (extension != ExtensionToString(kSPV_KHR_vulkan_memory_model)) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "For WebGPU, the only valid parameter to OpExtension is "
-             << "\"" << ExtensionToString(kSPV_KHR_vulkan_memory_model)
-             << "\".";
-    }
-  }
-
-  return SPV_SUCCESS;
-}
-
 spv_result_t ValidateExtInstImport(ValidationState_t& _,
                                    const Instruction* inst) {
   const auto name_id = 1;
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    const std::string name(reinterpret_cast<const char*>(
-        inst->words().data() + inst->operands()[name_id].offset));
-    if (name != "GLSL.std.450") {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "For WebGPU, the only valid parameter to OpExtInstImport is "
-                "\"GLSL.std.450\".";
-    }
-  }
-
   if (!_.HasExtension(kSPV_KHR_non_semantic_info)) {
     const std::string name(reinterpret_cast<const char*>(
         inst->words().data() + inst->operands()[name_id].offset));
@@ -3149,7 +3124,6 @@
 
 spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
   const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpExtension) return ValidateExtension(_, inst);
   if (opcode == SpvOpExtInstImport) return ValidateExtInstImport(_, inst);
   if (opcode == SpvOpExtInst) return ValidateExtInst(_, inst);
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_id.cpp b/third_party/SPIRV-Tools/source/val/validate_id.cpp
index e1a775a..2bab203 100644
--- a/third_party/SPIRV-Tools/source/val/validate_id.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_id.cpp
@@ -201,7 +201,7 @@
             ret = SPV_SUCCESS;
           }
         } else if (can_have_forward_declared_ids(i)) {
-          if (inst->opcode() == SpvOpTypeStruct &&
+          if (spvOpcodeGeneratesType(inst->opcode()) &&
               !_.IsForwardPointer(operand_word)) {
             ret = _.diag(SPV_ERROR_INVALID_ID, inst)
                   << "Operand " << _.getIdName(operand_word)
diff --git a/third_party/SPIRV-Tools/source/val/validate_image.cpp b/third_party/SPIRV-Tools/source/val/validate_image.cpp
index 299a3ef..fc37f08 100644
--- a/third_party/SPIRV-Tools/source/val/validate_image.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_image.cpp
@@ -16,8 +16,6 @@
 
 // Validates correctness of image instructions.
 
-#include "source/val/validate.h"
-
 #include <string>
 
 #include "source/diagnostic.h"
@@ -25,6 +23,7 @@
 #include "source/spirv_target_env.h"
 #include "source/util/bitutils.h"
 #include "source/val/instruction.h"
+#include "source/val/validate.h"
 #include "source/val/validate_scopes.h"
 #include "source/val/validation_state.h"
 
@@ -234,9 +233,10 @@
 }
 
 // Checks ImageOperand bitfield and respective operands.
+// word_index is the index of the first word after the image-operand mask word.
 spv_result_t ValidateImageOperands(ValidationState_t& _,
                                    const Instruction* inst,
-                                   const ImageTypeInfo& info, uint32_t mask,
+                                   const ImageTypeInfo& info,
                                    uint32_t word_index) {
   static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled();
   (void)kAllImageOperandsHandled;
@@ -244,24 +244,43 @@
   const SpvOp opcode = inst->opcode();
   const size_t num_words = inst->words().size();
 
-  // NonPrivate, Volatile, SignExtend, ZeroExtend take no operand words.
-  const uint32_t mask_bits_having_operands =
-      mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
-                       SpvImageOperandsVolatileTexelKHRMask |
-                       SpvImageOperandsSignExtendMask |
-                       SpvImageOperandsZeroExtendMask);
-  size_t expected_num_image_operand_words =
-      spvtools::utils::CountSetBits(mask_bits_having_operands);
-  if (mask & SpvImageOperandsGradMask) {
-    // Grad uses two words.
-    ++expected_num_image_operand_words;
-  }
+  const bool have_explicit_mask = (word_index - 1 < num_words);
+  const uint32_t mask = have_explicit_mask ? inst->word(word_index - 1) : 0u;
 
-  if (expected_num_image_operand_words != num_words - word_index) {
+  if (have_explicit_mask) {
+    // NonPrivate, Volatile, SignExtend, ZeroExtend take no operand words.
+    const uint32_t mask_bits_having_operands =
+        mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
+                         SpvImageOperandsVolatileTexelKHRMask |
+                         SpvImageOperandsSignExtendMask |
+                         SpvImageOperandsZeroExtendMask);
+    size_t expected_num_image_operand_words =
+        spvtools::utils::CountSetBits(mask_bits_having_operands);
+    if (mask & SpvImageOperandsGradMask) {
+      // Grad uses two words.
+      ++expected_num_image_operand_words;
+    }
+
+    if (expected_num_image_operand_words != num_words - word_index) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Number of image operand ids doesn't correspond to the bit "
+                "mask";
+    }
+  } else if (num_words != word_index - 1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Number of image operand ids doesn't correspond to the bit mask";
   }
 
+  if (info.multisampled & (0 == (mask & SpvImageOperandsSampleMask))) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Image Operand Sample is required for operation on "
+              "multi-sampled image";
+  }
+
+  // After this point, only set bits in the image operands mask can cause
+  // the module to be invalid.
+  if (mask == 0) return SPV_SUCCESS;
+
   if (spvtools::utils::CountSetBits(
           mask & (SpvImageOperandsOffsetMask | SpvImageOperandsConstOffsetMask |
                   SpvImageOperandsConstOffsetsMask)) > 1) {
@@ -296,10 +315,7 @@
                 "or Cube";
     }
 
-    if (info.multisampled != 0) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Operand Bias requires 'MS' parameter to be 0";
-    }
+    // Multisampled is already checked.
   }
 
   if (mask & SpvImageOperandsLodMask) {
@@ -338,10 +354,7 @@
                 "or Cube";
     }
 
-    if (info.multisampled != 0) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Operand Lod requires 'MS' parameter to be 0";
-    }
+    // Multisampled is already checked.
   }
 
   if (mask & SpvImageOperandsGradMask) {
@@ -374,10 +387,7 @@
              << " components, but given " << dy_size;
     }
 
-    if (info.multisampled != 0) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Operand Grad requires 'MS' parameter to be 0";
-    }
+    // Multisampled is already checked.
   }
 
   if (mask & SpvImageOperandsConstOffsetMask) {
@@ -613,12 +623,12 @@
 
     if (info.multisampled != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Image 'MS' parameter to be 0";
+             << "Expected Image 'MS' parameter to be 0";
     }
 
     if (info.arrayed != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Image 'arrayed' parameter to be 0";
+             << "Expected Image 'arrayed' parameter to be 0";
     }
   }
 
@@ -736,17 +746,28 @@
            << "Corrupt image type definition";
   }
 
-  if (spvIsVulkanEnv(_.context()->target_env)) {
+  if (_.IsIntScalarType(info.sampled_type) &&
+      (64 == _.GetBitWidth(info.sampled_type)) &&
+      !_.HasCapability(SpvCapabilityInt64ImageEXT)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Capability Int64ImageEXT is required when using Sampled Type of "
+              "64-bit int";
+  }
+
+  const auto target_env = _.context()->target_env;
+  if (spvIsVulkanEnv(target_env)) {
     if ((!_.IsFloatScalarType(info.sampled_type) &&
          !_.IsIntScalarType(info.sampled_type)) ||
-        (32 != _.GetBitWidth(info.sampled_type) &&
-         (64 != _.GetBitWidth(info.sampled_type) ||
-          !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
+        ((32 != _.GetBitWidth(info.sampled_type)) &&
+         (64 != _.GetBitWidth(info.sampled_type))) ||
+        ((64 == _.GetBitWidth(info.sampled_type)) &&
+         _.IsFloatScalarType(info.sampled_type))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Expected Sampled Type to be a 32-bit int or float "
-                "scalar type for Vulkan environment";
+             << _.VkErrorID(4656)
+             << "Expected Sampled Type to be a 32-bit int, 64-bit int or "
+                "32-bit float scalar type for Vulkan environment";
     }
-  } else if (spvIsOpenCLEnv(_.context()->target_env)) {
+  } else if (spvIsOpenCLEnv(target_env)) {
     if (!_.IsVoidType(info.sampled_type)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Sampled Type must be OpTypeVoid in the OpenCL environment.";
@@ -774,7 +795,7 @@
            << "Invalid Arrayed " << info.arrayed << " (must be 0 or 1)";
   }
 
-  if (spvIsOpenCLEnv(_.context()->target_env)) {
+  if (spvIsOpenCLEnv(target_env)) {
     if ((info.arrayed == 1) && (info.dim != SpvDim1D) &&
         (info.dim != SpvDim2D)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -788,10 +809,10 @@
            << "Invalid MS " << info.multisampled << " (must be 0 or 1)";
   }
 
-  if (spvIsOpenCLEnv(_.context()->target_env)) {
+  if (spvIsOpenCLEnv(target_env)) {
     if (info.multisampled != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "MS must be 0 in the OpenCL environement.";
+             << "MS must be 0 in the OpenCL environment.";
     }
   }
 
@@ -800,6 +821,14 @@
            << "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)";
   }
 
+  if (spvIsVulkanEnv(target_env)) {
+    if (info.sampled == 0) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4657)
+             << "Sampled must be 1 or 2 in the Vulkan environment.";
+    }
+  }
+
   if (spvIsOpenCLEnv(_.context()->target_env)) {
     if (info.sampled != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -829,6 +858,15 @@
     }
   }
 
+  if (info.multisampled && (info.sampled == 2) &&
+      (info.dim != SpvDimSubpassData)) {
+    if (!_.HasCapability(SpvCapabilityStorageImageMultisample)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Capability StorageImageMultisample is required when using "
+                "multisampled storage image";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 
@@ -839,6 +877,20 @@
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
+
+  ImageTypeInfo info;
+  if (!GetImageTypeInfo(_, image_type, &info)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Corrupt image type definition";
+  }
+  // OpenCL requires Sampled=0, checked elsewhere.
+  // Vulkan uses the Sampled=1 case.
+  if ((info.sampled != 0) && (info.sampled != 1)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Sampled image type requires an image type with \"Sampled\" "
+              "operand set to 0 or 1";
+  }
+
   return SPV_SUCCESS;
 }
 
@@ -1066,6 +1118,20 @@
                 "the value 0";
     }
   }
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((info.format != SpvImageFormatR64i) &&
+        (info.format != SpvImageFormatR64ui) &&
+        (info.format != SpvImageFormatR32f) &&
+        (info.format != SpvImageFormatR32i) &&
+        (info.format != SpvImageFormatR32ui)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4658)
+             << "Expected the Image Format in Image to be R64i, R64ui, R32f, "
+                "R32i, or R32ui for Vulkan environment";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 
@@ -1103,6 +1169,14 @@
 
   if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
 
+  if (info.multisampled) {
+    // When using image operands, the Sample image operand is required if and
+    // only if the image is multisampled (MS=1). The Sample image operand is
+    // only allowed for fetch, read, and write.
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Sampling operation is invalid for multisample image";
+  }
+
   if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
     const uint32_t texel_component_type =
         _.GetComponentType(actual_result_type);
@@ -1137,16 +1211,11 @@
            << " components, but given only " << actual_coord_size;
   }
 
-  if (inst->words().size() <= 5) {
-    assert(IsImplicitLod(opcode));
-    return SPV_SUCCESS;
-  }
+  const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
 
-  const uint32_t mask = inst->word(5);
-
-  if (spvIsOpenCLEnv(_.context()->target_env)) {
-    if (opcode == SpvOpImageSampleExplicitLod) {
-      if (mask & SpvImageOperandsConstOffsetMask) {
+  if (mask & SpvImageOperandsConstOffsetMask) {
+    if (spvIsOpenCLEnv(_.context()->target_env)) {
+      if (opcode == SpvOpImageSampleExplicitLod) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "ConstOffset image operand not allowed "
                << "in the OpenCL environment.";
@@ -1155,7 +1224,7 @@
   }
 
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 6))
     return result;
 
   return SPV_SUCCESS;
@@ -1190,6 +1259,14 @@
 
   if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
 
+  if (info.multisampled) {
+    // When using image operands, the Sample image operand is required if and
+    // only if the image is multisampled (MS=1). The Sample image operand is
+    // only allowed for fetch, read, and write.
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Dref sampling operation is invalid for multisample image";
+  }
+
   if (actual_result_type != info.sampled_type) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image 'Sampled Type' to be the same as "
@@ -1216,14 +1293,8 @@
            << "Expected Dref to be of 32-bit float type";
   }
 
-  if (inst->words().size() <= 6) {
-    assert(IsImplicitLod(opcode));
-    return SPV_SUCCESS;
-  }
-
-  const uint32_t mask = inst->word(6);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 7))
     return result;
 
   return SPV_SUCCESS;
@@ -1294,11 +1365,8 @@
            << " components, but given only " << actual_coord_size;
   }
 
-  if (inst->words().size() <= 5) return SPV_SUCCESS;
-
-  const uint32_t mask = inst->word(5);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 6))
     return result;
 
   return SPV_SUCCESS;
@@ -1336,6 +1404,14 @@
            << "Corrupt image type definition";
   }
 
+  if (info.multisampled) {
+    // When using image operands, the Sample image operand is required if and
+    // only if the image is multisampled (MS=1). The Sample image operand is
+    // only allowed for fetch, read, and write.
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Gather operation is invalid for multisample image";
+  }
+
   if (opcode == SpvOpImageDrefGather || opcode == SpvOpImageSparseDrefGather ||
       _.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
     const uint32_t result_component_type =
@@ -1384,11 +1460,8 @@
     }
   }
 
-  if (inst->words().size() <= 6) return SPV_SUCCESS;
-
-  const uint32_t mask = inst->word(6);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 7))
     return result;
 
   return SPV_SUCCESS;
@@ -1408,14 +1481,16 @@
            << " to be int or float scalar or vector type";
   }
 
-#if 0
-  // TODO(atgoo@github.com) Disabled until the spec is clarified.
-  if (_.GetDimension(actual_result_type) != 4) {
-    return _.diag(SPV_ERROR_INVALID_DATA, inst)
-           << "Expected " << GetActualResultTypeStr(opcode)
-           << " to have 4 components";
-  }
-#endif
+  const auto target_env = _.context()->target_env;
+  // Vulkan requires the result to be a 4-element int or float
+  // vector.
+  if (spvIsVulkanEnv(target_env)) {
+    if (_.GetDimension(actual_result_type) != 4) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Expected " << GetActualResultTypeStr(opcode)
+             << " to have 4 components";
+    }
+  }  // Check OpenCL below, after we get the image info.
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
   if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
@@ -1429,6 +1504,29 @@
            << "Corrupt image type definition";
   }
 
+  if (spvIsOpenCLEnv(target_env)) {
+    // In OpenCL, a read from a depth image returns a scalar float. In other
+    // cases, the result is always a 4-element vector.
+    // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Env.html#_data_format_for_reading_and_writing_images
+    // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_C.html#image-read-and-write-functions
+    // The builtins for reading depth images are:
+    //   float read_imagef(aQual image2d_depth_t image, int2 coord)
+    //   float read_imagef(aQual image2d_array_depth_t image, int4 coord)
+    if (info.depth) {
+      if (!_.IsFloatScalarType(actual_result_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected " << GetActualResultTypeStr(opcode)
+               << " from a depth image read to result in a scalar float value";
+      }
+    } else {
+      if (_.GetDimension(actual_result_type) != 4) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected " << GetActualResultTypeStr(opcode)
+               << " to have 4 components";
+      }
+    }
+  }
+
   if (info.dim == SpvDimSubpassData) {
     if (opcode == SpvOpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1477,12 +1575,10 @@
     }
   }
 
-  if (inst->words().size() <= 5) return SPV_SUCCESS;
+  const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
 
-  const uint32_t mask = inst->word(5);
-
-  if (spvIsOpenCLEnv(_.context()->target_env)) {
-    if (mask & SpvImageOperandsConstOffsetMask) {
+  if (mask & SpvImageOperandsConstOffsetMask) {
+    if (spvIsOpenCLEnv(_.context()->target_env)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "ConstOffset image operand not allowed "
              << "in the OpenCL environment.";
@@ -1490,7 +1586,7 @@
   }
 
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 6))
     return result;
 
   return SPV_SUCCESS;
@@ -1566,9 +1662,7 @@
     }
   }
 
-  if (inst->words().size() <= 4) {
-    return SPV_SUCCESS;
-  } else {
+  if (inst->words().size() > 4) {
     if (spvIsOpenCLEnv(_.context()->target_env)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Optional Image Operands are not allowed in the OpenCL "
@@ -1576,9 +1670,8 @@
     }
   }
 
-  const uint32_t mask = inst->word(4);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 5))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 5))
     return result;
 
   return SPV_SUCCESS;
@@ -1649,6 +1742,16 @@
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'MS' must be 0";
   }
 
+  const auto target_env = _.context()->target_env;
+  if (spvIsVulkanEnv(target_env)) {
+    if (info.sampled != 1) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4659)
+             << "OpImageQuerySizeLod must only consume an \"Image\" operand "
+                "whose type has its \"Sampled\" operand set to 1";
+    }
+  }
+
   uint32_t result_num_components = _.GetDimension(result_type);
   if (result_num_components != expected_num_components) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1823,6 +1926,13 @@
            << "Expected Coordinate to have at least " << min_coord_size
            << " components, but given only " << actual_coord_size;
   }
+
+  // The operad is a sampled image.
+  // The sampled image type is already checked to be parameterized by an image
+  // type with Sampled=0 or Sampled=1.  Vulkan bans Sampled=0, and so we have
+  // Sampled=1.  So the validator already enforces Vulkan VUID 4659:
+  //   OpImageQuerySizeLod must only consume an “Image” operand whose type has
+  //   its "Sampled" operand set to 1
   return SPV_SUCCESS;
 }
 
@@ -1859,6 +1969,15 @@
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image 'Dim' must be 1D, 2D, 3D or Cube";
     }
+    const auto target_env = _.context()->target_env;
+    if (spvIsVulkanEnv(target_env)) {
+      if (info.sampled != 1) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << _.VkErrorID(4659)
+               << "OpImageQueryLevels must only consume an \"Image\" operand "
+                  "whose type has its \"Sampled\" operand set to 1";
+      }
+    }
   } else {
     assert(opcode == SpvOpImageQuerySamples);
     if (info.dim != SpvDim2D) {
diff --git a/third_party/SPIRV-Tools/source/val/validate_memory.cpp b/third_party/SPIRV-Tools/source/val/validate_memory.cpp
index d9f8b99..45a232d 100644
--- a/third_party/SPIRV-Tools/source/val/validate_memory.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_memory.cpp
@@ -578,14 +578,15 @@
     }
   }
 
-  // WebGPU & Vulkan Appendix A: Check that if contains initializer, then
+  // Vulkan Appendix A: Check that if contains initializer, then
   // storage class is Output, Private, or Function.
   if (inst->operands().size() > 3 && storage_class != SpvStorageClassOutput &&
       storage_class != SpvStorageClassPrivate &&
       storage_class != SpvStorageClassFunction) {
-    if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+    if (spvIsVulkanEnv(_.context()->target_env)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpVariable, <id> '" << _.getIdName(inst->id())
+             << _.VkErrorID(4651) << "OpVariable, <id> '"
+             << _.getIdName(inst->id())
              << "', has a disallowed initializer & storage class "
              << "combination.\n"
              << "From " << spvLogStringForEnv(_.context()->target_env)
@@ -596,20 +597,6 @@
     }
   }
 
-  // WebGPU: All variables with storage class Output, Private, or Function MUST
-  // have an initializer.
-  if (spvIsWebGPUEnv(_.context()->target_env) && inst->operands().size() <= 3 &&
-      (storage_class == SpvStorageClassOutput ||
-       storage_class == SpvStorageClassPrivate ||
-       storage_class == SpvStorageClassFunction)) {
-    return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpVariable, <id> '" << _.getIdName(inst->id())
-           << "', must have an initializer.\n"
-           << "From WebGPU execution environment spec:\n"
-           << "All variables in the following storage classes must have an "
-           << "initializer: Output, Private, or Function";
-  }
-
   if (storage_class == SpvStorageClassPhysicalStorageBufferEXT) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "PhysicalStorageBufferEXT must not be used with OpVariable.";
@@ -702,41 +689,6 @@
     }
   }
 
-  // WebGPU specific validation rules for OpTypeRuntimeArray
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    // OpTypeRuntimeArray should only ever be in an OpTypeStruct,
-    // so should never appear as a bare variable.
-    if (value_type && value_type->opcode() == SpvOpTypeRuntimeArray) {
-      return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpVariable, <id> '" << _.getIdName(inst->id())
-             << "', is attempting to create memory for an illegal type, "
-             << "OpTypeRuntimeArray.\nFor WebGPU OpTypeRuntimeArray can only "
-             << "appear as the final member of an OpTypeStruct, thus cannot "
-             << "be instantiated via OpVariable";
-    }
-
-    // If an OpStruct has an OpTypeRuntimeArray somewhere within it, then it
-    // must have the storage class StorageBuffer and be decorated
-    // with Block.
-    if (value_type && value_type->opcode() == SpvOpTypeStruct) {
-      if (DoesStructContainRTA(_, value_type)) {
-        if (storage_class == SpvStorageClassStorageBuffer) {
-          if (!_.HasDecoration(value_id, SpvDecorationBlock)) {
-            return _.diag(SPV_ERROR_INVALID_ID, inst)
-                   << "For WebGPU, an OpTypeStruct variable containing an "
-                   << "OpTypeRuntimeArray must be decorated with Block if it "
-                   << "has storage class StorageBuffer.";
-          }
-        } else {
-          return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << "For WebGPU, OpTypeStruct variables containing "
-                 << "OpTypeRuntimeArray must have storage class of "
-                 << "StorageBuffer";
-        }
-      }
-    }
-  }
-
   // Cooperative matrix types can only be allocated in Function or Private
   if ((storage_class != SpvStorageClassFunction &&
        storage_class != SpvStorageClassPrivate) &&
diff --git a/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp b/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp
index 4c582f0..8e47f8a 100644
--- a/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp
@@ -56,55 +56,6 @@
     return SPV_SUCCESS;
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    uint32_t valid_bits;
-    switch (inst->opcode()) {
-      case SpvOpControlBarrier:
-        if (!(value & SpvMemorySemanticsAcquireReleaseMask)) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << "For WebGPU, AcquireRelease must be set for Memory "
-                    "Semantics of OpControlBarrier.";
-        }
-
-        if (!(value & SpvMemorySemanticsWorkgroupMemoryMask)) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << "For WebGPU, WorkgroupMemory must be set for Memory "
-                    "Semantics of OpControlBarrier.";
-        }
-
-        valid_bits = SpvMemorySemanticsAcquireReleaseMask |
-                     SpvMemorySemanticsWorkgroupMemoryMask;
-        if (value & ~valid_bits) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << "For WebGPU only WorkgroupMemory and AcquireRelease may be "
-                    "set for Memory Semantics of OpControlBarrier.";
-        }
-        break;
-      case SpvOpMemoryBarrier:
-        if (!(value & SpvMemorySemanticsImageMemoryMask)) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << "For WebGPU, ImageMemory must be set for Memory Semantics "
-                    "of OpMemoryBarrier.";
-        }
-        valid_bits = SpvMemorySemanticsImageMemoryMask;
-        if (value & ~valid_bits) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << "For WebGPU only ImageMemory may be set for Memory "
-                    "Semantics of OpMemoryBarrier.";
-        }
-        break;
-      default:
-        if (spvOpcodeIsAtomicOp(inst->opcode())) {
-          if (value != 0) {
-            return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                   << "For WebGPU Memory no bits may be set for Memory "
-                      "Semantics of OpAtomic* instructions.";
-          }
-        }
-        break;
-    }
-  }
-
   const size_t num_memory_order_set_bits = spvtools::utils::CountSetBits(
       value & (SpvMemorySemanticsAcquireMask | SpvMemorySemanticsReleaseMask |
                SpvMemorySemanticsAcquireReleaseMask |
@@ -221,7 +172,7 @@
 
     if (opcode == SpvOpMemoryBarrier && !num_memory_order_set_bits) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4649) << spvOpcodeString(opcode)
              << ": Vulkan specification requires Memory Semantics to have "
                 "one "
                 "of the following bits set: Acquire, Release, "
@@ -231,7 +182,7 @@
 
     if (opcode == SpvOpMemoryBarrier && !includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4649) << spvOpcodeString(opcode)
              << ": expected Memory Semantics to include a Vulkan-supported "
                 "storage class";
     }
diff --git a/third_party/SPIRV-Tools/source/val/validate_misc.cpp b/third_party/SPIRV-Tools/source/val/validate_misc.cpp
index f0deedf..0c30f3c 100644
--- a/third_party/SPIRV-Tools/source/val/validate_misc.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_misc.cpp
@@ -26,6 +26,10 @@
 namespace {
 
 spv_result_t ValidateUndef(ValidationState_t& _, const Instruction* inst) {
+  if (_.IsVoidType(inst->type_id())) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Cannot create undefined values with void type";
+  }
   if (_.HasCapability(SpvCapabilityShader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
       !_.IsPointerType(inst->type_id())) {
@@ -33,10 +37,6 @@
            << "Cannot create undefined values with 8- or 16-bit types";
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    return _.diag(SPV_ERROR_INVALID_BINARY, inst) << "OpUndef is disallowed";
-  }
-
   return SPV_SUCCESS;
 }
 
@@ -52,7 +52,7 @@
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
   if (is_const_int32 && value != SpvScopeSubgroup && value != SpvScopeDevice) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
-           << "Scope must be Subgroup or Device";
+           << _.VkErrorID(4652) << "Scope must be Subgroup or Device";
   }
 
   // Result Type must be a 64 - bit unsigned integer type or
diff --git a/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp b/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp
index a7f8d33..c816b75 100644
--- a/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp
@@ -42,7 +42,8 @@
     const auto entry_point_type = _.FindDef(entry_point_type_id);
     if (!entry_point_type || 3 != entry_point_type->words().size()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_point_id)
+             << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> '"
+             << _.getIdName(entry_point_id)
              << "'s function parameter count is not zero.";
     }
   }
@@ -50,7 +51,8 @@
   auto return_type = _.FindDef(entry_point->type_id());
   if (!return_type || SpvOpTypeVoid != return_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_point_id)
+           << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> '"
+           << _.getIdName(entry_point_id)
            << "'s function return type is not void.";
   }
 
@@ -457,31 +459,18 @@
   if (spvIsVulkanEnv(_.context()->target_env)) {
     if (mode == SpvExecutionModeOriginLowerLeft) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4653)
              << "In the Vulkan environment, the OriginLowerLeft execution mode "
                 "must not be used.";
     }
     if (mode == SpvExecutionModePixelCenterInteger) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4654)
              << "In the Vulkan environment, the PixelCenterInteger execution "
                 "mode must not be used.";
     }
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    if (mode != SpvExecutionModeOriginUpperLeft &&
-        mode != SpvExecutionModeDepthReplacing &&
-        mode != SpvExecutionModeDepthGreater &&
-        mode != SpvExecutionModeDepthLess &&
-        mode != SpvExecutionModeDepthUnchanged &&
-        mode != SpvExecutionModeLocalSize &&
-        mode != SpvExecutionModeLocalSizeHint) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Execution mode must be one of OriginUpperLeft, "
-                "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
-                "LocalSize, or LocalSizeHint for WebGPU environment.";
-    }
-  }
-
   return SPV_SUCCESS;
 }
 
@@ -496,13 +485,6 @@
               "the VulkanKHR memory model is used.";
   }
 
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    if (_.addressing_model() != SpvAddressingModelLogical) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Addressing model must be Logical for WebGPU environment.";
-    }
-  }
-
   if (spvIsOpenCLEnv(_.context()->target_env)) {
     if ((_.addressing_model() != SpvAddressingModelPhysical32) &&
         (_.addressing_model() != SpvAddressingModelPhysical64)) {
@@ -516,6 +498,15 @@
     }
   }
 
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((_.addressing_model() != SpvAddressingModelLogical) &&
+        (_.addressing_model() != SpvAddressingModelPhysicalStorageBuffer64)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4635)
+             << "Addressing model must be Logical or PhysicalStorageBuffer64 "
+             << "in the Vulkan environment.";
+    }
+  }
   return SPV_SUCCESS;
 }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp b/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp
index 8dcf974..2b6eb8b 100644
--- a/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp
@@ -47,6 +47,19 @@
                                                    "vector of four components "
                                                    "of integer type scalar";
   }
+
+  const auto group = inst->GetOperandAs<uint32_t>(3);
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((group != SpvGroupOperationReduce) &&
+        (group != SpvGroupOperationInclusiveScan) &&
+        (group != SpvGroupOperationExclusiveScan)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4685)
+             << "In Vulkan: The OpGroupNonUniformBallotBitCount group "
+                "operation must be only: Reduce, InclusiveScan, or "
+                "ExclusiveScan.";
+    }
+  }
   return SPV_SUCCESS;
 }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_scopes.cpp b/third_party/SPIRV-Tools/source/val/validate_scopes.cpp
index a6fb26d..a92f7fd 100644
--- a/third_party/SPIRV-Tools/source/val/validate_scopes.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_scopes.cpp
@@ -99,7 +99,7 @@
       if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
           value != SpvScopeSubgroup) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
-               << spvOpcodeString(opcode)
+               << _.VkErrorID(4642) << spvOpcodeString(opcode)
                << ": in Vulkan environment Execution scope is limited to "
                << "Subgroup";
       }
@@ -137,30 +137,6 @@
     }
   }
 
-  // WebGPU Specific rules
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    if (value != SpvScopeWorkgroup) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
-             << ": in WebGPU environment Execution Scope is limited to "
-             << "Workgroup";
-    } else {
-      _.function(inst->function()->id())
-          ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelGLCompute) {
-                  if (message) {
-                    *message =
-                        ": in WebGPU environment, Workgroup Execution Scope is "
-                        "limited to GLCompute execution model";
-                  }
-                  return false;
-                }
-                return true;
-              });
-    }
-  }
-
   // TODO(atgoo@github.com) Add checks for OpenCL and OpenGL environments.
 
   // General SPIRV rules
@@ -214,7 +190,7 @@
   if (spvIsVulkanEnv(_.context()->target_env)) {
     if (value == SpvScopeCrossDevice) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4638) << spvOpcodeString(opcode)
              << ": in Vulkan environment, Memory Scope cannot be CrossDevice";
     }
     // Vulkan 1.0 specifc rules
@@ -222,7 +198,7 @@
         value != SpvScopeDevice && value != SpvScopeWorkgroup &&
         value != SpvScopeInvocation) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4638) << spvOpcodeString(opcode)
              << ": in Vulkan 1.0 environment Memory Scope is limited to "
              << "Device, Workgroup and Invocation";
     }
@@ -233,15 +209,16 @@
         value != SpvScopeSubgroup && value != SpvScopeInvocation &&
         value != SpvScopeShaderCallKHR) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4638) << spvOpcodeString(opcode)
              << ": in Vulkan 1.1 and 1.2 environment Memory Scope is limited "
              << "to Device, Workgroup, Invocation, and ShaderCall";
     }
 
     if (value == SpvScopeShaderCallKHR) {
+      std::string errorVUID = _.VkErrorID(4640);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
+              [errorVUID](SpvExecutionModel model, std::string* message) {
                 if (model != SpvExecutionModelRayGenerationKHR &&
                     model != SpvExecutionModelIntersectionKHR &&
                     model != SpvExecutionModelAnyHitKHR &&
@@ -250,6 +227,7 @@
                     model != SpvExecutionModelCallableKHR) {
                   if (message) {
                     *message =
+                        errorVUID +
                         "ShaderCallKHR Memory Scope requires a ray tracing "
                         "execution model";
                   }
@@ -258,56 +236,19 @@
                 return true;
               });
     }
-  }
-
-  // WebGPU specific rules
-  if (spvIsWebGPUEnv(_.context()->target_env)) {
-    switch (inst->opcode()) {
-      case SpvOpControlBarrier:
-        if (value != SpvScopeWorkgroup) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << spvOpcodeString(opcode)
-                 << ": in WebGPU environment Memory Scope is limited to "
-                 << "Workgroup for OpControlBarrier";
-        }
-        break;
-      case SpvOpMemoryBarrier:
-        if (value != SpvScopeWorkgroup) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << spvOpcodeString(opcode)
-                 << ": in WebGPU environment Memory Scope is limited to "
-                 << "Workgroup for OpMemoryBarrier";
-        }
-        break;
-      default:
-        if (spvOpcodeIsAtomicOp(inst->opcode())) {
-          if (value != SpvScopeQueueFamilyKHR) {
-            return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                   << spvOpcodeString(opcode)
-                   << ": in WebGPU environment Memory Scope is limited to "
-                   << "QueueFamilyKHR for OpAtomic* operations";
-          }
-        }
-
-        if (value != SpvScopeWorkgroup && value != SpvScopeInvocation &&
-            value != SpvScopeQueueFamilyKHR) {
-          return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << spvOpcodeString(opcode)
-                 << ": in WebGPU environment Memory Scope is limited to "
-                 << "Workgroup, Invocation, and QueueFamilyKHR";
-        }
-        break;
-    }
 
     if (value == SpvScopeWorkgroup) {
+      std::string errorVUID = _.VkErrorID(4639);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelGLCompute) {
+              [errorVUID](SpvExecutionModel model, std::string* message) {
+                if (model != SpvExecutionModelGLCompute &&
+                    model != SpvExecutionModelTaskNV &&
+                    model != SpvExecutionModelMeshNV) {
                   if (message) {
-                    *message =
-                        ": in WebGPU environment, Workgroup Memory Scope is "
-                        "limited to GLCompute execution model";
+                    *message = errorVUID +
+                               "Workgroup Memory Scope is limited to MeshNV, "
+                               "TaskNV, and GLCompute execution model";
                   }
                   return false;
                 }
diff --git a/third_party/SPIRV-Tools/source/val/validate_type.cpp b/third_party/SPIRV-Tools/source/val/validate_type.cpp
index 5924c69..6a5ea3c 100644
--- a/third_party/SPIRV-Tools/source/val/validate_type.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_type.cpp
@@ -40,21 +40,6 @@
   return static_cast<int64_t>(uint64_t(lo_word) | uint64_t(hi_word) << 32);
 }
 
-// Returns, as an uint64_t, the literal value from an OpConstant or the
-// default value of an OpSpecConstant, assuming it is an integral type.
-// For signed integers, relies the rule that literal value is sign extended
-// to fill out to word granularity.  Assumes that the constant value
-// has
-int64_t ConstantLiteralAsUint64(uint32_t width,
-                                const std::vector<uint32_t>& const_words) {
-  const uint32_t lo_word = const_words[3];
-  if (width <= 32) return lo_word;
-  assert(width <= 64);
-  assert(const_words.size() > 4);
-  const uint32_t hi_word = const_words[4];  // Must exist, per spec.
-  return (uint64_t(lo_word) | uint64_t(hi_word) << 32);
-}
-
 // Validates that type declarations are unique, unless multiple declarations
 // of the same data type are allowed by the specification.
 // (see section 2.8 Types and Variables)
@@ -240,7 +225,7 @@
            << "' is a void type.";
   }
 
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env) &&
+  if (spvIsVulkanEnv(_.context()->target_env) &&
       element_type->opcode() == SpvOpTypeRuntimeArray) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeArray Element Type <id> '" << _.getIdName(element_type_id)
@@ -279,18 +264,6 @@
                << "OpTypeArray Length <id> '" << _.getIdName(length_id)
                << "' default value must be at least 1: found " << ivalue;
       }
-      if (spvIsWebGPUEnv(_.context()->target_env)) {
-        // WebGPU has maximum integer width of 32 bits, and max array size
-        // is one more than the max signed integer representation.
-        const uint64_t max_permitted = (uint64_t(1) << 31);
-        const uint64_t uvalue = ConstantLiteralAsUint64(width, length->words());
-        if (uvalue > max_permitted) {
-          return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << "OpTypeArray Length <id> '" << _.getIdName(length_id)
-                 << "' size exceeds max value " << max_permitted
-                 << " permitted by WebGPU: got " << uvalue;
-        }
-      }
     } break;
     case SpvOpConstantNull:
       return _.diag(SPV_ERROR_INVALID_ID, inst)
@@ -322,7 +295,7 @@
            << _.getIdName(element_id) << "' is a void type.";
   }
 
-  if (spvIsVulkanOrWebGPUEnv(_.context()->target_env) &&
+  if (spvIsVulkanEnv(_.context()->target_env) &&
       element_type->opcode() == SpvOpTypeRuntimeArray) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeRuntimeArray Element Type <id> '"
@@ -394,7 +367,7 @@
              << ".";
     }
 
-    if (spvIsVulkanOrWebGPUEnv(_.context()->target_env) &&
+    if (spvIsVulkanEnv(_.context()->target_env) &&
         member_type->opcode() == SpvOpTypeRuntimeArray) {
       const bool is_last_member =
           member_type_index == inst->operands().size() - 1;
@@ -555,8 +528,8 @@
            << "Pointer type in OpTypeForwardPointer is not a pointer type.";
   }
 
-  if (inst->GetOperandAs<uint32_t>(1) !=
-      pointer_type_inst->GetOperandAs<uint32_t>(1)) {
+  const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
+  if (storage_class != pointer_type_inst->GetOperandAs<uint32_t>(1)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Storage class in OpTypeForwardPointer does not match the "
            << "pointer definition.";
@@ -569,6 +542,15 @@
            << "Forward pointers must point to a structure";
   }
 
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if (storage_class != SpvStorageClassPhysicalStorageBuffer) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << _.VkErrorID(4711)
+             << "In Vulkan, OpTypeForwardPointer must have "
+             << "a storage class of PhysicalStorageBuffer.";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 
diff --git a/third_party/SPIRV-Tools/source/val/validation_state.cpp b/third_party/SPIRV-Tools/source/val/validation_state.cpp
index cb69dda..b9269db 100644
--- a/third_party/SPIRV-Tools/source/val/validation_state.cpp
+++ b/third_party/SPIRV-Tools/source/val/validation_state.cpp
@@ -1240,23 +1240,6 @@
 
 bool ValidationState_t::IsValidStorageClass(
     SpvStorageClass storage_class) const {
-  if (spvIsWebGPUEnv(context()->target_env)) {
-    switch (storage_class) {
-      case SpvStorageClassUniformConstant:
-      case SpvStorageClassUniform:
-      case SpvStorageClassStorageBuffer:
-      case SpvStorageClassInput:
-      case SpvStorageClassOutput:
-      case SpvStorageClassImage:
-      case SpvStorageClassWorkgroup:
-      case SpvStorageClassPrivate:
-      case SpvStorageClassFunction:
-        return true;
-      default:
-        return false;
-    }
-  }
-
   if (spvIsVulkanEnv(context()->target_env)) {
     switch (storage_class) {
       case SpvStorageClassUniformConstant:
@@ -1315,10 +1298,22 @@
       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04186);
     case 4187:
       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
+    case 4188:
+      return VUID_WRAP(VUID-ClipDistance-ClipDistance-04188);
+    case 4189:
+      return VUID_WRAP(VUID-ClipDistance-ClipDistance-04189);
+    case 4190:
+      return VUID_WRAP(VUID-ClipDistance-ClipDistance-04190);
     case 4191:
       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
     case 4196:
       return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
+    case 4197:
+      return VUID_WRAP(VUID-CullDistance-CullDistance-04197);
+    case 4198:
+      return VUID_WRAP(VUID-CullDistance-CullDistance-04198);
+    case 4199:
+      return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
     case 4200:
       return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
     case 4205:
@@ -1345,12 +1340,36 @@
       return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
     case 4216:
       return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
+    case 4217:
+      return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
+    case 4218:
+      return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
+    case 4219:
+      return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
+    case 4220:
+      return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
+    case 4221:
+      return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
+    case 4222:
+      return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
+    case 4223:
+      return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
+    case 4224:
+      return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
+    case 4225:
+      return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
     case 4229:
       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
     case 4230:
       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
     case 4231:
       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
+    case 4232:
+      return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
+    case 4233:
+      return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
+    case 4234:
+      return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
     case 4236:
       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
     case 4237:
@@ -1363,6 +1382,36 @@
       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
     case 4241:
       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
+    case 4242:
+      return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04242);
+    case 4243:
+      return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04243);
+    case 4244:
+      return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04244);
+    case 4245:
+      return VUID_WRAP(VUID-HitTNV-HitTNV-04245);
+    case 4246:
+      return VUID_WRAP(VUID-HitTNV-HitTNV-04246);
+    case 4247:
+      return VUID_WRAP(VUID-HitTNV-HitTNV-04247);
+    case 4248:
+      return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248);
+    case 4249:
+      return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249);
+    case 4250:
+      return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250);
+    case 4251:
+      return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251);
+    case 4252:
+      return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252);
+    case 4253:
+      return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253);
+    case 4254:
+      return VUID_WRAP(VUID-InstanceId-InstanceId-04254);
+    case 4255:
+      return VUID_WRAP(VUID-InstanceId-InstanceId-04255);
+    case 4256:
+      return VUID_WRAP(VUID-InstanceId-InstanceId-04256);
     case 4257:
       return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
     case 4258:
@@ -1375,8 +1424,22 @@
       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
     case 4265:
       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
+    case 4266:
+      return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04266);
+    case 4267:
+      return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04267);
+    case 4268:
+      return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04268);
+    case 4269:
+      return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04269);
+    case 4270:
+      return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04270);
+    case 4271:
+      return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04271);
     case 4272:
       return VUID_WRAP(VUID-Layer-Layer-04272);
+    case 4273:
+      return VUID_WRAP(VUID-Layer-Layer-04273);
     case 4274:
       return VUID_WRAP(VUID-Layer-Layer-04274);
     case 4275:
@@ -1389,12 +1452,36 @@
       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
     case 4283:
       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
+    case 4293:
+      return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
+    case 4294:
+      return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
+    case 4295:
+      return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
     case 4296:
       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
     case 4297:
       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04297);
     case 4298:
       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04298);
+    case 4299:
+      return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299);
+    case 4300:
+      return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300);
+    case 4301:
+      return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301);
+    case 4302:
+      return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302);
+    case 4303:
+      return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303);
+    case 4304:
+      return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304);
+    case 4305:
+      return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305);
+    case 4306:
+      return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306);
+    case 4307:
+      return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307);
     case 4308:
       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
     case 4309:
@@ -1417,6 +1504,8 @@
       return VUID_WRAP(VUID-PointSize-PointSize-04317);
     case 4318:
       return VUID_WRAP(VUID-Position-Position-04318);
+    case 4319:
+      return VUID_WRAP(VUID-Position-Position-04319);
     case 4320:
       return VUID_WRAP(VUID-Position-Position-04320);
     case 4321:
@@ -1427,6 +1516,24 @@
       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
     case 4337:
       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
+    case 4345:
+      return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345);
+    case 4346:
+      return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346);
+    case 4347:
+      return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347);
+    case 4348:
+      return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04348);
+    case 4349:
+      return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04349);
+    case 4350:
+      return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04350);
+    case 4351:
+      return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04351);
+    case 4352:
+      return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04352);
+    case 4353:
+      return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04353);
     case 4354:
       return VUID_WRAP(VUID-SampleId-SampleId-04354);
     case 4355:
@@ -1445,6 +1552,40 @@
       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
     case 4362:
       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
+    case 4367:
+      return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
+    case 4368:
+      return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
+    case 4369:
+      return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
+    case 4370:
+      return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
+    case 4371:
+      return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
+    case 4372:
+      return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
+    case 4373:
+      return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
+    case 4374:
+      return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
+    case 4375:
+      return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
+    case 4376:
+      return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
+    case 4377:
+      return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
+    case 4378:
+      return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
+    case 4379:
+      return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
+    case 4380:
+      return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
+    case 4381:
+      return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
+    case 4382:
+      return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
+    case 4383:
+      return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
     case 4387:
       return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
     case 4388:
@@ -1453,10 +1594,18 @@
       return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
     case 4390:
       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
+    case 4391:
+      return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04391);
+    case 4392:
+      return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04392);
     case 4393:
       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
     case 4394:
       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
+    case 4395:
+      return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04395);
+    case 4396:
+      return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04396);
     case 4397:
       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
     case 4398:
@@ -1473,6 +1622,8 @@
       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
     case 4404:
       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
+    case 4405:
+      return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04405);
     case 4406:
       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
     case 4407:
@@ -1491,6 +1642,24 @@
       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
     case 4427:
       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
+    case 4428:
+      return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428);
+    case 4429:
+      return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429);
+    case 4430:
+      return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430);
+    case 4431:
+      return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431);
+    case 4432:
+      return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432);
+    case 4433:
+      return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433);
+    case 4434:
+      return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04434);
+    case 4435:
+      return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04435);
+    case 4436:
+      return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04436);
     case 4484:
       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
     case 4485:
@@ -1503,6 +1672,44 @@
       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
     case 4492:
       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
+    case 4633:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
+    case 4635:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
+    case 4638:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
+    case 4639:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04639);
+    case 4640:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
+    case 4642:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
+    case 4649:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04649);
+    case 4651:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
+    case 4652:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
+    case 4653:
+      return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
+    case 4654:
+      return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
+    case 4656:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
+    case 4657:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
+    case 4658:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
+    case 4669:
+      return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
+    case 4675:
+      return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
+    case 4685:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
+    case 4686:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
+    case 4711:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
     default:
       return "";  // unknown id
   };
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_duplicate_region_with_selection_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_duplicate_region_with_selection_test.cpp
index f3738e7..31fb9a2 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_duplicate_region_with_selection_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_duplicate_region_with_selection_test.cpp
@@ -1334,6 +1334,9 @@
                OpBranch %50
          %50 = OpLabel
          %51 = OpCopyObject %7 %12
+               OpBranch %52
+         %52 = OpLabel
+         %53 = OpCopyObject %7 %51
                OpReturn
                OpFunctionEnd
     )";
@@ -2275,6 +2278,207 @@
                    .IsApplicable(context.get(), transformation_context));
 }
 
+TEST(TransformationDuplicateRegionWithSelectionTest,
+     DoNotProduceOpPhiWithVoidType) {
+  std::string reference_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+         %10 = OpTypeBool
+         %11 = OpConstantTrue %10
+          %4 = OpFunction %2 None %3
+         %12 = OpLabel
+               OpBranch %5
+          %5 = OpLabel
+          %8 = OpFunctionCall %2 %6
+               OpReturn
+               OpFunctionEnd
+          %6 = OpFunction %2 None %3
+          %7 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_4;
+  const auto consumer = nullptr;
+  const auto context =
+      BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
+  spvtools::ValidatorOptions validator_options;
+  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+                                               kConsoleMessageConsumer));
+  TransformationContext transformation_context(
+      MakeUnique<FactManager>(context.get()), validator_options);
+
+  TransformationDuplicateRegionWithSelection transformation(
+      100, 11, 101, 5, 5, {{5, 102}}, {{8, 103}}, {});
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+                                               kConsoleMessageConsumer));
+
+  std::string expected_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+         %10 = OpTypeBool
+         %11 = OpConstantTrue %10
+          %4 = OpFunction %2 None %3
+         %12 = OpLabel
+               OpBranch %100
+        %100 = OpLabel
+               OpSelectionMerge %101 None
+               OpBranchConditional %11 %5 %102
+          %5 = OpLabel
+          %8 = OpFunctionCall %2 %6
+               OpBranch %101
+        %102 = OpLabel
+        %103 = OpFunctionCall %2 %6
+               OpBranch %101
+        %101 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %6 = OpFunction %2 None %3
+          %7 = OpLabel
+               OpReturn
+               OpFunctionEnd
+        )";
+
+  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
+}
+
+TEST(TransformationDuplicateRegionWithSelectionTest,
+     DoNotProduceOpPhiWithDisallowedType) {
+  std::string reference_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpDecorate %13 DescriptorSet 0
+               OpDecorate %13 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+         %10 = OpTypeImage %6 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+         %12 = OpTypePointer UniformConstant %11
+         %13 = OpVariable %12 UniformConstant
+         %15 = OpConstant %6 1
+         %16 = OpConstantComposite %7 %15 %15
+         %17 = OpTypeVector %6 4
+         %19 = OpTypeInt 32 0
+         %20 = OpConstant %19 0
+         %22 = OpTypePointer Function %6
+         %90 = OpTypeBool
+         %91 = OpConstantTrue %90
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %9 = OpVariable %8 Function
+               OpBranch %81
+         %81 = OpLabel
+         %14 = OpLoad %11 %13
+         %18 = OpImageSampleImplicitLod %17 %14 %16
+         %21 = OpCompositeExtract %6 %18 0
+         %23 = OpAccessChain %22 %9 %20
+               OpStore %23 %21
+               OpBranch %80
+         %80 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context =
+      BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
+  spvtools::ValidatorOptions validator_options;
+  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+                                               kConsoleMessageConsumer));
+  TransformationContext transformation_context(
+      MakeUnique<FactManager>(context.get()), validator_options);
+
+  TransformationDuplicateRegionWithSelection transformation(
+      100, 91, 101, 81, 81, {{81, 102}},
+      {{14, 103}, {18, 104}, {21, 105}, {23, 106}}, {{18, 107}, {21, 108}});
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+                                               kConsoleMessageConsumer));
+
+  std::string expected_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpDecorate %13 DescriptorSet 0
+               OpDecorate %13 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+         %10 = OpTypeImage %6 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+         %12 = OpTypePointer UniformConstant %11
+         %13 = OpVariable %12 UniformConstant
+         %15 = OpConstant %6 1
+         %16 = OpConstantComposite %7 %15 %15
+         %17 = OpTypeVector %6 4
+         %19 = OpTypeInt 32 0
+         %20 = OpConstant %19 0
+         %22 = OpTypePointer Function %6
+         %90 = OpTypeBool
+         %91 = OpConstantTrue %90
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %9 = OpVariable %8 Function
+               OpBranch %100
+        %100 = OpLabel
+               OpSelectionMerge %101 None
+               OpBranchConditional %91 %81 %102
+         %81 = OpLabel
+         %14 = OpLoad %11 %13
+         %18 = OpImageSampleImplicitLod %17 %14 %16
+         %21 = OpCompositeExtract %6 %18 0
+         %23 = OpAccessChain %22 %9 %20
+               OpStore %23 %21
+               OpBranch %101
+        %102 = OpLabel
+        %103 = OpLoad %11 %13
+        %104 = OpImageSampleImplicitLod %17 %103 %16
+        %105 = OpCompositeExtract %6 %104 0
+        %106 = OpAccessChain %22 %9 %20
+               OpStore %106 %105
+               OpBranch %101
+        %101 = OpLabel
+        %107 = OpPhi %17 %18 %81 %104 %102
+        %108 = OpPhi %6 %21 %81 %105 %102
+               OpBranch %80
+         %80 = OpLabel
+               OpReturn
+               OpFunctionEnd
+        )";
+
+  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp
index 540275a..1a0ff6a 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp
@@ -666,7 +666,6 @@
                OpBranchConditional %5 %13 %12
          %13 = OpLabel
          %14 = OpFunctionCall %3 %11
-         %15 = OpCopyObject %3 %14
                OpBranch %12
          %12 = OpLabel
                OpReturn
@@ -774,7 +773,6 @@
                OpBranchConditional %5 %13 %12
          %13 = OpLabel
          %14 = OpFunctionCall %3 %11
-         %15 = OpCopyObject %3 %14
                OpBranch %12
          %12 = OpLabel
                OpReturn
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_outline_function_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_outline_function_test.cpp
index 6c0bff4..c567680 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_outline_function_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_outline_function_test.cpp
@@ -2531,98 +2531,6 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 }
 
-TEST(TransformationOutlineFunctionTest, SkipVoidOutputId) {
-  std::string shader = R"(
-               OpCapability Shader
-          %1 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint Fragment %6 "main"
-               OpExecutionMode %6 OriginUpperLeft
-               OpSource ESSL 310
-          %2 = OpTypeVoid
-          %3 = OpTypeFunction %2
-         %21 = OpTypeBool
-         %81 = OpConstantTrue %21
-          %6 = OpFunction %2 None %3
-          %7 = OpLabel
-               OpBranch %80
-         %80 = OpLabel
-         %84 = OpFunctionCall %2 %87
-               OpBranch %90
-         %90 = OpLabel
-         %86 = OpPhi %2 %84 %80
-               OpReturn
-               OpFunctionEnd
-         %87 = OpFunction %2 None %3
-         %88 = OpLabel
-               OpReturn
-               OpFunctionEnd
-  )";
-
-  const auto env = SPV_ENV_UNIVERSAL_1_5;
-  const auto consumer = nullptr;
-  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
-  spvtools::ValidatorOptions validator_options;
-  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
-                                               kConsoleMessageConsumer));
-  TransformationContext transformation_context(
-      MakeUnique<FactManager>(context.get()), validator_options);
-  TransformationOutlineFunction transformation(
-      /*entry_block*/ 80,
-      /*exit_block*/ 80,
-      /*new_function_struct_return_type_id*/ 300,
-      /*new_function_type_id*/ 301,
-      /*new_function_id*/ 302,
-      /*new_function_region_entry_block*/ 304,
-      /*new_caller_result_id*/ 305,
-      /*new_callee_result_id*/ 306,
-      /*input_id_to_fresh_id*/ {},
-      /*output_id_to_fresh_id*/ {{84, 307}});
-
-  ASSERT_TRUE(
-      transformation.IsApplicable(context.get(), transformation_context));
-  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
-                                               kConsoleMessageConsumer));
-
-  std::string after_transformation = R"(
-               OpCapability Shader
-          %1 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint Fragment %6 "main"
-               OpExecutionMode %6 OriginUpperLeft
-               OpSource ESSL 310
-          %2 = OpTypeVoid
-          %3 = OpTypeFunction %2
-         %21 = OpTypeBool
-         %81 = OpConstantTrue %21
-        %300 = OpTypeStruct
-        %301 = OpTypeFunction %300
-          %6 = OpFunction %2 None %3
-          %7 = OpLabel
-               OpBranch %80
-         %80 = OpLabel
-        %305 = OpFunctionCall %300 %302
-         %84 = OpUndef %2
-               OpBranch %90
-         %90 = OpLabel
-         %86 = OpPhi %2 %84 %80
-               OpReturn
-               OpFunctionEnd
-         %87 = OpFunction %2 None %3
-         %88 = OpLabel
-               OpReturn
-               OpFunctionEnd
-        %302 = OpFunction %300 None %301
-        %304 = OpLabel
-        %307 = OpFunctionCall %2 %87
-        %306 = OpCompositeConstruct %300
-               OpReturnValue %306
-               OpFunctionEnd
-  )";
-  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
-}
-
 TEST(TransformationOutlineFunctionTest, Miscellaneous1) {
   // This tests outlining of some non-trivial code, and also tests the way
   // overflow ids are used by the transformation.
diff --git a/third_party/SPIRV-Tools/test/fuzzers/BUILD.gn b/third_party/SPIRV-Tools/test/fuzzers/BUILD.gn
index be1258a..ec09b2b 100644
--- a/third_party/SPIRV-Tools/test/fuzzers/BUILD.gn
+++ b/third_party/SPIRV-Tools/test/fuzzers/BUILD.gn
@@ -39,10 +39,7 @@
       ":spvtools_opt_legalization_fuzzer",
       ":spvtools_opt_performance_fuzzer",
       ":spvtools_opt_size_fuzzer",
-      ":spvtools_opt_webgputovulkan_fuzzer",
-      ":spvtools_opt_vulkantowebgpu_fuzzer",
       ":spvtools_val_fuzzer",
-      ":spvtools_val_webgpu_fuzzer",
     ]
   }
 }
@@ -104,31 +101,12 @@
   ]
 }
 
-
-spvtools_fuzzer("spvtools_opt_webgputovulkan_fuzzer_src") {
-  sources = [
-    "spvtools_opt_webgputovulkan_fuzzer.cpp",
-  ]
-}
-
-spvtools_fuzzer("spvtools_opt_vulkantowebgpu_fuzzer_src") {
-  sources = [
-    "spvtools_opt_vulkantowebgpu_fuzzer.cpp",
-  ]
-}
-
 spvtools_fuzzer("spvtools_val_fuzzer_src") {
   sources = [
     "spvtools_val_fuzzer.cpp",
   ]
 }
 
-spvtools_fuzzer("spvtools_val_webgpu_fuzzer_src") {
-  sources = [
-    "spvtools_val_webgpu_fuzzer.cpp",
-  ]
-}
-
 if (!build_with_chromium || use_fuzzing_engine) {
   fuzzer_test("spvtools_as_fuzzer") {
     sources = []
@@ -181,22 +159,6 @@
     seed_corpus = "corpora/spv"
   }
 
-  fuzzer_test("spvtools_opt_webgputovulkan_fuzzer") {
-    sources = []
-    deps = [
-      ":spvtools_opt_webgputovulkan_fuzzer_src",
-    ]
-    seed_corpus = "corpora/spv"
-  }
-
-  fuzzer_test("spvtools_opt_vulkantowebgpu_fuzzer") {
-    sources = []
-    deps = [
-      ":spvtools_opt_vulkantowebgpu_fuzzer_src",
-    ]
-    seed_corpus = "corpora/spv"
-  }
-
   fuzzer_test("spvtools_val_fuzzer") {
     sources = []
     deps = [
@@ -204,12 +166,4 @@
     ]
     seed_corpus = "corpora/spv"
   }
-
-  fuzzer_test("spvtools_val_webgpu_fuzzer") {
-    sources = []
-    deps = [
-      ":spvtools_val_webgpu_fuzzer_src",
-    ]
-    seed_corpus = "corpora/spv"
-  }
 }
diff --git a/third_party/SPIRV-Tools/test/fuzzers/spvtools_opt_vulkantowebgpu_fuzzer.cpp b/third_party/SPIRV-Tools/test/fuzzers/spvtools_opt_vulkantowebgpu_fuzzer.cpp
deleted file mode 100644
index 9371c0d..0000000
--- a/third_party/SPIRV-Tools/test/fuzzers/spvtools_opt_vulkantowebgpu_fuzzer.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2019 Google Inc.
-//
-// 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 <cstdint>
-#include <vector>
-
-#include "spirv-tools/optimizer.hpp"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_1);
-  optimizer.SetMessageConsumer([](spv_message_level_t, const char*,
-                                  const spv_position_t&, const char*) {});
-
-  std::vector<uint32_t> input;
-  input.resize(size >> 2);
-
-  size_t count = 0;
-  for (size_t i = 0; (i + 3) < size; i += 4) {
-    input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) |
-                     (data[i + 3]) << 24;
-  }
-
-  optimizer.RegisterVulkanToWebGPUPasses();
-  optimizer.Run(input.data(), input.size(), &input);
-
-  return 0;
-}
diff --git a/third_party/SPIRV-Tools/test/fuzzers/spvtools_opt_webgputovulkan_fuzzer.cpp b/third_party/SPIRV-Tools/test/fuzzers/spvtools_opt_webgputovulkan_fuzzer.cpp
deleted file mode 100644
index 78ddbb7..0000000
--- a/third_party/SPIRV-Tools/test/fuzzers/spvtools_opt_webgputovulkan_fuzzer.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2019 Google Inc.
-//
-// 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 <cstdint>
-#include <vector>
-
-#include "spirv-tools/optimizer.hpp"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  spvtools::Optimizer optimizer(SPV_ENV_WEBGPU_0);
-  optimizer.SetMessageConsumer([](spv_message_level_t, const char*,
-                                  const spv_position_t&, const char*) {});
-
-  std::vector<uint32_t> input;
-  input.resize(size >> 2);
-
-  size_t count = 0;
-  for (size_t i = 0; (i + 3) < size; i += 4) {
-    input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) |
-                     (data[i + 3]) << 24;
-  }
-
-  optimizer.RegisterWebGPUToVulkanPasses();
-  optimizer.Run(input.data(), input.size(), &input);
-
-  return 0;
-}
diff --git a/third_party/SPIRV-Tools/test/fuzzers/spvtools_val_webgpu_fuzzer.cpp b/third_party/SPIRV-Tools/test/fuzzers/spvtools_val_webgpu_fuzzer.cpp
deleted file mode 100644
index bed6e1a..0000000
--- a/third_party/SPIRV-Tools/test/fuzzers/spvtools_val_webgpu_fuzzer.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2019 Google Inc.
-//
-// 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 <cstdint>
-#include <vector>
-
-#include "spirv-tools/libspirv.hpp"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  spvtools::SpirvTools tools(SPV_ENV_WEBGPU_0);
-  tools.SetMessageConsumer([](spv_message_level_t, const char*,
-                              const spv_position_t&, const char*) {});
-
-  std::vector<uint32_t> input;
-  input.resize(size >> 2);
-
-  size_t count = 0;
-  for (size_t i = 0; (i + 3) < size; i += 4) {
-    input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) |
-                     (data[i + 3]) << 24;
-  }
-
-  tools.Validate(input);
-  return 0;
-}
diff --git a/third_party/SPIRV-Tools/test/opt/CMakeLists.txt b/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
index 3426958..79cb3fc 100644
--- a/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
@@ -34,7 +34,6 @@
        dead_insert_elim_test.cpp
        dead_variable_elim_test.cpp
        debug_info_manager_test.cpp
-       decompose_initialized_variables_test.cpp
        decoration_manager_test.cpp
        def_use_test.cpp
        desc_sroa_test.cpp
@@ -48,7 +47,6 @@
        fold_test.cpp
        freeze_spec_const_test.cpp
        function_test.cpp
-       generate_webgpu_initializers_test.cpp
        graphics_robust_access_test.cpp
        if_conversion_test.cpp
        inline_opaque_test.cpp
@@ -63,7 +61,6 @@
        ir_context_test.cpp
        ir_loader_test.cpp
        iterator_test.cpp
-       legalize_vector_shuffle_test.cpp
        line_debug_info_test.cpp
        local_access_chain_convert_test.cpp
        local_redundancy_elimination_test.cpp
@@ -88,9 +85,7 @@
        scalar_replacement_test.cpp
        set_spec_const_default_value_test.cpp
        simplification_test.cpp
-       split_invalid_unreachable_test.cpp
        strength_reduction_test.cpp
-       strip_atomic_counter_memory_test.cpp
        strip_debug_info_test.cpp
        strip_reflect_info_test.cpp
        struct_cfg_analysis_test.cpp
diff --git a/third_party/SPIRV-Tools/test/opt/decompose_initialized_variables_test.cpp b/third_party/SPIRV-Tools/test/opt/decompose_initialized_variables_test.cpp
deleted file mode 100644
index 06ba59a..0000000
--- a/third_party/SPIRV-Tools/test/opt/decompose_initialized_variables_test.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright (c) 2019 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 <vector>
-
-#include "test/opt/pass_fixture.h"
-#include "test/opt/pass_utils.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-using DecomposeInitializedVariablesTest = PassTest<::testing::Test>;
-
-std::string single_entry_header = R"(OpCapability Shader
-OpCapability VulkanMemoryModel
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical Vulkan
-OpEntryPoint Vertex %1 "shader"
-%uint = OpTypeInt 32 0
-%uint_1 = OpConstant %uint 1
-%4 = OpConstantNull %uint
-%void = OpTypeVoid
-%6 = OpTypeFunction %void
-)";
-
-std::string GetFunctionTest(std::string body) {
-  auto result = single_entry_header;
-  result += "%_ptr_Function_uint = OpTypePointer Function %uint\n";
-  result += "%1 = OpFunction %void None %6\n";
-  result += "%8 = OpLabel\n";
-  result += body + "\n";
-  result += "OpReturn\n";
-  result += "OpFunctionEnd\n";
-  return result;
-}
-
-TEST_F(DecomposeInitializedVariablesTest, FunctionChanged) {
-  std::string input = "%9 = OpVariable %_ptr_Function_uint Function %uint_1";
-  std::string expected = R"(%9 = OpVariable %_ptr_Function_uint Function
-OpStore %9 %uint_1)";
-
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      GetFunctionTest(input), GetFunctionTest(expected),
-      /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, FunctionUnchanged) {
-  std::string input = "%9 = OpVariable %_ptr_Function_uint Function";
-
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      GetFunctionTest(input), GetFunctionTest(input), /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, FunctionMultipleVariables) {
-  std::string input = R"(%9 = OpVariable %_ptr_Function_uint Function %uint_1
-%10 = OpVariable %_ptr_Function_uint Function %4)";
-  std::string expected = R"(%9 = OpVariable %_ptr_Function_uint Function
-%10 = OpVariable %_ptr_Function_uint Function
-OpStore %9 %uint_1
-OpStore %10 %4)";
-
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      GetFunctionTest(input), GetFunctionTest(expected),
-      /* skip_nop = */ false);
-}
-
-std::string GetGlobalTest(std::string storage_class, bool initialized,
-                          bool decomposed) {
-  auto result = single_entry_header;
-
-  result += "%_ptr_" + storage_class + "_uint = OpTypePointer " +
-            storage_class + " %uint\n";
-  if (initialized) {
-    result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " +
-              storage_class + " %4\n";
-  } else {
-    result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " +
-              storage_class + "\n";
-  }
-  result += R"(%1 = OpFunction %void None %9
-%9 = OpLabel
-)";
-  if (decomposed) result += "OpStore %8 %4\n";
-  result += R"(OpReturn
-OpFunctionEnd
-)";
-  return result;
-}
-
-TEST_F(DecomposeInitializedVariablesTest, PrivateChanged) {
-  std::string input = GetGlobalTest("Private", true, false);
-  std::string expected = GetGlobalTest("Private", false, true);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, expected, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, PrivateUnchanged) {
-  std::string input = GetGlobalTest("Private", false, false);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, input, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, OutputChanged) {
-  std::string input = GetGlobalTest("Output", true, false);
-  std::string expected = GetGlobalTest("Output", false, true);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, expected, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, OutputUnchanged) {
-  std::string input = GetGlobalTest("Output", false, false);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, input, /* skip_nop = */ false);
-}
-
-std::string multiple_entry_header = R"(OpCapability Shader
-OpCapability VulkanMemoryModel
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical Vulkan
-OpEntryPoint Vertex %1 "vertex"
-OpEntryPoint Fragment %2 "fragment"
-%uint = OpTypeInt 32 0
-%4 = OpConstantNull %uint
-%void = OpTypeVoid
-%6 = OpTypeFunction %void
-)";
-
-std::string GetGlobalMultipleEntryTest(std::string storage_class,
-                                       bool initialized, bool decomposed) {
-  auto result = multiple_entry_header;
-  result += "%_ptr_" + storage_class + "_uint = OpTypePointer " +
-            storage_class + " %uint\n";
-  if (initialized) {
-    result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " +
-              storage_class + " %4\n";
-  } else {
-    result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " +
-              storage_class + "\n";
-  }
-  result += R"(%1 = OpFunction %void None %9
-%9 = OpLabel
-)";
-  if (decomposed) result += "OpStore %8 %4\n";
-  result += R"(OpReturn
-OpFunctionEnd
-%2 = OpFunction %void None %10
-%10 = OpLabel
-)";
-  if (decomposed) result += "OpStore %8 %4\n";
-  result += R"(OpReturn
-OpFunctionEnd
-)";
-
-  return result;
-}
-
-TEST_F(DecomposeInitializedVariablesTest, PrivateMultipleEntryChanged) {
-  std::string input = GetGlobalMultipleEntryTest("Private", true, false);
-  std::string expected = GetGlobalMultipleEntryTest("Private", false, true);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, expected, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, PrivateMultipleEntryUnchanged) {
-  std::string input = GetGlobalMultipleEntryTest("Private", false, false);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, input, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, OutputMultipleEntryChanged) {
-  std::string input = GetGlobalMultipleEntryTest("Output", true, false);
-  std::string expected = GetGlobalMultipleEntryTest("Output", false, true);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, expected, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, OutputMultipleEntryUnchanged) {
-  std::string input = GetGlobalMultipleEntryTest("Output", false, false);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, input, /* skip_nop = */ false);
-}
-
-std::string GetGlobalWithNonEntryPointTest(std::string storage_class,
-                                           bool initialized, bool decomposed) {
-  auto result = single_entry_header;
-  result += "%_ptr_" + storage_class + "_uint = OpTypePointer " +
-            storage_class + " %uint\n";
-  if (initialized) {
-    result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " +
-              storage_class + " %4\n";
-  } else {
-    result += "%8 = OpVariable %_ptr_" + storage_class + "_uint " +
-              storage_class + "\n";
-  }
-  result += R"(%1 = OpFunction %void None %9
-%9 = OpLabel
-)";
-  if (decomposed) result += "OpStore %8 %4\n";
-  result += R"(OpReturn
-OpFunctionEnd
-%10 = OpFunction %void None %11
-%11 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  return result;
-}
-
-TEST_F(DecomposeInitializedVariablesTest, PrivateWithNonEntryPointChanged) {
-  std::string input = GetGlobalWithNonEntryPointTest("Private", true, false);
-  std::string expected = GetGlobalWithNonEntryPointTest("Private", false, true);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, expected, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, PrivateWithNonEntryPointUnchanged) {
-  std::string input = GetGlobalWithNonEntryPointTest("Private", false, false);
-  //  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, input, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, OutputWithNonEntryPointChanged) {
-  std::string input = GetGlobalWithNonEntryPointTest("Output", true, false);
-  std::string expected = GetGlobalWithNonEntryPointTest("Output", false, true);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, expected, /* skip_nop = */ false);
-}
-
-TEST_F(DecomposeInitializedVariablesTest, OutputWithNonEntryPointUnchanged) {
-  std::string input = GetGlobalWithNonEntryPointTest("Output", false, false);
-  //  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<DecomposeInitializedVariablesPass>(
-      input, input, /* skip_nop = */ false);
-}
-
-}  // namespace
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/desc_sroa_test.cpp b/third_party/SPIRV-Tools/test/opt/desc_sroa_test.cpp
index cdcc9a8..b35ad47 100644
--- a/third_party/SPIRV-Tools/test/opt/desc_sroa_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/desc_sroa_test.cpp
@@ -729,6 +729,47 @@
   SinglePassRunAndMatch<DescriptorScalarReplacement>(checks + shader, true);
 }
 
+TEST_F(DescriptorScalarReplacementTest, BindingForResourceArrayOfStructs) {
+  // Check that correct binding numbers are given to an array of descriptors
+  // to structs.
+
+  const std::string shader = R"(
+; CHECK: OpDecorate {{%\w+}} Binding 0
+; CHECK: OpDecorate {{%\w+}} Binding 1
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "psmain"
+               OpExecutionMode %2 OriginUpperLeft
+               OpDecorate %5 DescriptorSet 0
+               OpDecorate %5 Binding 0
+               OpMemberDecorate %_struct_4 0 Offset 0
+               OpMemberDecorate %_struct_4 1 Offset 4
+               OpDecorate %_struct_4 Block
+      %float = OpTypeFloat 32
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+      %int_1 = OpConstant %int 1
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+  %_struct_4 = OpTypeStruct %float %int
+%_arr__struct_4_uint_2 = OpTypeArray %_struct_4 %uint_2
+%_ptr_Uniform__arr__struct_4_uint_2 = OpTypePointer Uniform %_arr__struct_4_uint_2
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+          %5 = OpVariable %_ptr_Uniform__arr__struct_4_uint_2 Uniform
+          %2 = OpFunction %void None %25
+         %29 = OpLabel
+         %40 = OpAccessChain %_ptr_Uniform_int %5 %int_0 %int_1
+         %41 = OpAccessChain %_ptr_Uniform_int %5 %int_1 %int_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<DescriptorScalarReplacement>(shader, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp b/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp
index a9b0f28..7728782 100644
--- a/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp
@@ -1184,4 +1184,86 @@
   SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
 }
 
+TEST_F(EliminateDeadMemberTest, 8BitIndexNoChange) {
+  // Test that the pass does not crash when an 8 bit index is used in an
+  // OpAccessChain. No change is expected.
+  const std::string text = R"(
+               OpCapability ImageQuery
+               OpCapability Int8
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %1 "OpnSeman/" %2
+               OpExecutionMode %1 OriginUpperLeft
+       %void = OpTypeVoid
+          %4 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+  %_struct_7 = OpTypeStruct %v4float
+%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+         %10 = OpTypeFunction %v4float %_ptr_Function__struct_7
+       %char = OpTypeInt 8 1
+     %char_0 = OpConstant %char 0
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+          %2 = OpVariable %_ptr_Output_v4float Output
+          %1 = OpFunction %void None %4
+         %14 = OpLabel
+         %15 = OpVariable %_ptr_Function__struct_7 Function
+         %16 = OpFunctionCall %v4float %17 %15
+               OpReturn
+               OpFunctionEnd
+         %17 = OpFunction %v4float DontInline %10
+         %18 = OpFunctionParameter %_ptr_Function__struct_7
+         %19 = OpLabel
+         %20 = OpAccessChain %_ptr_Function_v4float %18 %char_0
+         %21 = OpLoad %v4float %20
+               OpReturnValue %21
+               OpFunctionEnd
+)";
+
+  auto result = SinglePassRunAndDisassemble<opt::EliminateDeadMembersPass>(
+      text, /* skip_nop = */ true, /* do_validation = */ true);
+  EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
+}
+
+TEST_F(EliminateDeadMemberTest, 8BitIndexWithChange) {
+  // Test that the pass does not crash when an 8 bit index is used in an
+  // OpAccessChain. The index in the access change should be changed to 0.
+  const std::string text = R"(
+               OpCapability ImageQuery
+               OpCapability Int8
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %1 "OpnSeman/" %2
+               OpExecutionMode %1 OriginUpperLeft
+       %void = OpTypeVoid
+          %4 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+  %_struct_7 = OpTypeStruct %v4float %v4float
+%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+         %10 = OpTypeFunction %v4float %_ptr_Function__struct_7
+       %char = OpTypeInt 8 1
+     %char_1 = OpConstant %char 1
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+          %2 = OpVariable %_ptr_Output_v4float Output
+          %1 = OpFunction %void None %4
+         %14 = OpLabel
+         %15 = OpVariable %_ptr_Function__struct_7 Function
+         %16 = OpFunctionCall %v4float %17 %15
+               OpReturn
+               OpFunctionEnd
+         %17 = OpFunction %v4float DontInline %10
+; CHECK: [[param:%\w+]] = OpFunctionParameter
+         %18 = OpFunctionParameter %_ptr_Function__struct_7
+         %19 = OpLabel
+; CHECK: OpAccessChain %_ptr_Function_v4float [[param]] %uint_0
+         %20 = OpAccessChain %_ptr_Function_v4float %18 %char_1
+         %21 = OpLoad %v4float %20
+               OpReturnValue %21
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
+}
+
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/opt/generate_webgpu_initializers_test.cpp b/third_party/SPIRV-Tools/test/opt/generate_webgpu_initializers_test.cpp
deleted file mode 100644
index 4aab2ce..0000000
--- a/third_party/SPIRV-Tools/test/opt/generate_webgpu_initializers_test.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright (c) 2019 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 <vector>
-
-#include "test/opt/pass_fixture.h"
-#include "test/opt/pass_utils.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-typedef std::tuple<std::string, bool> GenerateWebGPUInitializersParam;
-
-using GlobalVariableTest =
-    PassTest<::testing::TestWithParam<GenerateWebGPUInitializersParam>>;
-using LocalVariableTest =
-    PassTest<::testing::TestWithParam<GenerateWebGPUInitializersParam>>;
-
-using GenerateWebGPUInitializersTest = PassTest<::testing::Test>;
-
-void operator+=(std::vector<const char*>& lhs, const char* rhs) {
-  lhs.push_back(rhs);
-}
-
-void operator+=(std::vector<const char*>& lhs,
-                const std::vector<const char*>& rhs) {
-  lhs.reserve(lhs.size() + rhs.size());
-  for (auto* c : rhs) lhs.push_back(c);
-}
-
-std::string GetGlobalVariableTestString(std::string ptr_str,
-                                        std::string var_str,
-                                        std::string const_str = "") {
-  std::vector<const char*> result = {
-      // clang-format off
-               "OpCapability Shader",
-               "OpCapability VulkanMemoryModel",
-               "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-               "OpMemoryModel Logical Vulkan",
-               "OpEntryPoint Vertex %1 \"shader\"",
-       "%uint = OpTypeInt 32 0",
-                ptr_str.c_str()};
-  // clang-format on
-
-  if (!const_str.empty()) result += const_str.c_str();
-
-  result += {
-      // clang-format off
-                var_str.c_str(),
-     "%uint_0 = OpConstant %uint 0",
-       "%void = OpTypeVoid",
-          "%7 = OpTypeFunction %void",
-          "%1 = OpFunction %void None %7",
-          "%8 = OpLabel",
-               "OpStore %4 %uint_0",
-               "OpReturn",
-               "OpFunctionEnd"
-      // clang-format on
-  };
-  return JoinAllInsts(result);
-}
-
-std::string GetPointerString(std::string storage_type) {
-  std::string result = "%_ptr_";
-  result += storage_type + "_uint = OpTypePointer ";
-  result += storage_type + " %uint";
-  return result;
-}
-
-std::string GetGlobalVariableString(std::string storage_type,
-                                    bool initialized) {
-  std::string result = "%4 = OpVariable %_ptr_";
-  result += storage_type + "_uint ";
-  result += storage_type;
-  if (initialized) result += " %9";
-  return result;
-}
-
-std::string GetUninitializedGlobalVariableTestString(std::string storage_type) {
-  return GetGlobalVariableTestString(
-      GetPointerString(storage_type),
-      GetGlobalVariableString(storage_type, false));
-}
-
-std::string GetNullConstantString() { return "%9 = OpConstantNull %uint"; }
-
-std::string GetInitializedGlobalVariableTestString(std::string storage_type) {
-  return GetGlobalVariableTestString(
-      GetPointerString(storage_type),
-      GetGlobalVariableString(storage_type, true), GetNullConstantString());
-}
-
-TEST_P(GlobalVariableTest, Check) {
-  std::string storage_class = std::get<0>(GetParam());
-  bool changed = std::get<1>(GetParam());
-  std::string input = GetUninitializedGlobalVariableTestString(storage_class);
-  std::string expected =
-      changed ? GetInitializedGlobalVariableTestString(storage_class) : input;
-
-  SinglePassRunAndCheck<GenerateWebGPUInitializersPass>(input, expected,
-                                                        /* skip_nop = */ false);
-}
-
-// clang-format off
-INSTANTIATE_TEST_SUITE_P(
-    GenerateWebGPUInitializers, GlobalVariableTest,
-    ::testing::ValuesIn(std::vector<GenerateWebGPUInitializersParam>({
-       std::make_tuple("Private", true),
-       std::make_tuple("Output", true),
-       std::make_tuple("Function", true),
-       std::make_tuple("UniformConstant", false),
-       std::make_tuple("Input", false),
-       std::make_tuple("Uniform", false),
-       std::make_tuple("Workgroup", false)
-    })));
-// clang-format on
-
-std::string GetLocalVariableTestString(std::string ptr_str, std::string var_str,
-                                       std::string const_str = "") {
-  std::vector<const char*> result = {
-      // clang-format off
-               "OpCapability Shader",
-               "OpCapability VulkanMemoryModel",
-               "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-               "OpMemoryModel Logical Vulkan",
-               "OpEntryPoint Vertex %1 \"shader\"",
-       "%uint = OpTypeInt 32 0",
-                ptr_str.c_str(),
-     "%uint_0 = OpConstant %uint 0",
-       "%void = OpTypeVoid",
-          "%6 = OpTypeFunction %void"};
-  // clang-format on
-
-  if (!const_str.empty()) result += const_str.c_str();
-
-  result += {
-      // clang-format off
-          "%1 = OpFunction %void None %6",
-          "%7 = OpLabel",
-                var_str.c_str(),
-               "OpStore %8 %uint_0"
-      // clang-format on
-  };
-  return JoinAllInsts(result);
-}
-
-std::string GetLocalVariableString(std::string storage_type, bool initialized) {
-  std::string result = "%8 = OpVariable %_ptr_";
-  result += storage_type + "_uint ";
-  result += storage_type;
-  if (initialized) result += " %9";
-  return result;
-}
-
-std::string GetUninitializedLocalVariableTestString(std::string storage_type) {
-  return GetLocalVariableTestString(
-      GetPointerString(storage_type),
-      GetLocalVariableString(storage_type, false));
-}
-
-std::string GetInitializedLocalVariableTestString(std::string storage_type) {
-  return GetLocalVariableTestString(GetPointerString(storage_type),
-                                    GetLocalVariableString(storage_type, true),
-                                    GetNullConstantString());
-}
-
-TEST_P(LocalVariableTest, Check) {
-  std::string storage_class = std::get<0>(GetParam());
-  bool changed = std::get<1>(GetParam());
-
-  std::string input = GetUninitializedLocalVariableTestString(storage_class);
-  std::string expected =
-      changed ? GetInitializedLocalVariableTestString(storage_class) : input;
-
-  SinglePassRunAndCheck<GenerateWebGPUInitializersPass>(input, expected,
-                                                        /* skip_nop = */ false);
-}
-
-// clang-format off
-INSTANTIATE_TEST_SUITE_P(
-    GenerateWebGPUInitializers, LocalVariableTest,
-    ::testing::ValuesIn(std::vector<GenerateWebGPUInitializersParam>({
-       std::make_tuple("Private", true),
-       std::make_tuple("Output", true),
-       std::make_tuple("Function", true),
-       std::make_tuple("UniformConstant", false),
-       std::make_tuple("Input", false),
-       std::make_tuple("Uniform", false),
-       std::make_tuple("Workgroup", false)
-    })));
-// clang-format on
-
-TEST_F(GenerateWebGPUInitializersTest, AlreadyInitializedUnchanged) {
-  std::vector<const char*> spirv = {
-      // clang-format off
-                       "OpCapability Shader",
-                       "OpCapability VulkanMemoryModel",
-                       "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-                       "OpMemoryModel Logical Vulkan",
-                       "OpEntryPoint Vertex %1 \"shader\"",
-               "%uint = OpTypeInt 32 0",
-  "%_ptr_Private_uint = OpTypePointer Private %uint",
-             "%uint_0 = OpConstant %uint 0",
-                  "%5 = OpVariable %_ptr_Private_uint Private %uint_0",
-               "%void = OpTypeVoid",
-                  "%7 = OpTypeFunction %void",
-                  "%1 = OpFunction %void None %7",
-                  "%8 = OpLabel",
-                       "OpReturn",
-                       "OpFunctionEnd"
-      // clang-format on
-  };
-  std::string str = JoinAllInsts(spirv);
-
-  SinglePassRunAndCheck<GenerateWebGPUInitializersPass>(str, str,
-                                                        /* skip_nop = */ false);
-}
-
-TEST_F(GenerateWebGPUInitializersTest, AmbigiousArrays) {
-  std::vector<const char*> input_spirv = {
-      // clang-format off
-                                   "OpCapability Shader",
-                                   "OpCapability VulkanMemoryModel",
-                                   "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-                                   "OpMemoryModel Logical Vulkan",
-                                   "OpEntryPoint Vertex %1 \"shader\"",
-                           "%uint = OpTypeInt 32 0",
-                         "%uint_2 = OpConstant %uint 2",
-               "%_arr_uint_uint_2 = OpTypeArray %uint %uint_2",
-             "%_arr_uint_uint_2_0 = OpTypeArray %uint %uint_2",
-  "%_ptr_Private__arr_uint_uint_2 = OpTypePointer Private %_arr_uint_uint_2",
-"%_ptr_Private__arr_uint_uint_2_0 = OpTypePointer Private %_arr_uint_uint_2_0",
-                              "%8 = OpConstantNull %_arr_uint_uint_2_0",
-                              "%9 = OpVariable %_ptr_Private__arr_uint_uint_2 Private",
-                             "%10 = OpVariable %_ptr_Private__arr_uint_uint_2_0 Private %8",
-                           "%void = OpTypeVoid",
-                             "%12 = OpTypeFunction %void",
-                              "%1 = OpFunction %void None %12",
-                             "%13 = OpLabel",
-                                   "OpReturn",
-                                   "OpFunctionEnd"
-      // clang-format on
-  };
-  std::string input_str = JoinAllInsts(input_spirv);
-
-  std::vector<const char*> expected_spirv = {
-      // clang-format off
-                                   "OpCapability Shader",
-                                   "OpCapability VulkanMemoryModel",
-                                   "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-                                   "OpMemoryModel Logical Vulkan",
-                                   "OpEntryPoint Vertex %1 \"shader\"",
-                           "%uint = OpTypeInt 32 0",
-                         "%uint_2 = OpConstant %uint 2",
-               "%_arr_uint_uint_2 = OpTypeArray %uint %uint_2",
-             "%_arr_uint_uint_2_0 = OpTypeArray %uint %uint_2",
-  "%_ptr_Private__arr_uint_uint_2 = OpTypePointer Private %_arr_uint_uint_2",
-"%_ptr_Private__arr_uint_uint_2_0 = OpTypePointer Private %_arr_uint_uint_2_0",
-                              "%8 = OpConstantNull %_arr_uint_uint_2_0",
-                             "%14 = OpConstantNull %_arr_uint_uint_2",
-                              "%9 = OpVariable %_ptr_Private__arr_uint_uint_2 Private %14",
-                             "%10 = OpVariable %_ptr_Private__arr_uint_uint_2_0 Private %8",
-                           "%void = OpTypeVoid",
-                             "%12 = OpTypeFunction %void",
-                              "%1 = OpFunction %void None %12",
-                             "%13 = OpLabel",
-                                   "OpReturn",
-                                   "OpFunctionEnd"
-      // clang-format on
-  };
-  std::string expected_str = JoinAllInsts(expected_spirv);
-
-  SinglePassRunAndCheck<GenerateWebGPUInitializersPass>(input_str, expected_str,
-                                                        /* skip_nop = */ false);
-}
-
-TEST_F(GenerateWebGPUInitializersTest, AmbigiousStructs) {
-  std::vector<const char*> input_spirv = {
-      // clang-format off
-                          "OpCapability Shader",
-                          "OpCapability VulkanMemoryModel",
-                          "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-                          "OpMemoryModel Logical Vulkan",
-                          "OpEntryPoint Vertex %1 \"shader\"",
-                  "%uint = OpTypeInt 32 0",
-             "%_struct_3 = OpTypeStruct %uint",
-             "%_struct_4 = OpTypeStruct %uint",
-"%_ptr_Private__struct_3 = OpTypePointer Private %_struct_3",
-"%_ptr_Private__struct_4 = OpTypePointer Private %_struct_4",
-                     "%7 = OpConstantNull %_struct_3",
-                     "%8 = OpVariable %_ptr_Private__struct_3 Private %7",
-                     "%9 = OpVariable %_ptr_Private__struct_4 Private",
-                  "%void = OpTypeVoid",
-                    "%11 = OpTypeFunction %void",
-                     "%1 = OpFunction %void None %11",
-                    "%12 = OpLabel",
-                          "OpReturn",
-                          "OpFunctionEnd"
-      // clang-format on
-  };
-  std::string input_str = JoinAllInsts(input_spirv);
-
-  std::vector<const char*> expected_spirv = {
-      // clang-format off
-                          "OpCapability Shader",
-                          "OpCapability VulkanMemoryModel",
-                          "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-                          "OpMemoryModel Logical Vulkan",
-                          "OpEntryPoint Vertex %1 \"shader\"",
-                  "%uint = OpTypeInt 32 0",
-             "%_struct_3 = OpTypeStruct %uint",
-             "%_struct_4 = OpTypeStruct %uint",
-"%_ptr_Private__struct_3 = OpTypePointer Private %_struct_3",
-"%_ptr_Private__struct_4 = OpTypePointer Private %_struct_4",
-                     "%7 = OpConstantNull %_struct_3",
-                     "%8 = OpVariable %_ptr_Private__struct_3 Private %7",
-                    "%13 = OpConstantNull %_struct_4",
-                     "%9 = OpVariable %_ptr_Private__struct_4 Private %13",
-                  "%void = OpTypeVoid",
-                    "%11 = OpTypeFunction %void",
-                     "%1 = OpFunction %void None %11",
-                    "%12 = OpLabel",
-                          "OpReturn",
-                          "OpFunctionEnd"
-      // clang-format on
-  };
-  std::string expected_str = JoinAllInsts(expected_spirv);
-
-  SinglePassRunAndCheck<GenerateWebGPUInitializersPass>(input_str, expected_str,
-                                                        /* skip_nop = */ false);
-}
-
-}  // namespace
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/inline_opaque_test.cpp b/third_party/SPIRV-Tools/test/opt/inline_opaque_test.cpp
index 47e0533..8cb8925 100644
--- a/third_party/SPIRV-Tools/test/opt/inline_opaque_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inline_opaque_test.cpp
@@ -28,7 +28,7 @@
   // Function with opaque argument is inlined.
   // TODO(greg-lunarg): Add HLSL code
 
-  const std::string predefs =
+  const std::string predefs_1 =
       R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -47,22 +47,27 @@
 OpName %s0 "s0"
 OpName %texCoords "texCoords"
 OpName %param "param"
-OpDecorate %sampler15 DescriptorSet 0
+)";
+
+  const std::string name = R"(OpName %return_value "return_value"
+)";
+
+  const std::string predefs_2 = R"(OpDecorate %sampler15 DescriptorSet 0
 %void = OpTypeVoid
-%12 = OpTypeFunction %void
+%13 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %v2float = OpTypeVector %float 2
 %v4float = OpTypeVector %float 4
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %outColor = OpVariable %_ptr_Output_v4float Output
-%17 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%18 = OpTypeSampledImage %17
-%S_t = OpTypeStruct %v2float %v2float %18
+%18 = OpTypeImage %float 2D 0 0 0 1 Unknown
+%19 = OpTypeSampledImage %18
+%S_t = OpTypeStruct %v2float %v2float %19
 %_ptr_Function_S_t = OpTypePointer Function %S_t
-%20 = OpTypeFunction %void %_ptr_Function_S_t
-%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
-%_ptr_Function_18 = OpTypePointer Function %18
-%sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant
+%21 = OpTypeFunction %void %_ptr_Function_S_t
+%_ptr_UniformConstant_19 = OpTypePointer UniformConstant %19
+%_ptr_Function_19 = OpTypePointer Function %19
+%sampler15 = OpVariable %_ptr_UniformConstant_19 UniformConstant
 %int = OpTypeInt 32 1
 %int_0 = OpConstant %int 0
 %int_2 = OpConstant %int 2
@@ -72,39 +77,38 @@
 )";
 
   const std::string before =
-      R"(%main = OpFunction %void None %12
-%28 = OpLabel
+      R"(%main = OpFunction %void None %13
+%29 = OpLabel
 %s0 = OpVariable %_ptr_Function_S_t Function
 %param = OpVariable %_ptr_Function_S_t Function
-%29 = OpLoad %v2float %texCoords
-%30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
-OpStore %30 %29
-%31 = OpLoad %18 %sampler15
-%32 = OpAccessChain %_ptr_Function_18 %s0 %int_2
-OpStore %32 %31
-%33 = OpLoad %S_t %s0
-OpStore %param %33
-%34 = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param
+%30 = OpLoad %v2float %texCoords
+%31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
+OpStore %31 %30
+%32 = OpLoad %19 %sampler15
+%33 = OpAccessChain %_ptr_Function_19 %s0 %int_2
+OpStore %33 %32
+%34 = OpLoad %S_t %s0
+OpStore %param %34
+%return_value = OpFunctionCall %void %foo_struct_S_t_vf2_vf21_ %param
 OpReturn
 OpFunctionEnd
 )";
 
   const std::string after =
-      R"(%34 = OpUndef %void
-%main = OpFunction %void None %12
-%28 = OpLabel
+      R"(%main = OpFunction %void None %13
+%29 = OpLabel
 %s0 = OpVariable %_ptr_Function_S_t Function
 %param = OpVariable %_ptr_Function_S_t Function
-%29 = OpLoad %v2float %texCoords
-%30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
-OpStore %30 %29
-%31 = OpLoad %18 %sampler15
-%32 = OpAccessChain %_ptr_Function_18 %s0 %int_2
-OpStore %32 %31
-%33 = OpLoad %S_t %s0
-OpStore %param %33
-%42 = OpAccessChain %_ptr_Function_18 %param %int_2
-%43 = OpLoad %18 %42
+%30 = OpLoad %v2float %texCoords
+%31 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
+OpStore %31 %30
+%32 = OpLoad %19 %sampler15
+%33 = OpAccessChain %_ptr_Function_19 %s0 %int_2
+OpStore %33 %32
+%34 = OpLoad %S_t %s0
+OpStore %param %34
+%42 = OpAccessChain %_ptr_Function_19 %param %int_2
+%43 = OpLoad %19 %42
 %44 = OpAccessChain %_ptr_Function_v2float %param %int_0
 %45 = OpLoad %v2float %44
 %46 = OpImageSampleImplicitLod %v4float %43 %45
@@ -114,11 +118,11 @@
 )";
 
   const std::string post_defs =
-      R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20
+      R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %21
 %s = OpFunctionParameter %_ptr_Function_S_t
 %35 = OpLabel
-%36 = OpAccessChain %_ptr_Function_18 %s %int_2
-%37 = OpLoad %18 %36
+%36 = OpAccessChain %_ptr_Function_19 %s %int_2
+%37 = OpLoad %19 %36
 %38 = OpAccessChain %_ptr_Function_v2float %s %int_0
 %39 = OpLoad %v2float %38
 %40 = OpImageSampleImplicitLod %v4float %37 %39
@@ -128,7 +132,8 @@
 )";
 
   SinglePassRunAndCheck<InlineOpaquePass>(
-      predefs + before + post_defs, predefs + after + post_defs, true, true);
+      predefs_1 + name + predefs_2 + before + post_defs,
+      predefs_1 + predefs_2 + after + post_defs, true, true);
 }
 
 TEST_F(InlineOpaqueTest, InlineOpaqueReturn) {
@@ -290,8 +295,7 @@
 )";
 
   const std::string after =
-      R"(%35 = OpUndef %void
-%main2 = OpFunction %void None %13
+      R"(%main2 = OpFunction %void None %13
 %29 = OpLabel
 %s0 = OpVariable %_ptr_Function_S_t Function
 %param = OpVariable %_ptr_Function_S_t Function
diff --git a/third_party/SPIRV-Tools/test/opt/inline_test.cpp b/third_party/SPIRV-Tools/test/opt/inline_test.cpp
index c0ca6da..2939901 100644
--- a/third_party/SPIRV-Tools/test/opt/inline_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inline_test.cpp
@@ -381,7 +381,6 @@
 
   const std::vector<const char*> after = {
       // clang-format off
-         "%26 = OpUndef %void",
        "%main = OpFunction %void None %11",
          "%23 = OpLabel",
           "%b = OpVariable %_ptr_Function_v4float Function",
@@ -1543,11 +1542,9 @@
 OpFunctionEnd
 )";
 
-  const std::string undef = "%11 = OpUndef %void\n";
-
-  SinglePassRunAndCheck<InlineExhaustivePass>(
-      predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
-      false, true);
+  SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
+                                              predefs + nonEntryFuncs + after,
+                                              false, true);
 }
 
 TEST_F(InlineTest, MultiBlockLoopHeaderCallsMultiBlockCallee) {
@@ -1622,10 +1619,9 @@
 OpFunctionEnd
 )";
 
-  const std::string undef = "%20 = OpUndef %void\n";
-  SinglePassRunAndCheck<InlineExhaustivePass>(
-      predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
-      false, true);
+  SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
+                                              predefs + nonEntryFuncs + after,
+                                              false, true);
 }
 
 TEST_F(InlineTest, SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge) {
@@ -1711,10 +1707,9 @@
 OpReturn
 OpFunctionEnd
 )";
-  const std::string undef = "%15 = OpUndef %void\n";
-  SinglePassRunAndCheck<InlineExhaustivePass>(
-      predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
-      false, true);
+  SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
+                                              predefs + nonEntryFuncs + after,
+                                              false, true);
 }
 
 TEST_F(InlineTest,
@@ -1793,10 +1788,9 @@
 OpFunctionEnd
 )";
 
-  const std::string undef = "%20 = OpUndef %void\n";
-  SinglePassRunAndCheck<InlineExhaustivePass>(
-      predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
-      false, true);
+  SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
+                                              predefs + nonEntryFuncs + after,
+                                              false, true);
 }
 
 TEST_F(InlineTest, NonInlinableCalleeWithSingleReturn) {
@@ -2169,7 +2163,6 @@
 OpName %foo_entry "foo_entry"
 %void = OpTypeVoid
 %void_fn = OpTypeFunction %void
-%3 = OpUndef %void
 %foo = OpFunction %void None %void_fn
 %foo_entry = OpLabel
 OpReturn
@@ -2475,7 +2468,6 @@
 %3 = OpTypeFunction %void
 %bool = OpTypeBool
 %true = OpConstantTrue %bool
-%16 = OpUndef %void
 %main = OpFunction %void None %3
 %5 = OpLabel
 OpKill
@@ -2573,7 +2565,6 @@
 %3 = OpTypeFunction %void
 %bool = OpTypeBool
 %true = OpConstantTrue %bool
-%16 = OpUndef %void
 %main = OpFunction %void None %3
 %5 = OpLabel
 OpTerminateInvocation
@@ -2590,6 +2581,63 @@
   SinglePassRunAndCheck<InlineExhaustivePass>(before, after, false, true);
 }
 
+TEST_F(InlineTest, InlineFuncWithOpTerminateRayNotInContinue) {
+  const std::string text =
+      R"(
+               OpCapability RayTracingKHR
+               OpExtension "SPV_KHR_ray_tracing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint AnyHitKHR %MyAHitMain2 "MyAHitMain2" %a
+               OpSource HLSL 630
+               OpName %a "a"
+               OpName %MyAHitMain2 "MyAHitMain2"
+               OpName %param_var_a "param.var.a"
+               OpName %src_MyAHitMain2 "src.MyAHitMain2"
+               OpName %a_0 "a"
+               OpName %bb_entry "bb.entry"
+        %int = OpTypeInt 32 1
+%_ptr_IncomingRayPayloadKHR_int = OpTypePointer IncomingRayPayloadKHR %int
+       %void = OpTypeVoid
+          %6 = OpTypeFunction %void
+%_ptr_Function_int = OpTypePointer Function %int
+         %14 = OpTypeFunction %void %_ptr_Function_int
+          %a = OpVariable %_ptr_IncomingRayPayloadKHR_int IncomingRayPayloadKHR
+%MyAHitMain2 = OpFunction %void None %6
+          %7 = OpLabel
+%param_var_a = OpVariable %_ptr_Function_int Function
+         %10 = OpLoad %int %a
+               OpStore %param_var_a %10
+         %11 = OpFunctionCall %void %src_MyAHitMain2 %param_var_a
+         %13 = OpLoad %int %param_var_a
+               OpStore %a %13
+               OpReturn
+               OpFunctionEnd
+%src_MyAHitMain2 = OpFunction %void None %14
+        %a_0 = OpFunctionParameter %_ptr_Function_int
+   %bb_entry = OpLabel
+         %17 = OpLoad %int %a_0
+               OpStore %a %17
+               OpTerminateRayKHR
+               OpFunctionEnd
+
+; CHECK:      %MyAHitMain2 = OpFunction %void None
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT:   %param_var_a = OpVariable %_ptr_Function_int Function
+; CHECK-NEXT:   OpLoad %int %a
+; CHECK-NEXT:   OpStore %param_var_a {{%\d+}}
+; CHECK-NEXT:   OpLoad %int %param_var_a
+; CHECK-NEXT:   OpStore %a {{%\d+}}
+; CHECK-NEXT:   OpTerminateRayKHR
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT:   OpLoad %int %param_var_a
+; CHECK-NEXT:   OpStore %a %16
+; CHECK-NEXT:   OpReturn
+; CHECK-NEXT: OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<InlineExhaustivePass>(text, false);
+}
+
 TEST_F(InlineTest, EarlyReturnFunctionInlined) {
   // #version 140
   //
@@ -2801,7 +2849,6 @@
 %uint_0 = OpConstant %uint 0
 %false = OpConstantFalse %bool
 %_ptr_Function_bool = OpTypePointer Function %bool
-%11 = OpUndef %void
 %foo_ = OpFunction %void None %4
 %7 = OpLabel
 %18 = OpVariable %_ptr_Function_bool Function %false
@@ -3890,35 +3937,6 @@
   SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
 }
 
-TEST_F(InlineTest, UsingVoidFunctionResult) {
-  const std::string text = R"(
-; CHECK: [[undef:%\w+]] = OpUndef %void
-; CHECK: OpFunction
-; CHECK: OpCopyObject %void [[undef]]
-; CHECK: OpFunctionEnd
-               OpCapability Shader
-          %1 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint Fragment %4 "main"
-               OpExecutionMode %4 OriginUpperLeft
-               OpSource ESSL 320
-          %2 = OpTypeVoid
-          %3 = OpTypeFunction %2
-          %4 = OpFunction %2 None %3
-          %5 = OpLabel
-          %8 = OpFunctionCall %2 %6
-          %9 = OpCopyObject %2 %8
-               OpReturn
-               OpFunctionEnd
-          %6 = OpFunction %2 None %3
-          %7 = OpLabel
-               OpReturn
-               OpFunctionEnd
-)";
-
-  SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
-}
-
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    Empty modules
diff --git a/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
index 691bc9a..f189962 100644
--- a/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
@@ -105,8 +105,8 @@
 )";
 
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(before, before, true, true, 7u,
-                                               23u, false, false);
+  SinglePassRunAndCheck<InstBindlessCheckPass>(
+      before, before, true, true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, NoInstrumentNonBindless) {
@@ -183,7 +183,8 @@
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(whole_file, whole_file, true,
-                                               true, 7u, 23u, false, false);
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, Simple) {
@@ -412,7 +413,7 @@
           func_pt2_before,
       entry_after + names_annots + new_annots + consts_types_vars +
           new_consts_types_vars + func_pt1 + func_pt2_after + output_func,
-      true, true, 7u, 23u, false, false);
+      true, true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentMultipleInstructions) {
@@ -707,7 +708,7 @@
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false);
+      true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentOpImage) {
@@ -935,7 +936,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false);
+      true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentSampledImage) {
@@ -1158,7 +1159,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false);
+      true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentImageWrite) {
@@ -1383,7 +1384,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false);
+      true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentVertexSimple) {
@@ -1657,7 +1658,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false);
+      true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentTeseSimple) {
@@ -1933,7 +1934,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false);
+      true, 7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, MultipleDebugFunctions) {
@@ -2261,7 +2262,7 @@
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func1_before + func2_before,
       defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u,
-      false, false);
+      false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, RuntimeArray) {
@@ -2557,7 +2558,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) {
@@ -2793,7 +2794,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, SPV14AddToEntryPoint) {
@@ -2849,7 +2850,8 @@
 )";
 
   SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4);
-  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, SPV14AddToEntryPoints) {
@@ -2907,7 +2909,8 @@
 )";
 
   SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4);
-  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedUBOArray) {
@@ -3188,7 +3191,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayDeprecated) {
@@ -3469,7 +3472,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArray) {
@@ -3739,7 +3742,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstInitLoadUBOScalar) {
@@ -3964,7 +3967,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsInitStoreUnsizedSSBOArray) {
@@ -4238,7 +4241,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsInitLoadSizedUBOArray) {
@@ -4507,7 +4510,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -4829,7 +4832,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -5153,7 +5156,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -5477,7 +5480,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -5801,7 +5804,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -6125,7 +6128,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -6449,7 +6452,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -6773,7 +6776,7 @@
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsInitSameBlockOpReplication) {
@@ -7182,7 +7185,7 @@
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true);
+      true, 7u, 23u, true, true, false, false, false);
 }
 
 TEST_F(InstBindlessTest, MultipleUniformNonAggregateRefsNoDescInit) {
@@ -7456,7 +7459,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
-                                               false, true);
+                                               false, true, false, true);
 }
 
 TEST_F(InstBindlessTest, UniformArrayRefNoDescInit) {
@@ -7721,7 +7724,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
-                                               false, true);
+                                               false, true, false, true);
 }
 
 TEST_F(InstBindlessTest, UniformArrayRefWithDescInit) {
@@ -7978,7 +7981,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
-                                               true);
+                                               true, false, true);
 }
 
 TEST_F(InstBindlessTest, Descriptor16BitIdxRef) {
@@ -8201,7 +8204,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
-                                               false);
+                                               false, false, true);
 }
 
 TEST_F(InstBindlessTest, UniformArray16bitIdxRef) {
@@ -8471,7 +8474,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
-                                               false, true);
+                                               false, true, false, true);
 }
 
 TEST_F(InstBindlessTest, UniformMatrixRefRowMajor) {
@@ -8679,7 +8682,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
-                                               false, true);
+                                               false, true, false, true);
 }
 
 TEST_F(InstBindlessTest, UniformMatrixRefColumnMajor) {
@@ -8885,7 +8888,7 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
-                                               false, true);
+                                               false, true, false, true);
 }
 
 TEST_F(InstBindlessTest, UniformMatrixVecRefRowMajor) {
@@ -9107,7 +9110,860 @@
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
-                                               false, true);
+                                               false, true, false, true);
+}
+
+TEST_F(InstBindlessTest, ImageBufferOOBRead) {
+  // Texel buffer (imagebuffer) oob check for ImageRead
+  //
+  // #version 450
+  // layout(set=3, binding=7, r32f) uniform readonly imageBuffer s;
+  // layout(location=11) out vec4 x;
+  // layout(location=13) in flat int ii;
+  //
+  // void main(){
+  //    x = imageLoad(s, ii);
+  // }
+
+  const std::string text = R"(
+                          OpCapability Shader
+                          OpCapability ImageBuffer
+;CHECK:                   OpCapability ImageQuery
+;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
+                     %1 = OpExtInstImport "GLSL.std.450"
+                          OpMemoryModel Logical GLSL450
+                          OpEntryPoint Fragment %main "main" %x %s %ii
+                          OpExecutionMode %main OriginUpperLeft
+                          OpSource GLSL 450
+                          OpName %main "main"
+                          OpName %x "x"
+                          OpName %s "s"
+                          OpName %ii "ii"
+                          OpDecorate %x Location 11
+                          OpDecorate %s DescriptorSet 3
+                          OpDecorate %s Binding 7
+                          OpDecorate %s NonWritable
+                          OpDecorate %ii Flat
+                          OpDecorate %ii Location 13
+;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
+;CHECK:                   OpDecorate %_struct_43 Block
+;CHECK:                   OpMemberDecorate %_struct_43 0 Offset 0
+;CHECK:                   OpMemberDecorate %_struct_43 1 Offset 4
+;CHECK:                   OpDecorate %45 DescriptorSet 7
+;CHECK:                   OpDecorate %45 Binding 0
+;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
+                  %void = OpTypeVoid
+                     %3 = OpTypeFunction %void
+                 %float = OpTypeFloat 32
+               %v4float = OpTypeVector %float 4
+           %_ptr_Output_v4float = OpTypePointer Output %v4float
+                     %x = OpVariable %_ptr_Output_v4float Output
+                    %10 = OpTypeImage %float Buffer 0 0 0 2 R32f
+           %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+                     %s = OpVariable %_ptr_UniformConstant_10 UniformConstant
+                   %int = OpTypeInt 32 1
+           %_ptr_Input_int = OpTypePointer Input %int
+                    %ii = OpVariable %_ptr_Input_int Input
+;CHECK:           %uint = OpTypeInt 32 0
+;CHECK:         %uint_0 = OpConstant %uint 0
+;CHECK:           %bool = OpTypeBool
+;CHECK:         %uint_3 = OpConstant %uint 3
+;CHECK:             %35 = OpTypeFunction %void %uint %uint %uint %uint %uint
+;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
+;CHECK:     %_struct_43 = OpTypeStruct %uint %_runtimearr_uint
+;CHECK:    %_ptr_StorageBuffer__struct_43 = OpTypePointer StorageBuffer %_struct_43
+;CHECK:             %45 = OpVariable %_ptr_StorageBuffer__struct_43 StorageBuffer
+;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+;CHECK:        %uint_11 = OpConstant %uint 11
+;CHECK:         %uint_4 = OpConstant %uint 4
+;CHECK:         %uint_1 = OpConstant %uint 1
+;CHECK:        %uint_23 = OpConstant %uint 23
+;CHECK:         %uint_2 = OpConstant %uint 2
+;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
+;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+;CHECK:         %v4uint = OpTypeVector %uint 4
+;CHECK:         %uint_5 = OpConstant %uint 5
+;CHECK:         %uint_7 = OpConstant %uint 7
+;CHECK:         %uint_8 = OpConstant %uint 8
+;CHECK:         %uint_9 = OpConstant %uint 9
+;CHECK:        %uint_10 = OpConstant %uint 10
+;CHECK:        %uint_33 = OpConstant %uint 33
+;CHECK:             %93 = OpConstantNull %v4float
+                  %main = OpFunction %void None %3
+                     %5 = OpLabel
+;CHECK:                   OpBranch %21
+;CHECK:             %21 = OpLabel
+;CHECK:                   OpBranch %20
+;CHECK:             %20 = OpLabel
+;CHECK:                   OpBranch %19
+;CHECK:             %19 = OpLabel
+                    %13 = OpLoad %10 %s
+                    %17 = OpLoad %int %ii
+                    %18 = OpImageRead %v4float %13 %17
+                          OpStore %x %18
+;CHECK-NOT:         %18 = OpImageRead %v4float %13 %17
+;CHECK-NOT:               OpStore %x %18
+;CHECK:             %23 = OpBitcast %uint %17
+;CHECK:             %25 = OpImageQuerySize %uint %13
+;CHECK:             %27 = OpULessThan %bool %23 %25
+;CHECK:                   OpSelectionMerge %29 None
+;CHECK:                   OpBranchConditional %27 %30 %31
+;CHECK:             %30 = OpLabel
+;CHECK:             %32 = OpLoad %10 %s
+;CHECK:             %33 = OpImageRead %v4float %32 %17
+;CHECK:                   OpBranch %29
+;CHECK:             %31 = OpLabel
+;CHECK:             %92 = OpFunctionCall %void %34 %uint_33 %uint_3 %uint_0 %23 %25
+;CHECK:                   OpBranch %29
+;CHECK:             %29 = OpLabel
+;CHECK:             %94 = OpPhi %v4float %33 %30 %93 %31
+;CHECK:                   OpStore %x %94
+                          OpReturn
+                          OpFunctionEnd
+;CHECK:             %34 = OpFunction %void None %35
+;CHECK:             %36 = OpFunctionParameter %uint
+;CHECK:             %37 = OpFunctionParameter %uint
+;CHECK:             %38 = OpFunctionParameter %uint
+;CHECK:             %39 = OpFunctionParameter %uint
+;CHECK:             %40 = OpFunctionParameter %uint
+;CHECK:             %41 = OpLabel
+;CHECK:             %47 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0
+;CHECK:             %50 = OpAtomicIAdd %uint %47 %uint_4 %uint_0 %uint_11
+;CHECK:             %51 = OpIAdd %uint %50 %uint_11
+;CHECK:             %52 = OpArrayLength %uint %45 1
+;CHECK:             %53 = OpULessThanEqual %bool %51 %52
+;CHECK:                   OpSelectionMerge %54 None
+;CHECK:                   OpBranchConditional %53 %55 %54
+;CHECK:             %55 = OpLabel
+;CHECK:             %56 = OpIAdd %uint %50 %uint_0
+;CHECK:             %58 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %56
+;CHECK:                   OpStore %58 %uint_11
+;CHECK:             %60 = OpIAdd %uint %50 %uint_1
+;CHECK:             %61 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %60
+;CHECK:                   OpStore %61 %uint_23
+;CHECK:             %63 = OpIAdd %uint %50 %uint_2
+;CHECK:             %64 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %63
+;CHECK:                   OpStore %64 %36
+;CHECK:             %65 = OpIAdd %uint %50 %uint_3
+;CHECK:             %66 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %65
+;CHECK:                   OpStore %66 %uint_4
+;CHECK:             %69 = OpLoad %v4float %gl_FragCoord
+;CHECK:             %71 = OpBitcast %v4uint %69
+;CHECK:             %72 = OpCompositeExtract %uint %71 0
+;CHECK:             %73 = OpIAdd %uint %50 %uint_4
+;CHECK:             %74 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %73
+;CHECK:                   OpStore %74 %72
+;CHECK:             %75 = OpCompositeExtract %uint %71 1
+;CHECK:             %77 = OpIAdd %uint %50 %uint_5
+;CHECK:             %78 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %77
+;CHECK:                   OpStore %78 %75
+;CHECK:             %80 = OpIAdd %uint %50 %uint_7
+;CHECK:             %81 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %80
+;CHECK:                   OpStore %81 %37
+;CHECK:             %83 = OpIAdd %uint %50 %uint_8
+;CHECK:             %84 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %83
+;CHECK:                   OpStore %84 %38
+;CHECK:             %86 = OpIAdd %uint %50 %uint_9
+;CHECK:             %87 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %86
+;CHECK:                   OpStore %87 %39
+;CHECK:             %89 = OpIAdd %uint %50 %uint_10
+;CHECK:             %90 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %89
+;CHECK:                   OpStore %90 %40
+;CHECK:                   OpBranch %54
+;CHECK:             %54 = OpLabel
+;CHECK:                   OpReturn
+;CHECK:                   OpFunctionEnd
+  )";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
+                                               false, true, true, true);
+}
+
+TEST_F(InstBindlessTest, ImageBufferOOBWrite) {
+  // Texel buffer (imagebuffer) oob check for ImageWrite
+  //
+  // #version 450
+  // layout(set=3, binding=7, r32f) uniform readonly imageBuffer s;
+  // layout(location=11) out vec4 x;
+  // layout(location=13) in flat int ii;
+  //
+  // void main(){
+  //    imageStore(s, ii, x);
+  // }
+
+  const std::string text = R"(
+                          OpCapability Shader
+                          OpCapability ImageBuffer
+;CHECK:                   OpCapability ImageQuery
+;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
+                     %1 = OpExtInstImport "GLSL.std.450"
+                          OpMemoryModel Logical GLSL450
+                          OpEntryPoint Fragment %main "main" %s %ii %x
+;CHECK:                   OpEntryPoint Fragment %main "main" %s %ii %x %44 %gl_FragCoord
+                          OpExecutionMode %main OriginUpperLeft
+                          OpSource GLSL 450
+                          OpName %main "main"
+                          OpName %s "s"
+                          OpName %ii "ii"
+                          OpName %x "x"
+                          OpDecorate %s DescriptorSet 3
+                          OpDecorate %s Binding 7
+                          OpDecorate %s NonReadable
+                          OpDecorate %ii Flat
+                          OpDecorate %ii Location 13
+                          OpDecorate %x Location 11
+;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
+;CHECK:                   OpDecorate %_struct_42 Block
+;CHECK:                   OpMemberDecorate %_struct_42 0 Offset 0
+;CHECK:                   OpMemberDecorate %_struct_42 1 Offset 4
+;CHECK:                   OpDecorate %44 DescriptorSet 7
+;CHECK:                   OpDecorate %44 Binding 0
+;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
+                  %void = OpTypeVoid
+                     %3 = OpTypeFunction %void
+                 %float = OpTypeFloat 32
+                     %7 = OpTypeImage %float Buffer 0 0 0 2 R32f
+           %_ptr_UniformConstant_7 = OpTypePointer UniformConstant %7
+                     %s = OpVariable %_ptr_UniformConstant_7 UniformConstant
+                   %int = OpTypeInt 32 1
+           %_ptr_Input_int = OpTypePointer Input %int
+                    %ii = OpVariable %_ptr_Input_int Input
+               %v4float = OpTypeVector %float 4
+           %_ptr_Output_v4float = OpTypePointer Output %v4float
+                     %x = OpVariable %_ptr_Output_v4float Output
+;CHECK:           %uint = OpTypeInt 32 0
+;CHECK:         %uint_0 = OpConstant %uint 0
+;CHECK:           %bool = OpTypeBool
+;CHECK:         %uint_3 = OpConstant %uint 3
+;CHECK:             %34 = OpTypeFunction %void %uint %uint %uint %uint %uint
+;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
+;CHECK:     %_struct_42 = OpTypeStruct %uint %_runtimearr_uint
+;CHECK:    %_ptr_StorageBuffer__struct_42 = OpTypePointer StorageBuffer %_struct_42
+;CHECK:             %44 = OpVariable %_ptr_StorageBuffer__struct_42 StorageBuffer
+;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+;CHECK:        %uint_11 = OpConstant %uint 11
+;CHECK:         %uint_4 = OpConstant %uint 4
+;CHECK:         %uint_1 = OpConstant %uint 1
+;CHECK:        %uint_23 = OpConstant %uint 23
+;CHECK:         %uint_2 = OpConstant %uint 2
+;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
+;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+;CHECK:         %v4uint = OpTypeVector %uint 4
+;CHECK:         %uint_5 = OpConstant %uint 5
+;CHECK:         %uint_7 = OpConstant %uint 7
+;CHECK:         %uint_8 = OpConstant %uint 8
+;CHECK:         %uint_9 = OpConstant %uint 9
+;CHECK:        %uint_10 = OpConstant %uint 10
+;CHECK:        %uint_34 = OpConstant %uint 34
+                  %main = OpFunction %void None %3
+                     %5 = OpLabel
+;CHECK:                   OpBranch %21
+;CHECK:             %21 = OpLabel
+;CHECK:                   OpBranch %20
+;CHECK:             %20 = OpLabel
+;CHECK:                   OpBranch %19
+;CHECK:             %19 = OpLabel
+                    %10 = OpLoad %7 %s
+                    %14 = OpLoad %int %ii
+                    %18 = OpLoad %v4float %x
+                          OpImageWrite %10 %14 %18
+;CHECK-NOT:               OpImageWrite %10 %14 %18
+;CHECK:             %23 = OpBitcast %uint %14
+;CHECK:             %25 = OpImageQuerySize %uint %10
+;CHECK:             %27 = OpULessThan %bool %23 %25
+;CHECK:                   OpSelectionMerge %29 None
+;CHECK:                   OpBranchConditional %27 %30 %31
+;CHECK:             %30 = OpLabel
+;CHECK:             %32 = OpLoad %7 %s
+;CHECK:                   OpImageWrite %32 %14 %18
+;CHECK:                   OpBranch %29
+;CHECK:             %31 = OpLabel
+;CHECK:             %91 = OpFunctionCall %void %33 %uint_34 %uint_3 %uint_0 %23 %25
+;CHECK:                   OpBranch %29
+;CHECK:             %29 = OpLabel
+                          OpReturn
+                          OpFunctionEnd
+;CHECK:             %33 = OpFunction %void None %34
+;CHECK:             %35 = OpFunctionParameter %uint
+;CHECK:             %36 = OpFunctionParameter %uint
+;CHECK:             %37 = OpFunctionParameter %uint
+;CHECK:             %38 = OpFunctionParameter %uint
+;CHECK:             %39 = OpFunctionParameter %uint
+;CHECK:             %40 = OpLabel
+;CHECK:             %46 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_0
+;CHECK:             %49 = OpAtomicIAdd %uint %46 %uint_4 %uint_0 %uint_11
+;CHECK:             %50 = OpIAdd %uint %49 %uint_11
+;CHECK:             %51 = OpArrayLength %uint %44 1
+;CHECK:             %52 = OpULessThanEqual %bool %50 %51
+;CHECK:                   OpSelectionMerge %53 None
+;CHECK:                   OpBranchConditional %52 %54 %53
+;CHECK:             %54 = OpLabel
+;CHECK:             %55 = OpIAdd %uint %49 %uint_0
+;CHECK:             %57 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %55
+;CHECK:                   OpStore %57 %uint_11
+;CHECK:             %59 = OpIAdd %uint %49 %uint_1
+;CHECK:             %60 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %59
+;CHECK:                   OpStore %60 %uint_23
+;CHECK:             %62 = OpIAdd %uint %49 %uint_2
+;CHECK:             %63 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %62
+;CHECK:                   OpStore %63 %35
+;CHECK:             %64 = OpIAdd %uint %49 %uint_3
+;CHECK:             %65 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %64
+;CHECK:                   OpStore %65 %uint_4
+;CHECK:             %68 = OpLoad %v4float %gl_FragCoord
+;CHECK:             %70 = OpBitcast %v4uint %68
+;CHECK:             %71 = OpCompositeExtract %uint %70 0
+;CHECK:             %72 = OpIAdd %uint %49 %uint_4
+;CHECK:             %73 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %72
+;CHECK:                   OpStore %73 %71
+;CHECK:             %74 = OpCompositeExtract %uint %70 1
+;CHECK:             %76 = OpIAdd %uint %49 %uint_5
+;CHECK:             %77 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %76
+;CHECK:                   OpStore %77 %74
+;CHECK:             %79 = OpIAdd %uint %49 %uint_7
+;CHECK:             %80 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %79
+;CHECK:                   OpStore %80 %36
+;CHECK:             %82 = OpIAdd %uint %49 %uint_8
+;CHECK:             %83 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %82
+;CHECK:                   OpStore %83 %37
+;CHECK:             %85 = OpIAdd %uint %49 %uint_9
+;CHECK:             %86 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %85
+;CHECK:                   OpStore %86 %38
+;CHECK:             %88 = OpIAdd %uint %49 %uint_10
+;CHECK:             %89 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %88
+;CHECK:                   OpStore %89 %39
+;CHECK:                   OpBranch %53
+;CHECK:             %53 = OpLabel
+;CHECK:                   OpReturn
+;CHECK:                   OpFunctionEnd
+  )";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
+                                               false, true, true, true);
+}
+
+TEST_F(InstBindlessTest, TextureBufferOOBFetch) {
+  // Texel buffer (texturebuffer) oob check for ImageFetch
+  //
+  // #version 450
+  // layout(set=3, binding=7) uniform textureBuffer s;
+  // layout(location=11) out vec4 x;
+  // layout(location=13) in flat int ii;
+  //
+  // void main(){
+  //    x = texelFetch(s, ii);
+  // }
+
+  const std::string text = R"(
+                          OpCapability Shader
+                          OpCapability SampledBuffer
+;CHECK:                   OpCapability ImageQuery
+;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
+                     %1 = OpExtInstImport "GLSL.std.450"
+                          OpMemoryModel Logical GLSL450
+                          OpEntryPoint Fragment %main "main" %x %s %ii
+;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %45 %gl_FragCoord
+                          OpExecutionMode %main OriginUpperLeft
+                          OpSource GLSL 450
+                          OpName %main "main"
+                          OpName %x "x"
+                          OpName %s "s"
+                          OpName %ii "ii"
+                          OpDecorate %x Location 11
+                          OpDecorate %s DescriptorSet 3
+                          OpDecorate %s Binding 7
+                          OpDecorate %ii Flat
+                          OpDecorate %ii Location 13
+;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
+;CHECK:                   OpDecorate %_struct_43 Block
+;CHECK:                   OpMemberDecorate %_struct_43 0 Offset 0
+;CHECK:                   OpMemberDecorate %_struct_43 1 Offset 4
+;CHECK:                   OpDecorate %45 DescriptorSet 7
+;CHECK:                   OpDecorate %45 Binding 0
+;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
+                  %void = OpTypeVoid
+                     %3 = OpTypeFunction %void
+                 %float = OpTypeFloat 32
+               %v4float = OpTypeVector %float 4
+           %_ptr_Output_v4float = OpTypePointer Output %v4float
+                     %x = OpVariable %_ptr_Output_v4float Output
+                    %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown
+           %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+                     %s = OpVariable %_ptr_UniformConstant_10 UniformConstant
+                   %int = OpTypeInt 32 1
+           %_ptr_Input_int = OpTypePointer Input %int
+                    %ii = OpVariable %_ptr_Input_int Input
+;CHECK:           %uint = OpTypeInt 32 0
+;CHECK:         %uint_0 = OpConstant %uint 0
+;CHECK:           %bool = OpTypeBool
+;CHECK:         %uint_3 = OpConstant %uint 3
+;CHECK:             %35 = OpTypeFunction %void %uint %uint %uint %uint %uint
+;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
+;CHECK:     %_struct_43 = OpTypeStruct %uint %_runtimearr_uint
+;CHECK:    %_ptr_StorageBuffer__struct_43 = OpTypePointer StorageBuffer %_struct_43
+;CHECK:             %45 = OpVariable %_ptr_StorageBuffer__struct_43 StorageBuffer
+;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+;CHECK:        %uint_11 = OpConstant %uint 11
+;CHECK:         %uint_4 = OpConstant %uint 4
+;CHECK:         %uint_1 = OpConstant %uint 1
+;CHECK:        %uint_23 = OpConstant %uint 23
+;CHECK:         %uint_2 = OpConstant %uint 2
+;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
+;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+;CHECK:         %v4uint = OpTypeVector %uint 4
+;CHECK:         %uint_5 = OpConstant %uint 5
+;CHECK:         %uint_7 = OpConstant %uint 7
+;CHECK:         %uint_8 = OpConstant %uint 8
+;CHECK:         %uint_9 = OpConstant %uint 9
+;CHECK:        %uint_10 = OpConstant %uint 10
+;CHECK:        %uint_32 = OpConstant %uint 32
+;CHECK:             %93 = OpConstantNull %v4float
+                  %main = OpFunction %void None %3
+                     %5 = OpLabel
+;CHECK:                   OpBranch %21
+;CHECK:             %21 = OpLabel
+;CHECK:                   OpBranch %20
+;CHECK:             %20 = OpLabel
+;CHECK:                   OpBranch %19
+;CHECK:             %19 = OpLabel
+                    %13 = OpLoad %10 %s
+                    %17 = OpLoad %int %ii
+                    %18 = OpImageFetch %v4float %13 %17
+                          OpStore %x %18
+;CHECK-NOT:         %18 = OpImageFetch %v4float %13 %17
+;CHECK-NOT:               OpStore %x %18
+;CHECK:             %23 = OpBitcast %uint %17
+;CHECK:             %25 = OpImageQuerySize %uint %13
+;CHECK:             %27 = OpULessThan %bool %23 %25
+;CHECK:                   OpSelectionMerge %29 None
+;CHECK:                   OpBranchConditional %27 %30 %31
+;CHECK:             %30 = OpLabel
+;CHECK:             %32 = OpLoad %10 %s
+;CHECK:             %33 = OpImageFetch %v4float %32 %17
+;CHECK:                   OpBranch %29
+;CHECK:             %31 = OpLabel
+;CHECK:             %92 = OpFunctionCall %void %34 %uint_32 %uint_3 %uint_0 %23 %25
+;CHECK:                   OpBranch %29
+;CHECK:             %29 = OpLabel
+;CHECK:             %94 = OpPhi %v4float %33 %30 %93 %31
+;CHECK:                   OpStore %x %94
+                          OpReturn
+                          OpFunctionEnd
+;CHECK:             %34 = OpFunction %void None %35
+;CHECK:             %36 = OpFunctionParameter %uint
+;CHECK:             %37 = OpFunctionParameter %uint
+;CHECK:             %38 = OpFunctionParameter %uint
+;CHECK:             %39 = OpFunctionParameter %uint
+;CHECK:             %40 = OpFunctionParameter %uint
+;CHECK:             %41 = OpLabel
+;CHECK:             %47 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0
+;CHECK:             %50 = OpAtomicIAdd %uint %47 %uint_4 %uint_0 %uint_11
+;CHECK:             %51 = OpIAdd %uint %50 %uint_11
+;CHECK:             %52 = OpArrayLength %uint %45 1
+;CHECK:             %53 = OpULessThanEqual %bool %51 %52
+;CHECK:                   OpSelectionMerge %54 None
+;CHECK:                   OpBranchConditional %53 %55 %54
+;CHECK:             %55 = OpLabel
+;CHECK:             %56 = OpIAdd %uint %50 %uint_0
+;CHECK:             %58 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %56
+;CHECK:                   OpStore %58 %uint_11
+;CHECK:             %60 = OpIAdd %uint %50 %uint_1
+;CHECK:             %61 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %60
+;CHECK:                   OpStore %61 %uint_23
+;CHECK:             %63 = OpIAdd %uint %50 %uint_2
+;CHECK:             %64 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %63
+;CHECK:                   OpStore %64 %36
+;CHECK:             %65 = OpIAdd %uint %50 %uint_3
+;CHECK:             %66 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %65
+;CHECK:                   OpStore %66 %uint_4
+;CHECK:             %69 = OpLoad %v4float %gl_FragCoord
+;CHECK:             %71 = OpBitcast %v4uint %69
+;CHECK:             %72 = OpCompositeExtract %uint %71 0
+;CHECK:             %73 = OpIAdd %uint %50 %uint_4
+;CHECK:             %74 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %73
+;CHECK:                   OpStore %74 %72
+;CHECK:             %75 = OpCompositeExtract %uint %71 1
+;CHECK:             %77 = OpIAdd %uint %50 %uint_5
+;CHECK:             %78 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %77
+;CHECK:                   OpStore %78 %75
+;CHECK:             %80 = OpIAdd %uint %50 %uint_7
+;CHECK:             %81 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %80
+;CHECK:                   OpStore %81 %37
+;CHECK:             %83 = OpIAdd %uint %50 %uint_8
+;CHECK:             %84 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %83
+;CHECK:                   OpStore %84 %38
+;CHECK:             %86 = OpIAdd %uint %50 %uint_9
+;CHECK:             %87 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %86
+;CHECK:                   OpStore %87 %39
+;CHECK:             %89 = OpIAdd %uint %50 %uint_10
+;CHECK:             %90 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %89
+;CHECK:                   OpStore %90 %40
+;CHECK:                   OpBranch %54
+;CHECK:             %54 = OpLabel
+;CHECK:                   OpReturn
+;CHECK:                   OpFunctionEnd
+  )";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
+                                               false, true, true, true);
+}
+
+TEST_F(InstBindlessTest, SamplerBufferOOBFetch) {
+  // Texel buffer (samplerbuffer) oob check for ImageFetch
+  //
+  // #version 450
+  // layout(set=3, binding=7) uniform samplerBuffer s;
+  // layout(location=11) out vec4 x;
+  // layout(location=13) in flat int ii;
+  //
+  // void main(){
+  //    x = texelFetch(s, ii);
+  // }
+
+  const std::string text = R"(
+                          OpCapability Shader
+                          OpCapability SampledBuffer
+;CHECK:                   OpCapability ImageQuery
+;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
+                     %1 = OpExtInstImport "GLSL.std.450"
+                          OpMemoryModel Logical GLSL450
+                          OpEntryPoint Fragment %main "main" %x %s %ii
+;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %48 %gl_FragCoord
+                          OpExecutionMode %main OriginUpperLeft
+                          OpSource GLSL 450
+                          OpName %main "main"
+                          OpName %x "x"
+                          OpName %s "s"
+                          OpName %ii "ii"
+                          OpDecorate %x Location 11
+                          OpDecorate %s DescriptorSet 3
+                          OpDecorate %s Binding 7
+                          OpDecorate %ii Flat
+                          OpDecorate %ii Location 13
+;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
+;CHECK:                   OpDecorate %_struct_46 Block
+;CHECK:                   OpMemberDecorate %_struct_46 0 Offset 0
+;CHECK:                   OpMemberDecorate %_struct_46 1 Offset 4
+;CHECK:                   OpDecorate %48 DescriptorSet 7
+;CHECK:                   OpDecorate %48 Binding 0
+;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
+                  %void = OpTypeVoid
+                     %3 = OpTypeFunction %void
+                 %float = OpTypeFloat 32
+               %v4float = OpTypeVector %float 4
+           %_ptr_Output_v4float = OpTypePointer Output %v4float
+                     %x = OpVariable %_ptr_Output_v4float Output
+                    %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown
+                    %11 = OpTypeSampledImage %10
+           %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+                     %s = OpVariable %_ptr_UniformConstant_11 UniformConstant
+                   %int = OpTypeInt 32 1
+           %_ptr_Input_int = OpTypePointer Input %int
+                    %ii = OpVariable %_ptr_Input_int Input
+;CHECK:           %uint = OpTypeInt 32 0
+;CHECK:         %uint_0 = OpConstant %uint 0
+;CHECK:           %bool = OpTypeBool
+;CHECK:         %uint_3 = OpConstant %uint 3
+;CHECK:             %38 = OpTypeFunction %void %uint %uint %uint %uint %uint
+;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
+;CHECK:     %_struct_46 = OpTypeStruct %uint %_runtimearr_uint
+;CHECK:    %_ptr_StorageBuffer__struct_46 = OpTypePointer StorageBuffer %_struct_46
+;CHECK:             %48 = OpVariable %_ptr_StorageBuffer__struct_46 StorageBuffer
+;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+;CHECK:        %uint_11 = OpConstant %uint 11
+;CHECK:         %uint_4 = OpConstant %uint 4
+;CHECK:         %uint_1 = OpConstant %uint 1
+;CHECK:        %uint_23 = OpConstant %uint 23
+;CHECK:         %uint_2 = OpConstant %uint 2
+;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
+;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+;CHECK:         %v4uint = OpTypeVector %uint 4
+;CHECK:         %uint_5 = OpConstant %uint 5
+;CHECK:         %uint_7 = OpConstant %uint 7
+;CHECK:         %uint_8 = OpConstant %uint 8
+;CHECK:         %uint_9 = OpConstant %uint 9
+;CHECK:        %uint_10 = OpConstant %uint 10
+;CHECK:        %uint_34 = OpConstant %uint 34
+;CHECK:             %96 = OpConstantNull %v4float
+                  %main = OpFunction %void None %3
+                     %5 = OpLabel
+;CHECK:                   OpBranch %23
+;CHECK:             %23 = OpLabel
+;CHECK:                   OpBranch %22
+;CHECK:             %22 = OpLabel
+;CHECK:                   OpBranch %21
+;CHECK:             %21 = OpLabel
+                    %14 = OpLoad %11 %s
+                    %18 = OpLoad %int %ii
+                    %19 = OpImage %10 %14
+                    %20 = OpImageFetch %v4float %19 %18
+                          OpStore %x %20
+;CHECK-NOT:         %20 = OpImageFetch %v4float %19 %18
+;CHECK-NOT:               OpStore %x %20
+;CHECK:             %25 = OpBitcast %uint %18
+;CHECK:             %27 = OpImageQuerySize %uint %19
+;CHECK:             %29 = OpULessThan %bool %25 %27
+;CHECK:                   OpSelectionMerge %31 None
+;CHECK:                   OpBranchConditional %29 %32 %33
+;CHECK:             %32 = OpLabel
+;CHECK:             %34 = OpLoad %11 %s
+;CHECK:             %35 = OpImage %10 %34
+;CHECK:             %36 = OpImageFetch %v4float %35 %18
+;CHECK:                   OpBranch %31
+;CHECK:             %33 = OpLabel
+;CHECK:             %95 = OpFunctionCall %void %37 %uint_34 %uint_3 %uint_0 %25 %27
+;CHECK:                   OpBranch %31
+;CHECK:             %31 = OpLabel
+;CHECK:             %97 = OpPhi %v4float %36 %32 %96 %33
+;CHECK:                   OpStore %x %97
+                          OpReturn
+                          OpFunctionEnd
+;CHECK:             %37 = OpFunction %void None %38
+;CHECK:             %39 = OpFunctionParameter %uint
+;CHECK:             %40 = OpFunctionParameter %uint
+;CHECK:             %41 = OpFunctionParameter %uint
+;CHECK:             %42 = OpFunctionParameter %uint
+;CHECK:             %43 = OpFunctionParameter %uint
+;CHECK:             %44 = OpLabel
+;CHECK:             %50 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0
+;CHECK:             %53 = OpAtomicIAdd %uint %50 %uint_4 %uint_0 %uint_11
+;CHECK:             %54 = OpIAdd %uint %53 %uint_11
+;CHECK:             %55 = OpArrayLength %uint %48 1
+;CHECK:             %56 = OpULessThanEqual %bool %54 %55
+;CHECK:                   OpSelectionMerge %57 None
+;CHECK:                   OpBranchConditional %56 %58 %57
+;CHECK:             %58 = OpLabel
+;CHECK:             %59 = OpIAdd %uint %53 %uint_0
+;CHECK:             %61 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %59
+;CHECK:                   OpStore %61 %uint_11
+;CHECK:             %63 = OpIAdd %uint %53 %uint_1
+;CHECK:             %64 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %63
+;CHECK:                   OpStore %64 %uint_23
+;CHECK:             %66 = OpIAdd %uint %53 %uint_2
+;CHECK:             %67 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %66
+;CHECK:                   OpStore %67 %39
+;CHECK:             %68 = OpIAdd %uint %53 %uint_3
+;CHECK:             %69 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %68
+;CHECK:                   OpStore %69 %uint_4
+;CHECK:             %72 = OpLoad %v4float %gl_FragCoord
+;CHECK:             %74 = OpBitcast %v4uint %72
+;CHECK:             %75 = OpCompositeExtract %uint %74 0
+;CHECK:             %76 = OpIAdd %uint %53 %uint_4
+;CHECK:             %77 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %76
+;CHECK:                   OpStore %77 %75
+;CHECK:             %78 = OpCompositeExtract %uint %74 1
+;CHECK:             %80 = OpIAdd %uint %53 %uint_5
+;CHECK:             %81 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %80
+;CHECK:                   OpStore %81 %78
+;CHECK:             %83 = OpIAdd %uint %53 %uint_7
+;CHECK:             %84 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %83
+;CHECK:                   OpStore %84 %40
+;CHECK:             %86 = OpIAdd %uint %53 %uint_8
+;CHECK:             %87 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %86
+;CHECK:                   OpStore %87 %41
+;CHECK:             %89 = OpIAdd %uint %53 %uint_9
+;CHECK:             %90 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %89
+;CHECK:                   OpStore %90 %42
+;CHECK:             %92 = OpIAdd %uint %53 %uint_10
+;CHECK:             %93 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %92
+;CHECK:                   OpStore %93 %43
+;CHECK:                   OpBranch %57
+;CHECK:             %57 = OpLabel
+;CHECK:                   OpReturn
+;CHECK:                   OpFunctionEnd
+  )";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
+                                               false, true, true, true);
+}
+
+TEST_F(InstBindlessTest, SamplerBufferConstructorOOBFetch) {
+  // Texel buffer (samplerbuffer constructor) oob check for ImageFetch
+  //
+  // #version 450
+  // layout(set=3, binding=7) uniform textureBuffer tBuf;
+  // layout(set=3, binding=8) uniform sampler s;
+  // layout(location=11) out vec4 x;
+  // layout(location=13) in flat int ii;
+  //
+  // void main(){
+  //    x = texelFetch(samplerBuffer(tBuf, s), ii);
+  // }
+
+  const std::string text = R"(
+                          OpCapability Shader
+                          OpCapability SampledBuffer
+;CHECK:                   OpCapability ImageQuery
+;CHECK:                   OpExtension "SPV_KHR_storage_buffer_storage_class"
+                     %1 = OpExtInstImport "GLSL.std.450"
+                          OpMemoryModel Logical GLSL450
+                          OpEntryPoint Fragment %main "main" %x %tBuf %s %ii
+;CHECK:                   OpEntryPoint Fragment %main "main" %x %tBuf %s %ii %54 %gl_FragCoord
+                          OpExecutionMode %main OriginUpperLeft
+                          OpSource GLSL 450
+                          OpName %main "main"
+                          OpName %x "x"
+                          OpName %tBuf "tBuf"
+                          OpName %s "s"
+                          OpName %ii "ii"
+                          OpDecorate %x Location 11
+                          OpDecorate %tBuf DescriptorSet 3
+                          OpDecorate %tBuf Binding 7
+                          OpDecorate %s DescriptorSet 3
+                          OpDecorate %s Binding 8
+                          OpDecorate %ii Flat
+                          OpDecorate %ii Location 13
+;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
+;CHECK:                   OpDecorate %_struct_52 Block
+;CHECK:                   OpMemberDecorate %_struct_52 0 Offset 0
+;CHECK:                   OpMemberDecorate %_struct_52 1 Offset 4
+;CHECK:                   OpDecorate %54 DescriptorSet 7
+;CHECK:                   OpDecorate %54 Binding 0
+;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
+                  %void = OpTypeVoid
+                     %3 = OpTypeFunction %void
+                 %float = OpTypeFloat 32
+               %v4float = OpTypeVector %float 4
+           %_ptr_Output_v4float = OpTypePointer Output %v4float
+                     %x = OpVariable %_ptr_Output_v4float Output
+                    %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown
+           %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+                  %tBuf = OpVariable %_ptr_UniformConstant_10 UniformConstant
+                    %14 = OpTypeSampler
+           %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
+                     %s = OpVariable %_ptr_UniformConstant_14 UniformConstant
+                    %18 = OpTypeSampledImage %10
+                   %int = OpTypeInt 32 1
+           %_ptr_Input_int = OpTypePointer Input %int
+                    %ii = OpVariable %_ptr_Input_int Input
+;CHECK:           %uint = OpTypeInt 32 0
+;CHECK:         %uint_0 = OpConstant %uint 0
+;CHECK:           %bool = OpTypeBool
+;CHECK:         %uint_3 = OpConstant %uint 3
+;CHECK:             %44 = OpTypeFunction %void %uint %uint %uint %uint %uint
+;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
+;CHECK:     %_struct_52 = OpTypeStruct %uint %_runtimearr_uint
+;CHECK:    %_ptr_StorageBuffer__struct_52 = OpTypePointer StorageBuffer %_struct_52
+;CHECK:             %54 = OpVariable %_ptr_StorageBuffer__struct_52 StorageBuffer
+;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+;CHECK:        %uint_11 = OpConstant %uint 11
+;CHECK:         %uint_4 = OpConstant %uint 4
+;CHECK:         %uint_1 = OpConstant %uint 1
+;CHECK:        %uint_23 = OpConstant %uint 23
+;CHECK:         %uint_2 = OpConstant %uint 2
+;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
+;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+;CHECK:         %v4uint = OpTypeVector %uint 4
+;CHECK:         %uint_5 = OpConstant %uint 5
+;CHECK:         %uint_7 = OpConstant %uint 7
+;CHECK:         %uint_8 = OpConstant %uint 8
+;CHECK:         %uint_9 = OpConstant %uint 9
+;CHECK:        %uint_10 = OpConstant %uint 10
+;CHECK:        %uint_42 = OpConstant %uint 42
+;CHECK:            %102 = OpConstantNull %v4float
+                  %main = OpFunction %void None %3
+                     %5 = OpLabel
+;CHECK:                   OpBranch %28
+;CHECK:             %28 = OpLabel
+;CHECK:                   OpBranch %27
+;CHECK:             %27 = OpLabel
+;CHECK:                   OpBranch %26
+;CHECK:             %26 = OpLabel
+                    %13 = OpLoad %10 %tBuf
+                    %17 = OpLoad %14 %s
+                    %19 = OpSampledImage %18 %13 %17
+                    %23 = OpLoad %int %ii
+                    %24 = OpImage %10 %19
+                    %25 = OpImageFetch %v4float %24 %23
+                          OpStore %x %25
+;CHECK-NOT:         %25 = OpImageFetch %v4float %24 %23
+;CHECK-NOT:               OpStore %x %25
+;CHECK:             %30 = OpBitcast %uint %23
+;CHECK:             %32 = OpImageQuerySize %uint %24
+;CHECK:             %34 = OpULessThan %bool %30 %32
+;CHECK:                   OpSelectionMerge %36 None
+;CHECK:                   OpBranchConditional %34 %37 %38
+;CHECK:             %37 = OpLabel
+;CHECK:             %39 = OpLoad %10 %tBuf
+;CHECK:             %40 = OpSampledImage %18 %39 %17
+;CHECK:             %41 = OpImage %10 %40
+;CHECK:             %42 = OpImageFetch %v4float %41 %23
+;CHECK:                   OpBranch %36
+;CHECK:             %38 = OpLabel
+;CHECK:            %101 = OpFunctionCall %void %43 %uint_42 %uint_3 %uint_0 %30 %32
+;CHECK:                   OpBranch %36
+;CHECK:             %36 = OpLabel
+;CHECK:            %103 = OpPhi %v4float %42 %37 %102 %38
+;CHECK:                   OpStore %x %103
+                          OpReturn
+                          OpFunctionEnd
+;CHECK:             %43 = OpFunction %void None %44
+;CHECK:             %45 = OpFunctionParameter %uint
+;CHECK:             %46 = OpFunctionParameter %uint
+;CHECK:             %47 = OpFunctionParameter %uint
+;CHECK:             %48 = OpFunctionParameter %uint
+;CHECK:             %49 = OpFunctionParameter %uint
+;CHECK:             %50 = OpLabel
+;CHECK:             %56 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_0
+;CHECK:             %59 = OpAtomicIAdd %uint %56 %uint_4 %uint_0 %uint_11
+;CHECK:             %60 = OpIAdd %uint %59 %uint_11
+;CHECK:             %61 = OpArrayLength %uint %54 1
+;CHECK:             %62 = OpULessThanEqual %bool %60 %61
+;CHECK:                   OpSelectionMerge %63 None
+;CHECK:                   OpBranchConditional %62 %64 %63
+;CHECK:             %64 = OpLabel
+;CHECK:             %65 = OpIAdd %uint %59 %uint_0
+;CHECK:             %67 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %65
+;CHECK:                   OpStore %67 %uint_11
+;CHECK:             %69 = OpIAdd %uint %59 %uint_1
+;CHECK:             %70 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %69
+;CHECK:                   OpStore %70 %uint_23
+;CHECK:             %72 = OpIAdd %uint %59 %uint_2
+;CHECK:             %73 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %72
+;CHECK:                   OpStore %73 %45
+;CHECK:             %74 = OpIAdd %uint %59 %uint_3
+;CHECK:             %75 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %74
+;CHECK:                   OpStore %75 %uint_4
+;CHECK:             %78 = OpLoad %v4float %gl_FragCoord
+;CHECK:             %80 = OpBitcast %v4uint %78
+;CHECK:             %81 = OpCompositeExtract %uint %80 0
+;CHECK:             %82 = OpIAdd %uint %59 %uint_4
+;CHECK:             %83 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %82
+;CHECK:                   OpStore %83 %81
+;CHECK:             %84 = OpCompositeExtract %uint %80 1
+;CHECK:             %86 = OpIAdd %uint %59 %uint_5
+;CHECK:             %87 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %86
+;CHECK:                   OpStore %87 %84
+;CHECK:             %89 = OpIAdd %uint %59 %uint_7
+;CHECK:             %90 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %89
+;CHECK:                   OpStore %90 %46
+;CHECK:             %92 = OpIAdd %uint %59 %uint_8
+;CHECK:             %93 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %92
+;CHECK:                   OpStore %93 %47
+;CHECK:             %95 = OpIAdd %uint %59 %uint_9
+;CHECK:             %96 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %95
+;CHECK:                   OpStore %96 %48
+;CHECK:             %98 = OpIAdd %uint %59 %uint_10
+;CHECK:             %99 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %98
+;CHECK:                   OpStore %99 %49
+;CHECK:                   OpBranch %63
+;CHECK:             %63 = OpLabel
+;CHECK:                   OpReturn
+;CHECK:                   OpFunctionEnd
+  )";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
+                                               false, true, true, true);
 }
 
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
diff --git a/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp b/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp
index 8b77aa3..475dd23 100644
--- a/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp
@@ -19,7 +19,7 @@
 #include <utility>
 #include <vector>
 
-#include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include "source/opt/build_module.h"
 #include "source/opt/def_use_manager.h"
 #include "source/opt/ir_context.h"
@@ -29,6 +29,8 @@
 namespace opt {
 namespace {
 
+using ::testing::ContainerEq;
+
 constexpr uint32_t kOpLineOperandLineIndex = 1;
 
 void DoRoundTripCheck(const std::string& text) {
@@ -236,6 +238,100 @@
   }
 }
 
+TEST(IrBuilder, BuildModule_WithoutExtraLines) {
+  const std::string text = R"(OpCapability Shader
+OpMemoryModel Logical Simple
+OpEntryPoint Vertex %main "main"
+%file = OpString "my file"
+%void = OpTypeVoid
+%voidfn = OpTypeFunction %void
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%main = OpFunction %void None %voidfn
+%100 = OpLabel
+%1 = OpFAdd %float %float_1 %float_1
+OpLine %file 1 0
+%2 = OpFMul %float %1 %1
+%3 = OpFSub %float %2 %2
+OpReturn
+OpFunctionEnd
+)";
+
+  std::vector<uint32_t> binary;
+  SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
+  ASSERT_TRUE(t.Assemble(text, &binary,
+                         SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS));
+
+  // This is the function we're testing.
+  std::unique_ptr<IRContext> context = BuildModule(
+      SPV_ENV_UNIVERSAL_1_5, nullptr, binary.data(), binary.size(), false);
+  ASSERT_NE(nullptr, context);
+
+  spvtools::opt::analysis::DefUseManager* def_use_mgr =
+      context->get_def_use_mgr();
+
+  std::vector<SpvOp> opcodes;
+  for (auto* inst = def_use_mgr->GetDef(1);
+       inst && (inst->opcode() != SpvOpFunctionEnd); inst = inst->NextNode()) {
+    inst->ForEachInst(
+        [&opcodes](spvtools::opt::Instruction* sub_inst) {
+          opcodes.push_back(sub_inst->opcode());
+        },
+        true);
+  }
+
+  EXPECT_THAT(opcodes,
+              ContainerEq(std::vector<SpvOp>{SpvOpFAdd, SpvOpLine, SpvOpFMul,
+                                             SpvOpFSub, SpvOpReturn}));
+}
+
+TEST(IrBuilder, BuildModule_WithExtraLines_IsDefault) {
+  const std::string text = R"(OpCapability Shader
+OpMemoryModel Logical Simple
+OpEntryPoint Vertex %main "main"
+%file = OpString "my file"
+%void = OpTypeVoid
+%voidfn = OpTypeFunction %void
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%main = OpFunction %void None %voidfn
+%100 = OpLabel
+%1 = OpFAdd %float %float_1 %float_1
+OpLine %file 1 0
+%2 = OpFMul %float %1 %1
+%3 = OpFSub %float %2 %2
+OpReturn
+OpFunctionEnd
+)";
+
+  std::vector<uint32_t> binary;
+
+  SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
+  ASSERT_TRUE(t.Assemble(text, &binary,
+                         SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS));
+
+  // This is the function we're testing.
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_5, nullptr, binary.data(), binary.size());
+
+  spvtools::opt::analysis::DefUseManager* def_use_mgr =
+      context->get_def_use_mgr();
+
+  std::vector<SpvOp> opcodes;
+  for (auto* inst = def_use_mgr->GetDef(1);
+       inst && (inst->opcode() != SpvOpFunctionEnd); inst = inst->NextNode()) {
+    inst->ForEachInst(
+        [&opcodes](spvtools::opt::Instruction* sub_inst) {
+          opcodes.push_back(sub_inst->opcode());
+        },
+        true);
+  }
+
+  EXPECT_THAT(opcodes, ContainerEq(std::vector<SpvOp>{
+                           SpvOpFAdd, SpvOpLine, SpvOpFMul, SpvOpLine,
+                           SpvOpFSub, SpvOpLine, SpvOpReturn}));
+}
+
 TEST(IrBuilder, ConsumeDebugInfoInst) {
   // /* HLSL */
   //
diff --git a/third_party/SPIRV-Tools/test/opt/legalize_vector_shuffle_test.cpp b/third_party/SPIRV-Tools/test/opt/legalize_vector_shuffle_test.cpp
deleted file mode 100644
index 07d96eb..0000000
--- a/third_party/SPIRV-Tools/test/opt/legalize_vector_shuffle_test.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2019 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 <vector>
-
-#include "test/opt/pass_fixture.h"
-#include "test/opt/pass_utils.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-using LegalizeVectorShuffleTest = PassTest<::testing::Test>;
-
-void operator+=(std::vector<const char*>& lhs, const char* rhs) {
-  lhs.push_back(rhs);
-}
-
-void operator+=(std::vector<const char*>& lhs,
-                const std::vector<const char*> rhs) {
-  for (auto elem : rhs) lhs.push_back(elem);
-}
-
-std::vector<const char*> header = {
-    "OpCapability Shader",
-    "OpCapability VulkanMemoryModel",
-    "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-    "OpMemoryModel Logical Vulkan",
-    "OpEntryPoint Vertex %1 \"shader\"",
-    "%uint = OpTypeInt 32 0",
-    "%v3uint = OpTypeVector %uint 3"};
-
-std::string GetTestString(const char* shuffle) {
-  std::vector<const char*> result = header;
-  result += {"%_ptr_Function_v3uint = OpTypePointer Function %v3uint",
-             "%void = OpTypeVoid",
-             "%6 = OpTypeFunction %void",
-             "%1 = OpFunction %void None %6",
-             "%7 = OpLabel",
-             "%8 = OpVariable %_ptr_Function_v3uint Function",
-             "%9 = OpLoad %v3uint %8",
-             "%10 = OpLoad %v3uint %8"};
-  result += shuffle;
-  result += {"OpReturn", "OpFunctionEnd"};
-  return JoinAllInsts(result);
-}
-
-TEST_F(LegalizeVectorShuffleTest, Changed) {
-  std::string input =
-      GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0xFFFFFFFF");
-  std::string expected =
-      GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0");
-
-  SinglePassRunAndCheck<LegalizeVectorShufflePass>(input, expected,
-                                                   /* skip_nop = */ false);
-}
-
-TEST_F(LegalizeVectorShuffleTest, FunctionUnchanged) {
-  std::string input =
-      GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0");
-  std::string expected =
-      GetTestString("%11 = OpVectorShuffle %v3uint %9 %10 2 1 0");
-
-  SinglePassRunAndCheck<LegalizeVectorShufflePass>(input, expected,
-                                                   /* skip_nop = */ false);
-}
-
-}  // namespace
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/optimizer_test.cpp b/third_party/SPIRV-Tools/test/opt/optimizer_test.cpp
index 945aa78..a51638a 100644
--- a/third_party/SPIRV-Tools/test/opt/optimizer_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/optimizer_test.cpp
@@ -221,498 +221,6 @@
   EXPECT_EQ(msg_level, SPV_MSG_ERROR);
 }
 
-TEST(Optimizer, VulkanToWebGPUSetsCorrectPasses) {
-  Optimizer opt(SPV_ENV_VULKAN_1_1);
-  opt.RegisterVulkanToWebGPUPasses();
-  std::vector<const char*> pass_names = opt.GetPassNames();
-
-  std::vector<std::string> registered_passes;
-  for (auto name = pass_names.begin(); name != pass_names.end(); ++name)
-    registered_passes.push_back(*name);
-
-  std::vector<std::string> expected_passes = {"eliminate-dead-branches",
-                                              "eliminate-dead-code-aggressive",
-                                              "eliminate-dead-const",
-                                              "flatten-decorations",
-                                              "strip-atomic-counter-memory",
-                                              "generate-webgpu-initializers",
-                                              "legalize-vector-shuffle",
-                                              "split-invalid-unreachable",
-                                              "compact-ids"};
-  std::sort(registered_passes.begin(), registered_passes.end());
-  std::sort(expected_passes.begin(), expected_passes.end());
-
-  ASSERT_EQ(registered_passes.size(), expected_passes.size());
-  for (size_t i = 0; i < registered_passes.size(); i++)
-    EXPECT_EQ(registered_passes[i], expected_passes[i]);
-}
-
-struct VulkanToWebGPUPassCase {
-  // Input SPIR-V
-  std::string input;
-  // Expected result SPIR-V
-  std::string expected;
-  // Specific pass under test, used for logging messages.
-  std::string pass;
-};
-
-using VulkanToWebGPUPassTest =
-    PassTest<::testing::TestWithParam<VulkanToWebGPUPassCase>>;
-
-TEST_P(VulkanToWebGPUPassTest, Ran) {
-  std::vector<uint32_t> binary;
-  {
-    SpirvTools tools(SPV_ENV_VULKAN_1_1);
-    tools.Assemble(GetParam().input, &binary);
-  }
-
-  Optimizer opt(SPV_ENV_VULKAN_1_1);
-  opt.RegisterVulkanToWebGPUPasses();
-
-  std::vector<uint32_t> optimized;
-  class ValidatorOptions validator_options;
-  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
-                      validator_options, true))
-      << GetParam().input << "\n";
-  std::string disassembly;
-  {
-    SpirvTools tools(SPV_ENV_WEBGPU_0);
-    tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
-  }
-
-  EXPECT_EQ(GetParam().expected, disassembly)
-      << "Was expecting pass '" << GetParam().pass << "' to have been run.\n";
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    Optimizer, VulkanToWebGPUPassTest,
-    ::testing::ValuesIn(std::vector<VulkanToWebGPUPassCase>{
-        // FlattenDecorations
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Fragment %main \"main\" %hue %saturation %value\n"
-         "OpExecutionMode %main OriginUpperLeft\n"
-         "OpDecorate %group Flat\n"
-         "OpDecorate %group NoPerspective\n"
-         "%group = OpDecorationGroup\n"
-         "%void = OpTypeVoid\n"
-         "%void_fn = OpTypeFunction %void\n"
-         "%float = OpTypeFloat 32\n"
-         "%_ptr_Input_float = OpTypePointer Input %float\n"
-         "%hue = OpVariable %_ptr_Input_float Input\n"
-         "%saturation = OpVariable %_ptr_Input_float Input\n"
-         "%value = OpVariable %_ptr_Input_float Input\n"
-         "%main = OpFunction %void None %void_fn\n"
-         "%entry = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Fragment %1 \"main\" %2 %3 %4\n"
-         "OpExecutionMode %1 OriginUpperLeft\n"
-         "%void = OpTypeVoid\n"
-         "%6 = OpTypeFunction %void\n"
-         "%float = OpTypeFloat 32\n"
-         "%_ptr_Input_float = OpTypePointer Input %float\n"
-         "%2 = OpVariable %_ptr_Input_float Input\n"
-         "%3 = OpVariable %_ptr_Input_float Input\n"
-         "%4 = OpVariable %_ptr_Input_float Input\n"
-         "%1 = OpFunction %void None %6\n"
-         "%9 = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "flatten-decorations"},
-        // Eliminate Dead Constants
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %func \"shader\"\n"
-         "%u32 = OpTypeInt 32 0\n"
-         "%u32_ptr = OpTypePointer Workgroup %u32\n"
-         "%u32_var = OpVariable %u32_ptr Workgroup\n"
-         "%u32_1 = OpConstant %u32 1\n"
-         "%cross_device = OpConstant %u32 0\n"
-         "%relaxed = OpConstant %u32 0\n"
-         "%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n"
-         "%void = OpTypeVoid\n"
-         "%void_f = OpTypeFunction %void\n"
-         "%func = OpFunction %void None %void_f\n"
-         "%label = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n"
-         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n"
-         "%void = OpTypeVoid\n"
-         "%6 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %6\n"
-         "%7 = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         "eliminate-dead-const"},
-        // Strip Atomic Counter Memory
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %func \"shader\"\n"
-         "%u32 = OpTypeInt 32 0\n"
-         "%u32_ptr = OpTypePointer Workgroup %u32\n"
-         "%u32_var = OpVariable %u32_ptr Workgroup\n"
-         "%u32_0 = OpConstant %u32 0\n"
-         "%u32_1 = OpConstant %u32 1\n"
-         "%cross_device = OpConstant %u32 0\n"
-         "%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n"
-         "%void = OpTypeVoid\n"
-         "%void_f = OpTypeFunction %void\n"
-         "%func = OpFunction %void None %void_f\n"
-         "%label = OpLabel\n"
-         "        OpAtomicStore %u32_var %cross_device "
-         "%acquire_release_atomic_counter_workgroup %u32_1\n"
-         "%val1 = OpAtomicIIncrement %u32 %u32_var %cross_device "
-         "%acquire_release_atomic_counter_workgroup\n"
-         "%val2 = OpAtomicCompareExchange %u32 %u32_var %cross_device "
-         "%acquire_release_atomic_counter_workgroup "
-         "%acquire_release_atomic_counter_workgroup %u32_0 %u32_0\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n"
-         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n"
-         "%uint_0 = OpConstant %uint 0\n"
-         "%uint_1 = OpConstant %uint 1\n"
-         "%uint_0_0 = OpConstant %uint 0\n"
-         "%void = OpTypeVoid\n"
-         "%9 = OpTypeFunction %void\n"
-         "%uint_264 = OpConstant %uint 264\n"
-         "%1 = OpFunction %void None %9\n"
-         "%11 = OpLabel\n"
-         "OpAtomicStore %4 %uint_0_0 %uint_264 %uint_1\n"
-         "%12 = OpAtomicIIncrement %uint %4 %uint_0_0 %uint_264\n"
-         "%13 = OpAtomicCompareExchange %uint %4 %uint_0_0 %uint_264 %uint_264 "
-         "%uint_0 %uint_0\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "strip-atomic-counter-memory"},
-        // Generate WebGPU Initializers
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %func \"shader\"\n"
-         "%u32 = OpTypeInt 32 0\n"
-         "%u32_ptr = OpTypePointer Private %u32\n"
-         "%u32_var = OpVariable %u32_ptr Private\n"
-         "%u32_0 = OpConstant %u32 0\n"
-         "%void = OpTypeVoid\n"
-         "%void_f = OpTypeFunction %void\n"
-         "%func = OpFunction %void None %void_f\n"
-         "%label = OpLabel\n"
-         "OpStore %u32_var %u32_0\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%_ptr_Private_uint = OpTypePointer Private %uint\n"
-         "%4 = OpConstantNull %uint\n"
-         "%5 = OpVariable %_ptr_Private_uint Private %4\n"
-         "%uint_0 = OpConstant %uint 0\n"
-         "%void = OpTypeVoid\n"
-         "%8 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %8\n"
-         "%9 = OpLabel\n"
-         "OpStore %5 %uint_0\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "generate-webgpu-initializers"},
-        // Legalize Vector Shuffle
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%v3uint = OpTypeVector %uint 3\n"
-         "%_ptr_Function_v3uint = OpTypePointer Function %v3uint\n"
-         "%void = OpTypeVoid\n"
-         "%6 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %6\n"
-         "%7 = OpLabel\n"
-         "%8 = OpVariable %_ptr_Function_v3uint Function\n"
-         "%9 = OpLoad %v3uint %8\n"
-         "%10 = OpLoad %v3uint %8\n"
-         "%11 = OpVectorShuffle %v3uint %9 %10 2 1 0xFFFFFFFF\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%v3uint = OpTypeVector %uint 3\n"
-         "%_ptr_Function_v3uint = OpTypePointer Function %v3uint\n"
-         "%void = OpTypeVoid\n"
-         "%6 = OpTypeFunction %void\n"
-         "%7 = OpConstantNull %v3uint\n"
-         "%1 = OpFunction %void None %6\n"
-         "%8 = OpLabel\n"
-         "%9 = OpVariable %_ptr_Function_v3uint Function %7\n"
-         "%10 = OpLoad %v3uint %9\n"
-         "%11 = OpLoad %v3uint %9\n"
-         "%12 = OpVectorShuffle %v3uint %10 %11 2 1 0\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "legalize-vector-shuffle"},
-        // Split Invalid Unreachable
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%uint_1 = OpConstant %uint 1\n"
-         "%uint_2 = OpConstant %uint 2\n"
-         "%void = OpTypeVoid\n"
-         "%bool = OpTypeBool\n"
-         "%7 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %7\n"
-         "%8 = OpLabel\n"
-         "OpBranch %9\n"
-         "%9 = OpLabel\n"
-         "OpLoopMerge %10 %11 None\n"
-         "OpBranch %12\n"
-         "%12 = OpLabel\n"
-         "%13 = OpSLessThan %bool %uint_1 %uint_2\n"
-         "OpSelectionMerge %11 None\n"
-         "OpBranchConditional %13 %14 %15\n"
-         "%14 = OpLabel\n"
-         "OpReturn\n"
-         "%15 = OpLabel\n"
-         "OpReturn\n"
-         "%10 = OpLabel\n"
-         "OpUnreachable\n"
-         "%11 = OpLabel\n"
-         "OpBranch %9\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%uint_1 = OpConstant %uint 1\n"
-         "%uint_2 = OpConstant %uint 2\n"
-         "%void = OpTypeVoid\n"
-         "%bool = OpTypeBool\n"
-         "%7 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %7\n"
-         "%8 = OpLabel\n"
-         "OpBranch %9\n"
-         "%9 = OpLabel\n"
-         "OpLoopMerge %10 %11 None\n"
-         "OpBranch %12\n"
-         "%12 = OpLabel\n"
-         "%13 = OpSLessThan %bool %uint_1 %uint_2\n"
-         "OpSelectionMerge %14 None\n"
-         "OpBranchConditional %13 %15 %16\n"
-         "%15 = OpLabel\n"
-         "OpReturn\n"
-         "%16 = OpLabel\n"
-         "OpReturn\n"
-         "%10 = OpLabel\n"
-         "OpUnreachable\n"
-         "%14 = OpLabel\n"
-         "OpUnreachable\n"
-         "%11 = OpLabel\n"
-         "OpBranch %9\n"
-         "OpFunctionEnd\n",
-         // pass
-         "split-invalid-unreachable"},
-        // Compact IDs
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1000 \"shader\"\n"
-         "%10 = OpTypeVoid\n"
-         "%100 = OpTypeFunction %10\n"
-         "%1000 = OpFunction %10 None %100\n"
-         "%10000 = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%void = OpTypeVoid\n"
-         "%3 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %3\n"
-         "%4 = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "compact-ids"}}));
-
-TEST(Optimizer, WebGPUToVulkanSetsCorrectPasses) {
-  Optimizer opt(SPV_ENV_WEBGPU_0);
-  opt.RegisterWebGPUToVulkanPasses();
-  std::vector<const char*> pass_names = opt.GetPassNames();
-
-  std::vector<std::string> registered_passes;
-  for (auto name = pass_names.begin(); name != pass_names.end(); ++name)
-    registered_passes.push_back(*name);
-
-  std::vector<std::string> expected_passes = {"decompose-initialized-variables",
-                                              "compact-ids"};
-  std::sort(registered_passes.begin(), registered_passes.end());
-  std::sort(expected_passes.begin(), expected_passes.end());
-
-  ASSERT_EQ(registered_passes.size(), expected_passes.size());
-  for (size_t i = 0; i < registered_passes.size(); i++)
-    EXPECT_EQ(registered_passes[i], expected_passes[i]);
-}
-
-struct WebGPUToVulkanPassCase {
-  // Input SPIR-V
-  std::string input;
-  // Expected result SPIR-V
-  std::string expected;
-  // Specific pass under test, used for logging messages.
-  std::string pass;
-};
-
-using WebGPUToVulkanPassTest =
-    PassTest<::testing::TestWithParam<WebGPUToVulkanPassCase>>;
-
-TEST_P(WebGPUToVulkanPassTest, Ran) {
-  std::vector<uint32_t> binary;
-  {
-    SpirvTools tools(SPV_ENV_WEBGPU_0);
-    tools.Assemble(GetParam().input, &binary);
-  }
-
-  Optimizer opt(SPV_ENV_WEBGPU_0);
-  opt.RegisterWebGPUToVulkanPasses();
-
-  std::vector<uint32_t> optimized;
-  class ValidatorOptions validator_options;
-  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
-                      validator_options, true));
-  std::string disassembly;
-  {
-    SpirvTools tools(SPV_ENV_VULKAN_1_1);
-    tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
-  }
-
-  EXPECT_EQ(GetParam().expected, disassembly)
-      << "Was expecting pass '" << GetParam().pass << "' to have been run.\n";
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    Optimizer, WebGPUToVulkanPassTest,
-    ::testing::ValuesIn(std::vector<WebGPUToVulkanPassCase>{
-        // Decompose Initialized Variables
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%_ptr_Function_uint = OpTypePointer Function %uint\n"
-         "%4 = OpConstantNull %uint\n"
-         "%void = OpTypeVoid\n"
-         "%6 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %6\n"
-         "%7 = OpLabel\n"
-         "%8 = OpVariable %_ptr_Function_uint Function %4\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%uint = OpTypeInt 32 0\n"
-         "%_ptr_Function_uint = OpTypePointer Function %uint\n"
-         "%4 = OpConstantNull %uint\n"
-         "%void = OpTypeVoid\n"
-         "%6 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %6\n"
-         "%7 = OpLabel\n"
-         "%8 = OpVariable %_ptr_Function_uint Function\n"
-         "OpStore %8 %4\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "decompose-initialized-variables"},
-        // Compact IDs
-        {// input
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1000 \"shader\"\n"
-         "%10 = OpTypeVoid\n"
-         "%100 = OpTypeFunction %10\n"
-         "%1000 = OpFunction %10 None %100\n"
-         "%10000 = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // expected
-         "OpCapability Shader\n"
-         "OpCapability VulkanMemoryModel\n"
-         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-         "OpMemoryModel Logical Vulkan\n"
-         "OpEntryPoint Vertex %1 \"shader\"\n"
-         "%void = OpTypeVoid\n"
-         "%3 = OpTypeFunction %void\n"
-         "%1 = OpFunction %void None %3\n"
-         "%4 = OpLabel\n"
-         "OpReturn\n"
-         "OpFunctionEnd\n",
-         // pass
-         "compact-ids"}}));
 
 TEST(Optimizer, RemoveNop) {
   // Test that OpNops are removed even if no optimizations are run.
@@ -754,7 +262,7 @@
       << before << "\n";
   std::string disassembly;
   {
-    SpirvTools tools(SPV_ENV_WEBGPU_0);
+    SpirvTools tools(SPV_ENV_VULKAN_1_1);
     tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
   }
 
@@ -762,6 +270,124 @@
       << "Was expecting the OpNop to have been removed.";
 }
 
+TEST(Optimizer, AvoidIntegrityCheckForExtraLineInfo) {
+  // Test that it avoids the integrity check when no optimizations are run and
+  // OpLines are propagated.
+  const std::string before = R"(OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%1 = OpString "Test"
+%void = OpTypeVoid
+%3 = OpTypeFunction %void
+%uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+%6 = OpFunction %void None %3
+%7 = OpLabel
+OpLine %1 10 0
+%8 = OpVariable %_ptr_Function_uint Function
+OpLine %1 10 0
+%9 = OpVariable %_ptr_Function_uint Function
+OpLine %1 20 0
+OpReturn
+OpFunctionEnd
+)";
+
+  const std::string after = R"(OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%1 = OpString "Test"
+%void = OpTypeVoid
+%3 = OpTypeFunction %void
+%uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+%6 = OpFunction %void None %3
+%7 = OpLabel
+OpLine %1 10 0
+%8 = OpVariable %_ptr_Function_uint Function
+%9 = OpVariable %_ptr_Function_uint Function
+OpLine %1 20 0
+OpReturn
+OpFunctionEnd
+)";
+
+  std::vector<uint32_t> binary;
+  SpirvTools tools(SPV_ENV_VULKAN_1_1);
+  tools.Assemble(before, &binary);
+
+  Optimizer opt(SPV_ENV_VULKAN_1_1);
+
+  std::vector<uint32_t> optimized;
+  class ValidatorOptions validator_options;
+  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
+                      validator_options, true))
+      << before << "\n";
+
+  std::string disassembly;
+  tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
+
+  EXPECT_EQ(after, disassembly)
+      << "Was expecting the OpLine to have been propagated.";
+}
+
+TEST(Optimizer, AvoidIntegrityCheckForDebugScope) {
+  // Test that it avoids the integrity check when the code contains DebugScope.
+  const std::string before = R"(OpCapability Shader
+%1 = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+%3 = OpString "simple_vs.hlsl"
+OpSource HLSL 600 %3
+OpName %main "main"
+%void = OpTypeVoid
+%5 = OpTypeFunction %void
+%6 = OpExtInst %void %1 DebugSource %3
+%7 = OpExtInst %void %1 DebugCompilationUnit 2 4 %6 HLSL
+%main = OpFunction %void None %5
+%14 = OpLabel
+%26 = OpExtInst %void %1 DebugScope %7
+OpReturn
+%27 = OpExtInst %void %1 DebugNoScope
+OpFunctionEnd
+)";
+
+  const std::string after = R"(OpCapability Shader
+%1 = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+%3 = OpString "simple_vs.hlsl"
+OpSource HLSL 600 %3
+OpName %main "main"
+%void = OpTypeVoid
+%5 = OpTypeFunction %void
+%6 = OpExtInst %void %1 DebugSource %3
+%7 = OpExtInst %void %1 DebugCompilationUnit 2 4 %6 HLSL
+%main = OpFunction %void None %5
+%8 = OpLabel
+%11 = OpExtInst %void %1 DebugScope %7
+OpReturn
+%12 = OpExtInst %void %1 DebugNoScope
+OpFunctionEnd
+)";
+
+  std::vector<uint32_t> binary;
+  SpirvTools tools(SPV_ENV_VULKAN_1_1);
+  tools.Assemble(before, &binary);
+
+  Optimizer opt(SPV_ENV_VULKAN_1_1);
+
+  std::vector<uint32_t> optimized;
+  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized))
+      << before << "\n";
+
+  std::string disassembly;
+  tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
+
+  EXPECT_EQ(after, disassembly)
+      << "Was expecting the result id of DebugScope to have been changed.";
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/split_invalid_unreachable_test.cpp b/third_party/SPIRV-Tools/test/opt/split_invalid_unreachable_test.cpp
deleted file mode 100644
index 520af01..0000000
--- a/third_party/SPIRV-Tools/test/opt/split_invalid_unreachable_test.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2019 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 <vector>
-
-#include "test/opt/pass_fixture.h"
-#include "test/opt/pass_utils.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-using SplitInvalidUnreachableTest = PassTest<::testing::Test>;
-
-std::string spirv_header = R"(OpCapability Shader
-OpCapability VulkanMemoryModel
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical Vulkan
-OpEntryPoint Vertex %1 "shader"
-%uint = OpTypeInt 32 0
-%uint_1 = OpConstant %uint 1
-%uint_2 = OpConstant %uint 2
-%void = OpTypeVoid
-%bool = OpTypeBool
-%7 = OpTypeFunction %void
-)";
-
-std::string function_head = R"(%1 = OpFunction %void None %7
-%8 = OpLabel
-OpBranch %9
-)";
-
-std::string function_tail = "OpFunctionEnd\n";
-
-std::string GetLoopMergeBlock(std::string block_id, std::string merge_id,
-                              std::string continue_id, std::string body_id) {
-  std::string result;
-  result += block_id + " = OpLabel\n";
-  result += "OpLoopMerge " + merge_id + " " + continue_id + " None\n";
-  result += "OpBranch " + body_id + "\n";
-  return result;
-}
-
-std::string GetSelectionMergeBlock(std::string block_id,
-                                   std::string condition_id,
-                                   std::string merge_id, std::string true_id,
-                                   std::string false_id) {
-  std::string result;
-  result += block_id + " = OpLabel\n";
-  result += condition_id + " = OpSLessThan %bool %uint_1 %uint_2\n";
-  result += "OpSelectionMerge " + merge_id + " None\n";
-  result += "OpBranchConditional " + condition_id + " " + true_id + " " +
-            false_id + "\n";
-
-  return result;
-}
-
-std::string GetReturnBlock(std::string block_id) {
-  std::string result;
-  result += block_id + " = OpLabel\n";
-  result += "OpReturn\n";
-  return result;
-}
-
-std::string GetUnreachableBlock(std::string block_id) {
-  std::string result;
-  result += block_id + " = OpLabel\n";
-  result += "OpUnreachable\n";
-  return result;
-}
-
-std::string GetBranchBlock(std::string block_id, std::string target_id) {
-  std::string result;
-  result += block_id + " = OpLabel\n";
-  result += "OpBranch " + target_id + "\n";
-  return result;
-}
-
-TEST_F(SplitInvalidUnreachableTest, NoInvalidBlocks) {
-  std::string input = spirv_header + function_head;
-  input += GetLoopMergeBlock("%9", "%10", "%11", "%12");
-  input += GetSelectionMergeBlock("%12", "%13", "%14", "%15", "%16");
-  input += GetReturnBlock("%15");
-  input += GetReturnBlock("%16");
-  input += GetUnreachableBlock("%10");
-  input += GetBranchBlock("%11", "%9");
-  input += GetUnreachableBlock("%14");
-  input += function_tail;
-
-  SinglePassRunAndCheck<SplitInvalidUnreachablePass>(input, input,
-                                                     /* skip_nop = */ false);
-}
-
-TEST_F(SplitInvalidUnreachableTest, SelectionInLoop) {
-  std::string input = spirv_header + function_head;
-  input += GetLoopMergeBlock("%9", "%10", "%11", "%12");
-  input += GetSelectionMergeBlock("%12", "%13", "%11", "%15", "%16");
-  input += GetReturnBlock("%15");
-  input += GetReturnBlock("%16");
-  input += GetUnreachableBlock("%10");
-  input += GetBranchBlock("%11", "%9");
-  input += function_tail;
-
-  std::string expected = spirv_header + function_head;
-  expected += GetLoopMergeBlock("%9", "%10", "%11", "%12");
-  expected += GetSelectionMergeBlock("%12", "%13", "%16", "%14", "%15");
-  expected += GetReturnBlock("%14");
-  expected += GetReturnBlock("%15");
-  expected += GetUnreachableBlock("%10");
-  expected += GetUnreachableBlock("%16");
-  expected += GetBranchBlock("%11", "%9");
-  expected += function_tail;
-
-  SinglePassRunAndCheck<SplitInvalidUnreachablePass>(input, expected,
-                                                     /* skip_nop = */ false);
-}
-
-TEST_F(SplitInvalidUnreachableTest, LoopInSelection) {
-  std::string input = spirv_header + function_head;
-  input += GetSelectionMergeBlock("%9", "%10", "%11", "%12", "%13");
-  input += GetLoopMergeBlock("%12", "%14", "%11", "%15");
-  input += GetReturnBlock("%13");
-  input += GetUnreachableBlock("%14");
-  input += GetBranchBlock("%11", "%12");
-  input += GetReturnBlock("%15");
-  input += function_tail;
-
-  std::string expected = spirv_header + function_head;
-  expected += GetSelectionMergeBlock("%9", "%10", "%16", "%12", "%13");
-  expected += GetLoopMergeBlock("%12", "%14", "%11", "%15");
-  expected += GetReturnBlock("%13");
-  expected += GetUnreachableBlock("%14");
-  expected += GetUnreachableBlock("%16");
-  expected += GetBranchBlock("%11", "%12");
-  expected += GetReturnBlock("%15");
-  expected += function_tail;
-
-  SinglePassRunAndCheck<SplitInvalidUnreachablePass>(input, expected,
-                                                     /* skip_nop = */ false);
-}
-
-}  // namespace
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/strip_atomic_counter_memory_test.cpp b/third_party/SPIRV-Tools/test/opt/strip_atomic_counter_memory_test.cpp
deleted file mode 100644
index 90daa59..0000000
--- a/third_party/SPIRV-Tools/test/opt/strip_atomic_counter_memory_test.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-// Copyright (c) 2019 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 <vector>
-
-#include "test/opt/pass_fixture.h"
-#include "test/opt/pass_utils.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-typedef std::tuple<std::string, std::string> StripAtomicCounterMemoryParam;
-
-using MemorySemanticsModified =
-    PassTest<::testing::TestWithParam<StripAtomicCounterMemoryParam>>;
-using NonMemorySemanticsUnmodifiedTest = PassTest<::testing::Test>;
-
-void operator+=(std::vector<const char*>& lhs, const char* rhs) {
-  lhs.push_back(rhs);
-}
-
-std::string GetConstDecl(std::string val) {
-  std::string decl;
-  decl += "%uint_" + val + " = OpConstant %uint " + val;
-  return decl;
-}
-
-std::string GetUnchangedString(std::string(generate_inst)(std::string),
-                               std::string val) {
-  std::string decl = GetConstDecl(val);
-  std::string inst = generate_inst(val);
-
-  std::vector<const char*> result = {
-      // clang-format off
-              "OpCapability Shader",
-              "OpCapability VulkanMemoryModel",
-              "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-              "OpMemoryModel Logical Vulkan",
-              "OpEntryPoint Vertex %1 \"shader\"",
-      "%uint = OpTypeInt 32 0",
-"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint",
-         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup",
-    "%uint_0 = OpConstant %uint 0",
-    "%uint_1 = OpConstant %uint 1",
-      "%void = OpTypeVoid",
-         "%8 = OpTypeFunction %void",
-               decl.c_str(),
-         "%1 = OpFunction %void None %8",
-        "%10 = OpLabel",
-               inst.c_str(),
-              "OpReturn",
-              "OpFunctionEnd"
-      // clang-format on
-  };
-  return JoinAllInsts(result);
-}
-
-std::string GetChangedString(std::string(generate_inst)(std::string),
-                             std::string orig, std::string changed) {
-  std::string orig_decl = GetConstDecl(orig);
-  std::string changed_decl = GetConstDecl(changed);
-  std::string inst = generate_inst(changed);
-
-  std::vector<const char*> result = {
-      // clang-format off
-              "OpCapability Shader",
-              "OpCapability VulkanMemoryModel",
-              "OpExtension \"SPV_KHR_vulkan_memory_model\"",
-              "OpMemoryModel Logical Vulkan",
-              "OpEntryPoint Vertex %1 \"shader\"",
-      "%uint = OpTypeInt 32 0",
-"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint",
-         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup",
-    "%uint_0 = OpConstant %uint 0",
-    "%uint_1 = OpConstant %uint 1",
-      "%void = OpTypeVoid",
-         "%8 = OpTypeFunction %void",
-               orig_decl.c_str() };
-  // clang-format on
-  if (changed != "0") result += changed_decl.c_str();
-  result += "%1 = OpFunction %void None %8";
-  result += "%10 = OpLabel";
-  result += inst.c_str();
-  result += "OpReturn";
-  result += "OpFunctionEnd";
-  return JoinAllInsts(result);
-}
-
-std::tuple<std::string, std::string> GetInputAndExpected(
-    std::string(generate_inst)(std::string),
-    StripAtomicCounterMemoryParam param) {
-  std::string orig = std::get<0>(param);
-  std::string changed = std::get<1>(param);
-  std::string input = GetUnchangedString(generate_inst, orig);
-  std::string expected = orig == changed
-                             ? GetUnchangedString(generate_inst, changed)
-                             : GetChangedString(generate_inst, orig, changed);
-  return std::make_tuple(input, expected);
-}
-
-std::string GetOpControlBarrierInst(std::string val) {
-  return "OpControlBarrier %uint_1 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpControlBarrier) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpControlBarrierInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpMemoryBarrierInst(std::string val) {
-  return "OpMemoryBarrier %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpMemoryBarrier) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpMemoryBarrierInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicLoadInst(std::string val) {
-  return "%11 = OpAtomicLoad %uint %4 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicLoad) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicLoadInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicStoreInst(std::string val) {
-  return "OpAtomicStore %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicStore) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicStoreInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicExchangeInst(std::string val) {
-  return "%11 = OpAtomicExchange %uint %4 %uint_1 %uint_" + val + " %uint_0";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicExchange) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicExchangeInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicCompareExchangeInst(std::string val) {
-  return "%11 = OpAtomicCompareExchange %uint %4 %uint_1 %uint_" + val +
-         " %uint_" + val + " %uint_0 %uint_0";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicCompareExchange) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicCompareExchangeInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicCompareExchangeWeakInst(std::string val) {
-  return "%11 = OpAtomicCompareExchangeWeak %uint %4 %uint_1 %uint_" + val +
-         " %uint_" + val + " %uint_0 %uint_0";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicCompareExchangeWeak) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicCompareExchangeWeakInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicIIncrementInst(std::string val) {
-  return "%11 = OpAtomicIIncrement %uint %4 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicIIncrement) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicIIncrementInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicIDecrementInst(std::string val) {
-  return "%11 = OpAtomicIDecrement %uint %4 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicIDecrement) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicIDecrementInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicIAddInst(std::string val) {
-  return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicIAdd) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicIAddInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicISubInst(std::string val) {
-  return "%11 = OpAtomicISub %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicISub) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicISubInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicSMinInst(std::string val) {
-  return "%11 = OpAtomicSMin %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicSMin) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicSMinInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicUMinInst(std::string val) {
-  return "%11 = OpAtomicUMin %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicUMin) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicUMinInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicSMaxInst(std::string val) {
-  return "%11 = OpAtomicSMax %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicSMax) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicSMaxInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicUMaxInst(std::string val) {
-  return "%11 = OpAtomicUMax %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicUMax) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicUMaxInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicAndInst(std::string val) {
-  return "%11 = OpAtomicAnd %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicAnd) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicAndInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicOrInst(std::string val) {
-  return "%11 = OpAtomicOr %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicOr) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicOrInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicXorInst(std::string val) {
-  return "%11 = OpAtomicXor %uint %4 %uint_1 %uint_" + val + " %uint_1";
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicXor) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicXorInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicFlagTestAndSetInst(std::string val) {
-  return "%11 = OpAtomicFlagTestAndSet %uint %4 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicFlagTestAndSet) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicFlagTestAndSetInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpAtomicFlagClearInst(std::string val) {
-  return "OpAtomicFlagClear %4 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpAtomicFlagClear) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpAtomicFlagClearInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetOpMemoryNamedBarrierInst(std::string val) {
-  return "OpMemoryNamedBarrier %4 %uint_1 %uint_" + val;
-}
-
-TEST_P(MemorySemanticsModified, OpMemoryNamedBarrier) {
-  std::string input, expected;
-  std::tie(input, expected) =
-      GetInputAndExpected(GetOpMemoryNamedBarrierInst, GetParam());
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-// clang-format off
-INSTANTIATE_TEST_SUITE_P(
-    StripAtomicCounterMemoryTest, MemorySemanticsModified,
-    ::testing::ValuesIn(std::vector<StripAtomicCounterMemoryParam>({
-       std::make_tuple("1024", "0"),
-       std::make_tuple("5", "5"),
-       std::make_tuple("1288", "264"),
-       std::make_tuple("264", "264")
-    })));
-// clang-format on
-
-std::string GetNoMemorySemanticsPresentInst(std::string val) {
-  return "%11 = OpVariable %_ptr_Workgroup_uint Workgroup %uint_" + val;
-}
-
-TEST_F(NonMemorySemanticsUnmodifiedTest, NoMemorySemanticsPresent) {
-  std::string input, expected;
-  StripAtomicCounterMemoryParam param = std::make_tuple("1288", "1288");
-  std::tie(input, expected) =
-      GetInputAndExpected(GetNoMemorySemanticsPresentInst, param);
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-std::string GetMemorySemanticsPresentInst(std::string val) {
-  return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1288";
-}
-
-TEST_F(NonMemorySemanticsUnmodifiedTest, MemorySemanticsPresent) {
-  std::string input, expected;
-  StripAtomicCounterMemoryParam param = std::make_tuple("1288", "264");
-  std::tie(input, expected) =
-      GetInputAndExpected(GetMemorySemanticsPresentInst, param);
-  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
-                                                      /* skip_nop = */ false);
-}
-
-}  // namespace
-}  // namespace opt
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/target_env_test.cpp b/third_party/SPIRV-Tools/test/target_env_test.cpp
index 9c86e2d..4acb8ff 100644
--- a/third_party/SPIRV-Tools/test/target_env_test.cpp
+++ b/third_party/SPIRV-Tools/test/target_env_test.cpp
@@ -95,7 +95,6 @@
         {"opencl2.0embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_0},
         {"opencl2.1embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_1},
         {"opencl2.2embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_2},
-        {"webgpu0", true, SPV_ENV_WEBGPU_0},
         {"opencl2.3", false, SPV_ENV_UNIVERSAL_1_0},
         {"opencl3.0", false, SPV_ENV_UNIVERSAL_1_0},
         {"vulkan1.9", false, SPV_ENV_UNIVERSAL_1_0},
diff --git a/third_party/SPIRV-Tools/test/tools/opt/flags.py b/third_party/SPIRV-Tools/test/tools/opt/flags.py
index f8117d9..c79f680 100644
--- a/third_party/SPIRV-Tools/test/tools/opt/flags.py
+++ b/third_party/SPIRV-Tools/test/tools/opt/flags.py
@@ -73,10 +73,7 @@
       '--remove-duplicates', '--replace-invalid-opcode', '--ssa-rewrite',
       '--scalar-replacement', '--scalar-replacement=42', '--strength-reduction',
       '--strip-debug', '--strip-reflect', '--vector-dce', '--workaround-1209',
-      '--unify-const', '--legalize-vector-shuffle',
-      '--split-invalid-unreachable', '--generate-webgpu-initializers',
-      '--decompose-initialized-variables', '--graphics-robust-access',
-      '--wrap-opkill', '--amd-ext-to-khr'
+      '--unify-const', '--graphics-robust-access', '--wrap-opkill', '--amd-ext-to-khr'
   ]
   expected_passes = [
       'wrap-opkill',
@@ -124,10 +121,6 @@
       'vector-dce',
       'workaround-1209',
       'unify-const',
-      'legalize-vector-shuffle',
-      'split-invalid-unreachable',
-      'generate-webgpu-initializers',
-      'decompose-initialized-variables',
       'graphics-robust-access',
       'wrap-opkill',
       'amd-ext-to-khr'
@@ -362,45 +355,3 @@
 
   spirv_args = ['--loop-peeling-threshold=a10f']
   expected_error_substr = 'must have a positive integer argument'
-
-@inside_spirv_testsuite('SpirvOptFlags')
-class TestWebGPUToVulkanThenVulkanToWebGPUIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr):
-  """Tests Vulkan->WebGPU flag cannot be used after WebGPU->Vulkan flag."""
-
-  spirv_args = ['--webgpu-to-vulkan', '--vulkan-to-webgpu']
-  expected_error_substr = 'Cannot use both'
-
-@inside_spirv_testsuite('SpirvOptFlags')
-class TestVulkanToWebGPUThenWebGPUToVulkanIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr):
-  """Tests WebGPU->Vulkan flag cannot be used after Vulkan->WebGPU flag."""
-
-  spirv_args = ['--vulkan-to-webgpu', '--webgpu-to-vulkan']
-  expected_error_substr = 'Cannot use both'
-
-@inside_spirv_testsuite('SpirvOptFlags')
-class TestTargetEnvThenVulkanToWebGPUIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr):
-  """Tests Vulkan->WebGPU flag cannot be used after target env flag."""
-
-  spirv_args = ['--target-env=opengl4.0', '--vulkan-to-webgpu']
-  expected_error_substr = 'defines the target environment'
-
-@inside_spirv_testsuite('SpirvOptFlags')
-class TestVulkanToWebGPUThenTargetEnvIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr):
-  """Tests target env flag cannot be used after Vulkan->WebGPU flag."""
-
-  spirv_args = ['--vulkan-to-webgpu', '--target-env=opengl4.0']
-  expected_error_substr = 'defines the target environment'
-
-@inside_spirv_testsuite('SpirvOptFlags')
-class TestTargetEnvThenWebGPUToVulkanIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr):
-  """Tests WebGPU->Vulkan flag cannot be used after target env flag."""
-
-  spirv_args = ['--target-env=opengl4.0', '--webgpu-to-vulkan']
-  expected_error_substr = 'defines the target environment'
-
-@inside_spirv_testsuite('SpirvOptFlags')
-class TestWebGPUToVulkanThenTargetEnvIsInvalid(expect.ReturnCodeIsNonZero, expect.ErrorMessageSubstr):
-  """Tests target env flag cannot be used after WebGPU->Vulkan flag."""
-
-  spirv_args = ['--webgpu-to-vulkan', '--target-env=opengl4.0']
-  expected_error_substr = 'defines the target environment'
diff --git a/third_party/SPIRV-Tools/test/unit_spirv.h b/third_party/SPIRV-Tools/test/unit_spirv.h
index 3264662..f0a2958 100644
--- a/third_party/SPIRV-Tools/test/unit_spirv.h
+++ b/third_party/SPIRV-Tools/test/unit_spirv.h
@@ -195,7 +195,7 @@
       SPV_ENV_OPENGL_4_1,    SPV_ENV_OPENGL_4_2,
       SPV_ENV_OPENGL_4_3,    SPV_ENV_OPENGL_4_5,
       SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3,
-      SPV_ENV_VULKAN_1_1,    SPV_ENV_WEBGPU_0,
+      SPV_ENV_VULKAN_1_1,
   };
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/CMakeLists.txt b/third_party/SPIRV-Tools/test/val/CMakeLists.txt
index 153a916..b17d1cb 100644
--- a/third_party/SPIRV-Tools/test/val/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/test/val/CMakeLists.txt
@@ -89,7 +89,6 @@
        val_type_unique_test.cpp
        val_validation_state_test.cpp
        val_version_test.cpp
-       val_webgpu_test.cpp
        ${VAL_TEST_COMMON_SRCS}
   LIBS ${SPIRV_TOOLS_FULL_VISIBILITY}
   PCH_FILE pch_test_val
diff --git a/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp b/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp
index aca0f3c..c7e36f5 100644
--- a/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp
@@ -30,16 +30,16 @@
 
 std::string GenerateShaderCodeImpl(
     const std::string& body, const std::string& capabilities_and_extensions,
-    const std::string& definitions, const std::string& memory_model) {
+    const std::string& definitions, const std::string& memory_model,
+    const std::string& execution) {
   std::ostringstream ss;
   ss << R"(
 OpCapability Shader
 )";
   ss << capabilities_and_extensions;
   ss << "OpMemoryModel Logical " << memory_model << "\n";
+  ss << execution;
   ss << R"(
-OpEntryPoint Fragment %main "main"
-OpExecutionMode %main OriginUpperLeft
 %void = OpTypeVoid
 %func = OpTypeFunction %void
 %bool = OpTypeBool
@@ -96,6 +96,10 @@
     const std::string& body,
     const std::string& capabilities_and_extensions = "",
     const std::string& memory_model = "GLSL450") {
+  const std::string execution = R"(
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+)";
   const std::string defintions = R"(
 %u64 = OpTypeInt 64 0
 %s64 = OpTypeInt 64 1
@@ -110,24 +114,32 @@
 )";
   return GenerateShaderCodeImpl(
       body, "OpCapability Int64\n" + capabilities_and_extensions, defintions,
-      memory_model);
+      memory_model, execution);
 }
 
-std::string GenerateWebGPUShaderCode(
+std::string GenerateShaderComputeCode(
     const std::string& body,
-    const std::string& capabilities_and_extensions = "") {
-  const std::string vulkan_memory_capability = R"(
-OpCapability VulkanMemoryModelDeviceScopeKHR
-OpCapability VulkanMemoryModelKHR
+    const std::string& capabilities_and_extensions = "",
+    const std::string& memory_model = "GLSL450") {
+  const std::string execution = R"(
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 32 1 1
 )";
-  const std::string vulkan_memory_extension = R"(
-OpExtension "SPV_KHR_vulkan_memory_model"
+  const std::string defintions = R"(
+%u64 = OpTypeInt 64 0
+%s64 = OpTypeInt 64 1
+
+%u64_1 = OpConstant %u64 1
+%s64_1 = OpConstant %s64 1
+
+%u64_ptr = OpTypePointer Workgroup %u64
+%s64_ptr = OpTypePointer Workgroup %s64
+%u64_var = OpVariable %u64_ptr Workgroup
+%s64_var = OpVariable %s64_ptr Workgroup
 )";
-  return GenerateShaderCodeImpl(body,
-                                vulkan_memory_capability +
-                                    capabilities_and_extensions +
-                                    vulkan_memory_extension,
-                                "", "VulkanKHR");
+  return GenerateShaderCodeImpl(
+      body, "OpCapability Int64\n" + capabilities_and_extensions, defintions,
+      memory_model, execution);
 }
 
 std::string GenerateKernelCode(
@@ -234,7 +246,7 @@
 %val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
 )";
 
-  CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+  CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
@@ -358,7 +370,7 @@
 %val2 = OpAtomicLoad %f32 %f32_var %workgroup %acquire
 )";
 
-  CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+  CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
@@ -386,8 +398,9 @@
   %val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
   )";
 
-  CompileSuccessfully(GenerateShaderCode(body, "OpCapability Int64Atomics\n"),
-                      SPV_ENV_VULKAN_1_0);
+  CompileSuccessfully(
+      GenerateShaderComputeCode(body, "OpCapability Int64Atomics\n"),
+      SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
@@ -397,7 +410,7 @@
   %val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
   )";
 
-  CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+  CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("64-bit atomics require the Int64Atomics capability"));
@@ -422,6 +435,23 @@
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04686"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("AtomicStore: Vulkan spec only allows storage classes for "
+                "atomic to be: Uniform, Workgroup, Image, StorageBuffer, or "
+                "PhysicalStorageBuffer."));
+}
+
+TEST_F(ValidateAtomics, AtomicStoreFunctionPointerStorageType) {
+  const std::string body = R"(
+%f32_var_function = OpVariable %f32_ptr_function Function
+OpAtomicStore %f32_var_function %device %relaxed %f32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body));
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("AtomicStore: Function storage class forbidden when "
                         "the Shader capability is declared."));
 }
@@ -501,39 +531,6 @@
           "AtomicLoad: 64-bit atomics require the Int64Atomics capability"));
 }
 
-TEST_F(ValidateAtomics, AtomicLoadWebGPUSuccess) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateAtomics, AtomicLoadWebGPUNonQueueFamilyFailure) {
-  const std::string body = R"(
-%val3 = OpAtomicLoad %u32 %u32_var %invocation %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Memory Scope is limited to QueueFamilyKHR for "
-                        "OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, AtomicLoadWebGPUNonRelaxedFailure) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %acquire
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("no bits may be set for Memory Semantics of OpAtomic* "
-                        "instructions"));
-}
-
 TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64Success) {
   const std::string body = R"(
 %val1 = OpAtomicUMin %u64 %u64_var %device %relaxed %u64_1
@@ -710,38 +707,6 @@
                 "Acquire, AcquireRelease and SequentiallyConsistent"));
 }
 
-TEST_F(ValidateAtomics, AtomicStoreWebGPUSuccess) {
-  const std::string body = R"(
-OpAtomicStore %u32_var %queuefamily %relaxed %u32_1
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-TEST_F(ValidateAtomics, AtomicStoreWebGPUNonQueueFamilyFailure) {
-  const std::string body = R"(
-OpAtomicStore %u32_var %workgroup %relaxed %u32_1
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Memory Scope is limited to QueueFamilyKHR for "
-                        "OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, AtomicStoreWebGPUNonRelaxedFailure) {
-  const std::string body = R"(
-OpAtomicStore %u32_var %queuefamily %release %u32_1
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("no bits may be set for Memory Semantics of OpAtomic* "
-                        "instructions"));
-}
-
 TEST_F(ValidateAtomics, AtomicStoreWrongPointerType) {
   const std::string body = R"(
 OpAtomicStore %f32_1 %device %relaxed %f32_1
@@ -2032,75 +1997,6 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateAtomics, WebGPUCrossDeviceMemoryScopeBad) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %cross_device %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("in WebGPU environment Memory Scope is limited to "
-                        "QueueFamilyKHR for OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, WebGPUDeviceMemoryScopeBad) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %device %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("in WebGPU environment Memory Scope is limited to "
-                        "QueueFamilyKHR for OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, WebGPUWorkgroupMemoryScopeBad) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %workgroup %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("in WebGPU environment Memory Scope is limited to "
-                        "QueueFamilyKHR for OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, WebGPUSubgroupMemoryScopeBad) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %subgroup %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("in WebGPU environment Memory Scope is limited to "
-                        "QueueFamilyKHR for OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, WebGPUInvocationMemoryScopeBad) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %invocation %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("in WebGPU environment Memory Scope is limited to "
-                        "QueueFamilyKHR for OpAtomic* operations"));
-}
-
-TEST_F(ValidateAtomics, WebGPUQueueFamilyMemoryScopeGood) {
-  const std::string body = R"(
-%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %relaxed
-)";
-
-  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
 TEST_F(ValidateAtomics, CompareExchangeWeakV13ValV14Good) {
   const std::string body = R"(
 %val1 = OpAtomicCompareExchangeWeak %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
diff --git a/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp b/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp
index 8bd10d4..9a4beba 100644
--- a/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp
@@ -121,40 +121,13 @@
       execution_model, memory_model);
 }
 
-std::string GenerateWebGPUComputeShaderCode(
-    const std::string& body,
-    const std::string& capabilities_and_extensions = "",
-    const std::string& execution_model = "GLCompute") {
-  const std::string vulkan_memory_capability = R"(
-OpCapability VulkanMemoryModelKHR
-)";
-  const std::string vulkan_memory_extension = R"(
-OpExtension "SPV_KHR_vulkan_memory_model"
-)";
-  const std::string memory_model = "OpMemoryModel Logical VulkanKHR";
-  return GenerateShaderCodeImpl(body,
-                                vulkan_memory_capability +
-                                    capabilities_and_extensions +
-                                    vulkan_memory_extension,
-                                "", execution_model, memory_model);
-}
-
-std::string GenerateWebGPUVertexShaderCode(
+std::string GenerateVulkanVertexShaderCode(
     const std::string& body,
     const std::string& capabilities_and_extensions = "",
     const std::string& execution_model = "Vertex") {
-  const std::string vulkan_memory_capability = R"(
-OpCapability VulkanMemoryModelKHR
-)";
-  const std::string vulkan_memory_extension = R"(
-OpExtension "SPV_KHR_vulkan_memory_model"
-)";
-  const std::string memory_model = "OpMemoryModel Logical VulkanKHR";
-  return GenerateShaderCodeImpl(body,
-                                vulkan_memory_capability +
-                                    capabilities_and_extensions +
-                                    vulkan_memory_extension,
-                                "", execution_model, memory_model);
+  const std::string memory_model = "OpMemoryModel Logical GLSL450";
+  return GenerateShaderCodeImpl(body, capabilities_and_extensions, "",
+                                execution_model, memory_model);
 }
 
 std::string GenerateKernelCode(
@@ -271,64 +244,6 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUAcquireReleaseSuccess) {
-  const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateBarriers, OpControlBarrierWebGPURelaxedFailure) {
-  const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, AcquireRelease must be set for Memory "
-                        "Semantics of OpControlBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUMissingWorkgroupFailure) {
-  const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %acquire_release
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, WorkgroupMemory must be set for Memory "
-                        "Semantics"));
-}
-
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUUniformFailure) {
-  const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("For WebGPU only WorkgroupMemory and AcquireRelease may be set "
-                "for Memory Semantics of OpControlBarrier."));
-}
-
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUReleaseFailure) {
-  const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %release_uniform_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, AcquireRelease must be set for Memory "
-                        "Semantics of OpControlBarrier"));
-}
-
 TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv12) {
   const std::string body = R"(
 OpControlBarrier %device %device %none
@@ -435,44 +350,6 @@
                         "is limited to Workgroup and Subgroup"));
 }
 
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUExecutionScopeDeviceBad) {
-  const std::string body = R"(
-OpControlBarrier %device %workgroup %none
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ControlBarrier: in WebGPU environment Execution Scope "
-                        "is limited to Workgroup"));
-}
-
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUExecutionScopeSubgroupBad) {
-  const std::string body = R"(
-OpControlBarrier %subgroup %workgroup %none
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ControlBarrier: in WebGPU environment Execution Scope "
-                        "is limited to Workgroup"));
-}
-
-TEST_F(ValidateBarriers,
-       OpControlBarrierWebGPUExecutionScopeWorkgroupNonComputeBad) {
-  const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUVertexShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "Workgroup Execution Scope is limited to GLCompute execution model"));
-}
-
 TEST_F(ValidateBarriers, OpControlBarrierVulkanMemoryScopeSubgroup) {
   const std::string body = R"(
 OpControlBarrier %subgroup %subgroup %none
@@ -480,6 +357,8 @@
 
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04638"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("ControlBarrier: in Vulkan 1.0 environment Memory Scope is "
@@ -503,20 +382,33 @@
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04638"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("ControlBarrier: in Vulkan environment, Memory Scope "
                         "cannot be CrossDevice"));
 }
 
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUMemoryScopeNonWorkgroup) {
+TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeFailure) {
   const std::string body = R"(
-OpControlBarrier %workgroup %subgroup %acquire_release_workgroup
+OpControlBarrier %workgroup %workgroup %acquire
 )";
 
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ControlBarrier: in WebGPU environment Memory Scope is "
-                        "limited to Workgroup for OpControlBarrier"));
+              AnyVUID("VUID-StandaloneSpirv-None-04639"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Workgroup Memory Scope is limited to MeshNV, TaskNV, "
+                        "and GLCompute execution model"));
+}
+
+TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
+  const std::string body = R"(
+OpControlBarrier %workgroup %workgroup %acquire
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
 }
 
 TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) {
@@ -738,100 +630,6 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUImageMemorySuccess) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %image_memory
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUDeviceFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %subgroup %image_memory
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("in WebGPU environment Memory Scope is limited to "
-                        "Workgroup for OpMemoryBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireReleaseFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ImageMemory must be set for Memory Semantics of "
-                        "OpMemoryBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPURelaxedFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %uniform_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ImageMemory must be set for Memory Semantics of "
-                        "OpMemoryBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %acquire_uniform_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ImageMemory must be set for Memory Semantics of "
-                        "OpMemoryBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUReleaseFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %release_uniform_workgroup
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ImageMemory must be set for Memory Semantics of "
-                        "OpMemoryBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUUniformFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %uniform_image_memory
-)";
-
-  CompileSuccessfully(GenerateWebGPUComputeShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("only ImageMemory may be set for Memory Semantics of "
-                        "OpMemoryBarrier"));
-}
-
-TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUWorkgroupNonComputeFailure) {
-  const std::string body = R"(
-OpMemoryBarrier %workgroup %image_memory
-)";
-
-  CompileSuccessfully(GenerateWebGPUVertexShaderCode(body), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "Workgroup Memory Scope is limited to GLCompute execution model"));
-}
-
 TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) {
   const std::string body = R"(
 OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup
@@ -885,6 +683,8 @@
 
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04638"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("MemoryBarrier: in Vulkan 1.0 environment Memory Scope is "
@@ -920,6 +720,8 @@
 
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04649"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("MemoryBarrier: Vulkan specification requires Memory Semantics "
@@ -935,6 +737,8 @@
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04649"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
                         "Vulkan-supported storage class"));
 }
@@ -947,6 +751,8 @@
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04649"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
                         "Vulkan-supported storage class"));
 }
@@ -1629,6 +1435,8 @@
                       SPV_ENV_VULKAN_1_1);
 
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04640"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
diff --git a/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp b/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp
index 74d5c3a..bbcdbb1 100644
--- a/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp
@@ -54,18 +54,14 @@
 using ::testing::ValuesIn;
 
 using ValidateBuiltIns = spvtest::ValidateBase<bool>;
-using ValidateVulkanSubgroupBuiltIns = spvtest::ValidateBase<
-    std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
+using ValidateVulkanSubgroupBuiltIns =
+    spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
+                                     const char*, const char*, TestResult>>;
 using ValidateVulkanCombineBuiltInExecutionModelDataTypeResult =
     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
                                      const char*, const char*, TestResult>>;
-using ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult =
-    spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
-                                     const char*, TestResult>>;
 using ValidateVulkanCombineBuiltInArrayedVariable = spvtest::ValidateBase<
     std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
-using ValidateWebGPUCombineBuiltInArrayedVariable = spvtest::ValidateBase<
-    std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
 using ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult =
     spvtest::ValidateBase<
         std::tuple<const char*, const char*, const char*, const char*,
@@ -76,22 +72,19 @@
                                      const char*, const char*, const char*,
                                      const char*, const char*, TestResult>>;
 
-bool InitializerRequired(spv_target_env env, const char* const storage_class) {
-  return spvIsWebGPUEnv(env) && (strncmp(storage_class, "Output", 6) == 0 ||
-                                 strncmp(storage_class, "Private", 7) == 0 ||
-                                 strncmp(storage_class, "Function", 8) == 0);
+bool InitializerRequired(const char* const storage_class) {
+  return (strncmp(storage_class, "Output", 6) == 0 ||
+          strncmp(storage_class, "Private", 7) == 0 ||
+          strncmp(storage_class, "Function", 8) == 0);
 }
 
-CodeGenerator GetInMainCodeGenerator(spv_target_env env,
-                                     const char* const built_in,
+CodeGenerator GetInMainCodeGenerator(const char* const built_in,
                                      const char* const execution_model,
                                      const char* const storage_class,
                                      const char* const capabilities,
                                      const char* const extensions,
                                      const char* const data_type) {
-  CodeGenerator generator =
-      spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                          : CodeGenerator::GetDefaultShaderCodeGenerator();
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   if (capabilities) {
     generator.capabilities_ += capabilities;
@@ -107,13 +100,13 @@
   std::ostringstream after_types;
 
   after_types << "%built_in_type = OpTypeStruct " << data_type << "\n";
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << "%built_in_null = OpConstantNull %built_in_type\n";
   }
   after_types << "%built_in_ptr = OpTypePointer " << storage_class
               << " %built_in_type\n";
   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << " %built_in_null";
   }
   after_types << "\n";
@@ -158,44 +151,6 @@
   return generator;
 }
 
-// Allows test parameter test to list all possible VUIDs with a delimiter that
-// is then split here to check if one VUID was in the error message
-MATCHER_P(AnyVUID, vuid_set, "VUID from the set is in error message") {
-  // use space as delimiter because clang-format will properly line break VUID
-  // strings which is important the entire VUID is in a single line for script
-  // to scan
-  std::string delimiter = " ";
-  std::string token;
-  std::string vuids = std::string(vuid_set);
-  size_t position;
-
-  // Catch case were someone accidentally left spaces by trimming string
-  // clang-format off
-  vuids.erase(std::find_if(vuids.rbegin(), vuids.rend(), [](unsigned char c) {
-    return (c != ' ');
-  }).base(), vuids.end());
-  vuids.erase(vuids.begin(), std::find_if(vuids.begin(), vuids.end(), [](unsigned char c) {
-    return (c != ' ');
-  }));
-  // clang-format on
-
-  do {
-    position = vuids.find(delimiter);
-    if (position != std::string::npos) {
-      token = vuids.substr(0, position);
-      vuids.erase(0, position + delimiter.length());
-    } else {
-      token = vuids.substr(0);  // last item
-    }
-
-    // arg contains diagnostic message
-    if (arg.find(token) != std::string::npos) {
-      return true;
-    }
-  } while (position != std::string::npos);
-  return false;
-}
-
 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InMain) {
   const char* const built_in = std::get<0>(GetParam());
   const char* const execution_model = std::get<1>(GetParam());
@@ -204,9 +159,8 @@
   const char* const vuid = std::get<4>(GetParam());
   const TestResult& test_result = std::get<5>(GetParam());
 
-  CodeGenerator generator =
-      GetInMainCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
-                             storage_class, NULL, NULL, data_type);
+  CodeGenerator generator = GetInMainCodeGenerator(
+      built_in, execution_model, storage_class, NULL, NULL, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -222,28 +176,6 @@
   }
 }
 
-TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InMain) {
-  const char* const built_in = std::get<0>(GetParam());
-  const char* const execution_model = std::get<1>(GetParam());
-  const char* const storage_class = std::get<2>(GetParam());
-  const char* const data_type = std::get<3>(GetParam());
-  const TestResult& test_result = std::get<4>(GetParam());
-
-  CodeGenerator generator =
-      GetInMainCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model,
-                             storage_class, NULL, NULL, data_type);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(test_result.validation_result,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  if (test_result.error_str) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
-  }
-  if (test_result.error_str2) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
-  }
-}
-
 TEST_P(
     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
     InMain) {
@@ -256,9 +188,9 @@
   const char* const vuid = std::get<6>(GetParam());
   const TestResult& test_result = std::get<7>(GetParam());
 
-  CodeGenerator generator = GetInMainCodeGenerator(
-      SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class,
-      capabilities, extensions, data_type);
+  CodeGenerator generator =
+      GetInMainCodeGenerator(built_in, execution_model, storage_class,
+                             capabilities, extensions, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -288,7 +220,7 @@
   const TestResult& test_result = std::get<8>(GetParam());
 
   CodeGenerator generator =
-      GetInMainCodeGenerator(env, built_in, execution_model, storage_class,
+      GetInMainCodeGenerator(built_in, execution_model, storage_class,
                              capabilities, extensions, data_type);
 
   CompileSuccessfully(generator.Build(), env);
@@ -304,16 +236,13 @@
   }
 }
 
-CodeGenerator GetInFunctionCodeGenerator(spv_target_env env,
-                                         const char* const built_in,
+CodeGenerator GetInFunctionCodeGenerator(const char* const built_in,
                                          const char* const execution_model,
                                          const char* const storage_class,
                                          const char* const capabilities,
                                          const char* const extensions,
                                          const char* const data_type) {
-  CodeGenerator generator =
-      spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                          : CodeGenerator::GetDefaultShaderCodeGenerator();
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   if (capabilities) {
     generator.capabilities_ += capabilities;
@@ -328,13 +257,13 @@
 
   std::ostringstream after_types;
   after_types << "%built_in_type = OpTypeStruct " << data_type << "\n";
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << "%built_in_null = OpConstantNull %built_in_type\n";
   }
   after_types << "%built_in_ptr = OpTypePointer " << storage_class
               << " %built_in_type\n";
   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << " %built_in_null";
   }
   after_types << "\n";
@@ -383,11 +312,7 @@
 OpFunctionEnd
 )";
 
-  if (spvIsWebGPUEnv(env)) {
-    generator.after_types_ += function_body;
-  } else {
-    generator.add_at_the_end_ = function_body;
-  }
+  generator.add_at_the_end_ = function_body;
 
   generator.entry_points_.push_back(std::move(entry_point));
 
@@ -402,9 +327,8 @@
   const char* const vuid = std::get<4>(GetParam());
   const TestResult& test_result = std::get<5>(GetParam());
 
-  CodeGenerator generator =
-      GetInFunctionCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
-                                 storage_class, NULL, NULL, data_type);
+  CodeGenerator generator = GetInFunctionCodeGenerator(
+      built_in, execution_model, storage_class, NULL, NULL, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -420,28 +344,6 @@
   }
 }
 
-TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InFunction) {
-  const char* const built_in = std::get<0>(GetParam());
-  const char* const execution_model = std::get<1>(GetParam());
-  const char* const storage_class = std::get<2>(GetParam());
-  const char* const data_type = std::get<3>(GetParam());
-  const TestResult& test_result = std::get<4>(GetParam());
-
-  CodeGenerator generator =
-      GetInFunctionCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model,
-                                 storage_class, NULL, NULL, data_type);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(test_result.validation_result,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  if (test_result.error_str) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
-  }
-  if (test_result.error_str2) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
-  }
-}
-
 TEST_P(
     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
     InFunction) {
@@ -454,9 +356,9 @@
   const char* const vuid = std::get<6>(GetParam());
   const TestResult& test_result = std::get<7>(GetParam());
 
-  CodeGenerator generator = GetInFunctionCodeGenerator(
-      SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class,
-      capabilities, extensions, data_type);
+  CodeGenerator generator =
+      GetInFunctionCodeGenerator(built_in, execution_model, storage_class,
+                                 capabilities, extensions, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -472,16 +374,13 @@
   }
 }
 
-CodeGenerator GetVariableCodeGenerator(spv_target_env env,
-                                       const char* const built_in,
+CodeGenerator GetVariableCodeGenerator(const char* const built_in,
                                        const char* const execution_model,
                                        const char* const storage_class,
                                        const char* const capabilities,
                                        const char* const extensions,
                                        const char* const data_type) {
-  CodeGenerator generator =
-      spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                          : CodeGenerator::GetDefaultShaderCodeGenerator();
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   if (capabilities) {
     generator.capabilities_ += capabilities;
@@ -495,13 +394,13 @@
   generator.before_types_ += "\n";
 
   std::ostringstream after_types;
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << "%built_in_null = OpConstantNull " << data_type << "\n";
   }
   after_types << "%built_in_ptr = OpTypePointer " << storage_class << " "
               << data_type << "\n";
   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << " %built_in_null";
   }
   after_types << "\n";
@@ -553,9 +452,8 @@
   const char* const vuid = std::get<4>(GetParam());
   const TestResult& test_result = std::get<5>(GetParam());
 
-  CodeGenerator generator =
-      GetVariableCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
-                               storage_class, NULL, NULL, data_type);
+  CodeGenerator generator = GetVariableCodeGenerator(
+      built_in, execution_model, storage_class, NULL, NULL, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -571,28 +469,6 @@
   }
 }
 
-TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, Variable) {
-  const char* const built_in = std::get<0>(GetParam());
-  const char* const execution_model = std::get<1>(GetParam());
-  const char* const storage_class = std::get<2>(GetParam());
-  const char* const data_type = std::get<3>(GetParam());
-  const TestResult& test_result = std::get<4>(GetParam());
-
-  CodeGenerator generator =
-      GetVariableCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model,
-                               storage_class, NULL, NULL, data_type);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(test_result.validation_result,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  if (test_result.error_str) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
-  }
-  if (test_result.error_str2) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
-  }
-}
-
 TEST_P(
     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
     Variable) {
@@ -605,9 +481,9 @@
   const char* const vuid = std::get<6>(GetParam());
   const TestResult& test_result = std::get<7>(GetParam());
 
-  CodeGenerator generator = GetVariableCodeGenerator(
-      SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class,
-      capabilities, extensions, data_type);
+  CodeGenerator generator =
+      GetVariableCodeGenerator(built_in, execution_model, storage_class,
+                               capabilities, extensions, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -642,10 +518,26 @@
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
+    ClipAndCullDistanceInvalidStorageClass,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
+    Combine(Values("ClipDistance", "CullDistance"),
+            Values("Vertex", "Geometry", "TessellationControl",
+                   "TessellationEvaluation"),
+            Values("Private"), Values("%f32arr2", "%f32arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04190 "
+                   "VUID-CullDistance-CullDistance-04199"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "to be only used for variables with Input or Output storage "
+                "class."))));
+
+INSTANTIATE_TEST_SUITE_P(
     ClipAndCullDistanceFragmentOutput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
-            Values("Output"), Values("%f32arr4"), Values(nullptr),
+            Values("Output"), Values("%f32arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04189 "
+                   "VUID-CullDistance-CullDistance-04198"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
@@ -654,20 +546,22 @@
                 "which is called with execution model Fragment."))));
 
 INSTANTIATE_TEST_SUITE_P(
-    VertexIdAndInstanceIdVertexInput,
+    VertexIdVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("VertexId", "InstanceId"), Values("Vertex"), Values("Input"),
-            Values("%u32"), Values(nullptr),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId to be "
-                "used."))));
+    Combine(
+        Values("VertexId"), Values("Vertex"), Values("Input"), Values("%u32"),
+        Values(nullptr),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "Vulkan spec doesn't allow BuiltIn VertexId to be "
+                          "used."))));
 
 INSTANTIATE_TEST_SUITE_P(
     ClipAndCullDistanceVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Vertex"),
-            Values("Input"), Values("%f32arr4"), Values(nullptr),
+            Values("Input"), Values("%f32arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04188 "
+                   "VUID-CullDistance-CullDistance-04197"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
@@ -726,11 +620,6 @@
             Values("%f32vec4"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragCoordSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec4"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
     FragCoordNotFragment,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
@@ -743,15 +632,6 @@
                           "to be used only with Fragment execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragCoordNotFragment,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("FragCoord"), Values("Vertex", "GLCompute"), Values("Input"),
-        Values("%f32vec4"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "to be used only with Fragment execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Output"),
             Values("%f32vec4"), Values("VUID-FragCoord-FragCoord-04211"),
@@ -761,15 +641,6 @@
                 "uses storage class Output"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragCoordNotInput, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragCoord"), Values("Fragment"), Values("Output"),
-            Values("%f32vec4"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be only used for variables with Input storage class",
-                "uses storage class Output"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragCoordNotFloatVector,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
@@ -780,15 +651,6 @@
                               "is not a float vector"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragCoordNotFloatVector,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32arr4", "%u32vec4"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 4-component 32-bit float vector",
-                              "is not a float vector"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragCoordNotFloatVec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
@@ -798,15 +660,6 @@
                               "has 3 components"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragCoordNotFloatVec4,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec3"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 4-component 32-bit float vector",
-                              "has 3 components"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragCoordNotF32Vec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
@@ -821,11 +674,6 @@
             Values("%f32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragDepthSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
-            Values("%f32"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
     FragDepthNotFragment,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
@@ -838,15 +686,6 @@
                           "to be used only with Fragment execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragDepthNotFragment,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("FragDepth"), Values("Vertex", "GLCompute"), Values("Output"),
-        Values("%f32"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "to be used only with Fragment execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragDepthNotOutput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Input"),
@@ -857,16 +696,6 @@
                 "uses storage class Input"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragDepthNotOutput,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragDepth"), Values("Fragment"), Values("Input"),
-            Values("%f32"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be only used for variables with Output storage class",
-                "uses storage class Input"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragDepthNotFloatScalar,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
@@ -877,15 +706,6 @@
                               "is not a float scalar"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FragDepthNotFloatScalar,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
-            Values("%f32vec4", "%u32"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 32-bit float scalar",
-                              "is not a float scalar"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FragDepthNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
             Values("%f64"), Values("VUID-FragDepth-FragDepth-04215"),
@@ -901,12 +721,6 @@
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    FrontFacingSuccess,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FrontFacing"), Values("Fragment"), Values("Input"),
-            Values("%bool"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
     FrontFacingAndHelperInvocationNotFragment,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
@@ -920,15 +734,6 @@
                           "to be used only with Fragment execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FrontFacingNotFragment,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("FrontFacing"), Values("Vertex", "GLCompute"), Values("Input"),
-        Values("%bool"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "to be used only with Fragment execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FrontFacingAndHelperInvocationNotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
@@ -941,16 +746,6 @@
                 "uses storage class Output"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FrontFacingNotInput,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FrontFacing"), Values("Fragment"), Values("Output"),
-            Values("%bool"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be only used for variables with Input storage class",
-                "uses storage class Output"))));
-
-INSTANTIATE_TEST_SUITE_P(
     FrontFacingAndHelperInvocationNotBool,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
@@ -962,15 +757,6 @@
                               "is not a bool scalar"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    FrontFacingNotBool,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("FrontFacing"), Values("Fragment"), Values("Input"),
-            Values("%f32", "%u32"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a bool scalar",
-                              "is not a bool scalar"))));
-
-INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3Success,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
@@ -979,13 +765,6 @@
             Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    ComputeShaderInputInt32Vec3Success,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
-            Values("GLCompute"), Values("Input"), Values("%u32vec3"),
-            Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3NotGLCompute,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
@@ -1002,15 +781,6 @@
                           "to be used only with GLCompute execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    ComputeShaderInputInt32Vec3NotGLCompute,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
-        Values("Vertex", "Fragment"), Values("Input"), Values("%u32vec3"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "to be used only with GLCompute execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3NotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
@@ -1026,16 +796,6 @@
                 "uses storage class Output"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    ComputeShaderInputInt32Vec3NotInput,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
-            Values("GLCompute"), Values("Output"), Values("%u32vec3"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be only used for variables with Input storage class",
-                "uses storage class Output"))));
-
-INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3NotIntVector,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
@@ -1051,16 +811,6 @@
                               "is not an int vector"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    ComputeShaderInputInt32Vec3NotIntVector,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
-            Values("GLCompute"), Values("Input"),
-            Values("%u32arr3", "%f32vec3"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 3-component 32-bit int vector",
-                              "is not an int vector"))));
-
-INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3NotIntVec3,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
@@ -1075,15 +825,6 @@
                               "has 4 components"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    ComputeShaderInputInt32Vec3NotIntVec3,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
-            Values("GLCompute"), Values("Input"), Values("%u32vec4"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 3-component 32-bit int vector",
-                              "has 4 components"))));
-
-INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3NotInt32Vec,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
@@ -1153,12 +894,6 @@
             Values("%u32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    InstanceIndexSuccess,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
-            Values("%u32"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
     InstanceIndexInvalidExecutionModel,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"),
@@ -1170,14 +905,6 @@
                               "to be used only with Vertex execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    InstanceIndexInvalidExecutionModel,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("InstanceIndex"), Values("Fragment", "GLCompute"),
-            Values("Input"), Values("%u32"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "to be used only with Vertex execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
     InstanceIndexNotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"),
@@ -1188,16 +915,6 @@
                 "uses storage class Output"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    InstanceIndexNotInput,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"),
-            Values("%u32"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be only used for variables with Input storage class",
-                "uses storage class Output"))));
-
-INSTANTIATE_TEST_SUITE_P(
     InstanceIndexNotIntScalar,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
@@ -1208,15 +925,6 @@
                               "is not an int scalar"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    InstanceIndexNotIntScalar,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
-            Values("%f32", "%u32vec3"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 32-bit int scalar",
-                              "is not an int scalar"))));
-
-INSTANTIATE_TEST_SUITE_P(
     InstanceIndexNotInt32,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
@@ -1256,7 +964,8 @@
     ViewportIndexExecutionModelEnabledByCapability,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ViewportIndex"), Values("Vertex", "TessellationEvaluation"),
-            Values("Output"), Values("%u32"), Values(nullptr),
+            Values("Output"), Values("%u32"),
+            Values("VUID-ViewportIndex-ViewportIndex-04405"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "ShaderViewportIndexLayerEXT or ShaderViewportIndex"))));
@@ -1265,7 +974,7 @@
     LayerExecutionModelEnabledByCapability,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Layer"), Values("Vertex", "TessellationEvaluation"),
-            Values("Output"), Values("%u32"), Values(nullptr),
+            Values("Output"), Values("%u32"), Values("VUID-Layer-Layer-04273"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "ShaderViewportIndexLayerEXT or ShaderLayer"))));
 
@@ -1507,21 +1216,6 @@
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    PositionOutputSuccess,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("Position"), Values("Vertex"), Values("Output"),
-            Values("%f32vec4"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
-    PositionOutputFailure,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("Position"), Values("Fragment", "GLCompute"),
-            Values("Output"), Values("%f32vec4"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "WebGPU spec allows BuiltIn Position to be used "
-                              "only with the Vertex execution model."))));
-
-INSTANTIATE_TEST_SUITE_P(
     PositionInputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"),
@@ -1530,20 +1224,22 @@
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    PositionInputFailure,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("Position"), Values("Vertex", "Fragment", "GLCompute"),
-        Values("Input"), Values("%f32vec4"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "WebGPU spec allows BuiltIn Position to be only used "
-                          "for variables with Output storage class"))));
+    PositionInvalidStorageClass,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
+    Combine(Values("Position"),
+            Values("Geometry", "TessellationControl", "TessellationEvaluation"),
+            Values("Private"), Values("%f32vec4"),
+            Values("VUID-Position-Position-04320"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "Vulkan spec allows BuiltIn Position to be only used for "
+                "variables with Input or Output storage class."))));
 
 INSTANTIATE_TEST_SUITE_P(
     PositionVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Vertex"), Values("Input"),
-            Values("%f32vec4"), Values("VUID-Position-Position-04320"),
+            Values("%f32vec4"), Values("VUID-Position-Position-04319"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn Position "
@@ -1573,15 +1269,6 @@
                               "is not a float vector"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    PositionNotFloatVector,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("Position"), Values("Vertex"), Values("Output"),
-        Values("%f32arr4", "%u32vec4"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "needs to be a 4-component 32-bit float vector"))));
-
-INSTANTIATE_TEST_SUITE_P(
     PositionNotFloatVec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Geometry"), Values("Input"),
@@ -1591,15 +1278,6 @@
                               "has 3 components"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    PositionNotFloatVec4,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("Position"), Values("Vertex"), Values("Output"),
-        Values("%f32vec3"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "needs to be a 4-component 32-bit float vector"))));
-
-INSTANTIATE_TEST_SUITE_P(
     PositionNotF32Vec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Geometry"), Values("Input"),
@@ -1632,7 +1310,8 @@
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be used only with Fragment, TessellationControl, "
-                "TessellationEvaluation or Geometry execution models"))));
+                "TessellationEvaluation, Geometry, MeshNV, IntersectionKHR, "
+                "AnyHitKHR, and ClosestHitKHR execution models"))));
 
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdFragmentNotInput,
@@ -1645,7 +1324,7 @@
                           "which is called with execution model Fragment"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    PrimitiveIdGeometryNotInput,
+    PrimitiveIdTessellationNotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PrimitiveId"),
             Values("TessellationControl", "TessellationEvaluation"),
@@ -1917,7 +1596,8 @@
     TessLevelOuterOutputTese,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
-            Values("Output"), Values("%f32arr4"), Values(nullptr),
+            Values("Output"), Values("%f32arr4"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04392"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -1928,7 +1608,8 @@
     TessLevelOuterInputTesc,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
-            Values("Input"), Values("%f32arr4"), Values(nullptr),
+            Values("Input"), Values("%f32arr4"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04391"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -2004,7 +1685,8 @@
     TessLevelInnerOutputTese,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
-            Values("Output"), Values("%f32arr2"), Values(nullptr),
+            Values("Output"), Values("%f32arr2"),
+            Values("VUID-TessLevelInner-TessLevelInner-04396"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -2015,7 +1697,8 @@
     TessLevelInnerInputTesc,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationControl"),
-            Values("Input"), Values("%f32arr2"), Values(nullptr),
+            Values("Input"), Values("%f32arr2"),
+            Values("VUID-TessLevelInner-TessLevelInner-04395"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -2069,12 +1752,6 @@
             Values("%u32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
-    VertexIndexSuccess,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
-            Values("%u32"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
     VertexIndexInvalidExecutionModel,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexIndex"),
@@ -2086,14 +1763,6 @@
                               "to be used only with Vertex execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    VertexIndexInvalidExecutionModel,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("VertexIndex"), Values("Fragment", "GLCompute"),
-            Values("Input"), Values("%u32"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "to be used only with Vertex execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
     VertexIndexNotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
@@ -2104,16 +1773,6 @@
                           "used for variables with Input storage class"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    VertexIndexNotInput,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("VertexIndex"), Values("Vertex"), Values("Output"),
-        Values("%u32"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "WebGPU spec allows BuiltIn VertexIndex to be only "
-                          "used for variables with Input storage class"))));
-
-INSTANTIATE_TEST_SUITE_P(
     VertexIndexNotIntScalar,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
@@ -2124,15 +1783,6 @@
                               "is not an int scalar"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    VertexIndexNotIntScalar,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
-            Values("%f32", "%u32vec3"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 32-bit int scalar",
-                              "is not an int scalar"))));
-
-INSTANTIATE_TEST_SUITE_P(
     VertexIndexNotInt32,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
@@ -2142,50 +1792,6 @@
                               "has bit width 64"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    LocalInvocationIndexSuccess,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("LocalInvocationIndex"), Values("GLCompute"),
-            Values("Input"), Values("%u32"), Values(TestResult())));
-
-INSTANTIATE_TEST_SUITE_P(
-    LocalInvocationIndexInvalidExecutionModel,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("LocalInvocationIndex"), Values("Fragment", "Vertex"),
-        Values("Input"), Values("%u32"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "to be used only with GLCompute execution model"))));
-
-INSTANTIATE_TEST_SUITE_P(
-    LocalInvocationIndexNotInput,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(
-        Values("LocalInvocationIndex"), Values("GLCompute"), Values("Output"),
-        Values("%u32"),
-        Values(TestResult(SPV_ERROR_INVALID_DATA,
-                          "WebGPU spec allows BuiltIn LocalInvocationIndex to "
-                          "be only used for variables with Input storage "
-                          "class"))));
-
-INSTANTIATE_TEST_SUITE_P(
-    LocalInvocationIndexNotIntScalar,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("LocalInvocationIndex"), Values("GLCompute"),
-            Values("Input"), Values("%f32", "%u32vec3"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 32-bit int", "is not an int"))));
-
-INSTANTIATE_TEST_SUITE_P(
-    AllowListRejection,
-    ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("PointSize", "ClipDistance", "CullDistance", "VertexId",
-                   "InstanceId", "PointCoord", "SampleMask", "HelperInvocation",
-                   "WorkgroupId"),
-            Values("Vertex"), Values("Input"), Values("%u32"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "WebGPU does not allow BuiltIn"))));
-
-INSTANTIATE_TEST_SUITE_P(
     BaseInstanceOrVertexSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
     Combine(Values("BaseInstance", "BaseVertex"), Values("Vertex"),
@@ -2362,14 +1968,586 @@
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
 
-CodeGenerator GetArrayedVariableCodeGenerator(spv_target_env env,
-                                              const char* const built_in,
+// Test HitKind in NV RT shaders
+INSTANTIATE_TEST_SUITE_P(
+    HitKindNVSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitKindNV"),
+            Values("AnyHitNV", "ClosestHitNV"), Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingNV\n"),
+            Values("OpExtension \"SPV_NV_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+// HitKind is valid in AH, CH shaders as input i32 scalar
+INSTANTIATE_TEST_SUITE_P(
+    HitKindSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitKindKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR"), Values("Input"),
+            Values("%u32"), Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    HitKindNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitKindKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "IntersectionKHR",
+                   "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-HitKindKHR-HitKindKHR-04242"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    HitKindNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitKindKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR"), Values("Output"),
+            Values("%u32"), Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-HitKindKHR-HitKindKHR-04243"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    HitKindNotIntScalar,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitKindKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR"), Values("Input"),
+            Values("%f32", "%u32vec3"), Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-HitKindKHR-HitKindKHR-04244"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit int scalar",
+                              "is not an int scalar"))));
+
+// Ensure HitT is not supported in KHR RT shaders
+INSTANTIATE_TEST_SUITE_P(
+    HitTNVNotSupportedInKHR,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitTNV"),
+            Values("AnyHitKHR", "ClosestHitKHR"), Values("Input"),
+            Values("%u32"), Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult(
+                SPV_ERROR_INVALID_CAPABILITY,
+                "of MemberDecorate requires one of these capabilities"))));
+
+// HitT is valid in AH, CH shaders as input f32 scalar (NV RT only)
+INSTANTIATE_TEST_SUITE_P(
+    HitTNVSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitTNV"),
+            Values("AnyHitNV", "ClosestHitNV"), Values("Input"), Values("%f32"),
+            Values("OpCapability RayTracingNV\n"),
+            Values("OpExtension \"SPV_NV_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    HitTNVNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitTNV"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationNV", "IntersectionNV", "MissNV",
+                   "CallableNV"),
+            Values("Input"), Values("%f32"),
+            Values("OpCapability RayTracingNV\n"),
+            Values("OpExtension \"SPV_NV_ray_tracing\"\n"),
+            Values("VUID-HitTNV-HitTNV-04245"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    HitTNVNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitTNV"),
+            Values("AnyHitNV", "ClosestHitNV"), Values("Output"),
+            Values("%f32"), Values("OpCapability RayTracingNV\n"),
+            Values("OpExtension \"SPV_NV_ray_tracing\"\n"),
+            Values("VUID-HitTNV-HitTNV-04246"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+INSTANTIATE_TEST_SUITE_P(
+    HitTNVNotIntScalar,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("HitTNV"),
+            Values("AnyHitNV", "ClosestHitNV"), Values("Input"),
+            Values("%u32", "%f32vec3"), Values("OpCapability RayTracingNV\n"),
+            Values("OpExtension \"SPV_NV_ray_tracing\"\n"),
+            Values("VUID-HitTNV-HitTNV-04247"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit float scalar",
+                              "is not a float scalar"))));
+
+// InstanceCustomIndexKHR, InstanceId, PrimitiveId, RayGeometryIndexKHR are
+// valid in IS, AH, CH shaders as input i32 scalars
+INSTANTIATE_TEST_SUITE_P(
+    RTBuiltIn3StageI32Success,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("InstanceCustomIndexKHR", "RayGeometryIndexKHR",
+                   "InstanceId", "PrimitiveId"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    RTBuiltIn3StageI32NotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("InstanceCustomIndexKHR", "RayGeometryIndexKHR",
+                   "InstanceId"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251 "
+                   "VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345 "
+                   "VUID-InstanceId-InstanceId-04254 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    RTBuiltIn3StageI32NotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("InstanceCustomIndexKHR", "RayGeometryIndexKHR",
+                   "InstanceId"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Output"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252 "
+                   "VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346 "
+                   "VUID-InstanceId-InstanceId-04255 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    RTBuiltIn3StageI32NotIntScalar,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("InstanceCustomIndexKHR", "RayGeometryIndexKHR",
+                   "InstanceId"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Input"), Values("%f32", "%u32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253 "
+                   "VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347 "
+                   "VUID-InstanceId-InstanceId-04256 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit int scalar",
+                              "is not an int scalar"))));
+
+// PrimitiveId needs special negative testing because it has non-RT uses
+INSTANTIATE_TEST_SUITE_P(
+    PrimitiveIdRTNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("PrimitiveId"),
+            Values("RayGenerationKHR", "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-PrimitiveId-PrimitiveId-04330"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "to be used only with Fragment, TessellationControl, "
+                "TessellationEvaluation, Geometry, MeshNV, IntersectionKHR, "
+                "AnyHitKHR, and ClosestHitKHR execution models"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    PrimitiveIdRTNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("PrimitiveId"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Output"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-PrimitiveId-PrimitiveId-04334"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Output storage class if execution model is "))));
+
+INSTANTIATE_TEST_SUITE_P(
+    PrimitiveIdRTNotIntScalar,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("PrimitiveId"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Input"), Values("%f32", "%u32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-PrimitiveId-PrimitiveId-04337"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit int scalar",
+                              "is not an int scalar"))));
+
+// ObjectRayDirectionKHR and ObjectRayOriginKHR valid
+// in IS, AH, CH shaders as input 32-bit float vec3
+INSTANTIATE_TEST_SUITE_P(
+    ObjectRayDirectionAndOriginSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectRayDirectionKHR", "ObjectRayOriginKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Input"), Values("%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    ObjectRayDirectionAndOriginNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectRayDirectionKHR", "ObjectRayOriginKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299 "
+                   "VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    ObjectRayDirectionAndOriginNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectRayDirectionKHR", "ObjectRayOriginKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Output"), Values("%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300 "
+                   "VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    ObjectRayDirectionAndOriginNotFloatVec3,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(
+        Values(SPV_ENV_VULKAN_1_2),
+        Values("ObjectRayDirectionKHR", "ObjectRayOriginKHR"),
+        Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+        Values("Input"), Values("%u32vec3", "%f32", "%f32vec2", "%f32vec4"),
+        Values("OpCapability RayTracingKHR\n"),
+        Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+        Values("VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301 "
+               "VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304 "),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "needs to be a 3-component 32-bit float vector"))));
+
+// ObjectToWorldKHR and WorldToObjectKHR valid
+// in IS, AH, CH shaders as input mat4x3
+INSTANTIATE_TEST_SUITE_P(
+    RTObjectMatrixSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectToWorldKHR", "WorldToObjectKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Input"), Values("%f32mat34"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    RTObjectMatrixNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectToWorldKHR", "WorldToObjectKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%f32mat34"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305 "
+                   "VUID-WorldToObjectKHR-WorldToObjectKHR-04434 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    RTObjectMatrixNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectToWorldKHR", "WorldToObjectKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Output"), Values("%f32mat34"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306 "
+                   "VUID-WorldToObjectKHR-WorldToObjectKHR-04435 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    RTObjectMatrixNotMat4x3,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("ObjectToWorldKHR", "WorldToObjectKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR"),
+            Values("Input"), Values("%f32mat43", "%f32mat44", "%f32vec4"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307 "
+                   "VUID-WorldToObjectKHR-WorldToObjectKHR-04436 "),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "variable needs to be a matrix with "
+                "4 columns of 3-component vectors of 32-bit floats"))));
+
+// IncomingRayFlagsKHR is valid
+// in IS, AH, CH, MS shaders as an input i32 scalar
+INSTANTIATE_TEST_SUITE_P(
+    IncomingRayFlagsSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("IncomingRayFlagsKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    IncomingRayFlagsNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("IncomingRayFlagsKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "CallableKHR"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248 "
+                   "VUID-RayTmaxKHR-RayTmaxKHR-04348 "
+                   "VUID-RayTminKHR-RayTminKHR-04351 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    IncomingRayFlagsNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("IncomingRayFlagsKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Output"), Values("%u32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249 "
+                   "VUID-RayTmaxKHR-RayTmaxKHR-04349 "
+                   "VUID-RayTminKHR-RayTminKHR-04352 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+INSTANTIATE_TEST_SUITE_P(
+    IncomingRayFlagsNotIntScalar,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("IncomingRayFlagsKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Input"), Values("%f32", "%u32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250 "
+                   "VUID-RayTmaxKHR-RayTmaxKHR-04350 "
+                   "VUID-RayTminKHR-RayTminKHR-04353 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit int scalar",
+                              "is not an int scalar"))));
+
+// RayTmaxKHR, RayTminKHR are all valid
+// in IS, AH, CH, MS shaders as input f32 scalars
+INSTANTIATE_TEST_SUITE_P(
+    RayTSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("RayTmaxKHR", "RayTminKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Input"), Values("%f32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    RayTNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("RayTmaxKHR", "RayTminKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "CallableKHR"),
+            Values("Input"), Values("%f32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248 "
+                   "VUID-RayTmaxKHR-RayTmaxKHR-04348 "
+                   "VUID-RayTminKHR-RayTminKHR-04351 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    RayTNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("RayTmaxKHR", "RayTminKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Output"), Values("%f32"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249 "
+                   "VUID-RayTmaxKHR-RayTmaxKHR-04349 "
+                   "VUID-RayTminKHR-RayTminKHR-04352 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+INSTANTIATE_TEST_SUITE_P(
+    RayTNotFloatScalar,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("RayTmaxKHR", "RayTminKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Input"), Values("%u32", "%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250 "
+                   "VUID-RayTmaxKHR-RayTmaxKHR-04350 "
+                   "VUID-RayTminKHR-RayTminKHR-04353 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit float scalar",
+                              "is not a float scalar"))));
+
+// WorldRayDirectionKHR and WorldRayOriginKHR are valid
+// in IS, AH, CH, MS shaders as input 32-bit float vec3
+INSTANTIATE_TEST_SUITE_P(
+    WorldRayDirectionAndOriginSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("WorldRayDirectionKHR", "WorldRayOriginKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Input"), Values("%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    WorldRayDirectionAndOriginNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("WorldRayDirectionKHR", "WorldRayOriginKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute", "RayGenerationKHR", "CallableKHR"),
+            Values("Input"), Values("%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428 "
+                   "VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    WorldRayDirectionAndOriginNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2),
+            Values("WorldRayDirectionKHR", "WorldRayOriginKHR"),
+            Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+            Values("Output"), Values("%f32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429 "
+                   "VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    WorldRayDirectionAndOriginNotFloatVec3,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(
+        Values(SPV_ENV_VULKAN_1_2),
+        Values("WorldRayDirectionKHR", "WorldRayOriginKHR"),
+        Values("AnyHitKHR", "ClosestHitKHR", "IntersectionKHR", "MissKHR"),
+        Values("Input"), Values("%u32vec3", "%f32", "%f32vec2", "%f32vec4"),
+        Values("OpCapability RayTracingKHR\n"),
+        Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+        Values("VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430 "
+               "VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433 "),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "needs to be a 3-component 32-bit float vector"))));
+
+// LaunchIdKHR and LaunchSizeKHR are valid
+// in RG, IS, AH, CH, MS shaders as input 32-bit ivec3
+INSTANTIATE_TEST_SUITE_P(
+    LaunchRTSuccess,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("LaunchIdKHR", "LaunchSizeKHR"),
+            Values("RayGenerationKHR", "AnyHitKHR", "ClosestHitKHR",
+                   "IntersectionKHR", "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%u32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    LaunchRTNotExecutionMode,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("LaunchIdKHR", "LaunchSizeKHR"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "Fragment",
+                   "GLCompute"),
+            Values("Input"), Values("%u32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-LaunchIdKHR-LaunchIdKHR-04266 "
+                   "VUID-LaunchSizeKHR-LaunchSizeKHR-04269 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec does not allow BuiltIn",
+                              "to be used with the execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    LaunchRTNotInput,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("LaunchIdKHR", "LaunchSizeKHR"),
+            Values("RayGenerationKHR", "AnyHitKHR", "ClosestHitKHR",
+                   "IntersectionKHR", "MissKHR", "CallableKHR"),
+            Values("Output"), Values("%u32vec3"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-LaunchIdKHR-LaunchIdKHR-04267 "
+                   "VUID-LaunchSizeKHR-LaunchSizeKHR-04270 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
+                              "used for variables with Input storage class"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    LaunchRTNotIntVec3,
+    ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values(SPV_ENV_VULKAN_1_2), Values("LaunchIdKHR", "LaunchSizeKHR"),
+            Values("RayGenerationKHR", "AnyHitKHR", "ClosestHitKHR",
+                   "IntersectionKHR", "MissKHR", "CallableKHR"),
+            Values("Input"), Values("%f32vec3", "%u32", "%u32vec2", "%u32vec4"),
+            Values("OpCapability RayTracingKHR\n"),
+            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+            Values("VUID-LaunchIdKHR-LaunchIdKHR-04268 "
+                   "VUID-LaunchSizeKHR-LaunchSizeKHR-04271 "),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 3-component 32-bit int vector"))));
+
+CodeGenerator GetArrayedVariableCodeGenerator(const char* const built_in,
                                               const char* const execution_model,
                                               const char* const storage_class,
                                               const char* const data_type) {
-  CodeGenerator generator =
-      spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                          : CodeGenerator::GetDefaultShaderCodeGenerator();
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = "OpDecorate %built_in_var BuiltIn ";
   generator.before_types_ += built_in;
@@ -2377,14 +2555,14 @@
 
   std::ostringstream after_types;
   after_types << "%built_in_array = OpTypeArray " << data_type << " %u32_3\n";
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << "%built_in_array_null = OpConstantNull %built_in_array\n";
   }
 
   after_types << "%built_in_ptr = OpTypePointer " << storage_class
               << " %built_in_array\n";
   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
-  if (InitializerRequired(env, storage_class)) {
+  if (InitializerRequired(storage_class)) {
     after_types << " %built_in_array_null";
   }
   after_types << "\n";
@@ -2433,7 +2611,7 @@
   const TestResult& test_result = std::get<4>(GetParam());
 
   CodeGenerator generator = GetArrayedVariableCodeGenerator(
-      SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class, data_type);
+      built_in, execution_model, storage_class, data_type);
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
@@ -2446,27 +2624,6 @@
   }
 }
 
-TEST_P(ValidateWebGPUCombineBuiltInArrayedVariable, Variable) {
-  const char* const built_in = std::get<0>(GetParam());
-  const char* const execution_model = std::get<1>(GetParam());
-  const char* const storage_class = std::get<2>(GetParam());
-  const char* const data_type = std::get<3>(GetParam());
-  const TestResult& test_result = std::get<4>(GetParam());
-
-  CodeGenerator generator = GetArrayedVariableCodeGenerator(
-      SPV_ENV_WEBGPU_0, built_in, execution_model, storage_class, data_type);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(test_result.validation_result,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  if (test_result.error_str) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
-  }
-  if (test_result.error_str2) {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
-  }
-}
-
 INSTANTIATE_TEST_SUITE_P(PointSizeArrayedF32TessControl,
                          ValidateVulkanCombineBuiltInArrayedVariable,
                          Combine(Values("PointSize"),
@@ -2513,14 +2670,6 @@
                               "is not a float vector"))));
 
 INSTANTIATE_TEST_SUITE_P(
-    PositionArrayedF32Vec4Vertex, ValidateWebGPUCombineBuiltInArrayedVariable,
-    Combine(Values("Position"), Values("Vertex"), Values("Output"),
-            Values("%f32vec4"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 4-component 32-bit float vector",
-                              "is not a float vector"))));
-
-INSTANTIATE_TEST_SUITE_P(
     ClipAndCullDistanceOutputSuccess,
     ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("ClipDistance", "CullDistance"),
@@ -2623,10 +2772,8 @@
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
 
-CodeGenerator GetWorkgroupSizeSuccessGenerator(spv_target_env env) {
-  CodeGenerator generator =
-      env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                              : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetWorkgroupSizeSuccessGenerator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpDecorate %workgroup_size BuiltIn WorkgroupSize
@@ -2648,22 +2795,13 @@
 }
 
 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeSuccess) {
-  CodeGenerator generator =
-      GetWorkgroupSizeSuccessGenerator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetWorkgroupSizeSuccessGenerator();
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
-TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeSuccess) {
-  CodeGenerator generator = GetWorkgroupSizeSuccessGenerator(SPV_ENV_WEBGPU_0);
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-CodeGenerator GetWorkgroupSizeFragmentGenerator(spv_target_env env) {
-  CodeGenerator generator =
-      env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                              : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetWorkgroupSizeFragmentGenerator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpDecorate %workgroup_size BuiltIn WorkgroupSize
@@ -2686,8 +2824,7 @@
 }
 
 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeFragment) {
-  CodeGenerator generator =
-      GetWorkgroupSizeFragmentGenerator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetWorkgroupSizeFragmentGenerator();
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
@@ -2703,20 +2840,6 @@
                       "VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
-TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeFragment) {
-  CodeGenerator generator = GetWorkgroupSizeFragmentGenerator(SPV_ENV_WEBGPU_0);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("WebGPU spec allows BuiltIn WorkgroupSize to be used "
-                        "only with GLCompute execution model"));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("is referencing ID <2> (OpConstantComposite) which is "
-                        "decorated with BuiltIn WorkgroupSize in function <1> "
-                        "called with execution model Fragment"));
-}
-
 TEST_F(ValidateBuiltIns, WorkgroupSizeNotConstant) {
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
   generator.before_types_ = R"(
@@ -2742,10 +2865,8 @@
       HasSubstr("BuiltIns can only target variables, structs or constants"));
 }
 
-CodeGenerator GetWorkgroupSizeNotVectorGenerator(spv_target_env env) {
-  CodeGenerator generator =
-      env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                              : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetWorkgroupSizeNotVectorGenerator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpDecorate %workgroup_size BuiltIn WorkgroupSize
@@ -2767,8 +2888,7 @@
 }
 
 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotVector) {
-  CodeGenerator generator =
-      GetWorkgroupSizeNotVectorGenerator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetWorkgroupSizeNotVectorGenerator();
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
@@ -2780,22 +2900,8 @@
               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
-TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVector) {
-  CodeGenerator generator =
-      GetWorkgroupSizeNotVectorGenerator(SPV_ENV_WEBGPU_0);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize "
-                        "variable needs to be a 3-component 32-bit int vector. "
-                        "ID <2> (OpConstant) is not an int vector."));
-}
-
-CodeGenerator GetWorkgroupSizeNotIntVectorGenerator(spv_target_env env) {
-  CodeGenerator generator =
-      env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                              : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetWorkgroupSizeNotIntVectorGenerator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpDecorate %workgroup_size BuiltIn WorkgroupSize
@@ -2817,8 +2923,7 @@
 }
 
 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotIntVector) {
-  CodeGenerator generator =
-      GetWorkgroupSizeNotIntVectorGenerator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetWorkgroupSizeNotIntVectorGenerator();
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
@@ -2830,22 +2935,8 @@
               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
-TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotIntVector) {
-  CodeGenerator generator =
-      GetWorkgroupSizeNotIntVectorGenerator(SPV_ENV_WEBGPU_0);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize "
-                        "variable needs to be a 3-component 32-bit int vector. "
-                        "ID <2> (OpConstantComposite) is not an int vector."));
-}
-
-CodeGenerator GetWorkgroupSizeNotVec3Generator(spv_target_env env) {
-  CodeGenerator generator =
-      env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                              : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetWorkgroupSizeNotVec3Generator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpDecorate %workgroup_size BuiltIn WorkgroupSize
@@ -2867,8 +2958,7 @@
 }
 
 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotVec3) {
-  CodeGenerator generator =
-      GetWorkgroupSizeNotVec3Generator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetWorkgroupSizeNotVec3Generator();
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
@@ -2880,17 +2970,6 @@
               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
-TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVec3) {
-  CodeGenerator generator = GetWorkgroupSizeNotVec3Generator(SPV_ENV_WEBGPU_0);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize "
-                        "variable needs to be a 3-component 32-bit int vector. "
-                        "ID <2> (OpConstantComposite) has 2 components."));
-}
-
 TEST_F(ValidateBuiltIns, WorkgroupSizeNotInt32Vec) {
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
   generator.before_types_ = R"(
@@ -3168,10 +3247,8 @@
               HasSubstr("called with execution model Fragment"));
 }
 
-CodeGenerator GetNoDepthReplacingGenerator(spv_target_env env) {
-  CodeGenerator generator =
-      spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                          : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetNoDepthReplacingGenerator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpMemberDecorate %output_type 0 BuiltIn FragDepth
@@ -3204,17 +3281,13 @@
 OpFunctionEnd
 )";
 
-  if (spvIsWebGPUEnv(env)) {
-    generator.after_types_ += function_body;
-  } else {
     generator.add_at_the_end_ = function_body;
-  }
 
   return generator;
 }
 
 TEST_F(ValidateBuiltIns, VulkanFragmentFragDepthNoDepthReplacing) {
-  CodeGenerator generator = GetNoDepthReplacingGenerator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetNoDepthReplacingGenerator();
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
@@ -3225,21 +3298,8 @@
               HasSubstr("VUID-FragDepth-FragDepth-04216"));
 }
 
-TEST_F(ValidateBuiltIns, WebGPUFragmentFragDepthNoDepthReplacing) {
-  CodeGenerator generator = GetNoDepthReplacingGenerator(SPV_ENV_WEBGPU_0);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("WebGPU spec requires DepthReplacing execution mode to "
-                        "be declared when using BuiltIn FragDepth"));
-}
-
-CodeGenerator GetOneMainHasDepthReplacingOtherHasntGenerator(
-    spv_target_env env) {
-  CodeGenerator generator =
-      spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
-                          : CodeGenerator::GetDefaultShaderCodeGenerator();
+CodeGenerator GetOneMainHasDepthReplacingOtherHasntGenerator() {
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
   generator.before_types_ = R"(
 OpMemberDecorate %output_type 0 BuiltIn FragDepth
@@ -3283,19 +3343,14 @@
 OpFunctionEnd
 )";
 
-  if (spvIsWebGPUEnv(env)) {
-    generator.after_types_ += function_body;
-  } else {
     generator.add_at_the_end_ = function_body;
-  }
 
   return generator;
 }
 
 TEST_F(ValidateBuiltIns,
        VulkanFragmentFragDepthOneMainHasDepthReplacingOtherHasnt) {
-  CodeGenerator generator =
-      GetOneMainHasDepthReplacingOtherHasntGenerator(SPV_ENV_VULKAN_1_0);
+  CodeGenerator generator = GetOneMainHasDepthReplacingOtherHasntGenerator();
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
@@ -3306,17 +3361,6 @@
               HasSubstr("VUID-FragDepth-FragDepth-04216"));
 }
 
-TEST_F(ValidateBuiltIns,
-       WebGPUFragmentFragDepthOneMainHasDepthReplacingOtherHasnt) {
-  CodeGenerator generator =
-      GetOneMainHasDepthReplacingOtherHasntGenerator(SPV_ENV_WEBGPU_0);
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("WebGPU spec requires DepthReplacing execution mode to "
-                        "be declared when using BuiltIn FragDepth"));
-}
 
 TEST_F(ValidateBuiltIns, AllowInstanceIdWithIntersectionShader) {
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
@@ -3358,44 +3402,6 @@
   EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
-TEST_F(ValidateBuiltIns, DisallowInstanceIdWithRayGenShader) {
-  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
-  generator.capabilities_ += R"(
-OpCapability RayTracingNV
-)";
-
-  generator.extensions_ = R"(
-OpExtension "SPV_NV_ray_tracing"
-)";
-
-  generator.before_types_ = R"(
-OpMemberDecorate %input_type 0 BuiltIn InstanceId
-)";
-
-  generator.after_types_ = R"(
-%input_type = OpTypeStruct %u32
-%input_ptr = OpTypePointer Input %input_type
-%input_ptr_u32 = OpTypePointer Input %u32
-%input = OpVariable %input_ptr Input
-)";
-
-  EntryPoint entry_point;
-  entry_point.name = "main_d_r";
-  entry_point.execution_model = "RayGenerationNV";
-  entry_point.interfaces = "%input";
-  entry_point.body = R"(
-%input_member = OpAccessChain %input_ptr_u32 %input %u32_0
-)";
-  generator.entry_points_.push_back(std::move(entry_point));
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Vulkan spec allows BuiltIn InstanceId to be used "
-                        "only with IntersectionNV, ClosestHitNV and "
-                        "AnyHitNV execution models"));
-}
-
 TEST_F(ValidateBuiltIns, ValidBuiltinsForMeshShader) {
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
   generator.capabilities_ += R"(
@@ -3509,7 +3515,8 @@
   const char* const execution_model = std::get<1>(GetParam());
   const char* const storage_class = std::get<2>(GetParam());
   const char* const data_type = std::get<3>(GetParam());
-  const TestResult& test_result = std::get<4>(GetParam());
+  const char* const vuid = std::get<4>(GetParam());
+  const TestResult& test_result = std::get<5>(GetParam());
 
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
   generator.capabilities_ += R"(
@@ -3569,6 +3576,9 @@
   if (test_result.error_str2) {
     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
   }
+  if (vuid) {
+    EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
+  }
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -3576,6 +3586,11 @@
     Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask",
                    "SubgroupLeMask", "SubgroupLtMask"),
             Values("GLCompute"), Values("Input"), Values("%u32vec3"),
+            Values("VUID-SubgroupEqMask-SubgroupEqMask-04371 "
+                   "VUID-SubgroupGeMask-SubgroupGeMask-04373 "
+                   "VUID-SubgroupGtMask-SubgroupGtMask-04375 "
+                   "VUID-SubgroupLeMask-SubgroupLeMask-04377 "
+                   "VUID-SubgroupLtMask-SubgroupLtMask-04379"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit int vector"))));
 
@@ -3584,6 +3599,11 @@
     Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask",
                    "SubgroupLeMask", "SubgroupLtMask"),
             Values("GLCompute"), Values("Input"), Values("%f32vec4"),
+            Values("VUID-SubgroupEqMask-SubgroupEqMask-04371 "
+                   "VUID-SubgroupGeMask-SubgroupGeMask-04373 "
+                   "VUID-SubgroupGtMask-SubgroupGtMask-04375 "
+                   "VUID-SubgroupLeMask-SubgroupLeMask-04377 "
+                   "VUID-SubgroupLtMask-SubgroupLtMask-04379"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit int vector"))));
 
@@ -3593,6 +3613,11 @@
                    "SubgroupLeMask", "SubgroupLtMask"),
             Values("GLCompute"), Values("Output", "Workgroup", "Private"),
             Values("%u32vec4"),
+            Values("VUID-SubgroupEqMask-SubgroupEqMask-04370 "
+                   "VUID-SubgroupGeMask-SubgroupGeMask-04372 "
+                   "VUID-SubgroupGtMask-SubgroupGtMask-04374 "
+                   "VUID-SubgroupLeMask-SubgroupLeMask-04376  "
+                   "VUID-SubgroupLtMask-SubgroupLtMask-04378"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class"))));
@@ -3602,7 +3627,7 @@
                                         "SubgroupGtMask", "SubgroupLeMask",
                                         "SubgroupLtMask"),
                                  Values("GLCompute"), Values("Input"),
-                                 Values("%u32vec4"),
+                                 Values("%u32vec4"), Values(nullptr),
                                  Values(TestResult(SPV_SUCCESS, ""))));
 
 TEST_F(ValidateBuiltIns, SubgroupMaskMemberDecorate) {
@@ -3635,6 +3660,8 @@
     SubgroupInvocationIdAndSizeNotU32, ValidateVulkanSubgroupBuiltIns,
     Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
             Values("GLCompute"), Values("Input"), Values("%f32"),
+            Values("VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-"
+                   "04381 VUID-SubgroupSize-SubgroupSize-04383"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int"))));
 
@@ -3643,6 +3670,8 @@
     Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
             Values("GLCompute"), Values("Output", "Workgroup", "Private"),
             Values("%u32"),
+            Values("VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-"
+                   "04380 VUID-SubgroupSize-SubgroupSize-04382"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class"))));
@@ -3651,7 +3680,7 @@
     SubgroupInvocationIdAndSizeOk, ValidateVulkanSubgroupBuiltIns,
     Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
             Values("GLCompute"), Values("Input"), Values("%u32"),
-            Values(TestResult(SPV_SUCCESS, ""))));
+            Values(nullptr), Values(TestResult(SPV_SUCCESS, ""))));
 
 TEST_F(ValidateBuiltIns, SubgroupSizeMemberDecorate) {
   const std::string text = R"(
@@ -3679,9 +3708,21 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(
+    SubgroupNumAndIdNotCompute, ValidateVulkanSubgroupBuiltIns,
+    Combine(
+        Values("SubgroupId", "NumSubgroups"), Values("Vertex"), Values("Input"),
+        Values("%u32"),
+        Values("VUID-SubgroupId-SubgroupId-04367 "
+               "VUID-NumSubgroups-NumSubgroups-04293"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "to be used only with GLCompute execution model"))));
+
+INSTANTIATE_TEST_SUITE_P(
     SubgroupNumAndIdNotU32, ValidateVulkanSubgroupBuiltIns,
     Combine(Values("SubgroupId", "NumSubgroups"), Values("GLCompute"),
             Values("Input"), Values("%f32"),
+            Values("VUID-SubgroupId-SubgroupId-04369 "
+                   "VUID-NumSubgroups-NumSubgroups-04295"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int"))));
 
@@ -3689,6 +3730,8 @@
     SubgroupNumAndIdNotInput, ValidateVulkanSubgroupBuiltIns,
     Combine(Values("SubgroupId", "NumSubgroups"), Values("GLCompute"),
             Values("Output", "Workgroup", "Private"), Values("%u32"),
+            Values("VUID-SubgroupId-SubgroupId-04368 "
+                   "VUID-NumSubgroups-NumSubgroups-04294"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class"))));
@@ -3696,7 +3739,7 @@
 INSTANTIATE_TEST_SUITE_P(SubgroupNumAndIdOk, ValidateVulkanSubgroupBuiltIns,
                          Combine(Values("SubgroupId", "NumSubgroups"),
                                  Values("GLCompute"), Values("Input"),
-                                 Values("%u32"),
+                                 Values("%u32"), Values(nullptr),
                                  Values(TestResult(SPV_SUCCESS, ""))));
 
 TEST_F(ValidateBuiltIns, SubgroupIdMemberDecorate) {
@@ -3898,6 +3941,184 @@
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "According to the Vulkan spec BuiltIn ShadingRateKHR "
                           "variable needs to be a 32-bit int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragInvocationCountInputSuccess,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragInvocationCountEXT"), Values("Fragment"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability FragmentDensityEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+            Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragInvocationCountInvalidExecutionModel,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(
+        Values("FragInvocationCountEXT"), Values("Vertex"), Values("Input"),
+        Values("%u32"), Values("OpCapability FragmentDensityEXT\n"),
+        Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+        Values("VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "Vulkan spec allows BuiltIn FragInvocationCountEXT "
+                          "to be used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragInvocationCountInvalidStorageClass,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragInvocationCountEXT"), Values("Fragment"),
+            Values("Output"), Values("%u32"),
+            Values("OpCapability FragmentDensityEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+            Values("VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "Vulkan spec allows BuiltIn FragInvocationCountEXT to be only "
+                "used for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragInvocationCountInvalidType,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragInvocationCountEXT"), Values("Fragment"),
+            Values("Input"), Values("%f32"),
+            Values("OpCapability FragmentDensityEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+            Values("VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "According to the Vulkan spec BuiltIn FragInvocationCountEXT "
+                "variable needs to be a 32-bit int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragSizeInputSuccess,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragSizeEXT"), Values("Fragment"), Values("Input"),
+            Values("%u32vec2"), Values("OpCapability FragmentDensityEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+            Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragSizeInvalidExecutionModel,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragSizeEXT"), Values("Vertex"), Values("Input"),
+            Values("%u32vec2"), Values("OpCapability FragmentDensityEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+            Values("VUID-FragSizeEXT-FragSizeEXT-04220"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec allows BuiltIn FragSizeEXT to be "
+                              "used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragSizeInvalidStorageClass,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(
+        Values("FragSizeEXT"), Values("Fragment"), Values("Output"),
+        Values("%u32vec2"), Values("OpCapability FragmentDensityEXT\n"),
+        Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+        Values("VUID-FragSizeEXT-FragSizeEXT-04221"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "Vulkan spec allows BuiltIn FragSizeEXT to be only "
+                          "used for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragSizeInvalidType,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragSizeEXT"), Values("Fragment"), Values("Input"),
+            Values("%u32vec3"), Values("OpCapability FragmentDensityEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+            Values("VUID-FragSizeEXT-FragSizeEXT-04222"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "According to the Vulkan spec BuiltIn FragSizeEXT variable "
+                "needs to be a 2-component 32-bit int vector."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragStencilRefOutputSuccess,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragStencilRefEXT"), Values("Fragment"), Values("Output"),
+            Values("%u32", "%u64"), Values("OpCapability StencilExportEXT\n"),
+            Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+            Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragStencilRefInvalidExecutionModel,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragStencilRefEXT"), Values("Vertex"), Values("Output"),
+            Values("%u32", "%u64"), Values("OpCapability StencilExportEXT\n"),
+            Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+            Values("VUID-FragStencilRefEXT-FragStencilRefEXT-04223"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec allows BuiltIn FragStencilRefEXT to "
+                              "be used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragStencilRefInvalidStorageClass,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragStencilRefEXT"), Values("Fragment"), Values("Input"),
+            Values("%u32", "%u64"), Values("OpCapability StencilExportEXT\n"),
+            Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+            Values("VUID-FragStencilRefEXT-FragStencilRefEXT-04224"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "Vulkan spec allows BuiltIn FragStencilRefEXT to be only used "
+                "for variables with Output storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FragStencilRefInvalidType,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FragStencilRefEXT"), Values("Fragment"), Values("Output"),
+            Values("%f32", "%f64", "%u32vec2"),
+            Values("OpCapability StencilExportEXT\n"),
+            Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+            Values("VUID-FragStencilRefEXT-FragStencilRefEXT-04225"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "According to the Vulkan spec BuiltIn FragStencilRefEXT "
+                "variable needs to be a int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FullyCoveredEXTInputSuccess,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FullyCoveredEXT"), Values("Fragment"), Values("Input"),
+            Values("%bool"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+            Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    FullyCoveredEXTInvalidExecutionModel,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FullyCoveredEXT"), Values("Vertex"), Values("Input"),
+            Values("%bool"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+            Values("VUID-FullyCoveredEXT-FullyCoveredEXT-04232"),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "Vulkan spec allows BuiltIn FullyCoveredEXT to "
+                              "be used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FullyCoveredEXTInvalidStorageClass,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FullyCoveredEXT"), Values("Fragment"), Values("Output"),
+            Values("%bool"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+            Values("VUID-FullyCoveredEXT-FullyCoveredEXT-04233"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "Vulkan spec allows BuiltIn FullyCoveredEXT to be only used "
+                "for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+    FullyCoveredEXTInvalidType,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("FullyCoveredEXT"), Values("Fragment"), Values("Input"),
+            Values("%f32"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+            Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+            Values("VUID-FullyCoveredEXT-FullyCoveredEXT-04234"),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "According to the Vulkan spec BuiltIn FullyCoveredEXT variable "
+                "needs to be a bool scalar."))));
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_capability_test.cpp b/third_party/SPIRV-Tools/test/val/val_capability_test.cpp
index 9705cb8..82f8d38 100644
--- a/third_party/SPIRV-Tools/test/val/val_capability_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_capability_test.cpp
@@ -116,8 +116,6 @@
 using ValidateCapabilityVulkan11 = spvtest::ValidateBase<CapTestParameter>;
 // Always assembles using Vulkan 1.2.
 using ValidateCapabilityVulkan12 = spvtest::ValidateBase<CapTestParameter>;
-// Always assembles using WebGPU.
-using ValidateCapabilityWebGPU = spvtest::ValidateBase<CapTestParameter>;
 
 TEST_F(ValidateCapability, Default) {
   const char str[] = R"(
@@ -588,18 +586,6 @@
   return *r;
 }
 
-const std::vector<std::string>& AllWebGPUCapabilities() {
-  static const auto r = new std::vector<std::string>{
-    "",
-    "Shader",
-    "Matrix",
-    "Sampled1D",
-    "Image1D",
-    "ImageQuery",
-    "DerivativeControl"};
-    return *r;
-}
-
 const std::vector<std::string>& MatrixDependencies() {
   static const auto r = new std::vector<std::string>{
   "Matrix",
@@ -790,12 +776,6 @@
   " OpCapability Shader"
   " OpMemoryModel Logical GLSL450 ";
 
-const char kVulkanMemoryModel[] = \
-  " OpCapability Shader"
-  " OpCapability VulkanMemoryModelKHR"
-  " OpExtension \"SPV_KHR_vulkan_memory_model\""
-  " OpMemoryModel Logical VulkanKHR ";
-
 const char kVoidFVoid[] = \
   " %void   = OpTypeVoid"
   " %void_f = OpTypeFunction %void"
@@ -1814,16 +1794,6 @@
           AllSpirV10Capabilities())
 )));
 
-INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityWebGPU,
-                        Combine(
-                            // All capabilities to try.
-                            ValuesIn(AllCapabilities()),
-                            Values(
-std::make_pair(std::string(kVulkanMemoryModel) +
-          "OpEntryPoint Vertex %func \"shader\" \n" + std::string(kVoidFVoid),
-          AllWebGPUCapabilities())
-)));
-
 INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityVulkan11,
                         Combine(
                             // All capabilities to try.
@@ -2047,17 +2017,6 @@
   }
 }
 
-TEST_P(ValidateCapabilityWebGPU, Capability) {
-  const std::string capability = Capability(GetParam());
-  if (Exists(capability, SPV_ENV_WEBGPU_0)) {
-    const std::string test_code = MakeAssembly(GetParam());
-    CompileSuccessfully(test_code, SPV_ENV_WEBGPU_0);
-    ASSERT_EQ(ExpectedResult(GetParam()),
-              ValidateInstructions(SPV_ENV_WEBGPU_0))
-        << test_code;
-  }
-}
-
 TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) {
   // From https://github.com/KhronosGroup/SPIRV-Tools/issues/248
   // The validator was interpreting the memory semantics ID number
diff --git a/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp b/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
index b4d1c28..9698fb1 100644
--- a/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
@@ -168,15 +168,6 @@
   return (cap == SpvCapabilityShader) ? shader_header : kernel_header;
 }
 
-const std::string& GetWebGPUHeader() {
-  static const std::string header =
-      "OpCapability Shader\n"
-      "OpCapability VulkanMemoryModelKHR\n"
-      "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
-      "OpMemoryModel Logical VulkanKHR\n";
-  return header;
-}
-
 const std::string& types_consts() {
   static const std::string types =
       "%voidt   = OpTypeVoid\n"
@@ -496,10 +487,10 @@
 
 TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceValue) {
   Block entry("entry");
-  entry.SetBody("%undef = OpUndef %voidt\n");
+  entry.SetBody("%undef = OpUndef %boolt\n");
   Block bad("bad");
   Block end("end", SpvOpReturn);
-  Block badvalue("undef");  // This referenes the OpUndef.
+  Block badvalue("undef");  // This references the OpUndef.
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("entry", "bad", std::make_pair("func", "Main")) +
                     types_consts() +
@@ -714,10 +705,8 @@
   }
 }
 
-std::string GetUnreachableMergeNoMergeInst(SpvCapability cap,
-                                           spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeNoMergeInst(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
   Block entry("entry");
   Block branch("branch", SpvOpBranchConditional);
   Block t("t", SpvOpReturn);
@@ -725,17 +714,11 @@
   Block merge("merge", SpvOpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
-  if (!spvIsWebGPUEnv(env) && cap == SpvCapabilityShader)
+  if (cap == SpvCapabilityShader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", std::make_pair("func", "Main"));
+  str += nameOps("branch", "merge", std::make_pair("func", "Main"));
   str += types_consts() + "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
   str += branch >> std::vector<Block>({t, f});
@@ -748,23 +731,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeNoMergeInst) {
-  CompileSuccessfully(
-      GetUnreachableMergeNoMergeInst(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableMergeNoMergeInst(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableMergeNoMergeInst) {
-  CompileSuccessfully(
-      GetUnreachableMergeNoMergeInst(SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, all blocks must be reachable"));
-}
-
-std::string GetUnreachableMergeTerminatedBy(SpvCapability cap,
-                                            spv_target_env env, SpvOp op) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeTerminatedBy(SpvCapability cap, SpvOp op) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranchConditional);
@@ -774,16 +746,10 @@
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
@@ -797,49 +763,24 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpUnreachable) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpUnreachable));
+  CompileSuccessfully(
+      GetUnreachableMergeTerminatedBy(GetParam(), SpvOpUnreachable));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
 TEST_F(ValidateCFG, UnreachableMergeTerminatedByOpKill) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_UNIVERSAL_1_0, SpvOpKill));
+  CompileSuccessfully(
+      GetUnreachableMergeTerminatedBy(SpvCapabilityShader, SpvOpKill));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
 TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpReturn) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpReturn));
+  CompileSuccessfully(GetUnreachableMergeTerminatedBy(GetParam(), SpvOpReturn));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableMergeTerminatedByOpUnreachable) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpUnreachable));
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateCFG, WebGPUUnreachableMergeTerminatedByOpKill) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpKill));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must terminate with OpUnreachable"));
-}
-
-TEST_P(ValidateCFG, WebGPUUnreachableMergeTerminatedByOpReturn) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpReturn));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must terminate with OpUnreachable"));
-}
-
-std::string GetUnreachableContinueTerminatedBy(SpvCapability cap,
-                                               spv_target_env env, SpvOp op) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableContinueTerminatedBy(SpvCapability cap, SpvOp op) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranch);
@@ -849,16 +790,10 @@
   if (op == SpvOpBranch) target >> branch;
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
@@ -871,8 +806,8 @@
 }
 
 TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpUnreachable) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpUnreachable));
+  CompileSuccessfully(
+      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpUnreachable));
   if (GetParam() == SpvCapabilityShader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
@@ -883,16 +818,16 @@
 }
 
 TEST_F(ValidateCFG, UnreachableContinueTerminatedBySpvOpKill) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_UNIVERSAL_1_0, SpvOpKill));
+  CompileSuccessfully(
+      GetUnreachableContinueTerminatedBy(SpvCapabilityShader, SpvOpKill));
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("targeted by 0 back-edge blocks"));
 }
 
 TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpReturn) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpReturn));
+  CompileSuccessfully(
+      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpReturn));
   if (GetParam() == SpvCapabilityShader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
@@ -903,48 +838,13 @@
 }
 
 TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpBranch) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0, SpvOpBranch));
+  CompileSuccessfully(
+      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpBranch));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpUnreachable) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpUnreachable));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, unreachable continue-target must "
-                        "terminate with OpBranch.\n  %12 = OpLabel\n"));
-}
-
-TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpKill) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpKill));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, unreachable continue-target must "
-                        "terminate with OpBranch.\n  %12 = OpLabel\n"));
-}
-
-TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpReturn) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpReturn));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, unreachable continue-target must "
-                        "terminate with OpBranch.\n  %12 = OpLabel\n"));
-}
-
-TEST_F(ValidateCFG, WebGPUUnreachableContinueTerminatedBySpvOpBranch) {
-  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0, SpvOpBranch));
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-std::string GetUnreachableMergeUnreachableMergeInst(SpvCapability cap,
-                                                    spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeUnreachableMergeInst(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block body("body", SpvOpReturn);
   Block entry("entry");
@@ -955,16 +855,10 @@
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += body;
@@ -979,23 +873,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeUnreachableMergeInst) {
-  CompileSuccessfully(GetUnreachableMergeUnreachableMergeInst(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableMergeUnreachableMergeInst(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableMergeUnreachableMergeInst) {
-  CompileSuccessfully(GetUnreachableMergeUnreachableMergeInst(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must be referenced by a reachable merge instruction"));
-}
-
-std::string GetUnreachableContinueUnreachableLoopInst(SpvCapability cap,
-                                                      spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableContinueUnreachableLoopInst(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block body("body", SpvOpReturn);
   Block entry("entry");
@@ -1006,16 +889,10 @@
   target >> branch;
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += body;
@@ -1029,8 +906,7 @@
 }
 
 TEST_P(ValidateCFG, UnreachableContinueUnreachableLoopInst) {
-  CompileSuccessfully(GetUnreachableContinueUnreachableLoopInst(
-      GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableContinueUnreachableLoopInst(GetParam()));
   if (GetParam() == SpvCapabilityShader) {
     // Shader causes additional structured CFG checks that cause a failure.
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
@@ -1043,18 +919,8 @@
   }
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableContinueUnreachableLoopInst) {
-  CompileSuccessfully(GetUnreachableContinueUnreachableLoopInst(
-      SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must be referenced by a reachable loop instruction"));
-}
-
-std::string GetUnreachableMergeWithComplexBody(SpvCapability cap,
-                                               spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeWithComplexBody(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranchConditional);
@@ -1062,23 +928,15 @@
   Block f("f", SpvOpReturn);
   Block merge("merge", SpvOpUnreachable);
 
-  entry.AppendBody(spvIsWebGPUEnv(env)
-                       ? "%placeholder   = OpVariable %intptrt Function %two\n"
-                       : "%placeholder   = OpVariable %intptrt Function\n");
+  entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
   merge.AppendBody("OpStore %placeholder %one\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%intptrt = OpTypePointer Function %intt\n";
   str += "%func    = OpFunction %voidt None %funct\n";
@@ -1093,24 +951,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeWithComplexBody) {
-  CompileSuccessfully(
-      GetUnreachableMergeWithComplexBody(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableMergeWithComplexBody(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableMergeWithComplexBody) {
-  CompileSuccessfully(GetUnreachableMergeWithComplexBody(SpvCapabilityShader,
-                                                         SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("must only contain an OpLabel and OpUnreachable instruction"));
-}
-
-std::string GetUnreachableContinueWithComplexBody(SpvCapability cap,
-                                                  spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableContinueWithComplexBody(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranch);
@@ -1119,22 +965,14 @@
 
   target >> branch;
 
-  entry.AppendBody(spvIsWebGPUEnv(env)
-                       ? "%placeholder   = OpVariable %intptrt Function %two\n"
-                       : "%placeholder   = OpVariable %intptrt Function\n");
+  entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
   target.AppendBody("OpStore %placeholder %one\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%intptrt = OpTypePointer Function %intt\n";
   str += "%func    = OpFunction %voidt None %funct\n";
@@ -1148,24 +986,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableContinueWithComplexBody) {
-  CompileSuccessfully(
-      GetUnreachableContinueWithComplexBody(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableContinueWithComplexBody(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableContinueWithComplexBody) {
-  CompileSuccessfully(GetUnreachableContinueWithComplexBody(SpvCapabilityShader,
-                                                            SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("must only contain an OpLabel and an OpBranch instruction"));
-}
-
-std::string GetUnreachableMergeWithBranchUse(SpvCapability cap,
-                                             spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeWithBranchUse(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranchConditional);
@@ -1176,16 +1002,10 @@
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
@@ -1199,15 +1019,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeWithBranchUse) {
-  CompileSuccessfully(
-      GetUnreachableMergeWithBranchUse(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableMergeWithBranchUse(GetParam()));
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithMultipleUses(SpvCapability cap,
-                                                spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeWithMultipleUses(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranchConditional);
@@ -1219,18 +1036,12 @@
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader) {
     branch.AppendBody("OpSelectionMerge %merge None\n");
     duplicate.AppendBody("OpSelectionMerge %merge None\n");
   }
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
@@ -1245,8 +1056,7 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeWithMultipleUses) {
-  CompileSuccessfully(
-      GetUnreachableMergeWithMultipleUses(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableMergeWithMultipleUses(GetParam()));
   if (GetParam() == SpvCapabilityShader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
@@ -1256,18 +1066,8 @@
   }
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableMergeWithMultipleUses) {
-  CompileSuccessfully(GetUnreachableMergeWithMultipleUses(SpvCapabilityShader,
-                                                          SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("is already a merge block for another header"));
-}
-
-std::string GetUnreachableContinueWithBranchUse(SpvCapability cap,
-                                                spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableContinueWithBranchUse(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block foo("foo", SpvOpBranch);
@@ -1278,21 +1078,13 @@
   foo >> target;
   target >> branch;
 
-  entry.AppendBody(spvIsWebGPUEnv(env)
-                       ? "%placeholder   = OpVariable %intptrt Function %two\n"
-                       : "%placeholder   = OpVariable %intptrt Function\n");
+  entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
 
+  str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%intptrt = OpTypePointer Function %intt\n";
   str += "%func    = OpFunction %voidt None %funct\n";
@@ -1307,23 +1099,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableContinueWithBranchUse) {
-  CompileSuccessfully(
-      GetUnreachableContinueWithBranchUse(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableContinueWithBranchUse(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableContinueWithBranchUse) {
-  CompileSuccessfully(GetUnreachableContinueWithBranchUse(SpvCapabilityShader,
-                                                          SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("cannot be the target of a branch."));
-}
-
-std::string GetReachableMergeAndContinue(SpvCapability cap,
-                                         spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetReachableMergeAndContinue(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranch);
@@ -1339,20 +1120,13 @@
   f >> target;
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader) {
     branch.AppendBody("OpLoopMerge %merge %target None\n");
     body.AppendBody("OpSelectionMerge %f None\n");
   }
 
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", "target", "body", "t", "f",
-                   std::make_pair("func", "Main"));
-
+  str += nameOps("branch", "merge", "target", "body", "t", "f",
+                 std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
@@ -1368,21 +1142,12 @@
 }
 
 TEST_P(ValidateCFG, ReachableMergeAndContinue) {
-  CompileSuccessfully(
-      GetReachableMergeAndContinue(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetReachableMergeAndContinue(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUReachableMergeAndContinue) {
-  CompileSuccessfully(
-      GetReachableMergeAndContinue(SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-std::string GetUnreachableMergeAndContinue(SpvCapability cap,
-                                           spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableMergeAndContinue(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block branch("branch", SpvOpBranch);
@@ -1396,20 +1161,13 @@
   body.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
   if (cap == SpvCapabilityShader) {
     branch.AppendBody("OpLoopMerge %merge %target None\n");
     body.AppendBody("OpSelectionMerge %target None\n");
   }
 
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("branch", "merge", "target", "body", "t", "f",
-                   std::make_pair("func", "Main"));
-
+  str += nameOps("branch", "merge", "target", "body", "t", "f",
+                 std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> branch;
@@ -1425,36 +1183,19 @@
 }
 
 TEST_P(ValidateCFG, UnreachableMergeAndContinue) {
-  CompileSuccessfully(
-      GetUnreachableMergeAndContinue(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableMergeAndContinue(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableMergeAndContinue) {
-  CompileSuccessfully(
-      GetUnreachableMergeAndContinue(SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("unreachable merge-blocks must terminate with OpUnreachable"));
-}
-
-std::string GetUnreachableBlock(SpvCapability cap, spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableBlock(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block unreachable("unreachable");
   Block exit("exit", SpvOpReturn);
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("unreachable", "exit", std::make_pair("func", "Main"));
+  str += nameOps("unreachable", "exit", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
   str += entry >> exit;
@@ -1466,20 +1207,12 @@
 }
 
 TEST_P(ValidateCFG, UnreachableBlock) {
-  CompileSuccessfully(GetUnreachableBlock(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableBlock(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableBlock) {
-  CompileSuccessfully(
-      GetUnreachableBlock(SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("all blocks must be reachable"));
-}
-
-std::string GetUnreachableBranch(SpvCapability cap, spv_target_env env) {
-  std::string header =
-      spvIsWebGPUEnv(env) ? GetWebGPUHeader() : GetDefaultHeader(cap);
+std::string GetUnreachableBranch(SpvCapability cap) {
+  std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block unreachable("unreachable", SpvOpBranchConditional);
@@ -1493,13 +1226,7 @@
     unreachable.AppendBody("OpSelectionMerge %merge None\n");
 
   std::string str = header;
-  if (spvIsWebGPUEnv(env)) {
-    str +=
-        "OpEntryPoint Fragment %func \"func\"\n"
-        "OpExecutionMode %func OriginUpperLeft\n";
-  }
-  if (!spvIsWebGPUEnv(env))
-    str += nameOps("unreachable", "exit", std::make_pair("func", "Main"));
+  str += nameOps("unreachable", "exit", std::make_pair("func", "Main"));
   str += types_consts();
   str += "%func    = OpFunction %voidt None %funct\n";
 
@@ -1516,17 +1243,10 @@
 }
 
 TEST_P(ValidateCFG, UnreachableBranch) {
-  CompileSuccessfully(GetUnreachableBranch(GetParam(), SPV_ENV_UNIVERSAL_1_0));
+  CompileSuccessfully(GetUnreachableBranch(GetParam()));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateCFG, WebGPUUnreachableBranch) {
-  CompileSuccessfully(
-      GetUnreachableBranch(SpvCapabilityShader, SPV_ENV_WEBGPU_0));
-  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("all blocks must be reachable"));
-}
-
 TEST_P(ValidateCFG, EmptyFunction) {
   std::string str = GetDefaultHeader(GetParam()) + std::string(types_consts()) +
                     R"(%func    = OpFunction %voidt None %funct
@@ -4598,6 +4318,38 @@
   EXPECT_THAT(getDiagnosticString(), HasSubstr("multiple times."));
 }
 
+TEST_F(ValidateCFG, PhiOnVoid) {
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpName %4 "main"
+               OpName %6 "foo("
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpFunctionCall %2 %6
+               OpBranch %20
+         %20 = OpLabel
+         %21 = OpPhi %2 %8 %20
+               OpReturn
+               OpFunctionEnd
+          %6 = OpFunction %2 None %3
+          %7 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpPhi must not have void result type"));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_code_generator.cpp b/third_party/SPIRV-Tools/test/val/val_code_generator.cpp
index 62aae9c..f151f51 100644
--- a/third_party/SPIRV-Tools/test/val/val_code_generator.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_code_generator.cpp
@@ -32,13 +32,6 @@
 )";
 }
 
-std::string GetWebGPUShaderCapabilities() {
-  return R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-)";
-}
-
 std::string GetDefaultShaderTypes() {
   return R"(
 %void = OpTypeVoid
@@ -115,55 +108,15 @@
 %f32vec3arr3 = OpTypeArray %f32vec3 %u32_3
 %f32vec4arr3 = OpTypeArray %f32vec4 %u32_3
 %f64vec4arr3 = OpTypeArray %f64vec4 %u32_3
-)";
-}
 
-std::string GetWebGPUShaderTypes() {
-  return R"(
-%void = OpTypeVoid
-%func = OpTypeFunction %void
-%bool = OpTypeBool
-%f32 = OpTypeFloat 32
-%u32 = OpTypeInt 32 0
-%f32vec2 = OpTypeVector %f32 2
-%f32vec3 = OpTypeVector %f32 3
-%f32vec4 = OpTypeVector %f32 4
-%u32vec2 = OpTypeVector %u32 2
-%u32vec3 = OpTypeVector %u32 3
-%u32vec4 = OpTypeVector %u32 4
-
-%f32_0 = OpConstant %f32 0
-%f32_1 = OpConstant %f32 1
-%f32_2 = OpConstant %f32 2
-%f32_3 = OpConstant %f32 3
-%f32_4 = OpConstant %f32 4
-%f32_h = OpConstant %f32 0.5
-%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
-%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
-%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
-%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
-%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
-%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
-
-%u32_0 = OpConstant %u32 0
-%u32_1 = OpConstant %u32 1
-%u32_2 = OpConstant %u32 2
-%u32_3 = OpConstant %u32 3
-%u32_4 = OpConstant %u32 4
-
-%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
-%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
-%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
-
-%u32arr2 = OpTypeArray %u32 %u32_2
-%u32arr3 = OpTypeArray %u32 %u32_3
-%u32arr4 = OpTypeArray %u32 %u32_4
-%f32arr2 = OpTypeArray %f32 %u32_2
-%f32arr3 = OpTypeArray %f32 %u32_3
-%f32arr4 = OpTypeArray %f32 %u32_4
-
-%f32vec3arr3 = OpTypeArray %f32vec3 %u32_3
-%f32vec4arr3 = OpTypeArray %f32vec4 %u32_3
+%f32mat22 = OpTypeMatrix %f32vec2 2
+%f32mat23 = OpTypeMatrix %f32vec2 3
+%f32mat32 = OpTypeMatrix %f32vec3 2
+%f32mat33 = OpTypeMatrix %f32vec3 3
+%f64mat22 = OpTypeMatrix %f64vec2 2
+%f32mat34 = OpTypeMatrix %f32vec3 4
+%f32mat43 = OpTypeMatrix %f32vec4 3
+%f32mat44 = OpTypeMatrix %f32vec4 4
 )";
 }
 
@@ -177,15 +130,6 @@
   return generator;
 }
 
-CodeGenerator CodeGenerator::GetWebGPUShaderCodeGenerator() {
-  CodeGenerator generator;
-  generator.capabilities_ = GetWebGPUShaderCapabilities();
-  generator.memory_model_ = "OpMemoryModel Logical VulkanKHR\n";
-  generator.extensions_ = "OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
-  generator.types_ = GetWebGPUShaderTypes();
-  return generator;
-}
-
 std::string CodeGenerator::Build() const {
   std::ostringstream ss;
 
diff --git a/third_party/SPIRV-Tools/test/val/val_code_generator.h b/third_party/SPIRV-Tools/test/val/val_code_generator.h
index e580ddf..c69deee 100644
--- a/third_party/SPIRV-Tools/test/val/val_code_generator.h
+++ b/third_party/SPIRV-Tools/test/val/val_code_generator.h
@@ -31,7 +31,6 @@
 class CodeGenerator {
  public:
   static CodeGenerator GetDefaultShaderCodeGenerator();
-  static CodeGenerator GetWebGPUShaderCodeGenerator();
 
   std::string Build() const;
 
diff --git a/third_party/SPIRV-Tools/test/val/val_composites_test.cpp b/third_party/SPIRV-Tools/test/val/val_composites_test.cpp
index e970562..bf7caa9 100644
--- a/third_party/SPIRV-Tools/test/val/val_composites_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_composites_test.cpp
@@ -1994,6 +1994,36 @@
               HasSubstr("Cannot transpose matrices of 16-bit floats"));
 }
 
+TEST_F(ValidateComposites, CopyObjectVoid) {
+  const std::string spirv = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpName %4 "main"
+               OpName %6 "foo("
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpFunctionCall %2 %6
+         %20 = OpCopyObject %2 %8
+               OpReturn
+               OpFunctionEnd
+          %6 = OpFunction %2 None %3
+          %7 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpCopyObject cannot have void result type"));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_data_test.cpp b/third_party/SPIRV-Tools/test/val/val_data_test.cpp
index 30afd03..1d4c0e0 100644
--- a/third_party/SPIRV-Tools/test/val/val_data_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_data_test.cpp
@@ -36,24 +36,6 @@
          cap + " OpMemoryModel Logical GLSL450 ";
 }
 
-std::string WebGPUHeaderWith(std::string cap) {
-  return R"(
-OpCapability Shader
-OpCapability )" +
-         cap + R"(
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-)";
-}
-
-std::string webgpu_header = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-)";
-
 std::string header = R"(
      OpCapability Shader
      OpCapability Linkage
@@ -267,18 +249,6 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
 }
 
-TEST_F(ValidateData, webgpu_int8_bad) {
-  std::string str = WebGPUHeaderWith("Int8") + "%2 = OpTypeInt 8 0";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Capability Int8 is not allowed by WebGPU specification (or "
-                "requires extension)\n"
-                "  OpCapability Int8\n"));
-}
-
 TEST_F(ValidateData, int16_good) {
   std::string str = header_with_int16 + "%2 = OpTypeInt 16 1";
   CompileSuccessfully(str.c_str());
@@ -338,34 +308,6 @@
   EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error));
 }
 
-TEST_F(ValidateData, webgpu_int16_bad) {
-  std::string str = WebGPUHeaderWith("Int16") + "%2 = OpTypeInt 16 1";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Capability Int16 is not allowed by WebGPU specification (or "
-                "requires extension)\n"
-                "  OpCapability Int16\n"));
-}
-
-TEST_F(ValidateData, webgpu_int32_good) {
-  std::string str = webgpu_header + R"(
-          OpEntryPoint Fragment %func "func"
-          OpExecutionMode %func OriginUpperLeft
-%uint_t = OpTypeInt 32 0
-  %void = OpTypeVoid
-%func_t = OpTypeFunction %void
-  %func = OpFunction %void None %func_t
-     %1 = OpLabel
-          OpReturn
-          OpFunctionEnd
-)";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
 TEST_F(ValidateData, int64_good) {
   std::string str = header_with_int64 + "%2 = OpTypeInt 64 1";
   CompileSuccessfully(str.c_str());
@@ -379,18 +321,6 @@
   EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error));
 }
 
-TEST_F(ValidateData, webgpu_int64_bad) {
-  std::string str = WebGPUHeaderWith("Int64") + "%2 = OpTypeInt 64 1";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Capability Int64 is not allowed by WebGPU specification (or "
-                "requires extension)\n"
-                "  OpCapability Int64\n"));
-}
-
 // Number of bits in an integer may be only one of: {8,16,32,64}
 TEST_F(ValidateData, int_invalid_num_bits) {
   std::string str = header + "%2 = OpTypeInt 48 1";
@@ -418,34 +348,6 @@
   EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error));
 }
 
-TEST_F(ValidateData, webgpu_float16_bad) {
-  std::string str = WebGPUHeaderWith("Float16") + "%2 = OpTypeFloat 16";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Capability Float16 is not allowed by WebGPU specification (or "
-                "requires extension)\n"
-                "  OpCapability Float16\n"));
-}
-
-TEST_F(ValidateData, webgpu_float32_good) {
-  std::string str = webgpu_header + R"(
-           OpEntryPoint Fragment %func "func"
-           OpExecutionMode %func OriginUpperLeft
-%float_t = OpTypeFloat 32
-   %void = OpTypeVoid
- %func_t = OpTypeFunction %void
-   %func = OpFunction %void None %func_t
-      %1 = OpLabel
-           OpReturn
-           OpFunctionEnd
-)";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
 TEST_F(ValidateData, float64_good) {
   std::string str = header_with_float64 + "%2 = OpTypeFloat 64";
   CompileSuccessfully(str.c_str());
@@ -459,18 +361,6 @@
   EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error));
 }
 
-TEST_F(ValidateData, webgpu_float64_bad) {
-  std::string str = WebGPUHeaderWith("Float64") + "%2 = OpTypeFloat 64";
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Capability Float64 is not allowed by WebGPU specification (or "
-                "requires extension)\n"
-                "  OpCapability Float64\n"));
-}
-
 // Number of bits in a float may be only one of: {16,32,64}
 TEST_F(ValidateData, float_invalid_num_bits) {
   std::string str = header + "%2 = OpTypeFloat 48";
@@ -497,7 +387,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 3[%3] has not been defined"));
+              HasSubstr("Operand 3[%3] requires a previous definition"));
 }
 
 TEST_F(ValidateData, matrix_bad_column_type) {
@@ -882,66 +772,58 @@
                         "OpTypeStruct %_runtimearr_uint %uint\n"));
 }
 
-TEST_F(ValidateData, webgpu_RTA_array_at_end_of_struct) {
-  std::string str = R"(
-              OpCapability Shader
-              OpCapability VulkanMemoryModelKHR
-              OpExtension "SPV_KHR_vulkan_memory_model"
-              OpMemoryModel Logical VulkanKHR
-              OpEntryPoint Fragment %func "func"
-              OpExecutionMode %func OriginUpperLeft
-              OpDecorate %array_t ArrayStride 4
-              OpMemberDecorate %struct_t 0 Offset 0
-              OpMemberDecorate %struct_t 1 Offset 4
-              OpDecorate %struct_t Block
-     %uint_t = OpTypeInt 32 0
-   %array_t = OpTypeRuntimeArray %uint_t
-  %struct_t = OpTypeStruct %uint_t %array_t
-%struct_ptr = OpTypePointer StorageBuffer %struct_t
-         %2 = OpVariable %struct_ptr StorageBuffer
-      %void = OpTypeVoid
-    %func_t = OpTypeFunction %void
-      %func = OpFunction %void None %func_t
-         %1 = OpLabel
-              OpReturn
-              OpFunctionEnd
+TEST_F(ValidateData, TypeForwardReference) {
+  std::string test = R"(
+OpCapability Shader
+OpCapability PhysicalStorageBufferAddresses
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpTypeForwardPointer %1 PhysicalStorageBuffer
+%2 = OpTypeStruct
+%3 = OpTypeRuntimeArray %1
+%1 = OpTypePointer PhysicalStorageBuffer %2
 )";
 
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
 }
 
-TEST_F(ValidateData, webgpu_RTA_not_at_end_of_struct) {
-  std::string str = R"(
-              OpCapability Shader
-              OpCapability VulkanMemoryModelKHR
-              OpExtension "SPV_KHR_vulkan_memory_model"
-              OpMemoryModel Logical VulkanKHR
-              OpEntryPoint Fragment %func "func"
-              OpExecutionMode %func OriginUpperLeft
-              OpDecorate %array_t ArrayStride 4
-              OpMemberDecorate %struct_t 0 Offset 0
-              OpMemberDecorate %struct_t 1 Offset 4
-              OpDecorate %struct_t Block
-     %uint_t = OpTypeInt 32 0
-   %array_t = OpTypeRuntimeArray %uint_t
-  %struct_t = OpTypeStruct %array_t %uint_t
-%struct_ptr = OpTypePointer StorageBuffer %struct_t
-         %2 = OpVariable %struct_ptr StorageBuffer
-      %void = OpTypeVoid
-    %func_t = OpTypeFunction %void
-      %func = OpFunction %void None %func_t
-         %1 = OpLabel
-              OpReturn
-              OpFunctionEnd
+TEST_F(ValidateData, VulkanTypeForwardStorageClass) {
+  std::string test = R"(
+OpCapability Shader
+OpCapability PhysicalStorageBufferAddresses
+OpMemoryModel Logical GLSL450
+OpTypeForwardPointer %1 Uniform
+%2 = OpTypeStruct
+%3 = OpTypeRuntimeArray %1
+%1 = OpTypePointer Uniform %2
 )";
 
-  CompileSuccessfully(str.c_str(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  CompileSuccessfully(test, SPV_ENV_VULKAN_1_2);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("In WebGPU, OpTypeRuntimeArray must only be used for "
-                        "the last member of an OpTypeStruct\n  %_struct_3 = "
-                        "OpTypeStruct %_runtimearr_uint %uint\n"));
+              AnyVUID("VUID-StandaloneSpirv-OpTypeForwardPointer-04711"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("In Vulkan, OpTypeForwardPointer must have "
+                        "a storage class of PhysicalStorageBuffer."));
+}
+
+TEST_F(ValidateData, TypeForwardReferenceMustBeForwardPointer) {
+  std::string test = R"(
+OpCapability Shader
+OpCapability PhysicalStorageBufferAddresses
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%1 = OpTypeStruct
+%2 = OpTypeRuntimeArray %3
+%3 = OpTypePointer PhysicalStorageBuffer %1
+)";
+
+  CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand 3[%_ptr_PhysicalStorageBuffer__struct_1] "
+                        "requires a previous definition"));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
index e646162..8fe1aa6 100644
--- a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
@@ -42,8 +42,8 @@
 };
 
 using ValidateDecorations = spvtest::ValidateBase<bool>;
-using ValidateWebGPUCombineDecorationResult =
-    spvtest::ValidateBase<std::tuple<const char*, TestResult>>;
+using ValidateVulkanCombineDecorationResult =
+    spvtest::ValidateBase<std::tuple<const char*, const char*, TestResult>>;
 
 TEST_F(ValidateDecorations, ValidateOpDecorateRegistration) {
   std::string spirv = R"(
@@ -163,44 +163,6 @@
   EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations));
 }
 
-TEST_F(ValidateDecorations, WebGPUOpDecorationGroupBad) {
-  std::string spirv = R"(
-               OpCapability Shader
-               OpCapability VulkanMemoryModelKHR
-               OpExtension "SPV_KHR_vulkan_memory_model"
-               OpMemoryModel Logical VulkanKHR
-               OpDecorate %1 DescriptorSet 0
-               OpDecorate %1 NonWritable
-               OpDecorate %1 Restrict
-          %1 = OpDecorationGroup
-               OpGroupDecorate %1 %2 %3
-               OpGroupDecorate %1 %4
-  %float = OpTypeFloat 32
-%_runtimearr_float = OpTypeRuntimeArray %float
-  %_struct_9 = OpTypeStruct %_runtimearr_float
-%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
-         %2 = OpVariable %_ptr_Uniform__struct_9 Uniform
- %_struct_10 = OpTypeStruct %_runtimearr_float
-%_ptr_Uniform__struct_10 = OpTypePointer Uniform %_struct_10
-         %3 = OpVariable %_ptr_Uniform__struct_10 Uniform
- %_struct_11 = OpTypeStruct %_runtimearr_float
-%_ptr_Uniform__struct_11 = OpTypePointer Uniform %_struct_11
-         %4 = OpVariable %_ptr_Uniform__struct_11 Uniform
-  )";
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpDecorationGroup is not allowed in the WebGPU "
-                        "execution environment.\n  %1 = OpDecorationGroup\n"));
-}
-
-// For WebGPU, OpGroupDecorate does not have a test case, because it requires
-// being preceded by OpDecorationGroup, which will cause a validation error.
-
-// For WebGPU, OpGroupMemberDecorate does not have a test case, because it
-// requires being preceded by OpDecorationGroup, which will cause a validation
-// error.
-
 TEST_F(ValidateDecorations, ValidateGroupMemberDecorateRegistration) {
   std::string spirv = R"(
                OpCapability Shader
@@ -4679,6 +4641,95 @@
                         "Object operand of an OpStore."));
 }
 
+TEST_F(ValidateDecorations, VulkanFPRoundingModeGood) {
+  std::string spirv = R"(
+               OpCapability Shader
+               OpCapability StorageBuffer16BitAccess
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %_
+               OpExecutionMode %main LocalSize 1 1 1
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpDecorate %ssbo Block
+               OpDecorate %_ DescriptorSet 0
+               OpDecorate %_ Binding 0
+               OpDecorate %17 FPRoundingMode RTE
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+%_ptr_Function_float = OpTypePointer Function %float
+    %float_1 = OpConstant %float 1
+       %half = OpTypeFloat 16
+       %ssbo = OpTypeStruct %half
+%_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
+          %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+          %b = OpVariable %_ptr_Function_float Function
+               OpStore %b %float_1
+         %16 = OpLoad %float %b
+         %17 = OpFConvert %half %16
+         %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
+               OpStore %19 %17
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
+}
+
+TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode) {
+  std::string spirv = R"(
+               OpCapability Shader
+               OpCapability StorageBuffer16BitAccess
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %_
+               OpExecutionMode %main LocalSize 1 1 1
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpDecorate %ssbo Block
+               OpDecorate %_ DescriptorSet 0
+               OpDecorate %_ Binding 0
+               OpDecorate %17 FPRoundingMode RTP
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+%_ptr_Function_float = OpTypePointer Function %float
+    %float_1 = OpConstant %float 1
+       %half = OpTypeFloat 16
+       %ssbo = OpTypeStruct %half
+%_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
+          %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+          %b = OpVariable %_ptr_Function_float Function
+               OpStore %b %float_1
+         %16 = OpLoad %float %b
+         %17 = OpFConvert %half %16
+         %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
+               OpStore %19 %17
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-FPRoundingMode-04675"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("In Vulkan, the FPRoundingMode mode must only by RTE or RTZ."));
+}
+
 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6299,11 +6350,12 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_P(ValidateWebGPUCombineDecorationResult, Decorate) {
+TEST_P(ValidateVulkanCombineDecorationResult, Decorate) {
   const char* const decoration = std::get<0>(GetParam());
-  const TestResult& test_result = std::get<1>(GetParam());
+  const char* const vuid = std::get<1>(GetParam());
+  const TestResult& test_result = std::get<2>(GetParam());
 
-  CodeGenerator generator = CodeGenerator::GetWebGPUShaderCodeGenerator();
+  CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
   generator.before_types_ = "OpDecorate %u32 ";
   generator.before_types_ += decoration;
   generator.before_types_ += "\n";
@@ -6313,52 +6365,24 @@
   entry_point.execution_model = "Vertex";
   generator.entry_points_.push_back(std::move(entry_point));
 
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
+  CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(test_result.validation_result,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  if (test_result.error_str != "") {
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
-  }
-}
-
-TEST_P(ValidateWebGPUCombineDecorationResult, DecorateMember) {
-  const char* const decoration = std::get<0>(GetParam());
-  const TestResult& test_result = std::get<1>(GetParam());
-
-  CodeGenerator generator = CodeGenerator::GetWebGPUShaderCodeGenerator();
-  generator.before_types_ = "OpMemberDecorate %struct_type 0 ";
-  generator.before_types_ += decoration;
-  generator.before_types_ += "\n";
-
-  generator.after_types_ = "%struct_type = OpTypeStruct %u32\n";
-
-  EntryPoint entry_point;
-  entry_point.name = "main";
-  entry_point.execution_model = "Vertex";
-  generator.entry_points_.push_back(std::move(entry_point));
-
-  CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(test_result.validation_result,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
+            ValidateInstructions(SPV_ENV_VULKAN_1_0));
   if (!test_result.error_str.empty()) {
     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
   }
+  if (vuid) {
+    EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
+  }
 }
 
 INSTANTIATE_TEST_SUITE_P(
-    DecorationCapabilityFailure, ValidateWebGPUCombineDecorationResult,
-    Combine(Values("CPacked", "Patch", "Sample", "Constant",
-                   "SaturatedConversion", "NonUniformEXT"),
-            Values(TestResult(SPV_ERROR_INVALID_CAPABILITY,
-                              "requires one of these capabilities"))));
-
-INSTANTIATE_TEST_SUITE_P(
-    DecorationAllowListFailure, ValidateWebGPUCombineDecorationResult,
-    Combine(Values("RelaxedPrecision", "BufferBlock", "GLSLShared",
-                   "GLSLPacked", "Invariant", "Volatile", "Coherent"),
+    DecorationAllowListFailure, ValidateVulkanCombineDecorationResult,
+    Combine(Values("GLSLShared", "GLSLPacked"),
+            Values("VUID-StandaloneSpirv-GLSLShared-04669"),
             Values(TestResult(
                 SPV_ERROR_INVALID_ID,
-                "is not valid for the WebGPU execution environment."))));
+                "is not valid for the Vulkan execution environment."))));
 
 TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) {
   std::string spirv = ShaderWithNonWritableTarget("%var_func");
diff --git a/third_party/SPIRV-Tools/test/val/val_fixtures.h b/third_party/SPIRV-Tools/test/val/val_fixtures.h
index 5635c78..acbe0e5 100644
--- a/third_party/SPIRV-Tools/test/val/val_fixtures.h
+++ b/third_party/SPIRV-Tools/test/val/val_fixtures.h
@@ -183,4 +183,43 @@
 
 }  // namespace spvtest
 
+// For Vulkan testing.
+// Allows test parameter test to list all possible VUIDs with a delimiter that
+// is then split here to check if one VUID was in the error message
+MATCHER_P(AnyVUID, vuid_set, "VUID from the set is in error message") {
+  // use space as delimiter because clang-format will properly line break VUID
+  // strings which is important the entire VUID is in a single line for script
+  // to scan
+  std::string delimiter = " ";
+  std::string token;
+  std::string vuids = std::string(vuid_set);
+  size_t position;
+
+  // Catch case were someone accidentally left spaces by trimming string
+  // clang-format off
+  vuids.erase(std::find_if(vuids.rbegin(), vuids.rend(), [](unsigned char c) {
+    return (c != ' ');
+  }).base(), vuids.end());
+  vuids.erase(vuids.begin(), std::find_if(vuids.begin(), vuids.end(), [](unsigned char c) {
+    return (c != ' ');
+  }));
+  // clang-format on
+
+  do {
+    position = vuids.find(delimiter);
+    if (position != std::string::npos) {
+      token = vuids.substr(0, position);
+      vuids.erase(0, position + delimiter.length());
+    } else {
+      token = vuids.substr(0);  // last item
+    }
+
+    // arg contains diagnostic message
+    if (arg.find(token) != std::string::npos) {
+      return true;
+    }
+  } while (position != std::string::npos);
+  return false;
+}
+
 #endif  // TEST_VAL_VAL_FIXTURES_H_
diff --git a/third_party/SPIRV-Tools/test/val/val_id_test.cpp b/third_party/SPIRV-Tools/test/val/val_id_test.cpp
index adea563..c65d171 100644
--- a/third_party/SPIRV-Tools/test/val/val_id_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_id_test.cpp
@@ -411,10 +411,10 @@
 }
 TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
-     OpEntryPoint GLCompute %3 ""
-%1 = OpTypeVoid
-%2 = OpTypeFunction %1 %1
-%3 = OpFunction %1 None %2
+     OpEntryPoint GLCompute %1 ""
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2 %2
+%1 = OpFunction %2 None %3
 %4 = OpLabel
      OpReturn
      OpFunctionEnd)";
@@ -426,11 +426,11 @@
 }
 TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
-     OpEntryPoint GLCompute %3 ""
-%1 = OpTypeInt 32 0
-%ret = OpConstant %1 0
-%2 = OpTypeFunction %1
-%3 = OpFunction %1 None %2
+     OpEntryPoint GLCompute %1 ""
+%2 = OpTypeInt 32 0
+%ret = OpConstant %2 0
+%3 = OpTypeFunction %2
+%1 = OpFunction %2 None %3
 %4 = OpLabel
      OpReturnValue %ret
      OpFunctionEnd)";
@@ -440,6 +440,45 @@
               HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
                         "return type is not void."));
 }
+TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBadInVulkan) {
+  std::string spirv = R"(
+     OpCapability Shader
+     OpMemoryModel Logical GLSL450
+     OpEntryPoint GLCompute %1 ""
+%2 = OpTypeVoid
+%3 = OpTypeFunction %2 %2
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+     OpReturn
+     OpFunctionEnd)";
+  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04633"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
+                        "parameter count is not zero"));
+}
+TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBadInVulkan) {
+  std::string spirv = R"(
+     OpCapability Shader
+     OpMemoryModel Logical GLSL450
+     OpEntryPoint GLCompute %1 ""
+%2 = OpTypeInt 32 0
+%ret = OpConstant %2 0
+%3 = OpTypeFunction %2
+%1 = OpFunction %2 None %3
+%4 = OpLabel
+     OpReturnValue %ret
+     OpFunctionEnd)";
+  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-None-04633"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
+                        "return type is not void."));
+}
 
 TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
   std::string spirv = R"(
@@ -915,31 +954,6 @@
   }
 }
 
-TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding0InWebGPU) {
-  env_ = SPV_ENV_WEBGPU_0;
-  const int width = GetParam();
-  // WebGPU only has 32 bit integers.
-  if (width != 32) return;
-  const int max_int_width = 32;
-  const auto module = CompileSuccessfully(MakeArrayLength(
-      big_num_ending_0(width), kUnsigned, width, max_int_width, true));
-  EXPECT_EQ(SPV_SUCCESS, Val(module));
-}
-
-TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding1InWebGPU) {
-  env_ = SPV_ENV_WEBGPU_0;
-  const int width = GetParam();
-  // WebGPU only has 32 bit integers.
-  if (width != 32) return;
-  const int max_int_width = 32;
-  const auto module = CompileSuccessfully(MakeArrayLength(
-      big_num_ending_1(width), kUnsigned, width, max_int_width, true));
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(module,
-                "OpTypeArray Length <id> '3\\[%.*\\]' size exceeds max value "
-                "2147483648 permitted by WebGPU: got 2147483649"));
-}
-
 // The only valid widths for integers are 8, 16, 32, and 64.
 // Since the Int8 capability requires the Kernel capability, and the Kernel
 // capability prohibits usage of signed integers, we can skip 8-bit integers
@@ -2749,9 +2763,13 @@
 %6 = OpVariable %3 Uniform
 %7 = OpFunction %1 None %4
 %8 = OpLabel
-%9 = OpUndef %1
+%9 = OpFunctionCall %1 %10
      OpStore %6 %9
      OpReturn
+     OpFunctionEnd
+%10 = OpFunction %1 None %4
+%11 = OpLabel
+      OpReturn
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
@@ -4688,39 +4706,6 @@
           "size of 5."));
 }
 
-TEST_F(ValidateIdWithMessage, WebGPUOpVectorShuffle0xFFFFFFFFLiteralBad) {
-  std::string spirv = R"(
-    OpCapability Shader
-    OpCapability VulkanMemoryModelKHR
-    OpExtension "SPV_KHR_vulkan_memory_model"
-    OpMemoryModel Logical VulkanKHR
-%float = OpTypeFloat 32
-%vec2 = OpTypeVector %float 2
-%vec3 = OpTypeVector %float 3
-%vec4 = OpTypeVector %float 4
-%ptr_vec2 = OpTypePointer Function %vec2
-%ptr_vec3 = OpTypePointer Function %vec3
-%float_1 = OpConstant %float 1
-%float_2 = OpConstant %float 2
-%1 = OpConstantComposite %vec2 %float_2 %float_1
-%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
-%3 = OpTypeFunction %vec4
-%4 = OpFunction %vec4 None %3
-%5 = OpLabel
-%var = OpVariable %ptr_vec2 Function %1
-%var2 = OpVariable %ptr_vec3 Function %2
-%6 = OpLoad %vec2 %var
-%7 = OpLoad %vec3 %var2
-%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0xffffffff
-     OpReturnValue %8
-     OpFunctionEnd)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Component literal at operand 3 cannot be 0xFFFFFFFF in"
-                        " WebGPU execution environment."));
-}
-
 // TODO: OpCompositeConstruct
 // TODO: OpCompositeExtract
 // TODO: OpCompositeInsert
diff --git a/third_party/SPIRV-Tools/test/val/val_image_test.cpp b/third_party/SPIRV-Tools/test/val/val_image_test.cpp
index 2e84a29..ce4bf1b 100644
--- a/third_party/SPIRV-Tools/test/val/val_image_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_image_test.cpp
@@ -66,9 +66,9 @@
 %uniform_image_f32_1d_0001
 %uniform_image_f32_1d_0002_rgba32f
 %uniform_image_f32_2d_0001
-%uniform_image_f32_2d_0010
+%uniform_image_f32_2d_0011 ; multisampled sampled
 %uniform_image_u32_2d_0001
-%uniform_image_u32_2d_0000
+%uniform_image_u32_2d_0002
 %uniform_image_s32_3d_0001
 %uniform_image_f32_2d_0002
 %uniform_image_s32_2d_0002
@@ -99,12 +99,12 @@
 OpDecorate %uniform_image_f32_1d_0002_rgba32f Binding 1
 OpDecorate %uniform_image_f32_2d_0001 DescriptorSet 0
 OpDecorate %uniform_image_f32_2d_0001 Binding 2
-OpDecorate %uniform_image_f32_2d_0010 DescriptorSet 0
-OpDecorate %uniform_image_f32_2d_0010 Binding 3
+OpDecorate %uniform_image_f32_2d_0011 DescriptorSet 0
+OpDecorate %uniform_image_f32_2d_0011 Binding 3
 OpDecorate %uniform_image_u32_2d_0001 DescriptorSet 1
 OpDecorate %uniform_image_u32_2d_0001 Binding 0
-OpDecorate %uniform_image_u32_2d_0000 DescriptorSet 1
-OpDecorate %uniform_image_u32_2d_0000 Binding 1
+OpDecorate %uniform_image_u32_2d_0002 DescriptorSet 1
+OpDecorate %uniform_image_u32_2d_0002 Binding 1
 OpDecorate %uniform_image_s32_3d_0001 DescriptorSet 1
 OpDecorate %uniform_image_s32_3d_0001 Binding 2
 OpDecorate %uniform_image_f32_2d_0002 DescriptorSet 1
@@ -133,6 +133,7 @@
 %u32 = OpTypeInt 32 0
 %s32 = OpTypeInt 32 1
 %u64 = OpTypeInt 64 0
+%s64 = OpTypeInt 64 1
 %s32vec2 = OpTypeVector %s32 2
 %u32vec2 = OpTypeVector %u32 2
 %f32vec2 = OpTypeVector %f32 2
@@ -223,27 +224,25 @@
 %type_image_f32_1d_0002_rgba32f = OpTypeImage %f32 1D 0 0 0 2 Rgba32f
 %ptr_image_f32_1d_0002_rgba32f = OpTypePointer UniformConstant %type_image_f32_1d_0002_rgba32f
 %uniform_image_f32_1d_0002_rgba32f = OpVariable %ptr_image_f32_1d_0002_rgba32f UniformConstant
-%type_sampled_image_f32_1d_0002_rgba32f = OpTypeSampledImage %type_image_f32_1d_0002_rgba32f
 
 %type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
 %ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
 %uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant
 %type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001
 
-%type_image_f32_2d_0010 = OpTypeImage %f32 2D 0 0 1 0 Unknown
-%ptr_image_f32_2d_0010 = OpTypePointer UniformConstant %type_image_f32_2d_0010
-%uniform_image_f32_2d_0010 = OpVariable %ptr_image_f32_2d_0010 UniformConstant
-%type_sampled_image_f32_2d_0010 = OpTypeSampledImage %type_image_f32_2d_0010
+%type_image_f32_2d_0011 = OpTypeImage %f32 2D 0 0 1 1 Unknown
+%ptr_image_f32_2d_0011 = OpTypePointer UniformConstant %type_image_f32_2d_0011
+%uniform_image_f32_2d_0011 = OpVariable %ptr_image_f32_2d_0011 UniformConstant
+%type_sampled_image_f32_2d_0011 = OpTypeSampledImage %type_image_f32_2d_0011
 
 %type_image_u32_2d_0001 = OpTypeImage %u32 2D 0 0 0 1 Unknown
 %ptr_image_u32_2d_0001 = OpTypePointer UniformConstant %type_image_u32_2d_0001
 %uniform_image_u32_2d_0001 = OpVariable %ptr_image_u32_2d_0001 UniformConstant
 %type_sampled_image_u32_2d_0001 = OpTypeSampledImage %type_image_u32_2d_0001
 
-%type_image_u32_2d_0000 = OpTypeImage %u32 2D 0 0 0 0 Unknown
-%ptr_image_u32_2d_0000 = OpTypePointer UniformConstant %type_image_u32_2d_0000
-%uniform_image_u32_2d_0000 = OpVariable %ptr_image_u32_2d_0000 UniformConstant
-%type_sampled_image_u32_2d_0000 = OpTypeSampledImage %type_image_u32_2d_0000
+%type_image_u32_2d_0002 = OpTypeImage %u32 2D 0 0 0 2 Unknown
+%ptr_image_u32_2d_0002 = OpTypePointer UniformConstant %type_image_u32_2d_0002
+%uniform_image_u32_2d_0002 = OpVariable %ptr_image_u32_2d_0002 UniformConstant
 
 %type_image_s32_3d_0001 = OpTypeImage %s32 3D 0 0 0 1 Unknown
 %ptr_image_s32_3d_0001 = OpTypePointer UniformConstant %type_image_s32_3d_0001
@@ -253,17 +252,14 @@
 %type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Unknown
 %ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
 %uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
-%type_sampled_image_f32_2d_0002 = OpTypeSampledImage %type_image_f32_2d_0002
 
 %type_image_s32_2d_0002 = OpTypeImage %s32 2D 0 0 0 2 Unknown
 %ptr_image_s32_2d_0002 = OpTypePointer UniformConstant %type_image_s32_2d_0002
 %uniform_image_s32_2d_0002 = OpVariable %ptr_image_s32_2d_0002 UniformConstant
-%type_sampled_image_s32_2d_0002 = OpTypeSampledImage %type_image_s32_2d_0002
 
 %type_image_f32_spd_0002 = OpTypeImage %f32 SubpassData 0 0 0 2 Unknown
 %ptr_image_f32_spd_0002 = OpTypePointer UniformConstant %type_image_f32_spd_0002
 %uniform_image_f32_spd_0002 = OpVariable %ptr_image_f32_spd_0002 UniformConstant
-%type_sampled_image_f32_spd_0002 = OpTypeSampledImage %type_image_f32_spd_0002
 
 %type_image_f32_3d_0111 = OpTypeImage %f32 3D 0 1 1 1 Unknown
 %ptr_image_f32_3d_0111 = OpTypePointer UniformConstant %type_image_f32_3d_0111
@@ -278,7 +274,6 @@
 %type_image_f32_cube_0102_rgba32f = OpTypeImage %f32 Cube 0 1 0 2 Rgba32f
 %ptr_image_f32_cube_0102_rgba32f = OpTypePointer UniformConstant %type_image_f32_cube_0102_rgba32f
 %uniform_image_f32_cube_0102_rgba32f = OpVariable %ptr_image_f32_cube_0102_rgba32f UniformConstant
-%type_sampled_image_f32_cube_0102_rgba32f = OpTypeSampledImage %type_image_f32_cube_0102_rgba32f
 
 %type_sampler = OpTypeSampler
 %ptr_sampler = OpTypePointer UniformConstant %type_sampler
@@ -311,7 +306,6 @@
 %type_image_void_2d_0002 = OpTypeImage %void 2D 0 0 0 2 Unknown
 %ptr_image_void_2d_0002 = OpTypePointer UniformConstant %type_image_void_2d_0002
 %uniform_image_void_2d_0002 = OpVariable %ptr_image_void_2d_0002 UniformConstant
-%type_sampled_image_void_2d_0002 = OpTypeSampledImage %type_image_void_2d_0002
 
 %type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
 %ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
@@ -400,15 +394,15 @@
 %uniform_image_f32_2d_0001 = OpVariable %ptr_image_f32_2d_0001 UniformConstant
 %type_sampled_image_f32_2d_0001 = OpTypeSampledImage %type_image_f32_2d_0001
 
-%type_image_f32_2d_0010 = OpTypeImage %f32 2D 0 0 1 0 Unknown
-%ptr_image_f32_2d_0010 = OpTypePointer UniformConstant %type_image_f32_2d_0010
-%uniform_image_f32_2d_0010 = OpVariable %ptr_image_f32_2d_0010 UniformConstant
-%type_sampled_image_f32_2d_0010 = OpTypeSampledImage %type_image_f32_2d_0010
+%type_image_f32_2d_0011 = OpTypeImage %f32 2D 0 0 1 1 Unknown
+%ptr_image_f32_2d_0011 = OpTypePointer UniformConstant %type_image_f32_2d_0011
+%uniform_image_f32_2d_0011 = OpVariable %ptr_image_f32_2d_0011 UniformConstant
+%type_sampled_image_f32_2d_0011 = OpTypeSampledImage %type_image_f32_2d_0011
 
-%type_image_f32_3d_0010 = OpTypeImage %f32 3D 0 0 1 0 Unknown
-%ptr_image_f32_3d_0010 = OpTypePointer UniformConstant %type_image_f32_3d_0010
-%uniform_image_f32_3d_0010 = OpVariable %ptr_image_f32_3d_0010 UniformConstant
-%type_sampled_image_f32_3d_0010 = OpTypeSampledImage %type_image_f32_3d_0010
+%type_image_f32_3d_0011 = OpTypeImage %f32 3D 0 0 1 1 Unknown
+%ptr_image_f32_3d_0011 = OpTypePointer UniformConstant %type_image_f32_3d_0011
+%uniform_image_f32_3d_0011 = OpVariable %ptr_image_f32_3d_0011 UniformConstant
+%type_sampled_image_f32_3d_0011 = OpTypeSampledImage %type_image_f32_3d_0011
 
 %type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
 %ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
@@ -431,12 +425,35 @@
   return ss.str();
 }
 
+std::string GetKernelHeader() {
+  return R"(
+  OpCapability Kernel
+  OpCapability Addresses
+  OpCapability Linkage
+  OpMemoryModel Physical32 OpenCL
+  %void = OpTypeVoid
+  %func = OpTypeFunction %void
+  %f32 = OpTypeFloat 32
+  %u32 = OpTypeInt 32 0
+  )";
+}
+
+std::string TrivialMain() {
+  return R"(
+  %main = OpFunction %void None %func
+  %entry = OpLabel
+  OpReturn
+  OpFunctionEnd
+  )";
+}
+
 std::string GetShaderHeader(const std::string& capabilities_and_extensions = "",
                             bool include_entry_point = true) {
   std::ostringstream ss;
   ss << R"(
 OpCapability Shader
 OpCapability Int64
+OpCapability Float64
 )";
 
   ss << capabilities_and_extensions;
@@ -457,9 +474,11 @@
 %func = OpTypeFunction %void
 %bool = OpTypeBool
 %f32 = OpTypeFloat 32
+%f64 = OpTypeFloat 64
 %u32 = OpTypeInt 32 0
 %u64 = OpTypeInt 64 0
 %s32 = OpTypeInt 32 1
+%s64 = OpTypeInt 64 1
 )";
 
   return ss.str();
@@ -481,8 +500,7 @@
 TEST_F(ValidateImage, TypeImageVoidSampledTypeVulkan) {
   const std::string code = GetShaderHeader() + R"(
 %img_type = OpTypeImage %void 2D 0 0 0 1 Unknown
-%void_func = OpTypeFunction %void
-%main = OpFunction %void None %void_func
+%main = OpFunction %void None %func
 %main_lab = OpLabel
 OpReturn
 OpFunctionEnd
@@ -492,15 +510,131 @@
   CompileSuccessfully(code, env);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Expected Sampled Type to be a 32-bit int "
-                        "or float scalar type for Vulkan environment"));
+              AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04656"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Sampled Type to be a 32-bit int, 64-bit int "
+                        "or 32-bit float scalar type for Vulkan environment"));
+}
+
+TEST_F(ValidateImage, TypeImageU32SampledTypeVulkan) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %u32 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImageI32SampledTypeVulkan) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %s32 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImageI64SampledTypeNoCapabilityVulkan) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %s64 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Capability Int64ImageEXT is required when using "
+                        "Sampled Type of 64-bit int"));
+}
+
+TEST_F(ValidateImage, TypeImageI64SampledTypeVulkan) {
+  const std::string code = GetShaderHeader(
+                               "OpCapability Int64ImageEXT\nOpExtension "
+                               "\"SPV_EXT_shader_image_int64\"\n") +
+                           R"(
+%img_type = OpTypeImage %s64 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImageU64SampledTypeNoCapabilityVulkan) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %u64 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Capability Int64ImageEXT is required when using "
+                        "Sampled Type of 64-bit int"));
 }
 
 TEST_F(ValidateImage, TypeImageU64SampledTypeVulkan) {
-  const std::string code = GetShaderHeader() + R"(
+  const std::string code = GetShaderHeader(
+                               "OpCapability Int64ImageEXT\nOpExtension "
+                               "\"SPV_EXT_shader_image_int64\"\n") +
+                           R"(
 %img_type = OpTypeImage %u64 2D 0 0 0 1 Unknown
-%void_func = OpTypeFunction %void
-%main = OpFunction %void None %void_func
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImageF32SampledTypeVulkan) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %f32 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImageF64SampledTypeVulkan) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %f64 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
 %main_lab = OpLabel
 OpReturn
 OpFunctionEnd
@@ -510,8 +644,32 @@
   CompileSuccessfully(code, env);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Expected Sampled Type to be a 32-bit int "
-                        "or float scalar type for Vulkan environment"));
+              AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04656"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Sampled Type to be a 32-bit int, 64-bit int "
+                        "or 32-bit float scalar type for Vulkan environment"));
+}
+
+TEST_F(ValidateImage, TypeImageF64SampledTypeWithInt64Vulkan) {
+  const std::string code = GetShaderHeader(
+                               "OpCapability Int64ImageEXT\nOpExtension "
+                               "\"SPV_EXT_shader_image_int64\"\n") +
+                           R"(
+%img_type = OpTypeImage %f64 2D 0 0 0 1 Unknown
+%main = OpFunction %void None %func
+%main_lab = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(code, env);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04656"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Sampled Type to be a 32-bit int, 64-bit int "
+                        "or 32-bit float scalar type for Vulkan environment"));
 }
 
 TEST_F(ValidateImage, TypeImageWrongDepth) {
@@ -571,6 +729,83 @@
               HasSubstr("Dim SubpassData requires Sampled to be 2"));
 }
 
+TEST_F(ValidateImage, TypeImage_OpenCL_Sampled0_OK) {
+  const std::string code = GetKernelHeader() + R"(
+%img_type = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_1));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImage_OpenCL_Sampled1_Invalid) {
+  const std::string code = GetKernelHeader() + R"(
+%img_type = OpTypeImage %void 2D 0 0 0 1 Unknown ReadOnly
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampled must be 0 in the OpenCL environment."));
+}
+
+TEST_F(ValidateImage, TypeImage_OpenCL_Sampled2_Invalid) {
+  const std::string code = GetKernelHeader() + R"(
+%img_type = OpTypeImage %void 2D 0 0 0 2 Unknown ReadOnly
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampled must be 0 in the OpenCL environment."));
+}
+
+TEST_F(ValidateImage, TypeImage_OpenCL_AccessQualifierMissing) {
+  const std::string code = GetKernelHeader() + R"(
+%img_type = OpTypeImage %void 2D 0 0 0 0 Unknown
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_2_1));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("In the OpenCL environment, the optional Access "
+                        "Qualifier must be present"));
+}
+
+TEST_F(ValidateImage, TypeImage_Vulkan_Sampled1_OK) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %f32 2D 0 0 0 1 Unknown
+)" + TrivialMain();
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImage_Vulkan_Sampled2_OK) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
+)" + TrivialMain();
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImage_Vulkan_Sampled0_Invalid) {
+  const std::string code = GetShaderHeader() + R"(
+%img_type = OpTypeImage %f32 2D 0 0 0 0 Unknown
+)" + TrivialMain();
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpTypeImage-04657"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampled must be 1 or 2 in the Vulkan environment."));
+}
+
 TEST_F(ValidateImage, TypeImageWrongFormatForSubpassData) {
   const std::string code =
       GetShaderHeader("OpCapability InputAttachment\n", false) +
@@ -584,7 +819,44 @@
               HasSubstr("Dim SubpassData requires format Unknown"));
 }
 
-TEST_F(ValidateImage, TypeSampledImageNotImage) {
+TEST_F(ValidateImage, TypeImageMultisampleStorageImage_MissingCapability) {
+  const std::string code = GetShaderHeader("", false) +
+                           R"(
+%img_type = OpTypeImage %f32 2D 0 0 1 2 Rgba32f
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()) << code;
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Capability StorageImageMultisample is required when "
+                        "using multisampled storage image"));
+}
+
+TEST_F(ValidateImage, TypeImageMultisampleStorageImage_UsesCapability) {
+  const std::string code =
+      GetShaderHeader("OpCapability StorageImageMultisample\n", false) +
+      R"(
+%img_type = OpTypeImage %f32 2D 0 0 1 2 Rgba32f
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << code;
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeImageMultisampleSubpassData_OK) {
+  const std::string code =
+      GetShaderHeader("OpCapability InputAttachment\n", false) +
+      R"(
+%img_type = OpTypeImage %f32 SubpassData 0 0 1 2 Unknown
+)";
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << code;
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, TypeSampledImage_NotImage_Error) {
   const std::string code = GetShaderHeader("", false) + R"(
 %simg_type = OpTypeSampledImage %f32
 )";
@@ -595,6 +867,43 @@
               HasSubstr("Expected Image to be of type OpTypeImage"));
 }
 
+TEST_F(ValidateImage, TypeSampledImage_Sampled0_Success) {
+  // This is ok in the OpenCL and universal environments.
+  // Vulkan will reject an OpTypeImage with Sampled=0, checked elsewhere.
+  const std::string code = GetShaderHeader() + R"(
+%imty = OpTypeImage %f32 2D 0 0 0 0 Unknown
+%simg_type = OpTypeSampledImage %imty
+)" + TrivialMain();
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+  EXPECT_EQ(getDiagnosticString(), "");
+}
+
+TEST_F(ValidateImage, TypeSampledImage_Sampled2_Error) {
+  const std::string code = GetShaderHeader() + R"(
+%storage_image = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
+%simg_type = OpTypeSampledImage %storage_image
+)" + TrivialMain();
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampled image type requires an image type with "
+                        "\"Sampled\" operand set to 0 or 1"));
+}
+
+TEST_F(ValidateImage, TypeSampledImage_Sampled1_Success) {
+  const std::string code = GetShaderHeader() + R"(
+%im = OpTypeImage %f32 2D 0 0 0 1 Unknown
+%simg_type = OpTypeSampledImage %im
+)" + TrivialMain();
+
+  CompileSuccessfully(code.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+  EXPECT_EQ(getDiagnosticString(), "");
+}
+
 TEST_F(ValidateImage, SampledImageSuccess) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -646,31 +955,32 @@
 }
 
 TEST_F(ValidateImage, SampledImageImageNotForSampling) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_2d_0002 %img %sampler
+  const std::string code = GetShaderHeader() + R"(
+%im_ty = OpTypeImage %f32 2D 0 0 0 2 Unknown
+%sampler_ty = OpTypeSampler
+%sampled_image_ty = OpTypeSampledImage %im_ty ; will fail here first!
+
+%ptr_im_ty = OpTypePointer UniformConstant %im_ty
+%var_im = OpVariable %ptr_im_ty UniformConstant
+
+%ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+%var_sampler = OpVariable %ptr_sampler_ty UniformConstant
+
+%main = OpFunction %void None %func
+%entry = OpLabel
+%im = OpLoad %im_ty %var_im
+%sampler = OpLoad %sampler_ty %var_sampler
+%sampled_image = OpSampledImage %sampled_image_ty %im %sampler
+OpReturn
+OpFunctionEnd
 )";
 
-  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  CompileSuccessfully(code.c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Expected Image 'Sampled' parameter to be 0 or 1"));
-}
-
-TEST_F(ValidateImage, SampledImageVulkanUnknownSampled) {
-  const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_u32_2d_0000 %img %sampler
-)";
-
-  const spv_target_env env = SPV_ENV_VULKAN_1_0;
-  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Expected Image 'Sampled' parameter to "
-                        "be 1 for Vulkan environment."));
+              HasSubstr("Sampled image type requires an image type with "
+                        "\"Sampled\" operand set to 0 or 1"))
+      << code;
 }
 
 TEST_F(ValidateImage, SampledImageNotSampler) {
@@ -743,7 +1053,7 @@
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 141[%141] cannot be a "
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 136[%136] cannot be a "
                                                "type"));
 }
 
@@ -801,7 +1111,7 @@
 
 TEST_F(ValidateImage, ImageTexelPointerImageCoordSizeBad) {
   const std::string body = R"(
-%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_u32_2d_0000 %u32vec3_012 %u32_0
+%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %uniform_image_u32_2d_0002 %u32vec3_012 %u32_0
 %sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1
 )";
 
@@ -902,6 +1212,20 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleImplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampling operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, SampleImplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -1050,6 +1374,20 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleExplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_0 %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampling operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, SampleExplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -1182,19 +1520,6 @@
                         "2D, 3D or Cube"));
 }
 
-TEST_F(ValidateImage, LodMultisampled) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_2d_0010 %img %sampler
-%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Lod %f32_0)";
-
-  CompileSuccessfully(GenerateShaderCode(body).c_str());
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Image Operand Lod requires 'MS' parameter to be 0"));
-}
-
 TEST_F(ValidateImage, MinLodIncompatible) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -1227,20 +1552,6 @@
           "Image Operand Grad can only be used with ExplicitLod opcodes"));
 }
 
-TEST_F(ValidateImage, SampleImplicitLod3DArrayedMultisampledSuccess) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000
-%res2 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec3_012
-%res3 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
-)";
-
-  CompileSuccessfully(GenerateShaderCode(body).c_str());
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
-}
-
 TEST_F(ValidateImage, SampleImplicitLodCubeArrayedSuccess) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
@@ -1285,20 +1596,6 @@
                         "2D, 3D or Cube"));
 }
 
-TEST_F(ValidateImage, SampleImplicitLodBiasMultisampled) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Bias %f32_0_25
-)";
-
-  CompileSuccessfully(GenerateShaderCode(body).c_str());
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Image Operand Bias requires 'MS' parameter to be 0"));
-}
-
 TEST_F(ValidateImage, SampleExplicitLodGradDxWrongType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
@@ -1361,20 +1658,6 @@
           "Expected Image Operand Grad dy to have 3 components, but given 2"));
 }
 
-TEST_F(ValidateImage, SampleExplicitLodGradMultisampled) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Grad %f32vec3_000 %f32vec3_000
-)";
-
-  CompileSuccessfully(GenerateShaderCode(body).c_str());
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Image Operand Grad requires 'MS' parameter to be 0"));
-}
-
 TEST_F(ValidateImage, SampleImplicitLodConstOffsetCubeDim) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
@@ -1393,10 +1676,10 @@
 
 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongType) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %f32vec3_000
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %f32vec2_00
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
@@ -1409,26 +1692,26 @@
 
 TEST_F(ValidateImage, SampleImplicitLodConstOffsetWrongSize) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %s32vec2_01
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %s32vec3_012
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Expected Image Operand ConstOffset to have 3 "
-                        "components, but given 2"));
+              HasSubstr("Expected Image Operand ConstOffset to have 2 "
+                        "components, but given 3"));
 }
 
 TEST_F(ValidateImage, SampleImplicitLodConstOffsetNotConst) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
 %offset = OpSNegate %s32vec3 %s32vec3_012
-%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset %offset
+%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_00 ConstOffset %offset
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
@@ -1455,10 +1738,10 @@
 
 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongType) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %f32vec3_000
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %f32vec2_00
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
@@ -1470,10 +1753,10 @@
 
 TEST_F(ValidateImage, SampleImplicitLodOffsetWrongSize) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec2_01
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 Offset %s32vec3_012
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
@@ -1481,15 +1764,15 @@
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
-          "Expected Image Operand Offset to have 3 components, but given 2"));
+          "Expected Image Operand Offset to have 2 components, but given 3"));
 }
 
 TEST_F(ValidateImage, SampleImplicitLodMoreThanOneOffset) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec3_012 %s32vec3_012
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res4 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 ConstOffset|Offset %s32vec2_01 %s32vec2_01
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
@@ -1528,21 +1811,6 @@
                         "1D, 2D, 3D or Cube"));
 }
 
-TEST_F(ValidateImage, SampleImplicitLodMinLodMultisampled) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0111 %uniform_image_f32_3d_0111
-%sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_3d_0111 %img %sampler
-%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec4_0000 MinLod %f32_0_25
-)";
-
-  CompileSuccessfully(GenerateShaderCode(body).c_str());
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Image Operand MinLod requires 'MS' parameter to be 0"));
-}
-
 TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -1620,6 +1888,20 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleProjExplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec2_hh Lod|Sample %f32_1 %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Image 'MS' parameter to be 0"));
+}
+
 TEST_F(ValidateImage, SampleProjExplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -1741,6 +2023,20 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleProjImplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec2_hh Sample %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Image 'MS' parameter to be 0"));
+}
+
 TEST_F(ValidateImage, SampleProjImplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -1848,6 +2144,21 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleDrefImplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleDrefImplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Dref sampling operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, SampleDrefImplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_u32_2d_0001 %uniform_image_u32_2d_0001
@@ -1971,6 +2282,21 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleDrefExplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Dref sampling operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, SampleDrefExplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_s32_3d_0001 %uniform_image_s32_3d_0001
@@ -2095,6 +2421,21 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleProjDrefImplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Sample %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Dref sampling operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -2218,6 +2559,21 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, SampleProjDrefExplicitLodMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageSampleDrefExplicitLod %f32 %simg %f32vec2_hh %f32_1 Lod|Sample %f32_1 %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Dref sampling operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001
@@ -2294,6 +2650,23 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
+TEST_F(ValidateImage, FetchMultisampledSuccess) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%res1 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample %u32_1
+%res2 = OpImageFetch %f32vec4 %img %u32vec2_01 Sample|NonPrivateTexelKHR %u32_1
+)";
+
+  const std::string extra = R"(
+OpCapability VulkanMemoryModelKHR
+OpExtension "SPV_KHR_vulkan_memory_model"
+)";
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
+                                         SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
+                          .c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
+}
+
 TEST_F(ValidateImage, FetchWrongResultType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
@@ -2349,7 +2722,7 @@
 
 TEST_F(ValidateImage, FetchNotSampled) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageFetch %u32vec4 %img %u32vec2_01
 )";
 
@@ -2433,6 +2806,21 @@
                         "with OpImageFetch"));
 }
 
+TEST_F(ValidateImage, FetchMultisampledMissingSample) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%res1 = OpImageFetch %f32vec4 %img %u32vec2_01
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions())
+      << GenerateShaderCode(body);
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Image Operand Sample is required for operation on "
+                        "multi-sampled image"))
+      << getDiagnosticString();
+}
+
 TEST_F(ValidateImage, GatherSuccess) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -2494,6 +2882,20 @@
       HasSubstr("Expected Sampled Image to be of type OpTypeSampledImage"));
 }
 
+TEST_F(ValidateImage, GatherMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 Sample %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Gather operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, GatherWrongSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_cube_0101 %uniform_image_f32_cube_0101
@@ -2709,6 +3111,20 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
+TEST_F(ValidateImage, DrefGatherMultisampleError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
+%res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_1 Sample %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Gather operation is invalid for multisample image"));
+}
+
 TEST_F(ValidateImage, DrefGatherVoidSampledType) {
   const std::string body = R"(
 %img = OpLoad %type_image_void_2d_0001 %uniform_image_void_2d_0001
@@ -2740,7 +3156,7 @@
 
 TEST_F(ValidateImage, ReadSuccess1) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
 )";
 
@@ -2783,7 +3199,7 @@
 
 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormat) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
 )";
 
@@ -2793,7 +3209,7 @@
 
 TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01
 )";
 
@@ -2836,7 +3252,7 @@
 // TODO(atgoo@github.com) Disabled until the spec is clarified.
 TEST_F(ValidateImage, DISABLED_ReadWrongResultType) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %f32 %img %u32vec2_01
 )";
 
@@ -2847,16 +3263,41 @@
               HasSubstr("Expected Result Type to be int or float vector type"));
 }
 
-// TODO(atgoo@github.com) Disabled until the spec is clarified.
-TEST_F(ValidateImage, DISABLED_ReadWrongNumComponentsResultType) {
+TEST_F(ValidateImage, ReadScalarResultType_Universal) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
-%res1 = OpImageRead %f32vec3 %img %u32vec2_01
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
+%res1 = OpImageRead %u32 %img %u32vec2_01
 )";
 
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, ReadUnusualNumComponentsResultType_Universal) {
+  const std::string body = R"(
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
+%res1 = OpImageRead %u32vec3 %img %u32vec2_01
+)";
+
+  const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
+  CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateImage, ReadWrongNumComponentsResultType_Vulkan) {
+  const std::string body = R"(
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
+%res1 = OpImageRead %u32vec3 %img %u32vec2_01
+)";
+
+  const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
+  CompileSuccessfully(
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_VULKAN_1_0)
+          .c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Expected Result Type to have 4 components"));
 }
@@ -2889,7 +3330,7 @@
 
 TEST_F(ValidateImage, ReadWrongSampledType) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %f32vec4 %img %u32vec2_01
 )";
 
@@ -2916,7 +3357,7 @@
 
 TEST_F(ValidateImage, ReadWrongCoordinateType) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %f32vec2_00
 )";
 
@@ -2929,7 +3370,7 @@
 
 TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32_1
 )";
 
@@ -2943,7 +3384,7 @@
 
 TEST_F(ValidateImage, WriteSuccess1) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123
 )";
 
@@ -2976,14 +3417,24 @@
 
 TEST_F(ValidateImage, WriteSuccess4) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
-;TODO(atgoo@github.com) Is it legal to write to MS image without sample index?
-OpImageWrite %img %u32vec2_01 %f32vec4_0000
+%img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
 )";
 
-  const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
-  CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
+  const std::string extra = R"(
+    OpCapability StorageImageWriteWithoutFormat
+    OpCapability StorageImageMultisample
+    )";
+
+  const std::string declarations = R"(
+%type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
+%ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
+%uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
+    )";
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
+                                         SPV_ENV_UNIVERSAL_1_0, "GLSL450",
+                                         declarations)
+                          .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
@@ -3001,7 +3452,7 @@
 
 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormat) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123
 )";
 
@@ -3011,7 +3462,7 @@
 
 TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123
 )";
 
@@ -3080,7 +3531,7 @@
 
 TEST_F(ValidateImage, WriteWrongCoordinateType) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %f32vec2_00 %u32vec4_0123
 )";
 
@@ -3093,7 +3544,7 @@
 
 TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32_1 %u32vec4_0123
 )";
 
@@ -3107,7 +3558,7 @@
 
 TEST_F(ValidateImage, WriteTexelWrongType) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %img
 )";
 
@@ -3120,7 +3571,7 @@
 
 TEST_F(ValidateImage, DISABLED_WriteTexelNotVector4) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec3_012
 )";
 
@@ -3133,7 +3584,7 @@
 
 TEST_F(ValidateImage, WriteTexelWrongComponentType) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %f32vec4_0000
 )";
 
@@ -3148,18 +3599,29 @@
 
 TEST_F(ValidateImage, WriteSampleNotInteger) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0012 %uniform_image_f32_2d_0012
 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1
 )";
 
-  const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
-  CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
+  const std::string extra = R"(
+    OpCapability StorageImageWriteWithoutFormat
+    OpCapability StorageImageMultisample
+    )";
+  const std::string declarations = R"(
+%type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
+%ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
+%uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
+    )";
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
+                                         SPV_ENV_UNIVERSAL_1_0, "GLSL450",
+                                         declarations)
+                          .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Expected Image Operand Sample to be int scalar"));
 }
 
-TEST_F(ValidateImage, SampleNotMultisampled) {
+TEST_F(ValidateImage, WriteSampleNotMultisampled) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
 OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
@@ -3175,18 +3637,16 @@
 
 TEST_F(ValidateImage, SampleWrongOpcode) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
 %sampler = OpLoad %type_sampler %uniform_sampler
-%simg = OpSampledImage %type_sampled_image_f32_2d_0010 %img %sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0011 %img %sampler
 %res1 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_00 Sample %u32_1
 )";
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Image Operand Sample can only be used with "
-                        "OpImageFetch, OpImageRead, OpImageWrite, "
-                        "OpImageSparseFetch and OpImageSparseRead"));
+              HasSubstr("Sampling operation is invalid for multisample image"));
 }
 
 TEST_F(ValidateImage, SampleImageToImageSuccess) {
@@ -3379,6 +3839,67 @@
                         "for OpImageQuerySizeLod"));
 }
 
+TEST_F(ValidateImage, QuerySizeLodMultisampledError) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
+%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
+}
+
+TEST_F(ValidateImage, QuerySizeLodNonSampledUniversalSuccess) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
+%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+  EXPECT_EQ(getDiagnosticString(), "");
+}
+
+TEST_F(ValidateImage, QuerySizeLodVulkanNonSampledError) {
+  // Create a whole shader module.  Avoid Vulkan incompatibility with
+  // SampledRrect images inserted by helper function GenerateShaderCode.
+  const std::string body = R"(
+OpCapability Shader
+OpCapability ImageQuery
+OpMemoryModel Logical Simple
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+
+%f32 = OpTypeFloat 32
+%u32 = OpTypeInt 32 0
+%u32_0 = OpConstant %u32 0
+%u32vec2 = OpTypeVector %u32 2
+%void = OpTypeVoid
+%voidfn = OpTypeFunction %void
+
+; Test with a storage image.
+%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
+%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
+%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
+
+%main = OpFunction %void None %voidfn
+%entry = OpLabel
+%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
+%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_0
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpImageQuerySizeLod must only consume an \"Image\" operand whose "
+          "type has its \"Sampled\" operand set to 1"));
+}
+
 TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
@@ -3391,17 +3912,6 @@
               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
 }
 
-TEST_F(ValidateImage, QuerySizeLodMultisampled) {
-  const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
-%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
-)";
-
-  CompileSuccessfully(GenerateKernelCode(body).c_str());
-  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
-}
-
 TEST_F(ValidateImage, QuerySizeLodWrongLodType) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -3416,7 +3926,7 @@
 
 TEST_F(ValidateImage, QuerySizeSuccess) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
 %res1 = OpImageQuerySize %u32vec2 %img
 )";
 
@@ -3426,7 +3936,7 @@
 
 TEST_F(ValidateImage, QuerySizeWrongResultType) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
 %res1 = OpImageQuerySize %f32vec2 %img
 )";
 
@@ -3439,7 +3949,7 @@
 
 TEST_F(ValidateImage, QuerySizeNotImage) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
 %sampler = OpLoad %type_sampler %uniform_sampler
 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
 %res1 = OpImageQuerySize %u32vec2 %sampler
@@ -3453,7 +3963,7 @@
 
 TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
 %sampler = OpLoad %type_sampler %uniform_sampler
 %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
 %res1 = OpImageQuerySize %u32vec2 %simg
@@ -3676,9 +4186,56 @@
               HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
 }
 
+TEST_F(ValidateImage, QuerySizeLevelsNonSampledUniversalSuccess) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
+%res1 = OpImageQueryLevels %u32 %img
+)";
+
+  CompileSuccessfully(GenerateShaderCode(body).c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+  EXPECT_EQ(getDiagnosticString(), "");
+}
+
+TEST_F(ValidateImage, QuerySizeLevelsVulkanNonSampledError) {
+  // Create a whole shader module.  Avoid Vulkan incompatibility with
+  // SampledRrect images inserted by helper function GenerateShaderCode.
+  const std::string body = R"(
+OpCapability Shader
+OpCapability ImageQuery
+OpMemoryModel Logical Simple
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+
+%f32 = OpTypeFloat 32
+%u32 = OpTypeInt 32 0
+%void = OpTypeVoid
+%voidfn = OpTypeFunction %void
+
+; Test with a storage image.
+%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
+%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
+%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
+
+%main = OpFunction %void None %voidfn
+%entry = OpLabel
+%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
+%res1 = OpImageQueryLevels %u32 %img
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpImageQueryLevels must only consume an \"Image\" operand "
+                "whose type has its \"Sampled\" operand set to 1"));
+}
+
 TEST_F(ValidateImage, QuerySamplesSuccess) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
+%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
 %res1 = OpImageQuerySamples %u32 %img
 )";
 
@@ -3688,7 +4245,7 @@
 
 TEST_F(ValidateImage, QuerySamplesNot2D) {
   const std::string body = R"(
-%img = OpLoad %type_image_f32_3d_0010 %uniform_image_f32_3d_0010
+%img = OpLoad %type_image_f32_3d_0011 %uniform_image_f32_3d_0011
 %res1 = OpImageQuerySamples %u32 %img
 )";
 
@@ -3766,6 +4323,100 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
+TEST_F(ValidateImage, QueryLodUniversalSuccess) {
+  // Create a whole shader module.  Avoid Vulkan incompatibility with
+  // SampledRrect images inserted by helper function GenerateShaderCode.
+  const std::string body = R"(
+OpCapability Shader
+OpCapability ImageQuery
+OpMemoryModel Logical Simple
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+
+OpDecorate %uniform_image_f32_2d_0000 DescriptorSet 0
+OpDecorate %uniform_image_f32_2d_0000 Binding 0
+OpDecorate %sampler DescriptorSet 0
+OpDecorate %sampler Binding 1
+
+%f32 = OpTypeFloat 32
+%f32vec2 = OpTypeVector %f32 2
+%f32vec2_null = OpConstantNull %f32vec2
+%u32 = OpTypeInt 32 0
+%u32vec2 = OpTypeVector %u32 2
+%void = OpTypeVoid
+%voidfn = OpTypeFunction %void
+
+; Test with an image with sampled = 0
+%type_image_f32_2d_0000 = OpTypeImage %f32 2D 0 0 0 0 Rgba32f
+%ptr_image_f32_2d_0000 = OpTypePointer UniformConstant %type_image_f32_2d_0000
+%uniform_image_f32_2d_0000 = OpVariable %ptr_image_f32_2d_0000 UniformConstant
+%sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0000
+
+%sampler_ty = OpTypeSampler
+%ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+%sampler = OpVariable %ptr_sampler_ty UniformConstant
+
+
+%main = OpFunction %void None %voidfn
+%entry = OpLabel
+%img = OpLoad %type_image_f32_2d_0000 %uniform_image_f32_2d_0000
+%s = OpLoad %sampler_ty %sampler
+%simg = OpSampledImage %sampled_image_ty %img %s
+%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, QueryLodVulkanNonSampledError) {
+  // Create a whole shader module.  Avoid Vulkan incompatibility with
+  // SampledRrect images inserted by helper function GenerateShaderCode.
+  const std::string body = R"(
+OpCapability Shader
+OpCapability ImageQuery
+OpMemoryModel Logical Simple
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+
+OpDecorate %sampled_image DescriptorSet 0
+OpDecorate %sampled_image Binding 0
+
+%f32 = OpTypeFloat 32
+%f32vec2 = OpTypeVector %f32 2
+%f32vec2_null = OpConstantNull %f32vec2
+%u32 = OpTypeInt 32 0
+%u32vec2 = OpTypeVector %u32 2
+%void = OpTypeVoid
+%voidfn = OpTypeFunction %void
+
+; Test with an image with Sampled = 2
+; In Vulkan it Sampled must be 1 or 2, checked in another part of the
+; validation flow.
+%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
+
+; Expect to fail here.
+%sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0002
+%ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+%sampled_image = OpVariable %ptr_sampled_image_ty UniformConstant
+
+%main = OpFunction %void None %voidfn
+%entry = OpLabel
+%simg = OpLoad %sampled_image_ty %sampled_image
+%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Sampled image type requires an image type with "
+                        "\"Sampled\" operand set to 0 or 1"));
+}
+
 TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
   const std::string body = R"(
 %img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
@@ -4453,7 +5104,7 @@
 
 TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_2
 )";
 
@@ -4511,7 +5162,7 @@
 
 TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1
 )";
 
@@ -4532,7 +5183,7 @@
 
 TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_2
 )";
 
@@ -4572,7 +5223,7 @@
 
 TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1
 )";
 
@@ -4593,7 +5244,7 @@
 
 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteBad) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
 )";
 
@@ -4615,7 +5266,7 @@
 
 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageWriteGood) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1
 )";
 
@@ -4633,7 +5284,7 @@
 
 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadBad) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
 )";
 
@@ -4655,7 +5306,7 @@
 
 TEST_F(ValidateImage, VulkanMemoryModelDeviceScopeImageReadGood) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1
 )";
 
@@ -4708,7 +5359,7 @@
 
 TEST_F(ValidateImage, SignExtendV13Bad) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
 )";
 
@@ -4719,7 +5370,7 @@
 
 TEST_F(ValidateImage, ZeroExtendV13Bad) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
 )";
 
@@ -4731,7 +5382,7 @@
 TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
   // Unsigned int sampled type
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32 %img %u32vec2_01 SignExtend
 )";
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
@@ -4760,7 +5411,7 @@
 
 TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
 )";
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
@@ -4792,7 +5443,7 @@
 TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
   // Unsigned int sampled type
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32 %img %u32vec2_01 ZeroExtend
 )";
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
@@ -4821,7 +5472,7 @@
 
 TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
 )";
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
@@ -4849,7 +5500,7 @@
 
 TEST_F(ValidateImage, ReadLodAMDSuccess1) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 Lod %u32_0
 )";
 
@@ -4914,7 +5565,7 @@
 
 TEST_F(ValidateImage, WriteLodAMDSuccess1) {
   const std::string body = R"(
-%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
 OpImageWrite %img %u32vec2_01 %u32vec4_0123 Lod %u32_0
 )";
 
@@ -5088,6 +5739,12 @@
 %ptr_image_u64_buffer_0002_r64ui = OpTypePointer Private %type_image_u64_buffer_0002_r64ui
 %private_image_u64_buffer_0002_r64ui = OpVariable %ptr_image_u64_buffer_0002_r64ui Private
 )";
+static const std::string declarations_image64i = R"(
+%type_image_s64_buffer_0002_r64i = OpTypeImage %s64 Buffer 0 0 0 2 R64i
+%ptr_Image_s64 = OpTypePointer Image %s64
+%ptr_image_s64_buffer_0002_r64i = OpTypePointer Private %type_image_s64_buffer_0002_r64i
+%private_image_s64_buffer_0002_r64i = OpVariable %ptr_image_s64_buffer_0002_r64i Private
+)";
 
 TEST_F(ValidateImage, Image64MissingCapability) {
   CompileSuccessfully(GenerateShaderCode("", "", "Fragment", "",
@@ -5173,6 +5830,134 @@
                         "<id> for the value 0"));
 }
 
+TEST_F(ValidateImage, ImageTexelPointerR32uiSuccessVulkan) {
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %private_image_u32_buffer_0002_r32ui %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
+                      env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+}
+
+TEST_F(ValidateImage, ImageTexelPointerR32iSuccessVulkan) {
+  const std::string& declarations = R"(
+%type_image_s32_buffer_0002_r32i = OpTypeImage %s32 Buffer 0 0 0 2 R32i
+%ptr_Image_s32 = OpTypePointer Image %s32
+%ptr_image_s32_buffer_0002_r32i = OpTypePointer Private %type_image_s32_buffer_0002_r32i
+%private_image_s32_buffer_0002_r32i = OpVariable %ptr_image_s32_buffer_0002_r32i Private
+)";
+
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_r32i %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(
+      GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
+          .c_str(),
+      env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+}
+
+TEST_F(ValidateImage, ImageTexelPointerR64uiSuccessVulkan) {
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_u64 %private_image_u64_buffer_0002_r64ui %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(
+      GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
+                         "", env, "GLSL450", declarations_image64)
+          .c_str(),
+      env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+}
+
+TEST_F(ValidateImage, ImageTexelPointerR64iSuccessVulkan) {
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_s64 %private_image_s64_buffer_0002_r64i %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(
+      GenerateShaderCode(body, capabilities_and_extensions_image64, "Fragment",
+                         "", env, "GLSL450", declarations_image64i)
+          .c_str(),
+      env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+}
+
+TEST_F(ValidateImage, ImageTexelPointerR32fSuccessVulkan) {
+  const std::string& declarations = R"(
+%type_image_f32_buffer_0002_r32f = OpTypeImage %f32 Buffer 0 0 0 2 R32f
+%ptr_image_f32_buffer_0002_r32f = OpTypePointer Private %type_image_f32_buffer_0002_r32f
+%private_image_f32_buffer_0002_r32f = OpVariable %ptr_image_f32_buffer_0002_r32f Private
+)";
+
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_f32 %private_image_f32_buffer_0002_r32f %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(
+      GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
+          .c_str(),
+      env);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
+}
+
+TEST_F(ValidateImage, ImageTexelPointerRgba32iVulkan) {
+  const std::string& declarations = R"(
+%type_image_s32_buffer_0002_rgba32i = OpTypeImage %s32 Buffer 0 0 0 2 Rgba32i
+%ptr_Image_s32 = OpTypePointer Image %s32
+%ptr_image_s32_buffer_0002_rgba32i = OpTypePointer Private %type_image_s32_buffer_0002_rgba32i
+%private_image_s32_buffer_0002_rgba32i = OpVariable %ptr_image_s32_buffer_0002_rgba32i Private
+)";
+
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba32i %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(
+      GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
+          .c_str(),
+      env);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
+                        "R32f, R32i, or R32ui for Vulkan environment"));
+}
+
+TEST_F(ValidateImage, ImageTexelPointerRgba16fVulkan) {
+  const std::string& declarations = R"(
+%type_image_s32_buffer_0002_rgba16f = OpTypeImage %s32 Buffer 0 0 0 2 Rgba16f
+%ptr_Image_s32 = OpTypePointer Image %s32
+%ptr_image_s32_buffer_0002_rgba16f = OpTypePointer Private %type_image_s32_buffer_0002_rgba16f
+%private_image_s32_buffer_0002_rgba16f = OpVariable %ptr_image_s32_buffer_0002_rgba16f Private
+)";
+
+  const std::string body = R"(
+%texel_ptr = OpImageTexelPointer %ptr_Image_s32 %private_image_s32_buffer_0002_rgba16f %u32_0 %u32_0
+)";
+
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
+  CompileSuccessfully(
+      GenerateShaderCode(body, "", "Fragment", "", env, "GLSL450", declarations)
+          .c_str(),
+      env);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpImageTexelPointer-04658"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected the Image Format in Image to be R64i, R64ui, "
+                        "R32f, R32i, or R32ui for Vulkan environment"));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_layout_test.cpp b/third_party/SPIRV-Tools/test/val/val_layout_test.cpp
index 43fa046..d34c97f 100644
--- a/third_party/SPIRV-Tools/test/val/val_layout_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_layout_test.cpp
@@ -667,57 +667,6 @@
       HasSubstr("ModuleProcessed cannot appear in a function declaration"));
 }
 
-TEST_F(ValidateLayout, WebGPUCallerBeforeCalleeBad) {
-  char str[] = R"(
-           OpCapability Shader
-           OpCapability VulkanMemoryModelKHR
-           OpExtension "SPV_KHR_vulkan_memory_model"
-           OpMemoryModel Logical VulkanKHR
-           OpEntryPoint GLCompute %main "main"
-%void    = OpTypeVoid
-%voidfn  = OpTypeFunction %void
-%main    = OpFunction %void None %voidfn
-%1       = OpLabel
-%2       = OpFunctionCall %void %callee
-           OpReturn
-           OpFunctionEnd
-%callee  = OpFunction %void None %voidfn
-%3       = OpLabel
-           OpReturn
-           OpFunctionEnd
-)";
-
-  CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, functions need to be defined before being "
-                        "called.\n  %5 = OpFunctionCall %void %6\n"));
-}
-
-TEST_F(ValidateLayout, WebGPUCalleeBeforeCallerGood) {
-  char str[] = R"(
-           OpCapability Shader
-           OpCapability VulkanMemoryModelKHR
-           OpExtension "SPV_KHR_vulkan_memory_model"
-           OpMemoryModel Logical VulkanKHR
-           OpEntryPoint GLCompute %main "main"
-%void    = OpTypeVoid
-%voidfn  = OpTypeFunction %void
-%callee  = OpFunction %void None %voidfn
-%3       = OpLabel
-           OpReturn
-           OpFunctionEnd
-%main    = OpFunction %void None %voidfn
-%1       = OpLabel
-%2       = OpFunctionCall %void %callee
-           OpReturn
-           OpFunctionEnd
-)";
-
-  CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
-  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
 // TODO(umar): Test optional instructions
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/val/val_memory_test.cpp b/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
index e541890..8142f85 100644
--- a/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
@@ -362,192 +362,6 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateMemory, WebGPUInitializerWithOutputStorageClassesGood) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Output %float
-%init_val = OpConstant %float 1.0
-%1 = OpVariable %float_ptr Output %init_val
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%2 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateMemory, WebGPUInitializerWithFunctionStorageClassesGood) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Function %float
-%init_val = OpConstant %float 1.0
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%1 = OpLabel
-%2 = OpVariable %float_ptr Function %init_val
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateMemory, WebGPUInitializerWithPrivateStorageClassesGood) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Private %float
-%init_val = OpConstant %float 1.0
-%1 = OpVariable %float_ptr Private %init_val
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%2 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateMemory, WebGPUInitializerWithDisallowedStorageClassesBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Uniform %float
-%init_val = OpConstant %float 1.0
-%1 = OpVariable %float_ptr Uniform %init_val
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%2 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpVariable, <id> '5[%5]', has a disallowed initializer & "
-                "storage class combination.\nFrom WebGPU spec:\nVariable "
-                "declarations that include initializers must have one of the "
-                "following storage classes: Output, Private, or Function\n  %5 "
-                "= OpVariable %_ptr_Uniform_float Uniform %float_1\n"));
-}
-
-TEST_F(ValidateMemory, WebGPUOutputStorageClassWithoutInitializerBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Output %float
-%1 = OpVariable %float_ptr Output
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%2 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpVariable, <id> '4[%4]', must have an initializer.\n"
-                "From WebGPU execution environment spec:\n"
-                "All variables in the following storage classes must have an "
-                "initializer: Output, Private, or Function\n"
-                "  %4 = OpVariable %_ptr_Output_float Output\n"));
-}
-
-TEST_F(ValidateMemory, WebGPUFunctionStorageClassWithoutInitializerBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Function %float
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%1 = OpLabel
-%2 = OpVariable %float_ptr Function
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpVariable, <id> '7[%7]', must have an initializer.\n"
-                "From WebGPU execution environment spec:\n"
-                "All variables in the following storage classes must have an "
-                "initializer: Output, Private, or Function\n"
-                "  %7 = OpVariable %_ptr_Function_float Function\n"));
-}
-
-TEST_F(ValidateMemory, WebGPUPrivateStorageClassWithoutInitializerBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%float = OpTypeFloat 32
-%float_ptr = OpTypePointer Private %float
-%1 = OpVariable %float_ptr Private
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%2 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpVariable, <id> '4[%4]', must have an initializer.\n"
-                "From WebGPU execution environment spec:\n"
-                "All variables in the following storage classes must have an "
-                "initializer: Output, Private, or Function\n"
-                "  %4 = OpVariable %_ptr_Private_float Private\n"));
-}
-
 TEST_F(ValidateMemory, VulkanInitializerWithOutputStorageClassesGood) {
   std::string spirv = R"(
 OpCapability Shader
@@ -630,6 +444,8 @@
 )";
   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpVariable-04651"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("OpVariable, <id> '5[%5]', has a disallowed initializer & "
@@ -2280,38 +2096,6 @@
           "%_ptr_UniformConstant__runtimearr_2 UniformConstant\n"));
 }
 
-TEST_F(ValidateMemory, WebGPURTAOutsideOfStructBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%sampler_t = OpTypeSampler
-%array_t = OpTypeRuntimeArray %sampler_t
-%array_ptr = OpTypePointer UniformConstant %array_t
-%2 = OpVariable %array_ptr UniformConstant
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "OpVariable, <id> '5[%5]', is attempting to create memory for an "
-          "illegal type, OpTypeRuntimeArray.\nFor WebGPU OpTypeRuntimeArray "
-          "can only appear as the final member of an OpTypeStruct, thus cannot "
-          "be instantiated via OpVariable\n  %5 = OpVariable "
-          "%_ptr_UniformConstant__runtimearr_2 UniformConstant\n"));
-}
-
 TEST_F(ValidateMemory, VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayGood) {
   std::string spirv = R"(
 OpCapability Shader
@@ -2401,34 +2185,6 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
 }
 
-TEST_F(ValidateMemory, WebGPURTAInsideStorageBufferStructGood) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-OpDecorate %array_t ArrayStride 4
-OpMemberDecorate %struct_t 0 Offset 0
-OpDecorate %struct_t Block
-%uint_t = OpTypeInt 32 0
-%array_t = OpTypeRuntimeArray %uint_t
-%struct_t = OpTypeStruct %array_t
-%struct_ptr = OpTypePointer StorageBuffer %struct_t
-%2 = OpVariable %struct_ptr StorageBuffer
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
 TEST_F(ValidateMemory, VulkanRTAInsideWrongStorageClassStructBad) {
   std::string spirv = R"(
 OpCapability Shader
@@ -2458,36 +2214,6 @@
           "OpVariable %_ptr_Workgroup__struct_4 Workgroup\n"));
 }
 
-TEST_F(ValidateMemory, WebGPURTAInsideWrongStorageClassStructBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%uint_t = OpTypeInt 32 0
-%array_t = OpTypeRuntimeArray %uint_t
-%struct_t = OpTypeStruct %array_t
-%struct_ptr = OpTypePointer Workgroup %struct_t
-%2 = OpVariable %struct_ptr Workgroup
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("For WebGPU, OpTypeStruct variables containing "
-                "OpTypeRuntimeArray must have storage class of StorageBuffer\n "
-                " %6 = OpVariable %_ptr_Workgroup__struct_4 Workgroup\n"));
-}
-
 TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructWithoutBlockBad) {
   std::string spirv = R"(
 OpCapability Shader
@@ -2516,36 +2242,6 @@
                         "%_ptr_StorageBuffer__struct_4 StorageBuffer\n"));
 }
 
-TEST_F(ValidateMemory, WebGPURTAInsideStorageBufferStructWithoutBlockBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%uint_t = OpTypeInt 32 0
-%array_t = OpTypeRuntimeArray %uint_t
-%struct_t = OpTypeStruct %array_t
-%struct_ptr = OpTypePointer StorageBuffer %struct_t
-%2 = OpVariable %struct_ptr StorageBuffer
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, an OpTypeStruct variable containing an "
-                        "OpTypeRuntimeArray must be decorated with Block if it "
-                        "has storage class StorageBuffer.\n  %6 = OpVariable "
-                        "%_ptr_StorageBuffer__struct_4 StorageBuffer\n"));
-}
-
 TEST_F(ValidateMemory, VulkanRTAInsideUniformStructGood) {
   std::string spirv = R"(
 OpCapability Shader
@@ -2572,39 +2268,6 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
 }
 
-TEST_F(ValidateMemory, WebGPURTAInsideUniformStructBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-OpDecorate %array_t ArrayStride 4
-OpMemberDecorate %struct_t 0 Offset 0
-OpDecorate %struct_t Block
-%uint_t = OpTypeInt 32 0
-%array_t = OpTypeRuntimeArray %uint_t
-%struct_t = OpTypeStruct %array_t
-%struct_ptr = OpTypePointer Uniform %struct_t
-%2 = OpVariable %struct_ptr Uniform
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("For WebGPU, OpTypeStruct variables containing "
-                "OpTypeRuntimeArray must have storage class of StorageBuffer\n "
-                " %6 = OpVariable %_ptr_Uniform__struct_3 Uniform\n"));
-}
-
 TEST_F(ValidateMemory, VulkanRTAInsideUniformStructWithoutBufferBlockBad) {
   std::string spirv = R"(
 OpCapability Shader
@@ -2662,37 +2325,6 @@
           "OpTypeRuntimeArray %_runtimearr_2\n"));
 }
 
-TEST_F(ValidateMemory, WebGPURTAInsideRTABad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%sampler_t = OpTypeSampler
-%inner_array_t = OpTypeRuntimeArray %sampler_t
-%array_t = OpTypeRuntimeArray %inner_array_t
-%array_ptr = OpTypePointer UniformConstant %array_t
-%2 = OpVariable %array_ptr UniformConstant
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "OpTypeRuntimeArray Element Type <id> '3[%_runtimearr_2]' is not "
-          "valid in WebGPU environments.\n  %_runtimearr__runtimearr_2 = "
-          "OpTypeRuntimeArray %_runtimearr_2\n"));
-}
-
 TEST_F(ValidateMemory, VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad) {
   std::string spirv = R"(
 OpCapability RuntimeDescriptorArrayEXT
@@ -2853,38 +2485,6 @@
                 "OpTypeArray %_runtimearr_4 %uint_1\n"));
 }
 
-TEST_F(ValidateMemory, WebGPURTAInsideArrayBad) {
-  std::string spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%uint_t = OpTypeInt 32 0
-%dim = OpConstant %uint_t 1
-%sampler_t = OpTypeSampler
-%inner_array_t = OpTypeRuntimeArray %sampler_t
-%array_t = OpTypeArray %inner_array_t %dim
-%array_ptr = OpTypePointer UniformConstant %array_t
-%2 = OpVariable %array_ptr UniformConstant
-%void = OpTypeVoid
-%func_t = OpTypeFunction %void
-%func = OpFunction %void None %func_t
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpTypeArray Element Type <id> '5[%_runtimearr_4]' is not "
-                "valid in WebGPU environments.\n  %_arr__runtimearr_4_uint_1 = "
-                "OpTypeArray %_runtimearr_4 %uint_1\n"));
-}
-
 TEST_F(ValidateMemory, VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad) {
   std::string spirv = R"(
 OpCapability RuntimeDescriptorArrayEXT
diff --git a/third_party/SPIRV-Tools/test/val/val_misc_test.cpp b/third_party/SPIRV-Tools/test/val/val_misc_test.cpp
index 9395484..499b5b2 100644
--- a/third_party/SPIRV-Tools/test/val/val_misc_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_misc_test.cpp
@@ -226,6 +226,53 @@
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Scope must be Subgroup or Device"));
 }
+
+TEST_F(ValidateMisc, VulkanShaderClockWorkgroupScope) {
+  const std::string spirv = ShaderClockSpriv + R"(
+%3 = OpTypeFunction %void
+%ulong = OpTypeInt 64 0
+%uint = OpTypeInt 32 0
+%_ptr_Function_ulong = OpTypePointer Function %ulong
+%workgroup = OpConstant %uint 2
+%uint_1 = OpConstant %uint 1
+%main = OpFunction %void None %3
+%5 = OpLabel
+%time1 = OpVariable %_ptr_Function_ulong Function
+%11 = OpReadClockKHR %ulong %workgroup
+OpStore %time1 %11
+OpReturn
+OpFunctionEnd)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpReadClockKHR-04652"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Scope must be Subgroup or Device"));
+}
+
+TEST_F(ValidateMisc, UndefVoid) {
+  const std::string spirv = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+          %2 = OpTypeVoid
+         %10 = OpUndef %2
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Cannot create undefined values with void type"));
+}
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_modes_test.cpp b/third_party/SPIRV-Tools/test/val/val_modes_test.cpp
index 0a1476e..7b23159 100644
--- a/third_party/SPIRV-Tools/test/val/val_modes_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_modes_test.cpp
@@ -111,6 +111,8 @@
   CompileSuccessfully(spirv, env);
   EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OriginLowerLeft-04653"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("In the Vulkan environment, the OriginLowerLeft "
                         "execution mode must not be used."));
 }
@@ -128,6 +130,8 @@
   CompileSuccessfully(spirv, env);
   EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-PixelCenterInteger-04654"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("In the Vulkan environment, the PixelCenterInteger "
                         "execution mode must not be used."));
 }
@@ -531,24 +535,16 @@
 
   std::ostringstream sstr;
   sstr << "OpCapability Shader\n";
-  if (!spvIsWebGPUEnv(env)) {
-    sstr << "OpCapability Geometry\n";
-    sstr << "OpCapability Tessellation\n";
-    sstr << "OpCapability TransformFeedback\n";
-  }
-  if (!spvIsVulkanOrWebGPUEnv(env)) {
+  sstr << "OpCapability Geometry\n";
+  sstr << "OpCapability Tessellation\n";
+  sstr << "OpCapability TransformFeedback\n";
+  if (!spvIsVulkanEnv(env)) {
     sstr << "OpCapability Kernel\n";
     if (env == SPV_ENV_UNIVERSAL_1_3) {
       sstr << "OpCapability SubgroupDispatch\n";
     }
   }
-  if (spvIsWebGPUEnv(env)) {
-    sstr << "OpCapability VulkanMemoryModelKHR\n";
-    sstr << "OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
-    sstr << "OpMemoryModel Logical VulkanKHR\n";
-  } else {
-    sstr << "OpMemoryModel Logical GLSL450\n";
-  }
+  sstr << "OpMemoryModel Logical GLSL450\n";
   sstr << "OpEntryPoint " << model << " %main \"main\"\n";
   if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
       mode.find("SubgroupsPerWorkgroupId") == 0) {
@@ -714,39 +710,6 @@
                    "SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
             Values(SPV_ENV_UNIVERSAL_1_3)));
 
-INSTANTIATE_TEST_SUITE_P(ValidateModeGLComputeWebGPUAllowListGood,
-                         ValidateModeExecution,
-                         Combine(Values(SPV_SUCCESS), Values(""),
-                                 Values("GLCompute"), Values("LocalSize 1 1 1"),
-                                 Values(SPV_ENV_WEBGPU_0)));
-
-INSTANTIATE_TEST_SUITE_P(
-    ValidateModeGLComputeWebGPUAllowListBad, ValidateModeExecution,
-    Combine(Values(SPV_ERROR_INVALID_DATA),
-            Values("Execution mode must be one of OriginUpperLeft, "
-                   "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
-                   "LocalSize, or LocalSizeHint for WebGPU environment"),
-            Values("GLCompute"), Values("LocalSizeId %int1 %int1 %int1"),
-            Values(SPV_ENV_WEBGPU_0)));
-
-INSTANTIATE_TEST_SUITE_P(
-    ValidateModeFragmentWebGPUAllowListGood, ValidateModeExecution,
-    Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
-            Values("OriginUpperLeft", "DepthReplacing", "DepthGreater",
-                   "DepthLess", "DepthUnchanged"),
-            Values(SPV_ENV_WEBGPU_0)));
-
-INSTANTIATE_TEST_SUITE_P(
-    ValidateModeFragmentWebGPUAllowListBad, ValidateModeExecution,
-    Combine(Values(SPV_ERROR_INVALID_DATA),
-            Values("Execution mode must be one of OriginUpperLeft, "
-                   "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
-                   "LocalSize, or LocalSizeHint for WebGPU environment"),
-            Values("Fragment"),
-            Values("PixelCenterInteger", "OriginLowerLeft",
-                   "EarlyFragmentTests"),
-            Values(SPV_ENV_WEBGPU_0)));
-
 TEST_F(ValidateModeExecution, MeshNVLocalSize) {
   const std::string spirv = R"(
 OpCapability Shader
diff --git a/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp b/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp
index fbd11a9..3840eec 100644
--- a/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp
@@ -100,6 +100,7 @@
 SpvScope scopes[] = {SpvScopeCrossDevice, SpvScopeDevice, SpvScopeWorkgroup,
                      SpvScopeSubgroup, SpvScopeInvocation};
 
+using ValidateGroupNonUniform = spvtest::ValidateBase<bool>;
 using GroupNonUniform = spvtest::ValidateBase<
     std::tuple<std::string, std::string, SpvScope, std::string, std::string>>;
 
@@ -140,6 +141,8 @@
       EXPECT_EQ(SPV_SUCCESS, result);
     } else {
       EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
+      EXPECT_THAT(getDiagnosticString(),
+                  AnyVUID("VUID-StandaloneSpirv-None-04642"));
       EXPECT_THAT(
           getDiagnosticString(),
           HasSubstr(
@@ -288,6 +291,41 @@
                                  Values("Expected Value to be a vector of four "
                                         "components of integer type scalar")));
 
+TEST_F(ValidateGroupNonUniform, VulkanGroupNonUniformBallotBitCountOperation) {
+  std::string test = R"(
+OpCapability Shader
+OpCapability GroupNonUniform
+OpCapability GroupNonUniformBallot
+OpCapability GroupNonUniformClustered
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%u32 = OpTypeInt 32 0
+%u32vec4 = OpTypeVector %u32 4
+%u32_0 = OpConstant %u32 0
+%u32vec4_null = OpConstantComposite %u32vec4 %u32_0 %u32_0 %u32_0 %u32_0
+%subgroup = OpConstant %u32 3
+%main = OpFunction %void None %func
+%main_entry = OpLabel
+%result = OpGroupNonUniformBallotBitCount %u32 %subgroup ClusteredReduce %u32vec4_null
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(test, SPV_ENV_VULKAN_1_1);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      AnyVUID("VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "In Vulkan: The OpGroupNonUniformBallotBitCount group operation must "
+          "be only: Reduce, InclusiveScan, or ExclusiveScan."));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_opencl_test.cpp b/third_party/SPIRV-Tools/test/val/val_opencl_test.cpp
index 1064158..9dab931 100644
--- a/third_party/SPIRV-Tools/test/val/val_opencl_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_opencl_test.cpp
@@ -23,6 +23,7 @@
 namespace val {
 namespace {
 
+using testing::Eq;
 using testing::HasSubstr;
 
 using ValidateOpenCL = spvtest::ValidateBase<bool>;
@@ -91,7 +92,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("MS must be 0 in the OpenCL environement."
+      HasSubstr("MS must be 0 in the OpenCL environment."
                 "\n  %2 = OpTypeImage %void 2D 0 0 1 0 Unknown ReadOnly\n"));
 }
 
@@ -224,6 +225,264 @@
           "\n  %call = OpImageRead %v4uint %img %coord ConstOffset %coord\n"));
 }
 
+TEST_F(ValidateOpenCL, ImageRead_NonDepthScalarFloatResult_Bad) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+          %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %float %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Result Type to have 4 components"));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_NonDepthScalarIntResult_Bad) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+          %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %uint %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Result Type to have 4 components"));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_NonDepthVector3FloatResult_Bad) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+          %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %v3float %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Result Type to have 4 components"));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_NonDepthVector4FloatResult_Ok) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+          %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %v4float %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_NonDepthVector4IntResult_Ok) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+     %v4uint = OpTypeVector %uint 4
+          %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %v4uint %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_DepthScalarFloatResult_Ok) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+          %3 = OpTypeImage %void 2D 1 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %float %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_DepthScalarIntResult_Bad) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+          %3 = OpTypeImage %void 2D 1 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %uint %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Result Type from a depth image "
+                        "read to result in a scalar float value"));
+}
+
+TEST_F(ValidateOpenCL, ImageRead_DepthVectorFloatResult_Bad) {
+  std::string spirv = R"(
+               OpCapability Addresses
+               OpCapability Kernel
+               OpCapability ImageBasic
+               OpMemoryModel Physical64 OpenCL
+               OpEntryPoint Kernel %5 "image_kernel"
+               OpName %img "img"
+               OpName %coord "coord"
+               OpName %call "call"
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
+       %void = OpTypeVoid
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+          %3 = OpTypeImage %void 2D 1 0 0 0 Unknown ReadOnly
+          %4 = OpTypeFunction %void %3
+          %5 = OpFunction %void None %4
+        %img = OpFunctionParameter %3
+      %entry = OpLabel
+       %call = OpImageRead %v4float %img %coord
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv);
+
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Result Type from a depth image "
+                        "read to result in a scalar float value"));
+}
+
 TEST_F(ValidateOpenCL, ImageSampleExplicitLodWithConstOffsetBad) {
   std::string spirv = R"(
                OpCapability Addresses
@@ -236,18 +495,16 @@
                OpName %coord "coord"
                OpName %call "call"
        %uint = OpTypeInt 32 0
-     %uint_7 = OpConstant %uint 7
-     %uint_3 = OpConstant %uint 3
+     %v2uint = OpTypeVector %uint 2
+      %coord = OpConstantNull %v2uint
        %void = OpTypeVoid
           %3 = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly
           %4 = OpTypeFunction %void %3
           %8 = OpTypeSampler
          %10 = OpTypeSampledImage %3
      %v4uint = OpTypeVector %uint 4
-     %v2uint = OpTypeVector %uint 2
       %float = OpTypeFloat 32
           %9 = OpConstantSampler %8 None 0 Nearest
-      %coord = OpConstantComposite %v2uint %uint_7 %uint_3
     %float_0 = OpConstant %float 0
           %5 = OpFunction %void None %4
           %6 = OpFunctionParameter %3
diff --git a/third_party/SPIRV-Tools/test/val/val_storage_test.cpp b/third_party/SPIRV-Tools/test/val/val_storage_test.cpp
index fe37a93..e6f98bf 100644
--- a/third_party/SPIRV-Tools/test/val/val_storage_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_storage_test.cpp
@@ -250,70 +250,6 @@
               HasSubstr("OpFunctionCall Argument <id> '"));
 }
 
-std::string GetVarDeclStr(const std::string& storage_class) {
-  if (storage_class != "Output" && storage_class != "Private" &&
-      storage_class != "Function") {
-    return "%var    = OpVariable %ptrt " + storage_class + "\n";
-  } else {
-    return "%var    = OpVariable %ptrt " + storage_class + " %null\n";
-  }
-}
-
-TEST_P(ValidateStorageClass, WebGPU) {
-  std::string storage_class = std::get<0>(GetParam());
-  bool is_local = std::get<1>(GetParam());
-  bool is_valid = std::get<2>(GetParam());
-  std::string error = std::get<3>(GetParam());
-
-  std::string str = R"(
-          OpCapability Shader
-          OpCapability VulkanMemoryModelKHR
-          OpExtension "SPV_KHR_vulkan_memory_model"
-          OpMemoryModel Logical VulkanKHR
-          OpEntryPoint Fragment %func "func"
-          OpExecutionMode %func OriginUpperLeft
-%intt   = OpTypeInt 32 1
-%voidt  = OpTypeVoid
-%vfunct = OpTypeFunction %voidt
-%null   = OpConstantNull %intt
-)";
-  str += "%ptrt   = OpTypePointer " + storage_class + " %intt\n";
-  if (!is_local) str += GetVarDeclStr(storage_class);
-  str += R"(
-%func   = OpFunction %voidt None %vfunct
-%funcl  = OpLabel
-)";
-  if (is_local) str += GetVarDeclStr(storage_class);
-  str += R"(
-OpReturn
-OpFunctionEnd
-)";
-
-  CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
-  if (is_valid) {
-    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  } else {
-    ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
-    EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
-  }
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    StorageClass, ValidateStorageClass,
-    Values(std::make_tuple("UniformConstant", false, true, ""),
-           std::make_tuple("Uniform", false, true, ""),
-           std::make_tuple("StorageBuffer", false, true, ""),
-           std::make_tuple("Input", false, true, ""),
-           std::make_tuple("Output", false, true, ""),
-           std::make_tuple("Image", false, true, ""),
-           std::make_tuple("Workgroup", false, true, ""),
-           std::make_tuple("Private", false, true, ""),
-           std::make_tuple("Function", true, true, ""),
-           std::make_tuple("CrossWorkgroup", false, false,
-                           "Invalid storage class for target environment"),
-           std::make_tuple("PushConstant", false, false,
-                           "Invalid storage class for target environment")));
-
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp b/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp
index 4581579..7a38d3a 100644
--- a/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp
@@ -245,12 +245,6 @@
             ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
 }
 
-TEST_F(ValidationStateTest, CheckWebGPUNonRecursiveBodyGood) {
-  std::string spirv = std::string(kVulkanMemoryHeader) + kNonRecursiveBody;
-  CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0));
-}
-
 TEST_F(ValidationStateTest, CheckDirectlyRecursiveBodyGood) {
   std::string spirv = std::string(kHeader) + kDirectlyRecursiveBody;
   CompileSuccessfully(spirv);
@@ -267,16 +261,6 @@
                         " %1 = OpFunction %void Pure|Const %3\n"));
 }
 
-TEST_F(ValidationStateTest, CheckWebGPUDirectlyRecursiveBodyBad) {
-  std::string spirv = std::string(kVulkanMemoryHeader) + kDirectlyRecursiveBody;
-  CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
-            ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Entry points may not have a call graph with cycles.\n "
-                        " %1 = OpFunction %void Pure|Const %3\n"));
-}
-
 TEST_F(ValidationStateTest, CheckIndirectlyRecursiveBodyGood) {
   std::string spirv = std::string(kHeader) + kIndirectlyRecursiveBody;
   CompileSuccessfully(spirv);
@@ -294,68 +278,6 @@
                         " %1 = OpFunction %void Pure|Const %3\n"));
 }
 
-// Indirectly recursive functions are caught by the function definition layout
-// rules, because they cause a situation where there are 2 functions that have
-// to be before each other, and layout is checked earlier.
-TEST_F(ValidationStateTest, CheckWebGPUIndirectlyRecursiveBodyBad) {
-  std::string spirv =
-      std::string(kVulkanMemoryHeader) + kIndirectlyRecursiveBody;
-  CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT,
-            ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, functions need to be defined before being "
-                        "called.\n  %10 = OpFunctionCall %_struct_5 %11\n"));
-}
-
-TEST_F(ValidationStateTest,
-       CheckWebGPUDuplicateEntryNamesDifferentFunctionsBad) {
-  std::string spirv = std::string(kVulkanMemoryHeader) + R"(
-OpEntryPoint Fragment %func_1 "main"
-OpEntryPoint Vertex %func_2 "main"
-OpExecutionMode %func_1 OriginUpperLeft
-%void    = OpTypeVoid
-%void_f  = OpTypeFunction %void
-%func_1  = OpFunction %void None %void_f
-%label_1 = OpLabel
-           OpReturn
-           OpFunctionEnd
-%func_2  = OpFunction %void None %void_f
-%label_2 = OpLabel
-           OpReturn
-           OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
-            ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Entry point name \"main\" is not unique, which is not allow "
-                "in WebGPU env.\n  %1 = OpFunction %void None %4\n"));
-}
-
-TEST_F(ValidationStateTest, CheckWebGPUDuplicateEntryNamesSameFunctionBad) {
-  std::string spirv = std::string(kVulkanMemoryHeader) + R"(
-OpEntryPoint GLCompute %func_1 "main"
-OpEntryPoint Vertex %func_1 "main"
-%void    = OpTypeVoid
-%void_f  = OpTypeFunction %void
-%func_1  = OpFunction %void None %void_f
-%label_1 = OpLabel
-           OpReturn
-           OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv, SPV_ENV_WEBGPU_0);
-  EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
-            ValidateAndRetrieveValidationState(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Entry point name \"main\" is not unique, which is not allow "
-                "in WebGPU env.\n  %1 = OpFunction %void None %3\n"));
-}
-
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_version_test.cpp b/third_party/SPIRV-Tools/test/val/val_version_test.cpp
index 2b9542a..98565dd 100644
--- a/third_party/SPIRV-Tools/test/val/val_version_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_version_test.cpp
@@ -40,21 +40,6 @@
 OpFunctionEnd
 )";
 
-const std::string webgpu_spirv = R"(
-OpCapability Shader
-OpCapability VulkanMemoryModelKHR
-OpExtension "SPV_KHR_vulkan_memory_model"
-OpMemoryModel Logical VulkanKHR
-OpEntryPoint Fragment %func "func"
-OpExecutionMode %func OriginUpperLeft
-%void = OpTypeVoid
-%functy = OpTypeFunction %void
-%func = OpFunction %void None %functy
-%1 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
 const std::string opencl_spirv = R"(
 OpCapability Addresses
 OpCapability Kernel
@@ -85,7 +70,6 @@
       return "1.2";
     case SPV_ENV_UNIVERSAL_1_3:
     case SPV_ENV_VULKAN_1_1:
-    case SPV_ENV_WEBGPU_0:
       return "1.3";
     case SPV_ENV_UNIVERSAL_1_4:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
@@ -126,7 +110,6 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_2,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_3,    vulkan_spirv, true),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_OPENGL_4_5,    vulkan_spirv, true),
-    std::make_tuple(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_WEBGPU_0,      webgpu_spirv, true),
 
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, true),
@@ -139,7 +122,6 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false),
-    std::make_tuple(SPV_ENV_UNIVERSAL_1_1, SPV_ENV_WEBGPU_0,      webgpu_spirv, true),
 
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false),
@@ -152,7 +134,6 @@
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_2,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false),
-    std::make_tuple(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_WEBGPU_0,      webgpu_spirv, true),
 
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_0, vulkan_spirv, false),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_1, vulkan_spirv, false),
@@ -164,8 +145,7 @@
     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),
     std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_3,    vulkan_spirv, false),
-    std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false),
-    std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_WEBGPU_0,      webgpu_spirv, true)
+    std::make_tuple(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_OPENGL_4_5,    vulkan_spirv, false)
   )
 );
 
diff --git a/third_party/SPIRV-Tools/test/val/val_webgpu_test.cpp b/third_party/SPIRV-Tools/test/val/val_webgpu_test.cpp
deleted file mode 100644
index 62fa6a7..0000000
--- a/third_party/SPIRV-Tools/test/val/val_webgpu_test.cpp
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright (c) 2018 Google Inc.
-//
-// 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.
-
-// Validation tests for WebGPU env specific checks
-
-#include <string>
-
-#include "gmock/gmock.h"
-#include "test/val/val_fixtures.h"
-
-namespace spvtools {
-namespace val {
-namespace {
-
-using testing::HasSubstr;
-
-using ValidateWebGPU = spvtest::ValidateBase<bool>;
-
-TEST_F(ValidateWebGPU, OpUndefIsDisallowed) {
-  std::string spirv = R"(
-          OpCapability Shader
-          OpCapability VulkanMemoryModelKHR
-          OpExtension "SPV_KHR_vulkan_memory_model"
-          OpMemoryModel Logical VulkanKHR
-          OpEntryPoint Vertex %func "shader"
-%float  = OpTypeFloat 32
-%1      = OpUndef %float
-%void   = OpTypeVoid
-%void_f = OpTypeFunction %void
-%func   = OpFunction %void None %void_f
-%label  = OpLabel
-          OpReturn
-          OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-
-  // Control case: OpUndef is allowed in SPIR-V 1.3
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-
-  // Control case: OpUndef is disallowed in the WebGPU env
-  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("OpUndef is disallowed"));
-}
-
-TEST_F(ValidateWebGPU, OpNameIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-            OpName %1 "foo"
-       %1 = OpTypeFloat 32
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpMemberNameIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-            OpMemberName %2 0 "foo"
-       %1 = OpTypeFloat 32
-       %2 = OpTypeStruct %1
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpSourceIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-            OpSource GLSL 450
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpSourceContinuedIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-            OpSource GLSL 450
-            OpSourceContinued "I am a happy shader! Yay! ;"
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpSourceExtensionIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-            OpSourceExtension "bar"
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpStringIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-       %1 = OpString "foo"
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpLineIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-       %1 = OpString "minimal.vert"
-            OpLine %1 1 1
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, OpNoLineIsAllowed) {
-  std::string spirv = R"(
-            OpCapability Shader
-            OpCapability VulkanMemoryModelKHR
-            OpExtension "SPV_KHR_vulkan_memory_model"
-            OpMemoryModel Logical VulkanKHR
-            OpEntryPoint Vertex %func "shader"
-            OpNoLine
-  %void   = OpTypeVoid
-  %void_f = OpTypeFunction %void
-  %func   = OpFunction %void None %void_f
-  %label  = OpLabel
-            OpReturn
-            OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, LogicalAddressingVulkanKHRMemoryGood) {
-  std::string spirv = R"(
-          OpCapability Shader
-          OpCapability VulkanMemoryModelKHR
-          OpExtension "SPV_KHR_vulkan_memory_model"
-          OpMemoryModel Logical VulkanKHR
-          OpEntryPoint Vertex %func "shader"
-%void   = OpTypeVoid
-%void_f = OpTypeFunction %void
-%func   = OpFunction %void None %void_f
-%label  = OpLabel
-          OpReturn
-          OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, LogicalAddressingGLSL450MemoryGood) {
-  std::string spirv = R"(
-          OpCapability Shader
-          OpMemoryModel Logical GLSL450
-          OpEntryPoint Vertex %func "shader"
-%void   = OpTypeVoid
-%void_f = OpTypeFunction %void
-%func   = OpFunction %void None %void_f
-%label  = OpLabel
-          OpReturn
-          OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, LogicalAddressingSimpleMemoryGood) {
-  std::string spirv = R"(
-          OpCapability Shader
-          OpMemoryModel Logical Simple
-          OpEntryPoint Vertex %func "shader"
-%void   = OpTypeVoid
-%void_f = OpTypeFunction %void
-%func   = OpFunction %void None %void_f
-%label  = OpLabel
-          OpReturn
-          OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, KernelIsBad) {
-  std::string spirv = R"(
-     OpCapability Kernel
-     OpMemoryModel Logical Simple
-     OpNoLine
-)";
-
-  CompileSuccessfully(spirv);
-
-  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Capability Kernel is not allowed by WebGPU "
-                        "specification (or requires extension)"));
-}
-
-TEST_F(ValidateWebGPU, OpenCLMemoryModelBad) {
-  std::string spirv = R"(
-     OpCapability Shader
-     OpMemoryModel Logical OpenCL
-     OpNoLine
-)";
-
-  CompileSuccessfully(spirv);
-
-  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
-            ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 2 of MemoryModel requires one of these "
-                        "capabilities: Kernel"));
-}
-
-TEST_F(ValidateWebGPU, AllowListedExtendedInstructionsImportGood) {
-  std::string spirv = R"(
-          OpCapability Shader
-          OpCapability VulkanMemoryModelKHR
-          OpExtension "SPV_KHR_vulkan_memory_model"
-%1      = OpExtInstImport "GLSL.std.450"
-          OpMemoryModel Logical VulkanKHR
-          OpEntryPoint Vertex %func "shader"
-%void   = OpTypeVoid
-%void_f = OpTypeFunction %void
-%func   = OpFunction %void None %void_f
-%label  = OpLabel
-          OpReturn
-          OpFunctionEnd
-)";
-
-  CompileSuccessfully(spirv);
-
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, NonAllowListedExtendedInstructionsImportBad) {
-  std::string spirv = R"(
-     OpCapability Shader
-     OpCapability VulkanMemoryModelKHR
-     OpExtension "SPV_KHR_vulkan_memory_model"
-%1 = OpExtInstImport "OpenCL.std"
-     OpMemoryModel Logical VulkanKHR
-)";
-
-  CompileSuccessfully(spirv);
-
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, the only valid parameter to "
-                        "OpExtInstImport is \"GLSL.std.450\".\n  %1 = "
-                        "OpExtInstImport \"OpenCL.std\"\n"));
-}
-
-TEST_F(ValidateWebGPU, NonVulkanKHRMemoryModelExtensionBad) {
-  std::string spirv = R"(
-     OpCapability Shader
-     OpCapability VulkanMemoryModelKHR
-     OpExtension "SPV_KHR_8bit_storage"
-     OpExtension "SPV_KHR_vulkan_memory_model"
-     OpMemoryModel Logical VulkanKHR
-)";
-
-  CompileSuccessfully(spirv);
-
-  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("For WebGPU, the only valid parameter to OpExtension "
-                        "is \"SPV_KHR_vulkan_memory_model\".\n  OpExtension "
-                        "\"SPV_KHR_8bit_storage\"\n"));
-}
-
-spv_binary GenerateTrivialBinary(bool need_little_endian) {
-  // Smallest possible valid WebGPU SPIR-V binary in little endian. Contains all
-  // the required boilerplate and a trivial entry point function.
-  static const uint8_t binary_bytes[] = {
-      // clang-format off
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00,
-    0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0xE1, 0x14, 0x00, 0x00,
-    0x0A, 0x00, 0x08, 0x00, 0x53, 0x50, 0x56, 0x5F, 0x4B, 0x48, 0x52, 0x5F,
-    0x76, 0x75, 0x6C, 0x6B, 0x61, 0x6E, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72,
-    0x79, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x6C, 0x00, 0x0E, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x05, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x64,
-    0x65, 0x72, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
-    0x04, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
-      // clang-format on
-  };
-  static const size_t word_count = sizeof(binary_bytes) / sizeof(uint32_t);
-  std::unique_ptr<spv_binary_t> result(new spv_binary_t);
-  if (!result) return nullptr;
-
-  result->wordCount = word_count;
-  result->code = new uint32_t[word_count];
-  if (!result->code) return nullptr;
-
-  if (need_little_endian) {
-    memcpy(result->code, binary_bytes, sizeof(binary_bytes));
-  } else {
-    uint8_t* code_bytes = reinterpret_cast<uint8_t*>(result->code);
-    for (size_t word = 0; word < word_count; ++word) {
-      code_bytes[4 * word] = binary_bytes[4 * word + 3];
-      code_bytes[4 * word + 1] = binary_bytes[4 * word + 2];
-      code_bytes[4 * word + 2] = binary_bytes[4 * word + 1];
-      code_bytes[4 * word + 3] = binary_bytes[4 * word];
-    }
-  }
-
-  return result.release();
-}
-
-TEST_F(ValidateWebGPU, LittleEndianGood) {
-  DestroyBinary();
-  binary_ = GenerateTrivialBinary(true);
-  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
-}
-
-TEST_F(ValidateWebGPU, BigEndianBad) {
-  DestroyBinary();
-  binary_ = GenerateTrivialBinary(false);
-  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("WebGPU requires SPIR-V to be little endian."));
-}
-
-}  // namespace
-}  // namespace val
-}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/tools/link/linker.cpp b/third_party/SPIRV-Tools/tools/link/linker.cpp
index 82d430e..1956f59 100644
--- a/third_party/SPIRV-Tools/tools/link/linker.cpp
+++ b/third_party/SPIRV-Tools/tools/link/linker.cpp
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "spirv-tools/linker.hpp"
+
 #include <cstring>
 #include <iostream>
 #include <vector>
@@ -19,42 +21,56 @@
 #include "source/spirv_target_env.h"
 #include "source/table.h"
 #include "spirv-tools/libspirv.hpp"
-#include "spirv-tools/linker.hpp"
 #include "tools/io.h"
 
-void print_usage(char* argv0) {
-  std::string target_env_list = spvTargetEnvList(27, 95);
+namespace {
+
+const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_5;
+
+void print_usage(const char* program) {
+  std::string target_env_list = spvTargetEnvList(16, 80);
+  // NOTE: Please maintain flags in lexicographical order.
   printf(
       R"(%s - Link SPIR-V binary files together.
 
-USAGE: %s [options] <filename> [<filename> ...]
+USAGE: %s [options] [-o <output>] <input>...
 
-The SPIR-V binaries are read from the different <filename>.
+The SPIR-V binaries are read from the different <input>(s).
+The SPIR-V resulting linked binary module is written to the file "out.spv"
+unless the -o option is used; if <output> is "-", it is written to the standard
+output.
 
 NOTE: The linker is a work in progress.
 
-Options:
-  -h, --help              Print this help.
-  -o                      Name of the resulting linked SPIR-V binary.
-  --create-library        Link the binaries into a library, keeping all exported symbols.
-  --allow-partial-linkage Allow partial linkage by accepting imported symbols to be unresolved.
-  --verify-ids            Verify that IDs in the resulting modules are truly unique.
-  --version               Display linker version information
-  --target-env            {%s}
-                          Use validation rules from the specified environment.
+Options (in lexicographical order):
+  --allow-partial-linkage
+               Allow partial linkage by accepting imported symbols to be
+               unresolved.
+  --create-library
+               Link the binaries into a library, keeping all exported symbols.
+  -h, --help
+                  Print this help.
+  --target-env <env>
+               Set the target environment. Without this flag the target
+               environment defaults to spv1.5. <env> must be one of
+               {%s}
+  --verify-ids
+               Verify that IDs in the resulting modules are truly unique.
+  --version
+               Display linker version information
 )",
-      argv0, argv0, target_env_list.c_str());
+      program, program, target_env_list.c_str());
 }
 
+}  // namespace
+
 int main(int argc, char** argv) {
   std::vector<const char*> inFiles;
   const char* outFile = nullptr;
-  spv_target_env target_env = SPV_ENV_UNIVERSAL_1_0;
+  spv_target_env target_env = kDefaultEnvironment;
   spvtools::LinkerOptions options;
-  bool continue_processing = true;
-  int return_code = 0;
 
-  for (int argi = 1; continue_processing && argi < argc; ++argi) {
+  for (int argi = 1; argi < argc; ++argi) {
     const char* cur_arg = argv[argi];
     if ('-' == cur_arg[0]) {
       if (0 == strcmp(cur_arg, "-o")) {
@@ -63,55 +79,48 @@
             outFile = argv[++argi];
           } else {
             fprintf(stderr, "error: More than one output file specified\n");
-            continue_processing = false;
-            return_code = 1;
+            return 1;
           }
         } else {
           fprintf(stderr, "error: Missing argument to %s\n", cur_arg);
-          continue_processing = false;
-          return_code = 1;
+          return 1;
         }
-      } else if (0 == strcmp(cur_arg, "--create-library")) {
-        options.SetCreateLibrary(true);
-      } else if (0 == strcmp(cur_arg, "--verify-ids")) {
-        options.SetVerifyIds(true);
       } else if (0 == strcmp(cur_arg, "--allow-partial-linkage")) {
         options.SetAllowPartialLinkage(true);
-      } else if (0 == strcmp(cur_arg, "--version")) {
-        printf("%s\n", spvSoftwareVersionDetailsString());
-        // TODO(dneto): Add OpenCL 2.2 at least.
-        printf("Targets:\n  %s\n  %s\n  %s\n",
-               spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_1),
-               spvTargetEnvDescription(SPV_ENV_VULKAN_1_0),
-               spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_2));
-        continue_processing = false;
-        return_code = 0;
+      } else if (0 == strcmp(cur_arg, "--create-library")) {
+        options.SetCreateLibrary(true);
       } else if (0 == strcmp(cur_arg, "--help") || 0 == strcmp(cur_arg, "-h")) {
         print_usage(argv[0]);
-        continue_processing = false;
-        return_code = 0;
+        return 0;
       } else if (0 == strcmp(cur_arg, "--target-env")) {
         if (argi + 1 < argc) {
           const auto env_str = argv[++argi];
           if (!spvParseTargetEnv(env_str, &target_env)) {
             fprintf(stderr, "error: Unrecognized target env: %s\n", env_str);
-            continue_processing = false;
-            return_code = 1;
+            return 1;
           }
         } else {
           fprintf(stderr, "error: Missing argument to --target-env\n");
-          continue_processing = false;
-          return_code = 1;
+          return 1;
         }
+      } else if (0 == strcmp(cur_arg, "--verify-ids")) {
+        options.SetVerifyIds(true);
+      } else if (0 == strcmp(cur_arg, "--version")) {
+        printf("%s\n", spvSoftwareVersionDetailsString());
+        printf("Target: %s\n", spvTargetEnvDescription(target_env));
+        return 0;
+      } else {
+        fprintf(stderr, "error: Unrecognized option: %s\n\n", argv[argi]);
+        print_usage(argv[0]);
+        return 1;
       }
     } else {
       inFiles.push_back(cur_arg);
     }
   }
 
-  // Exit if command line parsing was not successful.
-  if (!continue_processing) {
-    return return_code;
+  if (!outFile) {
+    outFile = "out.spv";
   }
 
   if (inFiles.empty()) {
diff --git a/third_party/SPIRV-Tools/tools/opt/opt.cpp b/third_party/SPIRV-Tools/tools/opt/opt.cpp
index 66f9228..e7e5899 100644
--- a/third_party/SPIRV-Tools/tools/opt/opt.cpp
+++ b/third_party/SPIRV-Tools/tools/opt/opt.cpp
@@ -79,18 +79,6 @@
   return GetListOfPassesAsString(optimizer);
 }
 
-std::string GetVulkanToWebGPUPasses() {
-  spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_1);
-  optimizer.RegisterVulkanToWebGPUPasses();
-  return GetListOfPassesAsString(optimizer);
-}
-
-std::string GetWebGPUToVulkanPasses() {
-  spvtools::Optimizer optimizer(SPV_ENV_WEBGPU_0);
-  optimizer.RegisterWebGPUToVulkanPasses();
-  return GetListOfPassesAsString(optimizer);
-}
-
 void PrintUsage(const char* program) {
   std::string target_env_list = spvTargetEnvList(16, 80);
   // NOTE: Please maintain flags in lexicographical order.
@@ -239,10 +227,6 @@
                values, providing guarantees that satisfy Vulkan's
                robustBufferAccess rules.)");
   printf(R"(
-  --generate-webgpu-initializers
-               Adds initial values to OpVariable instructions that are missing
-               them, due to their storage type requiring them for WebGPU.)");
-  printf(R"(
   --if-conversion
                Convert if-then-else like assignments into OpSelect.)");
   printf(R"(
@@ -261,11 +245,6 @@
                option --relax-logical-pointer to the validator.)",
          GetLegalizationPasses().c_str());
   printf(R"(
-  --legalize-vector-shuffle
-               Converts any usages of 0xFFFFFFFF for the literals in
-               OpVectorShuffle to a literal 0. This is done since 0xFFFFFFFF is
-               forbidden in WebGPU.)");
-  printf(R"(
   --local-redundancy-elimination
                Looks for instructions in the same basic block that compute the
                same value, and deletes the redundant ones.)");
@@ -463,13 +442,6 @@
                Forwards this option to the validator.  See the validator help
                for details.)");
   printf(R"(
-  --split-invalid-unreachable
-               Attempts to legalize for WebGPU cases where an unreachable
-               merge-block is also a continue-target by splitting it into two
-               separate blocks. There exist legal, for Vulkan, instances of this
-               pattern that cannot be converted into legal WebGPU, so this
-               conversion may not succeed.)");
-  printf(R"(
   --skip-validation
                Will not validate the SPIR-V before optimizing.  If the SPIR-V
                is invalid, the optimizer may fail or generate incorrect code.
@@ -513,34 +485,6 @@
                removes them from the vector.  Note this would still leave around
                lots of dead code that a pass of ADCE will be able to remove.)");
   printf(R"(
-  --vulkan-to-webgpu
-               Turns on the prescribed passes for converting from Vulkan to
-               WebGPU and sets the target environment to webgpu0. Other passes
-               may be turned on via additional flags, but such combinations are
-               not tested.
-               Using --target-env with this flag is not allowed.
-
-               This flag is the equivalent of passing in --target-env=webgpu0
-               and specifying the following optimization code names:
-               %s
-
-               NOTE: This flag is a WIP and its behaviour is subject to change.)",
-         GetVulkanToWebGPUPasses().c_str());
-  printf(R"(
-  --webgpu-to-vulkan
-               Turns on the prescribed passes for converting from WebGPU to
-               Vulkan and sets the target environment to vulkan1.1. Other passes
-               may be turned on via additional flags, but such combinations are
-               not tested.
-               Using --target-env with this flag is not allowed.
-
-               This flag is the equivalent of passing in --target-env=vulkan1.1
-               and specifying the following optimization code names:
-               %s
-
-               NOTE: This flag is a WIP and its behaviour is subject to change.)",
-         GetWebGPUToVulkanPasses().c_str());
-  printf(R"(
   --workaround-1209
                Rewrites instructions for which there are known driver bugs to
                avoid triggering those bugs.
@@ -714,9 +658,6 @@
                      spvtools::ValidatorOptions* validator_options,
                      spvtools::OptimizerOptions* optimizer_options) {
   std::vector<std::string> pass_flags;
-  bool target_env_set = false;
-  bool vulkan_to_webgpu_set = false;
-  bool webgpu_to_vulkan_set = false;
   for (int argi = 1; argi < argc; ++argi) {
     const char* cur_arg = argv[argi];
     if ('-' == cur_arg[0]) {
@@ -781,19 +722,6 @@
                                              max_id_bound);
       } else if (0 == strncmp(cur_arg,
                               "--target-env=", sizeof("--target-env=") - 1)) {
-        target_env_set = true;
-        if (vulkan_to_webgpu_set) {
-          spvtools::Error(opt_diagnostic, nullptr, {},
-                          "--vulkan-to-webgpu defines the target environment, "
-                          "so --target-env cannot be set at the same time");
-          return {OPT_STOP, 1};
-        }
-        if (webgpu_to_vulkan_set) {
-          spvtools::Error(opt_diagnostic, nullptr, {},
-                          "--webgpu-to-vulkan defines the target environment, "
-                          "so --target-env cannot be set at the same time");
-          return {OPT_STOP, 1};
-        }
         const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
         const auto target_env_str = split_flag.second.c_str();
         spv_target_env target_env;
@@ -803,42 +731,6 @@
           return {OPT_STOP, 1};
         }
         optimizer->SetTargetEnv(target_env);
-      } else if (0 == strcmp(cur_arg, "--vulkan-to-webgpu")) {
-        vulkan_to_webgpu_set = true;
-        if (target_env_set) {
-          spvtools::Error(opt_diagnostic, nullptr, {},
-                          "--vulkan-to-webgpu defines the target environment, "
-                          "so --target-env cannot be set at the same time");
-          return {OPT_STOP, 1};
-        }
-        if (webgpu_to_vulkan_set) {
-          spvtools::Error(opt_diagnostic, nullptr, {},
-                          "Cannot use both --webgpu-to-vulkan and "
-                          "--vulkan-to-webgpu at the same time, invoke twice "
-                          "if you are wanting to go to and from");
-          return {OPT_STOP, 1};
-        }
-
-        optimizer->SetTargetEnv(SPV_ENV_VULKAN_1_1);
-        optimizer->RegisterVulkanToWebGPUPasses();
-      } else if (0 == strcmp(cur_arg, "--webgpu-to-vulkan")) {
-        webgpu_to_vulkan_set = true;
-        if (target_env_set) {
-          spvtools::Error(opt_diagnostic, nullptr, {},
-                          "--webgpu-to-vulkan defines the target environment, "
-                          "so --target-env cannot be set at the same time");
-          return {OPT_STOP, 1};
-        }
-        if (vulkan_to_webgpu_set) {
-          spvtools::Error(opt_diagnostic, nullptr, {},
-                          "Cannot use both --webgpu-to-vulkan and "
-                          "--vulkan-to-webgpu at the same time, invoke twice "
-                          "if you are wanting to go to and from");
-          return {OPT_STOP, 1};
-        }
-
-        optimizer->SetTargetEnv(SPV_ENV_WEBGPU_0);
-        optimizer->RegisterWebGPUToVulkanPasses();
       } else if (0 == strcmp(cur_arg, "--validate-after-all")) {
         optimizer->SetValidateAfterAll(true);
       } else if (0 == strcmp(cur_arg, "--before-hlsl-legalization")) {
diff --git a/third_party/SPIRV-Tools/tools/sva/yarn.lock b/third_party/SPIRV-Tools/tools/sva/yarn.lock
index 34a1808..c46b901 100644
--- a/third_party/SPIRV-Tools/tools/sva/yarn.lock
+++ b/third_party/SPIRV-Tools/tools/sva/yarn.lock
@@ -795,9 +795,9 @@
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
 
 ini@~1.3.0:
-  version "1.3.5"
-  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
-  integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
+  integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
 
 inquirer@^6.4.1:
   version "6.5.2"
diff --git a/third_party/SPIRV-Tools/tools/val/val.cpp b/third_party/SPIRV-Tools/tools/val/val.cpp
index 19b8c77..da63245 100644
--- a/third_party/SPIRV-Tools/tools/val/val.cpp
+++ b/third_party/SPIRV-Tools/tools/val/val.cpp
@@ -108,7 +108,7 @@
         printf("%s\n", spvSoftwareVersionDetailsString());
         printf(
             "Targets:\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  "
-            "%s\n  %s\n",
+            "%s\n",
             spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0),
             spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_1),
             spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_2),
@@ -118,8 +118,7 @@
             spvTargetEnvDescription(SPV_ENV_OPENCL_2_2),
             spvTargetEnvDescription(SPV_ENV_VULKAN_1_0),
             spvTargetEnvDescription(SPV_ENV_VULKAN_1_1),
-            spvTargetEnvDescription(SPV_ENV_VULKAN_1_1_SPIRV_1_4),
-            spvTargetEnvDescription(SPV_ENV_WEBGPU_0));
+            spvTargetEnvDescription(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
         continue_processing = false;
         return_code = 0;
       } else if (0 == strcmp(cur_arg, "--help") || 0 == strcmp(cur_arg, "-h")) {
diff --git a/third_party/SPIRV-Tools/utils/check_copyright.py b/third_party/SPIRV-Tools/utils/check_copyright.py
index 39d27cb..b15bc20 100755
--- a/third_party/SPIRV-Tools/utils/check_copyright.py
+++ b/third_party/SPIRV-Tools/utils/check_copyright.py
@@ -39,7 +39,7 @@
            'Stefano Milizia']
 CURRENT_YEAR='2020'
 
-YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020)'
+YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020|2021)'
 COPYRIGHT_RE = re.compile(
         'Copyright \(c\) {} ({})'.format(YEARS, '|'.join(AUTHORS)))
 
diff --git a/third_party/SPIRV-Tools/utils/git-sync-deps b/third_party/SPIRV-Tools/utils/git-sync-deps
index 0575641..eecfbe9 100755
--- a/third_party/SPIRV-Tools/utils/git-sync-deps
+++ b/third_party/SPIRV-Tools/utils/git-sync-deps
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2014 Google Inc.
 #
 # Redistribution and use in source and binary forms, with or without