• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015-2019 The Khronos Group Inc.
2  * Copyright (c) 2015-2019 Valve Corporation
3  * Copyright (c) 2015-2019 LunarG, Inc.
4  * Copyright (C) 2015-2019 Google Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Dustin Graves <dustin@lunarg.com>
19  * Author: Mark Lobodzinski <mark@lunarg.com>
20  */
21 
22 #pragma once
23 
24 #include <bitset>
25 
26 #include "parameter_name.h"
27 #include "vk_typemap_helper.h"
28 
29 // Suppress unused warning on Linux
30 #if defined(__GNUC__)
31 #define DECORATE_UNUSED __attribute__((unused))
32 #else
33 #define DECORATE_UNUSED
34 #endif
35 
36 static const char DECORATE_UNUSED *kVUID_PVError_NONE = "UNASSIGNED-GeneralParameterError-Info";
37 static const char DECORATE_UNUSED *kVUID_PVError_InvalidUsage = "UNASSIGNED-GeneralParameterError-InvalidUsage";
38 static const char DECORATE_UNUSED *kVUID_PVError_InvalidStructSType = "UNASSIGNED-GeneralParameterError-InvalidStructSType";
39 static const char DECORATE_UNUSED *kVUID_PVError_InvalidStructPNext = "UNASSIGNED-GeneralParameterError-InvalidStructPNext";
40 static const char DECORATE_UNUSED *kVUID_PVError_RequiredParameter = "UNASSIGNED-GeneralParameterError-RequiredParameter";
41 static const char DECORATE_UNUSED *kVUID_PVError_ReservedParameter = "UNASSIGNED-GeneralParameterError-ReservedParameter";
42 static const char DECORATE_UNUSED *kVUID_PVError_UnrecognizedValue = "UNASSIGNED-GeneralParameterError-UnrecognizedValue";
43 static const char DECORATE_UNUSED *kVUID_PVError_DeviceLimit = "UNASSIGNED-GeneralParameterError-DeviceLimit";
44 static const char DECORATE_UNUSED *kVUID_PVError_DeviceFeature = "UNASSIGNED-GeneralParameterError-DeviceFeature";
45 static const char DECORATE_UNUSED *kVUID_PVError_FailureCode = "UNASSIGNED-GeneralParameterError-FailureCode";
46 static const char DECORATE_UNUSED *kVUID_PVError_ExtensionNotEnabled = "UNASSIGNED-GeneralParameterError-ExtensionNotEnabled";
47 
48 #undef DECORATE_UNUSED
49 
50 extern const uint32_t GeneratedVulkanHeaderVersion;
51 
52 extern const VkQueryPipelineStatisticFlags AllVkQueryPipelineStatisticFlagBits;
53 extern const VkColorComponentFlags AllVkColorComponentFlagBits;
54 extern const VkShaderStageFlags AllVkShaderStageFlagBits;
55 extern const VkQueryControlFlags AllVkQueryControlFlagBits;
56 extern const VkImageUsageFlags AllVkImageUsageFlagBits;
57 
58 extern const std::vector<VkCompareOp> AllVkCompareOpEnums;
59 extern const std::vector<VkStencilOp> AllVkStencilOpEnums;
60 extern const std::vector<VkBlendFactor> AllVkBlendFactorEnums;
61 extern const std::vector<VkBlendOp> AllVkBlendOpEnums;
62 extern const std::vector<VkLogicOp> AllVkLogicOpEnums;
63 extern const std::vector<VkBorderColor> AllVkBorderColorEnums;
64 extern const std::vector<VkImageLayout> AllVkImageLayoutEnums;
65 
66 struct GenericHeader {
67     VkStructureType sType;
68     const void *pNext;
69 };
70 
71 // String returned by string_VkStructureType for an unrecognized type.
72 const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
73 
74 // String returned by string_VkResult for an unrecognized type.
75 const std::string UnsupportedResultString = "Unhandled VkResult";
76 
77 // The base value used when computing the offset for an enumeration token value that is added by an extension.
78 // When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
79 // See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
80 const uint32_t ExtEnumBaseValue = 1000000000;
81 
82 // The value of all VK_xxx_MAX_ENUM tokens
83 const uint32_t MaxEnumValue = 0x7FFFFFFF;
84 
85 // Misc parameters of log_msg that are likely constant per command (or low frequency change)
86 struct LogMiscParams {
87     VkDebugReportObjectTypeEXT objectType;
88     uint64_t srcObject;
89     const char *api_name;
90 };
91 
92 class StatelessValidation : public ValidationObject {
93    public:
94     VkPhysicalDeviceLimits device_limits = {};
95     VkPhysicalDeviceFeatures physical_device_features = {};
96     VkDevice device = VK_NULL_HANDLE;
97     uint32_t api_version;
98 
99     // Override chassis read/write locks for this validation object
100     // This override takes a deferred lock. i.e. it is not acquired.
write_lock()101     std::unique_lock<std::mutex> write_lock() { return std::unique_lock<std::mutex>(validation_object_mutex, std::defer_lock); }
102 
103     // Device extension properties -- storing properties gathered from VkPhysicalDeviceProperties2KHR::pNext chain
104     struct DeviceExtensionProperties {
105         VkPhysicalDeviceShadingRateImagePropertiesNV shading_rate_image_props;
106         VkPhysicalDeviceMeshShaderPropertiesNV mesh_shader_props;
107     };
108     DeviceExtensionProperties phys_dev_ext_props = {};
109 
110     struct SubpassesUsageStates {
111         std::unordered_set<uint32_t> subpasses_using_color_attachment;
112         std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
113     };
114 
115     // Though this validation object is predominantly statless, the Framebuffer checks are greatly simplified by creating and
116     // updating a map of the renderpass usage states, and these accesses need thread protection. Use a mutex separate from the
117     // parent object's to maintain that functionality.
118     std::mutex renderpass_map_mutex;
119     std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
120 
121     // Constructor for stateles validation tracking
122     // StatelessValidation() : {}
123     /**
124      * Validate a minimum value.
125      *
126      * Verify that the specified value is greater than the specified lower bound.
127      *
128      * @param api_name Name of API call being validated.
129      * @param parameter_name Name of parameter being validated.
130      * @param value Value to validate.
131      * @param lower_bound Lower bound value to use for validation.
132      * @return Boolean value indicating that the call should be skipped.
133      */
134     template <typename T>
ValidateGreaterThan(const T value,const T lower_bound,const ParameterName & parameter_name,const std::string & vuid,const LogMiscParams & misc)135     bool ValidateGreaterThan(const T value, const T lower_bound, const ParameterName &parameter_name, const std::string &vuid,
136                              const LogMiscParams &misc) {
137         bool skip_call = false;
138 
139         if (value <= lower_bound) {
140             std::ostringstream ss;
141             ss << misc.api_name << ": parameter " << parameter_name.get_name() << " (= " << value << ") is greater than "
142                << lower_bound;
143             skip_call |=
144                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, misc.objectType, misc.srcObject, vuid, "%s", ss.str().c_str());
145         }
146 
147         return skip_call;
148     }
149 
150     template <typename T>
ValidateGreaterThanZero(const T value,const ParameterName & parameter_name,const std::string & vuid,const LogMiscParams & misc)151     bool ValidateGreaterThanZero(const T value, const ParameterName &parameter_name, const std::string &vuid,
152                                  const LogMiscParams &misc) {
153         return ValidateGreaterThan(value, T{0}, parameter_name, vuid, misc);
154     }
155     /**
156      * Validate a required pointer.
157      *
158      * Verify that a required pointer is not NULL.
159      *
160      * @param apiName Name of API call being validated.
161      * @param parameterName Name of parameter being validated.
162      * @param value Pointer to validate.
163      * @return Boolean value indicating that the call should be skipped.
164      */
validate_required_pointer(const char * apiName,const ParameterName & parameterName,const void * value,const std::string & vuid)165     bool validate_required_pointer(const char *apiName, const ParameterName &parameterName, const void *value,
166                                    const std::string &vuid) {
167         bool skip_call = false;
168 
169         if (value == NULL) {
170             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
171                                  "%s: required parameter %s specified as NULL.", apiName, parameterName.get_name().c_str());
172         }
173 
174         return skip_call;
175     }
176 
177     /**
178      * Validate array count and pointer to array.
179      *
180      * Verify that required count and array parameters are not 0 or NULL.  If the
181      * count parameter is not optional, verify that it is not 0.  If the array
182      * parameter is NULL, and it is not optional, verify that count is 0.
183      *
184      * @param apiName Name of API call being validated.
185      * @param countName Name of count parameter.
186      * @param arrayName Name of array parameter.
187      * @param count Number of elements in the array.
188      * @param array Array to validate.
189      * @param countRequired The 'count' parameter may not be 0 when true.
190      * @param arrayRequired The 'array' parameter may not be NULL when true.
191      * @return Boolean value indicating that the call should be skipped.
192      */
193     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)194     bool validate_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName, T1 count,
195                         const T2 *array, bool countRequired, bool arrayRequired, const char *count_required_vuid,
196                         const char *array_required_vuid) {
197         bool skip_call = false;
198 
199         // Count parameters not tagged as optional cannot be 0
200         if (countRequired && (count == 0)) {
201             skip_call |=
202                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, count_required_vuid,
203                         "%s: parameter %s must be greater than 0.", apiName, countName.get_name().c_str());
204         }
205 
206         // Array parameters not tagged as optional cannot be NULL, unless the count is 0
207         if (arrayRequired && (count != 0) && (*array == NULL)) {
208             skip_call |=
209                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, array_required_vuid,
210                         "%s: required parameter %s specified as NULL.", apiName, arrayName.get_name().c_str());
211         }
212 
213         return skip_call;
214     }
215 
216     /**
217      * Validate pointer to array count and pointer to array.
218      *
219      * Verify that required count and array parameters are not NULL.  If count
220      * is not NULL and its value is not optional, verify that it is not 0.  If the
221      * array parameter is NULL, and it is not optional, verify that count is 0.
222      * The array parameter will typically be optional for this case (where count is
223      * a pointer), allowing the caller to retrieve the available count.
224      *
225      * @param apiName Name of API call being validated.
226      * @param countName Name of count parameter.
227      * @param arrayName Name of array parameter.
228      * @param count Pointer to the number of elements in the array.
229      * @param array Array to validate.
230      * @param countPtrRequired The 'count' parameter may not be NULL when true.
231      * @param countValueRequired The '*count' value may not be 0 when true.
232      * @param arrayRequired The 'array' parameter may not be NULL when true.
233      * @return Boolean value indicating that the call should be skipped.
234      */
235     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)236     bool validate_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName, const T1 *count,
237                         const T2 *array, bool countPtrRequired, bool countValueRequired, bool arrayRequired,
238                         const char *count_required_vuid, const char *array_required_vuid) {
239         bool skip_call = false;
240 
241         if (count == NULL) {
242             if (countPtrRequired) {
243                 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
244                                      kVUID_PVError_RequiredParameter, "%s: required parameter %s specified as NULL", apiName,
245                                      countName.get_name().c_str());
246             }
247         } else {
248             skip_call |= validate_array(apiName, countName, arrayName, *array ? (*count) : 0, &array, countValueRequired,
249                                         arrayRequired, count_required_vuid, array_required_vuid);
250         }
251 
252         return skip_call;
253     }
254 
255     /**
256      * Validate a pointer to a Vulkan structure.
257      *
258      * Verify that a required pointer to a structure is not NULL.  If the pointer is
259      * not NULL, verify that each structure's sType field is set to the correct
260      * VkStructureType value.
261      *
262      * @param apiName Name of API call being validated.
263      * @param parameterName Name of struct parameter being validated.
264      * @param sTypeName Name of expected VkStructureType value.
265      * @param value Pointer to the struct to validate.
266      * @param sType VkStructureType for structure validation.
267      * @param required The parameter may not be NULL when true.
268      * @return Boolean value indicating that the call should be skipped.
269      */
270     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)271     bool validate_struct_type(const char *apiName, const ParameterName &parameterName, const char *sTypeName, const T *value,
272                               VkStructureType sType, bool required, const char *struct_vuid, const char *stype_vuid) {
273         bool skip_call = false;
274 
275         if (value == NULL) {
276             if (required) {
277                 skip_call |=
278                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, struct_vuid,
279                             "%s: required parameter %s specified as NULL", apiName, parameterName.get_name().c_str());
280             }
281         } else if (value->sType != sType) {
282             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, stype_vuid,
283                                  "%s: parameter %s->sType must be %s.", apiName, parameterName.get_name().c_str(), sTypeName);
284         }
285 
286         return skip_call;
287     }
288 
289     /**
290      * Validate an array of Vulkan structures
291      *
292      * Verify that required count and array parameters are not 0 or NULL.  If
293      * the array contains 1 or more structures, verify that each structure's
294      * sType field is set to the correct VkStructureType value.
295      *
296      * @param apiName Name of API call being validated.
297      * @param countName Name of count parameter.
298      * @param arrayName Name of array parameter.
299      * @param sTypeName Name of expected VkStructureType value.
300      * @param count Number of elements in the array.
301      * @param array Array to validate.
302      * @param sType VkStructureType for structure validation.
303      * @param countRequired The 'count' parameter may not be 0 when true.
304      * @param arrayRequired The 'array' parameter may not be NULL when true.
305      * @return Boolean value indicating that the call should be skipped.
306      */
307     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)308     bool validate_struct_type_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName,
309                                     const char *sTypeName, uint32_t count, const T *array, VkStructureType sType,
310                                     bool countRequired, bool arrayRequired, const char *stype_vuid, const char *param_vuid,
311                                     const char *count_required_vuid) {
312         bool skip_call = false;
313 
314         if ((count == 0) || (array == NULL)) {
315             skip_call |= validate_array(apiName, countName, arrayName, count, &array, countRequired, arrayRequired,
316                                         count_required_vuid, param_vuid);
317         } else {
318             // Verify that all structs in the array have the correct type
319             for (uint32_t i = 0; i < count; ++i) {
320                 if (array[i].sType != sType) {
321                     skip_call |=
322                         log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, stype_vuid,
323                                 "%s: parameter %s[%d].sType must be %s", apiName, arrayName.get_name().c_str(), i, sTypeName);
324                 }
325             }
326         }
327 
328         return skip_call;
329     }
330 
331     /**
332      * Validate an array of Vulkan structures.
333      *
334      * Verify that required count and array parameters are not NULL.  If count
335      * is not NULL and its value is not optional, verify that it is not 0.
336      * If the array contains 1 or more structures, verify that each structure's
337      * sType field is set to the correct VkStructureType value.
338      *
339      * @param apiName Name of API call being validated.
340      * @param countName Name of count parameter.
341      * @param arrayName Name of array parameter.
342      * @param sTypeName Name of expected VkStructureType value.
343      * @param count Pointer to the number of elements in the array.
344      * @param array Array to validate.
345      * @param sType VkStructureType for structure validation.
346      * @param countPtrRequired The 'count' parameter may not be NULL when true.
347      * @param countValueRequired The '*count' value may not be 0 when true.
348      * @param arrayRequired The 'array' parameter may not be NULL when true.
349      * @return Boolean value indicating that the call should be skipped.
350      */
351     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)352     bool validate_struct_type_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName,
353                                     const char *sTypeName, uint32_t *count, const T *array, VkStructureType sType,
354                                     bool countPtrRequired, bool countValueRequired, bool arrayRequired, const char *stype_vuid,
355                                     const char *param_vuid, const char *count_required_vuid) {
356         bool skip_call = false;
357 
358         if (count == NULL) {
359             if (countPtrRequired) {
360                 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
361                                      kVUID_PVError_RequiredParameter, "%s: required parameter %s specified as NULL", apiName,
362                                      countName.get_name().c_str());
363             }
364         } else {
365             skip_call |= validate_struct_type_array(apiName, countName, arrayName, sTypeName, (*count), array, sType,
366                                                     countValueRequired, arrayRequired, stype_vuid, param_vuid, count_required_vuid);
367         }
368 
369         return skip_call;
370     }
371 
372     /**
373      * Validate a Vulkan handle.
374      *
375      * Verify that the specified handle is not VK_NULL_HANDLE.
376      *
377      * @param api_name Name of API call being validated.
378      * @param parameter_name Name of struct parameter being validated.
379      * @param value Handle to validate.
380      * @return Boolean value indicating that the call should be skipped.
381      */
382     template <typename T>
validate_required_handle(const char * api_name,const ParameterName & parameter_name,T value)383     bool validate_required_handle(const char *api_name, const ParameterName &parameter_name, T value) {
384         bool skip_call = false;
385 
386         if (value == VK_NULL_HANDLE) {
387             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
388                                  kVUID_PVError_RequiredParameter, "%s: required parameter %s specified as VK_NULL_HANDLE", api_name,
389                                  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) {
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 |=
429                         log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
430                                 kVUID_PVError_RequiredParameter, "%s: required parameter %s[%d] specified as VK_NULL_HANDLE",
431                                 api_name, array_name.get_name().c_str(), i);
432                 }
433             }
434         }
435 
436         return skip_call;
437     }
438 
439     /**
440      * Validate string array count and content.
441      *
442      * Verify that required count and array parameters are not 0 or NULL.  If the
443      * count parameter is not optional, verify that it is not 0.  If the array
444      * parameter is NULL, and it is not optional, verify that count is 0.  If the
445      * array parameter is not NULL, verify that none of the strings are NULL.
446      *
447      * @param apiName Name of API call being validated.
448      * @param countName Name of count parameter.
449      * @param arrayName Name of array parameter.
450      * @param count Number of strings in the array.
451      * @param array Array of strings to validate.
452      * @param countRequired The 'count' parameter may not be 0 when true.
453      * @param arrayRequired The 'array' parameter may not be NULL when true.
454      * @return Boolean value indicating that the call should be skipped.
455      */
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)456     bool validate_string_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName, uint32_t count,
457                                const char *const *array, bool countRequired, bool arrayRequired, const char *count_required_vuid,
458                                const char *array_required_vuid) {
459         bool skip_call = false;
460 
461         if ((count == 0) || (array == NULL)) {
462             skip_call |= validate_array(apiName, countName, arrayName, count, &array, countRequired, arrayRequired,
463                                         count_required_vuid, array_required_vuid);
464         } else {
465             // Verify that strings in the array are not NULL
466             for (uint32_t i = 0; i < count; ++i) {
467                 if (array[i] == NULL) {
468                     skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
469                                          kVUID_PVError_RequiredParameter, "%s: required parameter %s[%d] specified as NULL",
470                                          apiName, arrayName.get_name().c_str(), i);
471                 }
472             }
473         }
474 
475         return skip_call;
476     }
477 
478     // Forward declaration for pNext validation
479     bool ValidatePnextStructContents(const char *api_name, const ParameterName &parameter_name, const GenericHeader *header);
480 
481     /**
482      * Validate a structure's pNext member.
483      *
484      * Verify that the specified pNext value points to the head of a list of
485      * allowed extension structures.  If no extension structures are allowed,
486      * verify that pNext is null.
487      *
488      * @param api_name Name of API call being validated.
489      * @param parameter_name Name of parameter being validated.
490      * @param allowed_struct_names Names of allowed structs.
491      * @param next Pointer to validate.
492      * @param allowed_type_count Total number of allowed structure types.
493      * @param allowed_types Array of structure types allowed for pNext.
494      * @param header_version Version of header defining the pNext validation rules.
495      * @return Boolean value indicating that the call should be skipped.
496      */
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 * vuid)497     bool validate_struct_pnext(const char *api_name, const ParameterName &parameter_name, const char *allowed_struct_names,
498                                const void *next, size_t allowed_type_count, const VkStructureType *allowed_types,
499                                uint32_t header_version, const char *vuid) {
500         bool skip_call = false;
501 
502         // TODO: The valid pNext structure types are not recursive. Each structure has its own list of valid sTypes for pNext.
503         // Codegen a map of vectors containing the allowable pNext types for each struct and use that here -- also simplifies parms.
504         if (next != NULL) {
505             std::unordered_set<const void *> cycle_check;
506             std::unordered_set<VkStructureType, std::hash<int>> unique_stype_check;
507 
508             const char *disclaimer =
509                 "This warning is based on the Valid Usage documentation for version %d of the Vulkan header.  It is possible that "
510                 "you "
511                 "are "
512                 "using a struct from a private extension or an extension that was added to a later version of the Vulkan header, "
513                 "in "
514                 "which "
515                 "case your use of %s is perfectly valid but is not guaranteed to work correctly with validation enabled";
516 
517             if (allowed_type_count == 0) {
518                 std::string message = "%s: value of %s must be NULL. ";
519                 message += disclaimer;
520                 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
521                                      message.c_str(), api_name, parameter_name.get_name().c_str(), header_version,
522                                      parameter_name.get_name().c_str());
523             } else {
524                 const VkStructureType *start = allowed_types;
525                 const VkStructureType *end = allowed_types + allowed_type_count;
526                 const GenericHeader *current = reinterpret_cast<const GenericHeader *>(next);
527 
528                 cycle_check.insert(next);
529 
530                 while (current != NULL) {
531                     if (((strncmp(api_name, "vkCreateInstance", strlen(api_name)) != 0) ||
532                          (current->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)) &&
533                         ((strncmp(api_name, "vkCreateDevice", strlen(api_name)) != 0) ||
534                          (current->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO))) {
535                         if (cycle_check.find(current->pNext) != cycle_check.end()) {
536                             std::string message = "%s: %s chain contains a cycle -- pNext pointer " PRIx64 " is repeated.";
537                             skip_call |=
538                                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
539                                         kVUID_PVError_InvalidStructPNext, message.c_str(), api_name,
540                                         parameter_name.get_name().c_str(), reinterpret_cast<uint64_t>(next));
541                             break;
542                         } else {
543                             cycle_check.insert(current->pNext);
544                         }
545 
546                         std::string type_name = string_VkStructureType(current->sType);
547                         if (unique_stype_check.find(current->sType) != unique_stype_check.end()) {
548                             std::string message = "%s: %s chain contains duplicate structure types: %s appears multiple times.";
549                             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
550                                                  VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, kVUID_PVError_InvalidStructPNext,
551                                                  message.c_str(), api_name, parameter_name.get_name().c_str(), type_name.c_str());
552                         } else {
553                             unique_stype_check.insert(current->sType);
554                         }
555 
556                         if (std::find(start, end, current->sType) == end) {
557                             if (type_name == UnsupportedStructureTypeString) {
558                                 std::string message =
559                                     "%s: %s chain includes a structure with unknown VkStructureType (%d); Allowed structures are "
560                                     "[%s]. ";
561                                 message += disclaimer;
562                                 skip_call |=
563                                     log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
564                                             0, vuid, message.c_str(), api_name, parameter_name.get_name().c_str(), current->sType,
565                                             allowed_struct_names, header_version, parameter_name.get_name().c_str());
566                             } else {
567                                 std::string message =
568                                     "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures are "
569                                     "[%s]. ";
570                                 message += disclaimer;
571                                 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
572                                                      VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid, message.c_str(), api_name,
573                                                      parameter_name.get_name().c_str(), type_name.c_str(), allowed_struct_names,
574                                                      header_version, parameter_name.get_name().c_str());
575                             }
576                         }
577                         skip_call |= ValidatePnextStructContents(api_name, parameter_name, current);
578                     }
579                     current = reinterpret_cast<const GenericHeader *>(current->pNext);
580                 }
581             }
582         }
583 
584         return skip_call;
585     }
586 
587     /**
588      * Validate a VkBool32 value.
589      *
590      * Generate a warning if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
591      *
592      * @param apiName Name of API call being validated.
593      * @param parameterName Name of parameter being validated.
594      * @param value Boolean value to validate.
595      * @return Boolean value indicating that the call should be skipped.
596      */
validate_bool32(const char * apiName,const ParameterName & parameterName,VkBool32 value)597     bool validate_bool32(const char *apiName, const ParameterName &parameterName, VkBool32 value) {
598         bool skip_call = false;
599 
600         if ((value != VK_TRUE) && (value != VK_FALSE)) {
601             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
602                                  kVUID_PVError_UnrecognizedValue, "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE", apiName,
603                                  parameterName.get_name().c_str(), value);
604         }
605 
606         return skip_call;
607     }
608 
609     /**
610      * Validate a Vulkan enumeration value.
611      *
612      * Generate a warning if an enumeration token value does not fall within the core enumeration
613      * begin and end token values, and was not added to the enumeration by an extension.  Extension
614      * provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
615      * with 1,000,000,000 as the base token value.
616      *
617      * @note This function does not expect to process enumerations defining bitmask flag bits.
618      *
619      * @param apiName Name of API call being validated.
620      * @param parameterName Name of parameter being validated.
621      * @param enumName Name of the enumeration being validated.
622      * @param valid_values The list of valid values for the enumeration.
623      * @param value Enumeration value to validate.
624      * @return Boolean value indicating that the call should be skipped.
625      */
626     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)627     bool validate_ranged_enum(const char *apiName, const ParameterName &parameterName, const char *enumName,
628                               const std::vector<T> &valid_values, T value, const char *vuid) {
629         bool skip = false;
630 
631         if (std::find(valid_values.begin(), valid_values.end(), value) == valid_values.end()) {
632             skip |=
633                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
634                         "%s: value of %s (%d) does not fall within the begin..end range of the core %s enumeration tokens and is "
635                         "not an extension added token.",
636                         apiName, parameterName.get_name().c_str(), value, enumName);
637         }
638 
639         return skip;
640     }
641 
642     /**
643      * Validate an array of Vulkan enumeration value.
644      *
645      * Process all enumeration token values in the specified array and generate a warning if a value
646      * does not fall within the core enumeration begin and end token values, and was not added to
647      * the enumeration by an extension.  Extension provided enumerations use the equation specified
648      * in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
649      *
650      * @note This function does not expect to process enumerations defining bitmask flag bits.
651      *
652      * @param apiName Name of API call being validated.
653      * @param countName Name of count parameter.
654      * @param arrayName Name of array parameter.
655      * @param enumName Name of the enumeration being validated.
656      * @param valid_values The list of valid values for the enumeration.
657      * @param count Number of enumeration values in the array.
658      * @param array Array of enumeration values to validate.
659      * @param countRequired The 'count' parameter may not be 0 when true.
660      * @param arrayRequired The 'array' parameter may not be NULL when true.
661      * @return Boolean value indicating that the call should be skipped.
662      */
663     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)664     bool validate_ranged_enum_array(const char *apiName, const ParameterName &countName, const ParameterName &arrayName,
665                                     const char *enumName, const std::vector<T> &valid_values, uint32_t count, const T *array,
666                                     bool countRequired, bool arrayRequired) {
667         bool skip_call = false;
668 
669         if ((count == 0) || (array == NULL)) {
670             skip_call |= validate_array(apiName, countName, arrayName, count, &array, countRequired, arrayRequired, kVUIDUndefined,
671                                         kVUIDUndefined);
672         } else {
673             for (uint32_t i = 0; i < count; ++i) {
674                 if (std::find(valid_values.begin(), valid_values.end(), array[i]) == valid_values.end()) {
675                     skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
676                                          kVUID_PVError_UnrecognizedValue,
677                                          "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
678                                          "enumeration tokens and is not an extension added token",
679                                          apiName, arrayName.get_name().c_str(), i, array[i], enumName);
680                 }
681             }
682         }
683 
684         return skip_call;
685     }
686 
687     /**
688      * Verify that a reserved VkFlags value is zero.
689      *
690      * Verify that the specified value is zero, to check VkFlags values that are reserved for
691      * future use.
692      *
693      * @param api_name Name of API call being validated.
694      * @param parameter_name Name of parameter being validated.
695      * @param value Value to validate.
696      * @return Boolean value indicating that the call should be skipped.
697      */
validate_reserved_flags(const char * api_name,const ParameterName & parameter_name,VkFlags value,const char * vuid)698     bool validate_reserved_flags(const char *api_name, const ParameterName &parameter_name, VkFlags value, const char *vuid) {
699         bool skip_call = false;
700 
701         if (value != 0) {
702             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
703                                  "%s: parameter %s must be 0.", api_name, parameter_name.get_name().c_str());
704         }
705 
706         return skip_call;
707     }
708 
709     /**
710      * Validate a Vulkan bitmask value.
711      *
712      * Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
713      * for that type.
714      *
715      * @param api_name Name of API call being validated.
716      * @param parameter_name Name of parameter being validated.
717      * @param flag_bits_name Name of the VkFlags type being validated.
718      * @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated.
719      * @param value VkFlags value to validate.
720      * @param flags_required The 'value' parameter may not be 0 when true.
721      * @param singleFlag The 'value' parameter may not contain more than one bit from all_flags.
722      * @return Boolean value indicating that the call should be skipped.
723      */
validate_flags(const char * api_name,const ParameterName & parameter_name,const char * flag_bits_name,VkFlags all_flags,VkFlags value,bool flags_required,bool singleFlag,const char * vuid)724     bool validate_flags(const char *api_name, const ParameterName &parameter_name, const char *flag_bits_name, VkFlags all_flags,
725                         VkFlags value, bool flags_required, bool singleFlag, const char *vuid) {
726         bool skip_call = false;
727 
728         if (value == 0) {
729             if (flags_required) {
730                 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
731                                      "%s: value of %s must not be 0.", api_name, parameter_name.get_name().c_str());
732             }
733         } else if ((value & (~all_flags)) != 0) {
734             skip_call |=
735                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
736                         kVUID_PVError_UnrecognizedValue, "%s: value of %s contains flag bits that are not recognized members of %s",
737                         api_name, parameter_name.get_name().c_str(), flag_bits_name);
738         } else if (singleFlag && (std::bitset<sizeof(VkFlags) * 8>(value).count() > 1)) {
739             skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
740                                  kVUID_PVError_UnrecognizedValue,
741                                  "%s: value of %s contains multiple members of %s when only a single value is allowed", api_name,
742                                  parameter_name.get_name().c_str(), flag_bits_name);
743         }
744 
745         return skip_call;
746     }
747 
748     /**
749      * Validate an array of Vulkan bitmask values.
750      *
751      * Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
752      * for that type.
753      *
754      * @param api_name Name of API call being validated.
755      * @param count_name Name of parameter being validated.
756      * @param array_name Name of parameter being validated.
757      * @param flag_bits_name Name of the VkFlags type being validated.
758      * @param all_flags A bitmask combining all valid flag bits for the VkFlags type being validated.
759      * @param count Number of VkFlags values in the array.
760      * @param array Array of VkFlags value to validate.
761      * @param count_required The 'count' parameter may not be 0 when true.
762      * @param array_required The 'array' parameter may not be NULL when true.
763      * @return Boolean value indicating that the call should be skipped.
764      */
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)765     bool validate_flags_array(const char *api_name, const ParameterName &count_name, const ParameterName &array_name,
766                               const char *flag_bits_name, VkFlags all_flags, uint32_t count, const VkFlags *array,
767                               bool count_required, bool array_required) {
768         bool skip_call = false;
769 
770         if ((count == 0) || (array == NULL)) {
771             skip_call |= validate_array(api_name, count_name, array_name, count, &array, count_required, array_required,
772                                         kVUIDUndefined, kVUIDUndefined);
773         } else {
774             // Verify that all VkFlags values in the array
775             for (uint32_t i = 0; i < count; ++i) {
776                 if (array[i] == 0) {
777                     // Current XML registry logic for validity generation uses the array parameter's optional tag to determine if
778                     // elements in the array are allowed be 0
779                     if (array_required) {
780                         skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
781                                              kVUID_PVError_RequiredParameter, "%s: value of %s[%d] must not be 0", api_name,
782                                              array_name.get_name().c_str(), i);
783                     }
784                 } else if ((array[i] & (~all_flags)) != 0) {
785                     skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
786                                          kVUID_PVError_UnrecognizedValue,
787                                          "%s: value of %s[%d] contains flag bits that are not recognized members of %s", api_name,
788                                          array_name.get_name().c_str(), i, flag_bits_name);
789                 }
790             }
791         }
792 
793         return skip_call;
794     }
795 
796     template <typename ExtensionState>
validate_extension_reqs(const ExtensionState & extensions,const char * vuid,const char * extension_type,const char * extension_name)797     bool validate_extension_reqs(const ExtensionState &extensions, const char *vuid, const char *extension_type,
798                                  const char *extension_name) {
799         bool skip = false;
800         if (!extension_name) {
801             return skip;  // Robust to invalid char *
802         }
803         auto info = ExtensionState::get_info(extension_name);
804 
805         if (!info.state) {
806             return skip;  // Unknown extensions cannot be checked so report OK
807         }
808 
809         // Check against the required list in the info
810         std::vector<const char *> missing;
811         for (const auto &req : info.requires) {
812             if (!(extensions.*(req.enabled))) {
813                 missing.push_back(req.name);
814             }
815         }
816 
817         // Report any missing requirements
818         if (missing.size()) {
819             std::string missing_joined_list = string_join(", ", missing);
820             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
821                             HandleToUint64(instance), vuid, "Missing extension%s required by the %s extension %s: %s.",
822                             ((missing.size() > 1) ? "s" : ""), extension_type, extension_name, missing_joined_list.c_str());
823         }
824         return skip;
825     }
826 
827     enum RenderPassCreateVersion { RENDER_PASS_VERSION_1 = 0, RENDER_PASS_VERSION_2 = 1 };
828 
829     template <typename RenderPassCreateInfoGeneric>
CreateRenderPassGeneric(VkDevice device,const RenderPassCreateInfoGeneric * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass,RenderPassCreateVersion rp_version)830     bool CreateRenderPassGeneric(VkDevice device, const RenderPassCreateInfoGeneric *pCreateInfo,
831                                  const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass,
832                                  RenderPassCreateVersion rp_version) {
833         bool skip = false;
834         uint32_t max_color_attachments = device_limits.maxColorAttachments;
835         bool use_rp2 = (rp_version == RENDER_PASS_VERSION_2);
836         const char *vuid;
837 
838         for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
839             if (pCreateInfo->pAttachments[i].format == VK_FORMAT_UNDEFINED) {
840                 std::stringstream ss;
841                 ss << (use_rp2 ? "vkCreateRenderPass2KHR" : "vkCreateRenderPass") << ": pCreateInfo->pAttachments[" << i
842                    << "].format is VK_FORMAT_UNDEFINED. ";
843                 vuid =
844                     use_rp2 ? "VUID-VkAttachmentDescription2KHR-format-parameter" : "VUID-VkAttachmentDescription-format-parameter";
845                 skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
846                                 "%s", ss.str().c_str());
847             }
848             if (pCreateInfo->pAttachments[i].finalLayout == VK_IMAGE_LAYOUT_UNDEFINED ||
849                 pCreateInfo->pAttachments[i].finalLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
850                 vuid = use_rp2 ? "VUID-VkAttachmentDescription2KHR-finalLayout-03061"
851                                : "VUID-VkAttachmentDescription-finalLayout-00843";
852                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
853                                 "pCreateInfo->pAttachments[%d].finalLayout must not be VK_IMAGE_LAYOUT_UNDEFINED or "
854                                 "VK_IMAGE_LAYOUT_PREINITIALIZED.",
855                                 i);
856             }
857         }
858 
859         for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
860             if (pCreateInfo->pSubpasses[i].colorAttachmentCount > max_color_attachments) {
861                 vuid = use_rp2 ? "VUID-VkSubpassDescription2KHR-colorAttachmentCount-03063"
862                                : "VUID-VkSubpassDescription-colorAttachmentCount-00845";
863                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
864                                 "Cannot create a render pass with %d color attachments. Max is %d.",
865                                 pCreateInfo->pSubpasses[i].colorAttachmentCount, max_color_attachments);
866             }
867         }
868         return skip;
869     }
870 
871     template <typename T>
RecordRenderPass(VkRenderPass renderPass,const T * pCreateInfo)872     void RecordRenderPass(VkRenderPass renderPass, const T *pCreateInfo) {
873         std::unique_lock<std::mutex> lock(renderpass_map_mutex);
874         auto &renderpass_state = renderpasses_states[renderPass];
875         lock.unlock();
876 
877         for (uint32_t subpass = 0; subpass < pCreateInfo->subpassCount; ++subpass) {
878             bool uses_color = false;
879             for (uint32_t i = 0; i < pCreateInfo->pSubpasses[subpass].colorAttachmentCount && !uses_color; ++i)
880                 if (pCreateInfo->pSubpasses[subpass].pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) uses_color = true;
881 
882             bool uses_depthstencil = false;
883             if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment)
884                 if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
885                     uses_depthstencil = true;
886 
887             if (uses_color) renderpass_state.subpasses_using_color_attachment.insert(subpass);
888             if (uses_depthstencil) renderpass_state.subpasses_using_depthstencil_attachment.insert(subpass);
889         }
890     }
891 
892     bool require_device_extension(bool flag, char const *function_name, char const *extension_name);
893 
894     bool validate_instance_extensions(const VkInstanceCreateInfo *pCreateInfo);
895 
896     bool validate_api_version(uint32_t api_version, uint32_t effective_api_version);
897 
898     bool validate_string(const char *apiName, const ParameterName &stringName, const std::string &vuid, const char *validateString);
899 
900     bool ValidateCoarseSampleOrderCustomNV(const VkCoarseSampleOrderCustomNV *order);
901 
902     bool ValidateQueueFamilies(uint32_t queue_family_count, const uint32_t *queue_families, const char *cmd_name,
903                                const char *array_parameter_name, const std::string &unique_error_code,
904                                const std::string &valid_error_code, bool optional);
905 
906     bool ValidateDeviceQueueFamily(uint32_t queue_family, const char *cmd_name, const char *parameter_name,
907                                    const std::string &error_code, bool optional);
908 
909     bool OutputExtensionError(const std::string &api_name, const std::string &extension_name);
910 
911     void PostCallRecordCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
912                                         const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass, VkResult result);
913     void PostCallRecordCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo,
914                                             const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass, VkResult result);
915     void PostCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator);
916     void PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
917                                     const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result);
918 
919     void PostCallRecordCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
920                                       VkInstance *pInstance, VkResult result);
921 
922     bool manual_PreCallValidateCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
923                                                const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool);
924 
925     bool manual_PreCallValidateCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
926                                               VkInstance *pInstance);
927 
928     bool manual_PreCallValidateCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
929                                             const VkAllocationCallbacks *pAllocator, VkDevice *pDevice);
930 
931     bool manual_PreCallValidateCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
932                                             const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer);
933 
934     bool manual_PreCallValidateCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
935                                            const VkAllocationCallbacks *pAllocator, VkImage *pImage);
936 
937     bool manual_PreCallValidateCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
938                                                const VkAllocationCallbacks *pAllocator, VkImageView *pView);
939 
940     bool manual_PreCallValidateViewport(const VkViewport &viewport, const char *fn_name, const ParameterName &parameter_name,
941                                         VkDebugReportObjectTypeEXT object_type, uint64_t object);
942 
943     bool manual_PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
944                                                        const VkGraphicsPipelineCreateInfo *pCreateInfos,
945                                                        const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines);
946     bool manual_PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
947                                                       const VkComputePipelineCreateInfo *pCreateInfos,
948                                                       const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines);
949 
950     bool manual_PreCallValidateCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
951                                              const VkAllocationCallbacks *pAllocator, VkSampler *pSampler);
952     bool manual_PreCallValidateCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
953                                                          const VkAllocationCallbacks *pAllocator,
954                                                          VkDescriptorSetLayout *pSetLayout);
955 
956     bool manual_PreCallValidateUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
957                                                     const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
958                                                     const VkCopyDescriptorSet *pDescriptorCopies);
959     ;
960     bool manual_PreCallValidateFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount,
961                                                   const VkDescriptorSet *pDescriptorSets);
962 
963     bool manual_PreCallValidateCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
964                                                 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
965 
966     bool manual_PreCallValidateCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo,
967                                                     const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
968 
969     bool manual_PreCallValidateFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
970                                                   const VkCommandBuffer *pCommandBuffers);
971 
972     bool manual_PreCallValidateBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo);
973 
974     bool manual_PreCallValidateCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount,
975                                               const VkViewport *pViewports);
976 
977     bool manual_PreCallValidateCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount,
978                                              const VkRect2D *pScissors);
979     bool manual_PreCallValidateCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth);
980 
981     bool manual_PreCallValidateCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
982                                        uint32_t firstVertex, uint32_t firstInstance);
983 
984     bool manual_PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
985                                                uint32_t stride);
986 
987     bool manual_PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
988                                                       uint32_t count, uint32_t stride);
989 
990     bool manual_PreCallValidateCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
991                                             VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
992                                             const VkImageCopy *pRegions);
993 
994     bool manual_PreCallValidateCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
995                                             VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
996                                             const VkImageBlit *pRegions, VkFilter filter);
997 
998     bool manual_PreCallValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
999                                                     VkImageLayout dstImageLayout, uint32_t regionCount,
1000                                                     const VkBufferImageCopy *pRegions);
1001 
1002     bool manual_PreCallValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
1003                                                     VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions);
1004 
1005     bool manual_PreCallValidateCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
1006                                                VkDeviceSize dataSize, const void *pData);
1007 
1008     bool manual_PreCallValidateCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
1009                                              VkDeviceSize size, uint32_t data);
1010 
1011     bool manual_PreCallValidateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1012                                                   const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain);
1013     bool manual_PreCallValidateQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo);
1014 
1015 #ifdef VK_USE_PLATFORM_WIN32_KHR
1016     bool manual_PreCallValidateCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
1017                                                      const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
1018 #endif  // VK_USE_PLATFORM_WIN32_KHR
1019 
1020     bool manual_PreCallValidateCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
1021                                                     const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool);
1022     bool manual_PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY,
1023                                            uint32_t groupCountZ);
1024 
1025     bool manual_PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
1026 
1027     bool manual_PreCallValidateCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1028                                                   uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1029                                                   uint32_t groupCountZ);
1030     bool manual_PreCallValidateCmdSetExclusiveScissorNV(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor,
1031                                                         uint32_t exclusiveScissorCount, const VkRect2D *pExclusiveScissors);
1032     bool manual_PreCallValidateCmdSetViewportShadingRatePaletteNV(VkCommandBuffer commandBuffer, uint32_t firstViewport,
1033                                                                   uint32_t viewportCount,
1034                                                                   const VkShadingRatePaletteNV *pShadingRatePalettes);
1035 
1036     bool manual_PreCallValidateCmdSetCoarseSampleOrderNV(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType,
1037                                                          uint32_t customSampleOrderCount,
1038                                                          const VkCoarseSampleOrderCustomNV *pCustomSampleOrders);
1039 
1040     bool manual_PreCallValidateCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask);
1041     bool manual_PreCallValidateCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1042                                                           uint32_t drawCount, uint32_t stride);
1043 
1044     bool manual_PreCallValidateCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1045                                                                VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1046                                                                uint32_t maxDrawCount, uint32_t stride);
1047 
1048     bool manual_PreCallValidateEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
1049                                                                   uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
1050     bool manual_PreCallValidateAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
1051                                               const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory);
1052 #include "parameter_validation.h"
1053 };  // Class StatelessValidation
1054