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