validation_state.cpp 88 KB

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