spirv-val: Add Vulkan VUID labels to BuiltIn (#3756)

The Vulkan 1.2.152 headers/spec now include Valid Usage IDs (VUID)
for every BuiltIn. This change adds labeling to help aid tracking
the coverage gap in Vulkan targeted validation. This is done with
a script in the Validation Layers that parses the source for VUID
strings, both that there is an implementation and a test for it.

There are 2 main changes:

1. A VUID string is added where applicable. It is wrapped in a function
that at runtimes checks if Vulkan is the target so that other targets
will not be effected as the output error only changes for Vulkan and
the overhead only occurs if there is an error at all.

2. For unit test, a new parameter value was added to allow make sure
that for each VUID there is a matching test. There are cases where the
same unit test checks multiple VUs via the parameter feature of gtest.
For this, I added a custom gMock Matcher to simply loop over a list
of VUID strings
diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp
index d86c91e..ab232c8 100644
--- a/source/val/validate_builtins.cpp
+++ b/source/val/validate_builtins.cpp
@@ -365,7 +365,7 @@
   // |referenced_from_inst| - instruction which references id defined by
   //                          |referenced_inst| from within a function.
   spv_result_t ValidateNotCalledWithExecutionModel(
-      const char* comment, SpvExecutionModel execution_model,
+      std::string comment, SpvExecutionModel execution_model,
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
@@ -864,7 +864,7 @@
 }
 
 spv_result_t BuiltInsValidator::ValidateNotCalledWithExecutionModel(
-    const char* comment, SpvExecutionModel execution_model,
+    std::string comment, SpvExecutionModel execution_model,
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
@@ -903,6 +903,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
+  uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
@@ -911,7 +912,7 @@
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+                                              operand)
              << " to be only used for variables with Input or Output storage "
                 "class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -949,7 +950,12 @@
                   decoration, built_in_inst, /* Any number of components */ 0,
                   [this, &decoration, &referenced_from_inst](
                       const std::string& message) -> spv_result_t {
+                    uint32_t vuid =
+                        (decoration.params()[0] == SpvBuiltInClipDistance)
+                            ? 4191
+                            : 4200;
                     return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                           << _.VkErrorID(vuid)
                            << "According to the Vulkan spec BuiltIn "
                            << _.grammar().lookupOperandName(
                                   SPV_OPERAND_TYPE_BUILT_IN,
@@ -971,8 +977,13 @@
                     decoration, built_in_inst, /* Any number of components */ 0,
                     [this, &decoration, &referenced_from_inst](
                         const std::string& message) -> spv_result_t {
+                      uint32_t vuid =
+                          (decoration.params()[0] == SpvBuiltInClipDistance)
+                              ? 4191
+                              : 4200;
                       return _.diag(SPV_ERROR_INVALID_DATA,
                                     &referenced_from_inst)
+                             << _.VkErrorID(vuid)
                              << "According to the Vulkan spec BuiltIn "
                              << _.grammar().lookupOperandName(
                                     SPV_OPERAND_TYPE_BUILT_IN,
@@ -987,8 +998,13 @@
                     decoration, built_in_inst, /* Any number of components */ 0,
                     [this, &decoration, &referenced_from_inst](
                         const std::string& message) -> spv_result_t {
+                      uint32_t vuid =
+                          (decoration.params()[0] == SpvBuiltInClipDistance)
+                              ? 4191
+                              : 4200;
                       return _.diag(SPV_ERROR_INVALID_DATA,
                                     &referenced_from_inst)
+                             << _.VkErrorID(vuid)
                              << "According to the Vulkan spec BuiltIn "
                              << _.grammar().lookupOperandName(
                                     SPV_OPERAND_TYPE_BUILT_IN,
@@ -1003,10 +1019,12 @@
         }
 
         default: {
+          uint32_t vuid =
+              (decoration.params()[0] == SpvBuiltInClipDistance) ? 4187 : 4196;
           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,
-                                                  decoration.params()[0])
+                                                  operand)
                  << " to be used only with Fragment, Vertex, "
                     "TessellationControl, TessellationEvaluation or Geometry "
                     "execution models. "
@@ -1035,7 +1053,7 @@
             decoration, inst, 4,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(4212) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn FragCoord "
                         "variable needs to be a 4-component 32-bit float "
@@ -1059,7 +1077,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << spvLogStringForEnv(_.context()->target_env)
+             << _.VkErrorID(4211) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FragCoord to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1070,6 +1088,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4210)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn FragCoord to be used only with "
                   "Fragment execution model. "
@@ -1096,7 +1115,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(4215) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn FragDepth "
                         "variable needs to be a 32-bit float scalar. "
@@ -1119,7 +1138,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassOutput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << spvLogStringForEnv(_.context()->target_env)
+             << _.VkErrorID(4214) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FragDepth to be only used for "
                 "variables with Output storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1130,6 +1149,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4213)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn FragDepth to be used only with "
                   "Fragment execution model. "
@@ -1144,6 +1164,7 @@
       const auto* modes = _.GetExecutionModes(entry_point);
       if (!modes || !modes->count(SpvExecutionModeDepthReplacing)) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4216)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec requires DepthReplacing execution mode to be "
                   "declared when using BuiltIn FragDepth. "
@@ -1170,7 +1191,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(4231) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn FrontFacing "
                         "variable needs to be a bool scalar. "
@@ -1193,7 +1214,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << spvLogStringForEnv(_.context()->target_env)
+             << _.VkErrorID(4230) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FrontFacing to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1204,6 +1225,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4229)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn FrontFacing to be used only with "
                   "Fragment execution model. "
@@ -1230,6 +1252,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4241)
                      << "According to the Vulkan spec BuiltIn HelperInvocation "
                         "variable needs to be a bool scalar. "
                      << message;
@@ -1251,6 +1274,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4240)
              << "Vulkan spec allows BuiltIn HelperInvocation to be only used "
                 "for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1261,6 +1285,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4239)
                << "Vulkan spec allows BuiltIn HelperInvocation to be used only "
                   "with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1287,6 +1312,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4259)
                      << "According to the Vulkan spec BuiltIn InvocationId "
                         "variable needs to be a 32-bit int scalar. "
                      << message;
@@ -1308,6 +1334,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4258)
              << "Vulkan spec allows BuiltIn InvocationId to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1319,6 +1346,7 @@
       if (execution_model != SpvExecutionModelTessellationControl &&
           execution_model != SpvExecutionModelGeometry) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4257)
                << "Vulkan spec allows BuiltIn InvocationId to be used only "
                   "with TessellationControl or Geometry execution models. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1344,7 +1372,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(4265) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn InstanceIndex "
                         "variable needs to be a 32-bit int scalar. "
@@ -1367,7 +1395,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << spvLogStringForEnv(_.context()->target_env)
+             << _.VkErrorID(4264) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn InstanceIndex to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1378,6 +1406,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelVertex) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4263)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn InstanceIndex to be used only "
                   "with Vertex execution model. "
@@ -1404,6 +1433,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4310)
                      << "According to the Vulkan spec BuiltIn PatchVertices "
                         "variable needs to be a 32-bit int scalar. "
                      << message;
@@ -1425,6 +1455,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4309)
              << "Vulkan spec allows BuiltIn PatchVertices to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1436,6 +1467,7 @@
       if (execution_model != SpvExecutionModelTessellationControl &&
           execution_model != SpvExecutionModelTessellationEvaluation) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4308)
                << "Vulkan spec allows BuiltIn PatchVertices to be used only "
                   "with TessellationControl or TessellationEvaluation "
                   "execution models. "
@@ -1462,6 +1494,7 @@
             decoration, inst, 2,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4313)
                      << "According to the Vulkan spec BuiltIn PointCoord "
                         "variable needs to be a 2-component 32-bit float "
                         "vector. "
@@ -1484,6 +1517,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4312)
              << "Vulkan spec allows BuiltIn PointCoord to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1494,6 +1528,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4311)
                << "Vulkan spec allows BuiltIn PointCoord to be used only with "
                   "Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1528,6 +1563,7 @@
         storage_class != SpvStorageClassInput &&
         storage_class != SpvStorageClassOutput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4316)
              << "Vulkan spec allows BuiltIn PointSize to be only used for "
                 "variables with Input or Output storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1539,8 +1575,11 @@
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this,
-          "Vulkan spec doesn't allow BuiltIn PointSize to be used for "
-          "variables with Input storage class if execution model is Vertex.",
+          std::string(
+              _.VkErrorID(4315) +
+              "Vulkan spec doesn't allow BuiltIn PointSize 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));
     }
@@ -1553,6 +1592,7 @@
                   [this, &referenced_from_inst](
                       const std::string& message) -> spv_result_t {
                     return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                           << _.VkErrorID(4317)
                            << "According to the Vulkan spec BuiltIn PointSize "
                               "variable needs to be a 32-bit float scalar. "
                            << message;
@@ -1576,6 +1616,7 @@
                         const std::string& message) -> spv_result_t {
                       return _.diag(SPV_ERROR_INVALID_DATA,
                                     &referenced_from_inst)
+                             << _.VkErrorID(4317)
                              << "According to the Vulkan spec BuiltIn "
                                 "PointSize variable needs to be a 32-bit "
                                 "float scalar. "
@@ -1590,6 +1631,7 @@
                         const std::string& message) -> spv_result_t {
                       return _.diag(SPV_ERROR_INVALID_DATA,
                                     &referenced_from_inst)
+                             << _.VkErrorID(4317)
                              << "According to the Vulkan spec BuiltIn "
                                 "PointSize variable needs to be a 32-bit "
                                 "float scalar. "
@@ -1603,6 +1645,7 @@
 
         default: {
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                 << _.VkErrorID(4314)
                  << "Vulkan spec allows BuiltIn PointSize to be used only with "
                     "Vertex, TessellationControl, TessellationEvaluation or "
                     "Geometry execution models. "
@@ -1650,8 +1693,10 @@
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this,
-          "Vulkan spec doesn't allow BuiltIn Position to be used for variables "
-          "with Input storage class if execution model is Vertex.",
+          std::string(_.VkErrorID(4320) +
+                      "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));
     }
@@ -1664,6 +1709,7 @@
                   [this, &referenced_from_inst](
                       const std::string& message) -> spv_result_t {
                     return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                           << _.VkErrorID(4321)
                            << "According to the Vulkan spec BuiltIn Position "
                               "variable needs to be a 4-component 32-bit float "
                               "vector. "
@@ -1690,6 +1736,7 @@
                         const std::string& message) -> spv_result_t {
                       return _.diag(SPV_ERROR_INVALID_DATA,
                                     &referenced_from_inst)
+                             << _.VkErrorID(4321)
                              << "According to the Vulkan spec BuiltIn Position "
                                 "variable needs to be a 4-component 32-bit "
                                 "float vector. "
@@ -1704,6 +1751,7 @@
                         const std::string& message) -> spv_result_t {
                       return _.diag(SPV_ERROR_INVALID_DATA,
                                     &referenced_from_inst)
+                             << _.VkErrorID(4321)
                              << "According to the Vulkan spec BuiltIn Position "
                                 "variable needs to be a 4-component 32-bit "
                                 "float vector. "
@@ -1717,6 +1765,7 @@
 
         default: {
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                 << _.VkErrorID(4318)
                  << "Vulkan spec allows BuiltIn Position to be used only "
                     "with Vertex, TessellationControl, TessellationEvaluation"
                     " or Geometry execution models. "
@@ -1788,6 +1837,7 @@
               decoration, inst,
               [this, &inst](const std::string& message) -> spv_result_t {
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                       << _.VkErrorID(4337)
                        << "According to the Vulkan spec BuiltIn PrimitiveId "
                           "variable needs to be a 32-bit int scalar. "
                        << message;
@@ -1799,6 +1849,7 @@
               decoration, inst,
               [this, &inst](const std::string& message) -> spv_result_t {
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                       << _.VkErrorID(4337)
                        << "According to the Vulkan spec BuiltIn PrimitiveId "
                           "variable needs to be a 32-bit int scalar. "
                        << message;
@@ -1833,23 +1884,29 @@
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this,
-          "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
-          "variables with Output storage class if execution model is "
-          "TessellationControl.",
+          std::string(
+              _.VkErrorID(4334) +
+              "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
+              "variables with Output storage class if execution model is "
+              "TessellationControl."),
           SpvExecutionModelTessellationControl, 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,
-          "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
-          "variables with Output storage class if execution model is "
-          "TessellationEvaluation.",
+          std::string(
+              _.VkErrorID(4334) +
+              "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
+              "variables with Output storage class if execution model is "
+              "TessellationEvaluation."),
           SpvExecutionModelTessellationEvaluation, 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,
-          "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
-          "variables with Output storage class if execution model is "
-          "Fragment.",
+          std::string(
+              _.VkErrorID(4334) +
+              "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
+              "variables with Output storage class if execution model is "
+              "Fragment."),
           SpvExecutionModelFragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
@@ -1873,6 +1930,7 @@
 
         default: {
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                 << _.VkErrorID(4330)
                  << "Vulkan spec allows BuiltIn PrimitiveId to be used only "
                     "with Fragment, TessellationControl, "
                     "TessellationEvaluation or Geometry execution models. "
@@ -1900,6 +1958,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4356)
                      << "According to the Vulkan spec BuiltIn SampleId "
                         "variable needs to be a 32-bit int scalar. "
                      << message;
@@ -1921,6 +1980,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4355)
              << "Vulkan spec allows BuiltIn SampleId to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1931,6 +1991,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4354)
                << "Vulkan spec allows BuiltIn SampleId to be used only with "
                   "Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1956,6 +2017,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4359)
                      << "According to the Vulkan spec BuiltIn SampleMask "
                         "variable needs to be a 32-bit int array. "
                      << message;
@@ -1978,6 +2040,7 @@
         storage_class != SpvStorageClassInput &&
         storage_class != SpvStorageClassOutput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4358)
              << "Vulkan spec allows BuiltIn SampleMask to be only used for "
                 "variables with Input or Output storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -1988,6 +2051,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4357)
                << "Vulkan spec allows BuiltIn SampleMask to be used only "
                   "with "
                   "Fragment execution model. "
@@ -2014,6 +2078,7 @@
             decoration, inst, 2,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4362)
                      << "According to the Vulkan spec BuiltIn SamplePosition "
                         "variable needs to be a 2-component 32-bit float "
                         "vector. "
@@ -2036,6 +2101,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4361)
              << "Vulkan spec allows BuiltIn SamplePosition to be only used "
                 "for "
                 "variables with Input storage class. "
@@ -2047,6 +2113,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelFragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4360)
                << "Vulkan spec allows BuiltIn SamplePosition to be used only "
                   "with "
                   "Fragment execution model. "
@@ -2073,6 +2140,7 @@
             decoration, inst, 3,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4389)
                      << "According to the Vulkan spec BuiltIn TessCoord "
                         "variable needs to be a 3-component 32-bit float "
                         "vector. "
@@ -2095,6 +2163,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4388)
              << "Vulkan spec allows BuiltIn TessCoord to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2105,6 +2174,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelTessellationEvaluation) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4387)
                << "Vulkan spec allows BuiltIn TessCoord to be used only with "
                   "TessellationEvaluation execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2130,6 +2200,7 @@
             decoration, inst, 4,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4393)
                      << "According to the Vulkan spec BuiltIn TessLevelOuter "
                         "variable needs to be a 4-component 32-bit float "
                         "array. "
@@ -2150,6 +2221,7 @@
             decoration, inst, 2,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4397)
                      << "According to the Vulkan spec BuiltIn TessLevelOuter "
                         "variable needs to be a 2-component 32-bit float "
                         "array. "
@@ -2167,6 +2239,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
+  uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
@@ -2175,7 +2248,7 @@
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+                                              operand)
              << " to be only used for variables with Input or Output storage "
                 "class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2216,10 +2289,11 @@
         }
 
         default: {
+          uint32_t vuid = (operand == SpvBuiltInTessLevelOuter) ? 4390 : 4394;
           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,
-                                                  decoration.params()[0])
+                                                  operand)
                  << " to be used only with TessellationControl or "
                     "TessellationEvaluation execution models. "
                  << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2246,7 +2320,7 @@
             decoration, inst,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(4400) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn VertexIndex variable needs to be a "
                         "32-bit int scalar. "
@@ -2381,7 +2455,7 @@
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << spvLogStringForEnv(_.context()->target_env)
+             << _.VkErrorID(4399) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn VertexIndex to be only used for "
                 "variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2392,6 +2466,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelVertex) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4398)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn VertexIndex to be used only with "
                   "Vertex execution model. "
@@ -2422,7 +2497,10 @@
               decoration, inst,
               [this, &decoration,
                &inst](const std::string& message) -> spv_result_t {
+                uint32_t vuid =
+                    (decoration.params()[0] == SpvBuiltInLayer) ? 4276 : 4408;
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                       << _.VkErrorID(vuid)
                        << "According to the Vulkan spec BuiltIn "
                        << _.grammar().lookupOperandName(
                               SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0])
@@ -2436,7 +2514,10 @@
               decoration, inst,
               [this, &decoration,
                &inst](const std::string& message) -> spv_result_t {
+                uint32_t vuid =
+                    (decoration.params()[0] == SpvBuiltInLayer) ? 4276 : 4408;
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                       << _.VkErrorID(vuid)
                        << "According to the Vulkan spec BuiltIn "
                        << _.grammar().lookupOperandName(
                               SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0])
@@ -2456,6 +2537,7 @@
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
+  uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
@@ -2464,7 +2546,7 @@
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+                                              operand)
              << " to be only used for variables with Input or Output storage "
                 "class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2516,17 +2598,18 @@
             return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                    << "Using BuiltIn "
                    << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                    decoration.params()[0])
+                                                    operand)
                    << " in Vertex or Tessellation execution model requires "
                       "the ShaderViewportIndexLayerEXT capability.";
           }
           break;
         }
         default: {
+          uint32_t vuid = (operand == SpvBuiltInLayer) ? 4272 : 4404;
           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,
-                                                  decoration.params()[0])
+                                                  operand)
                  << " to be used only with Vertex, TessellationEvaluation, "
                     "Geometry, or Fragment execution models. "
                  << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2554,12 +2637,28 @@
             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;
+              };
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(vuid) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                                                      operand)
                      << " variable needs to be a 3-component 32-bit int "
                         "vector. "
                      << message;
@@ -2577,12 +2676,28 @@
     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)) {
     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;
+      };
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
-             << spvLogStringForEnv(_.context()->target_env)
+             << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                                               decoration.params()[0])
@@ -2599,7 +2714,23 @@
       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;
+        };
         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,
@@ -2793,6 +2924,7 @@
     if (spvIsVulkanEnv(_.context()->target_env) &&
         !spvOpcodeIsConstant(inst.opcode())) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+             << _.VkErrorID(4426)
              << "Vulkan spec requires BuiltIn WorkgroupSize to be a "
                 "constant. "
              << GetIdDesc(inst) << " is not a constant.";
@@ -2802,7 +2934,7 @@
             decoration, inst, 3,
             [this, &inst](const std::string& message) -> spv_result_t {
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
-                     << "According to the "
+                     << _.VkErrorID(4427) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn WorkgroupSize variable needs to be a "
                         "3-component 32-bit int vector. "
@@ -2824,6 +2956,7 @@
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (execution_model != SpvExecutionModelGLCompute) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4425)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index 0739148..1d09066 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -1319,5 +1319,181 @@
   return true;
 }
 
+#define VUID_WRAP(vuid) "[" #vuid "] "
+
+// Currently no 2 VUID share the same id, so no need for |reference|
+std::string ValidationState_t::VkErrorID(uint32_t id,
+                                         const char* /*reference*/) const {
+  if (!spvIsVulkanEnv(context_->target_env)) {
+    return "";
+  }
+
+  // This large switch case is only searched when an error has occured.
+  // If an id is changed, the old case must be modified or removed. Each string
+  // here is interpreted as being "implemented"
+
+  // Clang format adds spaces between hyphens
+  // clang-format off
+  switch (id) {
+    case 4187:
+      return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
+    case 4191:
+      return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
+    case 4196:
+      return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
+    case 4200:
+      return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
+    case 4210:
+      return VUID_WRAP(VUID-FragCoord-FragCoord-04210);
+    case 4211:
+      return VUID_WRAP(VUID-FragCoord-FragCoord-04211);
+    case 4212:
+      return VUID_WRAP(VUID-FragCoord-FragCoord-04212);
+    case 4213:
+      return VUID_WRAP(VUID-FragDepth-FragDepth-04213);
+    case 4214:
+      return VUID_WRAP(VUID-FragDepth-FragDepth-04214);
+    case 4215:
+      return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
+    case 4216:
+      return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
+    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 4236:
+      return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
+    case 4237:
+      return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04237);
+    case 4238:
+      return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04238);
+    case 4239:
+      return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04239);
+    case 4240:
+      return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
+    case 4241:
+      return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
+    case 4257:
+      return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
+    case 4258:
+      return VUID_WRAP(VUID-InvocationId-InvocationId-04258);
+    case 4259:
+      return VUID_WRAP(VUID-InvocationId-InvocationId-04259);
+    case 4263:
+      return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04263);
+    case 4264:
+      return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
+    case 4265:
+      return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
+    case 4272:
+      return VUID_WRAP(VUID-Layer-Layer-04272);
+    case 4276:
+      return VUID_WRAP(VUID-Layer-Layer-04276);
+    case 4281:
+      return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04281);
+    case 4282:
+      return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
+    case 4283:
+      return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
+    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 4308:
+      return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
+    case 4309:
+      return VUID_WRAP(VUID-PatchVertices-PatchVertices-04309);
+    case 4310:
+      return VUID_WRAP(VUID-PatchVertices-PatchVertices-04310);
+    case 4311:
+      return VUID_WRAP(VUID-PointCoord-PointCoord-04311);
+    case 4312:
+      return VUID_WRAP(VUID-PointCoord-PointCoord-04312);
+    case 4313:
+      return VUID_WRAP(VUID-PointCoord-PointCoord-04313);
+    case 4314:
+      return VUID_WRAP(VUID-PointSize-PointSize-04314);
+    case 4315:
+      return VUID_WRAP(VUID-PointSize-PointSize-04315);
+    case 4316:
+      return VUID_WRAP(VUID-PointSize-PointSize-04316);
+    case 4317:
+      return VUID_WRAP(VUID-PointSize-PointSize-04317);
+    case 4318:
+      return VUID_WRAP(VUID-Position-Position-04318);
+    case 4320:
+      return VUID_WRAP(VUID-Position-Position-04320);
+    case 4321:
+      return VUID_WRAP(VUID-Position-Position-04321);
+    case 4330:
+      return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
+    case 4334:
+      return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
+    case 4337:
+      return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
+    case 4354:
+      return VUID_WRAP(VUID-SampleId-SampleId-04354);
+    case 4355:
+      return VUID_WRAP(VUID-SampleId-SampleId-04355);
+    case 4356:
+      return VUID_WRAP(VUID-SampleId-SampleId-04356);
+    case 4357:
+      return VUID_WRAP(VUID-SampleMask-SampleMask-04357);
+    case 4358:
+      return VUID_WRAP(VUID-SampleMask-SampleMask-04358);
+    case 4359:
+      return VUID_WRAP(VUID-SampleMask-SampleMask-04359);
+    case 4360:
+      return VUID_WRAP(VUID-SamplePosition-SamplePosition-04360);
+    case 4361:
+      return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
+    case 4362:
+      return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
+    case 4387:
+      return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
+    case 4388:
+      return VUID_WRAP(VUID-TessCoord-TessCoord-04388);
+    case 4389:
+      return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
+    case 4390:
+      return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
+    case 4393:
+      return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
+    case 4394:
+      return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
+    case 4397:
+      return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
+    case 4398:
+      return VUID_WRAP(VUID-VertexIndex-VertexIndex-04398);
+    case 4399:
+      return VUID_WRAP(VUID-VertexIndex-VertexIndex-04399);
+    case 4400:
+      return VUID_WRAP(VUID-VertexIndex-VertexIndex-04400);
+    case 4404:
+      return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
+    case 4408:
+      return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
+    case 4422:
+      return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04422);
+    case 4423:
+      return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04423);
+    case 4424:
+      return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04424);
+    case 4425:
+      return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04425);
+    case 4426:
+      return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
+    case 4427:
+      return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
+    default:
+      return "";  // unknown id
+  };
+  // clang-format on
+}
+
 }  // namespace val
 }  // namespace spvtools
diff --git a/source/val/validation_state.h b/source/val/validation_state.h
index e5d31ac..e852c52 100644
--- a/source/val/validation_state.h
+++ b/source/val/validation_state.h
@@ -707,6 +707,17 @@
   // Validates the storage class for the target environment.
   bool IsValidStorageClass(SpvStorageClass storage_class) const;
 
+  // Takes a Vulkan Valid Usage ID (VUID) as |id| and optional |reference| and
+  // will return a non-empty string only if ID is known and targeting Vulkan.
+  // VUIDs are found in the Vulkan-Docs repo in the form "[[VUID-ref-ref-id]]"
+  // where "id" is always an 5 char long number (with zeros padding) and matches
+  // to |id|. |reference| is used if there is a "common validity" and the VUID
+  // shares the same |id| value.
+  //
+  // More details about Vulkan validation can be found in Vulkan Guide:
+  // https://github.com/KhronosGroup/Vulkan-Guide/blob/master/chapters/validation_overview.md
+  std::string VkErrorID(uint32_t id, const char* reference = nullptr) const;
+
  private:
   ValidationState_t(const ValidationState_t&);
 
diff --git a/test/val/val_builtins_test.cpp b/test/val/val_builtins_test.cpp
index b1ab0c9..758e07b 100644
--- a/test/val/val_builtins_test.cpp
+++ b/test/val/val_builtins_test.cpp
@@ -56,7 +56,7 @@
     std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
 using ValidateVulkanCombineBuiltInExecutionModelDataTypeResult =
     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
-                                     const char*, TestResult>>;
+                                     const char*, const char*, TestResult>>;
 using ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult =
     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
                                      const char*, TestResult>>;
@@ -151,12 +151,40 @@
   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;
+  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());
   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 =
       GetInMainCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
@@ -171,6 +199,9 @@
   if (test_result.error_str2) {
     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
   }
+  if (vuid) {
+    EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
+  }
 }
 
 TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InMain) {
@@ -316,7 +347,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 =
       GetInFunctionCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
@@ -331,6 +363,9 @@
   if (test_result.error_str2) {
     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
   }
+  if (vuid) {
+    EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
+  }
 }
 
 TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InFunction) {
@@ -459,7 +494,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 =
       GetVariableCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
@@ -474,6 +510,9 @@
   if (test_result.error_str2) {
     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
   }
+  if (vuid) {
+    EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
+  }
 }
 
 TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, Variable) {
@@ -530,7 +569,7 @@
     Combine(Values("ClipDistance", "CullDistance"),
             Values("Vertex", "Geometry", "TessellationControl",
                    "TessellationEvaluation"),
-            Values("Output"), Values("%f32arr2", "%f32arr4"),
+            Values("Output"), Values("%f32arr2", "%f32arr4"), Values(nullptr),
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -539,14 +578,14 @@
     Combine(Values("ClipDistance", "CullDistance"),
             Values("Fragment", "Geometry", "TessellationControl",
                    "TessellationEvaluation"),
-            Values("Input"), Values("%f32arr2", "%f32arr4"),
+            Values("Input"), Values("%f32arr2", "%f32arr4"), Values(nullptr),
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     ClipAndCullDistanceFragmentOutput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
-            Values("Output"), Values("%f32arr4"),
+            Values("Output"), Values("%f32arr4"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
@@ -558,7 +597,7 @@
     VertexIdAndInstanceIdVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexId", "InstanceId"), Values("Vertex"), Values("Input"),
-            Values("%u32"),
+            Values("%u32"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId to be "
@@ -568,7 +607,7 @@
     ClipAndCullDistanceVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Vertex"),
-            Values("Input"), Values("%f32arr4"),
+            Values("Input"), Values("%f32arr4"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
@@ -581,6 +620,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("GLCompute"),
             Values("Input", "Output"), Values("%f32arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04187 "
+                   "VUID-CullDistance-CullDistance-04196"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be used only with Fragment, Vertex, TessellationControl, "
@@ -591,6 +632,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
             Values("Input"), Values("%f32vec2", "%f32vec4", "%f32"),
+            Values("VUID-ClipDistance-ClipDistance-04191 "
+                   "VUID-CullDistance-CullDistance-04200"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float array",
                               "is not an array"))));
@@ -600,6 +643,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
             Values("Input"), Values("%u32arr2", "%u64arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04191 "
+                   "VUID-CullDistance-CullDistance-04200"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float array",
                               "components are not float scalar"))));
@@ -609,6 +654,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
             Values("Input"), Values("%f64arr2", "%f64arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04191 "
+                   "VUID-CullDistance-CullDistance-04200"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float array",
                               "has components with bit width 64"))));
@@ -616,7 +663,7 @@
 INSTANTIATE_TEST_SUITE_P(
     FragCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec4"), Values(TestResult())));
+            Values("%f32vec4"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     FragCoordSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
@@ -631,6 +678,7 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Input"), Values("%f32vec4"),
+        Values("VUID-FragCoord-FragCoord-04210"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -646,7 +694,7 @@
 INSTANTIATE_TEST_SUITE_P(
     FragCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Output"),
-            Values("%f32vec4"),
+            Values("%f32vec4"), Values("VUID-FragCoord-FragCoord-04211"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -666,6 +714,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
             Values("%f32arr4", "%u32vec4"),
+            Values("VUID-FragCoord-FragCoord-04212"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "is not a float vector"))));
@@ -683,7 +732,7 @@
     FragCoordNotFloatVec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec3"),
+            Values("%f32vec3"), Values("VUID-FragCoord-FragCoord-04212"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "has 3 components"))));
@@ -701,7 +750,7 @@
     FragCoordNotF32Vec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
-            Values("%f64vec4"),
+            Values("%f64vec4"), Values("VUID-FragCoord-FragCoord-04212"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "has components with bit width 64"))));
@@ -709,7 +758,7 @@
 INSTANTIATE_TEST_SUITE_P(
     FragDepthSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
-            Values("%f32"), Values(TestResult())));
+            Values("%f32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     FragDepthSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
@@ -724,6 +773,7 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Output"), Values("%f32"),
+        Values("VUID-FragDepth-FragDepth-04213"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -740,7 +790,7 @@
     FragDepthNotOutput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Input"),
-            Values("%f32"),
+            Values("%f32"), Values("VUID-FragDepth-FragDepth-04214"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Output storage class",
@@ -761,6 +811,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
             Values("%f32vec4", "%u32"),
+            Values("VUID-FragDepth-FragDepth-04215"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float scalar",
                               "is not a float scalar"))));
@@ -777,7 +828,7 @@
 INSTANTIATE_TEST_SUITE_P(
     FragDepthNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
-            Values("%f64"),
+            Values("%f64"), Values("VUID-FragDepth-FragDepth-04215"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float scalar",
                               "has bit width 64"))));
@@ -786,7 +837,8 @@
     FrontFacingAndHelperInvocationSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
-            Values("Input"), Values("%bool"), Values(TestResult())));
+            Values("Input"), Values("%bool"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     FrontFacingSuccess,
@@ -802,6 +854,8 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Input"), Values("%bool"),
+        Values("VUID-FrontFacing-FrontFacing-04229 "
+               "VUID-HelperInvocation-HelperInvocation-04239"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -819,6 +873,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
             Values("Output"), Values("%bool"),
+            Values("VUID-FrontFacing-FrontFacing-04230 "
+                   "VUID-HelperInvocation-HelperInvocation-04240"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -839,6 +895,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
             Values("Input"), Values("%f32", "%u32"),
+            Values("VUID-FrontFacing-FrontFacing-04231 "
+                   "VUID-HelperInvocation-HelperInvocation-04241"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a bool scalar",
                               "is not a bool scalar"))));
@@ -858,7 +916,7 @@
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
                    "WorkgroupId"),
             Values("GLCompute"), Values("Input"), Values("%u32vec3"),
-            Values(TestResult())));
+            Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3Success,
@@ -876,6 +934,10 @@
         Values("Vertex", "Fragment", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Input"), Values("%u32vec3"),
+        Values("VUID-GlobalInvocationId-GlobalInvocationId-04236 "
+               "VUID-LocalInvocationId-LocalInvocationId-04281 "
+               "VUID-NumWorkgroups-NumWorkgroups-04296 "
+               "VUID-WorkgroupId-WorkgroupId-04422"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with GLCompute execution model"))));
 
@@ -894,6 +956,10 @@
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
                    "WorkgroupId"),
             Values("GLCompute"), Values("Output"), Values("%u32vec3"),
+            Values("VUID-GlobalInvocationId-GlobalInvocationId-04237 "
+                   "VUID-LocalInvocationId-LocalInvocationId-04282 "
+                   "VUID-NumWorkgroups-NumWorkgroups-04297 "
+                   "VUID-WorkgroupId-WorkgroupId-04423"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -916,6 +982,10 @@
                    "WorkgroupId"),
             Values("GLCompute"), Values("Input"),
             Values("%u32arr3", "%f32vec3"),
+            Values("VUID-GlobalInvocationId-GlobalInvocationId-04238 "
+                   "VUID-LocalInvocationId-LocalInvocationId-04283 "
+                   "VUID-NumWorkgroups-NumWorkgroups-04298 "
+                   "VUID-WorkgroupId-WorkgroupId-04424"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 3-component 32-bit int vector",
                               "is not an int vector"))));
@@ -936,6 +1006,10 @@
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
                    "WorkgroupId"),
             Values("GLCompute"), Values("Input"), Values("%u32vec4"),
+            Values("VUID-GlobalInvocationId-GlobalInvocationId-04238 "
+                   "VUID-LocalInvocationId-LocalInvocationId-04283 "
+                   "VUID-NumWorkgroups-NumWorkgroups-04298 "
+                   "VUID-WorkgroupId-WorkgroupId-04424"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 3-component 32-bit int vector",
                               "has 4 components"))));
@@ -955,6 +1029,10 @@
     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
                    "WorkgroupId"),
             Values("GLCompute"), Values("Input"), Values("%u64vec3"),
+            Values("VUID-GlobalInvocationId-GlobalInvocationId-04238 "
+                   "VUID-LocalInvocationId-LocalInvocationId-04283 "
+                   "VUID-NumWorkgroups-NumWorkgroups-04298 "
+                   "VUID-WorkgroupId-WorkgroupId-04424"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 3-component 32-bit int vector",
                               "has components with bit width 64"))));
@@ -963,7 +1041,8 @@
     InvocationIdSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
-            Values("Input"), Values("%u32"), Values(TestResult())));
+            Values("Input"), Values("%u32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     InvocationIdInvalidExecutionModel,
@@ -971,6 +1050,7 @@
     Combine(Values("InvocationId"),
             Values("Vertex", "Fragment", "GLCompute", "TessellationEvaluation"),
             Values("Input"), Values("%u32"),
+            Values("VUID-InvocationId-InvocationId-04257"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "to be used only with TessellationControl or "
                               "Geometry execution models"))));
@@ -980,6 +1060,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
             Values("Output"), Values("%u32"),
+            Values("VUID-InvocationId-InvocationId-04258"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -990,6 +1071,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
             Values("Input"), Values("%f32", "%u32vec3"),
+            Values("VUID-InvocationId-InvocationId-04259"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
@@ -999,6 +1081,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
             Values("Input"), Values("%u64"),
+            Values("VUID-InvocationId-InvocationId-04259"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
@@ -1007,7 +1090,7 @@
     InstanceIndexSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
-            Values("%u32"), Values(TestResult())));
+            Values("%u32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     InstanceIndexSuccess,
@@ -1022,6 +1105,7 @@
             Values("Geometry", "Fragment", "GLCompute", "TessellationControl",
                    "TessellationEvaluation"),
             Values("Input"), Values("%u32"),
+            Values("VUID-InstanceIndex-InstanceIndex-04263"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "to be used only with Vertex execution model"))));
 
@@ -1037,7 +1121,7 @@
     InstanceIndexNotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"),
-            Values("%u32"),
+            Values("%u32"), Values("VUID-InstanceIndex-InstanceIndex-04264"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -1058,6 +1142,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
             Values("%f32", "%u32vec3"),
+            Values("VUID-InstanceIndex-InstanceIndex-04265"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
@@ -1075,7 +1160,7 @@
     InstanceIndexNotInt32,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
-            Values("%u64"),
+            Values("%u64"), Values("VUID-InstanceIndex-InstanceIndex-04265"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
@@ -1084,31 +1169,35 @@
     LayerAndViewportIndexInputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
-            Values("Input"), Values("%u32"), Values(TestResult())));
+            Values("Input"), Values("%u32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     LayerAndViewportIndexOutputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Layer", "ViewportIndex"), Values("Geometry"),
-            Values("Output"), Values("%u32"), Values(TestResult())));
+            Values("Output"), Values("%u32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     LayerAndViewportIndexInvalidExecutionModel,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("Layer", "ViewportIndex"),
-            Values("TessellationControl", "GLCompute"), Values("Input"),
-            Values("%u32"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be used only with Vertex, TessellationEvaluation, "
-                "Geometry, or Fragment execution models"))));
+    Combine(
+        Values("Layer", "ViewportIndex"),
+        Values("TessellationControl", "GLCompute"), Values("Input"),
+        Values("%u32"),
+        Values("VUID-Layer-Layer-04272 VUID-ViewportIndex-ViewportIndex-04404"),
+        Values(
+            TestResult(SPV_ERROR_INVALID_DATA,
+                       "to be used only with Vertex, TessellationEvaluation, "
+                       "Geometry, or Fragment execution models"))));
 
 INSTANTIATE_TEST_SUITE_P(
     LayerAndViewportIndexExecutionModelEnabledByCapability,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Layer", "ViewportIndex"),
             Values("Vertex", "TessellationEvaluation"), Values("Output"),
-            Values("%u32"),
+            Values("%u32"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "requires the ShaderViewportIndexLayerEXT capability"))));
@@ -1118,7 +1207,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
         Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Output"),
-        Values("%u32"),
+        Values("%u32"), Values(nullptr),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "Output storage class if execution model is Fragment",
                           "which is called with execution model Fragment"))));
@@ -1129,7 +1218,7 @@
     Combine(
         Values("Layer", "ViewportIndex"),
         Values("Vertex", "TessellationEvaluation", "Geometry"), Values("Input"),
-        Values("%u32"),
+        Values("%u32"), Values(nullptr),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "Input storage class if execution model is Vertex, "
                           "TessellationEvaluation, or Geometry",
@@ -1138,27 +1227,32 @@
 INSTANTIATE_TEST_SUITE_P(
     LayerAndViewportIndexNotIntScalar,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
-            Values("Input"), Values("%f32", "%u32vec3"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 32-bit int scalar",
-                              "is not an int scalar"))));
+    Combine(
+        Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Input"),
+        Values("%f32", "%u32vec3"),
+        Values("VUID-Layer-Layer-04276 VUID-ViewportIndex-ViewportIndex-04408"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "needs to be a 32-bit int scalar",
+                          "is not an int scalar"))));
 
 INSTANTIATE_TEST_SUITE_P(
     LayerAndViewportIndexNotInt32,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
-            Values("Input"), Values("%u64"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "needs to be a 32-bit int scalar",
-                              "has bit width 64"))));
+    Combine(
+        Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Input"),
+        Values("%u64"),
+        Values("VUID-Layer-Layer-04276 VUID-ViewportIndex-ViewportIndex-04408"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "needs to be a 32-bit int scalar",
+                          "has bit width 64"))));
 
 INSTANTIATE_TEST_SUITE_P(
     PatchVerticesSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PatchVertices"),
             Values("TessellationEvaluation", "TessellationControl"),
-            Values("Input"), Values("%u32"), Values(TestResult())));
+            Values("Input"), Values("%u32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PatchVerticesInvalidExecutionModel,
@@ -1166,6 +1260,7 @@
     Combine(Values("PatchVertices"),
             Values("Vertex", "Fragment", "GLCompute", "Geometry"),
             Values("Input"), Values("%u32"),
+            Values("VUID-PatchVertices-PatchVertices-04308"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "to be used only with TessellationControl or "
                               "TessellationEvaluation execution models"))));
@@ -1176,6 +1271,7 @@
     Combine(Values("PatchVertices"),
             Values("TessellationEvaluation", "TessellationControl"),
             Values("Output"), Values("%u32"),
+            Values("VUID-PatchVertices-PatchVertices-04309"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -1187,6 +1283,7 @@
     Combine(Values("PatchVertices"),
             Values("TessellationEvaluation", "TessellationControl"),
             Values("Input"), Values("%f32", "%u32vec3"),
+            Values("VUID-PatchVertices-PatchVertices-04310"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
@@ -1197,6 +1294,7 @@
     Combine(Values("PatchVertices"),
             Values("TessellationEvaluation", "TessellationControl"),
             Values("Input"), Values("%u64"),
+            Values("VUID-PatchVertices-PatchVertices-04310"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
@@ -1204,7 +1302,7 @@
 INSTANTIATE_TEST_SUITE_P(
     PointCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec2"), Values(TestResult())));
+            Values("%f32vec2"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PointCoordNotFragment,
@@ -1214,6 +1312,7 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Input"), Values("%f32vec2"),
+        Values("VUID-PointCoord-PointCoord-04311"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -1221,7 +1320,7 @@
     PointCoordNotInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointCoord"), Values("Fragment"), Values("Output"),
-            Values("%f32vec2"),
+            Values("%f32vec2"), Values("VUID-PointCoord-PointCoord-04312"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -1232,6 +1331,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
             Values("%f32arr2", "%u32vec2"),
+            Values("VUID-PointCoord-PointCoord-04313"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float vector",
                               "is not a float vector"))));
@@ -1240,7 +1340,7 @@
     PointCoordNotFloatVec3,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec3"),
+            Values("%f32vec3"), Values("VUID-PointCoord-PointCoord-04313"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float vector",
                               "has 3 components"))));
@@ -1249,7 +1349,7 @@
     PointCoordNotF32Vec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
-            Values("%f64vec2"),
+            Values("%f64vec2"), Values("VUID-PointCoord-PointCoord-04313"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float vector",
                               "has components with bit width 64"))));
@@ -1260,20 +1360,22 @@
     Combine(Values("PointSize"),
             Values("Vertex", "Geometry", "TessellationControl",
                    "TessellationEvaluation"),
-            Values("Output"), Values("%f32"), Values(TestResult())));
+            Values("Output"), Values("%f32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PointSizeInputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointSize"),
             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
-            Values("Input"), Values("%f32"), Values(TestResult())));
+            Values("Input"), Values("%f32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PointSizeVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointSize"), Values("Vertex"), Values("Input"),
-            Values("%f32"),
+            Values("%f32"), Values("VUID-PointSize-PointSize-04315"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn PointSize "
@@ -1286,6 +1388,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointSize"), Values("GLCompute", "Fragment"),
             Values("Input", "Output"), Values("%f32"),
+            Values("VUID-PointSize-PointSize-04314"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be used only with Vertex, TessellationControl, "
@@ -1296,6 +1399,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
             Values("%f32vec4", "%u32"),
+            Values("VUID-PointSize-PointSize-04317"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float scalar",
                               "is not a float scalar"))));
@@ -1303,7 +1407,7 @@
 INSTANTIATE_TEST_SUITE_P(
     PointSizeNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
-            Values("%f64"),
+            Values("%f64"), Values("VUID-PointSize-PointSize-04317"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float scalar",
                               "has bit width 64"))));
@@ -1314,7 +1418,8 @@
     Combine(Values("Position"),
             Values("Vertex", "Geometry", "TessellationControl",
                    "TessellationEvaluation"),
-            Values("Output"), Values("%f32vec4"), Values(TestResult())));
+            Values("Output"), Values("%f32vec4"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PositionOutputSuccess,
@@ -1336,7 +1441,8 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"),
             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
-            Values("Input"), Values("%f32vec4"), Values(TestResult())));
+            Values("Input"), Values("%f32vec4"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PositionInputFailure,
@@ -1352,7 +1458,7 @@
     PositionVertexInput,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Vertex"), Values("Input"),
-            Values("%f32vec4"),
+            Values("%f32vec4"), Values("VUID-Position-Position-04320"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow BuiltIn Position "
@@ -1365,6 +1471,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("GLCompute", "Fragment"),
             Values("Input", "Output"), Values("%f32vec4"),
+            Values("VUID-Position-Position-04318"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be used only with Vertex, TessellationControl, "
@@ -1375,6 +1482,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Geometry"), Values("Input"),
             Values("%f32arr4", "%u32vec4"),
+            Values("VUID-Position-Position-04321"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "is not a float vector"))));
@@ -1392,7 +1500,7 @@
     PositionNotFloatVec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Geometry"), Values("Input"),
-            Values("%f32vec3"),
+            Values("%f32vec3"), Values("VUID-Position-Position-04321"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "has 3 components"))));
@@ -1410,7 +1518,7 @@
     PositionNotF32Vec4,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("Position"), Values("Geometry"), Values("Input"),
-            Values("%f64vec4"),
+            Values("%f64vec4"), Values("VUID-Position-Position-04321"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "has components with bit width 64"))));
@@ -1421,19 +1529,21 @@
     Combine(Values("PrimitiveId"),
             Values("Fragment", "TessellationControl", "TessellationEvaluation",
                    "Geometry"),
-            Values("Input"), Values("%u32"), Values(TestResult())));
+            Values("Input"), Values("%u32"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdOutputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PrimitiveId"), Values("Geometry"), Values("Output"),
-            Values("%u32"), Values(TestResult())));
+            Values("%u32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdInvalidExecutionModel,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PrimitiveId"), Values("Vertex", "GLCompute"),
             Values("Input"), Values("%u32"),
+            Values("VUID-PrimitiveId-PrimitiveId-04330"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be used only with Fragment, TessellationControl, "
@@ -1444,7 +1554,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
         Values("PrimitiveId"), Values("Fragment"), Values("Output"),
-        Values("%u32"),
+        Values("%u32"), Values("VUID-PrimitiveId-PrimitiveId-04334"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "Output storage class if execution model is Fragment",
                           "which is called with execution model Fragment"))));
@@ -1455,6 +1565,7 @@
     Combine(Values("PrimitiveId"),
             Values("TessellationControl", "TessellationEvaluation"),
             Values("Output"), Values("%u32"),
+            Values("VUID-PrimitiveId-PrimitiveId-04334"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Output storage class if execution model is Tessellation",
@@ -1465,6 +1576,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"),
             Values("%f32", "%u32vec3"),
+            Values("VUID-PrimitiveId-PrimitiveId-04337"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
@@ -1473,7 +1585,7 @@
     PrimitiveIdNotInt32,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"),
-            Values("%u64"),
+            Values("%u64"), Values("VUID-PrimitiveId-PrimitiveId-04337"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
@@ -1481,7 +1593,7 @@
 INSTANTIATE_TEST_SUITE_P(
     SampleIdSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
-            Values("%u32"), Values(TestResult())));
+            Values("%u32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     SampleIdInvalidExecutionModel,
@@ -1490,7 +1602,7 @@
         Values("SampleId"),
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
-        Values("Input"), Values("%u32"),
+        Values("Input"), Values("%u32"), Values("VUID-SampleId-SampleId-04354"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -1498,7 +1610,7 @@
     SampleIdNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
         Values("SampleId"), Values("Fragment"), Values("Output"),
-        Values("%u32"),
+        Values("%u32"), Values("VUID-SampleId-SampleId-04355"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "Vulkan spec allows BuiltIn SampleId to be only used "
                           "for variables with Input storage class"))));
@@ -1507,7 +1619,7 @@
     SampleIdNotIntScalar,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
-            Values("%f32", "%u32vec3"),
+            Values("%f32", "%u32vec3"), Values("VUID-SampleId-SampleId-04356"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
@@ -1515,7 +1627,7 @@
 INSTANTIATE_TEST_SUITE_P(
     SampleIdNotInt32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
-            Values("%u64"),
+            Values("%u64"), Values("VUID-SampleId-SampleId-04356"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
@@ -1523,7 +1635,8 @@
 INSTANTIATE_TEST_SUITE_P(
     SampleMaskSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleMask"), Values("Fragment"), Values("Input", "Output"),
-            Values("%u32arr2", "%u32arr4"), Values(TestResult())));
+            Values("%u32arr2", "%u32arr4"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     SampleMaskInvalidExecutionModel,
@@ -1533,6 +1646,7 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Input"), Values("%u32arr2"),
+        Values("VUID-SampleMask-SampleMask-04357"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -1540,7 +1654,7 @@
     SampleMaskWrongStorageClass,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleMask"), Values("Fragment"), Values("Workgroup"),
-            Values("%u32arr2"),
+            Values("%u32arr2"), Values("VUID-SampleMask-SampleMask-04358"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec allows BuiltIn SampleMask to be only used for "
@@ -1551,6 +1665,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
             Values("%f32", "%u32vec3"),
+            Values("VUID-SampleMask-SampleMask-04359"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int array",
                               "is not an array"))));
@@ -1559,7 +1674,7 @@
     SampleMaskNotIntArray,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
-            Values("%f32arr2"),
+            Values("%f32arr2"), Values("VUID-SampleMask-SampleMask-04359"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int array",
                               "components are not int scalar"))));
@@ -1568,7 +1683,7 @@
     SampleMaskNotInt32Array,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
-            Values("%u64arr2"),
+            Values("%u64arr2"), Values("VUID-SampleMask-SampleMask-04359"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int array",
                               "has components with bit width 64"))));
@@ -1577,7 +1692,7 @@
     SamplePositionSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
-            Values("%f32vec2"), Values(TestResult())));
+            Values("%f32vec2"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     SamplePositionNotFragment,
@@ -1587,6 +1702,7 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "TessellationEvaluation"),
         Values("Input"), Values("%f32vec2"),
+        Values("VUID-SamplePosition-SamplePosition-04360"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "to be used only with Fragment execution model"))));
 
@@ -1595,6 +1711,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SamplePosition"), Values("Fragment"), Values("Output"),
             Values("%f32vec2"),
+            Values("VUID-SamplePosition-SamplePosition-04361"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -1605,6 +1722,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
             Values("%f32arr2", "%u32vec4"),
+            Values("VUID-SamplePosition-SamplePosition-04362"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float vector",
                               "is not a float vector"))));
@@ -1614,6 +1732,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
             Values("%f32vec3"),
+            Values("VUID-SamplePosition-SamplePosition-04362"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float vector",
                               "has 3 components"))));
@@ -1623,6 +1742,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
             Values("%f64vec2"),
+            Values("VUID-SamplePosition-SamplePosition-04362"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float vector",
                               "has components with bit width 64"))));
@@ -1630,7 +1750,8 @@
 INSTANTIATE_TEST_SUITE_P(
     TessCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessCoord"), Values("TessellationEvaluation"),
-            Values("Input"), Values("%f32vec3"), Values(TestResult())));
+            Values("Input"), Values("%f32vec3"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     TessCoordNotFragment,
@@ -1640,6 +1761,7 @@
         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
                "Fragment"),
         Values("Input"), Values("%f32vec3"),
+        Values("VUID-TessCoord-TessCoord-04387"),
         Values(TestResult(
             SPV_ERROR_INVALID_DATA,
             "to be used only with TessellationEvaluation execution model"))));
@@ -1647,7 +1769,7 @@
 INSTANTIATE_TEST_SUITE_P(
     TessCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessCoord"), Values("Fragment"), Values("Output"),
-            Values("%f32vec3"),
+            Values("%f32vec3"), Values("VUID-TessCoord-TessCoord-04388"),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "to be only used for variables with Input storage class",
@@ -1658,6 +1780,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
             Values("%f32arr3", "%u32vec4"),
+            Values("VUID-TessCoord-TessCoord-04389"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 3-component 32-bit float vector",
                               "is not a float vector"))));
@@ -1666,7 +1789,7 @@
     TessCoordNotFloatVec3,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
-            Values("%f32vec2"),
+            Values("%f32vec2"), Values("VUID-TessCoord-TessCoord-04389"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 3-component 32-bit float vector",
                               "has 2 components"))));
@@ -1675,7 +1798,7 @@
     TessCoordNotF32Vec3,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
-            Values("%f64vec3"),
+            Values("%f64vec3"), Values("VUID-TessCoord-TessCoord-04389"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 3-component 32-bit float vector",
                               "has components with bit width 64"))));
@@ -1684,13 +1807,15 @@
     TessLevelOuterTeseInputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
-            Values("Input"), Values("%f32arr4"), Values(TestResult())));
+            Values("Input"), Values("%f32arr4"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     TessLevelOuterTescOutputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
-            Values("Output"), Values("%f32arr4"), Values(TestResult())));
+            Values("Output"), Values("%f32arr4"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     TessLevelOuterInvalidExecutionModel,
@@ -1698,6 +1823,7 @@
     Combine(Values("TessLevelOuter"),
             Values("Vertex", "GLCompute", "Geometry", "Fragment"),
             Values("Input"), Values("%f32arr4"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04390"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "to be used only with TessellationControl or "
                               "TessellationEvaluation execution models."))));
@@ -1706,7 +1832,7 @@
     TessLevelOuterOutputTese,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
-            Values("Output"), Values("%f32arr4"),
+            Values("Output"), Values("%f32arr4"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -1717,7 +1843,7 @@
     TessLevelOuterInputTesc,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
-            Values("Input"), Values("%f32arr4"),
+            Values("Input"), Values("%f32arr4"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -1729,6 +1855,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
             Values("Input"), Values("%f32vec4", "%f32"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float array",
                               "is not an array"))));
@@ -1738,6 +1865,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
             Values("Input"), Values("%u32arr4"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float array",
                               "components are not float scalar"))));
@@ -1747,6 +1875,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
             Values("Input"), Values("%f32arr3"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float array",
                               "has 3 components"))));
@@ -1756,6 +1885,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
             Values("Input"), Values("%f64arr4"),
+            Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float array",
                               "has components with bit width 64"))));
@@ -1764,13 +1894,15 @@
     TessLevelInnerTeseInputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
-            Values("Input"), Values("%f32arr2"), Values(TestResult())));
+            Values("Input"), Values("%f32arr2"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     TessLevelInnerTescOutputSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationControl"),
-            Values("Output"), Values("%f32arr2"), Values(TestResult())));
+            Values("Output"), Values("%f32arr2"), Values(nullptr),
+            Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     TessLevelInnerInvalidExecutionModel,
@@ -1778,6 +1910,7 @@
     Combine(Values("TessLevelInner"),
             Values("Vertex", "GLCompute", "Geometry", "Fragment"),
             Values("Input"), Values("%f32arr2"),
+            Values("VUID-TessLevelInner-TessLevelInner-04394"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "to be used only with TessellationControl or "
                               "TessellationEvaluation execution models."))));
@@ -1786,7 +1919,7 @@
     TessLevelInnerOutputTese,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
-            Values("Output"), Values("%f32arr2"),
+            Values("Output"), Values("%f32arr2"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -1797,7 +1930,7 @@
     TessLevelInnerInputTesc,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationControl"),
-            Values("Input"), Values("%f32arr2"),
+            Values("Input"), Values("%f32arr2"), Values(nullptr),
             Values(TestResult(
                 SPV_ERROR_INVALID_DATA,
                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@@ -1809,6 +1942,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
             Values("Input"), Values("%f32vec2", "%f32"),
+            Values("VUID-TessLevelInner-TessLevelInner-04397"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float array",
                               "is not an array"))));
@@ -1818,6 +1952,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
             Values("Input"), Values("%u32arr2"),
+            Values("VUID-TessLevelInner-TessLevelInner-04397"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float array",
                               "components are not float scalar"))));
@@ -1827,6 +1962,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
             Values("Input"), Values("%f32arr3"),
+            Values("VUID-TessLevelInner-TessLevelInner-04397"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float array",
                               "has 3 components"))));
@@ -1836,6 +1972,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
             Values("Input"), Values("%f64arr2"),
+            Values("VUID-TessLevelInner-TessLevelInner-04397"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 2-component 32-bit float array",
                               "has components with bit width 64"))));
@@ -1844,7 +1981,7 @@
     VertexIndexSuccess,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
-            Values("%u32"), Values(TestResult())));
+            Values("%u32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     VertexIndexSuccess,
@@ -1859,6 +1996,7 @@
             Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
                    "TessellationEvaluation"),
             Values("Input"), Values("%u32"),
+            Values("VUID-VertexIndex-VertexIndex-04398"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "to be used only with Vertex execution model"))));
 
@@ -1875,7 +2013,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(
         Values("VertexIndex"), Values("Vertex"), Values("Output"),
-        Values("%u32"),
+        Values("%u32"), Values("VUID-VertexIndex-VertexIndex-04399"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "Vulkan spec allows BuiltIn VertexIndex to be only "
                           "used for variables with Input storage class"))));
@@ -1895,6 +2033,7 @@
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
             Values("%f32", "%u32vec3"),
+            Values("VUID-VertexIndex-VertexIndex-04400"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "is not an int scalar"))));
@@ -1912,7 +2051,7 @@
     VertexIndexNotInt32,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
-            Values("%u64"),
+            Values("%u64"), Values("VUID-VertexIndex-VertexIndex-04400"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
@@ -2294,6 +2433,9 @@
               HasSubstr("is referencing ID <2> (OpConstantComposite) which is "
                         "decorated with BuiltIn WorkgroupSize in function <1> "
                         "called with execution model Fragment"));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04425 "
+                      "VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeFragment) {
@@ -2369,6 +2511,8 @@
               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
                         "variable needs to be a 3-component 32-bit int vector. "
                         "ID <2> (OpConstant) is not an int vector."));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVector) {
@@ -2417,6 +2561,8 @@
               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
                         "variable needs to be a 3-component 32-bit int vector. "
                         "ID <2> (OpConstantComposite) is not an int vector."));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotIntVector) {
@@ -2465,6 +2611,8 @@
               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
                         "variable needs to be a 3-component 32-bit int vector. "
                         "ID <2> (OpConstantComposite) has 2 components."));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVec3) {
@@ -2503,6 +2651,8 @@
       HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize variable "
                 "needs to be a 3-component 32-bit int vector. ID <2> "
                 "(OpConstantComposite) has components with bit width 64."));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
 }
 
 TEST_F(ValidateBuiltIns, WorkgroupSizePrivateVar) {
@@ -2806,6 +2956,8 @@
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Vulkan spec requires DepthReplacing execution mode to "
                         "be declared when using BuiltIn FragDepth"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("VUID-FragDepth-FragDepth-04216"));
 }
 
 TEST_F(ValidateBuiltIns, WebGPUFragmentFragDepthNoDepthReplacing) {
@@ -2885,6 +3037,8 @@
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Vulkan spec requires DepthReplacing execution mode to "
                         "be declared when using BuiltIn FragDepth"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("VUID-FragDepth-FragDepth-04216"));
 }
 
 TEST_F(ValidateBuiltIns,