Home | History | Annotate | Download | only in layers
      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