1 /* Copyright (c) 2015-2019 The Khronos Group Inc. 2 * Copyright (c) 2015-2019 Valve Corporation 3 * Copyright (c) 2015-2019 LunarG, Inc. 4 * Copyright (C) 2015-2019 Google Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Chris Forbes <chrisf (at) ijw.co.nz> 19 * Author: Dave Houlton <daveh (at) lunarg.com> 20 */ 21 22 #include <cinttypes> 23 #include <cassert> 24 #include <chrono> 25 #include <vector> 26 #include <unordered_map> 27 #include <string> 28 #include <sstream> 29 #include <SPIRV/spirv.hpp> 30 #include "vk_loader_platform.h" 31 #include "vk_enum_string_helper.h" 32 #include "vk_layer_data.h" 33 #include "vk_layer_extension_utils.h" 34 #include "vk_layer_utils.h" 35 #include "chassis.h" 36 #include "core_validation.h" 37 #include "shader_validation.h" 38 #include "spirv-tools/libspirv.h" 39 #include "xxhash.h" 40 41 enum FORMAT_TYPE { 42 FORMAT_TYPE_FLOAT = 1, // UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader 43 FORMAT_TYPE_SINT = 2, 44 FORMAT_TYPE_UINT = 4, 45 }; 46 47 typedef std::pair<unsigned, unsigned> location_t; 48 49 struct interface_var { 50 uint32_t id; 51 uint32_t type_id; 52 uint32_t offset; 53 bool is_patch; 54 bool is_block_member; 55 bool is_relaxed_precision; 56 // TODO: collect the name, too? Isn't required to be present. 57 }; 58 59 struct shader_stage_attributes { 60 char const *const name; 61 bool arrayed_input; 62 bool arrayed_output; 63 }; 64 65 static shader_stage_attributes shader_stage_attribs[] = { 66 {"vertex shader", false, false}, {"tessellation control shader", true, true}, {"tessellation evaluation shader", true, false}, 67 {"geometry shader", true, false}, {"fragment shader", false, false}, 68 }; 69 70 // SPIRV utility functions 71 void shader_module::BuildDefIndex() { 72 for (auto insn : *this) { 73 switch (insn.opcode()) { 74 // Types 75 case spv::OpTypeVoid: 76 case spv::OpTypeBool: 77 case spv::OpTypeInt: 78 case spv::OpTypeFloat: 79 case spv::OpTypeVector: 80 case spv::OpTypeMatrix: 81 case spv::OpTypeImage: 82 case spv::OpTypeSampler: 83 case spv::OpTypeSampledImage: 84 case spv::OpTypeArray: 85 case spv::OpTypeRuntimeArray: 86 case spv::OpTypeStruct: 87 case spv::OpTypeOpaque: 88 case spv::OpTypePointer: 89 case spv::OpTypeFunction: 90 case spv::OpTypeEvent: 91 case spv::OpTypeDeviceEvent: 92 case spv::OpTypeReserveId: 93 case spv::OpTypeQueue: 94 case spv::OpTypePipe: 95 case spv::OpTypeAccelerationStructureNV: 96 def_index[insn.word(1)] = insn.offset(); 97 break; 98 99 // Fixed constants 100 case spv::OpConstantTrue: 101 case spv::OpConstantFalse: 102 case spv::OpConstant: 103 case spv::OpConstantComposite: 104 case spv::OpConstantSampler: 105 case spv::OpConstantNull: 106 def_index[insn.word(2)] = insn.offset(); 107 break; 108 109 // Specialization constants 110 case spv::OpSpecConstantTrue: 111 case spv::OpSpecConstantFalse: 112 case spv::OpSpecConstant: 113 case spv::OpSpecConstantComposite: 114 case spv::OpSpecConstantOp: 115 def_index[insn.word(2)] = insn.offset(); 116 break; 117 118 // Variables 119 case spv::OpVariable: 120 def_index[insn.word(2)] = insn.offset(); 121 break; 122 123 // Functions 124 case spv::OpFunction: 125 def_index[insn.word(2)] = insn.offset(); 126 break; 127 128 default: 129 // We don't care about any other defs for now. 130 break; 131 } 132 } 133 } 134 135 unsigned ExecutionModelToShaderStageFlagBits(unsigned mode) { 136 switch (mode) { 137 case spv::ExecutionModelVertex: 138 return VK_SHADER_STAGE_VERTEX_BIT; 139 case spv::ExecutionModelTessellationControl: 140 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; 141 case spv::ExecutionModelTessellationEvaluation: 142 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; 143 case spv::ExecutionModelGeometry: 144 return VK_SHADER_STAGE_GEOMETRY_BIT; 145 case spv::ExecutionModelFragment: 146 return VK_SHADER_STAGE_FRAGMENT_BIT; 147 case spv::ExecutionModelGLCompute: 148 return VK_SHADER_STAGE_COMPUTE_BIT; 149 case spv::ExecutionModelRayGenerationNV: 150 return VK_SHADER_STAGE_RAYGEN_BIT_NV; 151 case spv::ExecutionModelAnyHitNV: 152 return VK_SHADER_STAGE_ANY_HIT_BIT_NV; 153 case spv::ExecutionModelClosestHitNV: 154 return VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV; 155 case spv::ExecutionModelMissNV: 156 return VK_SHADER_STAGE_MISS_BIT_NV; 157 case spv::ExecutionModelIntersectionNV: 158 return VK_SHADER_STAGE_INTERSECTION_BIT_NV; 159 case spv::ExecutionModelCallableNV: 160 return VK_SHADER_STAGE_CALLABLE_BIT_NV; 161 case spv::ExecutionModelTaskNV: 162 return VK_SHADER_STAGE_TASK_BIT_NV; 163 case spv::ExecutionModelMeshNV: 164 return VK_SHADER_STAGE_MESH_BIT_NV; 165 default: 166 return 0; 167 } 168 } 169 170 static spirv_inst_iter FindEntrypoint(shader_module const *src, char const *name, VkShaderStageFlagBits stageBits) { 171 for (auto insn : *src) { 172 if (insn.opcode() == spv::OpEntryPoint) { 173 auto entrypointName = (char const *)&insn.word(3); 174 auto executionModel = insn.word(1); 175 auto entrypointStageBits = ExecutionModelToShaderStageFlagBits(executionModel); 176 177 if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) { 178 return insn; 179 } 180 } 181 } 182 183 return src->end(); 184 } 185 186 static char const *StorageClassName(unsigned sc) { 187 switch (sc) { 188 case spv::StorageClassInput: 189 return "input"; 190 case spv::StorageClassOutput: 191 return "output"; 192 case spv::StorageClassUniformConstant: 193 return "const uniform"; 194 case spv::StorageClassUniform: 195 return "uniform"; 196 case spv::StorageClassWorkgroup: 197 return "workgroup local"; 198 case spv::StorageClassCrossWorkgroup: 199 return "workgroup global"; 200 case spv::StorageClassPrivate: 201 return "private global"; 202 case spv::StorageClassFunction: 203 return "function"; 204 case spv::StorageClassGeneric: 205 return "generic"; 206 case spv::StorageClassAtomicCounter: 207 return "atomic counter"; 208 case spv::StorageClassImage: 209 return "image"; 210 case spv::StorageClassPushConstant: 211 return "push constant"; 212 case spv::StorageClassStorageBuffer: 213 return "storage buffer"; 214 default: 215 return "unknown"; 216 } 217 } 218 219 // Get the value of an integral constant 220 unsigned GetConstantValue(shader_module const *src, unsigned id) { 221 auto value = src->get_def(id); 222 assert(value != src->end()); 223 224 if (value.opcode() != spv::OpConstant) { 225 // TODO: Either ensure that the specialization transform is already performed on a module we're 226 // considering here, OR -- specialize on the fly now. 227 return 1; 228 } 229 230 return value.word(3); 231 } 232 233 static void DescribeTypeInner(std::ostringstream &ss, shader_module const *src, unsigned type) { 234 auto insn = src->get_def(type); 235 assert(insn != src->end()); 236 237 switch (insn.opcode()) { 238 case spv::OpTypeBool: 239 ss << "bool"; 240 break; 241 case spv::OpTypeInt: 242 ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2); 243 break; 244 case spv::OpTypeFloat: 245 ss << "float" << insn.word(2); 246 break; 247 case spv::OpTypeVector: 248 ss << "vec" << insn.word(3) << " of "; 249 DescribeTypeInner(ss, src, insn.word(2)); 250 break; 251 case spv::OpTypeMatrix: 252 ss << "mat" << insn.word(3) << " of "; 253 DescribeTypeInner(ss, src, insn.word(2)); 254 break; 255 case spv::OpTypeArray: 256 ss << "arr[" << GetConstantValue(src, insn.word(3)) << "] of "; 257 DescribeTypeInner(ss, src, insn.word(2)); 258 break; 259 case spv::OpTypeRuntimeArray: 260 ss << "runtime arr[] of "; 261 DescribeTypeInner(ss, src, insn.word(2)); 262 break; 263 case spv::OpTypePointer: 264 ss << "ptr to " << StorageClassName(insn.word(2)) << " "; 265 DescribeTypeInner(ss, src, insn.word(3)); 266 break; 267 case spv::OpTypeStruct: { 268 ss << "struct of ("; 269 for (unsigned i = 2; i < insn.len(); i++) { 270 DescribeTypeInner(ss, src, insn.word(i)); 271 if (i == insn.len() - 1) { 272 ss << ")"; 273 } else { 274 ss << ", "; 275 } 276 } 277 break; 278 } 279 case spv::OpTypeSampler: 280 ss << "sampler"; 281 break; 282 case spv::OpTypeSampledImage: 283 ss << "sampler+"; 284 DescribeTypeInner(ss, src, insn.word(2)); 285 break; 286 case spv::OpTypeImage: 287 ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")"; 288 break; 289 case spv::OpTypeAccelerationStructureNV: 290 ss << "accelerationStruture"; 291 break; 292 default: 293 ss << "oddtype"; 294 break; 295 } 296 } 297 298 static std::string DescribeType(shader_module const *src, unsigned type) { 299 std::ostringstream ss; 300 DescribeTypeInner(ss, src, type); 301 return ss.str(); 302 } 303 304 static bool IsNarrowNumericType(spirv_inst_iter type) { 305 if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat) return false; 306 return type.word(2) < 64; 307 } 308 309 static bool TypesMatch(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, 310 bool b_arrayed, bool relaxed) { 311 // Walk two type trees together, and complain about differences 312 auto a_insn = a->get_def(a_type); 313 auto b_insn = b->get_def(b_type); 314 assert(a_insn != a->end()); 315 assert(b_insn != b->end()); 316 317 // Ignore runtime-sized arrays-- they cannot appear in these interfaces. 318 319 if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { 320 return TypesMatch(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed); 321 } 322 323 if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { 324 // We probably just found the extra level of arrayness in b_type: compare the type inside it to a_type 325 return TypesMatch(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed); 326 } 327 328 if (a_insn.opcode() == spv::OpTypeVector && relaxed && IsNarrowNumericType(b_insn)) { 329 return TypesMatch(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false); 330 } 331 332 if (a_insn.opcode() != b_insn.opcode()) { 333 return false; 334 } 335 336 if (a_insn.opcode() == spv::OpTypePointer) { 337 // Match on pointee type. storage class is expected to differ 338 return TypesMatch(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed); 339 } 340 341 if (a_arrayed || b_arrayed) { 342 // If we havent resolved array-of-verts by here, we're not going to. 343 return false; 344 } 345 346 switch (a_insn.opcode()) { 347 case spv::OpTypeBool: 348 return true; 349 case spv::OpTypeInt: 350 // Match on width, signedness 351 return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); 352 case spv::OpTypeFloat: 353 // Match on width 354 return a_insn.word(2) == b_insn.word(2); 355 case spv::OpTypeVector: 356 // Match on element type, count. 357 if (!TypesMatch(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false)) return false; 358 if (relaxed && IsNarrowNumericType(a->get_def(a_insn.word(2)))) { 359 return a_insn.word(3) >= b_insn.word(3); 360 } else { 361 return a_insn.word(3) == b_insn.word(3); 362 } 363 case spv::OpTypeMatrix: 364 // Match on element type, count. 365 return TypesMatch(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 366 a_insn.word(3) == b_insn.word(3); 367 case spv::OpTypeArray: 368 // Match on element type, count. these all have the same layout. we don't get here if b_arrayed. This differs from 369 // vector & matrix types in that the array size is the id of a constant instruction, * not a literal within OpTypeArray 370 return TypesMatch(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 371 GetConstantValue(a, a_insn.word(3)) == GetConstantValue(b, b_insn.word(3)); 372 case spv::OpTypeStruct: 373 // Match on all element types 374 { 375 if (a_insn.len() != b_insn.len()) { 376 return false; // Structs cannot match if member counts differ 377 } 378 379 for (unsigned i = 2; i < a_insn.len(); i++) { 380 if (!TypesMatch(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) { 381 return false; 382 } 383 } 384 385 return true; 386 } 387 default: 388 // Remaining types are CLisms, or may not appear in the interfaces we are interested in. Just claim no match. 389 return false; 390 } 391 } 392 393 static unsigned ValueOrDefault(std::unordered_map<unsigned, unsigned> const &map, unsigned id, unsigned def) { 394 auto it = map.find(id); 395 if (it == map.end()) 396 return def; 397 else 398 return it->second; 399 } 400 401 static unsigned GetLocationsConsumedByType(shader_module const *src, unsigned type, bool strip_array_level) { 402 auto insn = src->get_def(type); 403 assert(insn != src->end()); 404 405 switch (insn.opcode()) { 406 case spv::OpTypePointer: 407 // See through the ptr -- this is only ever at the toplevel for graphics shaders we're never actually passing 408 // pointers around. 409 return GetLocationsConsumedByType(src, insn.word(3), strip_array_level); 410 case spv::OpTypeArray: 411 if (strip_array_level) { 412 return GetLocationsConsumedByType(src, insn.word(2), false); 413 } else { 414 return GetConstantValue(src, insn.word(3)) * GetLocationsConsumedByType(src, insn.word(2), false); 415 } 416 case spv::OpTypeMatrix: 417 // Num locations is the dimension * element size 418 return insn.word(3) * GetLocationsConsumedByType(src, insn.word(2), false); 419 case spv::OpTypeVector: { 420 auto scalar_type = src->get_def(insn.word(2)); 421 auto bit_width = 422 (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? scalar_type.word(2) : 32; 423 424 // Locations are 128-bit wide; 3- and 4-component vectors of 64 bit types require two. 425 return (bit_width * insn.word(3) + 127) / 128; 426 } 427 default: 428 // Everything else is just 1. 429 return 1; 430 431 // TODO: extend to handle 64bit scalar types, whose vectors may need multiple locations. 432 } 433 } 434 435 static unsigned GetComponentsConsumedByType(shader_module const *src, unsigned type, bool strip_array_level) { 436 auto insn = src->get_def(type); 437 assert(insn != src->end()); 438 439 switch (insn.opcode()) { 440 case spv::OpTypePointer: 441 // See through the ptr -- this is only ever at the toplevel for graphics shaders we're never actually passing 442 // pointers around. 443 return GetComponentsConsumedByType(src, insn.word(3), strip_array_level); 444 case spv::OpTypeStruct: { 445 uint32_t sum = 0; 446 for (uint32_t i = 2; i < insn.len(); i++) { // i=2 to skip word(0) and word(1)=ID of struct 447 sum += GetComponentsConsumedByType(src, insn.word(i), false); 448 } 449 return sum; 450 } 451 case spv::OpTypeArray: { 452 uint32_t sum = 0; 453 for (uint32_t i = 2; i < insn.len(); i++) { 454 sum += GetComponentsConsumedByType(src, insn.word(i), false); 455 } 456 return sum; 457 } 458 case spv::OpTypeMatrix: 459 // Num locations is the dimension * element size 460 return insn.word(3) * GetComponentsConsumedByType(src, insn.word(2), false); 461 case spv::OpTypeVector: { 462 auto scalar_type = src->get_def(insn.word(2)); 463 auto bit_width = 464 (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? scalar_type.word(2) : 32; 465 // One component is 32-bit 466 return (bit_width * insn.word(3) + 31) / 32; 467 } 468 case spv::OpTypeFloat: { 469 auto bit_width = insn.word(2); 470 return (bit_width + 31) / 32; 471 } 472 case spv::OpTypeInt: { 473 auto bit_width = insn.word(2); 474 return (bit_width + 31) / 32; 475 } 476 case spv::OpConstant: 477 return GetComponentsConsumedByType(src, insn.word(1), false); 478 default: 479 return 0; 480 } 481 } 482 483 static unsigned GetLocationsConsumedByFormat(VkFormat format) { 484 switch (format) { 485 case VK_FORMAT_R64G64B64A64_SFLOAT: 486 case VK_FORMAT_R64G64B64A64_SINT: 487 case VK_FORMAT_R64G64B64A64_UINT: 488 case VK_FORMAT_R64G64B64_SFLOAT: 489 case VK_FORMAT_R64G64B64_SINT: 490 case VK_FORMAT_R64G64B64_UINT: 491 return 2; 492 default: 493 return 1; 494 } 495 } 496 497 static unsigned GetFormatType(VkFormat fmt) { 498 if (FormatIsSInt(fmt)) return FORMAT_TYPE_SINT; 499 if (FormatIsUInt(fmt)) return FORMAT_TYPE_UINT; 500 if (FormatIsDepthAndStencil(fmt)) return FORMAT_TYPE_FLOAT | FORMAT_TYPE_UINT; 501 if (fmt == VK_FORMAT_UNDEFINED) return 0; 502 // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader. 503 return FORMAT_TYPE_FLOAT; 504 } 505 506 // characterizes a SPIR-V type appearing in an interface to a FF stage, for comparison to a VkFormat's characterization above. 507 // also used for input attachments, as we statically know their format. 508 static unsigned GetFundamentalType(shader_module const *src, unsigned type) { 509 auto insn = src->get_def(type); 510 assert(insn != src->end()); 511 512 switch (insn.opcode()) { 513 case spv::OpTypeInt: 514 return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT; 515 case spv::OpTypeFloat: 516 return FORMAT_TYPE_FLOAT; 517 case spv::OpTypeVector: 518 case spv::OpTypeMatrix: 519 case spv::OpTypeArray: 520 case spv::OpTypeRuntimeArray: 521 case spv::OpTypeImage: 522 return GetFundamentalType(src, insn.word(2)); 523 case spv::OpTypePointer: 524 return GetFundamentalType(src, insn.word(3)); 525 526 default: 527 return 0; 528 } 529 } 530 531 static uint32_t GetShaderStageId(VkShaderStageFlagBits stage) { 532 uint32_t bit_pos = uint32_t(u_ffs(stage)); 533 return bit_pos - 1; 534 } 535 536 static spirv_inst_iter GetStructType(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) { 537 while (true) { 538 if (def.opcode() == spv::OpTypePointer) { 539 def = src->get_def(def.word(3)); 540 } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) { 541 def = src->get_def(def.word(2)); 542 is_array_of_verts = false; 543 } else if (def.opcode() == spv::OpTypeStruct) { 544 return def; 545 } else { 546 return src->end(); 547 } 548 } 549 } 550 551 static bool CollectInterfaceBlockMembers(shader_module const *src, std::map<location_t, interface_var> *out, 552 std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts, uint32_t id, 553 uint32_t type_id, bool is_patch, int /*first_location*/) { 554 // Walk down the type_id presented, trying to determine whether it's actually an interface block. 555 auto type = GetStructType(src, src->get_def(type_id), is_array_of_verts && !is_patch); 556 if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) { 557 // This isn't an interface block. 558 return false; 559 } 560 561 std::unordered_map<unsigned, unsigned> member_components; 562 std::unordered_map<unsigned, unsigned> member_relaxed_precision; 563 std::unordered_map<unsigned, unsigned> member_patch; 564 565 // Walk all the OpMemberDecorate for type's result id -- first pass, collect components. 566 for (auto insn : *src) { 567 if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 568 unsigned member_index = insn.word(2); 569 570 if (insn.word(3) == spv::DecorationComponent) { 571 unsigned component = insn.word(4); 572 member_components[member_index] = component; 573 } 574 575 if (insn.word(3) == spv::DecorationRelaxedPrecision) { 576 member_relaxed_precision[member_index] = 1; 577 } 578 579 if (insn.word(3) == spv::DecorationPatch) { 580 member_patch[member_index] = 1; 581 } 582 } 583 } 584 585 // TODO: correctly handle location assignment from outside 586 587 // Second pass -- produce the output, from Location decorations 588 for (auto insn : *src) { 589 if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 590 unsigned member_index = insn.word(2); 591 unsigned member_type_id = type.word(2 + member_index); 592 593 if (insn.word(3) == spv::DecorationLocation) { 594 unsigned location = insn.word(4); 595 unsigned num_locations = GetLocationsConsumedByType(src, member_type_id, false); 596 auto component_it = member_components.find(member_index); 597 unsigned component = component_it == member_components.end() ? 0 : component_it->second; 598 bool is_relaxed_precision = member_relaxed_precision.find(member_index) != member_relaxed_precision.end(); 599 bool member_is_patch = is_patch || member_patch.count(member_index) > 0; 600 601 for (unsigned int offset = 0; offset < num_locations; offset++) { 602 interface_var v = {}; 603 v.id = id; 604 // TODO: member index in interface_var too? 605 v.type_id = member_type_id; 606 v.offset = offset; 607 v.is_patch = member_is_patch; 608 v.is_block_member = true; 609 v.is_relaxed_precision = is_relaxed_precision; 610 (*out)[std::make_pair(location + offset, component)] = v; 611 } 612 } 613 } 614 } 615 616 return true; 617 } 618 619 static std::map<location_t, interface_var> CollectInterfaceByLocation(shader_module const *src, spirv_inst_iter entrypoint, 620 spv::StorageClass sinterface, bool is_array_of_verts) { 621 std::unordered_map<unsigned, unsigned> var_locations; 622 std::unordered_map<unsigned, unsigned> var_builtins; 623 std::unordered_map<unsigned, unsigned> var_components; 624 std::unordered_map<unsigned, unsigned> blocks; 625 std::unordered_map<unsigned, unsigned> var_patch; 626 std::unordered_map<unsigned, unsigned> var_relaxed_precision; 627 628 for (auto insn : *src) { 629 // We consider two interface models: SSO rendezvous-by-location, and builtins. Complain about anything that 630 // fits neither model. 631 if (insn.opcode() == spv::OpDecorate) { 632 if (insn.word(2) == spv::DecorationLocation) { 633 var_locations[insn.word(1)] = insn.word(3); 634 } 635 636 if (insn.word(2) == spv::DecorationBuiltIn) { 637 var_builtins[insn.word(1)] = insn.word(3); 638 } 639 640 if (insn.word(2) == spv::DecorationComponent) { 641 var_components[insn.word(1)] = insn.word(3); 642 } 643 644 if (insn.word(2) == spv::DecorationBlock) { 645 blocks[insn.word(1)] = 1; 646 } 647 648 if (insn.word(2) == spv::DecorationPatch) { 649 var_patch[insn.word(1)] = 1; 650 } 651 652 if (insn.word(2) == spv::DecorationRelaxedPrecision) { 653 var_relaxed_precision[insn.word(1)] = 1; 654 } 655 } 656 } 657 658 // TODO: handle grouped decorations 659 // TODO: handle index=1 dual source outputs from FS -- two vars will have the same location, and we DON'T want to clobber. 660 661 // Find the end of the entrypoint's name string. additional zero bytes follow the actual null terminator, to fill out the 662 // rest of the word - so we only need to look at the last byte in the word to determine which word contains the terminator. 663 uint32_t word = 3; 664 while (entrypoint.word(word) & 0xff000000u) { 665 ++word; 666 } 667 ++word; 668 669 std::map<location_t, interface_var> out; 670 671 for (; word < entrypoint.len(); word++) { 672 auto insn = src->get_def(entrypoint.word(word)); 673 assert(insn != src->end()); 674 assert(insn.opcode() == spv::OpVariable); 675 676 if (insn.word(3) == static_cast<uint32_t>(sinterface)) { 677 unsigned id = insn.word(2); 678 unsigned type = insn.word(1); 679 680 int location = ValueOrDefault(var_locations, id, static_cast<unsigned>(-1)); 681 int builtin = ValueOrDefault(var_builtins, id, static_cast<unsigned>(-1)); 682 unsigned component = ValueOrDefault(var_components, id, 0); // Unspecified is OK, is 0 683 bool is_patch = var_patch.find(id) != var_patch.end(); 684 bool is_relaxed_precision = var_relaxed_precision.find(id) != var_relaxed_precision.end(); 685 686 if (builtin != -1) 687 continue; 688 else if (!CollectInterfaceBlockMembers(src, &out, blocks, is_array_of_verts, id, type, is_patch, location)) { 689 // A user-defined interface variable, with a location. Where a variable occupied multiple locations, emit 690 // one result for each. 691 unsigned num_locations = GetLocationsConsumedByType(src, type, is_array_of_verts && !is_patch); 692 for (unsigned int offset = 0; offset < num_locations; offset++) { 693 interface_var v = {}; 694 v.id = id; 695 v.type_id = type; 696 v.offset = offset; 697 v.is_patch = is_patch; 698 v.is_relaxed_precision = is_relaxed_precision; 699 out[std::make_pair(location + offset, component)] = v; 700 } 701 } 702 } 703 } 704 705 return out; 706 } 707 708 static std::vector<std::pair<uint32_t, interface_var>> CollectInterfaceByInputAttachmentIndex( 709 shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 710 std::vector<std::pair<uint32_t, interface_var>> out; 711 712 for (auto insn : *src) { 713 if (insn.opcode() == spv::OpDecorate) { 714 if (insn.word(2) == spv::DecorationInputAttachmentIndex) { 715 auto attachment_index = insn.word(3); 716 auto id = insn.word(1); 717 718 if (accessible_ids.count(id)) { 719 auto def = src->get_def(id); 720 assert(def != src->end()); 721 722 if (def.opcode() == spv::OpVariable && insn.word(3) == spv::StorageClassUniformConstant) { 723 auto num_locations = GetLocationsConsumedByType(src, def.word(1), false); 724 for (unsigned int offset = 0; offset < num_locations; offset++) { 725 interface_var v = {}; 726 v.id = id; 727 v.type_id = def.word(1); 728 v.offset = offset; 729 out.emplace_back(attachment_index + offset, v); 730 } 731 } 732 } 733 } 734 } 735 } 736 737 return out; 738 } 739 740 static bool IsWritableDescriptorType(shader_module const *module, uint32_t type_id, bool is_storage_buffer) { 741 auto type = module->get_def(type_id); 742 743 // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension. 744 while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer || type.opcode() == spv::OpTypeRuntimeArray) { 745 if (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypeRuntimeArray) { 746 type = module->get_def(type.word(2)); // Element type 747 } else { 748 type = module->get_def(type.word(3)); // Pointee type 749 } 750 } 751 752 switch (type.opcode()) { 753 case spv::OpTypeImage: { 754 auto dim = type.word(3); 755 auto sampled = type.word(7); 756 return sampled == 2 && dim != spv::DimSubpassData; 757 } 758 759 case spv::OpTypeStruct: { 760 std::unordered_set<unsigned> nonwritable_members; 761 for (auto insn : *module) { 762 if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 763 if (insn.word(2) == spv::DecorationBufferBlock) { 764 // Legacy storage block in the Uniform storage class 765 // has its struct type decorated with BufferBlock. 766 is_storage_buffer = true; 767 } 768 } else if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1) && 769 insn.word(3) == spv::DecorationNonWritable) { 770 nonwritable_members.insert(insn.word(2)); 771 } 772 } 773 774 // A buffer is writable if it's either flavor of storage buffer, and has any member not decorated 775 // as nonwritable. 776 return is_storage_buffer && nonwritable_members.size() != type.len() - 2; 777 } 778 } 779 780 return false; 781 } 782 783 static std::vector<std::pair<descriptor_slot_t, interface_var>> CollectInterfaceByDescriptorSlot( 784 debug_report_data const *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids, 785 bool *has_writable_descriptor) { 786 std::unordered_map<unsigned, unsigned> var_sets; 787 std::unordered_map<unsigned, unsigned> var_bindings; 788 std::unordered_map<unsigned, unsigned> var_nonwritable; 789 790 for (auto insn : *src) { 791 // All variables in the Uniform or UniformConstant storage classes are required to be decorated with both 792 // DecorationDescriptorSet and DecorationBinding. 793 if (insn.opcode() == spv::OpDecorate) { 794 if (insn.word(2) == spv::DecorationDescriptorSet) { 795 var_sets[insn.word(1)] = insn.word(3); 796 } 797 798 if (insn.word(2) == spv::DecorationBinding) { 799 var_bindings[insn.word(1)] = insn.word(3); 800 } 801 802 // Note: do toplevel DecorationNonWritable out here; it applies to 803 // the OpVariable rather than the type. 804 if (insn.word(2) == spv::DecorationNonWritable) { 805 var_nonwritable[insn.word(1)] = 1; 806 } 807 } 808 } 809 810 std::vector<std::pair<descriptor_slot_t, interface_var>> out; 811 812 for (auto id : accessible_ids) { 813 auto insn = src->get_def(id); 814 assert(insn != src->end()); 815 816 if (insn.opcode() == spv::OpVariable && 817 (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant || 818 insn.word(3) == spv::StorageClassStorageBuffer)) { 819 unsigned set = ValueOrDefault(var_sets, insn.word(2), 0); 820 unsigned binding = ValueOrDefault(var_bindings, insn.word(2), 0); 821 822 interface_var v = {}; 823 v.id = insn.word(2); 824 v.type_id = insn.word(1); 825 out.emplace_back(std::make_pair(set, binding), v); 826 827 if (var_nonwritable.find(id) == var_nonwritable.end() && 828 IsWritableDescriptorType(src, insn.word(1), insn.word(3) == spv::StorageClassStorageBuffer)) { 829 *has_writable_descriptor = true; 830 } 831 } 832 } 833 834 return out; 835 } 836 837 static bool ValidateViConsistency(debug_report_data const *report_data, VkPipelineVertexInputStateCreateInfo const *vi) { 838 // Walk the binding descriptions, which describe the step rate and stride of each vertex buffer. Each binding should 839 // be specified only once. 840 std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings; 841 bool skip = false; 842 843 for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) { 844 auto desc = &vi->pVertexBindingDescriptions[i]; 845 auto &binding = bindings[desc->binding]; 846 if (binding) { 847 // TODO: "VUID-VkGraphicsPipelineCreateInfo-pStages-00742" perhaps? 848 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 849 kVUID_Core_Shader_InconsistentVi, "Duplicate vertex input binding descriptions for binding %d", 850 desc->binding); 851 } else { 852 binding = desc; 853 } 854 } 855 856 return skip; 857 } 858 859 static bool ValidateViAgainstVsInputs(debug_report_data const *report_data, VkPipelineVertexInputStateCreateInfo const *vi, 860 shader_module const *vs, spirv_inst_iter entrypoint) { 861 bool skip = false; 862 863 auto inputs = CollectInterfaceByLocation(vs, entrypoint, spv::StorageClassInput, false); 864 865 // Build index by location 866 std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs; 867 if (vi) { 868 for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) { 869 auto num_locations = GetLocationsConsumedByFormat(vi->pVertexAttributeDescriptions[i].format); 870 for (auto j = 0u; j < num_locations; j++) { 871 attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i]; 872 } 873 } 874 } 875 876 auto it_a = attribs.begin(); 877 auto it_b = inputs.begin(); 878 bool used = false; 879 880 while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) { 881 bool a_at_end = attribs.size() == 0 || it_a == attribs.end(); 882 bool b_at_end = inputs.size() == 0 || it_b == inputs.end(); 883 auto a_first = a_at_end ? 0 : it_a->first; 884 auto b_first = b_at_end ? 0 : it_b->first.first; 885 886 if (!a_at_end && (b_at_end || a_first < b_first)) { 887 if (!used && 888 log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 889 HandleToUint64(vs->vk_shader_module), kVUID_Core_Shader_OutputNotConsumed, 890 "Vertex attribute at location %d not consumed by vertex shader", a_first)) { 891 skip = true; 892 } 893 used = false; 894 it_a++; 895 } else if (!b_at_end && (a_at_end || b_first < a_first)) { 896 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 897 HandleToUint64(vs->vk_shader_module), kVUID_Core_Shader_InputNotProduced, 898 "Vertex shader consumes input at location %d but not provided", b_first); 899 it_b++; 900 } else { 901 unsigned attrib_type = GetFormatType(it_a->second->format); 902 unsigned input_type = GetFundamentalType(vs, it_b->second.type_id); 903 904 // Type checking 905 if (!(attrib_type & input_type)) { 906 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 907 HandleToUint64(vs->vk_shader_module), kVUID_Core_Shader_InterfaceTypeMismatch, 908 "Attribute type of `%s` at location %d does not match vertex shader input type of `%s`", 909 string_VkFormat(it_a->second->format), a_first, DescribeType(vs, it_b->second.type_id).c_str()); 910 } 911 912 // OK! 913 used = true; 914 it_b++; 915 } 916 } 917 918 return skip; 919 } 920 921 static bool ValidateFsOutputsAgainstRenderPass(debug_report_data const *report_data, shader_module const *fs, 922 spirv_inst_iter entrypoint, PIPELINE_STATE const *pipeline, uint32_t subpass_index) { 923 auto rpci = pipeline->rp_state->createInfo.ptr(); 924 925 std::map<uint32_t, VkFormat> color_attachments; 926 auto subpass = rpci->pSubpasses[subpass_index]; 927 for (auto i = 0u; i < subpass.colorAttachmentCount; ++i) { 928 uint32_t attachment = subpass.pColorAttachments[i].attachment; 929 if (attachment == VK_ATTACHMENT_UNUSED) continue; 930 if (rpci->pAttachments[attachment].format != VK_FORMAT_UNDEFINED) { 931 color_attachments[i] = rpci->pAttachments[attachment].format; 932 } 933 } 934 935 bool skip = false; 936 937 // TODO: dual source blend index (spv::DecIndex, zero if not provided) 938 939 auto outputs = CollectInterfaceByLocation(fs, entrypoint, spv::StorageClassOutput, false); 940 941 auto it_a = outputs.begin(); 942 auto it_b = color_attachments.begin(); 943 bool used = false; 944 bool alphaToCoverageEnabled = pipeline->graphicsPipelineCI.pMultisampleState != NULL && 945 pipeline->graphicsPipelineCI.pMultisampleState->alphaToCoverageEnable == VK_TRUE; 946 bool locationZeroHasAlpha = false; 947 948 // Walk attachment list and outputs together 949 950 while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) { 951 bool a_at_end = outputs.size() == 0 || it_a == outputs.end(); 952 bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end(); 953 954 if (!a_at_end && it_a->first.first == 0 && fs->get_def(it_a->second.type_id) != fs->end() && 955 GetComponentsConsumedByType(fs, it_a->second.type_id, false) == 4) 956 locationZeroHasAlpha = true; 957 958 if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) { 959 if (!alphaToCoverageEnabled || it_a->first.first != 0) { 960 skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 961 HandleToUint64(fs->vk_shader_module), kVUID_Core_Shader_OutputNotConsumed, 962 "fragment shader writes to output location %d with no matching attachment", it_a->first.first); 963 } 964 it_a++; 965 } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) { 966 // Only complain if there are unmasked channels for this attachment. If the writemask is 0, it's acceptable for the 967 // shader to not produce a matching output. 968 if (!used) { 969 if (pipeline->attachments[it_b->first].colorWriteMask != 0) { 970 skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 971 HandleToUint64(fs->vk_shader_module), kVUID_Core_Shader_InputNotProduced, 972 "Attachment %d not written by fragment shader; undefined values will be written to attachment", 973 it_b->first); 974 } 975 } 976 used = false; 977 it_b++; 978 } else { 979 unsigned output_type = GetFundamentalType(fs, it_a->second.type_id); 980 unsigned att_type = GetFormatType(it_b->second); 981 982 // Type checking 983 if (!(output_type & att_type)) { 984 skip |= log_msg( 985 report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 986 HandleToUint64(fs->vk_shader_module), kVUID_Core_Shader_InterfaceTypeMismatch, 987 "Attachment %d of type `%s` does not match fragment shader output type of `%s`; resulting values are undefined", 988 it_b->first, string_VkFormat(it_b->second), DescribeType(fs, it_a->second.type_id).c_str()); 989 } 990 991 // OK! 992 it_a++; 993 used = true; 994 } 995 } 996 997 if (alphaToCoverageEnabled && !locationZeroHasAlpha) { 998 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 999 HandleToUint64(fs->vk_shader_module), kVUID_Core_Shader_NoAlphaAtLocation0WithAlphaToCoverage, 1000 "fragment shader doesn't declare alpha output at location 0 even though alpha to coverage is enabled."); 1001 } 1002 1003 return skip; 1004 } 1005 1006 // For PointSize analysis we need to know if the variable decorated with the PointSize built-in was actually written to. 1007 // This function examines instructions in the static call tree for a write to this variable. 1008 static bool IsPointSizeWritten(shader_module const *src, spirv_inst_iter builtin_instr, spirv_inst_iter entrypoint) { 1009 auto type = builtin_instr.opcode(); 1010 uint32_t target_id = builtin_instr.word(1); 1011 bool init_complete = false; 1012 1013 if (type == spv::OpMemberDecorate) { 1014 // Built-in is part of a structure -- examine instructions up to first function body to get initial IDs 1015 auto insn = entrypoint; 1016 while (!init_complete && (insn.opcode() != spv::OpFunction)) { 1017 switch (insn.opcode()) { 1018 case spv::OpTypePointer: 1019 if ((insn.word(3) == target_id) && (insn.word(2) == spv::StorageClassOutput)) { 1020 target_id = insn.word(1); 1021 } 1022 break; 1023 case spv::OpVariable: 1024 if (insn.word(1) == target_id) { 1025 target_id = insn.word(2); 1026 init_complete = true; 1027 } 1028 break; 1029 } 1030 insn++; 1031 } 1032 } 1033 1034 if (!init_complete && (type == spv::OpMemberDecorate)) return false; 1035 1036 bool found_write = false; 1037 std::unordered_set<uint32_t> worklist; 1038 worklist.insert(entrypoint.word(2)); 1039 1040 // Follow instructions in call graph looking for writes to target 1041 while (!worklist.empty() && !found_write) { 1042 auto id_iter = worklist.begin(); 1043 auto id = *id_iter; 1044 worklist.erase(id_iter); 1045 1046 auto insn = src->get_def(id); 1047 if (insn == src->end()) { 1048 continue; 1049 } 1050 1051 if (insn.opcode() == spv::OpFunction) { 1052 // Scan body of function looking for other function calls or items in our ID chain 1053 while (++insn, insn.opcode() != spv::OpFunctionEnd) { 1054 switch (insn.opcode()) { 1055 case spv::OpAccessChain: 1056 if (insn.word(3) == target_id) { 1057 if (type == spv::OpMemberDecorate) { 1058 auto value = GetConstantValue(src, insn.word(4)); 1059 if (value == builtin_instr.word(2)) { 1060 target_id = insn.word(2); 1061 } 1062 } else { 1063 target_id = insn.word(2); 1064 } 1065 } 1066 break; 1067 case spv::OpStore: 1068 if (insn.word(1) == target_id) { 1069 found_write = true; 1070 } 1071 break; 1072 case spv::OpFunctionCall: 1073 worklist.insert(insn.word(3)); 1074 break; 1075 } 1076 } 1077 } 1078 } 1079 return found_write; 1080 } 1081 1082 // For some analyses, we need to know about all ids referenced by the static call tree of a particular entrypoint. This is 1083 // important for identifying the set of shader resources actually used by an entrypoint, for example. 1084 // Note: we only explore parts of the image which might actually contain ids we care about for the above analyses. 1085 // - NOT the shader input/output interfaces. 1086 // 1087 // TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth 1088 // converting parts of this to be generated from the machine-readable spec instead. 1089 static std::unordered_set<uint32_t> MarkAccessibleIds(shader_module const *src, spirv_inst_iter entrypoint) { 1090 std::unordered_set<uint32_t> ids; 1091 std::unordered_set<uint32_t> worklist; 1092 worklist.insert(entrypoint.word(2)); 1093 1094 while (!worklist.empty()) { 1095 auto id_iter = worklist.begin(); 1096 auto id = *id_iter; 1097 worklist.erase(id_iter); 1098 1099 auto insn = src->get_def(id); 1100 if (insn == src->end()) { 1101 // ID is something we didn't collect in BuildDefIndex. that's OK -- we'll stumble across all kinds of things here 1102 // that we may not care about. 1103 continue; 1104 } 1105 1106 // Try to add to the output set 1107 if (!ids.insert(id).second) { 1108 continue; // If we already saw this id, we don't want to walk it again. 1109 } 1110 1111 switch (insn.opcode()) { 1112 case spv::OpFunction: 1113 // Scan whole body of the function, enlisting anything interesting 1114 while (++insn, insn.opcode() != spv::OpFunctionEnd) { 1115 switch (insn.opcode()) { 1116 case spv::OpLoad: 1117 case spv::OpAtomicLoad: 1118 case spv::OpAtomicExchange: 1119 case spv::OpAtomicCompareExchange: 1120 case spv::OpAtomicCompareExchangeWeak: 1121 case spv::OpAtomicIIncrement: 1122 case spv::OpAtomicIDecrement: 1123 case spv::OpAtomicIAdd: 1124 case spv::OpAtomicISub: 1125 case spv::OpAtomicSMin: 1126 case spv::OpAtomicUMin: 1127 case spv::OpAtomicSMax: 1128 case spv::OpAtomicUMax: 1129 case spv::OpAtomicAnd: 1130 case spv::OpAtomicOr: 1131 case spv::OpAtomicXor: 1132 worklist.insert(insn.word(3)); // ptr 1133 break; 1134 case spv::OpStore: 1135 case spv::OpAtomicStore: 1136 worklist.insert(insn.word(1)); // ptr 1137 break; 1138 case spv::OpAccessChain: 1139 case spv::OpInBoundsAccessChain: 1140 worklist.insert(insn.word(3)); // base ptr 1141 break; 1142 case spv::OpSampledImage: 1143 case spv::OpImageSampleImplicitLod: 1144 case spv::OpImageSampleExplicitLod: 1145 case spv::OpImageSampleDrefImplicitLod: 1146 case spv::OpImageSampleDrefExplicitLod: 1147 case spv::OpImageSampleProjImplicitLod: 1148 case spv::OpImageSampleProjExplicitLod: 1149 case spv::OpImageSampleProjDrefImplicitLod: 1150 case spv::OpImageSampleProjDrefExplicitLod: 1151 case spv::OpImageFetch: 1152 case spv::OpImageGather: 1153 case spv::OpImageDrefGather: 1154 case spv::OpImageRead: 1155 case spv::OpImage: 1156 case spv::OpImageQueryFormat: 1157 case spv::OpImageQueryOrder: 1158 case spv::OpImageQuerySizeLod: 1159 case spv::OpImageQuerySize: 1160 case spv::OpImageQueryLod: 1161 case spv::OpImageQueryLevels: 1162 case spv::OpImageQuerySamples: 1163 case spv::OpImageSparseSampleImplicitLod: 1164 case spv::OpImageSparseSampleExplicitLod: 1165 case spv::OpImageSparseSampleDrefImplicitLod: 1166 case spv::OpImageSparseSampleDrefExplicitLod: 1167 case spv::OpImageSparseSampleProjImplicitLod: 1168 case spv::OpImageSparseSampleProjExplicitLod: 1169 case spv::OpImageSparseSampleProjDrefImplicitLod: 1170 case spv::OpImageSparseSampleProjDrefExplicitLod: 1171 case spv::OpImageSparseFetch: 1172 case spv::OpImageSparseGather: 1173 case spv::OpImageSparseDrefGather: 1174 case spv::OpImageTexelPointer: 1175 worklist.insert(insn.word(3)); // Image or sampled image 1176 break; 1177 case spv::OpImageWrite: 1178 worklist.insert(insn.word(1)); // Image -- different operand order to above 1179 break; 1180 case spv::OpFunctionCall: 1181 for (uint32_t i = 3; i < insn.len(); i++) { 1182 worklist.insert(insn.word(i)); // fn itself, and all args 1183 } 1184 break; 1185 1186 case spv::OpExtInst: 1187 for (uint32_t i = 5; i < insn.len(); i++) { 1188 worklist.insert(insn.word(i)); // Operands to ext inst 1189 } 1190 break; 1191 } 1192 } 1193 break; 1194 } 1195 } 1196 1197 return ids; 1198 } 1199 1200 static bool ValidatePushConstantBlockAgainstPipeline(debug_report_data const *report_data, 1201 std::vector<VkPushConstantRange> const *push_constant_ranges, 1202 shader_module const *src, spirv_inst_iter type, VkShaderStageFlagBits stage) { 1203 bool skip = false; 1204 1205 // Strip off ptrs etc 1206 type = GetStructType(src, type, false); 1207 assert(type != src->end()); 1208 1209 // Validate directly off the offsets. this isn't quite correct for arrays and matrices, but is a good first step. 1210 // TODO: arrays, matrices, weird sizes 1211 for (auto insn : *src) { 1212 if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 1213 if (insn.word(3) == spv::DecorationOffset) { 1214 unsigned offset = insn.word(4); 1215 auto size = 4; // Bytes; TODO: calculate this based on the type 1216 1217 bool found_range = false; 1218 for (auto const &range : *push_constant_ranges) { 1219 if (range.offset <= offset && range.offset + range.size >= offset + size) { 1220 found_range = true; 1221 1222 if ((range.stageFlags & stage) == 0) { 1223 skip |= 1224 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 1225 kVUID_Core_Shader_PushConstantNotAccessibleFromStage, 1226 "Push constant range covering variable starting at offset %u not accessible from stage %s", 1227 offset, string_VkShaderStageFlagBits(stage)); 1228 } 1229 1230 break; 1231 } 1232 } 1233 1234 if (!found_range) { 1235 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 1236 kVUID_Core_Shader_PushConstantOutOfRange, 1237 "Push constant range covering variable starting at offset %u not declared in layout", offset); 1238 } 1239 } 1240 } 1241 } 1242 1243 return skip; 1244 } 1245 1246 static bool ValidatePushConstantUsage(debug_report_data const *report_data, 1247 std::vector<VkPushConstantRange> const *push_constant_ranges, shader_module const *src, 1248 std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) { 1249 bool skip = false; 1250 1251 for (auto id : accessible_ids) { 1252 auto def_insn = src->get_def(id); 1253 if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) { 1254 skip |= ValidatePushConstantBlockAgainstPipeline(report_data, push_constant_ranges, src, src->get_def(def_insn.word(1)), 1255 stage); 1256 } 1257 } 1258 1259 return skip; 1260 } 1261 1262 // Validate that data for each specialization entry is fully contained within the buffer. 1263 static bool ValidateSpecializationOffsets(debug_report_data const *report_data, VkPipelineShaderStageCreateInfo const *info) { 1264 bool skip = false; 1265 1266 VkSpecializationInfo const *spec = info->pSpecializationInfo; 1267 1268 if (spec) { 1269 for (auto i = 0u; i < spec->mapEntryCount; i++) { 1270 // TODO: This is a good place for "VUID-VkSpecializationInfo-offset-00773". 1271 if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) { 1272 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, 1273 "VUID-VkSpecializationInfo-pMapEntries-00774", 1274 "Specialization entry %u (for constant id %u) references memory outside provided specialization " 1275 "data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER " bytes provided)..", 1276 i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset, 1277 spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize); 1278 } 1279 } 1280 } 1281 1282 return skip; 1283 } 1284 1285 // TODO (jbolz): Can this return a const reference? 1286 static std::set<uint32_t> TypeToDescriptorTypeSet(shader_module const *module, uint32_t type_id, unsigned &descriptor_count) { 1287 auto type = module->get_def(type_id); 1288 bool is_storage_buffer = false; 1289 descriptor_count = 1; 1290 std::set<uint32_t> ret; 1291 1292 // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension. 1293 while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer || type.opcode() == spv::OpTypeRuntimeArray) { 1294 if (type.opcode() == spv::OpTypeRuntimeArray) { 1295 descriptor_count = 0; 1296 type = module->get_def(type.word(2)); 1297 } else if (type.opcode() == spv::OpTypeArray) { 1298 descriptor_count *= GetConstantValue(module, type.word(3)); 1299 type = module->get_def(type.word(2)); 1300 } else { 1301 if (type.word(2) == spv::StorageClassStorageBuffer) { 1302 is_storage_buffer = true; 1303 } 1304 type = module->get_def(type.word(3)); 1305 } 1306 } 1307 1308 switch (type.opcode()) { 1309 case spv::OpTypeStruct: { 1310 for (auto insn : *module) { 1311 if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 1312 if (insn.word(2) == spv::DecorationBlock) { 1313 if (is_storage_buffer) { 1314 ret.insert(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 1315 ret.insert(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); 1316 return ret; 1317 } else { 1318 ret.insert(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); 1319 ret.insert(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); 1320 ret.insert(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT); 1321 return ret; 1322 } 1323 } else if (insn.word(2) == spv::DecorationBufferBlock) { 1324 ret.insert(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 1325 ret.insert(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); 1326 return ret; 1327 } 1328 } 1329 } 1330 1331 // Invalid 1332 return ret; 1333 } 1334 1335 case spv::OpTypeSampler: 1336 ret.insert(VK_DESCRIPTOR_TYPE_SAMPLER); 1337 ret.insert(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 1338 return ret; 1339 1340 case spv::OpTypeSampledImage: { 1341 // Slight relaxation for some GLSL historical madness: samplerBuffer doesn't really have a sampler, and a texel 1342 // buffer descriptor doesn't really provide one. Allow this slight mismatch. 1343 auto image_type = module->get_def(type.word(2)); 1344 auto dim = image_type.word(3); 1345 auto sampled = image_type.word(7); 1346 if (dim == spv::DimBuffer && sampled == 1) { 1347 ret.insert(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); 1348 return ret; 1349 } 1350 } 1351 ret.insert(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 1352 return ret; 1353 1354 case spv::OpTypeImage: { 1355 // Many descriptor types backing image types-- depends on dimension and whether the image will be used with a sampler. 1356 // SPIRV for Vulkan requires that sampled be 1 or 2 -- leaving the decision to runtime is unacceptable. 1357 auto dim = type.word(3); 1358 auto sampled = type.word(7); 1359 1360 if (dim == spv::DimSubpassData) { 1361 ret.insert(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); 1362 return ret; 1363 } else if (dim == spv::DimBuffer) { 1364 if (sampled == 1) { 1365 ret.insert(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); 1366 return ret; 1367 } else { 1368 ret.insert(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); 1369 return ret; 1370 } 1371 } else if (sampled == 1) { 1372 ret.insert(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); 1373 ret.insert(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 1374 return ret; 1375 } else { 1376 ret.insert(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 1377 return ret; 1378 } 1379 } 1380 case spv::OpTypeAccelerationStructureNV: 1381 ret.insert(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV); 1382 return ret; 1383 1384 // We shouldn't really see any other junk types -- but if we do, they're a mismatch. 1385 default: 1386 return ret; // Matches nothing 1387 } 1388 } 1389 1390 static std::string string_descriptorTypes(const std::set<uint32_t> &descriptor_types) { 1391 std::stringstream ss; 1392 for (auto it = descriptor_types.begin(); it != descriptor_types.end(); ++it) { 1393 if (ss.tellp()) ss << ", "; 1394 ss << string_VkDescriptorType(VkDescriptorType(*it)); 1395 } 1396 return ss.str(); 1397 } 1398 1399 static bool RequireFeature(debug_report_data const *report_data, VkBool32 feature, char const *feature_name) { 1400 if (!feature) { 1401 if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 1402 kVUID_Core_Shader_FeatureNotEnabled, "Shader requires %s but is not enabled on the device", feature_name)) { 1403 return true; 1404 } 1405 } 1406 1407 return false; 1408 } 1409 1410 static bool RequireExtension(debug_report_data const *report_data, bool extension, char const *extension_name) { 1411 if (!extension) { 1412 if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 1413 kVUID_Core_Shader_FeatureNotEnabled, "Shader requires extension %s but is not enabled on the device", 1414 extension_name)) { 1415 return true; 1416 } 1417 } 1418 1419 return false; 1420 } 1421 1422 bool CoreChecks::ValidateShaderCapabilities(layer_data *dev_data, shader_module const *src, VkShaderStageFlagBits stage, 1423 bool has_writable_descriptor) { 1424 bool skip = false; 1425 1426 auto const &features = GetEnabledFeatures(); 1427 auto const &extensions = GetDeviceExtensions(); 1428 1429 struct FeaturePointer { 1430 // Callable object to test if this feature is enabled in the given aggregate feature struct 1431 const std::function<VkBool32(const DeviceFeatures &)> IsEnabled; 1432 1433 // Test if feature pointer is populated 1434 explicit operator bool() const { return static_cast<bool>(IsEnabled); } 1435 1436 // Default and nullptr constructor to create an empty FeaturePointer 1437 FeaturePointer() : IsEnabled(nullptr) {} 1438 FeaturePointer(std::nullptr_t ptr) : IsEnabled(nullptr) {} 1439 1440 // Constructors to populate FeaturePointer based on given pointer to member 1441 FeaturePointer(VkBool32 VkPhysicalDeviceFeatures::*ptr) 1442 : IsEnabled([=](const DeviceFeatures &features) { return features.core.*ptr; }) {} 1443 FeaturePointer(VkBool32 VkPhysicalDeviceDescriptorIndexingFeaturesEXT::*ptr) 1444 : IsEnabled([=](const DeviceFeatures &features) { return features.descriptor_indexing.*ptr; }) {} 1445 FeaturePointer(VkBool32 VkPhysicalDevice8BitStorageFeaturesKHR::*ptr) 1446 : IsEnabled([=](const DeviceFeatures &features) { return features.eight_bit_storage.*ptr; }) {} 1447 FeaturePointer(VkBool32 VkPhysicalDeviceTransformFeedbackFeaturesEXT::*ptr) 1448 : IsEnabled([=](const DeviceFeatures &features) { return features.transform_feedback_features.*ptr; }) {} 1449 FeaturePointer(VkBool32 VkPhysicalDeviceFloat16Int8FeaturesKHR::*ptr) 1450 : IsEnabled([=](const DeviceFeatures &features) { return features.float16_int8.*ptr; }) {} 1451 FeaturePointer(VkBool32 VkPhysicalDeviceScalarBlockLayoutFeaturesEXT::*ptr) 1452 : IsEnabled([=](const DeviceFeatures &features) { return features.scalar_block_layout_features.*ptr; }) {} 1453 }; 1454 1455 struct CapabilityInfo { 1456 char const *name; 1457 FeaturePointer feature; 1458 bool DeviceExtensions::*extension; 1459 }; 1460 1461 // clang-format off 1462 static const std::unordered_multimap<uint32_t, CapabilityInfo> capabilities = { 1463 // Capabilities always supported by a Vulkan 1.0 implementation -- no 1464 // feature bits. 1465 {spv::CapabilityMatrix, {nullptr}}, 1466 {spv::CapabilityShader, {nullptr}}, 1467 {spv::CapabilityInputAttachment, {nullptr}}, 1468 {spv::CapabilitySampled1D, {nullptr}}, 1469 {spv::CapabilityImage1D, {nullptr}}, 1470 {spv::CapabilitySampledBuffer, {nullptr}}, 1471 {spv::CapabilityImageQuery, {nullptr}}, 1472 {spv::CapabilityDerivativeControl, {nullptr}}, 1473 1474 // Capabilities that are optionally supported, but require a feature to 1475 // be enabled on the device 1476 {spv::CapabilityGeometry, {"VkPhysicalDeviceFeatures::geometryShader", &VkPhysicalDeviceFeatures::geometryShader}}, 1477 {spv::CapabilityTessellation, {"VkPhysicalDeviceFeatures::tessellationShader", &VkPhysicalDeviceFeatures::tessellationShader}}, 1478 {spv::CapabilityFloat64, {"VkPhysicalDeviceFeatures::shaderFloat64", &VkPhysicalDeviceFeatures::shaderFloat64}}, 1479 {spv::CapabilityInt64, {"VkPhysicalDeviceFeatures::shaderInt64", &VkPhysicalDeviceFeatures::shaderInt64}}, 1480 {spv::CapabilityTessellationPointSize, {"VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize", &VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize}}, 1481 {spv::CapabilityGeometryPointSize, {"VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize", &VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize}}, 1482 {spv::CapabilityImageGatherExtended, {"VkPhysicalDeviceFeatures::shaderImageGatherExtended", &VkPhysicalDeviceFeatures::shaderImageGatherExtended}}, 1483 {spv::CapabilityStorageImageMultisample, {"VkPhysicalDeviceFeatures::shaderStorageImageMultisample", &VkPhysicalDeviceFeatures::shaderStorageImageMultisample}}, 1484 {spv::CapabilityUniformBufferArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing", &VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing}}, 1485 {spv::CapabilitySampledImageArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing", &VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing}}, 1486 {spv::CapabilityStorageBufferArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing", &VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing}}, 1487 {spv::CapabilityStorageImageArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderStorageImageArrayDynamicIndexing", &VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing}}, 1488 {spv::CapabilityClipDistance, {"VkPhysicalDeviceFeatures::shaderClipDistance", &VkPhysicalDeviceFeatures::shaderClipDistance}}, 1489 {spv::CapabilityCullDistance, {"VkPhysicalDeviceFeatures::shaderCullDistance", &VkPhysicalDeviceFeatures::shaderCullDistance}}, 1490 {spv::CapabilityImageCubeArray, {"VkPhysicalDeviceFeatures::imageCubeArray", &VkPhysicalDeviceFeatures::imageCubeArray}}, 1491 {spv::CapabilitySampleRateShading, {"VkPhysicalDeviceFeatures::sampleRateShading", &VkPhysicalDeviceFeatures::sampleRateShading}}, 1492 {spv::CapabilitySparseResidency, {"VkPhysicalDeviceFeatures::shaderResourceResidency", &VkPhysicalDeviceFeatures::shaderResourceResidency}}, 1493 {spv::CapabilityMinLod, {"VkPhysicalDeviceFeatures::shaderResourceMinLod", &VkPhysicalDeviceFeatures::shaderResourceMinLod}}, 1494 {spv::CapabilitySampledCubeArray, {"VkPhysicalDeviceFeatures::imageCubeArray", &VkPhysicalDeviceFeatures::imageCubeArray}}, 1495 {spv::CapabilityImageMSArray, {"VkPhysicalDeviceFeatures::shaderStorageImageMultisample", &VkPhysicalDeviceFeatures::shaderStorageImageMultisample}}, 1496 {spv::CapabilityStorageImageExtendedFormats, {"VkPhysicalDeviceFeatures::shaderStorageImageExtendedFormats", &VkPhysicalDeviceFeatures::shaderStorageImageExtendedFormats}}, 1497 {spv::CapabilityInterpolationFunction, {"VkPhysicalDeviceFeatures::sampleRateShading", &VkPhysicalDeviceFeatures::sampleRateShading}}, 1498 {spv::CapabilityStorageImageReadWithoutFormat, {"VkPhysicalDeviceFeatures::shaderStorageImageReadWithoutFormat", &VkPhysicalDeviceFeatures::shaderStorageImageReadWithoutFormat}}, 1499 {spv::CapabilityStorageImageWriteWithoutFormat, {"VkPhysicalDeviceFeatures::shaderStorageImageWriteWithoutFormat", &VkPhysicalDeviceFeatures::shaderStorageImageWriteWithoutFormat}}, 1500 {spv::CapabilityMultiViewport, {"VkPhysicalDeviceFeatures::multiViewport", &VkPhysicalDeviceFeatures::multiViewport}}, 1501 1502 {spv::CapabilityShaderNonUniformEXT, {VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_ext_descriptor_indexing}}, 1503 {spv::CapabilityRuntimeDescriptorArrayEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::runtimeDescriptorArray", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::runtimeDescriptorArray}}, 1504 {spv::CapabilityInputAttachmentArrayDynamicIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderInputAttachmentArrayDynamicIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderInputAttachmentArrayDynamicIndexing}}, 1505 {spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformTexelBufferArrayDynamicIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformTexelBufferArrayDynamicIndexing}}, 1506 {spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageTexelBufferArrayDynamicIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageTexelBufferArrayDynamicIndexing}}, 1507 {spv::CapabilityUniformBufferArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformBufferArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformBufferArrayNonUniformIndexing}}, 1508 {spv::CapabilitySampledImageArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderSampledImageArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderSampledImageArrayNonUniformIndexing}}, 1509 {spv::CapabilityStorageBufferArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageBufferArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageBufferArrayNonUniformIndexing}}, 1510 {spv::CapabilityStorageImageArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageImageArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageImageArrayNonUniformIndexing}}, 1511 {spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderInputAttachmentArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderInputAttachmentArrayNonUniformIndexing}}, 1512 {spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformTexelBufferArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformTexelBufferArrayNonUniformIndexing}}, 1513 {spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT , {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageTexelBufferArrayNonUniformIndexing", &VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageTexelBufferArrayNonUniformIndexing}}, 1514 1515 // Capabilities that require an extension 1516 {spv::CapabilityDrawParameters, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_khr_shader_draw_parameters}}, 1517 {spv::CapabilityGeometryShaderPassthroughNV, {VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_nv_geometry_shader_passthrough}}, 1518 {spv::CapabilitySampleMaskOverrideCoverageNV, {VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_nv_sample_mask_override_coverage}}, 1519 {spv::CapabilityShaderViewportIndexLayerEXT, {VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_ext_shader_viewport_index_layer}}, 1520 {spv::CapabilityShaderViewportIndexLayerNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_nv_viewport_array2}}, 1521 {spv::CapabilityShaderViewportMaskNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_nv_viewport_array2}}, 1522 {spv::CapabilitySubgroupBallotKHR, {VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_ext_shader_subgroup_ballot }}, 1523 {spv::CapabilitySubgroupVoteKHR, {VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_ext_shader_subgroup_vote }}, 1524 {spv::CapabilityInt64Atomics, {VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME, nullptr, &DeviceExtensions::vk_khr_shader_atomic_int64 }}, 1525 1526 {spv::CapabilityStorageBuffer8BitAccess , {"VkPhysicalDevice8BitStorageFeaturesKHR::storageBuffer8BitAccess", &VkPhysicalDevice8BitStorageFeaturesKHR::storageBuffer8BitAccess, &DeviceExtensions::vk_khr_8bit_storage}}, 1527 {spv::CapabilityUniformAndStorageBuffer8BitAccess , {"VkPhysicalDevice8BitStorageFeaturesKHR::uniformAndStorageBuffer8BitAccess", &VkPhysicalDevice8BitStorageFeaturesKHR::uniformAndStorageBuffer8BitAccess, &DeviceExtensions::vk_khr_8bit_storage}}, 1528 {spv::CapabilityStoragePushConstant8 , {"VkPhysicalDevice8BitStorageFeaturesKHR::storagePushConstant8", &VkPhysicalDevice8BitStorageFeaturesKHR::storagePushConstant8, &DeviceExtensions::vk_khr_8bit_storage}}, 1529 1530 {spv::CapabilityTransformFeedback , { "VkPhysicalDeviceTransformFeedbackFeaturesEXT::transformFeedback", &VkPhysicalDeviceTransformFeedbackFeaturesEXT::transformFeedback, &DeviceExtensions::vk_ext_transform_feedback}}, 1531 {spv::CapabilityGeometryStreams , { "VkPhysicalDeviceTransformFeedbackFeaturesEXT::geometryStreams", &VkPhysicalDeviceTransformFeedbackFeaturesEXT::geometryStreams, &DeviceExtensions::vk_ext_transform_feedback}}, 1532 1533 {spv::CapabilityFloat16 , {"VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderFloat16", &VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderFloat16, &DeviceExtensions::vk_khr_shader_float16_int8}}, 1534 {spv::CapabilityInt8 , {"VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderInt8", &VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderInt8, &DeviceExtensions::vk_khr_shader_float16_int8}}, 1535 }; 1536 // clang-format on 1537 1538 for (auto insn : *src) { 1539 if (insn.opcode() == spv::OpCapability) { 1540 size_t n = capabilities.count(insn.word(1)); 1541 if (1 == n) { // key occurs exactly once 1542 auto it = capabilities.find(insn.word(1)); 1543 if (it != capabilities.end()) { 1544 if (it->second.feature) { 1545 skip |= RequireFeature(report_data, it->second.feature.IsEnabled(*features), it->second.name); 1546 } 1547 if (it->second.extension) { 1548 skip |= RequireExtension(report_data, extensions->*(it->second.extension), it->second.name); 1549 } 1550 } 1551 } else if (1 < n) { // key occurs multiple times, at least one must be enabled 1552 bool needs_feature = false, has_feature = false; 1553 bool needs_ext = false, has_ext = false; 1554 std::string feature_names = "(one of) [ "; 1555 std::string extension_names = feature_names; 1556 auto caps = capabilities.equal_range(insn.word(1)); 1557 for (auto it = caps.first; it != caps.second; ++it) { 1558 if (it->second.feature) { 1559 needs_feature = true; 1560 has_feature = has_feature || it->second.feature.IsEnabled(*features); 1561 feature_names += it->second.name; 1562 feature_names += " "; 1563 } 1564 if (it->second.extension) { 1565 needs_ext = true; 1566 has_ext = has_ext || extensions->*(it->second.extension); 1567 extension_names += it->second.name; 1568 extension_names += " "; 1569 } 1570 } 1571 if (needs_feature) { 1572 feature_names += "]"; 1573 skip |= RequireFeature(report_data, has_feature, feature_names.c_str()); 1574 } 1575 if (needs_ext) { 1576 extension_names += "]"; 1577 skip |= RequireExtension(report_data, has_ext, extension_names.c_str()); 1578 } 1579 } 1580 } 1581 } 1582 1583 if (has_writable_descriptor) { 1584 switch (stage) { 1585 case VK_SHADER_STAGE_COMPUTE_BIT: 1586 case VK_SHADER_STAGE_RAYGEN_BIT_NV: 1587 case VK_SHADER_STAGE_ANY_HIT_BIT_NV: 1588 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV: 1589 case VK_SHADER_STAGE_MISS_BIT_NV: 1590 case VK_SHADER_STAGE_INTERSECTION_BIT_NV: 1591 case VK_SHADER_STAGE_CALLABLE_BIT_NV: 1592 case VK_SHADER_STAGE_TASK_BIT_NV: 1593 case VK_SHADER_STAGE_MESH_BIT_NV: 1594 /* No feature requirements for writes and atomics from compute 1595 * raytracing, or mesh stages */ 1596 break; 1597 case VK_SHADER_STAGE_FRAGMENT_BIT: 1598 skip |= RequireFeature(report_data, features->core.fragmentStoresAndAtomics, "fragmentStoresAndAtomics"); 1599 break; 1600 default: 1601 skip |= 1602 RequireFeature(report_data, features->core.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"); 1603 break; 1604 } 1605 } 1606 1607 return skip; 1608 } 1609 1610 static bool VariableIsBuiltIn(shader_module const *src, const uint32_t ID, std::vector<uint32_t> const &builtInBlockIDs, 1611 std::vector<uint32_t> const &builtInIDs) { 1612 auto insn = src->get_def(ID); 1613 1614 switch (insn.opcode()) { 1615 case spv::OpVariable: { 1616 // First check if the variable is a "pure" built-in type, e.g. gl_ViewportIndex 1617 uint32_t ID = insn.word(2); 1618 for (auto builtInID : builtInIDs) { 1619 if (ID == builtInID) { 1620 return true; 1621 } 1622 } 1623 1624 VariableIsBuiltIn(src, insn.word(1), builtInBlockIDs, builtInIDs); 1625 break; 1626 } 1627 case spv::OpTypePointer: 1628 VariableIsBuiltIn(src, insn.word(3), builtInBlockIDs, builtInIDs); 1629 break; 1630 case spv::OpTypeArray: 1631 VariableIsBuiltIn(src, insn.word(2), builtInBlockIDs, builtInIDs); 1632 break; 1633 case spv::OpTypeStruct: { 1634 uint32_t ID = insn.word(1); // We only need to check the first member as either all will be, or none will be built-in 1635 for (auto builtInBlockID : builtInBlockIDs) { 1636 if (ID == builtInBlockID) { 1637 return true; 1638 } 1639 } 1640 return false; 1641 } 1642 default: 1643 return false; 1644 } 1645 1646 return false; 1647 } 1648 1649 bool CoreChecks::ValidateShaderStageInputOutputLimits(layer_data *dev_data, shader_module const *src, 1650 VkPipelineShaderStageCreateInfo const *pStage, PIPELINE_STATE *pipeline) { 1651 if (pStage->stage == VK_SHADER_STAGE_COMPUTE_BIT || pStage->stage == VK_SHADER_STAGE_ALL_GRAPHICS || 1652 pStage->stage == VK_SHADER_STAGE_ALL) { 1653 return false; 1654 } 1655 1656 bool skip = false; 1657 auto const &limits = dev_data->phys_dev_props.limits; 1658 1659 std::vector<uint32_t> builtInBlockIDs; 1660 std::vector<uint32_t> builtInIDs; 1661 struct Variable { 1662 uint32_t baseTypePtrID; 1663 uint32_t ID; 1664 uint32_t storageClass; 1665 }; 1666 std::vector<Variable> variables; 1667 1668 for (auto insn : *src) { 1669 switch (insn.opcode()) { 1670 // Find all built-in member decorations 1671 case spv::OpMemberDecorate: 1672 if (insn.word(3) == spv::DecorationBuiltIn) { 1673 builtInBlockIDs.push_back(insn.word(1)); 1674 } 1675 break; 1676 // Find all built-in decorations 1677 case spv::OpDecorate: 1678 switch (insn.word(2)) { 1679 case spv::DecorationBlock: { 1680 uint32_t blockID = insn.word(1); 1681 for (auto builtInBlockID : builtInBlockIDs) { 1682 // Check if one of the members of the block are built-in -> the block is built-in 1683 if (blockID == builtInBlockID) { 1684 builtInIDs.push_back(blockID); 1685 break; 1686 } 1687 } 1688 break; 1689 } 1690 case spv::DecorationBuiltIn: 1691 builtInIDs.push_back(insn.word(1)); 1692 break; 1693 default: 1694 break; 1695 } 1696 break; 1697 // Find all input and output variables 1698 case spv::OpVariable: { 1699 Variable var = {}; 1700 var.storageClass = insn.word(3); 1701 if (var.storageClass == spv::StorageClassInput || var.storageClass == spv::StorageClassOutput) { 1702 var.baseTypePtrID = insn.word(1); 1703 var.ID = insn.word(2); 1704 variables.push_back(var); 1705 } 1706 break; 1707 } 1708 default: 1709 break; 1710 } 1711 } 1712 1713 uint32_t numCompIn = 0, numCompOut = 0; 1714 for (auto &var : variables) { 1715 // Check the variable's ID 1716 if (VariableIsBuiltIn(src, var.ID, builtInBlockIDs, builtInIDs)) { 1717 continue; 1718 } 1719 // Check the variable's type's ID - e.g. gl_PerVertex is made of basic types, not built-in types 1720 if (VariableIsBuiltIn(src, src->get_def(var.baseTypePtrID).word(3), builtInBlockIDs, builtInIDs)) { 1721 continue; 1722 } 1723 1724 if (var.storageClass == spv::StorageClassInput) { 1725 numCompIn += GetComponentsConsumedByType(src, var.baseTypePtrID, false); 1726 } else { // var.storageClass == spv::StorageClassOutput 1727 numCompOut += GetComponentsConsumedByType(src, var.baseTypePtrID, false); 1728 } 1729 } 1730 1731 switch (pStage->stage) { 1732 case VK_SHADER_STAGE_VERTEX_BIT: 1733 if (numCompOut > limits.maxVertexOutputComponents) { 1734 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1735 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1736 "Invalid Pipeline CreateInfo State: Vertex shader exceeds " 1737 "VkPhysicalDeviceLimits::maxVertexOutputComponents of %u " 1738 "components by %u components", 1739 limits.maxVertexOutputComponents, numCompOut - limits.maxVertexOutputComponents); 1740 } 1741 break; 1742 1743 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: 1744 if (numCompIn > limits.maxTessellationControlPerVertexInputComponents) { 1745 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1746 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1747 "Invalid Pipeline CreateInfo State: Tessellation control shader exceeds " 1748 "VkPhysicalDeviceLimits::maxTessellationControlPerVertexInputComponents of %u " 1749 "components by %u components", 1750 limits.maxTessellationControlPerVertexInputComponents, 1751 numCompIn - limits.maxTessellationControlPerVertexInputComponents); 1752 } 1753 if (numCompOut > limits.maxTessellationControlPerVertexOutputComponents) { 1754 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1755 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1756 "Invalid Pipeline CreateInfo State: Tessellation control shader exceeds " 1757 "VkPhysicalDeviceLimits::maxTessellationControlPerVertexOutputComponents of %u " 1758 "components by %u components", 1759 limits.maxTessellationControlPerVertexOutputComponents, 1760 numCompOut - limits.maxTessellationControlPerVertexOutputComponents); 1761 } 1762 break; 1763 1764 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: 1765 if (numCompIn > limits.maxTessellationEvaluationInputComponents) { 1766 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1767 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1768 "Invalid Pipeline CreateInfo State: Tessellation evaluation shader exceeds " 1769 "VkPhysicalDeviceLimits::maxTessellationEvaluationInputComponents of %u " 1770 "components by %u components", 1771 limits.maxTessellationEvaluationInputComponents, 1772 numCompIn - limits.maxTessellationEvaluationInputComponents); 1773 } 1774 if (numCompOut > limits.maxTessellationEvaluationOutputComponents) { 1775 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1776 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1777 "Invalid Pipeline CreateInfo State: Tessellation evaluation shader exceeds " 1778 "VkPhysicalDeviceLimits::maxTessellationEvaluationOutputComponents of %u " 1779 "components by %u components", 1780 limits.maxTessellationEvaluationOutputComponents, 1781 numCompOut - limits.maxTessellationEvaluationOutputComponents); 1782 } 1783 break; 1784 1785 case VK_SHADER_STAGE_GEOMETRY_BIT: 1786 if (numCompIn > limits.maxGeometryInputComponents) { 1787 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1788 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1789 "Invalid Pipeline CreateInfo State: Geometry shader exceeds " 1790 "VkPhysicalDeviceLimits::maxGeometryInputComponents of %u " 1791 "components by %u components", 1792 limits.maxGeometryInputComponents, numCompIn - limits.maxGeometryInputComponents); 1793 } 1794 if (numCompOut > limits.maxGeometryOutputComponents) { 1795 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1796 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1797 "Invalid Pipeline CreateInfo State: Geometry shader exceeds " 1798 "VkPhysicalDeviceLimits::maxGeometryOutputComponents of %u " 1799 "components by %u components", 1800 limits.maxGeometryOutputComponents, numCompOut - limits.maxGeometryOutputComponents); 1801 } 1802 break; 1803 1804 case VK_SHADER_STAGE_FRAGMENT_BIT: 1805 if (numCompIn > limits.maxFragmentInputComponents) { 1806 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1807 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_ExceedDeviceLimit, 1808 "Invalid Pipeline CreateInfo State: Fragment shader exceeds " 1809 "VkPhysicalDeviceLimits::maxFragmentInputComponents of %u " 1810 "components by %u components", 1811 limits.maxFragmentInputComponents, numCompIn - limits.maxFragmentInputComponents); 1812 } 1813 break; 1814 1815 case VK_SHADER_STAGE_RAYGEN_BIT_NV: 1816 case VK_SHADER_STAGE_ANY_HIT_BIT_NV: 1817 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV: 1818 case VK_SHADER_STAGE_MISS_BIT_NV: 1819 case VK_SHADER_STAGE_INTERSECTION_BIT_NV: 1820 case VK_SHADER_STAGE_CALLABLE_BIT_NV: 1821 case VK_SHADER_STAGE_TASK_BIT_NV: 1822 case VK_SHADER_STAGE_MESH_BIT_NV: 1823 break; 1824 1825 default: 1826 assert(false); // This should never happen 1827 } 1828 return skip; 1829 } 1830 1831 uint32_t DescriptorTypeToReqs(shader_module const *module, uint32_t type_id) { 1832 auto type = module->get_def(type_id); 1833 1834 while (true) { 1835 switch (type.opcode()) { 1836 case spv::OpTypeArray: 1837 case spv::OpTypeRuntimeArray: 1838 case spv::OpTypeSampledImage: 1839 type = module->get_def(type.word(2)); 1840 break; 1841 case spv::OpTypePointer: 1842 type = module->get_def(type.word(3)); 1843 break; 1844 case spv::OpTypeImage: { 1845 auto dim = type.word(3); 1846 auto arrayed = type.word(5); 1847 auto msaa = type.word(6); 1848 1849 uint32_t bits = 0; 1850 switch (GetFundamentalType(module, type.word(2))) { 1851 case FORMAT_TYPE_FLOAT: 1852 bits = DESCRIPTOR_REQ_COMPONENT_TYPE_FLOAT; 1853 break; 1854 case FORMAT_TYPE_UINT: 1855 bits = DESCRIPTOR_REQ_COMPONENT_TYPE_UINT; 1856 break; 1857 case FORMAT_TYPE_SINT: 1858 bits = DESCRIPTOR_REQ_COMPONENT_TYPE_SINT; 1859 break; 1860 default: 1861 break; 1862 } 1863 1864 switch (dim) { 1865 case spv::Dim1D: 1866 bits |= arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_1D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_1D; 1867 return bits; 1868 case spv::Dim2D: 1869 bits |= msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE; 1870 bits |= arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_2D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_2D; 1871 return bits; 1872 case spv::Dim3D: 1873 bits |= DESCRIPTOR_REQ_VIEW_TYPE_3D; 1874 return bits; 1875 case spv::DimCube: 1876 bits |= arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_CUBE_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_CUBE; 1877 return bits; 1878 case spv::DimSubpassData: 1879 bits |= msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE; 1880 return bits; 1881 default: // buffer, etc. 1882 return bits; 1883 } 1884 } 1885 default: 1886 return 0; 1887 } 1888 } 1889 } 1890 1891 // For given pipelineLayout verify that the set_layout_node at slot.first 1892 // has the requested binding at slot.second and return ptr to that binding 1893 static VkDescriptorSetLayoutBinding const *GetDescriptorBinding(PIPELINE_LAYOUT_NODE const *pipelineLayout, 1894 descriptor_slot_t slot) { 1895 if (!pipelineLayout) return nullptr; 1896 1897 if (slot.first >= pipelineLayout->set_layouts.size()) return nullptr; 1898 1899 return pipelineLayout->set_layouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second); 1900 } 1901 1902 static void ProcessExecutionModes(shader_module const *src, spirv_inst_iter entrypoint, PIPELINE_STATE *pipeline) { 1903 auto entrypoint_id = entrypoint.word(2); 1904 bool is_point_mode = false; 1905 1906 for (auto insn : *src) { 1907 if (insn.opcode() == spv::OpExecutionMode && insn.word(1) == entrypoint_id) { 1908 switch (insn.word(2)) { 1909 case spv::ExecutionModePointMode: 1910 // In tessellation shaders, PointMode is separate and trumps the tessellation topology. 1911 is_point_mode = true; 1912 break; 1913 1914 case spv::ExecutionModeOutputPoints: 1915 pipeline->topology_at_rasterizer = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; 1916 break; 1917 1918 case spv::ExecutionModeIsolines: 1919 case spv::ExecutionModeOutputLineStrip: 1920 pipeline->topology_at_rasterizer = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; 1921 break; 1922 1923 case spv::ExecutionModeTriangles: 1924 case spv::ExecutionModeQuads: 1925 case spv::ExecutionModeOutputTriangleStrip: 1926 pipeline->topology_at_rasterizer = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 1927 break; 1928 } 1929 } 1930 } 1931 1932 if (is_point_mode) pipeline->topology_at_rasterizer = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; 1933 } 1934 1935 // If PointList topology is specified in the pipeline, verify that a shader geometry stage writes PointSize 1936 // o If there is only a vertex shader : gl_PointSize must be written when using points 1937 // o If there is a geometry or tessellation shader: 1938 // - If shaderTessellationAndGeometryPointSize feature is enabled: 1939 // * gl_PointSize must be written in the final geometry stage 1940 // - If shaderTessellationAndGeometryPointSize feature is disabled: 1941 // * gl_PointSize must NOT be written and a default of 1.0 is assumed 1942 bool CoreChecks::ValidatePointListShaderState(const layer_data *dev_data, const PIPELINE_STATE *pipeline, shader_module const *src, 1943 spirv_inst_iter entrypoint, VkShaderStageFlagBits stage) { 1944 if (pipeline->topology_at_rasterizer != VK_PRIMITIVE_TOPOLOGY_POINT_LIST) { 1945 return false; 1946 } 1947 1948 bool pointsize_written = false; 1949 bool skip = false; 1950 1951 // Search for PointSize built-in decorations 1952 std::vector<uint32_t> pointsize_builtin_offsets; 1953 spirv_inst_iter insn = entrypoint; 1954 while (!pointsize_written && (insn.opcode() != spv::OpFunction)) { 1955 if (insn.opcode() == spv::OpMemberDecorate) { 1956 if (insn.word(3) == spv::DecorationBuiltIn) { 1957 if (insn.word(4) == spv::BuiltInPointSize) { 1958 pointsize_written = IsPointSizeWritten(src, insn, entrypoint); 1959 } 1960 } 1961 } else if (insn.opcode() == spv::OpDecorate) { 1962 if (insn.word(2) == spv::DecorationBuiltIn) { 1963 if (insn.word(3) == spv::BuiltInPointSize) { 1964 pointsize_written = IsPointSizeWritten(src, insn, entrypoint); 1965 } 1966 } 1967 } 1968 1969 insn++; 1970 } 1971 1972 if ((stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT || stage == VK_SHADER_STAGE_GEOMETRY_BIT) && 1973 !GetEnabledFeatures()->core.shaderTessellationAndGeometryPointSize) { 1974 if (pointsize_written) { 1975 skip |= log_msg(GetReportData(), VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1976 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_PointSizeBuiltInOverSpecified, 1977 "Pipeline topology is set to POINT_LIST and geometry or tessellation shaders write PointSize which " 1978 "is prohibited when the shaderTessellationAndGeometryPointSize feature is not enabled."); 1979 } 1980 } else if (!pointsize_written) { 1981 skip |= 1982 log_msg(GetReportData(), VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1983 HandleToUint64(pipeline->pipeline), kVUID_Core_Shader_MissingPointSizeBuiltIn, 1984 "Pipeline topology is set to POINT_LIST, but PointSize is not written to in the shader corresponding to %s.", 1985 string_VkShaderStageFlagBits(stage)); 1986 } 1987 return skip; 1988 } 1989 1990 bool CoreChecks::ValidatePipelineShaderStage(layer_data *dev_data, VkPipelineShaderStageCreateInfo const *pStage, 1991 PIPELINE_STATE *pipeline, shader_module const **out_module, 1992 spirv_inst_iter *out_entrypoint, bool check_point_size) { 1993 bool skip = false; 1994 auto module = *out_module = GetShaderModuleState(pStage->module); 1995 auto report_data = GetReportData(); 1996 1997 if (!module->has_valid_spirv) return false; 1998 1999 // Find the entrypoint 2000 auto entrypoint = *out_entrypoint = FindEntrypoint(module, pStage->pName, pStage->stage); 2001 if (entrypoint == module->end()) { 2002 if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2003 "VUID-VkPipelineShaderStageCreateInfo-pName-00707", "No entrypoint found named `%s` for stage %s..", 2004 pStage->pName, string_VkShaderStageFlagBits(pStage->stage))) { 2005 return true; // no point continuing beyond here, any analysis is just going to be garbage. 2006 } 2007 } 2008 2009 // Mark accessible ids 2010 auto accessible_ids = MarkAccessibleIds(module, entrypoint); 2011 ProcessExecutionModes(module, entrypoint, pipeline); 2012 2013 // Validate descriptor set layout against what the entrypoint actually uses 2014 bool has_writable_descriptor = false; 2015 auto descriptor_uses = CollectInterfaceByDescriptorSlot(report_data, module, accessible_ids, &has_writable_descriptor); 2016 2017 // Validate shader capabilities against enabled device features 2018 skip |= ValidateShaderCapabilities(dev_data, module, pStage->stage, has_writable_descriptor); 2019 skip |= ValidateShaderStageInputOutputLimits(dev_data, module, pStage, pipeline); 2020 skip |= ValidateSpecializationOffsets(report_data, pStage); 2021 skip |= ValidatePushConstantUsage(report_data, pipeline->pipeline_layout.push_constant_ranges.get(), module, accessible_ids, 2022 pStage->stage); 2023 if (check_point_size && !pipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable) { 2024 skip |= ValidatePointListShaderState(dev_data, pipeline, module, entrypoint, pStage->stage); 2025 } 2026 2027 // Validate descriptor use 2028 for (auto use : descriptor_uses) { 2029 // While validating shaders capture which slots are used by the pipeline 2030 auto &reqs = pipeline->active_slots[use.first.first][use.first.second]; 2031 reqs = descriptor_req(reqs | DescriptorTypeToReqs(module, use.second.type_id)); 2032 2033 // Verify given pipelineLayout has requested setLayout with requested binding 2034 const auto &binding = GetDescriptorBinding(&pipeline->pipeline_layout, use.first); 2035 unsigned required_descriptor_count; 2036 std::set<uint32_t> descriptor_types = TypeToDescriptorTypeSet(module, use.second.type_id, required_descriptor_count); 2037 2038 if (!binding) { 2039 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2040 kVUID_Core_Shader_MissingDescriptor, 2041 "Shader uses descriptor slot %u.%u (expected `%s`) but not declared in pipeline layout", 2042 use.first.first, use.first.second, string_descriptorTypes(descriptor_types).c_str()); 2043 } else if (~binding->stageFlags & pStage->stage) { 2044 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, 2045 kVUID_Core_Shader_DescriptorNotAccessibleFromStage, 2046 "Shader uses descriptor slot %u.%u but descriptor not accessible from stage %s", use.first.first, 2047 use.first.second, string_VkShaderStageFlagBits(pStage->stage)); 2048 } else if (descriptor_types.find(binding->descriptorType) == descriptor_types.end()) { 2049 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2050 kVUID_Core_Shader_DescriptorTypeMismatch, 2051 "Type mismatch on descriptor slot %u.%u (expected `%s`) but descriptor of type %s", use.first.first, 2052 use.first.second, string_descriptorTypes(descriptor_types).c_str(), 2053 string_VkDescriptorType(binding->descriptorType)); 2054 } else if (binding->descriptorCount < required_descriptor_count) { 2055 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2056 kVUID_Core_Shader_DescriptorTypeMismatch, 2057 "Shader expects at least %u descriptors for binding %u.%u but only %u provided", 2058 required_descriptor_count, use.first.first, use.first.second, binding->descriptorCount); 2059 } 2060 } 2061 2062 // Validate use of input attachments against subpass structure 2063 if (pStage->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { 2064 auto input_attachment_uses = CollectInterfaceByInputAttachmentIndex(module, accessible_ids); 2065 2066 auto rpci = pipeline->rp_state->createInfo.ptr(); 2067 auto subpass = pipeline->graphicsPipelineCI.subpass; 2068 2069 for (auto use : input_attachment_uses) { 2070 auto input_attachments = rpci->pSubpasses[subpass].pInputAttachments; 2071 auto index = (input_attachments && use.first < rpci->pSubpasses[subpass].inputAttachmentCount) 2072 ? input_attachments[use.first].attachment 2073 : VK_ATTACHMENT_UNUSED; 2074 2075 if (index == VK_ATTACHMENT_UNUSED) { 2076 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2077 kVUID_Core_Shader_MissingInputAttachment, 2078 "Shader consumes input attachment index %d but not provided in subpass", use.first); 2079 } else if (!(GetFormatType(rpci->pAttachments[index].format) & GetFundamentalType(module, use.second.type_id))) { 2080 skip |= 2081 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2082 kVUID_Core_Shader_InputAttachmentTypeMismatch, 2083 "Subpass input attachment %u format of %s does not match type used in shader `%s`", use.first, 2084 string_VkFormat(rpci->pAttachments[index].format), DescribeType(module, use.second.type_id).c_str()); 2085 } 2086 } 2087 } 2088 2089 return skip; 2090 } 2091 2092 static bool ValidateInterfaceBetweenStages(debug_report_data const *report_data, shader_module const *producer, 2093 spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage, 2094 shader_module const *consumer, spirv_inst_iter consumer_entrypoint, 2095 shader_stage_attributes const *consumer_stage) { 2096 bool skip = false; 2097 2098 auto outputs = 2099 CollectInterfaceByLocation(producer, producer_entrypoint, spv::StorageClassOutput, producer_stage->arrayed_output); 2100 auto inputs = CollectInterfaceByLocation(consumer, consumer_entrypoint, spv::StorageClassInput, consumer_stage->arrayed_input); 2101 2102 auto a_it = outputs.begin(); 2103 auto b_it = inputs.begin(); 2104 2105 // Maps sorted by key (location); walk them together to find mismatches 2106 while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) { 2107 bool a_at_end = outputs.size() == 0 || a_it == outputs.end(); 2108 bool b_at_end = inputs.size() == 0 || b_it == inputs.end(); 2109 auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first; 2110 auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first; 2111 2112 if (b_at_end || ((!a_at_end) && (a_first < b_first))) { 2113 skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 2114 HandleToUint64(producer->vk_shader_module), kVUID_Core_Shader_OutputNotConsumed, 2115 "%s writes to output location %u.%u which is not consumed by %s", producer_stage->name, a_first.first, 2116 a_first.second, consumer_stage->name); 2117 a_it++; 2118 } else if (a_at_end || a_first > b_first) { 2119 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 2120 HandleToUint64(consumer->vk_shader_module), kVUID_Core_Shader_InputNotProduced, 2121 "%s consumes input location %u.%u which is not written by %s", consumer_stage->name, b_first.first, 2122 b_first.second, producer_stage->name); 2123 b_it++; 2124 } else { 2125 // subtleties of arrayed interfaces: 2126 // - if is_patch, then the member is not arrayed, even though the interface may be. 2127 // - if is_block_member, then the extra array level of an arrayed interface is not 2128 // expressed in the member type -- it's expressed in the block type. 2129 if (!TypesMatch(producer, consumer, a_it->second.type_id, b_it->second.type_id, 2130 producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member, 2131 consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member, true)) { 2132 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 2133 HandleToUint64(producer->vk_shader_module), kVUID_Core_Shader_InterfaceTypeMismatch, 2134 "Type mismatch on location %u.%u: '%s' vs '%s'", a_first.first, a_first.second, 2135 DescribeType(producer, a_it->second.type_id).c_str(), 2136 DescribeType(consumer, b_it->second.type_id).c_str()); 2137 } 2138 if (a_it->second.is_patch != b_it->second.is_patch) { 2139 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 2140 HandleToUint64(producer->vk_shader_module), kVUID_Core_Shader_InterfaceTypeMismatch, 2141 "Decoration mismatch on location %u.%u: is per-%s in %s stage but per-%s in %s stage", 2142 a_first.first, a_first.second, a_it->second.is_patch ? "patch" : "vertex", producer_stage->name, 2143 b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name); 2144 } 2145 if (a_it->second.is_relaxed_precision != b_it->second.is_relaxed_precision) { 2146 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, 2147 HandleToUint64(producer->vk_shader_module), kVUID_Core_Shader_InterfaceTypeMismatch, 2148 "Decoration mismatch on location %u.%u: %s and %s stages differ in precision", a_first.first, 2149 a_first.second, producer_stage->name, consumer_stage->name); 2150 } 2151 a_it++; 2152 b_it++; 2153 } 2154 } 2155 2156 return skip; 2157 } 2158 2159 static inline uint32_t DetermineFinalGeomStage(PIPELINE_STATE *pipeline, VkGraphicsPipelineCreateInfo *pCreateInfo) { 2160 uint32_t stage_mask = 0; 2161 if (pipeline->topology_at_rasterizer == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) { 2162 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 2163 stage_mask |= pCreateInfo->pStages[i].stage; 2164 } 2165 // Determine which shader in which PointSize should be written (the final geometry stage) 2166 if (stage_mask & VK_SHADER_STAGE_MESH_BIT_NV) { 2167 stage_mask = VK_SHADER_STAGE_MESH_BIT_NV; 2168 } else if (stage_mask & VK_SHADER_STAGE_GEOMETRY_BIT) { 2169 stage_mask = VK_SHADER_STAGE_GEOMETRY_BIT; 2170 } else if (stage_mask & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { 2171 stage_mask = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; 2172 } else if (stage_mask & VK_SHADER_STAGE_VERTEX_BIT) { 2173 stage_mask = VK_SHADER_STAGE_VERTEX_BIT; 2174 } 2175 } 2176 return stage_mask; 2177 } 2178 2179 // Validate that the shaders used by the given pipeline and store the active_slots 2180 // that are actually used by the pipeline into pPipeline->active_slots 2181 bool CoreChecks::ValidateAndCapturePipelineShaderState(layer_data *dev_data, PIPELINE_STATE *pipeline) { 2182 auto pCreateInfo = pipeline->graphicsPipelineCI.ptr(); 2183 int vertex_stage = GetShaderStageId(VK_SHADER_STAGE_VERTEX_BIT); 2184 int fragment_stage = GetShaderStageId(VK_SHADER_STAGE_FRAGMENT_BIT); 2185 auto report_data = GetReportData(); 2186 2187 shader_module const *shaders[32]; 2188 memset(shaders, 0, sizeof(shaders)); 2189 spirv_inst_iter entrypoints[32]; 2190 memset(entrypoints, 0, sizeof(entrypoints)); 2191 bool skip = false; 2192 2193 uint32_t pointlist_stage_mask = DetermineFinalGeomStage(pipeline, pCreateInfo); 2194 2195 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 2196 auto pStage = &pCreateInfo->pStages[i]; 2197 auto stage_id = GetShaderStageId(pStage->stage); 2198 skip |= ValidatePipelineShaderStage(dev_data, pStage, pipeline, &shaders[stage_id], &entrypoints[stage_id], 2199 (pointlist_stage_mask == pStage->stage)); 2200 } 2201 2202 // if the shader stages are no good individually, cross-stage validation is pointless. 2203 if (skip) return true; 2204 2205 auto vi = pCreateInfo->pVertexInputState; 2206 2207 if (vi) { 2208 skip |= ValidateViConsistency(report_data, vi); 2209 } 2210 2211 if (shaders[vertex_stage] && shaders[vertex_stage]->has_valid_spirv) { 2212 skip |= ValidateViAgainstVsInputs(report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]); 2213 } 2214 2215 int producer = GetShaderStageId(VK_SHADER_STAGE_VERTEX_BIT); 2216 int consumer = GetShaderStageId(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 2217 2218 while (!shaders[producer] && producer != fragment_stage) { 2219 producer++; 2220 consumer++; 2221 } 2222 2223 for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) { 2224 assert(shaders[producer]); 2225 if (shaders[consumer]) { 2226 if (shaders[consumer]->has_valid_spirv && shaders[producer]->has_valid_spirv) { 2227 skip |= ValidateInterfaceBetweenStages(report_data, shaders[producer], entrypoints[producer], 2228 &shader_stage_attribs[producer], shaders[consumer], entrypoints[consumer], 2229 &shader_stage_attribs[consumer]); 2230 } 2231 2232 producer = consumer; 2233 } 2234 } 2235 2236 if (shaders[fragment_stage] && shaders[fragment_stage]->has_valid_spirv) { 2237 skip |= ValidateFsOutputsAgainstRenderPass(report_data, shaders[fragment_stage], entrypoints[fragment_stage], pipeline, 2238 pCreateInfo->subpass); 2239 } 2240 2241 return skip; 2242 } 2243 2244 bool CoreChecks::ValidateComputePipeline(layer_data *dev_data, PIPELINE_STATE *pipeline) { 2245 auto pCreateInfo = pipeline->computePipelineCI.ptr(); 2246 2247 shader_module const *module; 2248 spirv_inst_iter entrypoint; 2249 2250 return ValidatePipelineShaderStage(dev_data, &pCreateInfo->stage, pipeline, &module, &entrypoint, false); 2251 } 2252 2253 bool CoreChecks::ValidateRayTracingPipelineNV(layer_data *dev_data, PIPELINE_STATE *pipeline) { 2254 auto pCreateInfo = pipeline->raytracingPipelineCI.ptr(); 2255 2256 shader_module const *module; 2257 spirv_inst_iter entrypoint; 2258 2259 return ValidatePipelineShaderStage(dev_data, pCreateInfo->pStages, pipeline, &module, &entrypoint, false); 2260 } 2261 2262 uint32_t ValidationCache::MakeShaderHash(VkShaderModuleCreateInfo const *smci) { return XXH32(smci->pCode, smci->codeSize, 0); } 2263 2264 static ValidationCache *GetValidationCacheInfo(VkShaderModuleCreateInfo const *pCreateInfo) { 2265 while ((pCreateInfo = (VkShaderModuleCreateInfo const *)pCreateInfo->pNext) != nullptr) { 2266 if (pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT) 2267 return (ValidationCache *)((VkShaderModuleValidationCacheCreateInfoEXT const *)pCreateInfo)->validationCache; 2268 } 2269 2270 return nullptr; 2271 } 2272 2273 bool CoreChecks::PreCallValidateCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 2274 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) { 2275 layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 2276 2277 bool skip = false; 2278 spv_result_t spv_valid = SPV_SUCCESS; 2279 2280 if (GetDisables()->shader_validation) { 2281 return false; 2282 } 2283 2284 auto have_glsl_shader = GetDeviceExtensions()->vk_nv_glsl_shader; 2285 2286 if (!have_glsl_shader && (pCreateInfo->codeSize % 4)) { 2287 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 2288 "VUID-VkShaderModuleCreateInfo-pCode-01376", 2289 "SPIR-V module not valid: Codesize must be a multiple of 4 but is " PRINTF_SIZE_T_SPECIFIER ".", 2290 pCreateInfo->codeSize); 2291 } else { 2292 auto cache = GetValidationCacheInfo(pCreateInfo); 2293 uint32_t hash = 0; 2294 if (cache) { 2295 hash = ValidationCache::MakeShaderHash(pCreateInfo); 2296 if (cache->Contains(hash)) return false; 2297 } 2298 2299 // Use SPIRV-Tools validator to try and catch any issues with the module itself 2300 spv_target_env spirv_environment = SPV_ENV_VULKAN_1_0; 2301 if (GetApiVersion() >= VK_API_VERSION_1_1) { 2302 spirv_environment = SPV_ENV_VULKAN_1_1; 2303 } 2304 spv_context ctx = spvContextCreate(spirv_environment); 2305 spv_const_binary_t binary{pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t)}; 2306 spv_diagnostic diag = nullptr; 2307 spv_validator_options options = spvValidatorOptionsCreate(); 2308 if (GetDeviceExtensions()->vk_khr_relaxed_block_layout) { 2309 spvValidatorOptionsSetRelaxBlockLayout(options, true); 2310 } 2311 if (GetDeviceExtensions()->vk_ext_scalar_block_layout && 2312 GetEnabledFeatures()->scalar_block_layout_features.scalarBlockLayout == VK_TRUE) { 2313 spvValidatorOptionsSetScalarBlockLayout(options, true); 2314 } 2315 spv_valid = spvValidateWithOptions(ctx, options, &binary, &diag); 2316 if (spv_valid != SPV_SUCCESS) { 2317 if (!have_glsl_shader || (pCreateInfo->pCode[0] == spv::MagicNumber)) { 2318 skip |= log_msg(device_data->report_data, 2319 spv_valid == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT, 2320 VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, kVUID_Core_Shader_InconsistentSpirv, 2321 "SPIR-V module not valid: %s", diag && diag->error ? diag->error : "(no error text)"); 2322 } 2323 } else { 2324 if (cache) { 2325 cache->Insert(hash); 2326 } 2327 } 2328 2329 spvValidatorOptionsDestroy(options); 2330 spvDiagnosticDestroy(diag); 2331 spvContextDestroy(ctx); 2332 } 2333 2334 return skip; 2335 } 2336 2337 void CoreChecks::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 2338 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule, 2339 void *csm_state_data) { 2340 layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 2341 2342 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data); 2343 if (GetEnables()->gpu_validation) { 2344 GpuPreCallCreateShaderModule(device_data, pCreateInfo, pAllocator, pShaderModule, &csm_state->unique_shader_id, 2345 &csm_state->instrumented_create_info, &csm_state->instrumented_pgm); 2346 } 2347 } 2348 2349 void CoreChecks::PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 2350 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule, 2351 VkResult result, void *csm_state_data) { 2352 layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 2353 2354 if (VK_SUCCESS != result) return; 2355 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data); 2356 2357 spv_target_env spirv_environment = ((GetApiVersion() >= VK_API_VERSION_1_1) ? SPV_ENV_VULKAN_1_1 : SPV_ENV_VULKAN_1_0); 2358 bool is_spirv = (pCreateInfo->pCode[0] == spv::MagicNumber); 2359 std::unique_ptr<shader_module> new_shader_module( 2360 is_spirv ? new shader_module(pCreateInfo, *pShaderModule, spirv_environment, csm_state->unique_shader_id) 2361 : new shader_module()); 2362 device_data->shaderModuleMap[*pShaderModule] = std::move(new_shader_module); 2363 } 2364