• 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*,
__anone05b7e310202(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     qcom_image_processing_consumers_.insert(consumer0->id());
620     if (consumer1) {
621       qcom_image_processing_consumers_.insert(consumer1->id());
622     }
623   }
624 }
625 
RegisterStorageClassConsumer(spv::StorageClass storage_class,Instruction * consumer)626 void ValidationState_t::RegisterStorageClassConsumer(
627     spv::StorageClass storage_class, Instruction* consumer) {
628   if (spvIsVulkanEnv(context()->target_env)) {
629     if (storage_class == spv::StorageClass::Output) {
630       std::string errorVUID = VkErrorID(4644);
631       function(consumer->function()->id())
632           ->RegisterExecutionModelLimitation([errorVUID](
633                                                  spv::ExecutionModel model,
634                                                  std::string* message) {
635             if (model == spv::ExecutionModel::GLCompute ||
636                 model == spv::ExecutionModel::RayGenerationKHR ||
637                 model == spv::ExecutionModel::IntersectionKHR ||
638                 model == spv::ExecutionModel::AnyHitKHR ||
639                 model == spv::ExecutionModel::ClosestHitKHR ||
640                 model == spv::ExecutionModel::MissKHR ||
641                 model == spv::ExecutionModel::CallableKHR) {
642               if (message) {
643                 *message =
644                     errorVUID +
645                     "in Vulkan environment, Output Storage Class must not be "
646                     "used in GLCompute, RayGenerationKHR, IntersectionKHR, "
647                     "AnyHitKHR, ClosestHitKHR, MissKHR, or CallableKHR "
648                     "execution models";
649               }
650               return false;
651             }
652             return true;
653           });
654     }
655 
656     if (storage_class == spv::StorageClass::Workgroup) {
657       std::string errorVUID = VkErrorID(4645);
658       function(consumer->function()->id())
659           ->RegisterExecutionModelLimitation([errorVUID](
660                                                  spv::ExecutionModel model,
661                                                  std::string* message) {
662             if (model != spv::ExecutionModel::GLCompute &&
663                 model != spv::ExecutionModel::TaskNV &&
664                 model != spv::ExecutionModel::MeshNV &&
665                 model != spv::ExecutionModel::TaskEXT &&
666                 model != spv::ExecutionModel::MeshEXT) {
667               if (message) {
668                 *message =
669                     errorVUID +
670                     "in Vulkan environment, Workgroup Storage Class is limited "
671                     "to MeshNV, TaskNV, and GLCompute execution model";
672               }
673               return false;
674             }
675             return true;
676           });
677     }
678   }
679 
680   if (storage_class == spv::StorageClass::CallableDataKHR) {
681     std::string errorVUID = VkErrorID(4704);
682     function(consumer->function()->id())
683         ->RegisterExecutionModelLimitation(
684             [errorVUID](spv::ExecutionModel model, std::string* message) {
685               if (model != spv::ExecutionModel::RayGenerationKHR &&
686                   model != spv::ExecutionModel::ClosestHitKHR &&
687                   model != spv::ExecutionModel::CallableKHR &&
688                   model != spv::ExecutionModel::MissKHR) {
689                 if (message) {
690                   *message =
691                       errorVUID +
692                       "CallableDataKHR Storage Class is limited to "
693                       "RayGenerationKHR, ClosestHitKHR, CallableKHR, and "
694                       "MissKHR execution model";
695                 }
696                 return false;
697               }
698               return true;
699             });
700   } else if (storage_class == spv::StorageClass::IncomingCallableDataKHR) {
701     std::string errorVUID = VkErrorID(4705);
702     function(consumer->function()->id())
703         ->RegisterExecutionModelLimitation(
704             [errorVUID](spv::ExecutionModel model, std::string* message) {
705               if (model != spv::ExecutionModel::CallableKHR) {
706                 if (message) {
707                   *message =
708                       errorVUID +
709                       "IncomingCallableDataKHR Storage Class is limited to "
710                       "CallableKHR execution model";
711                 }
712                 return false;
713               }
714               return true;
715             });
716   } else if (storage_class == spv::StorageClass::RayPayloadKHR) {
717     std::string errorVUID = VkErrorID(4698);
718     function(consumer->function()->id())
719         ->RegisterExecutionModelLimitation([errorVUID](
720                                                spv::ExecutionModel model,
721                                                std::string* message) {
722           if (model != spv::ExecutionModel::RayGenerationKHR &&
723               model != spv::ExecutionModel::ClosestHitKHR &&
724               model != spv::ExecutionModel::MissKHR) {
725             if (message) {
726               *message =
727                   errorVUID +
728                   "RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
729                   "ClosestHitKHR, and MissKHR execution model";
730             }
731             return false;
732           }
733           return true;
734         });
735   } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
736     std::string errorVUID = VkErrorID(4701);
737     function(consumer->function()->id())
738         ->RegisterExecutionModelLimitation(
739             [errorVUID](spv::ExecutionModel model, std::string* message) {
740               if (model != spv::ExecutionModel::IntersectionKHR &&
741                   model != spv::ExecutionModel::AnyHitKHR &&
742                   model != spv::ExecutionModel::ClosestHitKHR) {
743                 if (message) {
744                   *message = errorVUID +
745                              "HitAttributeKHR Storage Class is limited to "
746                              "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR "
747                              "execution model";
748                 }
749                 return false;
750               }
751               return true;
752             });
753   } else if (storage_class == spv::StorageClass::IncomingRayPayloadKHR) {
754     std::string errorVUID = VkErrorID(4699);
755     function(consumer->function()->id())
756         ->RegisterExecutionModelLimitation(
757             [errorVUID](spv::ExecutionModel model, std::string* message) {
758               if (model != spv::ExecutionModel::AnyHitKHR &&
759                   model != spv::ExecutionModel::ClosestHitKHR &&
760                   model != spv::ExecutionModel::MissKHR) {
761                 if (message) {
762                   *message =
763                       errorVUID +
764                       "IncomingRayPayloadKHR Storage Class is limited to "
765                       "AnyHitKHR, ClosestHitKHR, and MissKHR execution model";
766                 }
767                 return false;
768               }
769               return true;
770             });
771   } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
772     std::string errorVUID = VkErrorID(7119);
773     function(consumer->function()->id())
774         ->RegisterExecutionModelLimitation(
775             [errorVUID](spv::ExecutionModel model, std::string* message) {
776               if (model != spv::ExecutionModel::RayGenerationKHR &&
777                   model != spv::ExecutionModel::IntersectionKHR &&
778                   model != spv::ExecutionModel::AnyHitKHR &&
779                   model != spv::ExecutionModel::ClosestHitKHR &&
780                   model != spv::ExecutionModel::CallableKHR &&
781                   model != spv::ExecutionModel::MissKHR) {
782                 if (message) {
783                   *message =
784                       errorVUID +
785                       "ShaderRecordBufferKHR Storage Class is limited to "
786                       "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
787                       "ClosestHitKHR, CallableKHR, and MissKHR execution model";
788                 }
789                 return false;
790               }
791               return true;
792             });
793   } else if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
794     function(consumer->function()->id())
795         ->RegisterExecutionModelLimitation(
796             [](spv::ExecutionModel model, std::string* message) {
797               if (model != spv::ExecutionModel::TaskEXT &&
798                   model != spv::ExecutionModel::MeshEXT) {
799                 if (message) {
800                   *message =
801                       "TaskPayloadWorkgroupEXT Storage Class is limited to "
802                       "TaskEXT and MeshKHR execution model";
803                 }
804                 return false;
805               }
806               return true;
807             });
808   } else if (storage_class == spv::StorageClass::HitObjectAttributeNV) {
809     function(consumer->function()->id())
810         ->RegisterExecutionModelLimitation([](spv::ExecutionModel model,
811                                               std::string* message) {
812           if (model != spv::ExecutionModel::RayGenerationKHR &&
813               model != spv::ExecutionModel::ClosestHitKHR &&
814               model != spv::ExecutionModel::MissKHR) {
815             if (message) {
816               *message =
817                   "HitObjectAttributeNV Storage Class is limited to "
818                   "RayGenerationKHR, ClosestHitKHR or MissKHR execution model";
819             }
820             return false;
821           }
822           return true;
823         });
824   }
825 }
826 
getIdBound() const827 uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
828 
setIdBound(const uint32_t bound)829 void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
830 
RegisterUniqueTypeDeclaration(const Instruction * inst)831 bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) {
832   std::vector<uint32_t> key;
833   key.push_back(static_cast<uint32_t>(inst->opcode()));
834   for (size_t index = 0; index < inst->operands().size(); ++index) {
835     const spv_parsed_operand_t& operand = inst->operand(index);
836 
837     if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue;
838 
839     const int words_begin = operand.offset;
840     const int words_end = words_begin + operand.num_words;
841     assert(words_end <= static_cast<int>(inst->words().size()));
842 
843     key.insert(key.end(), inst->words().begin() + words_begin,
844                inst->words().begin() + words_end);
845   }
846 
847   return unique_type_declarations_.insert(std::move(key)).second;
848 }
849 
GetTypeId(uint32_t id) const850 uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
851   const Instruction* inst = FindDef(id);
852   return inst ? inst->type_id() : 0;
853 }
854 
GetIdOpcode(uint32_t id) const855 spv::Op ValidationState_t::GetIdOpcode(uint32_t id) const {
856   const Instruction* inst = FindDef(id);
857   return inst ? inst->opcode() : spv::Op::OpNop;
858 }
859 
GetComponentType(uint32_t id) const860 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
861   const Instruction* inst = FindDef(id);
862   assert(inst);
863 
864   switch (inst->opcode()) {
865     case spv::Op::OpTypeFloat:
866     case spv::Op::OpTypeInt:
867     case spv::Op::OpTypeBool:
868       return id;
869 
870     case spv::Op::OpTypeVector:
871       return inst->word(2);
872 
873     case spv::Op::OpTypeMatrix:
874       return GetComponentType(inst->word(2));
875 
876     case spv::Op::OpTypeCooperativeMatrixNV:
877     case spv::Op::OpTypeCooperativeMatrixKHR:
878       return inst->word(2);
879 
880     default:
881       break;
882   }
883 
884   if (inst->type_id()) return GetComponentType(inst->type_id());
885 
886   assert(0);
887   return 0;
888 }
889 
GetDimension(uint32_t id) const890 uint32_t ValidationState_t::GetDimension(uint32_t id) const {
891   const Instruction* inst = FindDef(id);
892   assert(inst);
893 
894   switch (inst->opcode()) {
895     case spv::Op::OpTypeFloat:
896     case spv::Op::OpTypeInt:
897     case spv::Op::OpTypeBool:
898       return 1;
899 
900     case spv::Op::OpTypeVector:
901     case spv::Op::OpTypeMatrix:
902       return inst->word(3);
903 
904     case spv::Op::OpTypeCooperativeMatrixNV:
905     case spv::Op::OpTypeCooperativeMatrixKHR:
906       // Actual dimension isn't known, return 0
907       return 0;
908 
909     default:
910       break;
911   }
912 
913   if (inst->type_id()) return GetDimension(inst->type_id());
914 
915   assert(0);
916   return 0;
917 }
918 
GetBitWidth(uint32_t id) const919 uint32_t ValidationState_t::GetBitWidth(uint32_t id) const {
920   const uint32_t component_type_id = GetComponentType(id);
921   const Instruction* inst = FindDef(component_type_id);
922   assert(inst);
923 
924   if (inst->opcode() == spv::Op::OpTypeFloat ||
925       inst->opcode() == spv::Op::OpTypeInt)
926     return inst->word(2);
927 
928   if (inst->opcode() == spv::Op::OpTypeBool) return 1;
929 
930   assert(0);
931   return 0;
932 }
933 
IsVoidType(uint32_t id) const934 bool ValidationState_t::IsVoidType(uint32_t id) const {
935   const Instruction* inst = FindDef(id);
936   return inst && inst->opcode() == spv::Op::OpTypeVoid;
937 }
938 
IsFloatScalarType(uint32_t id) const939 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
940   const Instruction* inst = FindDef(id);
941   return inst && inst->opcode() == spv::Op::OpTypeFloat;
942 }
943 
IsFloatVectorType(uint32_t id) const944 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
945   const Instruction* inst = FindDef(id);
946   if (!inst) {
947     return false;
948   }
949 
950   if (inst->opcode() == spv::Op::OpTypeVector) {
951     return IsFloatScalarType(GetComponentType(id));
952   }
953 
954   return false;
955 }
956 
IsFloatScalarOrVectorType(uint32_t id) const957 bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
958   const Instruction* inst = FindDef(id);
959   if (!inst) {
960     return false;
961   }
962 
963   if (inst->opcode() == spv::Op::OpTypeFloat) {
964     return true;
965   }
966 
967   if (inst->opcode() == spv::Op::OpTypeVector) {
968     return IsFloatScalarType(GetComponentType(id));
969   }
970 
971   return false;
972 }
973 
IsIntScalarType(uint32_t id) const974 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
975   const Instruction* inst = FindDef(id);
976   return inst && inst->opcode() == spv::Op::OpTypeInt;
977 }
978 
IsIntVectorType(uint32_t id) const979 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
980   const Instruction* inst = FindDef(id);
981   if (!inst) {
982     return false;
983   }
984 
985   if (inst->opcode() == spv::Op::OpTypeVector) {
986     return IsIntScalarType(GetComponentType(id));
987   }
988 
989   return false;
990 }
991 
IsIntScalarOrVectorType(uint32_t id) const992 bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
993   const Instruction* inst = FindDef(id);
994   if (!inst) {
995     return false;
996   }
997 
998   if (inst->opcode() == spv::Op::OpTypeInt) {
999     return true;
1000   }
1001 
1002   if (inst->opcode() == spv::Op::OpTypeVector) {
1003     return IsIntScalarType(GetComponentType(id));
1004   }
1005 
1006   return false;
1007 }
1008 
IsUnsignedIntScalarType(uint32_t id) const1009 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
1010   const Instruction* inst = FindDef(id);
1011   return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 0;
1012 }
1013 
IsUnsignedIntVectorType(uint32_t id) const1014 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
1015   const Instruction* inst = FindDef(id);
1016   if (!inst) {
1017     return false;
1018   }
1019 
1020   if (inst->opcode() == spv::Op::OpTypeVector) {
1021     return IsUnsignedIntScalarType(GetComponentType(id));
1022   }
1023 
1024   return false;
1025 }
1026 
IsUnsignedIntScalarOrVectorType(uint32_t id) const1027 bool ValidationState_t::IsUnsignedIntScalarOrVectorType(uint32_t id) const {
1028   const Instruction* inst = FindDef(id);
1029   if (!inst) {
1030     return false;
1031   }
1032 
1033   if (inst->opcode() == spv::Op::OpTypeInt) {
1034     return inst->GetOperandAs<uint32_t>(2) == 0;
1035   }
1036 
1037   if (inst->opcode() == spv::Op::OpTypeVector) {
1038     return IsUnsignedIntScalarType(GetComponentType(id));
1039   }
1040 
1041   return false;
1042 }
1043 
IsSignedIntScalarType(uint32_t id) const1044 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
1045   const Instruction* inst = FindDef(id);
1046   return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 1;
1047 }
1048 
IsSignedIntVectorType(uint32_t id) const1049 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
1050   const Instruction* inst = FindDef(id);
1051   if (!inst) {
1052     return false;
1053   }
1054 
1055   if (inst->opcode() == spv::Op::OpTypeVector) {
1056     return IsSignedIntScalarType(GetComponentType(id));
1057   }
1058 
1059   return false;
1060 }
1061 
IsBoolScalarType(uint32_t id) const1062 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
1063   const Instruction* inst = FindDef(id);
1064   return inst && inst->opcode() == spv::Op::OpTypeBool;
1065 }
1066 
IsBoolVectorType(uint32_t id) const1067 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
1068   const Instruction* inst = FindDef(id);
1069   if (!inst) {
1070     return false;
1071   }
1072 
1073   if (inst->opcode() == spv::Op::OpTypeVector) {
1074     return IsBoolScalarType(GetComponentType(id));
1075   }
1076 
1077   return false;
1078 }
1079 
IsBoolScalarOrVectorType(uint32_t id) const1080 bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
1081   const Instruction* inst = FindDef(id);
1082   if (!inst) {
1083     return false;
1084   }
1085 
1086   if (inst->opcode() == spv::Op::OpTypeBool) {
1087     return true;
1088   }
1089 
1090   if (inst->opcode() == spv::Op::OpTypeVector) {
1091     return IsBoolScalarType(GetComponentType(id));
1092   }
1093 
1094   return false;
1095 }
1096 
IsFloatMatrixType(uint32_t id) const1097 bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
1098   const Instruction* inst = FindDef(id);
1099   if (!inst) {
1100     return false;
1101   }
1102 
1103   if (inst->opcode() == spv::Op::OpTypeMatrix) {
1104     return IsFloatScalarType(GetComponentType(id));
1105   }
1106 
1107   return false;
1108 }
1109 
GetMatrixTypeInfo(uint32_t id,uint32_t * num_rows,uint32_t * num_cols,uint32_t * column_type,uint32_t * component_type) const1110 bool ValidationState_t::GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows,
1111                                           uint32_t* num_cols,
1112                                           uint32_t* column_type,
1113                                           uint32_t* component_type) const {
1114   if (!id) return false;
1115 
1116   const Instruction* mat_inst = FindDef(id);
1117   assert(mat_inst);
1118   if (mat_inst->opcode() != spv::Op::OpTypeMatrix) return false;
1119 
1120   const uint32_t vec_type = mat_inst->word(2);
1121   const Instruction* vec_inst = FindDef(vec_type);
1122   assert(vec_inst);
1123 
1124   if (vec_inst->opcode() != spv::Op::OpTypeVector) {
1125     assert(0);
1126     return false;
1127   }
1128 
1129   *num_cols = mat_inst->word(3);
1130   *num_rows = vec_inst->word(3);
1131   *column_type = mat_inst->word(2);
1132   *component_type = vec_inst->word(2);
1133 
1134   return true;
1135 }
1136 
GetStructMemberTypes(uint32_t struct_type_id,std::vector<uint32_t> * member_types) const1137 bool ValidationState_t::GetStructMemberTypes(
1138     uint32_t struct_type_id, std::vector<uint32_t>* member_types) const {
1139   member_types->clear();
1140   if (!struct_type_id) return false;
1141 
1142   const Instruction* inst = FindDef(struct_type_id);
1143   assert(inst);
1144   if (inst->opcode() != spv::Op::OpTypeStruct) return false;
1145 
1146   *member_types =
1147       std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
1148 
1149   if (member_types->empty()) return false;
1150 
1151   return true;
1152 }
1153 
IsPointerType(uint32_t id) const1154 bool ValidationState_t::IsPointerType(uint32_t id) const {
1155   const Instruction* inst = FindDef(id);
1156   return inst && inst->opcode() == spv::Op::OpTypePointer;
1157 }
1158 
GetPointerTypeInfo(uint32_t id,uint32_t * data_type,spv::StorageClass * storage_class) const1159 bool ValidationState_t::GetPointerTypeInfo(
1160     uint32_t id, uint32_t* data_type, spv::StorageClass* storage_class) const {
1161   *storage_class = spv::StorageClass::Max;
1162   if (!id) return false;
1163 
1164   const Instruction* inst = FindDef(id);
1165   assert(inst);
1166   if (inst->opcode() != spv::Op::OpTypePointer) return false;
1167 
1168   *storage_class = spv::StorageClass(inst->word(2));
1169   *data_type = inst->word(3);
1170   return true;
1171 }
1172 
IsAccelerationStructureType(uint32_t id) const1173 bool ValidationState_t::IsAccelerationStructureType(uint32_t id) const {
1174   const Instruction* inst = FindDef(id);
1175   return inst && inst->opcode() == spv::Op::OpTypeAccelerationStructureKHR;
1176 }
1177 
IsCooperativeMatrixType(uint32_t id) const1178 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
1179   const Instruction* inst = FindDef(id);
1180   return inst && (inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV ||
1181                   inst->opcode() == spv::Op::OpTypeCooperativeMatrixKHR);
1182 }
1183 
IsCooperativeMatrixNVType(uint32_t id) const1184 bool ValidationState_t::IsCooperativeMatrixNVType(uint32_t id) const {
1185   const Instruction* inst = FindDef(id);
1186   return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV;
1187 }
1188 
IsCooperativeMatrixKHRType(uint32_t id) const1189 bool ValidationState_t::IsCooperativeMatrixKHRType(uint32_t id) const {
1190   const Instruction* inst = FindDef(id);
1191   return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixKHR;
1192 }
1193 
IsCooperativeMatrixAType(uint32_t id) const1194 bool ValidationState_t::IsCooperativeMatrixAType(uint32_t id) const {
1195   if (!IsCooperativeMatrixKHRType(id)) return false;
1196   const Instruction* inst = FindDef(id);
1197   uint64_t matrixUse = 0;
1198   if (GetConstantValUint64(inst->word(6), &matrixUse)) {
1199     return matrixUse ==
1200            static_cast<uint64_t>(spv::CooperativeMatrixUse::MatrixAKHR);
1201   }
1202   return false;
1203 }
1204 
IsCooperativeMatrixBType(uint32_t id) const1205 bool ValidationState_t::IsCooperativeMatrixBType(uint32_t id) const {
1206   if (!IsCooperativeMatrixKHRType(id)) return false;
1207   const Instruction* inst = FindDef(id);
1208   uint64_t matrixUse = 0;
1209   if (GetConstantValUint64(inst->word(6), &matrixUse)) {
1210     return matrixUse ==
1211            static_cast<uint64_t>(spv::CooperativeMatrixUse::MatrixBKHR);
1212   }
1213   return false;
1214 }
IsCooperativeMatrixAccType(uint32_t id) const1215 bool ValidationState_t::IsCooperativeMatrixAccType(uint32_t id) const {
1216   if (!IsCooperativeMatrixKHRType(id)) return false;
1217   const Instruction* inst = FindDef(id);
1218   uint64_t matrixUse = 0;
1219   if (GetConstantValUint64(inst->word(6), &matrixUse)) {
1220     return matrixUse == static_cast<uint64_t>(
1221                             spv::CooperativeMatrixUse::MatrixAccumulatorKHR);
1222   }
1223   return false;
1224 }
1225 
IsFloatCooperativeMatrixType(uint32_t id) const1226 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
1227   if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1228     return false;
1229   return IsFloatScalarType(FindDef(id)->word(2));
1230 }
1231 
IsIntCooperativeMatrixType(uint32_t id) const1232 bool ValidationState_t::IsIntCooperativeMatrixType(uint32_t id) const {
1233   if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1234     return false;
1235   return IsIntScalarType(FindDef(id)->word(2));
1236 }
1237 
IsUnsignedIntCooperativeMatrixType(uint32_t id) const1238 bool ValidationState_t::IsUnsignedIntCooperativeMatrixType(uint32_t id) const {
1239   if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1240     return false;
1241   return IsUnsignedIntScalarType(FindDef(id)->word(2));
1242 }
1243 
1244 // Either a 32 bit 2-component uint vector or a 64 bit uint scalar
IsUnsigned64BitHandle(uint32_t id) const1245 bool ValidationState_t::IsUnsigned64BitHandle(uint32_t id) const {
1246   return ((IsUnsignedIntScalarType(id) && GetBitWidth(id) == 64) ||
1247           (IsUnsignedIntVectorType(id) && GetDimension(id) == 2 &&
1248            GetBitWidth(id) == 32));
1249 }
1250 
CooperativeMatrixShapesMatch(const Instruction * inst,uint32_t m1,uint32_t m2)1251 spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
1252     const Instruction* inst, uint32_t m1, uint32_t m2) {
1253   const auto m1_type = FindDef(m1);
1254   const auto m2_type = FindDef(m2);
1255 
1256   if (m1_type->opcode() != m2_type->opcode()) {
1257     return diag(SPV_ERROR_INVALID_DATA, inst)
1258            << "Expected cooperative matrix types";
1259   }
1260 
1261   uint32_t m1_scope_id = m1_type->GetOperandAs<uint32_t>(2);
1262   uint32_t m1_rows_id = m1_type->GetOperandAs<uint32_t>(3);
1263   uint32_t m1_cols_id = m1_type->GetOperandAs<uint32_t>(4);
1264 
1265   uint32_t m2_scope_id = m2_type->GetOperandAs<uint32_t>(2);
1266   uint32_t m2_rows_id = m2_type->GetOperandAs<uint32_t>(3);
1267   uint32_t m2_cols_id = m2_type->GetOperandAs<uint32_t>(4);
1268 
1269   bool m1_is_int32 = false, m1_is_const_int32 = false, m2_is_int32 = false,
1270        m2_is_const_int32 = false;
1271   uint32_t m1_value = 0, m2_value = 0;
1272 
1273   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1274       EvalInt32IfConst(m1_scope_id);
1275   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1276       EvalInt32IfConst(m2_scope_id);
1277 
1278   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1279     return diag(SPV_ERROR_INVALID_DATA, inst)
1280            << "Expected scopes of Matrix and Result Type to be "
1281            << "identical";
1282   }
1283 
1284   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1285       EvalInt32IfConst(m1_rows_id);
1286   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1287       EvalInt32IfConst(m2_rows_id);
1288 
1289   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1290     return diag(SPV_ERROR_INVALID_DATA, inst)
1291            << "Expected rows of Matrix type and Result Type to be "
1292            << "identical";
1293   }
1294 
1295   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1296       EvalInt32IfConst(m1_cols_id);
1297   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1298       EvalInt32IfConst(m2_cols_id);
1299 
1300   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1301     return diag(SPV_ERROR_INVALID_DATA, inst)
1302            << "Expected columns of Matrix type and Result Type to be "
1303            << "identical";
1304   }
1305 
1306   if (m1_type->opcode() == spv::Op::OpTypeCooperativeMatrixKHR) {
1307     uint32_t m1_use_id = m1_type->GetOperandAs<uint32_t>(5);
1308     uint32_t m2_use_id = m2_type->GetOperandAs<uint32_t>(5);
1309     std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1310         EvalInt32IfConst(m1_use_id);
1311     std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1312         EvalInt32IfConst(m2_use_id);
1313 
1314     if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1315       return diag(SPV_ERROR_INVALID_DATA, inst)
1316              << "Expected Use of Matrix type and Result Type to be "
1317              << "identical";
1318     }
1319   }
1320 
1321   return SPV_SUCCESS;
1322 }
1323 
GetOperandTypeId(const Instruction * inst,size_t operand_index) const1324 uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst,
1325                                              size_t operand_index) const {
1326   return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index));
1327 }
1328 
GetConstantValUint64(uint32_t id,uint64_t * val) const1329 bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const {
1330   const Instruction* inst = FindDef(id);
1331   if (!inst) {
1332     assert(0 && "Instruction not found");
1333     return false;
1334   }
1335 
1336   if (inst->opcode() != spv::Op::OpConstant &&
1337       inst->opcode() != spv::Op::OpSpecConstant)
1338     return false;
1339 
1340   if (!IsIntScalarType(inst->type_id())) return false;
1341 
1342   if (inst->words().size() == 4) {
1343     *val = inst->word(3);
1344   } else {
1345     assert(inst->words().size() == 5);
1346     *val = inst->word(3);
1347     *val |= uint64_t(inst->word(4)) << 32;
1348   }
1349   return true;
1350 }
1351 
EvalInt32IfConst(uint32_t id) const1352 std::tuple<bool, bool, uint32_t> ValidationState_t::EvalInt32IfConst(
1353     uint32_t id) const {
1354   const Instruction* const inst = FindDef(id);
1355   assert(inst);
1356   const uint32_t type = inst->type_id();
1357 
1358   if (type == 0 || !IsIntScalarType(type) || GetBitWidth(type) != 32) {
1359     return std::make_tuple(false, false, 0);
1360   }
1361 
1362   // Spec constant values cannot be evaluated so don't consider constant for
1363   // the purpose of this method.
1364   if (!spvOpcodeIsConstant(inst->opcode()) ||
1365       spvOpcodeIsSpecConstant(inst->opcode())) {
1366     return std::make_tuple(true, false, 0);
1367   }
1368 
1369   if (inst->opcode() == spv::Op::OpConstantNull) {
1370     return std::make_tuple(true, true, 0);
1371   }
1372 
1373   assert(inst->words().size() == 4);
1374   return std::make_tuple(true, true, inst->word(3));
1375 }
1376 
ComputeFunctionToEntryPointMapping()1377 void ValidationState_t::ComputeFunctionToEntryPointMapping() {
1378   for (const uint32_t entry_point : entry_points()) {
1379     std::stack<uint32_t> call_stack;
1380     std::set<uint32_t> visited;
1381     call_stack.push(entry_point);
1382     while (!call_stack.empty()) {
1383       const uint32_t called_func_id = call_stack.top();
1384       call_stack.pop();
1385       if (!visited.insert(called_func_id).second) continue;
1386 
1387       function_to_entry_points_[called_func_id].push_back(entry_point);
1388 
1389       const Function* called_func = function(called_func_id);
1390       if (called_func) {
1391         // Other checks should error out on this invalid SPIR-V.
1392         for (const uint32_t new_call : called_func->function_call_targets()) {
1393           call_stack.push(new_call);
1394         }
1395       }
1396     }
1397   }
1398 }
1399 
ComputeRecursiveEntryPoints()1400 void ValidationState_t::ComputeRecursiveEntryPoints() {
1401   for (const Function& func : functions()) {
1402     std::stack<uint32_t> call_stack;
1403     std::set<uint32_t> visited;
1404 
1405     for (const uint32_t new_call : func.function_call_targets()) {
1406       call_stack.push(new_call);
1407     }
1408 
1409     while (!call_stack.empty()) {
1410       const uint32_t called_func_id = call_stack.top();
1411       call_stack.pop();
1412 
1413       if (!visited.insert(called_func_id).second) continue;
1414 
1415       if (called_func_id == func.id()) {
1416         for (const uint32_t entry_point :
1417              function_to_entry_points_[called_func_id])
1418           recursive_entry_points_.insert(entry_point);
1419         break;
1420       }
1421 
1422       const Function* called_func = function(called_func_id);
1423       if (called_func) {
1424         // Other checks should error out on this invalid SPIR-V.
1425         for (const uint32_t new_call : called_func->function_call_targets()) {
1426           call_stack.push(new_call);
1427         }
1428       }
1429     }
1430   }
1431 }
1432 
FunctionEntryPoints(uint32_t func) const1433 const std::vector<uint32_t>& ValidationState_t::FunctionEntryPoints(
1434     uint32_t func) const {
1435   auto iter = function_to_entry_points_.find(func);
1436   if (iter == function_to_entry_points_.end()) {
1437     return empty_ids_;
1438   } else {
1439     return iter->second;
1440   }
1441 }
1442 
EntryPointReferences(uint32_t id) const1443 std::set<uint32_t> ValidationState_t::EntryPointReferences(uint32_t id) const {
1444   std::set<uint32_t> referenced_entry_points;
1445   const auto inst = FindDef(id);
1446   if (!inst) return referenced_entry_points;
1447 
1448   std::vector<const Instruction*> stack;
1449   stack.push_back(inst);
1450   while (!stack.empty()) {
1451     const auto current_inst = stack.back();
1452     stack.pop_back();
1453 
1454     if (const auto func = current_inst->function()) {
1455       // Instruction lives in a function, we can stop searching.
1456       const auto function_entry_points = FunctionEntryPoints(func->id());
1457       referenced_entry_points.insert(function_entry_points.begin(),
1458                                      function_entry_points.end());
1459     } else {
1460       // Instruction is in the global scope, keep searching its uses.
1461       for (auto pair : current_inst->uses()) {
1462         const auto next_inst = pair.first;
1463         stack.push_back(next_inst);
1464       }
1465     }
1466   }
1467 
1468   return referenced_entry_points;
1469 }
1470 
Disassemble(const Instruction & inst) const1471 std::string ValidationState_t::Disassemble(const Instruction& inst) const {
1472   const spv_parsed_instruction_t& c_inst(inst.c_inst());
1473   return Disassemble(c_inst.words, c_inst.num_words);
1474 }
1475 
Disassemble(const uint32_t * words,uint16_t num_words) const1476 std::string ValidationState_t::Disassemble(const uint32_t* words,
1477                                            uint16_t num_words) const {
1478   uint32_t disassembly_options = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1479                                  SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
1480 
1481   return spvInstructionBinaryToText(context()->target_env, words, num_words,
1482                                     words_, num_words_, disassembly_options);
1483 }
1484 
LogicallyMatch(const Instruction * lhs,const Instruction * rhs,bool check_decorations)1485 bool ValidationState_t::LogicallyMatch(const Instruction* lhs,
1486                                        const Instruction* rhs,
1487                                        bool check_decorations) {
1488   if (lhs->opcode() != rhs->opcode()) {
1489     return false;
1490   }
1491 
1492   if (check_decorations) {
1493     const auto& dec_a = id_decorations(lhs->id());
1494     const auto& dec_b = id_decorations(rhs->id());
1495 
1496     for (const auto& dec : dec_b) {
1497       if (std::find(dec_a.begin(), dec_a.end(), dec) == dec_a.end()) {
1498         return false;
1499       }
1500     }
1501   }
1502 
1503   if (lhs->opcode() == spv::Op::OpTypeArray) {
1504     // Size operands must match.
1505     if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
1506       return false;
1507     }
1508 
1509     // Elements must match or logically match.
1510     const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(1u);
1511     const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(1u);
1512     if (lhs_ele_id == rhs_ele_id) {
1513       return true;
1514     }
1515 
1516     const auto lhs_ele = FindDef(lhs_ele_id);
1517     const auto rhs_ele = FindDef(rhs_ele_id);
1518     if (!lhs_ele || !rhs_ele) {
1519       return false;
1520     }
1521     return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
1522   } else if (lhs->opcode() == spv::Op::OpTypeStruct) {
1523     // Number of elements must match.
1524     if (lhs->operands().size() != rhs->operands().size()) {
1525       return false;
1526     }
1527 
1528     for (size_t i = 1u; i < lhs->operands().size(); ++i) {
1529       const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(i);
1530       const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(i);
1531       // Elements must match or logically match.
1532       if (lhs_ele_id == rhs_ele_id) {
1533         continue;
1534       }
1535 
1536       const auto lhs_ele = FindDef(lhs_ele_id);
1537       const auto rhs_ele = FindDef(rhs_ele_id);
1538       if (!lhs_ele || !rhs_ele) {
1539         return false;
1540       }
1541 
1542       if (!LogicallyMatch(lhs_ele, rhs_ele, check_decorations)) {
1543         return false;
1544       }
1545     }
1546 
1547     // All checks passed.
1548     return true;
1549   }
1550 
1551   // No other opcodes are acceptable at this point. Arrays and structs are
1552   // caught above and if they're elements are not arrays or structs they are
1553   // required to match exactly.
1554   return false;
1555 }
1556 
TracePointer(const Instruction * inst) const1557 const Instruction* ValidationState_t::TracePointer(
1558     const Instruction* inst) const {
1559   auto base_ptr = inst;
1560   while (base_ptr->opcode() == spv::Op::OpAccessChain ||
1561          base_ptr->opcode() == spv::Op::OpInBoundsAccessChain ||
1562          base_ptr->opcode() == spv::Op::OpPtrAccessChain ||
1563          base_ptr->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
1564          base_ptr->opcode() == spv::Op::OpCopyObject) {
1565     base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
1566   }
1567   return base_ptr;
1568 }
1569 
ContainsType(uint32_t id,const std::function<bool (const Instruction *)> & f,bool traverse_all_types) const1570 bool ValidationState_t::ContainsType(
1571     uint32_t id, const std::function<bool(const Instruction*)>& f,
1572     bool traverse_all_types) const {
1573   const auto inst = FindDef(id);
1574   if (!inst) return false;
1575 
1576   if (f(inst)) return true;
1577 
1578   switch (inst->opcode()) {
1579     case spv::Op::OpTypeArray:
1580     case spv::Op::OpTypeRuntimeArray:
1581     case spv::Op::OpTypeVector:
1582     case spv::Op::OpTypeMatrix:
1583     case spv::Op::OpTypeImage:
1584     case spv::Op::OpTypeSampledImage:
1585     case spv::Op::OpTypeCooperativeMatrixNV:
1586     case spv::Op::OpTypeCooperativeMatrixKHR:
1587       return ContainsType(inst->GetOperandAs<uint32_t>(1u), f,
1588                           traverse_all_types);
1589     case spv::Op::OpTypePointer:
1590       if (IsForwardPointer(id)) return false;
1591       if (traverse_all_types) {
1592         return ContainsType(inst->GetOperandAs<uint32_t>(2u), f,
1593                             traverse_all_types);
1594       }
1595       break;
1596     case spv::Op::OpTypeFunction:
1597     case spv::Op::OpTypeStruct:
1598       if (inst->opcode() == spv::Op::OpTypeFunction && !traverse_all_types) {
1599         return false;
1600       }
1601       for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1602         if (ContainsType(inst->GetOperandAs<uint32_t>(i), f,
1603                          traverse_all_types)) {
1604           return true;
1605         }
1606       }
1607       break;
1608     default:
1609       break;
1610   }
1611 
1612   return false;
1613 }
1614 
ContainsSizedIntOrFloatType(uint32_t id,spv::Op type,uint32_t width) const1615 bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
1616                                                     uint32_t width) const {
1617   if (type != spv::Op::OpTypeInt && type != spv::Op::OpTypeFloat) return false;
1618 
1619   const auto f = [type, width](const Instruction* inst) {
1620     if (inst->opcode() == type) {
1621       return inst->GetOperandAs<uint32_t>(1u) == width;
1622     }
1623     return false;
1624   };
1625   return ContainsType(id, f);
1626 }
1627 
ContainsLimitedUseIntOrFloatType(uint32_t id) const1628 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
1629   if ((!HasCapability(spv::Capability::Int16) &&
1630        ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 16)) ||
1631       (!HasCapability(spv::Capability::Int8) &&
1632        ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 8)) ||
1633       (!HasCapability(spv::Capability::Float16) &&
1634        ContainsSizedIntOrFloatType(id, spv::Op::OpTypeFloat, 16))) {
1635     return true;
1636   }
1637   return false;
1638 }
1639 
ContainsRuntimeArray(uint32_t id) const1640 bool ValidationState_t::ContainsRuntimeArray(uint32_t id) const {
1641   const auto f = [](const Instruction* inst) {
1642     return inst->opcode() == spv::Op::OpTypeRuntimeArray;
1643   };
1644   return ContainsType(id, f, /* traverse_all_types = */ false);
1645 }
1646 
IsValidStorageClass(spv::StorageClass storage_class) const1647 bool ValidationState_t::IsValidStorageClass(
1648     spv::StorageClass storage_class) const {
1649   if (spvIsVulkanEnv(context()->target_env)) {
1650     switch (storage_class) {
1651       case spv::StorageClass::UniformConstant:
1652       case spv::StorageClass::Uniform:
1653       case spv::StorageClass::StorageBuffer:
1654       case spv::StorageClass::Input:
1655       case spv::StorageClass::Output:
1656       case spv::StorageClass::Image:
1657       case spv::StorageClass::Workgroup:
1658       case spv::StorageClass::Private:
1659       case spv::StorageClass::Function:
1660       case spv::StorageClass::PushConstant:
1661       case spv::StorageClass::PhysicalStorageBuffer:
1662       case spv::StorageClass::RayPayloadKHR:
1663       case spv::StorageClass::IncomingRayPayloadKHR:
1664       case spv::StorageClass::HitAttributeKHR:
1665       case spv::StorageClass::CallableDataKHR:
1666       case spv::StorageClass::IncomingCallableDataKHR:
1667       case spv::StorageClass::ShaderRecordBufferKHR:
1668       case spv::StorageClass::TaskPayloadWorkgroupEXT:
1669       case spv::StorageClass::HitObjectAttributeNV:
1670       case spv::StorageClass::TileImageEXT:
1671         return true;
1672       default:
1673         return false;
1674     }
1675   }
1676 
1677   return true;
1678 }
1679 
1680 #define VUID_WRAP(vuid) "[" #vuid "] "
1681 
1682 // Currently no 2 VUID share the same id, so no need for |reference|
VkErrorID(uint32_t id,const char *) const1683 std::string ValidationState_t::VkErrorID(uint32_t id,
1684                                          const char* /*reference*/) const {
1685   if (!spvIsVulkanEnv(context_->target_env)) {
1686     return "";
1687   }
1688 
1689   // This large switch case is only searched when an error has occurred.
1690   // If an id is changed, the old case must be modified or removed. Each string
1691   // here is interpreted as being "implemented"
1692 
1693   // Clang format adds spaces between hyphens
1694   // clang-format off
1695   switch (id) {
1696     case 4154:
1697       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04154);
1698     case 4155:
1699       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04155);
1700     case 4156:
1701       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04156);
1702     case 4160:
1703       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04160);
1704     case 4161:
1705       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04161);
1706     case 4162:
1707       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04162);
1708     case 4181:
1709       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04181);
1710     case 4182:
1711       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04182);
1712     case 4183:
1713       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04183);
1714     case 4184:
1715       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04184);
1716     case 4185:
1717       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04185);
1718     case 4186:
1719       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04186);
1720     case 4187:
1721       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
1722     case 4188:
1723       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04188);
1724     case 4189:
1725       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04189);
1726     case 4190:
1727       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04190);
1728     case 4191:
1729       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
1730     case 4196:
1731       return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
1732     case 4197:
1733       return VUID_WRAP(VUID-CullDistance-CullDistance-04197);
1734     case 4198:
1735       return VUID_WRAP(VUID-CullDistance-CullDistance-04198);
1736     case 4199:
1737       return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
1738     case 4200:
1739       return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
1740     case 6735:
1741       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06735); // Execution Model
1742     case 6736:
1743       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06736); // input storage
1744     case 6737:
1745       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06737); // 32 int scalar
1746     case 4205:
1747       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04205);
1748     case 4206:
1749       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04206);
1750     case 4207:
1751       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04207);
1752     case 4208:
1753       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04208);
1754     case 4209:
1755       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04209);
1756     case 4210:
1757       return VUID_WRAP(VUID-FragCoord-FragCoord-04210);
1758     case 4211:
1759       return VUID_WRAP(VUID-FragCoord-FragCoord-04211);
1760     case 4212:
1761       return VUID_WRAP(VUID-FragCoord-FragCoord-04212);
1762     case 4213:
1763       return VUID_WRAP(VUID-FragDepth-FragDepth-04213);
1764     case 4214:
1765       return VUID_WRAP(VUID-FragDepth-FragDepth-04214);
1766     case 4215:
1767       return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
1768     case 4216:
1769       return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
1770     case 4217:
1771       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
1772     case 4218:
1773       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
1774     case 4219:
1775       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
1776     case 4220:
1777       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
1778     case 4221:
1779       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
1780     case 4222:
1781       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
1782     case 4223:
1783       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
1784     case 4224:
1785       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
1786     case 4225:
1787       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
1788     case 4229:
1789       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
1790     case 4230:
1791       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
1792     case 4231:
1793       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
1794     case 4232:
1795       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
1796     case 4233:
1797       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
1798     case 4234:
1799       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
1800     case 4236:
1801       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
1802     case 4237:
1803       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04237);
1804     case 4238:
1805       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04238);
1806     case 4239:
1807       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04239);
1808     case 4240:
1809       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
1810     case 4241:
1811       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
1812     case 4242:
1813       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04242);
1814     case 4243:
1815       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04243);
1816     case 4244:
1817       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04244);
1818     case 4245:
1819       return VUID_WRAP(VUID-HitTNV-HitTNV-04245);
1820     case 4246:
1821       return VUID_WRAP(VUID-HitTNV-HitTNV-04246);
1822     case 4247:
1823       return VUID_WRAP(VUID-HitTNV-HitTNV-04247);
1824     case 4248:
1825       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248);
1826     case 4249:
1827       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249);
1828     case 4250:
1829       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250);
1830     case 4251:
1831       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251);
1832     case 4252:
1833       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252);
1834     case 4253:
1835       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253);
1836     case 4254:
1837       return VUID_WRAP(VUID-InstanceId-InstanceId-04254);
1838     case 4255:
1839       return VUID_WRAP(VUID-InstanceId-InstanceId-04255);
1840     case 4256:
1841       return VUID_WRAP(VUID-InstanceId-InstanceId-04256);
1842     case 4257:
1843       return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
1844     case 4258:
1845       return VUID_WRAP(VUID-InvocationId-InvocationId-04258);
1846     case 4259:
1847       return VUID_WRAP(VUID-InvocationId-InvocationId-04259);
1848     case 4263:
1849       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04263);
1850     case 4264:
1851       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
1852     case 4265:
1853       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
1854     case 4266:
1855       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04266);
1856     case 4267:
1857       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04267);
1858     case 4268:
1859       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04268);
1860     case 4269:
1861       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04269);
1862     case 4270:
1863       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04270);
1864     case 4271:
1865       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04271);
1866     case 4272:
1867       return VUID_WRAP(VUID-Layer-Layer-04272);
1868     case 4273:
1869       return VUID_WRAP(VUID-Layer-Layer-04273);
1870     case 4274:
1871       return VUID_WRAP(VUID-Layer-Layer-04274);
1872     case 4275:
1873       return VUID_WRAP(VUID-Layer-Layer-04275);
1874     case 4276:
1875       return VUID_WRAP(VUID-Layer-Layer-04276);
1876     case 4281:
1877       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04281);
1878     case 4282:
1879       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
1880     case 4283:
1881       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
1882     case 4293:
1883       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
1884     case 4294:
1885       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
1886     case 4295:
1887       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
1888     case 4296:
1889       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
1890     case 4297:
1891       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04297);
1892     case 4298:
1893       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04298);
1894     case 4299:
1895       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299);
1896     case 4300:
1897       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300);
1898     case 4301:
1899       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301);
1900     case 4302:
1901       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302);
1902     case 4303:
1903       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303);
1904     case 4304:
1905       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304);
1906     case 4305:
1907       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305);
1908     case 4306:
1909       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306);
1910     case 4307:
1911       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307);
1912     case 4308:
1913       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
1914     case 4309:
1915       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04309);
1916     case 4310:
1917       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04310);
1918     case 4311:
1919       return VUID_WRAP(VUID-PointCoord-PointCoord-04311);
1920     case 4312:
1921       return VUID_WRAP(VUID-PointCoord-PointCoord-04312);
1922     case 4313:
1923       return VUID_WRAP(VUID-PointCoord-PointCoord-04313);
1924     case 4314:
1925       return VUID_WRAP(VUID-PointSize-PointSize-04314);
1926     case 4315:
1927       return VUID_WRAP(VUID-PointSize-PointSize-04315);
1928     case 4316:
1929       return VUID_WRAP(VUID-PointSize-PointSize-04316);
1930     case 4317:
1931       return VUID_WRAP(VUID-PointSize-PointSize-04317);
1932     case 4318:
1933       return VUID_WRAP(VUID-Position-Position-04318);
1934     case 4319:
1935       return VUID_WRAP(VUID-Position-Position-04319);
1936     case 4320:
1937       return VUID_WRAP(VUID-Position-Position-04320);
1938     case 4321:
1939       return VUID_WRAP(VUID-Position-Position-04321);
1940     case 4330:
1941       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
1942     case 4334:
1943       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
1944     case 4337:
1945       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
1946     case 4345:
1947       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345);
1948     case 4346:
1949       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346);
1950     case 4347:
1951       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347);
1952     case 4348:
1953       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04348);
1954     case 4349:
1955       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04349);
1956     case 4350:
1957       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04350);
1958     case 4351:
1959       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04351);
1960     case 4352:
1961       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04352);
1962     case 4353:
1963       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04353);
1964     case 4354:
1965       return VUID_WRAP(VUID-SampleId-SampleId-04354);
1966     case 4355:
1967       return VUID_WRAP(VUID-SampleId-SampleId-04355);
1968     case 4356:
1969       return VUID_WRAP(VUID-SampleId-SampleId-04356);
1970     case 4357:
1971       return VUID_WRAP(VUID-SampleMask-SampleMask-04357);
1972     case 4358:
1973       return VUID_WRAP(VUID-SampleMask-SampleMask-04358);
1974     case 4359:
1975       return VUID_WRAP(VUID-SampleMask-SampleMask-04359);
1976     case 4360:
1977       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04360);
1978     case 4361:
1979       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
1980     case 4362:
1981       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
1982     case 4367:
1983       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
1984     case 4368:
1985       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
1986     case 4369:
1987       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
1988     case 4370:
1989       return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
1990     case 4371:
1991       return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
1992     case 4372:
1993       return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
1994     case 4373:
1995       return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
1996     case 4374:
1997       return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
1998     case 4375:
1999       return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
2000     case 4376:
2001       return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
2002     case 4377:
2003       return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
2004     case 4378:
2005       return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
2006     case 4379:
2007       return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
2008     case 4380:
2009       return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
2010     case 4381:
2011       return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
2012     case 4382:
2013       return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
2014     case 4383:
2015       return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
2016     case 4387:
2017       return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
2018     case 4388:
2019       return VUID_WRAP(VUID-TessCoord-TessCoord-04388);
2020     case 4389:
2021       return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
2022     case 4390:
2023       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
2024     case 4391:
2025       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04391);
2026     case 4392:
2027       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04392);
2028     case 4393:
2029       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
2030     case 4394:
2031       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
2032     case 4395:
2033       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04395);
2034     case 4396:
2035       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04396);
2036     case 4397:
2037       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
2038     case 4398:
2039       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04398);
2040     case 4399:
2041       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04399);
2042     case 4400:
2043       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04400);
2044     case 4401:
2045       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04401);
2046     case 4402:
2047       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04402);
2048     case 4403:
2049       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
2050     case 4404:
2051       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
2052     case 4405:
2053       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04405);
2054     case 4406:
2055       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
2056     case 4407:
2057       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407);
2058     case 4408:
2059       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
2060     case 4422:
2061       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04422);
2062     case 4423:
2063       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04423);
2064     case 4424:
2065       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04424);
2066     case 4425:
2067       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04425);
2068     case 4426:
2069       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
2070     case 4427:
2071       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
2072     case 4428:
2073       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428);
2074     case 4429:
2075       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429);
2076     case 4430:
2077       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430);
2078     case 4431:
2079       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431);
2080     case 4432:
2081       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432);
2082     case 4433:
2083       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433);
2084     case 4434:
2085       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04434);
2086     case 4435:
2087       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04435);
2088     case 4436:
2089       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04436);
2090     case 4484:
2091       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
2092     case 4485:
2093       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485);
2094     case 4486:
2095       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486);
2096     case 4490:
2097       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490);
2098     case 4491:
2099       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
2100     case 4492:
2101       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
2102     case 4633:
2103       return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
2104     case 4634:
2105       return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
2106     case 4635:
2107       return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
2108     case 4636:
2109       return VUID_WRAP(VUID-StandaloneSpirv-None-04636);
2110     case 4637:
2111       return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
2112     case 4638:
2113       return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
2114     case 7321:
2115       return VUID_WRAP(VUID-StandaloneSpirv-None-07321);
2116     case 4640:
2117       return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
2118     case 4641:
2119       return VUID_WRAP(VUID-StandaloneSpirv-None-04641);
2120     case 4642:
2121       return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
2122     case 4643:
2123       return VUID_WRAP(VUID-StandaloneSpirv-None-04643);
2124     case 4644:
2125       return VUID_WRAP(VUID-StandaloneSpirv-None-04644);
2126     case 4645:
2127       return VUID_WRAP(VUID-StandaloneSpirv-None-04645);
2128     case 4651:
2129       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
2130     case 4652:
2131       return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
2132     case 4653:
2133       return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
2134     case 4654:
2135       return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
2136     case 4655:
2137       return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-04655);
2138     case 4656:
2139       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
2140     case 4657:
2141       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
2142     case 4658:
2143       return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
2144     case 4659:
2145       return VUID_WRAP(VUID-StandaloneSpirv-OpImageQuerySizeLod-04659);
2146     case 4663:
2147       return VUID_WRAP(VUID-StandaloneSpirv-Offset-04663);
2148     case 4664:
2149       return VUID_WRAP(VUID-StandaloneSpirv-OpImageGather-04664);
2150     case 4667:
2151       return VUID_WRAP(VUID-StandaloneSpirv-None-04667);
2152     case 4669:
2153       return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
2154     case 4670:
2155       return VUID_WRAP(VUID-StandaloneSpirv-Flat-04670);
2156     case 4675:
2157       return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
2158     case 4677:
2159       return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
2160     case 4680:
2161       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeRuntimeArray-04680);
2162     case 4682:
2163       return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
2164     case 6426:
2165       return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-06426); // formally 04683
2166     case 4685:
2167       return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
2168     case 4686:
2169       return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
2170     case 4698:
2171       return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698);
2172     case 4699:
2173       return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699);
2174     case 4701:
2175       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701);
2176     case 4703:
2177       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703);
2178     case 4704:
2179       return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704);
2180     case 4705:
2181       return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705);
2182     case 7119:
2183       return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119);
2184     case 4708:
2185       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708);
2186     case 4710:
2187       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710);
2188     case 4711:
2189       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
2190     case 4730:
2191       return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicStore-04730);
2192     case 4731:
2193       return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicLoad-04731);
2194     case 4732:
2195       return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04732);
2196     case 4733:
2197       return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
2198     case 4734:
2199       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04734);
2200     case 4744:
2201       return VUID_WRAP(VUID-StandaloneSpirv-Flat-04744);
2202     case 4777:
2203       return VUID_WRAP(VUID-StandaloneSpirv-OpImage-04777);
2204     case 4780:
2205       return VUID_WRAP(VUID-StandaloneSpirv-Result-04780);
2206     case 4781:
2207       return VUID_WRAP(VUID-StandaloneSpirv-Base-04781);
2208     case 4915:
2209       return VUID_WRAP(VUID-StandaloneSpirv-Location-04915);
2210     case 4916:
2211       return VUID_WRAP(VUID-StandaloneSpirv-Location-04916);
2212     case 4917:
2213       return VUID_WRAP(VUID-StandaloneSpirv-Location-04917);
2214     case 4918:
2215       return VUID_WRAP(VUID-StandaloneSpirv-Location-04918);
2216     case 4919:
2217       return VUID_WRAP(VUID-StandaloneSpirv-Location-04919);
2218     case 4920:
2219       return VUID_WRAP(VUID-StandaloneSpirv-Component-04920);
2220     case 4921:
2221       return VUID_WRAP(VUID-StandaloneSpirv-Component-04921);
2222     case 4922:
2223       return VUID_WRAP(VUID-StandaloneSpirv-Component-04922);
2224     case 4923:
2225       return VUID_WRAP(VUID-StandaloneSpirv-Component-04923);
2226     case 4924:
2227       return VUID_WRAP(VUID-StandaloneSpirv-Component-04924);
2228     case 6201:
2229       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06201);
2230     case 6202:
2231       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06202);
2232     case 6214:
2233       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-06214);
2234     case 6491:
2235       return VUID_WRAP(VUID-StandaloneSpirv-DescriptorSet-06491);
2236     case 6671:
2237       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeSampledImage-06671);
2238     case 6672:
2239       return VUID_WRAP(VUID-StandaloneSpirv-Location-06672);
2240     case 6674:
2241       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-06674);
2242     case 6675:
2243       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06675);
2244     case 6676:
2245       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06676);
2246     case 6677:
2247       return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-06677);
2248     case 6678:
2249       return VUID_WRAP(VUID-StandaloneSpirv-InputAttachmentIndex-06678);
2250     case 6777:
2251       return VUID_WRAP(VUID-StandaloneSpirv-PerVertexKHR-06777);
2252     case 6778:
2253       return VUID_WRAP(VUID-StandaloneSpirv-Input-06778);
2254     case 6807:
2255       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06807);
2256     case 6808:
2257       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
2258     case 6925:
2259       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
2260     case 7102:
2261       return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
2262     case 7320:
2263       return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
2264     case 7290:
2265       return VUID_WRAP(VUID-StandaloneSpirv-Input-07290);
2266     case 7650:
2267       return VUID_WRAP(VUID-StandaloneSpirv-Base-07650);
2268     case 7651:
2269       return VUID_WRAP(VUID-StandaloneSpirv-Base-07651);
2270     case 7652:
2271       return VUID_WRAP(VUID-StandaloneSpirv-Base-07652);
2272     case 7703:
2273       return VUID_WRAP(VUID-StandaloneSpirv-Component-07703);
2274     case 7951:
2275       return VUID_WRAP(VUID-StandaloneSpirv-SubgroupVoteKHR-07951);
2276     case 8721:
2277       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08721);
2278     case 8722:
2279       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08722);
2280     case 8973:
2281       return VUID_WRAP(VUID-StandaloneSpirv-Pointer-08973);
2282     default:
2283       return "";  // unknown id
2284   }
2285   // clang-format on
2286 }
2287 
2288 }  // namespace val
2289 }  // namespace spvtools
2290