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