Home | History | Annotate | Download | only in layers
      1 /* Copyright (c) 2015-2019 The Khronos Group Inc.
      2  * Copyright (c) 2015-2019 Valve Corporation
      3  * Copyright (c) 2015-2019 LunarG, Inc.
      4  * Copyright (C) 2015-2019 Google Inc.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Dustin Graves <dustin (at) lunarg.com>
     19  * Author: Mark Lobodzinski <mark (at) 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.
    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>
    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>
    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      */
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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      */
    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      */
    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      */
    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>
    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>
    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      */
    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      */
    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      */
    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>
    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>
    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>
    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