1 /* Copyright (c) 2015-2020 The Khronos Group Inc.
2  * Copyright (c) 2015-2020 Valve Corporation
3  * Copyright (c) 2015-2020 LunarG, Inc.
4  * Copyright (C) 2015-2020 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: Dustin Graves <dustin@lunarg.com>
19  * Author: Mark Lobodzinski <mark@lunarg.com>
20  */
21 
22 #pragma once
23 
24 #include "parameter_name.h"
25 #include "vk_typemap_helper.h"
26 
27 // Suppress unused warning on Linux
28 #if defined(__GNUC__)
29 #define DECORATE_UNUSED __attribute__((unused))
30 #else
31 #define DECORATE_UNUSED
32 #endif
33 
34 static const char DECORATE_UNUSED *kVUID_PVError_RequiredParameter = "UNASSIGNED-GeneralParameterError-RequiredParameter";
35 static const char DECORATE_UNUSED *kVUID_PVError_UnrecognizedValue = "UNASSIGNED-GeneralParameterError-UnrecognizedValue";
36 static const char DECORATE_UNUSED *kVUID_PVError_ExtensionNotEnabled = "UNASSIGNED-GeneralParameterError-ExtensionNotEnabled";
37 static const char DECORATE_UNUSED *kVUID_PVError_ApiVersionViolation = "UNASSIGNED-API-Version-Violation";
38 // static const char DECORATE_UNUSED *kVUID_PVError_InvalidStructPNext = "UNASSIGNED-GeneralParameterError-InvalidStructPNext";
39 // static const char DECORATE_UNUSED *kVUID_PVError_NONE = "UNASSIGNED-GeneralParameterError-Info";
40 // static const char DECORATE_UNUSED *kVUID_PVError_InvalidUsage = "UNASSIGNED-GeneralParameterError-InvalidUsage";
41 // static const char DECORATE_UNUSED *kVUID_PVError_InvalidStructSType = "UNASSIGNED-GeneralParameterError-InvalidStructSType";
42 // static const char DECORATE_UNUSED *kVUID_PVError_ReservedParameter = "UNASSIGNED-GeneralParameterError-ReservedParameter";
43 // static const char DECORATE_UNUSED *kVUID_PVError_DeviceLimit = "UNASSIGNED-GeneralParameterError-DeviceLimit";
44 // static const char DECORATE_UNUSED *kVUID_PVError_FailureCode = "UNASSIGNED-GeneralParameterError-FailureCode";
45 // static const char DECORATE_UNUSED *kVUID_PVError_DeviceFeature = "UNASSIGNED-GeneralParameterError-DeviceFeature";
46 
47 extern const uint32_t GeneratedVulkanHeaderVersion;
48 
49 extern const VkQueryPipelineStatisticFlags AllVkQueryPipelineStatisticFlagBits;
50 extern const VkColorComponentFlags AllVkColorComponentFlagBits;
51 extern const VkShaderStageFlags AllVkShaderStageFlagBits;
52 extern const VkQueryControlFlags AllVkQueryControlFlagBits;
53 extern const VkImageUsageFlags AllVkImageUsageFlagBits;
54 extern const VkSampleCountFlags AllVkSampleCountFlagBits;
55 extern const VkBuildAccelerationStructureFlagsNV AllVkBuildAccelerationStructureFlagBitsNV;
56 extern const VkGeometryFlagsKHR AllVkGeometryFlagBitsKHR;
57 
58 extern const std::vector<VkGeometryTypeKHR> AllVkGeometryTypeKHREnums;
59 extern const std::vector<VkCompareOp> AllVkCompareOpEnums;
60 extern const std::vector<VkStencilOp> AllVkStencilOpEnums;
61 extern const std::vector<VkBlendFactor> AllVkBlendFactorEnums;
62 extern const std::vector<VkBlendOp> AllVkBlendOpEnums;
63 extern const std::vector<VkLogicOp> AllVkLogicOpEnums;
64 extern const std::vector<VkBorderColor> AllVkBorderColorEnums;
65 extern const std::vector<VkImageLayout> AllVkImageLayoutEnums;
66 extern const std::vector<VkFormat> AllVkFormatEnums;
67 extern const std::vector<VkVertexInputRate> AllVkVertexInputRateEnums;
68 extern const std::vector<VkPrimitiveTopology> AllVkPrimitiveTopologyEnums;
69 extern const std::vector<VkIndexType> AllVkIndexTypeEnums;
70 
71 extern std::vector<std::pair<uint32_t, uint32_t>> custom_stype_info;
72 
73 // String returned by string_VkStructureType for an unrecognized type.
74 const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
75 
76 // String returned by string_VkResult for an unrecognized type.
77 const std::string UnsupportedResultString = "Unhandled VkResult";
78 
79 // The base value used when computing the offset for an enumeration token value that is added by an extension.
80 // When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
81 // See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
82 const uint32_t ExtEnumBaseValue = 1000000000;
83 
84 // The value of all VK_xxx_MAX_ENUM tokens
85 const uint32_t MaxEnumValue = 0x7FFFFFFF;
86 
87 class StatelessValidation : public ValidationObject {
88   public:
89     VkPhysicalDeviceLimits device_limits = {};
90     safe_VkPhysicalDeviceFeatures2 physical_device_features2;
91     void *device_createinfo_pnext;
92     const VkPhysicalDeviceFeatures &physical_device_features = physical_device_features2.features;
93     std::unordered_map<VkPhysicalDevice, VkPhysicalDeviceProperties *> physical_device_properties_map;
94     std::unordered_map<VkPhysicalDevice, std::unordered_set<std::string>> device_extensions_enumerated{};
95 
96     // Override chassis read/write locks for this validation object
97     // This override takes a deferred lock. i.e. it is not acquired.
read_lock()98     virtual read_lock_guard_t read_lock() { return read_lock_guard_t(validation_object_mutex, std::defer_lock); }
write_lock()99     virtual write_lock_guard_t write_lock() { return write_lock_guard_t(validation_object_mutex, std::defer_lock); }
100 
101     // Device extension properties -- storing properties gathered from VkPhysicalDeviceProperties2KHR::pNext chain
102     struct DeviceExtensionProperties {
103         VkPhysicalDeviceShadingRateImagePropertiesNV shading_rate_image_props;
104         VkPhysicalDeviceMeshShaderPropertiesNV mesh_shader_props;
105         VkPhysicalDeviceRayTracingPropertiesNV ray_tracing_propsNV;
106         VkPhysicalDeviceRayTracingPropertiesKHR ray_tracing_propsKHR;
107         VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback_props;
108     };
109     DeviceExtensionProperties phys_dev_ext_props = {};
110 
111     struct SubpassesUsageStates {
112         std::unordered_set<uint32_t> subpasses_using_color_attachment;
113         std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
114     };
115 
116     // Though this validation object is predominantly statless, the Framebuffer checks are greatly simplified by creating and
117     // updating a map of the renderpass usage states, and these accesses need thread protection. Use a mutex separate from the
118     // parent object's to maintain that functionality.
119     mutable std::mutex renderpass_map_mutex;
120     std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
121 
122     // Constructor for stateles validation tracking
StatelessValidation()123     StatelessValidation() : device_createinfo_pnext(nullptr) { container_type = LayerObjectTypeParameterValidation; }
~StatelessValidation()124     ~StatelessValidation() {
125         if (device_createinfo_pnext) {
126             FreePnextChain(device_createinfo_pnext);
127         }
128     }
129 
130     /**
131      * Validate a minimum value.
132      *
133      * Verify that the specified value is greater than the specified lower bound.
134      *
135      * @param api_name Name of API call being validated.
136      * @param parameter_name Name of parameter being validated.
137      * @param value Value to validate.
138      * @param lower_bound Lower bound value to use for validation.
139      * @return Boolean value indicating that the call should be skipped.
140      */
141     template <typename T>
ValidateGreaterThan(const T value,const T lower_bound,const ParameterName & parameter_name,const std::string & vuid,const char * api_name)142     bool ValidateGreaterThan(const T value, const T lower_bound, const ParameterName &parameter_name, const std::string &vuid,
143                              const char *api_name) const {
144         bool skip_call = false;
145 
146         if (value <= lower_bound) {
147             std::ostringstream ss;
148             ss << api_name << ": parameter " << parameter_name.get_name() << " (= " << value << ") is not greater than "
149                << lower_bound;
150             skip_call |= LogError(device, vuid, "%s", ss.str().c_str());
151         }
152 
153         return skip_call;
154     }
155 
156     template <typename T>
ValidateGreaterThanZero(const T value,const ParameterName & parameter_name,const std::string & vuid,const char * api_name)157     bool ValidateGreaterThanZero(const T value, const ParameterName &parameter_name, const std::string &vuid,
158                                  const char *api_name) const {
159         return ValidateGreaterThan(value, T{0}, parameter_name, vuid, api_name);
160     }
161     /**
162      * Validate a required pointer.
163      *
164      * Verify that a required pointer is not NULL.
165      *
166      * @param apiName Name of API call being validated.
167      * @param parameterName Name of parameter being validated.
168      * @param value Pointer to validate.
169      * @return Boolean value indicating that the call should be skipped.
170      */
validate_required_pointer(const char * apiName,const ParameterName & parameterName,const void * value,const std::string & vuid)171     bool validate_required_pointer(const char *apiName, const ParameterName &parameterName, const void *value,
172                                    const std::string &vuid) const {
173         bool skip_call = false;
174 
175         if (value == NULL) {
176             skip_call |=
177                 LogError(device, vuid, "%s: required parameter %s specified as NULL.", apiName, parameterName.get_name().c_str());
178         }
179 
180         return skip_call;
181     }
182 
183     /**
184      * Validate array count and pointer to array.
185      *
186      * Verify that required count and array parameters are not 0 or NULL.  If the
187      * count parameter is not optional, verify that it is not 0.  If the array
188      * parameter is NULL, and it is not optional, verify that count is 0.
189      *
190      * @param apiName Name of API call being validated.
191      * @param countName Name of count parameter.
192      * @param arrayName Name of array parameter.
193      * @param count Number of elements in the array.
194      * @param array Array to validate.
195      * @param countRequired The 'count' parameter may not be 0 when true.
196      * @param arrayRequired The 'array' parameter may not be NULL when true.
197      * @return Boolean value indicating that the call should be skipped.
198      */
199     template <typename T1, typename T2>
validate_array(const char * apiName,const ParameterName & countName,const ParameterName & arrayName,T1 count,const T2 * array,bool countRequired,bool arrayRequired,const char * count_required_vuid,const char * array_required_vuid)200     bool validate_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName, T1 count,
201                         const T2 *array, bool countRequired, bool arrayRequired, const char *count_required_vuid,
202                         const char *array_required_vuid) const {
203         bool skip_call = false;
204 
205         // Count parameters not tagged as optional cannot be 0
206         if (countRequired && (count == 0)) {
207             skip_call |= LogError(device, count_required_vuid, "%s: parameter %s must be greater than 0.", apiName,
208                                   countName.get_name().c_str());
209         }
210 
211         // Array parameters not tagged as optional cannot be NULL, unless the count is 0
212         if (arrayRequired && (count != 0) && (*array == NULL)) {
213             skip_call |= LogError(device, array_required_vuid, "%s: required parameter %s specified as NULL.", apiName,
214                                   arrayName.get_name().c_str());
215         }
216 
217         return skip_call;
218     }
219 
220     /**
221      * Validate pointer to array count and pointer to array.
222      *
223      * Verify that required count and array parameters are not NULL.  If count
224      * is not NULL and its value is not optional, verify that it is not 0.  If the
225      * array parameter is NULL, and it is not optional, verify that count is 0.
226      * The array parameter will typically be optional for this case (where count is
227      * a pointer), allowing the caller to retrieve the available count.
228      *
229      * @param apiName Name of API call being validated.
230      * @param countName Name of count parameter.
231      * @param arrayName Name of array parameter.
232      * @param count Pointer to the number of elements in the array.
233      * @param array Array to validate.
234      * @param countPtrRequired The 'count' parameter may not be NULL when true.
235      * @param countValueRequired The '*count' value may not be 0 when true.
236      * @param arrayRequired The 'array' parameter may not be NULL when true.
237      * @return Boolean value indicating that the call should be skipped.
238      */
239     template <typename T1, typename T2>
validate_array(const char * apiName,const ParameterName & countName,const ParameterName & arrayName,const T1 * count,const T2 * array,bool countPtrRequired,bool countValueRequired,bool arrayRequired,const char * count_required_vuid,const char * array_required_vuid)240     bool validate_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName, const T1 *count,
241                         const T2 *array, bool countPtrRequired, bool countValueRequired, bool arrayRequired,
242                         const char *count_required_vuid, const char *array_required_vuid) const {
243         bool skip_call = false;
244 
245         if (count == NULL) {
246             if (countPtrRequired) {
247                 skip_call |= LogError(device, kVUID_PVError_RequiredParameter, "%s: required parameter %s specified as NULL",
248                                       apiName, countName.get_name().c_str());
249             }
250         } else {
251             skip_call |= validate_array(apiName, countName, arrayName, *array ? (*count) : 0, &array, countValueRequired,
252                                         arrayRequired, count_required_vuid, array_required_vuid);
253         }
254 
255         return skip_call;
256     }
257 
258     /**
259      * Validate a pointer to a Vulkan structure.
260      *
261      * Verify that a required pointer to a structure is not NULL.  If the pointer is
262      * not NULL, verify that each structure's sType field is set to the correct
263      * VkStructureType value.
264      *
265      * @param apiName Name of API call being validated.
266      * @param parameterName Name of struct parameter being validated.
267      * @param sTypeName Name of expected VkStructureType value.
268      * @param value Pointer to the struct to validate.
269      * @param sType VkStructureType for structure validation.
270      * @param required The parameter may not be NULL when true.
271      * @return Boolean value indicating that the call should be skipped.
272      */
273     template <typename T>
validate_struct_type(const char * apiName,const ParameterName & parameterName,const char * sTypeName,const T * value,VkStructureType sType,bool required,const char * struct_vuid,const char * stype_vuid)274     bool validate_struct_type(const char *apiName, const ParameterName &parameterName, const char *sTypeName, const T *value,
275                               VkStructureType sType, bool required, const char *struct_vuid, const char *stype_vuid) const {
276         bool skip_call = false;
277 
278         if (value == NULL) {
279             if (required) {
280                 skip_call |= LogError(device, struct_vuid, "%s: required parameter %s specified as NULL", apiName,
281                                       parameterName.get_name().c_str());
282             }
283         } else if (value->sType != sType) {
284             skip_call |= LogError(device, stype_vuid, "%s: parameter %s->sType must be %s.", apiName,
285                                   parameterName.get_name().c_str(), sTypeName);
286         }
287 
288         return skip_call;
289     }
290 
291     /**
292      * Validate an array of Vulkan structures
293      *
294      * Verify that required count and array parameters are not 0 or NULL.  If
295      * the array contains 1 or more structures, verify that each structure's
296      * sType field is set to the correct VkStructureType value.
297      *
298      * @param apiName Name of API call being validated.
299      * @param countName Name of count parameter.
300      * @param arrayName Name of array parameter.
301      * @param sTypeName Name of expected VkStructureType value.
302      * @param count Number of elements in the array.
303      * @param array Array to validate.
304      * @param sType VkStructureType for structure validation.
305      * @param countRequired The 'count' parameter may not be 0 when true.
306      * @param arrayRequired The 'array' parameter may not be NULL when true.
307      * @return Boolean value indicating that the call should be skipped.
308      */
309     template <typename T>
validate_struct_type_array(const char * apiName,const ParameterName & countName,const ParameterName & arrayName,const char * sTypeName,uint32_t count,const T * array,VkStructureType sType,bool countRequired,bool arrayRequired,const char * stype_vuid,const char * param_vuid,const char * count_required_vuid)310     bool validate_struct_type_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName,
311                                     const char *sTypeName, uint32_t count, const T *array, VkStructureType sType,
312                                     bool countRequired, bool arrayRequired, const char *stype_vuid, const char *param_vuid,
313                                     const char *count_required_vuid) const {
314         bool skip_call = false;
315 
316         if ((count == 0) || (array == NULL)) {
317             skip_call |= validate_array(apiName, countName, arrayName, count, &array, countRequired, arrayRequired,
318                                         count_required_vuid, param_vuid);
319         } else {
320             // Verify that all structs in the array have the correct type
321             for (uint32_t i = 0; i < count; ++i) {
322                 if (array[i].sType != sType) {
323                     skip_call |= LogError(device, stype_vuid, "%s: parameter %s[%d].sType must be %s", apiName,
324                                           arrayName.get_name().c_str(), i, sTypeName);
325                 }
326             }
327         }
328 
329         return skip_call;
330     }
331 
332     /**
333      * Validate an array of Vulkan structures.
334      *
335      * Verify that required count and array parameters are not NULL.  If count
336      * is not NULL and its value is not optional, verify that it is not 0.
337      * If the array contains 1 or more structures, verify that each structure's
338      * sType field is set to the correct VkStructureType value.
339      *
340      * @param apiName Name of API call being validated.
341      * @param countName Name of count parameter.
342      * @param arrayName Name of array parameter.
343      * @param sTypeName Name of expected VkStructureType value.
344      * @param count Pointer to the number of elements in the array.
345      * @param array Array to validate.
346      * @param sType VkStructureType for structure validation.
347      * @param countPtrRequired The 'count' parameter may not be NULL when true.
348      * @param countValueRequired The '*count' value may not be 0 when true.
349      * @param arrayRequired The 'array' parameter may not be NULL when true.
350      * @return Boolean value indicating that the call should be skipped.
351      */
352     template <typename T>
validate_struct_type_array(const char * apiName,const ParameterName & countName,const ParameterName & arrayName,const char * sTypeName,uint32_t * count,const T * array,VkStructureType sType,bool countPtrRequired,bool countValueRequired,bool arrayRequired,const char * stype_vuid,const char * param_vuid,const char * count_required_vuid)353     bool validate_struct_type_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName,
354                                     const char *sTypeName, uint32_t *count, const T *array, VkStructureType sType,
355                                     bool countPtrRequired, bool countValueRequired, bool arrayRequired, const char *stype_vuid,
356                                     const char *param_vuid, const char *count_required_vuid) const {
357         bool skip_call = false;
358 
359         if (count == NULL) {
360             if (countPtrRequired) {
361                 skip_call |= LogError(device, kVUID_PVError_RequiredParameter, "%s: required parameter %s specified as NULL",
362                                       apiName, countName.get_name().c_str());
363             }
364         } else {
365             skip_call |= validate_struct_type_array(apiName, countName, arrayName, sTypeName, (*count), array, sType,
366                                                     countValueRequired && (array != nullptr), arrayRequired, stype_vuid, param_vuid,
367                                                     count_required_vuid);
368         }
369 
370         return skip_call;
371     }
372 
373     /**
374      * Validate a Vulkan handle.
375      *
376      * Verify that the specified handle is not VK_NULL_HANDLE.
377      *
378      * @param api_name Name of API call being validated.
379      * @param parameter_name Name of struct parameter being validated.
380      * @param value Handle to validate.
381      * @return Boolean value indicating that the call should be skipped.
382      */
383     template <typename T>
validate_required_handle(const char * api_name,const ParameterName & parameter_name,T value)384     bool validate_required_handle(const char *api_name, const ParameterName &parameter_name, T value) const {
385         bool skip_call = false;
386 
387         if (value == VK_NULL_HANDLE) {
388             skip_call |= LogError(device, kVUID_PVError_RequiredParameter, "%s: required parameter %s specified as VK_NULL_HANDLE",
389                                   api_name, parameter_name.get_name().c_str());
390         }
391 
392         return skip_call;
393     }
394 
395     /**
396      * Validate an array of Vulkan handles.
397      *
398      * Verify that required count and array parameters are not NULL.  If count
399      * is not NULL and its value is not optional, verify that it is not 0.
400      * If the array contains 1 or more handles, verify that no handle is set to
401      * VK_NULL_HANDLE.
402      *
403      * @note This function is only intended to validate arrays of handles when none
404      *       of the handles are allowed to be VK_NULL_HANDLE.  For arrays of handles
405      *       that are allowed to contain VK_NULL_HANDLE, use validate_array() instead.
406      *
407      * @param api_name Name of API call being validated.
408      * @param count_name Name of count parameter.
409      * @param array_name Name of array parameter.
410      * @param count Number of elements in the array.
411      * @param array Array to validate.
412      * @param count_required The 'count' parameter may not be 0 when true.
413      * @param array_required The 'array' parameter may not be NULL when true.
414      * @return Boolean value indicating that the call should be skipped.
415      */
416     template <typename T>
validate_handle_array(const char * api_name,const ParameterName & count_name,const ParameterName & array_name,uint32_t count,const T * array,bool count_required,bool array_required)417     bool validate_handle_array(const char *api_name, const ParameterName &count_name, const ParameterName &array_name,
418                                uint32_t count, const T *array, bool count_required, bool array_required) const {
419         bool skip_call = false;
420 
421         if ((count == 0) || (array == NULL)) {
422             skip_call |= validate_array(api_name, count_name, array_name, count, &array, count_required, array_required,
423                                         kVUIDUndefined, kVUIDUndefined);
424         } else {
425             // Verify that no handles in the array are VK_NULL_HANDLE
426             for (uint32_t i = 0; i < count; ++i) {
427                 if (array[i] == VK_NULL_HANDLE) {
428                     skip_call |= LogError(device, kVUID_PVError_RequiredParameter,
429                                           "%s: required parameter %s[%d] specified as VK_NULL_HANDLE", api_name,
430                                           array_name.get_name().c_str(), i);
431                 }
432             }
433         }
434 
435         return skip_call;
436     }
437 
438     /**
439      * Validate string array count and content.
440      *
441      * Verify that required count and array parameters are not 0 or NULL.  If the
442      * count parameter is not optional, verify that it is not 0.  If the array
443      * parameter is NULL, and it is not optional, verify that count is 0.  If the
444      * array parameter is not NULL, verify that none of the strings are NULL.
445      *
446      * @param apiName Name of API call being validated.
447      * @param countName Name of count parameter.
448      * @param arrayName Name of array parameter.
449      * @param count Number of strings in the array.
450      * @param array Array of strings to validate.
451      * @param countRequired The 'count' parameter may not be 0 when true.
452      * @param arrayRequired The 'array' parameter may not be NULL when true.
453      * @return Boolean value indicating that the call should be skipped.
454      */
validate_string_array(const char * apiName,const ParameterName & countName,const ParameterName & arrayName,uint32_t count,const char * const * array,bool countRequired,bool arrayRequired,const char * count_required_vuid,const char * array_required_vuid)455     bool validate_string_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName, uint32_t count,
456                                const char *const *array, bool countRequired, bool arrayRequired, const char *count_required_vuid,
457                                const char *array_required_vuid) const {
458         bool skip_call = false;
459 
460         if ((count == 0) || (array == NULL)) {
461             skip_call |= validate_array(apiName, countName, arrayName, count, &array, countRequired, arrayRequired,
462                                         count_required_vuid, array_required_vuid);
463         } else {
464             // Verify that strings in the array are not NULL
465             for (uint32_t i = 0; i < count; ++i) {
466                 if (array[i] == NULL) {
467                     skip_call |= LogError(device, array_required_vuid, "%s: required parameter %s[%d] specified as NULL", apiName,
468                                           arrayName.get_name().c_str(), i);
469                 }
470             }
471         }
472 
473         return skip_call;
474     }
475 
476     // Forward declarations
477     bool CheckPromotedApiAgainstVulkanVersion(VkInstance instance, const char *api_name, const uint32_t promoted_version) const;
478     bool CheckPromotedApiAgainstVulkanVersion(VkPhysicalDevice pdev, const char *api_name, const uint32_t promoted_version) const;
479     bool SupportedByPdev(const VkPhysicalDevice physical_device, const std::string ext_name) const;
480 
481     bool ValidatePnextStructContents(const char *api_name, const ParameterName &parameter_name, const VkBaseOutStructure *header,
482                                      const char *pnext_vuid) const;
483 
484     /**
485      * Validate a structure's pNext member.
486      *
487      * Verify that the specified pNext value points to the head of a list of
488      * allowed extension structures.  If no extension structures are allowed,
489      * verify that pNext is null.
490      *
491      * @param api_name Name of API call being validated.
492      * @param parameter_name Name of parameter being validated.
493      * @param allowed_struct_names Names of allowed structs.
494      * @param next Pointer to validate.
495      * @param allowed_type_count Total number of allowed structure types.
496      * @param allowed_types Array of structure types allowed for pNext.
497      * @param header_version Version of header defining the pNext validation rules.
498      * @return Boolean value indicating that the call should be skipped.
499      */
validate_struct_pnext(const char * api_name,const ParameterName & parameter_name,const char * allowed_struct_names,const void * next,size_t allowed_type_count,const VkStructureType * allowed_types,uint32_t header_version,const char * pnext_vuid,const char * stype_vuid)500     bool validate_struct_pnext(const char *api_name, const ParameterName &parameter_name, const char *allowed_struct_names,
501                                const void *next, size_t allowed_type_count, const VkStructureType *allowed_types,
502                                uint32_t header_version, const char *pnext_vuid, const char *stype_vuid) const {
503         bool skip_call = false;
504 
505         if (next != NULL) {
506             std::unordered_set<const void *> cycle_check;
507             std::unordered_set<VkStructureType, std::hash<int>> unique_stype_check;
508 
509             const char *disclaimer =
510                 "This error is based on the Valid Usage documentation for version %d of the Vulkan header.  It is possible that "
511                 "you are using a struct from a private extension or an extension that was added to a later version of the Vulkan "
512                 "header, in which case the use of %s is undefined and may not work correctly with validation enabled";
513 
514             if ((allowed_type_count == 0) && (custom_stype_info.size() == 0)) {
515                 std::string message = "%s: value of %s must be NULL. ";
516                 message += disclaimer;
517                 skip_call |= LogError(device, pnext_vuid, message.c_str(), api_name, parameter_name.get_name().c_str(),
518                                       header_version, parameter_name.get_name().c_str());
519             } else {
520                 const VkStructureType *start = allowed_types;
521                 const VkStructureType *end = allowed_types + allowed_type_count;
522                 const VkBaseOutStructure *current = reinterpret_cast<const VkBaseOutStructure *>(next);
523 
524                 while (current != NULL) {
525                     if (((strncmp(api_name, "vkCreateInstance", strlen(api_name)) != 0) ||
526                          (current->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)) &&
527                         ((strncmp(api_name, "vkCreateDevice", strlen(api_name)) != 0) ||
528                          (current->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO))) {
529                         std::string type_name = string_VkStructureType(current->sType);
530                         if (unique_stype_check.find(current->sType) != unique_stype_check.end()) {
531                             // stype_vuid will only be null if there are no listed pNext and will hit disclaimer check
532                             std::string message = "%s: %s chain contains duplicate structure types: %s appears multiple times.";
533                             skip_call |= LogError(device, stype_vuid, message.c_str(), api_name, parameter_name.get_name().c_str(),
534                                                   type_name.c_str());
535                         } else {
536                             unique_stype_check.insert(current->sType);
537                         }
538 
539                         // Search custom stype list -- if sType found, skip this entirely
540                         bool custom = false;
541                         for (auto item : custom_stype_info) {
542                             if (item.first == current->sType) {
543                                 custom = true;
544                                 break;
545                             }
546                         }
547                         if (!custom) {
548                             if (std::find(start, end, current->sType) == end) {
549                                 if (type_name.compare(UnsupportedStructureTypeString) == 0) {
550                                     std::string message =
551                                         "%s: %s chain includes a structure with unknown VkStructureType (%d); Allowed structures "
552                                         "are [%s]. ";
553                                     message += disclaimer;
554                                     skip_call |= LogError(device, pnext_vuid, message.c_str(), api_name,
555                                                           parameter_name.get_name().c_str(), current->sType, allowed_struct_names,
556                                                           header_version, parameter_name.get_name().c_str());
557                                 } else {
558                                     std::string message =
559                                         "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures "
560                                         "are [%s]. ";
561                                     message += disclaimer;
562                                     skip_call |= LogError(device, pnext_vuid, message.c_str(), api_name,
563                                                           parameter_name.get_name().c_str(), type_name.c_str(),
564                                                           allowed_struct_names, header_version, parameter_name.get_name().c_str());
565                                 }
566                             }
567                             skip_call |= ValidatePnextStructContents(api_name, parameter_name, current, pnext_vuid);
568                         }
569                     }
570                     current = reinterpret_cast<const VkBaseOutStructure *>(current->pNext);
571                 }
572             }
573         }
574 
575         return skip_call;
576     }
577 
578     /**
579      * Validate a VkBool32 value.
580      *
581      * Generate an error if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
582      *
583      * @param apiName Name of API call being validated.
584      * @param parameterName Name of parameter being validated.
585      * @param value Boolean value to validate.
586      * @return Boolean value indicating that the call should be skipped.
587      */
validate_bool32(const char * apiName,const ParameterName & parameterName,VkBool32 value)588     bool validate_bool32(const char *apiName, const ParameterName &parameterName, VkBool32 value) const {
589         bool skip_call = false;
590         if ((value != VK_TRUE) && (value != VK_FALSE)) {
591             skip_call |= LogError(device, kVUID_PVError_UnrecognizedValue,
592                                   "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE. Applications MUST not pass any other "
593                                   "values than VK_TRUE or VK_FALSE into a Vulkan implementation where a VkBool32 is expected.",
594                                   apiName, parameterName.get_name().c_str(), value);
595         }
596         return skip_call;
597     }
598 
599     /**
600      * Validate a Vulkan enumeration value.
601      *
602      * Generate a warning if an enumeration token value does not fall within the core enumeration
603      * begin and end token values, and was not added to the enumeration by an extension.  Extension
604      * provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
605      * with 1,000,000,000 as the base token value.
606      *
607      * @note This function does not expect to process enumerations defining bitmask flag bits.
608      *
609      * @param apiName Name of API call being validated.
610      * @param parameterName Name of parameter being validated.
611      * @param enumName Name of the enumeration being validated.
612      * @param valid_values The list of valid values for the enumeration.
613      * @param value Enumeration value to validate.
614      * @return Boolean value indicating that the call should be skipped.
615      */
616     template <typename T>
validate_ranged_enum(const char * apiName,const ParameterName & parameterName,const char * enumName,const std::vector<T> & valid_values,T value,const char * vuid)617     bool validate_ranged_enum(const char *apiName, const ParameterName &parameterName, const char *enumName,
618                               const std::vector<T> &valid_values, T value, const char *vuid) const {
619         bool skip = false;
620 
621         if (std::find(valid_values.begin(), valid_values.end(), value) == valid_values.end()) {
622             skip |=
623                 LogError(device, vuid,
624                          "%s: value of %s (%d) does not fall within the begin..end range of the core %s enumeration tokens and is "
625                          "not an extension added token.",
626                          apiName, parameterName.get_name().c_str(), value, enumName);
627         }
628 
629         return skip;
630     }
631 
632     /**
633      * Validate an array of Vulkan enumeration value.
634      *
635      * Process all enumeration token values in the specified array and generate a warning if a value
636      * does not fall within the core enumeration begin and end token values, and was not added to
637      * the enumeration by an extension.  Extension provided enumerations use the equation specified
638      * in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
639      *
640      * @note This function does not expect to process enumerations defining bitmask flag bits.
641      *
642      * @param apiName Name of API call being validated.
643      * @param countName Name of count parameter.
644      * @param arrayName Name of array parameter.
645      * @param enumName Name of the enumeration being validated.
646      * @param valid_values The list of valid values for the enumeration.
647      * @param count Number of enumeration values in the array.
648      * @param array Array of enumeration values to validate.
649      * @param countRequired The 'count' parameter may not be 0 when true.
650      * @param arrayRequired The 'array' parameter may not be NULL when true.
651      * @return Boolean value indicating that the call should be skipped.
652      */
653     template <typename T>
validate_ranged_enum_array(const char * apiName,const ParameterName & countName,const ParameterName & arrayName,const char * enumName,const std::vector<T> & valid_values,uint32_t count,const T * array,bool countRequired,bool arrayRequired)654     bool validate_ranged_enum_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName,
655                                     const char *enumName, const std::vector<T> &valid_values, uint32_t count, const T *array,
656                                     bool countRequired, bool arrayRequired) const {
657         bool skip_call = false;
658 
659         if ((count == 0) || (array == NULL)) {
660             skip_call |= validate_array(apiName, countName, arrayName, count, &array, countRequired, arrayRequired, kVUIDUndefined,
661                                         kVUIDUndefined);
662         } else {
663             for (uint32_t i = 0; i < count; ++i) {
664                 if (std::find(valid_values.begin(), valid_values.end(), array[i]) == valid_values.end()) {
665                     skip_call |= LogError(device, kVUID_PVError_UnrecognizedValue,
666                                           "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
667                                           "enumeration tokens and is not an extension added token",
668                                           apiName, arrayName.get_name().c_str(), i, array[i], enumName);
669                 }
670             }
671         }
672 
673         return skip_call;
674     }
675 
676     /**
677      * Verify that a reserved VkFlags value is zero.
678      *
679      * Verify that the specified value is zero, to check VkFlags values that are reserved for
680      * future use.
681      *
682      * @param api_name Name of API call being validated.
683      * @param parameter_name Name of parameter being validated.
684      * @param value Value to validate.
685      * @return Boolean value indicating that the call should be skipped.
686      */
validate_reserved_flags(const char * api_name,const ParameterName & parameter_name,VkFlags value,const char * vuid)687     bool validate_reserved_flags(const char *api_name, const ParameterName &parameter_name, VkFlags value, const char *vuid) const {
688         bool skip_call = false;
689 
690         if (value != 0) {
691             skip_call |= LogError(device, vuid, "%s: parameter %s must be 0.", api_name, parameter_name.get_name().c_str());
692         }
693 
694         return skip_call;
695     }
696 
697     enum FlagType { kRequiredFlags, kOptionalFlags, kRequiredSingleBit, kOptionalSingleBit };
698 
699     /**
700      * Validate a Vulkan bitmask value.
701      *
702      * Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
703      * for that type.
704      *
705      * @param api_name Name of API call being validated.
706      * @param parameter_name Name of parameter being validated.
707      * @param flag_bits_name Name of the VkFlags type being validated.
708      * @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated.
709      * @param value VkFlags value to validate.
710      * @param flag_type The type of flag, like optional, or single bit.
711      * @param vuid VUID used for flag that is outside defined bits (or has more than one bit for Bits type).
712      * @param flags_zero_vuid VUID used for non-optional Flags that are zero.
713      * @return Boolean value indicating that the call should be skipped.
714      */
715     bool validate_flags(const char *api_name, const ParameterName &parameter_name, const char *flag_bits_name, VkFlags all_flags,
716                         VkFlags value, const FlagType flag_type, const char *vuid, const char *flags_zero_vuid = nullptr) const {
717         bool skip_call = false;
718 
719         if ((value & ~all_flags) != 0) {
720             skip_call |= LogError(device, vuid, "%s: value of %s contains flag bits that are not recognized members of %s",
721                                   api_name, parameter_name.get_name().c_str(), flag_bits_name);
722         }
723 
724         const bool required = flag_type == kRequiredFlags || flag_type == kRequiredSingleBit;
725         const char *zero_vuid = flag_type == kRequiredFlags ? flags_zero_vuid : vuid;
726         if (required && value == 0) {
727             skip_call |= LogError(device, zero_vuid, "%s: value of %s must not be 0.", api_name, parameter_name.get_name().c_str());
728         }
729 
730         const auto HasMaxOneBitSet = [](const VkFlags f) {
731             // Decrement flips bits from right upto first 1.
732             // Rest stays same, and if there was any other 1s &ded together they would be non-zero. QED
733             return f == 0 || !(f & (f - 1));
734         };
735 
736         const bool is_bits_type = flag_type == kRequiredSingleBit || flag_type == kOptionalSingleBit;
737         if (is_bits_type && !HasMaxOneBitSet(value)) {
738             skip_call |=
739                 LogError(device, vuid, "%s: value of %s contains multiple members of %s when only a single value is allowed",
740                          api_name, parameter_name.get_name().c_str(), flag_bits_name);
741         }
742 
743         return skip_call;
744     }
745 
746     /**
747      * Validate an array of Vulkan bitmask values.
748      *
749      * Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
750      * for that type.
751      *
752      * @param api_name Name of API call being validated.
753      * @param count_name Name of parameter being validated.
754      * @param array_name Name of parameter being validated.
755      * @param flag_bits_name Name of the VkFlags type being validated.
756      * @param all_flags A bitmask combining all valid flag bits for the VkFlags type being validated.
757      * @param count Number of VkFlags values in the array.
758      * @param array Array of VkFlags value to validate.
759      * @param count_required The 'count' parameter may not be 0 when true.
760      * @param array_required The 'array' parameter may not be NULL when true.
761      * @return Boolean value indicating that the call should be skipped.
762      */
validate_flags_array(const char * api_name,const ParameterName & count_name,const ParameterName & array_name,const char * flag_bits_name,VkFlags all_flags,uint32_t count,const VkFlags * array,bool count_required,bool array_required)763     bool validate_flags_array(const char *api_name, const ParameterName &count_name, const ParameterName &array_name,
764                               const char *flag_bits_name, VkFlags all_flags, uint32_t count, const VkFlags *array,
765                               bool count_required, bool array_required) const {
766         bool skip_call = false;
767 
768         if ((count == 0) || (array == NULL)) {
769             skip_call |= validate_array(api_name, count_name, array_name, count, &array, count_required, array_required,
770                                         kVUIDUndefined, kVUIDUndefined);
771         } else {
772             // Verify that all VkFlags values in the array
773             for (uint32_t i = 0; i < count; ++i) {
774                 if (array[i] == 0) {
775                     // Current XML registry logic for validity generation uses the array parameter's optional tag to determine if
776                     // elements in the array are allowed be 0
777                     if (array_required) {
778                         skip_call |= LogError(device, kVUID_PVError_RequiredParameter, "%s: value of %s[%d] must not be 0",
779                                               api_name, array_name.get_name().c_str(), i);
780                     }
781                 } else if ((array[i] & (~all_flags)) != 0) {
782                     skip_call |= LogError(device, kVUID_PVError_UnrecognizedValue,
783                                           "%s: value of %s[%d] contains flag bits that are not recognized members of %s", api_name,
784                                           array_name.get_name().c_str(), i, flag_bits_name);
785                 }
786             }
787         }
788 
789         return skip_call;
790     }
791 
792     template <typename ExtensionState>
validate_extension_reqs(const ExtensionState & extensions,const char * vuid,const char * extension_type,const char * extension_name)793     bool validate_extension_reqs(const ExtensionState &extensions, const char *vuid, const char *extension_type,
794                                  const char *extension_name) const {
795         bool skip = false;
796         if (!extension_name) {
797             return skip;  // Robust to invalid char *
798         }
799         auto info = ExtensionState::get_info(extension_name);
800 
801         if (!info.state) {
802             return skip;  // Unknown extensions cannot be checked so report OK
803         }
804 
805         // Check against the required list in the info
806         std::vector<const char *> missing;
807         for (const auto &req : info.requirements) {
808             if (!(extensions.*(req.enabled))) {
809                 missing.push_back(req.name);
810             }
811         }
812 
813         // Report any missing requirements
814         if (missing.size()) {
815             std::string missing_joined_list = string_join(", ", missing);
816             skip |= LogError(instance, vuid, "Missing extension%s required by the %s extension %s: %s.",
817                              ((missing.size() > 1) ? "s" : ""), extension_type, extension_name, missing_joined_list.c_str());
818         }
819         return skip;
820     }
821 
822     enum RenderPassCreateVersion { RENDER_PASS_VERSION_1 = 0, RENDER_PASS_VERSION_2 = 1 };
823 
824     template <typename RenderPassCreateInfoGeneric>
ValidateSubpassGraphicsFlags(const debug_report_data * report_data,const RenderPassCreateInfoGeneric * pCreateInfo,uint32_t dependency_index,uint32_t subpass,VkPipelineStageFlags stages,const char * vuid,const char * target,const char * func_name)825     bool ValidateSubpassGraphicsFlags(const debug_report_data *report_data, const RenderPassCreateInfoGeneric *pCreateInfo,
826                                       uint32_t dependency_index, uint32_t subpass, VkPipelineStageFlags stages, const char *vuid,
827                                       const char *target, const char *func_name) const {
828         const VkPipelineStageFlags kCommonStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
829         const VkPipelineStageFlags kFramebufferStages =
830             VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
831             VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
832         const VkPipelineStageFlags kPrimitiveShadingPipelineStages =
833             kCommonStages | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
834             VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
835             VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
836             VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT | VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV | kFramebufferStages;
837         const VkPipelineStageFlags kMeshShadingPipelineStages =
838             kCommonStages | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV |
839             VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV | VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV | kFramebufferStages;
840         const VkPipelineStageFlags kFragmentDensityStages = VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT;
841         const VkPipelineStageFlags kConditionalRenderingStages = VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT;
842         const VkPipelineStageFlags kCommandProcessingPipelineStages = kCommonStages | VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV;
843 
844         const VkPipelineStageFlags kGraphicsStages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | kPrimitiveShadingPipelineStages |
845                                                      kMeshShadingPipelineStages | kFragmentDensityStages |
846                                                      kConditionalRenderingStages | kCommandProcessingPipelineStages;
847 
848         bool skip = false;
849 
850         const auto IsPipeline = [pCreateInfo](uint32_t subpass, const VkPipelineBindPoint stage) {
851             if (subpass == VK_SUBPASS_EXTERNAL)
852                 return false;
853             else
854                 return pCreateInfo->pSubpasses[subpass].pipelineBindPoint == stage;
855         };
856 
857         const bool is_all_graphics_stages = (stages & ~kGraphicsStages) == 0;
858         if (IsPipeline(subpass, VK_PIPELINE_BIND_POINT_GRAPHICS) && !is_all_graphics_stages) {
859             skip |= LogError(VkRenderPass(0), vuid,
860                              "%s: Dependency pDependencies[%" PRIu32
861                              "] specifies a %sStageMask that contains stages (%s) that are not part "
862                              "of the Graphics pipeline, as specified by the %sSubpass (= %" PRIu32 ") in pipelineBindPoint.",
863                              func_name, dependency_index, target, string_VkPipelineStageFlags(stages & ~kGraphicsStages).c_str(),
864                              target, subpass);
865         }
866 
867         return skip;
868     };
869 
870     template <typename RenderPassCreateInfoGeneric>
CreateRenderPassGeneric(VkDevice device,const RenderPassCreateInfoGeneric * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass,RenderPassCreateVersion rp_version)871     bool CreateRenderPassGeneric(VkDevice device, const RenderPassCreateInfoGeneric *pCreateInfo,
872                                  const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass,
873                                  RenderPassCreateVersion rp_version) const {
874         bool skip = false;
875         uint32_t max_color_attachments = device_limits.maxColorAttachments;
876         bool use_rp2 = (rp_version == RENDER_PASS_VERSION_2);
877         const char *func_name = (use_rp2) ? "vkCreateRenderPass2" : "vkCreateRenderPass";
878         const char *vuid;
879         VkBool32 separate_depth_stencil_layouts = false;
880         const auto *vulkan_12_features = lvl_find_in_chain<VkPhysicalDeviceVulkan12Features>(device_createinfo_pnext);
881         if (vulkan_12_features) {
882             separate_depth_stencil_layouts = vulkan_12_features->separateDepthStencilLayouts;
883         } else {
884             const auto *separate_depth_stencil_layouts_features =
885                 lvl_find_in_chain<VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR>(device_createinfo_pnext);
886             if (separate_depth_stencil_layouts_features)
887                 separate_depth_stencil_layouts = separate_depth_stencil_layouts_features->separateDepthStencilLayouts;
888         }
889 
890         for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
891             const auto *attachment_description_stencil_layout =
892                 (use_rp2) ? lvl_find_in_chain<VkAttachmentDescriptionStencilLayoutKHR>(
893                                 reinterpret_cast<VkAttachmentDescription2KHR const *>(&pCreateInfo->pAttachments[i])->pNext)
894                           : 0;
895 
896             const VkFormat attachment_format = pCreateInfo->pAttachments[i].format;
897             const VkImageLayout initial_layout = pCreateInfo->pAttachments[i].initialLayout;
898             const VkImageLayout final_layout = pCreateInfo->pAttachments[i].finalLayout;
899             if (attachment_format == VK_FORMAT_UNDEFINED) {
900                 vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-parameter" : "VUID-VkAttachmentDescription-format-parameter";
901                 skip |= LogWarning(device, vuid, "%s: pCreateInfo->pAttachments[%u].format is VK_FORMAT_UNDEFINED.", func_name, i);
902             }
903             if (final_layout == VK_IMAGE_LAYOUT_UNDEFINED || final_layout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
904                 vuid =
905                     use_rp2 ? "VUID-VkAttachmentDescription2-finalLayout-03061" : "VUID-VkAttachmentDescription-finalLayout-00843";
906                 skip |= LogError(device, vuid,
907                                  "%s: pCreateInfo->pAttachments[%d].finalLayout must not be VK_IMAGE_LAYOUT_UNDEFINED or "
908                                  "VK_IMAGE_LAYOUT_PREINITIALIZED.",
909                                  func_name, i);
910             }
911             if (!separate_depth_stencil_layouts) {
912                 if (pCreateInfo->pAttachments[i].initialLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
913                     pCreateInfo->pAttachments[i].initialLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
914                     pCreateInfo->pAttachments[i].initialLayout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
915                     pCreateInfo->pAttachments[i].initialLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
916                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03298"
917                                    : "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03284";
918                     skip |= LogError(
919                         device, vuid,
920                         "%s: pCreateInfo->pAttachments[%d].initialLayout must not be VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, "
921                         "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
922                         "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
923                         func_name, i);
924                 }
925                 if (final_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
926                     final_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
927                     final_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
928                     final_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
929                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-separateDepthStencilLayouts-03299"
930                                    : "VUID-VkAttachmentDescription-separateDepthStencilLayouts-03285";
931                     skip |= LogError(
932                         device, vuid,
933                         "%s: pCreateInfo->pAttachments[%d].finalLayout must not be VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, "
934                         "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
935                         "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
936                         func_name, i);
937                 }
938             }
939             if (!FormatIsDepthOrStencil(attachment_format)) {
940                 if (initial_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
941                     initial_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
942                     initial_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
943                     initial_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
944                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03300" : "VUID-VkAttachmentDescription-format-03286";
945                     skip |= LogError(
946                         device, vuid,
947                         "%s: pCreateInfo->pAttachments[%d].initialLayout must not be VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, "
948                         "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
949                         "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMA_KHRL",
950                         func_name, i);
951                 }
952                 if (final_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
953                     final_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
954                     final_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
955                     final_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
956                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03301" : "VUID-VkAttachmentDescription-format-03287";
957                     skip |= LogError(
958                         device, vuid,
959                         "%s: pCreateInfo->pAttachments[%d].finalLayout must not be VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, "
960                         "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
961                         "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
962                         func_name, i);
963                 }
964             } else if (FormatIsDepthAndStencil(attachment_format)) {
965                 if (use_rp2) {
966                     if (!attachment_description_stencil_layout) {
967                         if (initial_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
968                             initial_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR) {
969                             skip |= LogError(
970                                 device, "VUID-VkAttachmentDescription2-format-03302",
971                                 "%s: pCreateInfo->pNext must include an instance of VkAttachmentDescriptionStencilLayoutKHR",
972                                 func_name);
973                         }
974                         if (final_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
975                             final_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR) {
976                             skip |= LogError(
977                                 device, "VUID-VkAttachmentDescription2-format-03303",
978                                 "%s: pCreateInfo->pNext must include an instance of VkAttachmentDescriptionStencilLayoutKHR",
979                                 func_name);
980                         }
981                     }
982                 } else {
983                     if (initial_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
984                         initial_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
985                         initial_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
986                         initial_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
987                         skip |= LogError(
988                             device, "VUID-VkAttachmentDescription-format-03288",
989                             "%s: pCreateInfo->pAttachments[%d].initialLayout must not be "
990                             "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, "
991                             "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
992                             "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
993                             func_name, i);
994                     }
995                     if (final_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
996                         final_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
997                         final_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
998                         final_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
999                         skip |= LogError(
1000                             device, "VUID-VkAttachmentDescription-format-03289",
1001                             "%s: pCreateInfo->pAttachments[%d].finalLayout must not be "
1002                             "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, "
1003                             "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
1004                             "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
1005                             func_name, i);
1006                     }
1007                 }
1008             } else if (FormatIsDepthOnly(attachment_format)) {
1009                 if (initial_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
1010                     initial_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
1011                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03304" : "VUID-VkAttachmentDescription-format-03290";
1012                     skip |= LogError(device, vuid,
1013                                      "%s: pCreateInfo->pAttachments[%d].initialLayout must not be "
1014                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, or"
1015                                      "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
1016                                      func_name, i);
1017                 }
1018                 if (final_layout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR ||
1019                     final_layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR) {
1020                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03305" : "VUID-VkAttachmentDescription-format-03291";
1021                     skip |= LogError(device, vuid,
1022                                      "%s: pCreateInfo->pAttachments[%d].finalLayout must not be "
1023                                      "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR, or "
1024                                      "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR",
1025                                      func_name, i);
1026                 }
1027             } else if (FormatIsStencilOnly(attachment_format)) {
1028                 if (initial_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
1029                     initial_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR) {
1030                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03306" : "VUID-VkAttachmentDescription-format-03292";
1031                     skip |= LogError(device, vuid,
1032                                      "%s: pCreateInfo->pAttachments[%d].initialLayout must not be "
1033                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, or"
1034                                      "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR",
1035                                      func_name, i);
1036                 }
1037                 if (final_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
1038                     final_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR) {
1039                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03307" : "VUID-VkAttachmentDescription-format-03293";
1040                     skip |= LogError(device, vuid,
1041                                      "%s: pCreateInfo->pAttachments[%d].finalLayout must not be "
1042                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, or "
1043                                      "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMA_KHRL",
1044                                      func_name, i);
1045                 }
1046             }
1047             if (use_rp2 && attachment_description_stencil_layout) {
1048                 if (attachment_description_stencil_layout->stencilInitialLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ||
1049                     attachment_description_stencil_layout->stencilInitialLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
1050                     attachment_description_stencil_layout->stencilInitialLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
1051                     attachment_description_stencil_layout->stencilInitialLayout ==
1052                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
1053                     attachment_description_stencil_layout->stencilInitialLayout ==
1054                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1055                     attachment_description_stencil_layout->stencilInitialLayout ==
1056                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
1057                     attachment_description_stencil_layout->stencilInitialLayout ==
1058                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) {
1059                     skip |= LogError(device, "VUID-VkAttachmentDescriptionStencilLayout-stencilInitialLayout-03308",
1060                                      "%s: VkAttachmentDescriptionStencilLayoutKHR.stencilInitialLayout must not be "
1061                                      "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
1062                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, "
1063                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
1064                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
1065                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, or "
1066                                      "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL.",
1067                                      func_name);
1068                 }
1069                 if (attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ||
1070                     attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR ||
1071                     attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR ||
1072                     attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
1073                     attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1074                     attachment_description_stencil_layout->stencilFinalLayout ==
1075                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
1076                     attachment_description_stencil_layout->stencilFinalLayout ==
1077                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) {
1078                     skip |= LogError(device, "VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03309",
1079                                      "%s: VkAttachmentDescriptionStencilLayoutKHR.stencilFinalLayout must not be "
1080                                      "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
1081                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR, "
1082                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
1083                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
1084                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, or "
1085                                      "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL.",
1086                                      func_name);
1087                 }
1088                 if (attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_UNDEFINED ||
1089                     attachment_description_stencil_layout->stencilFinalLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
1090                     skip |= LogError(
1091                         device, "VUID-VkAttachmentDescriptionStencilLayout-stencilFinalLayout-03310",
1092                         "%s: VkAttachmentDescriptionStencilLayoutKHR.stencilFinalLayout must not be VK_IMAGE_LAYOUT_UNDEFINED, or "
1093                         "VK_IMAGE_LAYOUT_PREINITIALIZED.",
1094                         func_name);
1095                 }
1096             }
1097 
1098             if (FormatIsDepthOrStencil(attachment_format)) {
1099                 if (initial_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
1100                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03295" : "VUID-VkAttachmentDescription-format-03281";
1101                     skip |= LogError(device, vuid,
1102                                      "%s: pCreateInfo->pAttachments[%d].initialLayout must not be "
1103                                      "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL when using a Depth or Stencil format",
1104                                      func_name, i);
1105                 }
1106                 if (final_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
1107                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03297" : "VUID-VkAttachmentDescription-format-03283";
1108                     skip |= LogError(device, vuid,
1109                                      "%s: pCreateInfo->pAttachments[%d].finalLayout must not be "
1110                                      "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL when using a Depth or Stencil format",
1111                                      func_name, i);
1112                 }
1113             }
1114             if (FormatIsColor(attachment_format)) {
1115                 if (initial_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
1116                     initial_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1117                     initial_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
1118                     initial_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) {
1119                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03294" : "VUID-VkAttachmentDescription-format-03280";
1120                     skip |= LogError(device, vuid,
1121                                      "%s: pCreateInfo->pAttachments[%d].initialLayout must not be "
1122                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
1123                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
1124                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, or "
1125                                      "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL when using a Color format",
1126                                      func_name, i);
1127                 }
1128                 if (final_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
1129                     final_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ||
1130                     final_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
1131                     final_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) {
1132                     vuid = use_rp2 ? "VUID-VkAttachmentDescription2-format-03296" : "VUID-VkAttachmentDescription-format-03282";
1133                     skip |= LogError(device, vuid,
1134                                      "%s: pCreateInfo->pAttachments[%d].finalLayout must not be "
1135                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "
1136                                      "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "
1137                                      "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, or "
1138                                      "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL when using a Color format",
1139                                      func_name, i);
1140                 }
1141             }
1142         }
1143 
1144         for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
1145             if (pCreateInfo->pSubpasses[i].colorAttachmentCount > max_color_attachments) {
1146                 vuid = use_rp2 ? "VUID-VkSubpassDescription2-colorAttachmentCount-03063"
1147                                : "VUID-VkSubpassDescription-colorAttachmentCount-00845";
1148                 skip |=
1149                     LogError(device, vuid,
1150                              "%s: Cannot create a render pass with %d color attachments in pCreateInfo->pSubpasses[%u]. Max is %d.",
1151                              func_name, pCreateInfo->pSubpasses[i].colorAttachmentCount, i, max_color_attachments);
1152             }
1153         }
1154 
1155         for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
1156             const auto &dependency = pCreateInfo->pDependencies[i];
1157 
1158             // Need to check first so layer doesn't segfault from out of bound array access
1159             // src subpass bound check
1160             if ((dependency.srcSubpass != VK_SUBPASS_EXTERNAL) && (dependency.srcSubpass >= pCreateInfo->subpassCount)) {
1161                 vuid = use_rp2 ? "VUID-VkRenderPassCreateInfo2-srcSubpass-02526" : "VUID-VkRenderPassCreateInfo-srcSubpass-02517";
1162                 skip |= LogError(device, vuid,
1163                                  "%s: pCreateInfo->pDependencies[%u].srcSubpass index (%u) has to be less than subpassCount (%u)",
1164                                  func_name, i, dependency.srcSubpass, pCreateInfo->subpassCount);
1165             }
1166 
1167             // dst subpass bound check
1168             if ((dependency.dstSubpass != VK_SUBPASS_EXTERNAL) && (dependency.dstSubpass >= pCreateInfo->subpassCount)) {
1169                 vuid = use_rp2 ? "VUID-VkRenderPassCreateInfo2-dstSubpass-02527" : "VUID-VkRenderPassCreateInfo-dstSubpass-02518";
1170                 skip |= LogError(device, vuid,
1171                                  "%s: pCreateInfo->pDependencies[%u].dstSubpass index (%u) has to be less than subpassCount (%u)",
1172                                  func_name, i, dependency.dstSubpass, pCreateInfo->subpassCount);
1173             }
1174 
1175             // Spec currently only supports Graphics pipeline in render pass -- so only that pipeline is currently checked
1176             vuid = use_rp2 ? "VUID-VkRenderPassCreateInfo2-pDependencies-03054" : "VUID-VkRenderPassCreateInfo-pDependencies-00837";
1177             skip |= ValidateSubpassGraphicsFlags(report_data, pCreateInfo, i, dependency.srcSubpass, dependency.srcStageMask, vuid,
1178                                                  "src", func_name);
1179 
1180             vuid = use_rp2 ? "VUID-VkRenderPassCreateInfo2-pDependencies-03055" : "VUID-VkRenderPassCreateInfo-pDependencies-00838";
1181             skip |= ValidateSubpassGraphicsFlags(report_data, pCreateInfo, i, dependency.dstSubpass, dependency.dstStageMask, vuid,
1182                                                  "dst", func_name);
1183         }
1184 
1185         return skip;
1186     }
1187 
1188     template <typename T>
RecordRenderPass(VkRenderPass renderPass,const T * pCreateInfo)1189     void RecordRenderPass(VkRenderPass renderPass, const T *pCreateInfo) {
1190         std::unique_lock<std::mutex> lock(renderpass_map_mutex);
1191         auto &renderpass_state = renderpasses_states[renderPass];
1192         lock.unlock();
1193 
1194         for (uint32_t subpass = 0; subpass < pCreateInfo->subpassCount; ++subpass) {
1195             bool uses_color = false;
1196             for (uint32_t i = 0; i < pCreateInfo->pSubpasses[subpass].colorAttachmentCount && !uses_color; ++i)
1197                 if (pCreateInfo->pSubpasses[subpass].pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) uses_color = true;
1198 
1199             bool uses_depthstencil = false;
1200             if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment)
1201                 if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
1202                     uses_depthstencil = true;
1203 
1204             if (uses_color) renderpass_state.subpasses_using_color_attachment.insert(subpass);
1205             if (uses_depthstencil) renderpass_state.subpasses_using_depthstencil_attachment.insert(subpass);
1206         }
1207     }
1208 
1209     bool require_device_extension(bool flag, char const *function_name, char const *extension_name) const;
1210 
1211     bool validate_instance_extensions(const VkInstanceCreateInfo *pCreateInfo) const;
1212 
1213     bool validate_validation_features(const VkInstanceCreateInfo *pCreateInfo,
1214                                       const VkValidationFeaturesEXT *validation_features) const;
1215 
1216     bool validate_api_version(uint32_t api_version, uint32_t effective_api_version) const;
1217 
1218     bool validate_string(const char *apiName, const ParameterName &stringName, const std::string &vuid,
1219                          const char *validateString) const;
1220 
1221     bool ValidateCoarseSampleOrderCustomNV(const VkCoarseSampleOrderCustomNV *order) const;
1222 
1223     bool ValidateQueueFamilies(uint32_t queue_family_count, const uint32_t *queue_families, const char *cmd_name,
1224                                const char *array_parameter_name, const std::string &unique_error_code,
1225                                const std::string &valid_error_code, bool optional);
1226 
1227     bool ValidateDeviceQueueFamily(uint32_t queue_family, const char *cmd_name, const char *parameter_name,
1228                                    const std::string &error_code, bool optional);
1229 
1230     bool ValidateGeometryTrianglesNV(const VkGeometryTrianglesNV &triangles, VkAccelerationStructureNV object_handle,
1231                                      const char *func_name) const;
1232     bool ValidateGeometryAABBNV(const VkGeometryAABBNV &geometry, VkAccelerationStructureNV object_handle,
1233                                 const char *func_name) const;
1234     bool ValidateGeometryNV(const VkGeometryNV &geometry, VkAccelerationStructureNV object_handle, const char *func_name) const;
1235     bool ValidateAccelerationStructureInfoNV(const VkAccelerationStructureInfoNV &info, VkAccelerationStructureNV object_handle,
1236                                              const char *func_nam, bool is_cmd) const;
1237     bool ValidateCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1238                                               const VkAllocationCallbacks *pAllocator, VkSamplerYcbcrConversion *pYcbcrConversion,
1239                                               const char *apiName) const;
1240     bool ValidateCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkDeviceSize offset, VkDeviceSize countBufferOffset,
1241                                       bool khr) const;
1242     bool ValidateCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkDeviceSize offset, VkDeviceSize countBufferOffset,
1243                                              bool khr) const;
1244 
1245     bool OutputExtensionError(const std::string &api_name, const std::string &extension_name) const;
1246 
1247     void PostCallRecordCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
1248                                         const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass, VkResult result);
1249     void PostCallRecordCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo,
1250                                             const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass, VkResult result);
1251     void PostCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator);
1252     void PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
1253                                     const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result);
1254 
1255     void PostCallRecordCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1256                                       VkInstance *pInstance, VkResult result);
1257 
1258     void PreCallRecordDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator);
1259 
1260     bool manual_PreCallValidateCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
1261                                                const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) const;
1262 
1263     bool manual_PreCallValidateCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1264                                               VkInstance *pInstance) const;
1265 
1266     bool manual_PreCallValidateCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
1267                                             const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) const;
1268 
1269     bool manual_PreCallValidateCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
1270                                             const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) const;
1271 
1272     bool manual_PreCallValidateCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
1273                                            const VkAllocationCallbacks *pAllocator, VkImage *pImage) const;
1274 
1275     bool manual_PreCallValidateCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
1276                                                const VkAllocationCallbacks *pAllocator, VkImageView *pView) const;
1277 
1278     bool manual_PreCallValidateViewport(const VkViewport &viewport, const char *fn_name, const ParameterName &parameter_name,
1279                                         VkCommandBuffer object) const;
1280 
1281     bool manual_PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
1282                                                        const VkGraphicsPipelineCreateInfo *pCreateInfos,
1283                                                        const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) const;
1284     bool manual_PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
1285                                                       const VkComputePipelineCreateInfo *pCreateInfos,
1286                                                       const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) const;
1287 
1288     bool manual_PreCallValidateCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
1289                                              const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) const;
1290     bool manual_PreCallValidateCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
1291                                                          const VkAllocationCallbacks *pAllocator,
1292                                                          VkDescriptorSetLayout *pSetLayout) const;
1293 
1294     bool validate_WriteDescriptorSet(const char *vkCallingFunction, const uint32_t descriptorWriteCount,
1295                                      const VkWriteDescriptorSet *pDescriptorWrites, const bool validateDstSet = true) const;
1296     bool manual_PreCallValidateUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
1297                                                     const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
1298                                                     const VkCopyDescriptorSet *pDescriptorCopies) const;
1299 
1300     bool manual_PreCallValidateFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount,
1301                                                   const VkDescriptorSet *pDescriptorSets) const;
1302 
1303     bool manual_PreCallValidateCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
1304                                                 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const;
1305 
1306     bool manual_PreCallValidateCreateRenderPass2(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
1307                                                  const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const;
1308 
1309     bool manual_PreCallValidateCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo,
1310                                                     const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const;
1311 
1312     bool manual_PreCallValidateFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
1313                                                   const VkCommandBuffer *pCommandBuffers) const;
1314 
1315     bool manual_PreCallValidateBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) const;
1316 
1317     bool manual_PreCallValidateCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount,
1318                                               const VkViewport *pViewports) const;
1319 
1320     bool manual_PreCallValidateCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount,
1321                                              const VkRect2D *pScissors) const;
1322     bool manual_PreCallValidateCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) const;
1323 
1324     bool manual_PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1325                                                uint32_t stride) const;
1326 
1327     bool manual_PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1328                                                       uint32_t count, uint32_t stride) const;
1329 
1330     bool manual_PreCallValidateCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1331                                                     VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1332                                                     uint32_t stride) const;
1333 
1334     bool manual_PreCallValidateCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1335                                                        VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1336                                                        uint32_t stride) const;
1337 
1338     bool manual_PreCallValidateCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1339                                                            VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1340                                                            uint32_t maxDrawCount, uint32_t stride) const;
1341 
1342     bool manual_PreCallValidateCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1343                                                               VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1344                                                               uint32_t maxDrawCount, uint32_t stride) const;
1345 
1346     bool manual_PreCallValidateCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
1347                                                    const VkClearAttachment *pAttachments, uint32_t rectCount,
1348                                                    const VkClearRect *pRects) const;
1349 
1350     bool ValidateGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
1351                                                          const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
1352                                                          VkImageFormatProperties2 *pImageFormatProperties,
1353                                                          const char *apiName) const;
1354     bool manual_PreCallValidateGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
1355                                                                        const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
1356                                                                        VkImageFormatProperties2 *pImageFormatProperties) const;
1357     bool manual_PreCallValidateGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice,
1358                                                                           const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
1359                                                                           VkImageFormatProperties2 *pImageFormatProperties) const;
1360 
1361     bool manual_PreCallValidateCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
1362                                              uint32_t regionCount, const VkBufferCopy *pRegions) const;
1363 
1364     bool manual_PreCallValidateCmdCopyBuffer2KHR(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR *pCopyBufferInfo) const;
1365 
1366     bool manual_PreCallValidateCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
1367                                                VkDeviceSize dataSize, const void *pData) const;
1368 
1369     bool manual_PreCallValidateCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
1370                                              VkDeviceSize size, uint32_t data) const;
1371 
1372     bool manual_PreCallValidateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1373                                                   const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) const;
1374     bool manual_PreCallValidateQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) const;
1375 
1376 #ifdef VK_USE_PLATFORM_WIN32_KHR
1377     bool manual_PreCallValidateCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
1378                                                      const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) const;
1379 #endif  // VK_USE_PLATFORM_WIN32_KHR
1380 
1381     bool manual_PreCallValidateCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
1382                                                     const VkAllocationCallbacks *pAllocator,
1383                                                     VkDescriptorPool *pDescriptorPool) const;
1384     bool manual_PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY,
1385                                            uint32_t groupCountZ) const;
1386 
1387     bool manual_PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) const;
1388 
1389     bool manual_PreCallValidateCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1390                                                   uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1391                                                   uint32_t groupCountZ) const;
1392     bool manual_PreCallValidateCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
1393                                                        VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
1394                                                        const VkWriteDescriptorSet *pDescriptorWrites) const;
1395     bool manual_PreCallValidateCmdSetExclusiveScissorNV(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor,
1396                                                         uint32_t exclusiveScissorCount, const VkRect2D *pExclusiveScissors) const;
1397     bool manual_PreCallValidateCmdSetViewportShadingRatePaletteNV(VkCommandBuffer commandBuffer, uint32_t firstViewport,
1398                                                                   uint32_t viewportCount,
1399                                                                   const VkShadingRatePaletteNV *pShadingRatePalettes) const;
1400 
1401     bool manual_PreCallValidateCmdSetCoarseSampleOrderNV(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType,
1402                                                          uint32_t customSampleOrderCount,
1403                                                          const VkCoarseSampleOrderCustomNV *pCustomSampleOrders) const;
1404 
1405     bool manual_PreCallValidateCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) const;
1406     bool manual_PreCallValidateCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1407                                                           uint32_t drawCount, uint32_t stride) const;
1408 
1409     bool manual_PreCallValidateCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1410                                                                VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1411                                                                uint32_t maxDrawCount, uint32_t stride) const;
1412 
1413     bool manual_PreCallValidateEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
1414                                                                   uint32_t *pPropertyCount,
1415                                                                   VkExtensionProperties *pProperties) const;
1416     bool manual_PreCallValidateAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
1417                                               const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) const;
1418 
1419     bool manual_PreCallValidateCreateAccelerationStructureNV(VkDevice device,
1420                                                              const VkAccelerationStructureCreateInfoNV *pCreateInfo,
1421                                                              const VkAllocationCallbacks *pAllocator,
1422                                                              VkAccelerationStructureNV *pAccelerationStructure) const;
1423     bool manual_PreCallValidateCreateAccelerationStructureKHR(VkDevice device,
1424                                                               const VkAccelerationStructureCreateInfoKHR *pCreateInfo,
1425                                                               const VkAllocationCallbacks *pAllocator,
1426                                                               VkAccelerationStructureKHR *pAccelerationStructure) const;
1427     bool manual_PreCallValidateCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
1428                                                                const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
1429                                                                VkDeviceSize instanceOffset, VkBool32 update,
1430                                                                VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
1431                                                                VkBuffer scratch, VkDeviceSize scratchOffset) const;
1432     bool manual_PreCallValidateGetAccelerationStructureHandleNV(VkDevice device, VkAccelerationStructureNV accelerationStructure,
1433                                                                 size_t dataSize, void *pData) const;
1434     bool manual_PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
1435                                                            const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1436                                                            const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) const;
1437     bool manual_PreCallValidateCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache,
1438                                                             uint32_t createInfoCount,
1439                                                             const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1440                                                             const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) const;
1441     bool manual_PreCallValidateCmdSetViewportWScalingNV(VkCommandBuffer commandBuffer, uint32_t firstViewport,
1442                                                         uint32_t viewportCount,
1443                                                         const VkViewportWScalingNV *pViewportWScalings) const;
1444 
1445 #ifdef VK_USE_PLATFORM_WIN32_KHR
1446     bool PreCallValidateGetDeviceGroupSurfacePresentModes2EXT(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
1447                                                               VkDeviceGroupPresentModeFlagsKHR *pModes) const;
1448 #endif  // VK_USE_PLATFORM_WIN32_KHR
1449 
1450     bool manual_PreCallValidateCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
1451                                                  const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) const;
1452 
1453     bool manual_PreCallValidateCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
1454                                                     uint16_t lineStipplePattern) const;
1455 
1456     bool manual_PreCallValidateCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1457                                                   VkIndexType indexType) const;
1458     bool manual_PreCallValidateCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount,
1459                                                     const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) const;
1460 
1461     bool manual_PreCallValidateSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) const;
1462 
1463     bool manual_PreCallValidateSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) const;
1464 
1465     bool manual_PreCallValidateAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
1466                                                    VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) const;
1467 
1468     bool manual_PreCallValidateAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo,
1469                                                     uint32_t *pImageIndex) const;
1470 
1471     bool manual_PreCallValidateCmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer, uint32_t firstBinding,
1472                                                                   uint32_t bindingCount, const VkBuffer *pBuffers,
1473                                                                   const VkDeviceSize *pOffsets, const VkDeviceSize *pSizes) const;
1474 
1475     bool manual_PreCallValidateCmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer,
1476                                                             uint32_t counterBufferCount, const VkBuffer *pCounterBuffers,
1477                                                             const VkDeviceSize *pCounterBufferOffsets) const;
1478 
1479     bool manual_PreCallValidateCmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer,
1480                                                           uint32_t counterBufferCount, const VkBuffer *pCounterBuffers,
1481                                                           const VkDeviceSize *pCounterBufferOffsets) const;
1482 
1483     bool manual_PreCallValidateCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1484                                                            uint32_t firstInstance, VkBuffer counterBuffer,
1485                                                            VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1486                                                            uint32_t vertexStride) const;
1487 
1488     bool manual_PreCallValidateCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1489                                                             const VkAllocationCallbacks *pAllocator,
1490                                                             VkSamplerYcbcrConversion *pYcbcrConversion) const;
1491     bool manual_PreCallValidateCreateSamplerYcbcrConversionKHR(VkDevice device,
1492                                                                const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1493                                                                const VkAllocationCallbacks *pAllocator,
1494                                                                VkSamplerYcbcrConversion *pYcbcrConversion) const;
1495     bool manual_PreCallValidateImportSemaphoreFdKHR(VkDevice device,
1496                                                     const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo) const;
1497 
1498     bool manual_PreCallValidateCopyAccelerationStructureToMemoryKHR(VkDevice device,
1499                                                                     const VkCopyAccelerationStructureToMemoryInfoKHR *pInfo) const;
1500 
1501     bool manual_PreCallValidateCmdCopyAccelerationStructureToMemoryKHR(
1502         VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR *pInfo) const;
1503 
1504     bool manual_PreCallValidateCopyAccelerationStructureKHR(VkDevice device, const VkCopyAccelerationStructureInfoKHR *pInfo) const;
1505 
1506     bool manual_PreCallValidateCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
1507                                                                const VkCopyAccelerationStructureInfoKHR *pInfo) const;
1508     bool ValidateCopyAccelerationStructureInfoKHR(const VkCopyAccelerationStructureInfoKHR *pInfo, const char *api_name) const;
1509     bool ValidateCopyMemoryToAccelerationStructureInfoKHR(const VkCopyMemoryToAccelerationStructureInfoKHR *pInfo,
1510                                                           const char *api_name, bool is_cmd = false) const;
1511 
1512     bool manual_PreCallValidateCopyMemoryToAccelerationStructureKHR(VkDevice device,
1513                                                                     const VkCopyMemoryToAccelerationStructureInfoKHR *pInfo) const;
1514     bool manual_PreCallValidateCmdCopyMemoryToAccelerationStructureKHR(
1515         VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR *pInfo) const;
1516 
1517     bool manual_PreCallValidateCmdWriteAccelerationStructuresPropertiesKHR(
1518         VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount,
1519         const VkAccelerationStructureKHR *pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool,
1520         uint32_t firstQuery) const;
1521     bool manual_PreCallValidateWriteAccelerationStructuresPropertiesKHR(VkDevice device, uint32_t accelerationStructureCount,
1522                                                                         const VkAccelerationStructureKHR *pAccelerationStructures,
1523                                                                         VkQueryType queryType, size_t dataSize, void *pData,
1524                                                                         size_t stride) const;
1525     bool manual_PreCallValidateGetRayTracingCaptureReplayShaderGroupHandlesKHR(VkDevice device, VkPipeline pipeline,
1526                                                                                uint32_t firstGroup, uint32_t groupCount,
1527                                                                                size_t dataSize, void *pData) const;
1528 
1529     bool manual_PreCallValidateCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1530                                                const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1531                                                const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1532                                                const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1533                                                const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1534                                                uint32_t height, uint32_t depth) const;
1535 
1536     bool manual_PreCallValidateCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1537                                                        const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1538                                                        const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1539                                                        const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1540                                                        const VkStridedBufferRegionKHR *pCallableShaderBindingTable, VkBuffer buffer,
1541                                                        VkDeviceSize offset) const;
1542 
1543     bool manual_PreCallValidateCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1544                                               VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1545                                               VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1546                                               VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1547                                               VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1548                                               VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1549                                               uint32_t width, uint32_t height, uint32_t depth) const;
1550 
1551     bool manual_PreCallValidateCmdBuildAccelerationStructureIndirectKHR(VkCommandBuffer commandBuffer,
1552                                                                         const VkAccelerationStructureBuildGeometryInfoKHR *pInfo,
1553                                                                         VkBuffer indirectBuffer, VkDeviceSize indirectOffset,
1554                                                                         uint32_t indirectStride) const;
1555 
1556     bool manual_PreCallValidateGetDeviceAccelerationStructureCompatibilityKHR(
1557         VkDevice device, const VkAccelerationStructureVersionKHR *version) const;
1558 
1559     bool manual_PreCallValidateBuildAccelerationStructureKHR(
1560         VkDevice device, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
1561         const VkAccelerationStructureBuildOffsetInfoKHR *const *ppOffsetInfos) const;
1562 
1563     bool manual_PreCallValidateCmdBuildAccelerationStructureKHR(
1564         VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
1565         const VkAccelerationStructureBuildOffsetInfoKHR *const *ppOffsetInfos) const;
1566 
1567     bool manual_PreCallValidateCmdSetViewportWithCountEXT(VkCommandBuffer commandBuffer, uint32_t viewportCount,
1568                                                           const VkViewport *pViewports) const;
1569     bool manual_PreCallValidateCmdSetScissorWithCountEXT(VkCommandBuffer commandBuffer, uint32_t scissorCount,
1570                                                          const VkRect2D *pScissors) const;
1571     bool manual_PreCallValidateCmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount,
1572                                                         const VkBuffer *pBuffers, const VkDeviceSize *pOffsets,
1573                                                         const VkDeviceSize *pSizes, const VkDeviceSize *pStrides) const;
1574 
1575 #include "parameter_validation.h"
1576 };  // Class StatelessValidation
1577