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, ¤t_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