Add validation for SPV_NV_linear_swept_spheres. (#5975)
[KhronosGroup/SPIRV-Tools.git] / source / val / validation_state.cpp
blob4604d6da5183478f0833b70fc2fdfda191696c03
1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 // Modifications Copyright (C) 2024 Advanced Micro Devices, Inc. All rights
3 // reserved.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 #include "source/val/validation_state.h"
19 #include <cassert>
20 #include <stack>
21 #include <utility>
23 #include "source/opcode.h"
24 #include "source/spirv_constant.h"
25 #include "source/spirv_target_env.h"
26 #include "source/util/make_unique.h"
27 #include "source/val/basic_block.h"
28 #include "source/val/construct.h"
29 #include "source/val/function.h"
30 #include "spirv-tools/libspirv.h"
32 namespace spvtools {
33 namespace val {
34 namespace {
36 ModuleLayoutSection InstructionLayoutSection(
37 ModuleLayoutSection current_section, spv::Op op) {
38 // See Section 2.4
39 if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op))
40 return kLayoutTypes;
42 switch (op) {
43 case spv::Op::OpCapability:
44 return kLayoutCapabilities;
45 case spv::Op::OpExtension:
46 return kLayoutExtensions;
47 case spv::Op::OpExtInstImport:
48 return kLayoutExtInstImport;
49 case spv::Op::OpMemoryModel:
50 return kLayoutMemoryModel;
51 case spv::Op::OpEntryPoint:
52 return kLayoutEntryPoint;
53 case spv::Op::OpExecutionMode:
54 case spv::Op::OpExecutionModeId:
55 return kLayoutExecutionMode;
56 case spv::Op::OpSourceContinued:
57 case spv::Op::OpSource:
58 case spv::Op::OpSourceExtension:
59 case spv::Op::OpString:
60 return kLayoutDebug1;
61 case spv::Op::OpName:
62 case spv::Op::OpMemberName:
63 return kLayoutDebug2;
64 case spv::Op::OpModuleProcessed:
65 return kLayoutDebug3;
66 case spv::Op::OpDecorate:
67 case spv::Op::OpMemberDecorate:
68 case spv::Op::OpGroupDecorate:
69 case spv::Op::OpGroupMemberDecorate:
70 case spv::Op::OpDecorationGroup:
71 case spv::Op::OpDecorateId:
72 case spv::Op::OpDecorateStringGOOGLE:
73 case spv::Op::OpMemberDecorateStringGOOGLE:
74 return kLayoutAnnotations;
75 case spv::Op::OpTypeForwardPointer:
76 return kLayoutTypes;
77 case spv::Op::OpVariable:
78 case spv::Op::OpUntypedVariableKHR:
79 if (current_section == kLayoutTypes) return kLayoutTypes;
80 return kLayoutFunctionDefinitions;
81 case spv::Op::OpExtInst:
82 case spv::Op::OpExtInstWithForwardRefsKHR:
83 // spv::Op::OpExtInst is only allowed in types section for certain
84 // extended instruction sets. This will be checked separately.
85 if (current_section == kLayoutTypes) return kLayoutTypes;
86 return kLayoutFunctionDefinitions;
87 case spv::Op::OpLine:
88 case spv::Op::OpNoLine:
89 case spv::Op::OpUndef:
90 if (current_section == kLayoutTypes) return kLayoutTypes;
91 return kLayoutFunctionDefinitions;
92 case spv::Op::OpFunction:
93 case spv::Op::OpFunctionParameter:
94 case spv::Op::OpFunctionEnd:
95 if (current_section == kLayoutFunctionDeclarations)
96 return kLayoutFunctionDeclarations;
97 return kLayoutFunctionDefinitions;
98 case spv::Op::OpSamplerImageAddressingModeNV:
99 return kLayoutSamplerImageAddressMode;
100 default:
101 break;
103 return kLayoutFunctionDefinitions;
106 bool IsInstructionInLayoutSection(ModuleLayoutSection layout, spv::Op op) {
107 return layout == InstructionLayoutSection(layout, op);
110 // Counts the number of instructions and functions in the file.
111 spv_result_t CountInstructions(void* user_data,
112 const spv_parsed_instruction_t* inst) {
113 ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
114 if (spv::Op(inst->opcode) == spv::Op::OpFunction) {
115 _.increment_total_functions();
117 _.increment_total_instructions();
119 return SPV_SUCCESS;
122 spv_result_t setHeader(void* user_data, spv_endianness_t, uint32_t,
123 uint32_t version, uint32_t generator, uint32_t id_bound,
124 uint32_t) {
125 ValidationState_t& vstate =
126 *(reinterpret_cast<ValidationState_t*>(user_data));
127 vstate.setIdBound(id_bound);
128 vstate.setGenerator(generator);
129 vstate.setVersion(version);
131 return SPV_SUCCESS;
134 // Add features based on SPIR-V core version number.
135 void UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature* features,
136 uint32_t version) {
137 assert(features);
138 if (version >= SPV_SPIRV_VERSION_WORD(1, 4)) {
139 features->select_between_composites = true;
140 features->copy_memory_permits_two_memory_accesses = true;
141 features->uconvert_spec_constant_op = true;
142 features->nonwritable_var_in_function_or_private = true;
146 } // namespace
148 ValidationState_t::ValidationState_t(const spv_const_context ctx,
149 const spv_const_validator_options opt,
150 const uint32_t* words,
151 const size_t num_words,
152 const uint32_t max_warnings)
153 : context_(ctx),
154 options_(opt),
155 words_(words),
156 num_words_(num_words),
157 unresolved_forward_ids_{},
158 operand_names_{},
159 current_layout_section_(kLayoutCapabilities),
160 module_functions_(),
161 module_capabilities_(),
162 module_extensions_(),
163 ordered_instructions_(),
164 all_definitions_(),
165 global_vars_(),
166 local_vars_(),
167 struct_nesting_depth_(),
168 struct_has_nested_blockorbufferblock_struct_(),
169 grammar_(ctx),
170 addressing_model_(spv::AddressingModel::Max),
171 memory_model_(spv::MemoryModel::Max),
172 pointer_size_and_alignment_(0),
173 sampler_image_addressing_mode_(0),
174 in_function_(false),
175 num_of_warnings_(0),
176 max_num_of_warnings_(max_warnings) {
177 assert(opt && "Validator options may not be Null.");
179 const auto env = context_->target_env;
181 if (spvIsVulkanEnv(env)) {
182 // Vulkan 1.1 includes VK_KHR_relaxed_block_layout in core.
183 if (env != SPV_ENV_VULKAN_1_0) {
184 features_.env_relaxed_block_layout = true;
188 // LocalSizeId is only disallowed prior to Vulkan 1.3 without maintenance4.
189 switch (env) {
190 case SPV_ENV_VULKAN_1_0:
191 case SPV_ENV_VULKAN_1_1:
192 case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
193 case SPV_ENV_VULKAN_1_2:
194 features_.env_allow_localsizeid = false;
195 break;
196 default:
197 features_.env_allow_localsizeid = true;
198 break;
201 // Only attempt to count if we have words, otherwise let the other validation
202 // fail and generate an error.
203 if (num_words > 0) {
204 // Count the number of instructions in the binary.
205 // This parse should not produce any error messages. Hijack the context and
206 // replace the message consumer so that we do not pollute any state in input
207 // consumer.
208 spv_context_t hijacked_context = *ctx;
209 hijacked_context.consumer = [](spv_message_level_t, const char*,
210 const spv_position_t&, const char*) {};
211 spvBinaryParse(&hijacked_context, this, words, num_words, setHeader,
212 CountInstructions,
213 /* diagnostic = */ nullptr);
214 preallocateStorage();
216 UpdateFeaturesBasedOnSpirvVersion(&features_, version_);
218 name_mapper_ = spvtools::GetTrivialNameMapper();
219 if (options_->use_friendly_names) {
220 friendly_mapper_ = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
221 context_, words_, num_words_);
222 name_mapper_ = friendly_mapper_->GetNameMapper();
226 void ValidationState_t::preallocateStorage() {
227 ordered_instructions_.reserve(total_instructions_);
228 module_functions_.reserve(total_functions_);
231 spv_result_t ValidationState_t::ForwardDeclareId(uint32_t id) {
232 unresolved_forward_ids_.insert(id);
233 return SPV_SUCCESS;
236 spv_result_t ValidationState_t::RemoveIfForwardDeclared(uint32_t id) {
237 unresolved_forward_ids_.erase(id);
238 return SPV_SUCCESS;
241 spv_result_t ValidationState_t::RegisterForwardPointer(uint32_t id) {
242 forward_pointer_ids_.insert(id);
243 return SPV_SUCCESS;
246 bool ValidationState_t::IsForwardPointer(uint32_t id) const {
247 return (forward_pointer_ids_.find(id) != forward_pointer_ids_.end());
250 void ValidationState_t::AssignNameToId(uint32_t id, std::string name) {
251 operand_names_[id] = name;
254 std::string ValidationState_t::getIdName(uint32_t id) const {
255 const std::string id_name = name_mapper_(id);
257 std::stringstream out;
258 out << "'" << id << "[%" << id_name << "]'";
259 return out.str();
262 size_t ValidationState_t::unresolved_forward_id_count() const {
263 return unresolved_forward_ids_.size();
266 std::vector<uint32_t> ValidationState_t::UnresolvedForwardIds() const {
267 std::vector<uint32_t> out(std::begin(unresolved_forward_ids_),
268 std::end(unresolved_forward_ids_));
269 return out;
272 bool ValidationState_t::IsDefinedId(uint32_t id) const {
273 return all_definitions_.find(id) != std::end(all_definitions_);
276 const Instruction* ValidationState_t::FindDef(uint32_t id) const {
277 auto it = all_definitions_.find(id);
278 if (it == all_definitions_.end()) return nullptr;
279 return it->second;
282 Instruction* ValidationState_t::FindDef(uint32_t id) {
283 auto it = all_definitions_.find(id);
284 if (it == all_definitions_.end()) return nullptr;
285 return it->second;
288 ModuleLayoutSection ValidationState_t::current_layout_section() const {
289 return current_layout_section_;
292 void ValidationState_t::ProgressToNextLayoutSectionOrder() {
293 // Guard against going past the last element(kLayoutFunctionDefinitions)
294 if (current_layout_section_ <= kLayoutFunctionDefinitions) {
295 current_layout_section_ =
296 static_cast<ModuleLayoutSection>(current_layout_section_ + 1);
300 bool ValidationState_t::IsOpcodeInPreviousLayoutSection(spv::Op op) {
301 ModuleLayoutSection section =
302 InstructionLayoutSection(current_layout_section_, op);
303 return section < current_layout_section_;
306 bool ValidationState_t::IsOpcodeInCurrentLayoutSection(spv::Op op) {
307 return IsInstructionInLayoutSection(current_layout_section_, op);
310 DiagnosticStream ValidationState_t::diag(spv_result_t error_code,
311 const Instruction* inst) {
312 if (error_code == SPV_WARNING) {
313 if (num_of_warnings_ == max_num_of_warnings_) {
314 DiagnosticStream({0, 0, 0}, context_->consumer, "", error_code)
315 << "Other warnings have been suppressed.\n";
317 if (num_of_warnings_ >= max_num_of_warnings_) {
318 return DiagnosticStream({0, 0, 0}, nullptr, "", error_code);
320 ++num_of_warnings_;
323 std::string disassembly;
324 if (inst) disassembly = Disassemble(*inst);
326 return DiagnosticStream({0, 0, inst ? inst->LineNum() : 0},
327 context_->consumer, disassembly, error_code);
330 std::vector<Function>& ValidationState_t::functions() {
331 return module_functions_;
334 Function& ValidationState_t::current_function() {
335 assert(in_function_body());
336 return module_functions_.back();
339 const Function& ValidationState_t::current_function() const {
340 assert(in_function_body());
341 return module_functions_.back();
344 const Function* ValidationState_t::function(uint32_t id) const {
345 const auto it = id_to_function_.find(id);
346 if (it == id_to_function_.end()) return nullptr;
347 return it->second;
350 Function* ValidationState_t::function(uint32_t id) {
351 auto it = id_to_function_.find(id);
352 if (it == id_to_function_.end()) return nullptr;
353 return it->second;
356 bool ValidationState_t::in_function_body() const { return in_function_; }
358 bool ValidationState_t::in_block() const {
359 return module_functions_.empty() == false &&
360 module_functions_.back().current_block() != nullptr;
363 void ValidationState_t::RegisterCapability(spv::Capability cap) {
364 // Avoid redundant work. Otherwise the recursion could induce work
365 // quadrdatic in the capability dependency depth. (Ok, not much, but
366 // it's something.)
367 if (module_capabilities_.contains(cap)) return;
369 module_capabilities_.insert(cap);
370 spv_operand_desc desc;
371 if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
372 uint32_t(cap), &desc)) {
373 for (auto capability :
374 CapabilitySet(desc->numCapabilities, desc->capabilities)) {
375 RegisterCapability(capability);
379 switch (cap) {
380 case spv::Capability::Kernel:
381 features_.group_ops_reduce_and_scans = true;
382 break;
383 case spv::Capability::Int8:
384 features_.use_int8_type = true;
385 features_.declare_int8_type = true;
386 break;
387 case spv::Capability::StorageBuffer8BitAccess:
388 case spv::Capability::UniformAndStorageBuffer8BitAccess:
389 case spv::Capability::StoragePushConstant8:
390 case spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR:
391 features_.declare_int8_type = true;
392 break;
393 case spv::Capability::Int16:
394 features_.declare_int16_type = true;
395 break;
396 case spv::Capability::Float16:
397 case spv::Capability::Float16Buffer:
398 features_.declare_float16_type = true;
399 break;
400 case spv::Capability::StorageUniformBufferBlock16:
401 case spv::Capability::StorageUniform16:
402 case spv::Capability::StoragePushConstant16:
403 case spv::Capability::StorageInputOutput16:
404 case spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR:
405 features_.declare_int16_type = true;
406 features_.declare_float16_type = true;
407 features_.free_fp_rounding_mode = true;
408 break;
409 case spv::Capability::VariablePointers:
410 case spv::Capability::VariablePointersStorageBuffer:
411 features_.variable_pointers = true;
412 break;
413 default:
414 // TODO(dneto): For now don't validate SPV_NV_ray_tracing, which uses
415 // capability spv::Capability::RayTracingNV.
416 // spv::Capability::RayTracingProvisionalKHR would need the same
417 // treatment. One of the differences going from SPV_KHR_ray_tracing from
418 // provisional to final spec was the provisional spec uses Locations
419 // for variables in certain storage classes, just like the
420 // SPV_NV_ray_tracing extension. So it mimics the NVIDIA extension.
421 // The final SPV_KHR_ray_tracing uses a different capability token
422 // number, so it doesn't fall into this case.
423 break;
427 void ValidationState_t::RegisterExtension(Extension ext) {
428 if (module_extensions_.contains(ext)) return;
430 module_extensions_.insert(ext);
432 switch (ext) {
433 case kSPV_AMD_gpu_shader_half_float:
434 case kSPV_AMD_gpu_shader_half_float_fetch:
435 // SPV_AMD_gpu_shader_half_float enables float16 type.
436 // https://github.com/KhronosGroup/SPIRV-Tools/issues/1375
437 features_.declare_float16_type = true;
438 break;
439 case kSPV_AMD_gpu_shader_int16:
440 // This is not yet in the extension, but it's recommended for it.
441 // See https://github.com/KhronosGroup/glslang/issues/848
442 features_.uconvert_spec_constant_op = true;
443 break;
444 case kSPV_AMD_shader_ballot:
445 // The grammar doesn't encode the fact that SPV_AMD_shader_ballot
446 // enables the use of group operations Reduce, InclusiveScan,
447 // and ExclusiveScan. Enable it manually.
448 // https://github.com/KhronosGroup/SPIRV-Tools/issues/991
449 features_.group_ops_reduce_and_scans = true;
450 break;
451 default:
452 break;
456 bool ValidationState_t::HasAnyOfCapabilities(
457 const CapabilitySet& capabilities) const {
458 return module_capabilities_.HasAnyOf(capabilities);
461 bool ValidationState_t::HasAnyOfExtensions(
462 const ExtensionSet& extensions) const {
463 return module_extensions_.HasAnyOf(extensions);
466 void ValidationState_t::set_addressing_model(spv::AddressingModel am) {
467 addressing_model_ = am;
468 switch (am) {
469 case spv::AddressingModel::Physical32:
470 pointer_size_and_alignment_ = 4;
471 break;
472 default:
473 // fall through
474 case spv::AddressingModel::Physical64:
475 case spv::AddressingModel::PhysicalStorageBuffer64:
476 pointer_size_and_alignment_ = 8;
477 break;
481 spv::AddressingModel ValidationState_t::addressing_model() const {
482 return addressing_model_;
485 void ValidationState_t::set_memory_model(spv::MemoryModel mm) {
486 memory_model_ = mm;
489 spv::MemoryModel ValidationState_t::memory_model() const {
490 return memory_model_;
493 void ValidationState_t::set_samplerimage_variable_address_mode(
494 uint32_t bit_width) {
495 sampler_image_addressing_mode_ = bit_width;
498 uint32_t ValidationState_t::samplerimage_variable_address_mode() const {
499 return sampler_image_addressing_mode_;
502 spv_result_t ValidationState_t::RegisterFunction(
503 uint32_t id, uint32_t ret_type_id,
504 spv::FunctionControlMask function_control, uint32_t function_type_id) {
505 assert(in_function_body() == false &&
506 "RegisterFunction can only be called when parsing the binary outside "
507 "of another function");
508 in_function_ = true;
509 module_functions_.emplace_back(id, ret_type_id, function_control,
510 function_type_id);
511 id_to_function_.emplace(id, &current_function());
513 // TODO(umar): validate function type and type_id
515 return SPV_SUCCESS;
518 spv_result_t ValidationState_t::RegisterFunctionEnd() {
519 assert(in_function_body() == true &&
520 "RegisterFunctionEnd can only be called when parsing the binary "
521 "inside of another function");
522 assert(in_block() == false &&
523 "RegisterFunctionParameter can only be called when parsing the binary "
524 "outside of a block");
525 current_function().RegisterFunctionEnd();
526 in_function_ = false;
527 return SPV_SUCCESS;
530 Instruction* ValidationState_t::AddOrderedInstruction(
531 const spv_parsed_instruction_t* inst) {
532 ordered_instructions_.emplace_back(inst);
533 ordered_instructions_.back().SetLineNum(ordered_instructions_.size());
534 return &ordered_instructions_.back();
537 // Improves diagnostic messages by collecting names of IDs
538 void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
539 switch (inst->opcode()) {
540 case spv::Op::OpName: {
541 const auto target = inst->GetOperandAs<uint32_t>(0);
542 const std::string str = inst->GetOperandAs<std::string>(1);
543 AssignNameToId(target, str);
544 break;
546 case spv::Op::OpMemberName: {
547 const auto target = inst->GetOperandAs<uint32_t>(0);
548 const std::string str = inst->GetOperandAs<std::string>(2);
549 AssignNameToId(target, str);
550 break;
552 case spv::Op::OpSourceContinued:
553 case spv::Op::OpSource:
554 case spv::Op::OpSourceExtension:
555 case spv::Op::OpString:
556 case spv::Op::OpLine:
557 case spv::Op::OpNoLine:
558 default:
559 break;
563 void ValidationState_t::RegisterInstruction(Instruction* inst) {
564 if (inst->id()) all_definitions_.insert(std::make_pair(inst->id(), inst));
566 // Some validation checks are easier by getting all the consumers
567 for (size_t i = 0; i < inst->operands().size(); ++i) {
568 const spv_parsed_operand_t& operand = inst->operand(i);
569 if ((SPV_OPERAND_TYPE_ID == operand.type) ||
570 (SPV_OPERAND_TYPE_TYPE_ID == operand.type)) {
571 const uint32_t operand_word = inst->word(operand.offset);
572 Instruction* operand_inst = FindDef(operand_word);
573 if (!operand_inst) {
574 continue;
577 // If the instruction is using an OpTypeSampledImage as an operand, it
578 // should be recorded. The validator will ensure that all usages of an
579 // OpTypeSampledImage and its definition are in the same basic block.
580 if ((SPV_OPERAND_TYPE_ID == operand.type) &&
581 (spv::Op::OpSampledImage == operand_inst->opcode())) {
582 RegisterSampledImageConsumer(operand_word, inst);
585 // In order to track storage classes (not Function) used per execution
586 // model we can't use RegisterExecutionModelLimitation on instructions
587 // like OpTypePointer which are going to be in the pre-function section.
588 // Instead just need to register storage class usage for consumers in a
589 // function block.
590 if (inst->function()) {
591 if (operand_inst->opcode() == spv::Op::OpTypePointer) {
592 RegisterStorageClassConsumer(
593 operand_inst->GetOperandAs<spv::StorageClass>(1), inst);
594 } else if (operand_inst->opcode() == spv::Op::OpVariable) {
595 RegisterStorageClassConsumer(
596 operand_inst->GetOperandAs<spv::StorageClass>(2), inst);
603 std::vector<Instruction*> ValidationState_t::getSampledImageConsumers(
604 uint32_t sampled_image_id) const {
605 std::vector<Instruction*> result;
606 auto iter = sampled_image_consumers_.find(sampled_image_id);
607 if (iter != sampled_image_consumers_.end()) {
608 result = iter->second;
610 return result;
613 void ValidationState_t::RegisterSampledImageConsumer(uint32_t sampled_image_id,
614 Instruction* consumer) {
615 sampled_image_consumers_[sampled_image_id].push_back(consumer);
618 void ValidationState_t::RegisterQCOMImageProcessingTextureConsumer(
619 uint32_t texture_id, const Instruction* consumer0,
620 const Instruction* consumer1) {
621 if (HasDecoration(texture_id, spv::Decoration::WeightTextureQCOM) ||
622 HasDecoration(texture_id, spv::Decoration::BlockMatchTextureQCOM) ||
623 HasDecoration(texture_id, spv::Decoration::BlockMatchSamplerQCOM)) {
624 qcom_image_processing_consumers_.insert(consumer0->id());
625 if (consumer1) {
626 qcom_image_processing_consumers_.insert(consumer1->id());
631 void ValidationState_t::RegisterStorageClassConsumer(
632 spv::StorageClass storage_class, Instruction* consumer) {
633 if (spvIsVulkanEnv(context()->target_env)) {
634 if (storage_class == spv::StorageClass::Output) {
635 std::string errorVUID = VkErrorID(4644);
636 function(consumer->function()->id())
637 ->RegisterExecutionModelLimitation([errorVUID](
638 spv::ExecutionModel model,
639 std::string* message) {
640 if (model == spv::ExecutionModel::GLCompute ||
641 model == spv::ExecutionModel::RayGenerationKHR ||
642 model == spv::ExecutionModel::IntersectionKHR ||
643 model == spv::ExecutionModel::AnyHitKHR ||
644 model == spv::ExecutionModel::ClosestHitKHR ||
645 model == spv::ExecutionModel::MissKHR ||
646 model == spv::ExecutionModel::CallableKHR) {
647 if (message) {
648 *message =
649 errorVUID +
650 "in Vulkan environment, Output Storage Class must not be "
651 "used in GLCompute, RayGenerationKHR, IntersectionKHR, "
652 "AnyHitKHR, ClosestHitKHR, MissKHR, or CallableKHR "
653 "execution models";
655 return false;
657 return true;
661 if (storage_class == spv::StorageClass::Workgroup) {
662 std::string errorVUID = VkErrorID(4645);
663 function(consumer->function()->id())
664 ->RegisterExecutionModelLimitation([errorVUID](
665 spv::ExecutionModel model,
666 std::string* message) {
667 if (model != spv::ExecutionModel::GLCompute &&
668 model != spv::ExecutionModel::TaskNV &&
669 model != spv::ExecutionModel::MeshNV &&
670 model != spv::ExecutionModel::TaskEXT &&
671 model != spv::ExecutionModel::MeshEXT) {
672 if (message) {
673 *message =
674 errorVUID +
675 "in Vulkan environment, Workgroup Storage Class is limited "
676 "to MeshNV, TaskNV, and GLCompute execution model";
678 return false;
680 return true;
685 if (storage_class == spv::StorageClass::CallableDataKHR) {
686 std::string errorVUID = VkErrorID(4704);
687 function(consumer->function()->id())
688 ->RegisterExecutionModelLimitation(
689 [errorVUID](spv::ExecutionModel model, std::string* message) {
690 if (model != spv::ExecutionModel::RayGenerationKHR &&
691 model != spv::ExecutionModel::ClosestHitKHR &&
692 model != spv::ExecutionModel::CallableKHR &&
693 model != spv::ExecutionModel::MissKHR) {
694 if (message) {
695 *message =
696 errorVUID +
697 "CallableDataKHR Storage Class is limited to "
698 "RayGenerationKHR, ClosestHitKHR, CallableKHR, and "
699 "MissKHR execution model";
701 return false;
703 return true;
705 } else if (storage_class == spv::StorageClass::IncomingCallableDataKHR) {
706 std::string errorVUID = VkErrorID(4705);
707 function(consumer->function()->id())
708 ->RegisterExecutionModelLimitation(
709 [errorVUID](spv::ExecutionModel model, std::string* message) {
710 if (model != spv::ExecutionModel::CallableKHR) {
711 if (message) {
712 *message =
713 errorVUID +
714 "IncomingCallableDataKHR Storage Class is limited to "
715 "CallableKHR execution model";
717 return false;
719 return true;
721 } else if (storage_class == spv::StorageClass::RayPayloadKHR) {
722 std::string errorVUID = VkErrorID(4698);
723 function(consumer->function()->id())
724 ->RegisterExecutionModelLimitation([errorVUID](
725 spv::ExecutionModel model,
726 std::string* message) {
727 if (model != spv::ExecutionModel::RayGenerationKHR &&
728 model != spv::ExecutionModel::ClosestHitKHR &&
729 model != spv::ExecutionModel::MissKHR) {
730 if (message) {
731 *message =
732 errorVUID +
733 "RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
734 "ClosestHitKHR, and MissKHR execution model";
736 return false;
738 return true;
740 } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
741 std::string errorVUID = VkErrorID(4701);
742 function(consumer->function()->id())
743 ->RegisterExecutionModelLimitation(
744 [errorVUID](spv::ExecutionModel model, std::string* message) {
745 if (model != spv::ExecutionModel::IntersectionKHR &&
746 model != spv::ExecutionModel::AnyHitKHR &&
747 model != spv::ExecutionModel::ClosestHitKHR) {
748 if (message) {
749 *message = errorVUID +
750 "HitAttributeKHR Storage Class is limited to "
751 "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR "
752 "execution model";
754 return false;
756 return true;
758 } else if (storage_class == spv::StorageClass::IncomingRayPayloadKHR) {
759 std::string errorVUID = VkErrorID(4699);
760 function(consumer->function()->id())
761 ->RegisterExecutionModelLimitation(
762 [errorVUID](spv::ExecutionModel model, std::string* message) {
763 if (model != spv::ExecutionModel::AnyHitKHR &&
764 model != spv::ExecutionModel::ClosestHitKHR &&
765 model != spv::ExecutionModel::MissKHR) {
766 if (message) {
767 *message =
768 errorVUID +
769 "IncomingRayPayloadKHR Storage Class is limited to "
770 "AnyHitKHR, ClosestHitKHR, and MissKHR execution model";
772 return false;
774 return true;
776 } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
777 std::string errorVUID = VkErrorID(7119);
778 function(consumer->function()->id())
779 ->RegisterExecutionModelLimitation(
780 [errorVUID](spv::ExecutionModel model, std::string* message) {
781 if (model != spv::ExecutionModel::RayGenerationKHR &&
782 model != spv::ExecutionModel::IntersectionKHR &&
783 model != spv::ExecutionModel::AnyHitKHR &&
784 model != spv::ExecutionModel::ClosestHitKHR &&
785 model != spv::ExecutionModel::CallableKHR &&
786 model != spv::ExecutionModel::MissKHR) {
787 if (message) {
788 *message =
789 errorVUID +
790 "ShaderRecordBufferKHR Storage Class is limited to "
791 "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
792 "ClosestHitKHR, CallableKHR, and MissKHR execution model";
794 return false;
796 return true;
798 } else if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
799 function(consumer->function()->id())
800 ->RegisterExecutionModelLimitation(
801 [](spv::ExecutionModel model, std::string* message) {
802 if (model != spv::ExecutionModel::TaskEXT &&
803 model != spv::ExecutionModel::MeshEXT) {
804 if (message) {
805 *message =
806 "TaskPayloadWorkgroupEXT Storage Class is limited to "
807 "TaskEXT and MeshKHR execution model";
809 return false;
811 return true;
813 } else if (storage_class == spv::StorageClass::HitObjectAttributeNV) {
814 function(consumer->function()->id())
815 ->RegisterExecutionModelLimitation([](spv::ExecutionModel model,
816 std::string* message) {
817 if (model != spv::ExecutionModel::RayGenerationKHR &&
818 model != spv::ExecutionModel::ClosestHitKHR &&
819 model != spv::ExecutionModel::MissKHR) {
820 if (message) {
821 *message =
822 "HitObjectAttributeNV Storage Class is limited to "
823 "RayGenerationKHR, ClosestHitKHR or MissKHR execution model";
825 return false;
827 return true;
832 uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
834 void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
836 bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) {
837 std::vector<uint32_t> key;
838 key.push_back(static_cast<uint32_t>(inst->opcode()));
839 for (size_t index = 0; index < inst->operands().size(); ++index) {
840 const spv_parsed_operand_t& operand = inst->operand(index);
842 if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue;
844 const int words_begin = operand.offset;
845 const int words_end = words_begin + operand.num_words;
846 assert(words_end <= static_cast<int>(inst->words().size()));
848 key.insert(key.end(), inst->words().begin() + words_begin,
849 inst->words().begin() + words_end);
852 return unique_type_declarations_.insert(std::move(key)).second;
855 uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
856 const Instruction* inst = FindDef(id);
857 return inst ? inst->type_id() : 0;
860 spv::Op ValidationState_t::GetIdOpcode(uint32_t id) const {
861 const Instruction* inst = FindDef(id);
862 return inst ? inst->opcode() : spv::Op::OpNop;
865 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
866 const Instruction* inst = FindDef(id);
867 assert(inst);
869 switch (inst->opcode()) {
870 case spv::Op::OpTypeFloat:
871 case spv::Op::OpTypeInt:
872 case spv::Op::OpTypeBool:
873 return id;
875 case spv::Op::OpTypeArray:
876 return inst->word(2);
878 case spv::Op::OpTypeVector:
879 return inst->word(2);
881 case spv::Op::OpTypeMatrix:
882 return GetComponentType(inst->word(2));
884 case spv::Op::OpTypeCooperativeMatrixNV:
885 case spv::Op::OpTypeCooperativeMatrixKHR:
886 case spv::Op::OpTypeCooperativeVectorNV:
887 return inst->word(2);
889 default:
890 break;
893 if (inst->type_id()) return GetComponentType(inst->type_id());
895 assert(0);
896 return 0;
899 uint32_t ValidationState_t::GetDimension(uint32_t id) const {
900 const Instruction* inst = FindDef(id);
901 assert(inst);
903 switch (inst->opcode()) {
904 case spv::Op::OpTypeFloat:
905 case spv::Op::OpTypeInt:
906 case spv::Op::OpTypeBool:
907 return 1;
909 case spv::Op::OpTypeVector:
910 case spv::Op::OpTypeMatrix:
911 return inst->word(3);
913 case spv::Op::OpTypeCooperativeMatrixNV:
914 case spv::Op::OpTypeCooperativeMatrixKHR:
915 case spv::Op::OpTypeCooperativeVectorNV:
916 // Actual dimension isn't known, return 0
917 return 0;
919 default:
920 break;
923 if (inst->type_id()) return GetDimension(inst->type_id());
925 assert(0);
926 return 0;
929 uint32_t ValidationState_t::GetBitWidth(uint32_t id) const {
930 const uint32_t component_type_id = GetComponentType(id);
931 const Instruction* inst = FindDef(component_type_id);
932 assert(inst);
934 if (inst->opcode() == spv::Op::OpTypeFloat ||
935 inst->opcode() == spv::Op::OpTypeInt)
936 return inst->word(2);
938 if (inst->opcode() == spv::Op::OpTypeBool) return 1;
940 assert(0);
941 return 0;
944 bool ValidationState_t::IsVoidType(uint32_t id) const {
945 const Instruction* inst = FindDef(id);
946 return inst && inst->opcode() == spv::Op::OpTypeVoid;
949 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
950 const Instruction* inst = FindDef(id);
951 return inst && inst->opcode() == spv::Op::OpTypeFloat;
954 bool ValidationState_t::IsFloatArrayType(uint32_t id) const {
955 const Instruction* inst = FindDef(id);
956 if (!inst) {
957 return false;
960 if (inst->opcode() == spv::Op::OpTypeArray) {
961 return IsFloatScalarType(GetComponentType(id));
964 return false;
967 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
968 const Instruction* inst = FindDef(id);
969 if (!inst) {
970 return false;
973 if (inst->opcode() == spv::Op::OpTypeVector) {
974 return IsFloatScalarType(GetComponentType(id));
977 return false;
980 bool ValidationState_t::IsFloat16Vector2Or4Type(uint32_t id) const {
981 const Instruction* inst = FindDef(id);
982 assert(inst);
984 if (inst->opcode() == spv::Op::OpTypeVector) {
985 uint32_t vectorDim = GetDimension(id);
986 return IsFloatScalarType(GetComponentType(id)) &&
987 (vectorDim == 2 || vectorDim == 4) &&
988 (GetBitWidth(GetComponentType(id)) == 16);
991 return false;
994 bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
995 const Instruction* inst = FindDef(id);
996 if (!inst) {
997 return false;
1000 if (inst->opcode() == spv::Op::OpTypeFloat) {
1001 return true;
1004 if (inst->opcode() == spv::Op::OpTypeVector) {
1005 return IsFloatScalarType(GetComponentType(id));
1008 return false;
1011 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
1012 const Instruction* inst = FindDef(id);
1013 return inst && inst->opcode() == spv::Op::OpTypeInt;
1016 bool ValidationState_t::IsIntArrayType(uint32_t id) const {
1017 const Instruction* inst = FindDef(id);
1018 if (!inst) {
1019 return false;
1022 if (inst->opcode() == spv::Op::OpTypeArray) {
1023 return IsIntScalarType(GetComponentType(id));
1026 return false;
1029 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
1030 const Instruction* inst = FindDef(id);
1031 if (!inst) {
1032 return false;
1035 if (inst->opcode() == spv::Op::OpTypeVector) {
1036 return IsIntScalarType(GetComponentType(id));
1039 return false;
1042 bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
1043 const Instruction* inst = FindDef(id);
1044 if (!inst) {
1045 return false;
1048 if (inst->opcode() == spv::Op::OpTypeInt) {
1049 return true;
1052 if (inst->opcode() == spv::Op::OpTypeVector) {
1053 return IsIntScalarType(GetComponentType(id));
1056 return false;
1059 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
1060 const Instruction* inst = FindDef(id);
1061 return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 0;
1064 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
1065 const Instruction* inst = FindDef(id);
1066 if (!inst) {
1067 return false;
1070 if (inst->opcode() == spv::Op::OpTypeVector) {
1071 return IsUnsignedIntScalarType(GetComponentType(id));
1074 return false;
1077 bool ValidationState_t::IsUnsignedIntScalarOrVectorType(uint32_t id) const {
1078 const Instruction* inst = FindDef(id);
1079 if (!inst) {
1080 return false;
1083 if (inst->opcode() == spv::Op::OpTypeInt) {
1084 return inst->GetOperandAs<uint32_t>(2) == 0;
1087 if (inst->opcode() == spv::Op::OpTypeVector) {
1088 return IsUnsignedIntScalarType(GetComponentType(id));
1091 return false;
1094 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
1095 const Instruction* inst = FindDef(id);
1096 return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 1;
1099 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
1100 const Instruction* inst = FindDef(id);
1101 if (!inst) {
1102 return false;
1105 if (inst->opcode() == spv::Op::OpTypeVector) {
1106 return IsSignedIntScalarType(GetComponentType(id));
1109 return false;
1112 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
1113 const Instruction* inst = FindDef(id);
1114 return inst && inst->opcode() == spv::Op::OpTypeBool;
1117 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
1118 const Instruction* inst = FindDef(id);
1119 if (!inst) {
1120 return false;
1123 if (inst->opcode() == spv::Op::OpTypeVector) {
1124 return IsBoolScalarType(GetComponentType(id));
1127 return false;
1130 bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
1131 const Instruction* inst = FindDef(id);
1132 if (!inst) {
1133 return false;
1136 if (inst->opcode() == spv::Op::OpTypeBool) {
1137 return true;
1140 if (inst->opcode() == spv::Op::OpTypeVector) {
1141 return IsBoolScalarType(GetComponentType(id));
1144 return false;
1147 bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
1148 const Instruction* inst = FindDef(id);
1149 if (!inst) {
1150 return false;
1153 if (inst->opcode() == spv::Op::OpTypeMatrix) {
1154 return IsFloatScalarType(GetComponentType(id));
1157 return false;
1160 bool ValidationState_t::GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows,
1161 uint32_t* num_cols,
1162 uint32_t* column_type,
1163 uint32_t* component_type) const {
1164 if (!id) return false;
1166 const Instruction* mat_inst = FindDef(id);
1167 assert(mat_inst);
1168 if (mat_inst->opcode() != spv::Op::OpTypeMatrix) return false;
1170 const uint32_t vec_type = mat_inst->word(2);
1171 const Instruction* vec_inst = FindDef(vec_type);
1172 assert(vec_inst);
1174 if (vec_inst->opcode() != spv::Op::OpTypeVector) {
1175 assert(0);
1176 return false;
1179 *num_cols = mat_inst->word(3);
1180 *num_rows = vec_inst->word(3);
1181 *column_type = mat_inst->word(2);
1182 *component_type = vec_inst->word(2);
1184 return true;
1187 bool ValidationState_t::GetStructMemberTypes(
1188 uint32_t struct_type_id, std::vector<uint32_t>* member_types) const {
1189 member_types->clear();
1190 if (!struct_type_id) return false;
1192 const Instruction* inst = FindDef(struct_type_id);
1193 assert(inst);
1194 if (inst->opcode() != spv::Op::OpTypeStruct) return false;
1196 *member_types =
1197 std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
1199 if (member_types->empty()) return false;
1201 return true;
1204 bool ValidationState_t::IsPointerType(uint32_t id) const {
1205 if (!id) return false;
1206 const Instruction* inst = FindDef(id);
1207 assert(inst);
1208 return inst->opcode() == spv::Op::OpTypePointer ||
1209 inst->opcode() == spv::Op::OpTypeUntypedPointerKHR;
1212 bool ValidationState_t::GetPointerTypeInfo(
1213 uint32_t id, uint32_t* data_type, spv::StorageClass* storage_class) const {
1214 *storage_class = spv::StorageClass::Max;
1215 if (!id) return false;
1217 const Instruction* inst = FindDef(id);
1218 assert(inst);
1219 if (inst->opcode() == spv::Op::OpTypeUntypedPointerKHR) {
1220 *storage_class = spv::StorageClass(inst->word(2));
1221 *data_type = 0;
1222 return true;
1225 if (inst->opcode() != spv::Op::OpTypePointer) return false;
1227 *storage_class = spv::StorageClass(inst->word(2));
1228 *data_type = inst->word(3);
1229 return true;
1232 bool ValidationState_t::IsAccelerationStructureType(uint32_t id) const {
1233 const Instruction* inst = FindDef(id);
1234 return inst && inst->opcode() == spv::Op::OpTypeAccelerationStructureKHR;
1237 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
1238 const Instruction* inst = FindDef(id);
1239 return inst && (inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV ||
1240 inst->opcode() == spv::Op::OpTypeCooperativeMatrixKHR);
1243 bool ValidationState_t::IsCooperativeMatrixNVType(uint32_t id) const {
1244 const Instruction* inst = FindDef(id);
1245 return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV;
1248 bool ValidationState_t::IsCooperativeMatrixKHRType(uint32_t id) const {
1249 const Instruction* inst = FindDef(id);
1250 return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixKHR;
1253 bool ValidationState_t::IsCooperativeMatrixAType(uint32_t id) const {
1254 if (!IsCooperativeMatrixKHRType(id)) return false;
1255 const Instruction* inst = FindDef(id);
1256 uint64_t matrixUse = 0;
1257 if (EvalConstantValUint64(inst->word(6), &matrixUse)) {
1258 return matrixUse ==
1259 static_cast<uint64_t>(spv::CooperativeMatrixUse::MatrixAKHR);
1261 return false;
1264 bool ValidationState_t::IsCooperativeMatrixBType(uint32_t id) const {
1265 if (!IsCooperativeMatrixKHRType(id)) return false;
1266 const Instruction* inst = FindDef(id);
1267 uint64_t matrixUse = 0;
1268 if (EvalConstantValUint64(inst->word(6), &matrixUse)) {
1269 return matrixUse ==
1270 static_cast<uint64_t>(spv::CooperativeMatrixUse::MatrixBKHR);
1272 return false;
1274 bool ValidationState_t::IsCooperativeMatrixAccType(uint32_t id) const {
1275 if (!IsCooperativeMatrixKHRType(id)) return false;
1276 const Instruction* inst = FindDef(id);
1277 uint64_t matrixUse = 0;
1278 if (EvalConstantValUint64(inst->word(6), &matrixUse)) {
1279 return matrixUse == static_cast<uint64_t>(
1280 spv::CooperativeMatrixUse::MatrixAccumulatorKHR);
1282 return false;
1285 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
1286 if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1287 return false;
1288 return IsFloatScalarType(FindDef(id)->word(2));
1291 bool ValidationState_t::IsIntCooperativeMatrixType(uint32_t id) const {
1292 if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1293 return false;
1294 return IsIntScalarType(FindDef(id)->word(2));
1297 bool ValidationState_t::IsUnsignedIntCooperativeMatrixType(uint32_t id) const {
1298 if (!IsCooperativeMatrixNVType(id) && !IsCooperativeMatrixKHRType(id))
1299 return false;
1300 return IsUnsignedIntScalarType(FindDef(id)->word(2));
1303 // Either a 32 bit 2-component uint vector or a 64 bit uint scalar
1304 bool ValidationState_t::IsUnsigned64BitHandle(uint32_t id) const {
1305 return ((IsUnsignedIntScalarType(id) && GetBitWidth(id) == 64) ||
1306 (IsUnsignedIntVectorType(id) && GetDimension(id) == 2 &&
1307 GetBitWidth(id) == 32));
1310 bool ValidationState_t::IsCooperativeVectorNVType(uint32_t id) const {
1311 const Instruction* inst = FindDef(id);
1312 return inst && inst->opcode() == spv::Op::OpTypeCooperativeVectorNV;
1315 bool ValidationState_t::IsFloatCooperativeVectorNVType(uint32_t id) const {
1316 if (!IsCooperativeVectorNVType(id)) return false;
1317 return IsFloatScalarType(FindDef(id)->word(2));
1320 bool ValidationState_t::IsIntCooperativeVectorNVType(uint32_t id) const {
1321 if (!IsCooperativeVectorNVType(id)) return false;
1322 return IsIntScalarType(FindDef(id)->word(2));
1325 bool ValidationState_t::IsUnsignedIntCooperativeVectorNVType(
1326 uint32_t id) const {
1327 if (!IsCooperativeVectorNVType(id)) return false;
1328 return IsUnsignedIntScalarType(FindDef(id)->word(2));
1331 spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
1332 const Instruction* inst, uint32_t result_type_id, uint32_t m2,
1333 bool is_conversion, bool swap_row_col) {
1334 const auto m1_type = FindDef(result_type_id);
1335 const auto m2_type = FindDef(m2);
1337 if (m1_type->opcode() != m2_type->opcode()) {
1338 return diag(SPV_ERROR_INVALID_DATA, inst)
1339 << "Expected cooperative matrix types";
1342 uint32_t m1_scope_id = m1_type->GetOperandAs<uint32_t>(2);
1343 uint32_t m1_rows_id = m1_type->GetOperandAs<uint32_t>(3);
1344 uint32_t m1_cols_id = m1_type->GetOperandAs<uint32_t>(4);
1346 uint32_t m2_scope_id = m2_type->GetOperandAs<uint32_t>(2);
1347 uint32_t m2_rows_id = m2_type->GetOperandAs<uint32_t>(3);
1348 uint32_t m2_cols_id = m2_type->GetOperandAs<uint32_t>(4);
1350 if (swap_row_col) {
1351 std::swap(m1_rows_id, m1_cols_id);
1354 bool m1_is_int32 = false, m1_is_const_int32 = false, m2_is_int32 = false,
1355 m2_is_const_int32 = false;
1356 uint32_t m1_value = 0, m2_value = 0;
1358 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1359 EvalInt32IfConst(m1_scope_id);
1360 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1361 EvalInt32IfConst(m2_scope_id);
1363 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1364 return diag(SPV_ERROR_INVALID_DATA, inst)
1365 << "Expected scopes of Matrix and Result Type to be "
1366 << "identical";
1369 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1370 EvalInt32IfConst(m1_rows_id);
1371 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1372 EvalInt32IfConst(m2_rows_id);
1374 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1375 return diag(SPV_ERROR_INVALID_DATA, inst)
1376 << "Expected rows of Matrix type and Result Type to be "
1377 << (swap_row_col ? "swapped with columns" : "identical");
1380 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1381 EvalInt32IfConst(m1_cols_id);
1382 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1383 EvalInt32IfConst(m2_cols_id);
1385 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1386 return diag(SPV_ERROR_INVALID_DATA, inst)
1387 << "Expected columns of Matrix type and Result Type to be "
1388 << (swap_row_col ? "swapped with rows" : "identical");
1391 if (m1_type->opcode() == spv::Op::OpTypeCooperativeMatrixKHR) {
1392 uint32_t m1_use_id = m1_type->GetOperandAs<uint32_t>(5);
1393 uint32_t m2_use_id = m2_type->GetOperandAs<uint32_t>(5);
1394 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1395 EvalInt32IfConst(m1_use_id);
1396 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1397 EvalInt32IfConst(m2_use_id);
1399 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value &&
1400 // CooperativeMatrixConversionsNV allows conversions from Acc->A/B
1401 !(is_conversion &&
1402 HasCapability(spv::Capability::CooperativeMatrixConversionsNV) &&
1403 m2_value ==
1404 (uint32_t)spv::CooperativeMatrixUse::MatrixAccumulatorKHR)) {
1405 return diag(SPV_ERROR_INVALID_DATA, inst)
1406 << "Expected Use of Matrix type and Result Type to be "
1407 << "identical";
1411 return SPV_SUCCESS;
1414 spv_result_t ValidationState_t::CooperativeVectorDimensionsMatch(
1415 const Instruction* inst, uint32_t v1, uint32_t v2) {
1416 const auto v1_type = FindDef(v1);
1417 const auto v2_type = FindDef(v2);
1419 if (v1_type->opcode() != v2_type->opcode()) {
1420 return diag(SPV_ERROR_INVALID_DATA, inst)
1421 << "Expected cooperative vector types";
1424 uint32_t v1_components_id = v1_type->GetOperandAs<uint32_t>(2);
1425 uint32_t v2_components_id = v2_type->GetOperandAs<uint32_t>(2);
1427 bool v1_is_int32 = false, v1_is_const_int32 = false, v2_is_int32 = false,
1428 v2_is_const_int32 = false;
1429 uint32_t v1_value = 0, v2_value = 0;
1431 std::tie(v1_is_int32, v1_is_const_int32, v1_value) =
1432 EvalInt32IfConst(v1_components_id);
1433 std::tie(v2_is_int32, v2_is_const_int32, v2_value) =
1434 EvalInt32IfConst(v2_components_id);
1436 if (v1_is_const_int32 && v2_is_const_int32 && v1_value != v2_value) {
1437 return diag(SPV_ERROR_INVALID_DATA, inst)
1438 << "Expected number of components to be identical";
1441 return SPV_SUCCESS;
1444 uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst,
1445 size_t operand_index) const {
1446 return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index));
1449 bool ValidationState_t::EvalConstantValUint64(uint32_t id,
1450 uint64_t* val) const {
1451 const Instruction* inst = FindDef(id);
1452 if (!inst) {
1453 assert(0 && "Instruction not found");
1454 return false;
1457 if (!IsIntScalarType(inst->type_id())) return false;
1459 if (inst->opcode() == spv::Op::OpConstantNull) {
1460 *val = 0;
1461 } else if (inst->opcode() != spv::Op::OpConstant) {
1462 // Spec constant values cannot be evaluated so don't consider constant for
1463 // static validation
1464 return false;
1465 } else if (inst->words().size() == 4) {
1466 *val = inst->word(3);
1467 } else {
1468 assert(inst->words().size() == 5);
1469 *val = inst->word(3);
1470 *val |= uint64_t(inst->word(4)) << 32;
1472 return true;
1475 bool ValidationState_t::EvalConstantValInt64(uint32_t id, int64_t* val) const {
1476 const Instruction* inst = FindDef(id);
1477 if (!inst) {
1478 assert(0 && "Instruction not found");
1479 return false;
1482 if (!IsIntScalarType(inst->type_id())) return false;
1484 if (inst->opcode() == spv::Op::OpConstantNull) {
1485 *val = 0;
1486 } else if (inst->opcode() != spv::Op::OpConstant) {
1487 // Spec constant values cannot be evaluated so don't consider constant for
1488 // static validation
1489 return false;
1490 } else if (inst->words().size() == 4) {
1491 *val = int32_t(inst->word(3));
1492 } else {
1493 assert(inst->words().size() == 5);
1494 const uint32_t lo_word = inst->word(3);
1495 const uint32_t hi_word = inst->word(4);
1496 *val = static_cast<int64_t>(uint64_t(lo_word) | uint64_t(hi_word) << 32);
1498 return true;
1501 std::tuple<bool, bool, uint32_t> ValidationState_t::EvalInt32IfConst(
1502 uint32_t id) const {
1503 const Instruction* const inst = FindDef(id);
1504 assert(inst);
1505 const uint32_t type = inst->type_id();
1507 if (type == 0 || !IsIntScalarType(type) || GetBitWidth(type) != 32) {
1508 return std::make_tuple(false, false, 0);
1511 // Spec constant values cannot be evaluated so don't consider constant for
1512 // the purpose of this method.
1513 if (!spvOpcodeIsConstant(inst->opcode()) ||
1514 spvOpcodeIsSpecConstant(inst->opcode())) {
1515 return std::make_tuple(true, false, 0);
1518 if (inst->opcode() == spv::Op::OpConstantNull) {
1519 return std::make_tuple(true, true, 0);
1522 assert(inst->words().size() == 4);
1523 return std::make_tuple(true, true, inst->word(3));
1526 void ValidationState_t::ComputeFunctionToEntryPointMapping() {
1527 for (const uint32_t entry_point : entry_points()) {
1528 std::stack<uint32_t> call_stack;
1529 std::set<uint32_t> visited;
1530 call_stack.push(entry_point);
1531 while (!call_stack.empty()) {
1532 const uint32_t called_func_id = call_stack.top();
1533 call_stack.pop();
1534 if (!visited.insert(called_func_id).second) continue;
1536 function_to_entry_points_[called_func_id].push_back(entry_point);
1538 const Function* called_func = function(called_func_id);
1539 if (called_func) {
1540 // Other checks should error out on this invalid SPIR-V.
1541 for (const uint32_t new_call : called_func->function_call_targets()) {
1542 call_stack.push(new_call);
1549 void ValidationState_t::ComputeRecursiveEntryPoints() {
1550 for (const Function& func : functions()) {
1551 std::stack<uint32_t> call_stack;
1552 std::set<uint32_t> visited;
1554 for (const uint32_t new_call : func.function_call_targets()) {
1555 call_stack.push(new_call);
1558 while (!call_stack.empty()) {
1559 const uint32_t called_func_id = call_stack.top();
1560 call_stack.pop();
1562 if (!visited.insert(called_func_id).second) continue;
1564 if (called_func_id == func.id()) {
1565 for (const uint32_t entry_point :
1566 function_to_entry_points_[called_func_id])
1567 recursive_entry_points_.insert(entry_point);
1568 break;
1571 const Function* called_func = function(called_func_id);
1572 if (called_func) {
1573 // Other checks should error out on this invalid SPIR-V.
1574 for (const uint32_t new_call : called_func->function_call_targets()) {
1575 call_stack.push(new_call);
1582 const std::vector<uint32_t>& ValidationState_t::FunctionEntryPoints(
1583 uint32_t func) const {
1584 auto iter = function_to_entry_points_.find(func);
1585 if (iter == function_to_entry_points_.end()) {
1586 return empty_ids_;
1587 } else {
1588 return iter->second;
1592 std::set<uint32_t> ValidationState_t::EntryPointReferences(uint32_t id) const {
1593 std::set<uint32_t> referenced_entry_points;
1594 const auto inst = FindDef(id);
1595 if (!inst) return referenced_entry_points;
1597 std::vector<const Instruction*> stack;
1598 stack.push_back(inst);
1599 while (!stack.empty()) {
1600 const auto current_inst = stack.back();
1601 stack.pop_back();
1603 if (const auto func = current_inst->function()) {
1604 // Instruction lives in a function, we can stop searching.
1605 const auto function_entry_points = FunctionEntryPoints(func->id());
1606 referenced_entry_points.insert(function_entry_points.begin(),
1607 function_entry_points.end());
1608 } else {
1609 // Instruction is in the global scope, keep searching its uses.
1610 for (auto pair : current_inst->uses()) {
1611 const auto next_inst = pair.first;
1612 stack.push_back(next_inst);
1617 return referenced_entry_points;
1620 std::string ValidationState_t::Disassemble(const Instruction& inst) const {
1621 const spv_parsed_instruction_t& c_inst(inst.c_inst());
1622 return Disassemble(c_inst.words, c_inst.num_words);
1625 std::string ValidationState_t::Disassemble(const uint32_t* words,
1626 uint16_t num_words) const {
1627 uint32_t disassembly_options = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1628 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
1630 return spvInstructionBinaryToText(context()->target_env, words, num_words,
1631 words_, num_words_, disassembly_options);
1634 bool ValidationState_t::LogicallyMatch(const Instruction* lhs,
1635 const Instruction* rhs,
1636 bool check_decorations) {
1637 if (lhs->opcode() != rhs->opcode()) {
1638 return false;
1641 if (check_decorations) {
1642 const auto& dec_a = id_decorations(lhs->id());
1643 const auto& dec_b = id_decorations(rhs->id());
1645 for (const auto& dec : dec_b) {
1646 if (std::find(dec_a.begin(), dec_a.end(), dec) == dec_a.end()) {
1647 return false;
1652 if (lhs->opcode() == spv::Op::OpTypeArray) {
1653 // Size operands must match.
1654 if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
1655 return false;
1658 // Elements must match or logically match.
1659 const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(1u);
1660 const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(1u);
1661 if (lhs_ele_id == rhs_ele_id) {
1662 return true;
1665 const auto lhs_ele = FindDef(lhs_ele_id);
1666 const auto rhs_ele = FindDef(rhs_ele_id);
1667 if (!lhs_ele || !rhs_ele) {
1668 return false;
1670 return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
1671 } else if (lhs->opcode() == spv::Op::OpTypeStruct) {
1672 // Number of elements must match.
1673 if (lhs->operands().size() != rhs->operands().size()) {
1674 return false;
1677 for (size_t i = 1u; i < lhs->operands().size(); ++i) {
1678 const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(i);
1679 const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(i);
1680 // Elements must match or logically match.
1681 if (lhs_ele_id == rhs_ele_id) {
1682 continue;
1685 const auto lhs_ele = FindDef(lhs_ele_id);
1686 const auto rhs_ele = FindDef(rhs_ele_id);
1687 if (!lhs_ele || !rhs_ele) {
1688 return false;
1691 if (!LogicallyMatch(lhs_ele, rhs_ele, check_decorations)) {
1692 return false;
1696 // All checks passed.
1697 return true;
1700 // No other opcodes are acceptable at this point. Arrays and structs are
1701 // caught above and if they're elements are not arrays or structs they are
1702 // required to match exactly.
1703 return false;
1706 const Instruction* ValidationState_t::TracePointer(
1707 const Instruction* inst) const {
1708 auto base_ptr = inst;
1709 while (base_ptr->opcode() == spv::Op::OpAccessChain ||
1710 base_ptr->opcode() == spv::Op::OpInBoundsAccessChain ||
1711 base_ptr->opcode() == spv::Op::OpPtrAccessChain ||
1712 base_ptr->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
1713 base_ptr->opcode() == spv::Op::OpCopyObject) {
1714 base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
1716 return base_ptr;
1719 bool ValidationState_t::ContainsType(
1720 uint32_t id, const std::function<bool(const Instruction*)>& f,
1721 bool traverse_all_types) const {
1722 const auto inst = FindDef(id);
1723 if (!inst) return false;
1725 if (f(inst)) return true;
1727 switch (inst->opcode()) {
1728 case spv::Op::OpTypeArray:
1729 case spv::Op::OpTypeRuntimeArray:
1730 case spv::Op::OpTypeVector:
1731 case spv::Op::OpTypeMatrix:
1732 case spv::Op::OpTypeImage:
1733 case spv::Op::OpTypeSampledImage:
1734 case spv::Op::OpTypeCooperativeMatrixNV:
1735 case spv::Op::OpTypeCooperativeMatrixKHR:
1736 case spv::Op::OpTypeCooperativeVectorNV:
1737 return ContainsType(inst->GetOperandAs<uint32_t>(1u), f,
1738 traverse_all_types);
1739 case spv::Op::OpTypePointer:
1740 if (IsForwardPointer(id)) return false;
1741 if (traverse_all_types) {
1742 return ContainsType(inst->GetOperandAs<uint32_t>(2u), f,
1743 traverse_all_types);
1745 break;
1746 case spv::Op::OpTypeFunction:
1747 case spv::Op::OpTypeStruct:
1748 if (inst->opcode() == spv::Op::OpTypeFunction && !traverse_all_types) {
1749 return false;
1751 for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1752 if (ContainsType(inst->GetOperandAs<uint32_t>(i), f,
1753 traverse_all_types)) {
1754 return true;
1757 break;
1758 default:
1759 break;
1762 return false;
1765 bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
1766 uint32_t width) const {
1767 if (type != spv::Op::OpTypeInt && type != spv::Op::OpTypeFloat) return false;
1769 const auto f = [type, width](const Instruction* inst) {
1770 if (inst->opcode() == type) {
1771 return inst->GetOperandAs<uint32_t>(1u) == width;
1773 return false;
1775 return ContainsType(id, f);
1778 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
1779 if ((!HasCapability(spv::Capability::Int16) &&
1780 ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 16)) ||
1781 (!HasCapability(spv::Capability::Int8) &&
1782 ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 8)) ||
1783 (!HasCapability(spv::Capability::Float16) &&
1784 ContainsSizedIntOrFloatType(id, spv::Op::OpTypeFloat, 16))) {
1785 return true;
1787 return false;
1790 bool ValidationState_t::ContainsRuntimeArray(uint32_t id) const {
1791 const auto f = [](const Instruction* inst) {
1792 return inst->opcode() == spv::Op::OpTypeRuntimeArray;
1794 return ContainsType(id, f, /* traverse_all_types = */ false);
1797 bool ValidationState_t::ContainsUntypedPointer(uint32_t id) const {
1798 const auto inst = FindDef(id);
1799 if (!inst) return false;
1800 if (!spvOpcodeGeneratesType(inst->opcode())) return false;
1801 if (inst->opcode() == spv::Op::OpTypeUntypedPointerKHR) return true;
1803 switch (inst->opcode()) {
1804 case spv::Op::OpTypeArray:
1805 case spv::Op::OpTypeRuntimeArray:
1806 case spv::Op::OpTypeVector:
1807 case spv::Op::OpTypeMatrix:
1808 case spv::Op::OpTypeImage:
1809 case spv::Op::OpTypeSampledImage:
1810 case spv::Op::OpTypeCooperativeMatrixNV:
1811 return ContainsUntypedPointer(inst->GetOperandAs<uint32_t>(1u));
1812 case spv::Op::OpTypePointer:
1813 if (IsForwardPointer(id)) return false;
1814 return ContainsUntypedPointer(inst->GetOperandAs<uint32_t>(2u));
1815 case spv::Op::OpTypeFunction:
1816 case spv::Op::OpTypeStruct: {
1817 for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1818 if (ContainsUntypedPointer(inst->GetOperandAs<uint32_t>(i)))
1819 return true;
1821 return false;
1823 default:
1824 return false;
1827 return false;
1830 bool ValidationState_t::IsValidStorageClass(
1831 spv::StorageClass storage_class) const {
1832 if (spvIsVulkanEnv(context()->target_env)) {
1833 switch (storage_class) {
1834 case spv::StorageClass::UniformConstant:
1835 case spv::StorageClass::Uniform:
1836 case spv::StorageClass::StorageBuffer:
1837 case spv::StorageClass::Input:
1838 case spv::StorageClass::Output:
1839 case spv::StorageClass::Image:
1840 case spv::StorageClass::Workgroup:
1841 case spv::StorageClass::Private:
1842 case spv::StorageClass::Function:
1843 case spv::StorageClass::PushConstant:
1844 case spv::StorageClass::PhysicalStorageBuffer:
1845 case spv::StorageClass::RayPayloadKHR:
1846 case spv::StorageClass::IncomingRayPayloadKHR:
1847 case spv::StorageClass::HitAttributeKHR:
1848 case spv::StorageClass::CallableDataKHR:
1849 case spv::StorageClass::IncomingCallableDataKHR:
1850 case spv::StorageClass::ShaderRecordBufferKHR:
1851 case spv::StorageClass::TaskPayloadWorkgroupEXT:
1852 case spv::StorageClass::HitObjectAttributeNV:
1853 case spv::StorageClass::TileImageEXT:
1854 case spv::StorageClass::NodePayloadAMDX:
1855 return true;
1856 default:
1857 return false;
1861 return true;
1864 #define VUID_WRAP(vuid) "[" #vuid "] "
1866 // Currently no 2 VUID share the same id, so no need for |reference|
1867 std::string ValidationState_t::VkErrorID(uint32_t id,
1868 const char* /*reference*/) const {
1869 if (!spvIsVulkanEnv(context_->target_env)) {
1870 return "";
1873 // This large switch case is only searched when an error has occurred.
1874 // If an id is changed, the old case must be modified or removed. Each string
1875 // here is interpreted as being "implemented"
1877 // Clang format adds spaces between hyphens
1878 // clang-format off
1879 switch (id) {
1880 case 4154:
1881 return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04154);
1882 case 4155:
1883 return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04155);
1884 case 4156:
1885 return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04156);
1886 case 4160:
1887 return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04160);
1888 case 4161:
1889 return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04161);
1890 case 4162:
1891 return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04162);
1892 case 4181:
1893 return VUID_WRAP(VUID-BaseInstance-BaseInstance-04181);
1894 case 4182:
1895 return VUID_WRAP(VUID-BaseInstance-BaseInstance-04182);
1896 case 4183:
1897 return VUID_WRAP(VUID-BaseInstance-BaseInstance-04183);
1898 case 4184:
1899 return VUID_WRAP(VUID-BaseVertex-BaseVertex-04184);
1900 case 4185:
1901 return VUID_WRAP(VUID-BaseVertex-BaseVertex-04185);
1902 case 4186:
1903 return VUID_WRAP(VUID-BaseVertex-BaseVertex-04186);
1904 case 4187:
1905 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
1906 case 4188:
1907 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04188);
1908 case 4189:
1909 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04189);
1910 case 4190:
1911 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04190);
1912 case 4191:
1913 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
1914 case 4196:
1915 return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
1916 case 4197:
1917 return VUID_WRAP(VUID-CullDistance-CullDistance-04197);
1918 case 4198:
1919 return VUID_WRAP(VUID-CullDistance-CullDistance-04198);
1920 case 4199:
1921 return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
1922 case 4200:
1923 return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
1924 case 6735:
1925 return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06735); // Execution Model
1926 case 6736:
1927 return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06736); // input storage
1928 case 6737:
1929 return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06737); // 32 int scalar
1930 case 4205:
1931 return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04205);
1932 case 4206:
1933 return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04206);
1934 case 4207:
1935 return VUID_WRAP(VUID-DrawIndex-DrawIndex-04207);
1936 case 4208:
1937 return VUID_WRAP(VUID-DrawIndex-DrawIndex-04208);
1938 case 4209:
1939 return VUID_WRAP(VUID-DrawIndex-DrawIndex-04209);
1940 case 4210:
1941 return VUID_WRAP(VUID-FragCoord-FragCoord-04210);
1942 case 4211:
1943 return VUID_WRAP(VUID-FragCoord-FragCoord-04211);
1944 case 4212:
1945 return VUID_WRAP(VUID-FragCoord-FragCoord-04212);
1946 case 4213:
1947 return VUID_WRAP(VUID-FragDepth-FragDepth-04213);
1948 case 4214:
1949 return VUID_WRAP(VUID-FragDepth-FragDepth-04214);
1950 case 4215:
1951 return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
1952 case 4216:
1953 return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
1954 case 4217:
1955 return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
1956 case 4218:
1957 return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
1958 case 4219:
1959 return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
1960 case 4220:
1961 return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
1962 case 4221:
1963 return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
1964 case 4222:
1965 return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
1966 case 4223:
1967 return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
1968 case 4224:
1969 return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
1970 case 4225:
1971 return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
1972 case 4229:
1973 return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
1974 case 4230:
1975 return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
1976 case 4231:
1977 return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
1978 case 4232:
1979 return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
1980 case 4233:
1981 return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
1982 case 4234:
1983 return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
1984 case 4236:
1985 return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
1986 case 4237:
1987 return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04237);
1988 case 4238:
1989 return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04238);
1990 case 4239:
1991 return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04239);
1992 case 4240:
1993 return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
1994 case 4241:
1995 return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
1996 case 4242:
1997 return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04242);
1998 case 4243:
1999 return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04243);
2000 case 4244:
2001 return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04244);
2002 case 4245:
2003 return VUID_WRAP(VUID-HitTNV-HitTNV-04245);
2004 case 4246:
2005 return VUID_WRAP(VUID-HitTNV-HitTNV-04246);
2006 case 4247:
2007 return VUID_WRAP(VUID-HitTNV-HitTNV-04247);
2008 case 4248:
2009 return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248);
2010 case 4249:
2011 return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249);
2012 case 4250:
2013 return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250);
2014 case 4251:
2015 return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251);
2016 case 4252:
2017 return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252);
2018 case 4253:
2019 return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253);
2020 case 4254:
2021 return VUID_WRAP(VUID-InstanceId-InstanceId-04254);
2022 case 4255:
2023 return VUID_WRAP(VUID-InstanceId-InstanceId-04255);
2024 case 4256:
2025 return VUID_WRAP(VUID-InstanceId-InstanceId-04256);
2026 case 4257:
2027 return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
2028 case 4258:
2029 return VUID_WRAP(VUID-InvocationId-InvocationId-04258);
2030 case 4259:
2031 return VUID_WRAP(VUID-InvocationId-InvocationId-04259);
2032 case 4263:
2033 return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04263);
2034 case 4264:
2035 return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
2036 case 4265:
2037 return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
2038 case 4266:
2039 return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04266);
2040 case 4267:
2041 return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04267);
2042 case 4268:
2043 return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04268);
2044 case 4269:
2045 return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04269);
2046 case 4270:
2047 return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04270);
2048 case 4271:
2049 return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04271);
2050 case 4272:
2051 return VUID_WRAP(VUID-Layer-Layer-04272);
2052 case 4273:
2053 return VUID_WRAP(VUID-Layer-Layer-04273);
2054 case 4274:
2055 return VUID_WRAP(VUID-Layer-Layer-04274);
2056 case 4275:
2057 return VUID_WRAP(VUID-Layer-Layer-04275);
2058 case 4276:
2059 return VUID_WRAP(VUID-Layer-Layer-04276);
2060 case 4281:
2061 return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04281);
2062 case 4282:
2063 return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
2064 case 4283:
2065 return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
2066 case 4293:
2067 return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
2068 case 4294:
2069 return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
2070 case 4295:
2071 return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
2072 case 4296:
2073 return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
2074 case 4297:
2075 return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04297);
2076 case 4298:
2077 return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04298);
2078 case 4299:
2079 return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299);
2080 case 4300:
2081 return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300);
2082 case 4301:
2083 return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301);
2084 case 4302:
2085 return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302);
2086 case 4303:
2087 return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303);
2088 case 4304:
2089 return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304);
2090 case 4305:
2091 return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305);
2092 case 4306:
2093 return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306);
2094 case 4307:
2095 return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307);
2096 case 4308:
2097 return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
2098 case 4309:
2099 return VUID_WRAP(VUID-PatchVertices-PatchVertices-04309);
2100 case 4310:
2101 return VUID_WRAP(VUID-PatchVertices-PatchVertices-04310);
2102 case 4311:
2103 return VUID_WRAP(VUID-PointCoord-PointCoord-04311);
2104 case 4312:
2105 return VUID_WRAP(VUID-PointCoord-PointCoord-04312);
2106 case 4313:
2107 return VUID_WRAP(VUID-PointCoord-PointCoord-04313);
2108 case 4314:
2109 return VUID_WRAP(VUID-PointSize-PointSize-04314);
2110 case 4315:
2111 return VUID_WRAP(VUID-PointSize-PointSize-04315);
2112 case 4316:
2113 return VUID_WRAP(VUID-PointSize-PointSize-04316);
2114 case 4317:
2115 return VUID_WRAP(VUID-PointSize-PointSize-04317);
2116 case 4318:
2117 return VUID_WRAP(VUID-Position-Position-04318);
2118 case 4319:
2119 return VUID_WRAP(VUID-Position-Position-04319);
2120 case 4320:
2121 return VUID_WRAP(VUID-Position-Position-04320);
2122 case 4321:
2123 return VUID_WRAP(VUID-Position-Position-04321);
2124 case 4330:
2125 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
2126 case 4334:
2127 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
2128 case 4336:
2129 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04336);
2130 case 4337:
2131 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
2132 case 4345:
2133 return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345);
2134 case 4346:
2135 return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346);
2136 case 4347:
2137 return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347);
2138 case 4348:
2139 return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04348);
2140 case 4349:
2141 return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04349);
2142 case 4350:
2143 return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04350);
2144 case 4351:
2145 return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04351);
2146 case 4352:
2147 return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04352);
2148 case 4353:
2149 return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04353);
2150 case 4354:
2151 return VUID_WRAP(VUID-SampleId-SampleId-04354);
2152 case 4355:
2153 return VUID_WRAP(VUID-SampleId-SampleId-04355);
2154 case 4356:
2155 return VUID_WRAP(VUID-SampleId-SampleId-04356);
2156 case 4357:
2157 return VUID_WRAP(VUID-SampleMask-SampleMask-04357);
2158 case 4358:
2159 return VUID_WRAP(VUID-SampleMask-SampleMask-04358);
2160 case 4359:
2161 return VUID_WRAP(VUID-SampleMask-SampleMask-04359);
2162 case 4360:
2163 return VUID_WRAP(VUID-SamplePosition-SamplePosition-04360);
2164 case 4361:
2165 return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
2166 case 4362:
2167 return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
2168 case 4367:
2169 return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
2170 case 4368:
2171 return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
2172 case 4369:
2173 return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
2174 case 4370:
2175 return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
2176 case 4371:
2177 return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
2178 case 4372:
2179 return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
2180 case 4373:
2181 return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
2182 case 4374:
2183 return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
2184 case 4375:
2185 return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
2186 case 4376:
2187 return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
2188 case 4377:
2189 return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
2190 case 4378:
2191 return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
2192 case 4379:
2193 return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
2194 case 4380:
2195 return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
2196 case 4381:
2197 return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
2198 case 4382:
2199 return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
2200 case 4383:
2201 return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
2202 case 4387:
2203 return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
2204 case 4388:
2205 return VUID_WRAP(VUID-TessCoord-TessCoord-04388);
2206 case 4389:
2207 return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
2208 case 4390:
2209 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
2210 case 4391:
2211 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04391);
2212 case 4392:
2213 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04392);
2214 case 4393:
2215 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
2216 case 4394:
2217 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
2218 case 4395:
2219 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04395);
2220 case 4396:
2221 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04396);
2222 case 4397:
2223 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
2224 case 4398:
2225 return VUID_WRAP(VUID-VertexIndex-VertexIndex-04398);
2226 case 4399:
2227 return VUID_WRAP(VUID-VertexIndex-VertexIndex-04399);
2228 case 4400:
2229 return VUID_WRAP(VUID-VertexIndex-VertexIndex-04400);
2230 case 4401:
2231 return VUID_WRAP(VUID-ViewIndex-ViewIndex-04401);
2232 case 4402:
2233 return VUID_WRAP(VUID-ViewIndex-ViewIndex-04402);
2234 case 4403:
2235 return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
2236 case 4404:
2237 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
2238 case 4405:
2239 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04405);
2240 case 4406:
2241 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
2242 case 4407:
2243 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407);
2244 case 4408:
2245 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
2246 case 4422:
2247 return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04422);
2248 case 4423:
2249 return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04423);
2250 case 4424:
2251 return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04424);
2252 case 4425:
2253 return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04425);
2254 case 4426:
2255 return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
2256 case 4427:
2257 return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
2258 case 4428:
2259 return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428);
2260 case 4429:
2261 return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429);
2262 case 4430:
2263 return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430);
2264 case 4431:
2265 return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431);
2266 case 4432:
2267 return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432);
2268 case 4433:
2269 return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433);
2270 case 4434:
2271 return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04434);
2272 case 4435:
2273 return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04435);
2274 case 4436:
2275 return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04436);
2276 case 4484:
2277 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
2278 case 4485:
2279 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485);
2280 case 4486:
2281 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486);
2282 case 4490:
2283 return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490);
2284 case 4491:
2285 return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
2286 case 4492:
2287 return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
2288 case 4633:
2289 return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
2290 case 4634:
2291 return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
2292 case 4635:
2293 return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
2294 case 4636:
2295 return VUID_WRAP(VUID-StandaloneSpirv-None-04636);
2296 case 4637:
2297 return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
2298 case 4638:
2299 return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
2300 case 7321:
2301 return VUID_WRAP(VUID-StandaloneSpirv-None-07321);
2302 case 4640:
2303 return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
2304 case 4641:
2305 return VUID_WRAP(VUID-StandaloneSpirv-None-04641);
2306 case 4642:
2307 return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
2308 case 4643:
2309 return VUID_WRAP(VUID-StandaloneSpirv-None-04643);
2310 case 4644:
2311 return VUID_WRAP(VUID-StandaloneSpirv-None-04644);
2312 case 4645:
2313 return VUID_WRAP(VUID-StandaloneSpirv-None-04645);
2314 case 4650:
2315 return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04650);
2316 case 4651:
2317 return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
2318 case 4652:
2319 return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
2320 case 4653:
2321 return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
2322 case 4654:
2323 return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
2324 case 4655:
2325 return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-04655);
2326 case 4656:
2327 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
2328 case 4657:
2329 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
2330 case 4658:
2331 return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
2332 case 4659:
2333 return VUID_WRAP(VUID-StandaloneSpirv-OpImageQuerySizeLod-04659);
2334 case 4664:
2335 return VUID_WRAP(VUID-StandaloneSpirv-OpImageGather-04664);
2336 case 4667:
2337 return VUID_WRAP(VUID-StandaloneSpirv-None-04667);
2338 case 4669:
2339 return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
2340 case 4670:
2341 return VUID_WRAP(VUID-StandaloneSpirv-Flat-04670);
2342 case 4675:
2343 return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
2344 case 4677:
2345 return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
2346 case 4680:
2347 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeRuntimeArray-04680);
2348 case 4682:
2349 return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
2350 case 6426:
2351 return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-06426); // formally 04683
2352 case 4685:
2353 return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
2354 case 4686:
2355 return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
2356 case 4698:
2357 return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698);
2358 case 4699:
2359 return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699);
2360 case 4700:
2361 return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04700);
2362 case 4701:
2363 return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701);
2364 case 4702:
2365 return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04702);
2366 case 4703:
2367 return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703);
2368 case 4704:
2369 return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704);
2370 case 4705:
2371 return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705);
2372 case 4706:
2373 return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04706);
2374 case 7119:
2375 return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119);
2376 case 4708:
2377 return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708);
2378 case 4710:
2379 return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710);
2380 case 4711:
2381 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
2382 case 4730:
2383 return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicStore-04730);
2384 case 4731:
2385 return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicLoad-04731);
2386 case 4732:
2387 return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04732);
2388 case 4733:
2389 return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
2390 case 4734:
2391 return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04734);
2392 case 4744:
2393 return VUID_WRAP(VUID-StandaloneSpirv-Flat-04744);
2394 case 4777:
2395 return VUID_WRAP(VUID-StandaloneSpirv-OpImage-04777);
2396 case 4780:
2397 return VUID_WRAP(VUID-StandaloneSpirv-Result-04780);
2398 case 4781:
2399 return VUID_WRAP(VUID-StandaloneSpirv-Base-04781);
2400 case 4915:
2401 return VUID_WRAP(VUID-StandaloneSpirv-Location-04915);
2402 case 4916:
2403 return VUID_WRAP(VUID-StandaloneSpirv-Location-04916);
2404 case 4917:
2405 return VUID_WRAP(VUID-StandaloneSpirv-Location-04917);
2406 case 4918:
2407 return VUID_WRAP(VUID-StandaloneSpirv-Location-04918);
2408 case 4919:
2409 return VUID_WRAP(VUID-StandaloneSpirv-Location-04919);
2410 case 4920:
2411 return VUID_WRAP(VUID-StandaloneSpirv-Component-04920);
2412 case 4921:
2413 return VUID_WRAP(VUID-StandaloneSpirv-Component-04921);
2414 case 4922:
2415 return VUID_WRAP(VUID-StandaloneSpirv-Component-04922);
2416 case 4923:
2417 return VUID_WRAP(VUID-StandaloneSpirv-Component-04923);
2418 case 4924:
2419 return VUID_WRAP(VUID-StandaloneSpirv-Component-04924);
2420 case 6201:
2421 return VUID_WRAP(VUID-StandaloneSpirv-Flat-06201);
2422 case 6202:
2423 return VUID_WRAP(VUID-StandaloneSpirv-Flat-06202);
2424 case 6214:
2425 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-06214);
2426 case 6491:
2427 return VUID_WRAP(VUID-StandaloneSpirv-DescriptorSet-06491);
2428 case 6671:
2429 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeSampledImage-06671);
2430 case 6672:
2431 return VUID_WRAP(VUID-StandaloneSpirv-Location-06672);
2432 case 6673:
2433 return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-06673);
2434 case 6674:
2435 return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-06674);
2436 case 6675:
2437 return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06675);
2438 case 6676:
2439 return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06676);
2440 case 6677:
2441 return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-06677);
2442 case 6678:
2443 return VUID_WRAP(VUID-StandaloneSpirv-InputAttachmentIndex-06678);
2444 case 6777:
2445 return VUID_WRAP(VUID-StandaloneSpirv-PerVertexKHR-06777);
2446 case 6778:
2447 return VUID_WRAP(VUID-StandaloneSpirv-Input-06778);
2448 case 6807:
2449 return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06807);
2450 case 6808:
2451 return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
2452 case 6924:
2453 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-06924);
2454 case 6925:
2455 return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
2456 case 7034:
2457 return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-07034);
2458 case 7035:
2459 return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-07035);
2460 case 7036:
2461 return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-07036);
2462 case 7038:
2463 return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-07038);
2464 case 7039:
2465 return VUID_WRAP(VUID-Layer-Layer-07039);
2466 case 7040:
2467 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-07040);
2468 case 7041:
2469 return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07041);
2470 case 7042:
2471 return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07042);
2472 case 7043:
2473 return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07043);
2474 case 7044:
2475 return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07044);
2476 case 7046:
2477 return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07046);
2478 case 7047:
2479 return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07047);
2480 case 7048:
2481 return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07048);
2482 case 7049:
2483 return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07049);
2484 case 7050:
2485 return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07050);
2486 case 7052:
2487 return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07052);
2488 case 7053:
2489 return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07053);
2490 case 7054:
2491 return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07054);
2492 case 7055:
2493 return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07055);
2494 case 7056:
2495 return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07056);
2496 case 7058:
2497 return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07058);
2498 case 7059:
2499 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-07059);
2500 case 7060:
2501 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-07060);
2502 case 7102:
2503 return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
2504 case 7290:
2505 return VUID_WRAP(VUID-StandaloneSpirv-Input-07290);
2506 case 7320:
2507 return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
2508 case 7330:
2509 return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07330);
2510 case 7331:
2511 return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07331);
2512 case 7650:
2513 return VUID_WRAP(VUID-StandaloneSpirv-Base-07650);
2514 case 7651:
2515 return VUID_WRAP(VUID-StandaloneSpirv-Base-07651);
2516 case 7652:
2517 return VUID_WRAP(VUID-StandaloneSpirv-Base-07652);
2518 case 7703:
2519 return VUID_WRAP(VUID-StandaloneSpirv-Component-07703);
2520 case 7951:
2521 return VUID_WRAP(VUID-StandaloneSpirv-SubgroupVoteKHR-07951);
2522 case 8721:
2523 return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08721);
2524 case 8722:
2525 return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08722);
2526 case 8973:
2527 return VUID_WRAP(VUID-StandaloneSpirv-Pointer-08973);
2528 case 9638:
2529 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-09638);
2530 case 9658:
2531 return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-09658);
2532 case 9659:
2533 return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-09659);
2534 case 10213:
2535 // This use to be a standalone, but maintenance8 will set allow_offset_texture_operand now
2536 return VUID_WRAP(VUID-RuntimeSpirv-Offset-10213);
2537 default:
2538 return ""; // unknown id
2540 // clang-format on
2543 } // namespace val
2544 } // namespace spvtools