• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "source/val/validation_state.h"
16 
17 #include <cassert>
18 #include <stack>
19 #include <utility>
20 
21 #include "source/opcode.h"
22 #include "source/spirv_constant.h"
23 #include "source/spirv_target_env.h"
24 #include "source/util/make_unique.h"
25 #include "source/val/basic_block.h"
26 #include "source/val/construct.h"
27 #include "source/val/function.h"
28 #include "spirv-tools/libspirv.h"
29 
30 namespace spvtools {
31 namespace val {
32 namespace {
33 
InstructionLayoutSection(ModuleLayoutSection current_section,spv::Op op)34 ModuleLayoutSection InstructionLayoutSection(
35     ModuleLayoutSection current_section, spv::Op op) {
36   // See Section 2.4
37   if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op))
38     return kLayoutTypes;
39 
40   switch (op) {
41     case spv::Op::OpCapability:
42       return kLayoutCapabilities;
43     case spv::Op::OpExtension:
44       return kLayoutExtensions;
45     case spv::Op::OpExtInstImport:
46       return kLayoutExtInstImport;
47     case spv::Op::OpMemoryModel:
48       return kLayoutMemoryModel;
49     case spv::Op::OpEntryPoint:
50       return kLayoutEntryPoint;
51     case spv::Op::OpExecutionMode:
52     case spv::Op::OpExecutionModeId:
53       return kLayoutExecutionMode;
54     case spv::Op::OpSourceContinued:
55     case spv::Op::OpSource:
56     case spv::Op::OpSourceExtension:
57     case spv::Op::OpString:
58       return kLayoutDebug1;
59     case spv::Op::OpName:
60     case spv::Op::OpMemberName:
61       return kLayoutDebug2;
62     case spv::Op::OpModuleProcessed:
63       return kLayoutDebug3;
64     case spv::Op::OpDecorate:
65     case spv::Op::OpMemberDecorate:
66     case spv::Op::OpGroupDecorate:
67     case spv::Op::OpGroupMemberDecorate:
68     case spv::Op::OpDecorationGroup:
69     case spv::Op::OpDecorateId:
70     case spv::Op::OpDecorateStringGOOGLE:
71     case spv::Op::OpMemberDecorateStringGOOGLE:
72       return kLayoutAnnotations;
73     case spv::Op::OpTypeForwardPointer:
74       return kLayoutTypes;
75     case spv::Op::OpVariable:
76       if (current_section == kLayoutTypes) return kLayoutTypes;
77       return kLayoutFunctionDefinitions;
78     case spv::Op::OpExtInst:
79       // spv::Op::OpExtInst is only allowed in types section for certain
80       // extended instruction sets. This will be checked separately.
81       if (current_section == kLayoutTypes) return kLayoutTypes;
82       return kLayoutFunctionDefinitions;
83     case spv::Op::OpLine:
84     case spv::Op::OpNoLine:
85     case spv::Op::OpUndef:
86       if (current_section == kLayoutTypes) return kLayoutTypes;
87       return kLayoutFunctionDefinitions;
88     case spv::Op::OpFunction:
89     case spv::Op::OpFunctionParameter:
90     case spv::Op::OpFunctionEnd:
91       if (current_section == kLayoutFunctionDeclarations)
92         return kLayoutFunctionDeclarations;
93       return kLayoutFunctionDefinitions;
94     case spv::Op::OpSamplerImageAddressingModeNV:
95       return kLayoutSamplerImageAddressMode;
96     default:
97       break;
98   }
99   return kLayoutFunctionDefinitions;
100 }
101 
IsInstructionInLayoutSection(ModuleLayoutSection layout,spv::Op op)102 bool IsInstructionInLayoutSection(ModuleLayoutSection layout, spv::Op op) {
103   return layout == InstructionLayoutSection(layout, op);
104 }
105 
106 // Counts the number of instructions and functions in the file.
CountInstructions(void * user_data,const spv_parsed_instruction_t * inst)107 spv_result_t CountInstructions(void* user_data,
108                                const spv_parsed_instruction_t* inst) {
109   ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
110   if (spv::Op(inst->opcode) == spv::Op::OpFunction) {
111     _.increment_total_functions();
112   }
113   _.increment_total_instructions();
114 
115   return SPV_SUCCESS;
116 }
117 
setHeader(void * user_data,spv_endianness_t,uint32_t,uint32_t version,uint32_t generator,uint32_t id_bound,uint32_t)118 spv_result_t setHeader(void* user_data, spv_endianness_t, uint32_t,
119                        uint32_t version, uint32_t generator, uint32_t id_bound,
120                        uint32_t) {
121   ValidationState_t& vstate =
122       *(reinterpret_cast<ValidationState_t*>(user_data));
123   vstate.setIdBound(id_bound);
124   vstate.setGenerator(generator);
125   vstate.setVersion(version);
126 
127   return SPV_SUCCESS;
128 }
129 
130 // Add features based on SPIR-V core version number.
UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature * features,uint32_t version)131 void UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature* features,
132                                        uint32_t version) {
133   assert(features);
134   if (version >= SPV_SPIRV_VERSION_WORD(1, 4)) {
135     features->select_between_composites = true;
136     features->copy_memory_permits_two_memory_accesses = true;
137     features->uconvert_spec_constant_op = true;
138     features->nonwritable_var_in_function_or_private = true;
139   }
140 }
141 
142 }  // namespace
143 
ValidationState_t(const spv_const_context ctx,const spv_const_validator_options opt,const uint32_t * words,const size_t num_words,const uint32_t max_warnings)144 ValidationState_t::ValidationState_t(const spv_const_context ctx,
145                                      const spv_const_validator_options opt,
146                                      const uint32_t* words,
147                                      const size_t num_words,
148                                      const uint32_t max_warnings)
149     : context_(ctx),
150       options_(opt),
151       words_(words),
152       num_words_(num_words),
153       unresolved_forward_ids_{},
154       operand_names_{},
155       current_layout_section_(kLayoutCapabilities),
156       module_functions_(),
157       module_capabilities_(),
158       module_extensions_(),
159       ordered_instructions_(),
160       all_definitions_(),
161       global_vars_(),
162       local_vars_(),
163       struct_nesting_depth_(),
164       struct_has_nested_blockorbufferblock_struct_(),
165       grammar_(ctx),
166       addressing_model_(spv::AddressingModel::Max),
167       memory_model_(spv::MemoryModel::Max),
168       pointer_size_and_alignment_(0),
169       sampler_image_addressing_mode_(0),
170       in_function_(false),
171       num_of_warnings_(0),
172       max_num_of_warnings_(max_warnings) {
173   assert(opt && "Validator options may not be Null.");
174 
175   const auto env = context_->target_env;
176 
177   if (spvIsVulkanEnv(env)) {
178     // Vulkan 1.1 includes VK_KHR_relaxed_block_layout in core.
179     if (env != SPV_ENV_VULKAN_1_0) {
180       features_.env_relaxed_block_layout = true;
181     }
182   }
183 
184   // LocalSizeId is only disallowed prior to Vulkan 1.3 without maintenance4.
185   switch (env) {
186     case SPV_ENV_VULKAN_1_0:
187     case SPV_ENV_VULKAN_1_1:
188     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
189     case SPV_ENV_VULKAN_1_2:
190       features_.env_allow_localsizeid = false;
191       break;
192     default:
193       features_.env_allow_localsizeid = true;
194       break;
195   }
196 
197   // Only attempt to count if we have words, otherwise let the other validation
198   // fail and generate an error.
199   if (num_words > 0) {
200     // Count the number of instructions in the binary.
201     // This parse should not produce any error messages. Hijack the context and
202     // replace the message consumer so that we do not pollute any state in input
203     // consumer.
204     spv_context_t hijacked_context = *ctx;
205     hijacked_context.consumer = [](spv_message_level_t, const char*,
__anond8a2fda00202(spv_message_level_t, const char*, const spv_position_t&, const char*) 206                                    const spv_position_t&, const char*) {};
207     spvBinaryParse(&hijacked_context, this, words, num_words, setHeader,
208                    CountInstructions,
209                    /* diagnostic = */ nullptr);
210     preallocateStorage();
211   }
212   UpdateFeaturesBasedOnSpirvVersion(&features_, version_);
213 
214   name_mapper_ = spvtools::GetTrivialNameMapper();
215   if (options_->use_friendly_names) {
216     friendly_mapper_ = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
217         context_, words_, num_words_);
218     name_mapper_ = friendly_mapper_->GetNameMapper();
219   }
220 }
221 
preallocateStorage()222 void ValidationState_t::preallocateStorage() {
223   ordered_instructions_.reserve(total_instructions_);
224   module_functions_.reserve(total_functions_);
225 }
226 
ForwardDeclareId(uint32_t id)227 spv_result_t ValidationState_t::ForwardDeclareId(uint32_t id) {
228   unresolved_forward_ids_.insert(id);
229   return SPV_SUCCESS;
230 }
231 
RemoveIfForwardDeclared(uint32_t id)232 spv_result_t ValidationState_t::RemoveIfForwardDeclared(uint32_t id) {
233   unresolved_forward_ids_.erase(id);
234   return SPV_SUCCESS;
235 }
236 
RegisterForwardPointer(uint32_t id)237 spv_result_t ValidationState_t::RegisterForwardPointer(uint32_t id) {
238   forward_pointer_ids_.insert(id);
239   return SPV_SUCCESS;
240 }
241 
IsForwardPointer(uint32_t id) const242 bool ValidationState_t::IsForwardPointer(uint32_t id) const {
243   return (forward_pointer_ids_.find(id) != forward_pointer_ids_.end());
244 }
245 
AssignNameToId(uint32_t id,std::string name)246 void ValidationState_t::AssignNameToId(uint32_t id, std::string name) {
247   operand_names_[id] = name;
248 }
249 
getIdName(uint32_t id) const250 std::string ValidationState_t::getIdName(uint32_t id) const {
251   const std::string id_name = name_mapper_(id);
252 
253   std::stringstream out;
254   out << "'" << id << "[%" << id_name << "]'";
255   return out.str();
256 }
257 
unresolved_forward_id_count() const258 size_t ValidationState_t::unresolved_forward_id_count() const {
259   return unresolved_forward_ids_.size();
260 }
261 
UnresolvedForwardIds() const262 std::vector<uint32_t> ValidationState_t::UnresolvedForwardIds() const {
263   std::vector<uint32_t> out(std::begin(unresolved_forward_ids_),
264                             std::end(unresolved_forward_ids_));
265   return out;
266 }
267 
IsDefinedId(uint32_t id) const268 bool ValidationState_t::IsDefinedId(uint32_t id) const {
269   return all_definitions_.find(id) != std::end(all_definitions_);
270 }
271 
FindDef(uint32_t id) const272 const Instruction* ValidationState_t::FindDef(uint32_t id) const {
273   auto it = all_definitions_.find(id);
274   if (it == all_definitions_.end()) return nullptr;
275   return it->second;
276 }
277 
FindDef(uint32_t id)278 Instruction* ValidationState_t::FindDef(uint32_t id) {
279   auto it = all_definitions_.find(id);
280   if (it == all_definitions_.end()) return nullptr;
281   return it->second;
282 }
283 
current_layout_section() const284 ModuleLayoutSection ValidationState_t::current_layout_section() const {
285   return current_layout_section_;
286 }
287 
ProgressToNextLayoutSectionOrder()288 void ValidationState_t::ProgressToNextLayoutSectionOrder() {
289   // Guard against going past the last element(kLayoutFunctionDefinitions)
290   if (current_layout_section_ <= kLayoutFunctionDefinitions) {
291     current_layout_section_ =
292         static_cast<ModuleLayoutSection>(current_layout_section_ + 1);
293   }
294 }
295 
IsOpcodeInPreviousLayoutSection(spv::Op op)296 bool ValidationState_t::IsOpcodeInPreviousLayoutSection(spv::Op op) {
297   ModuleLayoutSection section =
298       InstructionLayoutSection(current_layout_section_, op);
299   return section < current_layout_section_;
300 }
301 
IsOpcodeInCurrentLayoutSection(spv::Op op)302 bool ValidationState_t::IsOpcodeInCurrentLayoutSection(spv::Op op) {
303   return IsInstructionInLayoutSection(current_layout_section_, op);
304 }
305 
diag(spv_result_t error_code,const Instruction * inst)306 DiagnosticStream ValidationState_t::diag(spv_result_t error_code,
307                                          const Instruction* inst) {
308   if (error_code == SPV_WARNING) {
309     if (num_of_warnings_ == max_num_of_warnings_) {
310       DiagnosticStream({0, 0, 0}, context_->consumer, "", error_code)
311           << "Other warnings have been suppressed.\n";
312     }
313     if (num_of_warnings_ >= max_num_of_warnings_) {
314       return DiagnosticStream({0, 0, 0}, nullptr, "", error_code);
315     }
316     ++num_of_warnings_;
317   }
318 
319   std::string disassembly;
320   if (inst) disassembly = Disassemble(*inst);
321 
322   return DiagnosticStream({0, 0, inst ? inst->LineNum() : 0},
323                           context_->consumer, disassembly, error_code);
324 }
325 
functions()326 std::vector<Function>& ValidationState_t::functions() {
327   return module_functions_;
328 }
329 
current_function()330 Function& ValidationState_t::current_function() {
331   assert(in_function_body());
332   return module_functions_.back();
333 }
334 
current_function() const335 const Function& ValidationState_t::current_function() const {
336   assert(in_function_body());
337   return module_functions_.back();
338 }
339 
function(uint32_t id) const340 const Function* ValidationState_t::function(uint32_t id) const {
341   const auto it = id_to_function_.find(id);
342   if (it == id_to_function_.end()) return nullptr;
343   return it->second;
344 }
345 
function(uint32_t id)346 Function* ValidationState_t::function(uint32_t id) {
347   auto it = id_to_function_.find(id);
348   if (it == id_to_function_.end()) return nullptr;
349   return it->second;
350 }
351 
in_function_body() const352 bool ValidationState_t::in_function_body() const { return in_function_; }
353 
in_block() const354 bool ValidationState_t::in_block() const {
355   return module_functions_.empty() == false &&
356          module_functions_.back().current_block() != nullptr;
357 }
358 
RegisterCapability(spv::Capability cap)359 void ValidationState_t::RegisterCapability(spv::Capability cap) {
360   // Avoid redundant work.  Otherwise the recursion could induce work
361   // quadrdatic in the capability dependency depth. (Ok, not much, but
362   // it's something.)
363   if (module_capabilities_.contains(cap)) return;
364 
365   module_capabilities_.insert(cap);
366   spv_operand_desc desc;
367   if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
368                                             uint32_t(cap), &desc)) {
369     for (auto capability :
370          CapabilitySet(desc->numCapabilities, desc->capabilities)) {
371       RegisterCapability(capability);
372     }
373   }
374 
375   switch (cap) {
376     case spv::Capability::Kernel:
377       features_.group_ops_reduce_and_scans = true;
378       break;
379     case spv::Capability::Int8:
380       features_.use_int8_type = true;
381       features_.declare_int8_type = true;
382       break;
383     case spv::Capability::StorageBuffer8BitAccess:
384     case spv::Capability::UniformAndStorageBuffer8BitAccess:
385     case spv::Capability::StoragePushConstant8:
386     case spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR:
387       features_.declare_int8_type = true;
388       break;
389     case spv::Capability::Int16:
390       features_.declare_int16_type = true;
391       break;
392     case spv::Capability::Float16:
393     case spv::Capability::Float16Buffer:
394       features_.declare_float16_type = true;
395       break;
396     case spv::Capability::StorageUniformBufferBlock16:
397     case spv::Capability::StorageUniform16:
398     case spv::Capability::StoragePushConstant16:
399     case spv::Capability::StorageInputOutput16:
400     case spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR:
401       features_.declare_int16_type = true;
402       features_.declare_float16_type = true;
403       features_.free_fp_rounding_mode = true;
404       break;
405     case spv::Capability::VariablePointers:
406     case spv::Capability::VariablePointersStorageBuffer:
407       features_.variable_pointers = true;
408       break;
409     default:
410       // TODO(dneto): For now don't validate SPV_NV_ray_tracing, which uses
411       // capability spv::Capability::RayTracingNV.
412       // spv::Capability::RayTracingProvisionalKHR would need the same
413       // treatment. One of the differences going from SPV_KHR_ray_tracing from
414       // provisional to final spec was the provisional spec uses Locations
415       // for variables in certain storage classes, just like the
416       // SPV_NV_ray_tracing extension.  So it mimics the NVIDIA extension.
417       // The final SPV_KHR_ray_tracing uses a different capability token
418       // number, so it doesn't fall into this case.
419       break;
420   }
421 }
422 
RegisterExtension(Extension ext)423 void ValidationState_t::RegisterExtension(Extension ext) {
424   if (module_extensions_.contains(ext)) return;
425 
426   module_extensions_.insert(ext);
427 
428   switch (ext) {
429     case kSPV_AMD_gpu_shader_half_float:
430     case kSPV_AMD_gpu_shader_half_float_fetch:
431       // SPV_AMD_gpu_shader_half_float enables float16 type.
432       // https://github.com/KhronosGroup/SPIRV-Tools/issues/1375
433       features_.declare_float16_type = true;
434       break;
435     case kSPV_AMD_gpu_shader_int16:
436       // This is not yet in the extension, but it's recommended for it.
437       // See https://github.com/KhronosGroup/glslang/issues/848
438       features_.uconvert_spec_constant_op = true;
439       break;
440     case kSPV_AMD_shader_ballot:
441       // The grammar doesn't encode the fact that SPV_AMD_shader_ballot
442       // enables the use of group operations Reduce, InclusiveScan,
443       // and ExclusiveScan.  Enable it manually.
444       // https://github.com/KhronosGroup/SPIRV-Tools/issues/991
445       features_.group_ops_reduce_and_scans = true;
446       break;
447     default:
448       break;
449   }
450 }
451 
HasAnyOfCapabilities(const CapabilitySet & capabilities) const452 bool ValidationState_t::HasAnyOfCapabilities(
453     const CapabilitySet& capabilities) const {
454   return module_capabilities_.HasAnyOf(capabilities);
455 }
456 
HasAnyOfExtensions(const ExtensionSet & extensions) const457 bool ValidationState_t::HasAnyOfExtensions(
458     const ExtensionSet& extensions) const {
459   return module_extensions_.HasAnyOf(extensions);
460 }
461 
set_addressing_model(spv::AddressingModel am)462 void ValidationState_t::set_addressing_model(spv::AddressingModel am) {
463   addressing_model_ = am;
464   switch (am) {
465     case spv::AddressingModel::Physical32:
466       pointer_size_and_alignment_ = 4;
467       break;
468     default:
469     // fall through
470     case spv::AddressingModel::Physical64:
471     case spv::AddressingModel::PhysicalStorageBuffer64:
472       pointer_size_and_alignment_ = 8;
473       break;
474   }
475 }
476 
addressing_model() const477 spv::AddressingModel ValidationState_t::addressing_model() const {
478   return addressing_model_;
479 }
480 
set_memory_model(spv::MemoryModel mm)481 void ValidationState_t::set_memory_model(spv::MemoryModel mm) {
482   memory_model_ = mm;
483 }
484 
memory_model() const485 spv::MemoryModel ValidationState_t::memory_model() const {
486   return memory_model_;
487 }
488 
set_samplerimage_variable_address_mode(uint32_t bit_width)489 void ValidationState_t::set_samplerimage_variable_address_mode(
490     uint32_t bit_width) {
491   sampler_image_addressing_mode_ = bit_width;
492 }
493 
samplerimage_variable_address_mode() const494 uint32_t ValidationState_t::samplerimage_variable_address_mode() const {
495   return sampler_image_addressing_mode_;
496 }
497 
RegisterFunction(uint32_t id,uint32_t ret_type_id,spv::FunctionControlMask function_control,uint32_t function_type_id)498 spv_result_t ValidationState_t::RegisterFunction(
499     uint32_t id, uint32_t ret_type_id,
500     spv::FunctionControlMask function_control, uint32_t function_type_id) {
501   assert(in_function_body() == false &&
502          "RegisterFunction can only be called when parsing the binary outside "
503          "of another function");
504   in_function_ = true;
505   module_functions_.emplace_back(id, ret_type_id, function_control,
506                                  function_type_id);
507   id_to_function_.emplace(id, &current_function());
508 
509   // TODO(umar): validate function type and type_id
510 
511   return SPV_SUCCESS;
512 }
513 
RegisterFunctionEnd()514 spv_result_t ValidationState_t::RegisterFunctionEnd() {
515   assert(in_function_body() == true &&
516          "RegisterFunctionEnd can only be called when parsing the binary "
517          "inside of another function");
518   assert(in_block() == false &&
519          "RegisterFunctionParameter can only be called when parsing the binary "
520          "outside of a block");
521   current_function().RegisterFunctionEnd();
522   in_function_ = false;
523   return SPV_SUCCESS;
524 }
525 
AddOrderedInstruction(const spv_parsed_instruction_t * inst)526 Instruction* ValidationState_t::AddOrderedInstruction(
527     const spv_parsed_instruction_t* inst) {
528   ordered_instructions_.emplace_back(inst);
529   ordered_instructions_.back().SetLineNum(ordered_instructions_.size());
530   return &ordered_instructions_.back();
531 }
532 
533 // Improves diagnostic messages by collecting names of IDs
RegisterDebugInstruction(const Instruction * inst)534 void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
535   switch (inst->opcode()) {
536     case spv::Op::OpName: {
537       const auto target = inst->GetOperandAs<uint32_t>(0);
538       const std::string str = inst->GetOperandAs<std::string>(1);
539       AssignNameToId(target, str);
540       break;
541     }
542     case spv::Op::OpMemberName: {
543       const auto target = inst->GetOperandAs<uint32_t>(0);
544       const std::string str = inst->GetOperandAs<std::string>(2);
545       AssignNameToId(target, str);
546       break;
547     }
548     case spv::Op::OpSourceContinued:
549     case spv::Op::OpSource:
550     case spv::Op::OpSourceExtension:
551     case spv::Op::OpString:
552     case spv::Op::OpLine:
553     case spv::Op::OpNoLine:
554     default:
555       break;
556   }
557 }
558 
RegisterInstruction(Instruction * inst)559 void ValidationState_t::RegisterInstruction(Instruction* inst) {
560   if (inst->id()) all_definitions_.insert(std::make_pair(inst->id(), inst));
561 
562   // Some validation checks are easier by getting all the consumers
563   for (size_t i = 0; i < inst->operands().size(); ++i) {
564     const spv_parsed_operand_t& operand = inst->operand(i);
565     if ((SPV_OPERAND_TYPE_ID == operand.type) ||
566         (SPV_OPERAND_TYPE_TYPE_ID == operand.type)) {
567       const uint32_t operand_word = inst->word(operand.offset);
568       Instruction* operand_inst = FindDef(operand_word);
569       if (!operand_inst) {
570         continue;
571       }
572 
573       // If the instruction is using an OpTypeSampledImage as an operand, it
574       // should be recorded. The validator will ensure that all usages of an
575       // OpTypeSampledImage and its definition are in the same basic block.
576       if ((SPV_OPERAND_TYPE_ID == operand.type) &&
577           (spv::Op::OpSampledImage == operand_inst->opcode())) {
578         RegisterSampledImageConsumer(operand_word, inst);
579       }
580 
581       // In order to track storage classes (not Function) used per execution
582       // model we can't use RegisterExecutionModelLimitation on instructions
583       // like OpTypePointer which are going to be in the pre-function section.
584       // Instead just need to register storage class usage for consumers in a
585       // function block.
586       if (inst->function()) {
587         if (operand_inst->opcode() == spv::Op::OpTypePointer) {
588           RegisterStorageClassConsumer(
589               operand_inst->GetOperandAs<spv::StorageClass>(1), inst);
590         } else if (operand_inst->opcode() == spv::Op::OpVariable) {
591           RegisterStorageClassConsumer(
592               operand_inst->GetOperandAs<spv::StorageClass>(2), inst);
593         }
594       }
595     }
596   }
597 }
598 
getSampledImageConsumers(uint32_t sampled_image_id) const599 std::vector<Instruction*> ValidationState_t::getSampledImageConsumers(
600     uint32_t sampled_image_id) const {
601   std::vector<Instruction*> result;
602   auto iter = sampled_image_consumers_.find(sampled_image_id);
603   if (iter != sampled_image_consumers_.end()) {
604     result = iter->second;
605   }
606   return result;
607 }
608 
RegisterSampledImageConsumer(uint32_t sampled_image_id,Instruction * consumer)609 void ValidationState_t::RegisterSampledImageConsumer(uint32_t sampled_image_id,
610                                                      Instruction* consumer) {
611   sampled_image_consumers_[sampled_image_id].push_back(consumer);
612 }
613 
RegisterQCOMImageProcessingTextureConsumer(uint32_t texture_id,const Instruction * consumer0,const Instruction * consumer1)614 void ValidationState_t::RegisterQCOMImageProcessingTextureConsumer(
615     uint32_t texture_id, const Instruction* consumer0,
616     const Instruction* consumer1) {
617   if (HasDecoration(texture_id, spv::Decoration::WeightTextureQCOM) ||
618       HasDecoration(texture_id, spv::Decoration::BlockMatchTextureQCOM) ||
619       HasDecoration(texture_id, spv::Decoration::BlockMatchSamplerQCOM)) {
620     qcom_image_processing_consumers_.insert(consumer0->id());
621     if (consumer1) {
622       qcom_image_processing_consumers_.insert(consumer1->id());
623     }
624   }
625 }
626 
RegisterStorageClassConsumer(spv::StorageClass storage_class,Instruction * consumer)627 void ValidationState_t::RegisterStorageClassConsumer(
628     spv::StorageClass storage_class, Instruction* consumer) {
629   if (spvIsVulkanEnv(context()->target_env)) {
630     if (storage_class == spv::StorageClass::Output) {
631       std::string errorVUID = VkErrorID(4644);
632       function(consumer->function()->id())
633           ->RegisterExecutionModelLimitation([errorVUID](
634                                                  spv::ExecutionModel model,
635                                                  std::string* message) {
636             if (model == spv::ExecutionModel::GLCompute ||
637                 model == spv::ExecutionModel::RayGenerationKHR ||
638                 model == spv::ExecutionModel::IntersectionKHR ||
639                 model == spv::ExecutionModel::AnyHitKHR ||
640                 model == spv::ExecutionModel::ClosestHitKHR ||
641                 model == spv::ExecutionModel::MissKHR ||
642                 model == spv::ExecutionModel::CallableKHR) {
643               if (message) {
644                 *message =
645                     errorVUID +
646                     "in Vulkan environment, Output Storage Class must not be "
647                     "used in GLCompute, RayGenerationKHR, IntersectionKHR, "
648                     "AnyHitKHR, ClosestHitKHR, MissKHR, or CallableKHR "
649                     "execution models";
650               }
651               return false;
652             }
653             return true;
654           });
655     }
656 
657     if (storage_class == spv::StorageClass::Workgroup) {
658       std::string errorVUID = VkErrorID(4645);
659       function(consumer->function()->id())
660           ->RegisterExecutionModelLimitation([errorVUID](
661                                                  spv::ExecutionModel model,
662                                                  std::string* message) {
663             if (model != spv::ExecutionModel::GLCompute &&
664                 model != spv::ExecutionModel::TaskNV &&
665                 model != spv::ExecutionModel::MeshNV &&
666                 model != spv::ExecutionModel::TaskEXT &&
667                 model != spv::ExecutionModel::MeshEXT) {
668               if (message) {
669                 *message =
670                     errorVUID +
671                     "in Vulkan environment, Workgroup Storage Class is limited "
672                     "to MeshNV, TaskNV, and GLCompute execution model";
673               }
674               return false;
675             }
676             return true;
677           });
678     }
679   }
680 
681   if (storage_class == spv::StorageClass::CallableDataKHR) {
682     std::string errorVUID = VkErrorID(4704);
683     function(consumer->function()->id())
684         ->RegisterExecutionModelLimitation(
685             [errorVUID](spv::ExecutionModel model, std::string* message) {
686               if (model != spv::ExecutionModel::RayGenerationKHR &&
687                   model != spv::ExecutionModel::ClosestHitKHR &&
688                   model != spv::ExecutionModel::CallableKHR &&
689                   model != spv::ExecutionModel::MissKHR) {
690                 if (message) {
691                   *message =
692                       errorVUID +
693                       "CallableDataKHR Storage Class is limited to "
694                       "RayGenerationKHR, ClosestHitKHR, CallableKHR, and "
695                       "MissKHR execution model";
696                 }
697                 return false;
698               }
699               return true;
700             });
701   } else if (storage_class == spv::StorageClass::IncomingCallableDataKHR) {
702     std::string errorVUID = VkErrorID(4705);
703     function(consumer->function()->id())
704         ->RegisterExecutionModelLimitation(
705             [errorVUID](spv::ExecutionModel model, std::string* message) {
706               if (model != spv::ExecutionModel::CallableKHR) {
707                 if (message) {
708                   *message =
709                       errorVUID +
710                       "IncomingCallableDataKHR Storage Class is limited to "
711                       "CallableKHR execution model";
712                 }
713                 return false;
714               }
715               return true;
716             });
717   } else if (storage_class == spv::StorageClass::RayPayloadKHR) {
718     std::string errorVUID = VkErrorID(4698);
719     function(consumer->function()->id())
720         ->RegisterExecutionModelLimitation([errorVUID](
721                                                spv::ExecutionModel model,
722                                                std::string* message) {
723           if (model != spv::ExecutionModel::RayGenerationKHR &&
724               model != spv::ExecutionModel::ClosestHitKHR &&
725               model != spv::ExecutionModel::MissKHR) {
726             if (message) {
727               *message =
728                   errorVUID +
729                   "RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
730                   "ClosestHitKHR, and MissKHR execution model";
731             }
732             return false;
733           }
734           return true;
735         });
736   } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
737     std::string errorVUID = VkErrorID(4701);
738     function(consumer->function()->id())
739         ->RegisterExecutionModelLimitation(
740             [errorVUID](spv::ExecutionModel model, std::string* message) {
741               if (model != spv::ExecutionModel::IntersectionKHR &&
742                   model != spv::ExecutionModel::AnyHitKHR &&
743                   model != spv::ExecutionModel::ClosestHitKHR) {
744                 if (message) {
745                   *message = errorVUID +
746                              "HitAttributeKHR Storage Class is limited to "
747                              "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR "
748                              "execution model";
749                 }
750                 return false;
751               }
752               return true;
753             });
754   } else if (storage_class == spv::StorageClass::IncomingRayPayloadKHR) {
755     std::string errorVUID = VkErrorID(4699);
756     function(consumer->function()->id())
757         ->RegisterExecutionModelLimitation(
758             [errorVUID](spv::ExecutionModel model, std::string* message) {
759               if (model != spv::ExecutionModel::AnyHitKHR &&
760                   model != spv::ExecutionModel::ClosestHitKHR &&
761                   model != spv::ExecutionModel::MissKHR) {
762                 if (message) {
763                   *message =
764                       errorVUID +
765                       "IncomingRayPayloadKHR Storage Class is limited to "
766                       "AnyHitKHR, ClosestHitKHR, and MissKHR execution model";
767                 }
768                 return false;
769               }
770               return true;
771             });
772   } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
773     std::string errorVUID = VkErrorID(7119);
774     function(consumer->function()->id())
775         ->RegisterExecutionModelLimitation(
776             [errorVUID](spv::ExecutionModel model, std::string* message) {
777               if (model != spv::ExecutionModel::RayGenerationKHR &&
778                   model != spv::ExecutionModel::IntersectionKHR &&
779                   model != spv::ExecutionModel::AnyHitKHR &&
780                   model != spv::ExecutionModel::ClosestHitKHR &&
781                   model != spv::ExecutionModel::CallableKHR &&
782                   model != spv::ExecutionModel::MissKHR) {
783                 if (message) {
784                   *message =
785                       errorVUID +
786                       "ShaderRecordBufferKHR Storage Class is limited to "
787                       "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
788                       "ClosestHitKHR, CallableKHR, and MissKHR execution model";
789                 }
790                 return false;
791               }
792               return true;
793             });
794   } else if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
795     function(consumer->function()->id())
796         ->RegisterExecutionModelLimitation(
797             [](spv::ExecutionModel model, std::string* message) {
798               if (model != spv::ExecutionModel::TaskEXT &&
799                   model != spv::ExecutionModel::MeshEXT) {
800                 if (message) {
801                   *message =
802                       "TaskPayloadWorkgroupEXT Storage Class is limited to "
803                       "TaskEXT and MeshKHR execution model";
804                 }
805                 return false;
806               }
807               return true;
808             });
809   } else if (storage_class == spv::StorageClass::HitObjectAttributeNV) {
810     function(consumer->function()->id())
811         ->RegisterExecutionModelLimitation([](spv::ExecutionModel model,
812                                               std::string* message) {
813           if (model != spv::ExecutionModel::RayGenerationKHR &&
814               model != spv::ExecutionModel::ClosestHitKHR &&
815               model != spv::ExecutionModel::MissKHR) {
816             if (message) {
817               *message =
818                   "HitObjectAttributeNV Storage Class is limited to "
819                   "RayGenerationKHR, ClosestHitKHR or MissKHR execution model";
820             }
821             return false;
822           }
823           return true;
824         });
825   }
826 }
827 
getIdBound() const828 uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
829 
setIdBound(const uint32_t bound)830 void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
831 
RegisterUniqueTypeDeclaration(const Instruction * inst)832 bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) {
833   std::vector<uint32_t> key;
834   key.push_back(static_cast<uint32_t>(inst->opcode()));
835   for (size_t index = 0; index < inst->operands().size(); ++index) {
836     const spv_parsed_operand_t& operand = inst->operand(index);
837 
838     if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue;
839 
840     const int words_begin = operand.offset;
841     const int words_end = words_begin + operand.num_words;
842     assert(words_end <= static_cast<int>(inst->words().size()));
843 
844     key.insert(key.end(), inst->words().begin() + words_begin,
845                inst->words().begin() + words_end);
846   }
847 
848   return unique_type_declarations_.insert(std::move(key)).second;
849 }
850 
GetTypeId(uint32_t id) const851 uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
852   const Instruction* inst = FindDef(id);
853   return inst ? inst->type_id() : 0;
854 }
855 
GetIdOpcode(uint32_t id) const856 spv::Op ValidationState_t::GetIdOpcode(uint32_t id) const {
857   const Instruction* inst = FindDef(id);
858   return inst ? inst->opcode() : spv::Op::OpNop;
859 }
860 
GetComponentType(uint32_t id) const861 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
862   const Instruction* inst = FindDef(id);
863   assert(inst);
864 
865   switch (inst->opcode()) {
866     case spv::Op::OpTypeFloat:
867     case spv::Op::OpTypeInt:
868     case spv::Op::OpTypeBool:
869       return id;
870 
871     case spv::Op::OpTypeVector:
872       return inst->word(2);
873 
874     case spv::Op::OpTypeMatrix:
875       return GetComponentType(inst->word(2));
876 
877     case spv::Op::OpTypeCooperativeMatrixNV:
878     case spv::Op::OpTypeCooperativeMatrixKHR:
879       return inst->word(2);
880 
881     default:
882       break;
883   }
884 
885   if (inst->type_id()) return GetComponentType(inst->type_id());
886 
887   assert(0);
888   return 0;
889 }
890 
GetDimension(uint32_t id) const891 uint32_t ValidationState_t::GetDimension(uint32_t id) const {
892   const Instruction* inst = FindDef(id);
893   assert(inst);
894 
895   switch (inst->opcode()) {
896     case spv::Op::OpTypeFloat:
897     case spv::Op::OpTypeInt:
898     case spv::Op::OpTypeBool:
899       return 1;
900 
901     case spv::Op::OpTypeVector:
902     case spv::Op::OpTypeMatrix:
903       return inst->word(3);
904 
905     case spv::Op::OpTypeCooperativeMatrixNV:
906     case spv::Op::OpTypeCooperativeMatrixKHR:
907       // Actual dimension isn't known, return 0
908       return 0;
909 
910     default:
911       break;
912   }
913 
914   if (inst->type_id()) return GetDimension(inst->type_id());
915 
916   assert(0);
917   return 0;
918 }
919 
GetBitWidth(uint32_t id) const920 uint32_t ValidationState_t::GetBitWidth(uint32_t id) const {
921   const uint32_t component_type_id = GetComponentType(id);
922   const Instruction* inst = FindDef(component_type_id);
923   assert(inst);
924 
925   if (inst->opcode() == spv::Op::OpTypeFloat ||
926       inst->opcode() == spv::Op::OpTypeInt)
927     return inst->word(2);
928 
929   if (inst->opcode() == spv::Op::OpTypeBool) return 1;
930 
931   assert(0);
932   return 0;
933 }
934 
IsVoidType(uint32_t id) const935 bool ValidationState_t::IsVoidType(uint32_t id) const {
936   const Instruction* inst = FindDef(id);
937   return inst && inst->opcode() == spv::Op::OpTypeVoid;
938 }
939 
IsFloatScalarType(uint32_t id) const940 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
941   const Instruction* inst = FindDef(id);
942   return inst && inst->opcode() == spv::Op::OpTypeFloat;
943 }
944 
IsFloatVectorType(uint32_t id) const945 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
946   const Instruction* inst = FindDef(id);
947   if (!inst) {
948     return false;
949   }
950 
951   if (inst->opcode() == spv::Op::OpTypeVector) {
952     return IsFloatScalarType(GetComponentType(id));
953   }
954 
955   return false;
956 }
957 
IsFloat16Vector2Or4Type(uint32_t id) const958 bool ValidationState_t::IsFloat16Vector2Or4Type(uint32_t id) const {
959   const Instruction* inst = FindDef(id);
960   assert(inst);
961 
962   if (inst->opcode() == spv::Op::OpTypeVector) {
963     uint32_t vectorDim = GetDimension(id);
964     return IsFloatScalarType(GetComponentType(id)) &&
965            (vectorDim == 2 || vectorDim == 4) &&
966            (GetBitWidth(GetComponentType(id)) == 16);
967   }
968 
969   return false;
970 }
971 
IsFloatScalarOrVectorType(uint32_t id) const972 bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
973   const Instruction* inst = FindDef(id);
974   if (!inst) {
975     return false;
976   }
977 
978   if (inst->opcode() == spv::Op::OpTypeFloat) {
979     return true;
980   }
981 
982   if (inst->opcode() == spv::Op::OpTypeVector) {
983     return IsFloatScalarType(GetComponentType(id));
984   }
985 
986   return false;
987 }
988 
IsIntScalarType(uint32_t id) const989 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
990   const Instruction* inst = FindDef(id);
991   return inst && inst->opcode() == spv::Op::OpTypeInt;
992 }
993 
IsIntVectorType(uint32_t id) const994 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
995   const Instruction* inst = FindDef(id);
996   if (!inst) {
997     return false;
998   }
999 
1000   if (inst->opcode() == spv::Op::OpTypeVector) {
1001     return IsIntScalarType(GetComponentType(id));
1002   }
1003 
1004   return false;
1005 }
1006 
IsIntScalarOrVectorType(uint32_t id) const1007 bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
1008   const Instruction* inst = FindDef(id);
1009   if (!inst) {
1010     return false;
1011   }
1012 
1013   if (inst->opcode() == spv::Op::OpTypeInt) {
1014     return true;
1015   }
1016 
1017   if (inst->opcode() == spv::Op::OpTypeVector) {
1018     return IsIntScalarType(GetComponentType(id));
1019   }
1020 
1021   return false;
1022 }
1023 
IsUnsignedIntScalarType(uint32_t id) const1024 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
1025   const Instruction* inst = FindDef(id);
1026   return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 0;
1027 }
1028 
IsUnsignedIntVectorType(uint32_t id) const1029 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
1030   const Instruction* inst = FindDef(id);
1031   if (!inst) {
1032     return false;
1033   }
1034 
1035   if (inst->opcode() == spv::Op::OpTypeVector) {
1036     return IsUnsignedIntScalarType(GetComponentType(id));
1037   }
1038 
1039   return false;
1040 }
1041 
IsUnsignedIntScalarOrVectorType(uint32_t id) const1042 bool ValidationState_t::IsUnsignedIntScalarOrVectorType(uint32_t id) const {
1043   const Instruction* inst = FindDef(id);
1044   if (!inst) {
1045     return false;
1046   }
1047 
1048   if (inst->opcode() == spv::Op::OpTypeInt) {
1049     return inst->GetOperandAs<uint32_t>(2) == 0;
1050   }
1051 
1052   if (inst->opcode() == spv::Op::OpTypeVector) {
1053     return IsUnsignedIntScalarType(GetComponentType(id));
1054   }
1055 
1056   return false;
1057 }
1058 
IsSignedIntScalarType(uint32_t id) const1059 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
1060   const Instruction* inst = FindDef(id);
1061   return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 1;
1062 }
1063 
IsSignedIntVectorType(uint32_t id) const1064 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
1065   const Instruction* inst = FindDef(id);
1066   if (!inst) {
1067     return false;
1068   }
1069 
1070   if (inst->opcode() == spv::Op::OpTypeVector) {
1071     return IsSignedIntScalarType(GetComponentType(id));
1072   }
1073 
1074   return false;
1075 }
1076 
IsBoolScalarType(uint32_t id) const1077 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
1078   const Instruction* inst = FindDef(id);
1079   return inst && inst->opcode() == spv::Op::OpTypeBool;
1080 }
1081 
IsBoolVectorType(uint32_t id) const1082 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
1083   const Instruction* inst = FindDef(id);
1084   if (!inst) {
1085     return false;
1086   }
1087 
1088   if (inst->opcode() == spv::Op::OpTypeVector) {
1089     return IsBoolScalarType(GetComponentType(id));
1090   }
1091 
1092   return false;
1093 }
1094 
IsBoolScalarOrVectorType(uint32_t id) const1095 bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
1096   const Instruction* inst = FindDef(id);
1097   if (!inst) {
1098     return false;
1099   }
1100 
1101   if (inst->opcode() == spv::Op::OpTypeBool) {
1102     return true;
1103   }
1104 
1105   if (inst->opcode() == spv::Op::OpTypeVector) {
1106     return IsBoolScalarType(GetComponentType(id));
1107   }
1108 
1109   return false;
1110 }
1111 
IsFloatMatrixType(uint32_t id) const1112 bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
1113   const Instruction* inst = FindDef(id);
1114   if (!inst) {
1115     return false;
1116   }
1117 
1118   if (inst->opcode() == spv::Op::OpTypeMatrix) {
1119     return IsFloatScalarType(GetComponentType(id));
1120   }
1121 
1122   return false;
1123 }
1124 
GetMatrixTypeInfo(uint32_t id,uint32_t * num_rows,uint32_t * num_cols,uint32_t * column_type,uint32_t * component_type) const1125 bool ValidationState_t::GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows,
1126                                           uint32_t* num_cols,
1127                                           uint32_t* column_type,
1128                                           uint32_t* component_type) const {
1129   if (!id) return false;
1130 
1131   const Instruction* mat_inst = FindDef(id);
1132   assert(mat_inst);
1133   if (mat_inst->opcode() != spv::Op::OpTypeMatrix) return false;
1134 
1135   const uint32_t vec_type = mat_inst->word(2);
1136   const Instruction* vec_inst = FindDef(vec_type);
1137   assert(vec_inst);
1138 
1139   if (vec_inst->opcode() != spv::Op::OpTypeVector) {
1140     assert(0);
1141     return false;
1142   }
1143 
1144   *num_cols = mat_inst->word(3);
1145   *num_rows = vec_inst->word(3);
1146   *column_type = mat_inst->word(2);
1147   *component_type = vec_inst->word(2);
1148 
1149   return true;
1150 }
1151 
GetStructMemberTypes(uint32_t struct_type_id,std::vector<uint32_t> * member_types) const1152 bool ValidationState_t::GetStructMemberTypes(
1153     uint32_t struct_type_id, std::vector<uint32_t>* member_types) const {
1154   member_types->clear();
1155   if (!struct_type_id) return false;
1156 
1157   const Instruction* inst = FindDef(struct_type_id);
1158   assert(inst);
1159   if (inst->opcode() != spv::Op::OpTypeStruct) return false;
1160 
1161   *member_types =
1162       std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
1163 
1164   if (member_types->empty()) return false;
1165 
1166   return true;
1167 }
1168 
IsPointerType(uint32_t id) const1169 bool ValidationState_t::IsPointerType(uint32_t id) const {
1170   const Instruction* inst = FindDef(id);
1171   return inst && inst->opcode() == spv::Op::OpTypePointer;
1172 }
1173 
GetPointerTypeInfo(uint32_t id,uint32_t * data_type,spv::StorageClass * storage_class) const1174 bool ValidationState_t::GetPointerTypeInfo(
1175     uint32_t id, uint32_t* data_type, spv::StorageClass* storage_class) const {
1176   *storage_class = spv::StorageClass::Max;
1177   if (!id) return false;
1178 
1179   const Instruction* inst = FindDef(id);
1180   assert(inst);
1181   if (inst->opcode() != spv::Op::OpTypePointer) return false;
1182 
1183   *storage_class = spv::StorageClass(inst->word(2));
1184   *data_type = inst->word(3);
1185   return true;
1186 }
1187 
IsAccelerationStructureType(uint32_t id) const1188 bool ValidationState_t::IsAccelerationStructureType(uint32_t id) const {
1189   const Instruction* inst = FindDef(id);
1190   return inst && inst->opcode() == spv::Op::OpTypeAccelerationStructureKHR;
1191 }
1192 
IsCooperativeMatrixType(uint32_t id) const1193 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
1194   const Instruction* inst = FindDef(id);
1195   return inst && (inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV ||
1196                   inst->opcode() == spv::Op::OpTypeCooperativeMatrixKHR);
1197 }
1198 
IsCooperativeMatrixNVType(uint32_t id) const1199 bool ValidationState_t::IsCooperativeMatrixNVType(uint32_t id) const {
1200   const Instruction* inst = FindDef(id);
1201   return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV;
1202 }
1203 
IsCooperativeMatrixKHRType(uint32_t id) const1204 bool ValidationState_t::IsCooperativeMatrixKHRType(uint32_t id) const {
1205   const Instruction* inst = FindDef(id);
1206   return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixKHR;
1207 }
1208 
IsCooperativeMatrixAType(uint32_t id) const1209 bool ValidationState_t::IsCooperativeMatrixAType(uint32_t id) const {
1210   if (!IsCooperativeMatrixKHRType(id)) return false;
1211   const Instruction* inst = FindDef(id);
1212   uint64_t matrixUse = 0;
1213   if (EvalConstantValUint64(inst->word(6), &matrixUse)) {
1214     return matrixUse ==
1215            static_cast<uint64_t>(spv::CooperativeMatrixUse::MatrixAKHR);
1216   }
1217   return false;
1218 }
1219 
IsCooperativeMatrixBType(uint32_t id) const1220 bool ValidationState_t::IsCooperativeMatrixBType(uint32_t id) const {
1221   if (!IsCooperativeMatrixKHRType(id)) return false;
1222   const Instruction* inst = FindDef(id);
1223   uint64_t matrixUse = 0;
1224   if (EvalConstantValUint64(inst->word(6), &matrixUse)) {
1225     return matrixUse ==
1226            static_cast<uint64_t>(spv::CooperativeMatrixUse::MatrixBKHR);
1227   }
1228   return false;
1229 }
IsCooperativeMatrixAccType(uint32_t id) const1230 bool ValidationState_t::IsCooperativeMatrixAccType(uint32_t id) const {
1231   if (!IsCooperativeMatrixKHRType(id)) return false;
1232   const Instruction* inst = FindDef(id);
1233   uint64_t matrixUse = 0;
1234   if (EvalConstantValUint64(inst->word(6), &matrixUse)) {
1235     return matrixUse == static_cast<uint64_t>(
1236                             spv::CooperativeMatrixUse::MatrixAccumulatorKHR);
1237   }
1238   return false;
1239 }
1240 
IsFloatCooperativeMatrixType(uint32_t id) const1241 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
1242   if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1243     return false;
1244   return IsFloatScalarType(FindDef(id)->word(2));
1245 }
1246 
IsIntCooperativeMatrixType(uint32_t id) const1247 bool ValidationState_t::IsIntCooperativeMatrixType(uint32_t id) const {
1248   if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1249     return false;
1250   return IsIntScalarType(FindDef(id)->word(2));
1251 }
1252 
IsUnsignedIntCooperativeMatrixType(uint32_t id) const1253 bool ValidationState_t::IsUnsignedIntCooperativeMatrixType(uint32_t id) const {
1254   if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1255     return false;
1256   return IsUnsignedIntScalarType(FindDef(id)->word(2));
1257 }
1258 
1259 // Either a 32 bit 2-component uint vector or a 64 bit uint scalar
IsUnsigned64BitHandle(uint32_t id) const1260 bool ValidationState_t::IsUnsigned64BitHandle(uint32_t id) const {
1261   return ((IsUnsignedIntScalarType(id) && GetBitWidth(id) == 64) ||
1262           (IsUnsignedIntVectorType(id) && GetDimension(id) == 2 &&
1263            GetBitWidth(id) == 32));
1264 }
1265 
CooperativeMatrixShapesMatch(const Instruction * inst,uint32_t m1,uint32_t m2)1266 spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
1267     const Instruction* inst, uint32_t m1, uint32_t m2) {
1268   const auto m1_type = FindDef(m1);
1269   const auto m2_type = FindDef(m2);
1270 
1271   if (m1_type->opcode() != m2_type->opcode()) {
1272     return diag(SPV_ERROR_INVALID_DATA, inst)
1273            << "Expected cooperative matrix types";
1274   }
1275 
1276   uint32_t m1_scope_id = m1_type->GetOperandAs<uint32_t>(2);
1277   uint32_t m1_rows_id = m1_type->GetOperandAs<uint32_t>(3);
1278   uint32_t m1_cols_id = m1_type->GetOperandAs<uint32_t>(4);
1279 
1280   uint32_t m2_scope_id = m2_type->GetOperandAs<uint32_t>(2);
1281   uint32_t m2_rows_id = m2_type->GetOperandAs<uint32_t>(3);
1282   uint32_t m2_cols_id = m2_type->GetOperandAs<uint32_t>(4);
1283 
1284   bool m1_is_int32 = false, m1_is_const_int32 = false, m2_is_int32 = false,
1285        m2_is_const_int32 = false;
1286   uint32_t m1_value = 0, m2_value = 0;
1287 
1288   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1289       EvalInt32IfConst(m1_scope_id);
1290   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1291       EvalInt32IfConst(m2_scope_id);
1292 
1293   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1294     return diag(SPV_ERROR_INVALID_DATA, inst)
1295            << "Expected scopes of Matrix and Result Type to be "
1296            << "identical";
1297   }
1298 
1299   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1300       EvalInt32IfConst(m1_rows_id);
1301   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1302       EvalInt32IfConst(m2_rows_id);
1303 
1304   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1305     return diag(SPV_ERROR_INVALID_DATA, inst)
1306            << "Expected rows of Matrix type and Result Type to be "
1307            << "identical";
1308   }
1309 
1310   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1311       EvalInt32IfConst(m1_cols_id);
1312   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1313       EvalInt32IfConst(m2_cols_id);
1314 
1315   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1316     return diag(SPV_ERROR_INVALID_DATA, inst)
1317            << "Expected columns of Matrix type and Result Type to be "
1318            << "identical";
1319   }
1320 
1321   if (m1_type->opcode() == spv::Op::OpTypeCooperativeMatrixKHR) {
1322     uint32_t m1_use_id = m1_type->GetOperandAs<uint32_t>(5);
1323     uint32_t m2_use_id = m2_type->GetOperandAs<uint32_t>(5);
1324     std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1325         EvalInt32IfConst(m1_use_id);
1326     std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1327         EvalInt32IfConst(m2_use_id);
1328 
1329     if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1330       return diag(SPV_ERROR_INVALID_DATA, inst)
1331              << "Expected Use of Matrix type and Result Type to be "
1332              << "identical";
1333     }
1334   }
1335 
1336   return SPV_SUCCESS;
1337 }
1338 
GetOperandTypeId(const Instruction * inst,size_t operand_index) const1339 uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst,
1340                                              size_t operand_index) const {
1341   return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index));
1342 }
1343 
EvalConstantValUint64(uint32_t id,uint64_t * val) const1344 bool ValidationState_t::EvalConstantValUint64(uint32_t id,
1345                                               uint64_t* val) const {
1346   const Instruction* inst = FindDef(id);
1347   if (!inst) {
1348     assert(0 && "Instruction not found");
1349     return false;
1350   }
1351 
1352   if (!IsIntScalarType(inst->type_id())) return false;
1353 
1354   if (inst->opcode() == spv::Op::OpConstantNull) {
1355     *val = 0;
1356   } else if (inst->opcode() != spv::Op::OpConstant) {
1357     // Spec constant values cannot be evaluated so don't consider constant for
1358     // static validation
1359     return false;
1360   } else if (inst->words().size() == 4) {
1361     *val = inst->word(3);
1362   } else {
1363     assert(inst->words().size() == 5);
1364     *val = inst->word(3);
1365     *val |= uint64_t(inst->word(4)) << 32;
1366   }
1367   return true;
1368 }
1369 
EvalConstantValInt64(uint32_t id,int64_t * val) const1370 bool ValidationState_t::EvalConstantValInt64(uint32_t id, int64_t* val) const {
1371   const Instruction* inst = FindDef(id);
1372   if (!inst) {
1373     assert(0 && "Instruction not found");
1374     return false;
1375   }
1376 
1377   if (!IsIntScalarType(inst->type_id())) return false;
1378 
1379   if (inst->opcode() == spv::Op::OpConstantNull) {
1380     *val = 0;
1381   } else if (inst->opcode() != spv::Op::OpConstant) {
1382     // Spec constant values cannot be evaluated so don't consider constant for
1383     // static validation
1384     return false;
1385   } else if (inst->words().size() == 4) {
1386     *val = int32_t(inst->word(3));
1387   } else {
1388     assert(inst->words().size() == 5);
1389     const uint32_t lo_word = inst->word(3);
1390     const uint32_t hi_word = inst->word(4);
1391     *val = static_cast<int64_t>(uint64_t(lo_word) | uint64_t(hi_word) << 32);
1392   }
1393   return true;
1394 }
1395 
EvalInt32IfConst(uint32_t id) const1396 std::tuple<bool, bool, uint32_t> ValidationState_t::EvalInt32IfConst(
1397     uint32_t id) const {
1398   const Instruction* const inst = FindDef(id);
1399   assert(inst);
1400   const uint32_t type = inst->type_id();
1401 
1402   if (type == 0 || !IsIntScalarType(type) || GetBitWidth(type) != 32) {
1403     return std::make_tuple(false, false, 0);
1404   }
1405 
1406   // Spec constant values cannot be evaluated so don't consider constant for
1407   // the purpose of this method.
1408   if (!spvOpcodeIsConstant(inst->opcode()) ||
1409       spvOpcodeIsSpecConstant(inst->opcode())) {
1410     return std::make_tuple(true, false, 0);
1411   }
1412 
1413   if (inst->opcode() == spv::Op::OpConstantNull) {
1414     return std::make_tuple(true, true, 0);
1415   }
1416 
1417   assert(inst->words().size() == 4);
1418   return std::make_tuple(true, true, inst->word(3));
1419 }
1420 
ComputeFunctionToEntryPointMapping()1421 void ValidationState_t::ComputeFunctionToEntryPointMapping() {
1422   for (const uint32_t entry_point : entry_points()) {
1423     std::stack<uint32_t> call_stack;
1424     std::set<uint32_t> visited;
1425     call_stack.push(entry_point);
1426     while (!call_stack.empty()) {
1427       const uint32_t called_func_id = call_stack.top();
1428       call_stack.pop();
1429       if (!visited.insert(called_func_id).second) continue;
1430 
1431       function_to_entry_points_[called_func_id].push_back(entry_point);
1432 
1433       const Function* called_func = function(called_func_id);
1434       if (called_func) {
1435         // Other checks should error out on this invalid SPIR-V.
1436         for (const uint32_t new_call : called_func->function_call_targets()) {
1437           call_stack.push(new_call);
1438         }
1439       }
1440     }
1441   }
1442 }
1443 
ComputeRecursiveEntryPoints()1444 void ValidationState_t::ComputeRecursiveEntryPoints() {
1445   for (const Function& func : functions()) {
1446     std::stack<uint32_t> call_stack;
1447     std::set<uint32_t> visited;
1448 
1449     for (const uint32_t new_call : func.function_call_targets()) {
1450       call_stack.push(new_call);
1451     }
1452 
1453     while (!call_stack.empty()) {
1454       const uint32_t called_func_id = call_stack.top();
1455       call_stack.pop();
1456 
1457       if (!visited.insert(called_func_id).second) continue;
1458 
1459       if (called_func_id == func.id()) {
1460         for (const uint32_t entry_point :
1461              function_to_entry_points_[called_func_id])
1462           recursive_entry_points_.insert(entry_point);
1463         break;
1464       }
1465 
1466       const Function* called_func = function(called_func_id);
1467       if (called_func) {
1468         // Other checks should error out on this invalid SPIR-V.
1469         for (const uint32_t new_call : called_func->function_call_targets()) {
1470           call_stack.push(new_call);
1471         }
1472       }
1473     }
1474   }
1475 }
1476 
FunctionEntryPoints(uint32_t func) const1477 const std::vector<uint32_t>& ValidationState_t::FunctionEntryPoints(
1478     uint32_t func) const {
1479   auto iter = function_to_entry_points_.find(func);
1480   if (iter == function_to_entry_points_.end()) {
1481     return empty_ids_;
1482   } else {
1483     return iter->second;
1484   }
1485 }
1486 
EntryPointReferences(uint32_t id) const1487 std::set<uint32_t> ValidationState_t::EntryPointReferences(uint32_t id) const {
1488   std::set<uint32_t> referenced_entry_points;
1489   const auto inst = FindDef(id);
1490   if (!inst) return referenced_entry_points;
1491 
1492   std::vector<const Instruction*> stack;
1493   stack.push_back(inst);
1494   while (!stack.empty()) {
1495     const auto current_inst = stack.back();
1496     stack.pop_back();
1497 
1498     if (const auto func = current_inst->function()) {
1499       // Instruction lives in a function, we can stop searching.
1500       const auto function_entry_points = FunctionEntryPoints(func->id());
1501       referenced_entry_points.insert(function_entry_points.begin(),
1502                                      function_entry_points.end());
1503     } else {
1504       // Instruction is in the global scope, keep searching its uses.
1505       for (auto pair : current_inst->uses()) {
1506         const auto next_inst = pair.first;
1507         stack.push_back(next_inst);
1508       }
1509     }
1510   }
1511 
1512   return referenced_entry_points;
1513 }
1514 
Disassemble(const Instruction & inst) const1515 std::string ValidationState_t::Disassemble(const Instruction& inst) const {
1516   const spv_parsed_instruction_t& c_inst(inst.c_inst());
1517   return Disassemble(c_inst.words, c_inst.num_words);
1518 }
1519 
Disassemble(const uint32_t * words,uint16_t num_words) const1520 std::string ValidationState_t::Disassemble(const uint32_t* words,
1521                                            uint16_t num_words) const {
1522   uint32_t disassembly_options = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1523                                  SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
1524 
1525   return spvInstructionBinaryToText(context()->target_env, words, num_words,
1526                                     words_, num_words_, disassembly_options);
1527 }
1528 
LogicallyMatch(const Instruction * lhs,const Instruction * rhs,bool check_decorations)1529 bool ValidationState_t::LogicallyMatch(const Instruction* lhs,
1530                                        const Instruction* rhs,
1531                                        bool check_decorations) {
1532   if (lhs->opcode() != rhs->opcode()) {
1533     return false;
1534   }
1535 
1536   if (check_decorations) {
1537     const auto& dec_a = id_decorations(lhs->id());
1538     const auto& dec_b = id_decorations(rhs->id());
1539 
1540     for (const auto& dec : dec_b) {
1541       if (std::find(dec_a.begin(), dec_a.end(), dec) == dec_a.end()) {
1542         return false;
1543       }
1544     }
1545   }
1546 
1547   if (lhs->opcode() == spv::Op::OpTypeArray) {
1548     // Size operands must match.
1549     if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
1550       return false;
1551     }
1552 
1553     // Elements must match or logically match.
1554     const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(1u);
1555     const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(1u);
1556     if (lhs_ele_id == rhs_ele_id) {
1557       return true;
1558     }
1559 
1560     const auto lhs_ele = FindDef(lhs_ele_id);
1561     const auto rhs_ele = FindDef(rhs_ele_id);
1562     if (!lhs_ele || !rhs_ele) {
1563       return false;
1564     }
1565     return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
1566   } else if (lhs->opcode() == spv::Op::OpTypeStruct) {
1567     // Number of elements must match.
1568     if (lhs->operands().size() != rhs->operands().size()) {
1569       return false;
1570     }
1571 
1572     for (size_t i = 1u; i < lhs->operands().size(); ++i) {
1573       const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(i);
1574       const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(i);
1575       // Elements must match or logically match.
1576       if (lhs_ele_id == rhs_ele_id) {
1577         continue;
1578       }
1579 
1580       const auto lhs_ele = FindDef(lhs_ele_id);
1581       const auto rhs_ele = FindDef(rhs_ele_id);
1582       if (!lhs_ele || !rhs_ele) {
1583         return false;
1584       }
1585 
1586       if (!LogicallyMatch(lhs_ele, rhs_ele, check_decorations)) {
1587         return false;
1588       }
1589     }
1590 
1591     // All checks passed.
1592     return true;
1593   }
1594 
1595   // No other opcodes are acceptable at this point. Arrays and structs are
1596   // caught above and if they're elements are not arrays or structs they are
1597   // required to match exactly.
1598   return false;
1599 }
1600 
TracePointer(const Instruction * inst) const1601 const Instruction* ValidationState_t::TracePointer(
1602     const Instruction* inst) const {
1603   auto base_ptr = inst;
1604   while (base_ptr->opcode() == spv::Op::OpAccessChain ||
1605          base_ptr->opcode() == spv::Op::OpInBoundsAccessChain ||
1606          base_ptr->opcode() == spv::Op::OpPtrAccessChain ||
1607          base_ptr->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
1608          base_ptr->opcode() == spv::Op::OpCopyObject) {
1609     base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
1610   }
1611   return base_ptr;
1612 }
1613 
ContainsType(uint32_t id,const std::function<bool (const Instruction *)> & f,bool traverse_all_types) const1614 bool ValidationState_t::ContainsType(
1615     uint32_t id, const std::function<bool(const Instruction*)>& f,
1616     bool traverse_all_types) const {
1617   const auto inst = FindDef(id);
1618   if (!inst) return false;
1619 
1620   if (f(inst)) return true;
1621 
1622   switch (inst->opcode()) {
1623     case spv::Op::OpTypeArray:
1624     case spv::Op::OpTypeRuntimeArray:
1625     case spv::Op::OpTypeVector:
1626     case spv::Op::OpTypeMatrix:
1627     case spv::Op::OpTypeImage:
1628     case spv::Op::OpTypeSampledImage:
1629     case spv::Op::OpTypeCooperativeMatrixNV:
1630     case spv::Op::OpTypeCooperativeMatrixKHR:
1631       return ContainsType(inst->GetOperandAs<uint32_t>(1u), f,
1632                           traverse_all_types);
1633     case spv::Op::OpTypePointer:
1634       if (IsForwardPointer(id)) return false;
1635       if (traverse_all_types) {
1636         return ContainsType(inst->GetOperandAs<uint32_t>(2u), f,
1637                             traverse_all_types);
1638       }
1639       break;
1640     case spv::Op::OpTypeFunction:
1641     case spv::Op::OpTypeStruct:
1642       if (inst->opcode() == spv::Op::OpTypeFunction && !traverse_all_types) {
1643         return false;
1644       }
1645       for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1646         if (ContainsType(inst->GetOperandAs<uint32_t>(i), f,
1647                          traverse_all_types)) {
1648           return true;
1649         }
1650       }
1651       break;
1652     default:
1653       break;
1654   }
1655 
1656   return false;
1657 }
1658 
ContainsSizedIntOrFloatType(uint32_t id,spv::Op type,uint32_t width) const1659 bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
1660                                                     uint32_t width) const {
1661   if (type != spv::Op::OpTypeInt && type != spv::Op::OpTypeFloat) return false;
1662 
1663   const auto f = [type, width](const Instruction* inst) {
1664     if (inst->opcode() == type) {
1665       return inst->GetOperandAs<uint32_t>(1u) == width;
1666     }
1667     return false;
1668   };
1669   return ContainsType(id, f);
1670 }
1671 
ContainsLimitedUseIntOrFloatType(uint32_t id) const1672 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
1673   if ((!HasCapability(spv::Capability::Int16) &&
1674        ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 16)) ||
1675       (!HasCapability(spv::Capability::Int8) &&
1676        ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 8)) ||
1677       (!HasCapability(spv::Capability::Float16) &&
1678        ContainsSizedIntOrFloatType(id, spv::Op::OpTypeFloat, 16))) {
1679     return true;
1680   }
1681   return false;
1682 }
1683 
ContainsRuntimeArray(uint32_t id) const1684 bool ValidationState_t::ContainsRuntimeArray(uint32_t id) const {
1685   const auto f = [](const Instruction* inst) {
1686     return inst->opcode() == spv::Op::OpTypeRuntimeArray;
1687   };
1688   return ContainsType(id, f, /* traverse_all_types = */ false);
1689 }
1690 
IsValidStorageClass(spv::StorageClass storage_class) const1691 bool ValidationState_t::IsValidStorageClass(
1692     spv::StorageClass storage_class) const {
1693   if (spvIsVulkanEnv(context()->target_env)) {
1694     switch (storage_class) {
1695       case spv::StorageClass::UniformConstant:
1696       case spv::StorageClass::Uniform:
1697       case spv::StorageClass::StorageBuffer:
1698       case spv::StorageClass::Input:
1699       case spv::StorageClass::Output:
1700       case spv::StorageClass::Image:
1701       case spv::StorageClass::Workgroup:
1702       case spv::StorageClass::Private:
1703       case spv::StorageClass::Function:
1704       case spv::StorageClass::PushConstant:
1705       case spv::StorageClass::PhysicalStorageBuffer:
1706       case spv::StorageClass::RayPayloadKHR:
1707       case spv::StorageClass::IncomingRayPayloadKHR:
1708       case spv::StorageClass::HitAttributeKHR:
1709       case spv::StorageClass::CallableDataKHR:
1710       case spv::StorageClass::IncomingCallableDataKHR:
1711       case spv::StorageClass::ShaderRecordBufferKHR:
1712       case spv::StorageClass::TaskPayloadWorkgroupEXT:
1713       case spv::StorageClass::HitObjectAttributeNV:
1714       case spv::StorageClass::TileImageEXT:
1715         return true;
1716       default:
1717         return false;
1718     }
1719   }
1720 
1721   return true;
1722 }
1723 
1724 #define VUID_WRAP(vuid) "[" #vuid "] "
1725 
1726 // Currently no 2 VUID share the same id, so no need for |reference|
VkErrorID(uint32_t id,const char *) const1727 std::string ValidationState_t::VkErrorID(uint32_t id,
1728                                          const char* /*reference*/) const {
1729   if (!spvIsVulkanEnv(context_->target_env)) {
1730     return "";
1731   }
1732 
1733   // This large switch case is only searched when an error has occurred.
1734   // If an id is changed, the old case must be modified or removed. Each string
1735   // here is interpreted as being "implemented"
1736 
1737   // Clang format adds spaces between hyphens
1738   // clang-format off
1739   switch (id) {
1740     case 4154:
1741       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04154);
1742     case 4155:
1743       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04155);
1744     case 4156:
1745       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04156);
1746     case 4160:
1747       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04160);
1748     case 4161:
1749       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04161);
1750     case 4162:
1751       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04162);
1752     case 4181:
1753       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04181);
1754     case 4182:
1755       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04182);
1756     case 4183:
1757       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04183);
1758     case 4184:
1759       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04184);
1760     case 4185:
1761       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04185);
1762     case 4186:
1763       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04186);
1764     case 4187:
1765       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
1766     case 4188:
1767       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04188);
1768     case 4189:
1769       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04189);
1770     case 4190:
1771       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04190);
1772     case 4191:
1773       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
1774     case 4196:
1775       return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
1776     case 4197:
1777       return VUID_WRAP(VUID-CullDistance-CullDistance-04197);
1778     case 4198:
1779       return VUID_WRAP(VUID-CullDistance-CullDistance-04198);
1780     case 4199:
1781       return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
1782     case 4200:
1783       return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
1784     case 6735:
1785       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06735); // Execution Model
1786     case 6736:
1787       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06736); // input storage
1788     case 6737:
1789       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06737); // 32 int scalar
1790     case 4205:
1791       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04205);
1792     case 4206:
1793       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04206);
1794     case 4207:
1795       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04207);
1796     case 4208:
1797       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04208);
1798     case 4209:
1799       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04209);
1800     case 4210:
1801       return VUID_WRAP(VUID-FragCoord-FragCoord-04210);
1802     case 4211:
1803       return VUID_WRAP(VUID-FragCoord-FragCoord-04211);
1804     case 4212:
1805       return VUID_WRAP(VUID-FragCoord-FragCoord-04212);
1806     case 4213:
1807       return VUID_WRAP(VUID-FragDepth-FragDepth-04213);
1808     case 4214:
1809       return VUID_WRAP(VUID-FragDepth-FragDepth-04214);
1810     case 4215:
1811       return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
1812     case 4216:
1813       return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
1814     case 4217:
1815       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
1816     case 4218:
1817       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
1818     case 4219:
1819       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
1820     case 4220:
1821       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
1822     case 4221:
1823       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
1824     case 4222:
1825       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
1826     case 4223:
1827       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
1828     case 4224:
1829       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
1830     case 4225:
1831       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
1832     case 4229:
1833       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
1834     case 4230:
1835       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
1836     case 4231:
1837       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
1838     case 4232:
1839       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
1840     case 4233:
1841       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
1842     case 4234:
1843       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
1844     case 4236:
1845       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
1846     case 4237:
1847       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04237);
1848     case 4238:
1849       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04238);
1850     case 4239:
1851       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04239);
1852     case 4240:
1853       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
1854     case 4241:
1855       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
1856     case 4242:
1857       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04242);
1858     case 4243:
1859       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04243);
1860     case 4244:
1861       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04244);
1862     case 4245:
1863       return VUID_WRAP(VUID-HitTNV-HitTNV-04245);
1864     case 4246:
1865       return VUID_WRAP(VUID-HitTNV-HitTNV-04246);
1866     case 4247:
1867       return VUID_WRAP(VUID-HitTNV-HitTNV-04247);
1868     case 4248:
1869       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248);
1870     case 4249:
1871       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249);
1872     case 4250:
1873       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250);
1874     case 4251:
1875       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251);
1876     case 4252:
1877       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252);
1878     case 4253:
1879       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253);
1880     case 4254:
1881       return VUID_WRAP(VUID-InstanceId-InstanceId-04254);
1882     case 4255:
1883       return VUID_WRAP(VUID-InstanceId-InstanceId-04255);
1884     case 4256:
1885       return VUID_WRAP(VUID-InstanceId-InstanceId-04256);
1886     case 4257:
1887       return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
1888     case 4258:
1889       return VUID_WRAP(VUID-InvocationId-InvocationId-04258);
1890     case 4259:
1891       return VUID_WRAP(VUID-InvocationId-InvocationId-04259);
1892     case 4263:
1893       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04263);
1894     case 4264:
1895       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
1896     case 4265:
1897       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
1898     case 4266:
1899       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04266);
1900     case 4267:
1901       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04267);
1902     case 4268:
1903       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04268);
1904     case 4269:
1905       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04269);
1906     case 4270:
1907       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04270);
1908     case 4271:
1909       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04271);
1910     case 4272:
1911       return VUID_WRAP(VUID-Layer-Layer-04272);
1912     case 4273:
1913       return VUID_WRAP(VUID-Layer-Layer-04273);
1914     case 4274:
1915       return VUID_WRAP(VUID-Layer-Layer-04274);
1916     case 4275:
1917       return VUID_WRAP(VUID-Layer-Layer-04275);
1918     case 4276:
1919       return VUID_WRAP(VUID-Layer-Layer-04276);
1920     case 4281:
1921       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04281);
1922     case 4282:
1923       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
1924     case 4283:
1925       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
1926     case 4293:
1927       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
1928     case 4294:
1929       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
1930     case 4295:
1931       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
1932     case 4296:
1933       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
1934     case 4297:
1935       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04297);
1936     case 4298:
1937       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04298);
1938     case 4299:
1939       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299);
1940     case 4300:
1941       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300);
1942     case 4301:
1943       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301);
1944     case 4302:
1945       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302);
1946     case 4303:
1947       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303);
1948     case 4304:
1949       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304);
1950     case 4305:
1951       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305);
1952     case 4306:
1953       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306);
1954     case 4307:
1955       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307);
1956     case 4308:
1957       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
1958     case 4309:
1959       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04309);
1960     case 4310:
1961       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04310);
1962     case 4311:
1963       return VUID_WRAP(VUID-PointCoord-PointCoord-04311);
1964     case 4312:
1965       return VUID_WRAP(VUID-PointCoord-PointCoord-04312);
1966     case 4313:
1967       return VUID_WRAP(VUID-PointCoord-PointCoord-04313);
1968     case 4314:
1969       return VUID_WRAP(VUID-PointSize-PointSize-04314);
1970     case 4315:
1971       return VUID_WRAP(VUID-PointSize-PointSize-04315);
1972     case 4316:
1973       return VUID_WRAP(VUID-PointSize-PointSize-04316);
1974     case 4317:
1975       return VUID_WRAP(VUID-PointSize-PointSize-04317);
1976     case 4318:
1977       return VUID_WRAP(VUID-Position-Position-04318);
1978     case 4319:
1979       return VUID_WRAP(VUID-Position-Position-04319);
1980     case 4320:
1981       return VUID_WRAP(VUID-Position-Position-04320);
1982     case 4321:
1983       return VUID_WRAP(VUID-Position-Position-04321);
1984     case 4330:
1985       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
1986     case 4334:
1987       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
1988     case 4337:
1989       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
1990     case 4345:
1991       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345);
1992     case 4346:
1993       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346);
1994     case 4347:
1995       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347);
1996     case 4348:
1997       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04348);
1998     case 4349:
1999       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04349);
2000     case 4350:
2001       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04350);
2002     case 4351:
2003       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04351);
2004     case 4352:
2005       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04352);
2006     case 4353:
2007       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04353);
2008     case 4354:
2009       return VUID_WRAP(VUID-SampleId-SampleId-04354);
2010     case 4355:
2011       return VUID_WRAP(VUID-SampleId-SampleId-04355);
2012     case 4356:
2013       return VUID_WRAP(VUID-SampleId-SampleId-04356);
2014     case 4357:
2015       return VUID_WRAP(VUID-SampleMask-SampleMask-04357);
2016     case 4358:
2017       return VUID_WRAP(VUID-SampleMask-SampleMask-04358);
2018     case 4359:
2019       return VUID_WRAP(VUID-SampleMask-SampleMask-04359);
2020     case 4360:
2021       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04360);
2022     case 4361:
2023       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
2024     case 4362:
2025       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
2026     case 4367:
2027       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
2028     case 4368:
2029       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
2030     case 4369:
2031       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
2032     case 4370:
2033       return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
2034     case 4371:
2035       return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
2036     case 4372:
2037       return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
2038     case 4373:
2039       return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
2040     case 4374:
2041       return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
2042     case 4375:
2043       return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
2044     case 4376:
2045       return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
2046     case 4377:
2047       return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
2048     case 4378:
2049       return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
2050     case 4379:
2051       return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
2052     case 4380:
2053       return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
2054     case 4381:
2055       return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
2056     case 4382:
2057       return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
2058     case 4383:
2059       return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
2060     case 4387:
2061       return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
2062     case 4388:
2063       return VUID_WRAP(VUID-TessCoord-TessCoord-04388);
2064     case 4389:
2065       return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
2066     case 4390:
2067       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
2068     case 4391:
2069       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04391);
2070     case 4392:
2071       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04392);
2072     case 4393:
2073       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
2074     case 4394:
2075       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
2076     case 4395:
2077       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04395);
2078     case 4396:
2079       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04396);
2080     case 4397:
2081       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
2082     case 4398:
2083       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04398);
2084     case 4399:
2085       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04399);
2086     case 4400:
2087       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04400);
2088     case 4401:
2089       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04401);
2090     case 4402:
2091       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04402);
2092     case 4403:
2093       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
2094     case 4404:
2095       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
2096     case 4405:
2097       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04405);
2098     case 4406:
2099       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
2100     case 4407:
2101       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407);
2102     case 4408:
2103       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
2104     case 4422:
2105       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04422);
2106     case 4423:
2107       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04423);
2108     case 4424:
2109       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04424);
2110     case 4425:
2111       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04425);
2112     case 4426:
2113       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
2114     case 4427:
2115       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
2116     case 4428:
2117       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428);
2118     case 4429:
2119       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429);
2120     case 4430:
2121       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430);
2122     case 4431:
2123       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431);
2124     case 4432:
2125       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432);
2126     case 4433:
2127       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433);
2128     case 4434:
2129       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04434);
2130     case 4435:
2131       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04435);
2132     case 4436:
2133       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04436);
2134     case 4484:
2135       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
2136     case 4485:
2137       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485);
2138     case 4486:
2139       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486);
2140     case 4490:
2141       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490);
2142     case 4491:
2143       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
2144     case 4492:
2145       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
2146     case 4633:
2147       return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
2148     case 4634:
2149       return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
2150     case 4635:
2151       return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
2152     case 4636:
2153       return VUID_WRAP(VUID-StandaloneSpirv-None-04636);
2154     case 4637:
2155       return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
2156     case 4638:
2157       return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
2158     case 7321:
2159       return VUID_WRAP(VUID-StandaloneSpirv-None-07321);
2160     case 4640:
2161       return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
2162     case 4641:
2163       return VUID_WRAP(VUID-StandaloneSpirv-None-04641);
2164     case 4642:
2165       return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
2166     case 4643:
2167       return VUID_WRAP(VUID-StandaloneSpirv-None-04643);
2168     case 4644:
2169       return VUID_WRAP(VUID-StandaloneSpirv-None-04644);
2170     case 4645:
2171       return VUID_WRAP(VUID-StandaloneSpirv-None-04645);
2172     case 4650:
2173       return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04650);
2174     case 4651:
2175       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
2176     case 4652:
2177       return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
2178     case 4653:
2179       return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
2180     case 4654:
2181       return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
2182     case 4655:
2183       return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-04655);
2184     case 4656:
2185       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
2186     case 4657:
2187       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
2188     case 4658:
2189       return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
2190     case 4659:
2191       return VUID_WRAP(VUID-StandaloneSpirv-OpImageQuerySizeLod-04659);
2192     case 4663:
2193       return VUID_WRAP(VUID-StandaloneSpirv-Offset-04663);
2194     case 4664:
2195       return VUID_WRAP(VUID-StandaloneSpirv-OpImageGather-04664);
2196     case 4667:
2197       return VUID_WRAP(VUID-StandaloneSpirv-None-04667);
2198     case 4669:
2199       return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
2200     case 4670:
2201       return VUID_WRAP(VUID-StandaloneSpirv-Flat-04670);
2202     case 4675:
2203       return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
2204     case 4677:
2205       return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
2206     case 4680:
2207       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeRuntimeArray-04680);
2208     case 4682:
2209       return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
2210     case 6426:
2211       return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-06426); // formally 04683
2212     case 4685:
2213       return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
2214     case 4686:
2215       return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
2216     case 4698:
2217       return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698);
2218     case 4699:
2219       return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699);
2220     case 4700:
2221       return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04700);
2222     case 4701:
2223       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701);
2224     case 4702:
2225       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04702);
2226     case 4703:
2227       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703);
2228     case 4704:
2229       return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704);
2230     case 4705:
2231       return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705);
2232     case 4706:
2233       return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04706);
2234     case 7119:
2235       return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119);
2236     case 4708:
2237       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708);
2238     case 4710:
2239       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710);
2240     case 4711:
2241       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
2242     case 4730:
2243       return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicStore-04730);
2244     case 4731:
2245       return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicLoad-04731);
2246     case 4732:
2247       return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04732);
2248     case 4733:
2249       return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
2250     case 4734:
2251       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04734);
2252     case 4744:
2253       return VUID_WRAP(VUID-StandaloneSpirv-Flat-04744);
2254     case 4777:
2255       return VUID_WRAP(VUID-StandaloneSpirv-OpImage-04777);
2256     case 4780:
2257       return VUID_WRAP(VUID-StandaloneSpirv-Result-04780);
2258     case 4781:
2259       return VUID_WRAP(VUID-StandaloneSpirv-Base-04781);
2260     case 4915:
2261       return VUID_WRAP(VUID-StandaloneSpirv-Location-04915);
2262     case 4916:
2263       return VUID_WRAP(VUID-StandaloneSpirv-Location-04916);
2264     case 4917:
2265       return VUID_WRAP(VUID-StandaloneSpirv-Location-04917);
2266     case 4918:
2267       return VUID_WRAP(VUID-StandaloneSpirv-Location-04918);
2268     case 4919:
2269       return VUID_WRAP(VUID-StandaloneSpirv-Location-04919);
2270     case 4920:
2271       return VUID_WRAP(VUID-StandaloneSpirv-Component-04920);
2272     case 4921:
2273       return VUID_WRAP(VUID-StandaloneSpirv-Component-04921);
2274     case 4922:
2275       return VUID_WRAP(VUID-StandaloneSpirv-Component-04922);
2276     case 4923:
2277       return VUID_WRAP(VUID-StandaloneSpirv-Component-04923);
2278     case 4924:
2279       return VUID_WRAP(VUID-StandaloneSpirv-Component-04924);
2280     case 6201:
2281       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06201);
2282     case 6202:
2283       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06202);
2284     case 6214:
2285       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-06214);
2286     case 6491:
2287       return VUID_WRAP(VUID-StandaloneSpirv-DescriptorSet-06491);
2288     case 6671:
2289       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeSampledImage-06671);
2290     case 6672:
2291       return VUID_WRAP(VUID-StandaloneSpirv-Location-06672);
2292     case 6673:
2293       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-06673);
2294     case 6674:
2295       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-06674);
2296     case 6675:
2297       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06675);
2298     case 6676:
2299       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06676);
2300     case 6677:
2301       return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-06677);
2302     case 6678:
2303       return VUID_WRAP(VUID-StandaloneSpirv-InputAttachmentIndex-06678);
2304     case 6777:
2305       return VUID_WRAP(VUID-StandaloneSpirv-PerVertexKHR-06777);
2306     case 6778:
2307       return VUID_WRAP(VUID-StandaloneSpirv-Input-06778);
2308     case 6807:
2309       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06807);
2310     case 6808:
2311       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
2312     case 6925:
2313       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
2314     case 7041:
2315       return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07041);
2316     case 7043:
2317       return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07043);
2318     case 7044:
2319       return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07044);
2320     case 7047:
2321       return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07047);
2322     case 7049:
2323       return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07049);
2324     case 7050:
2325       return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07050);
2326     case 7053:
2327       return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07053);
2328     case 7055:
2329       return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07055);
2330     case 7056:
2331       return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07056);
2332     case 7102:
2333       return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
2334     case 7320:
2335       return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
2336     case 7290:
2337       return VUID_WRAP(VUID-StandaloneSpirv-Input-07290);
2338     case 7650:
2339       return VUID_WRAP(VUID-StandaloneSpirv-Base-07650);
2340     case 7651:
2341       return VUID_WRAP(VUID-StandaloneSpirv-Base-07651);
2342     case 7652:
2343       return VUID_WRAP(VUID-StandaloneSpirv-Base-07652);
2344     case 7703:
2345       return VUID_WRAP(VUID-StandaloneSpirv-Component-07703);
2346     case 7951:
2347       return VUID_WRAP(VUID-StandaloneSpirv-SubgroupVoteKHR-07951);
2348     case 8721:
2349       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08721);
2350     case 8722:
2351       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08722);
2352     case 8973:
2353       return VUID_WRAP(VUID-StandaloneSpirv-Pointer-08973);
2354     case 9638:
2355       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-09638);
2356     default:
2357       return "";  // unknown id
2358   }
2359   // clang-format on
2360 }
2361 
2362 }  // namespace val
2363 }  // namespace spvtools
2364