• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@ijw.co.nz>
19  * Author: Dave Houlton <daveh@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
BuildDefIndex()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 
ExecutionModelToShaderStageFlagBits(unsigned mode)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 
FindEntrypoint(shader_module const * src,char const * name,VkShaderStageFlagBits stageBits)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 
StorageClassName(unsigned sc)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
GetConstantValue(shader_module const * src,unsigned id)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 
DescribeTypeInner(std::ostringstream & ss,shader_module const * src,unsigned type)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 
DescribeType(shader_module const * src,unsigned type)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 
IsNarrowNumericType(spirv_inst_iter type)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 
TypesMatch(shader_module const * a,shader_module const * b,unsigned a_type,unsigned b_type,bool a_arrayed,bool b_arrayed,bool relaxed)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 
ValueOrDefault(std::unordered_map<unsigned,unsigned> const & map,unsigned id,unsigned def)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 
GetLocationsConsumedByType(shader_module const * src,unsigned type,bool strip_array_level)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 
GetComponentsConsumedByType(shader_module const * src,unsigned type,bool strip_array_level)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 
GetLocationsConsumedByFormat(VkFormat format)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 
GetFormatType(VkFormat fmt)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.
GetFundamentalType(shader_module const * src,unsigned type)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 
GetShaderStageId(VkShaderStageFlagBits stage)531 static uint32_t GetShaderStageId(VkShaderStageFlagBits stage) {
532     uint32_t bit_pos = uint32_t(u_ffs(stage));
533     return bit_pos - 1;
534 }
535 
GetStructType(shader_module const * src,spirv_inst_iter def,bool is_array_of_verts)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 
CollectInterfaceBlockMembers(shader_module const * src,std::map<location_t,interface_var> * out,std::unordered_map<unsigned,unsigned> const & blocks,bool is_array_of_verts,uint32_t id,uint32_t type_id,bool is_patch,int)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 
CollectInterfaceByLocation(shader_module const * src,spirv_inst_iter entrypoint,spv::StorageClass sinterface,bool is_array_of_verts)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 
CollectInterfaceByInputAttachmentIndex(shader_module const * src,std::unordered_set<uint32_t> const & accessible_ids)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 
IsWritableDescriptorType(shader_module const * module,uint32_t type_id,bool is_storage_buffer)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 
CollectInterfaceByDescriptorSlot(debug_report_data const * report_data,shader_module const * src,std::unordered_set<uint32_t> const & accessible_ids,bool * has_writable_descriptor)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 
ValidateViConsistency(debug_report_data const * report_data,VkPipelineVertexInputStateCreateInfo const * vi)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 
ValidateViAgainstVsInputs(debug_report_data const * report_data,VkPipelineVertexInputStateCreateInfo const * vi,shader_module const * vs,spirv_inst_iter entrypoint)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 
ValidateFsOutputsAgainstRenderPass(debug_report_data const * report_data,shader_module const * fs,spirv_inst_iter entrypoint,PIPELINE_STATE const * pipeline,uint32_t subpass_index)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.
IsPointSizeWritten(shader_module const * src,spirv_inst_iter builtin_instr,spirv_inst_iter entrypoint)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.
MarkAccessibleIds(shader_module const * src,spirv_inst_iter entrypoint)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 
ValidatePushConstantBlockAgainstPipeline(debug_report_data const * report_data,std::vector<VkPushConstantRange> const * push_constant_ranges,shader_module const * src,spirv_inst_iter type,VkShaderStageFlagBits stage)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 
ValidatePushConstantUsage(debug_report_data const * report_data,std::vector<VkPushConstantRange> const * push_constant_ranges,shader_module const * src,std::unordered_set<uint32_t> accessible_ids,VkShaderStageFlagBits stage)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.
ValidateSpecializationOffsets(debug_report_data const * report_data,VkPipelineShaderStageCreateInfo const * info)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?
TypeToDescriptorTypeSet(shader_module const * module,uint32_t type_id,unsigned & descriptor_count)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 
string_descriptorTypes(const std::set<uint32_t> & descriptor_types)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 
RequireFeature(debug_report_data const * report_data,VkBool32 feature,char const * feature_name)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 
RequireExtension(debug_report_data const * report_data,bool extension,char const * extension_name)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 
ValidateShaderCapabilities(layer_data * dev_data,shader_module const * src,VkShaderStageFlagBits stage,bool has_writable_descriptor)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 
VariableIsBuiltIn(shader_module const * src,const uint32_t ID,std::vector<uint32_t> const & builtInBlockIDs,std::vector<uint32_t> const & builtInIDs)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 
ValidateShaderStageInputOutputLimits(layer_data * dev_data,shader_module const * src,VkPipelineShaderStageCreateInfo const * pStage,PIPELINE_STATE * pipeline)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 
DescriptorTypeToReqs(shader_module const * module,uint32_t type_id)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
GetDescriptorBinding(PIPELINE_LAYOUT_NODE const * pipelineLayout,descriptor_slot_t slot)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 
ProcessExecutionModes(shader_module const * src,spirv_inst_iter entrypoint,PIPELINE_STATE * pipeline)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
ValidatePointListShaderState(const layer_data * dev_data,const PIPELINE_STATE * pipeline,shader_module const * src,spirv_inst_iter entrypoint,VkShaderStageFlagBits stage)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 
ValidatePipelineShaderStage(layer_data * dev_data,VkPipelineShaderStageCreateInfo const * pStage,PIPELINE_STATE * pipeline,shader_module const ** out_module,spirv_inst_iter * out_entrypoint,bool check_point_size)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 
ValidateInterfaceBetweenStages(debug_report_data const * report_data,shader_module const * producer,spirv_inst_iter producer_entrypoint,shader_stage_attributes const * producer_stage,shader_module const * consumer,spirv_inst_iter consumer_entrypoint,shader_stage_attributes const * consumer_stage)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 
DetermineFinalGeomStage(PIPELINE_STATE * pipeline,VkGraphicsPipelineCreateInfo * pCreateInfo)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
ValidateAndCapturePipelineShaderState(layer_data * dev_data,PIPELINE_STATE * pipeline)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 
ValidateComputePipeline(layer_data * dev_data,PIPELINE_STATE * pipeline)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 
ValidateRayTracingPipelineNV(layer_data * dev_data,PIPELINE_STATE * pipeline)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 
MakeShaderHash(VkShaderModuleCreateInfo const * smci)2262 uint32_t ValidationCache::MakeShaderHash(VkShaderModuleCreateInfo const *smci) { return XXH32(smci->pCode, smci->codeSize, 0); }
2263 
GetValidationCacheInfo(VkShaderModuleCreateInfo const * pCreateInfo)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 
PreCallValidateCreateShaderModule(VkDevice device,const VkShaderModuleCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkShaderModule * pShaderModule)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 
PreCallRecordCreateShaderModule(VkDevice device,const VkShaderModuleCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkShaderModule * pShaderModule,void * csm_state_data)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 
PostCallRecordCreateShaderModule(VkDevice device,const VkShaderModuleCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkShaderModule * pShaderModule,VkResult result,void * csm_state_data)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