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