xref: /aosp_15_r20/external/vulkan-validation-layers/layers/stateless_validation.h (revision b7893ccf7851cd6a48cc5a1e965257d8a5cdcc70)
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 &parameter_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 &parameter_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 &parameterName, 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 &parameterName, 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 &parameter_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 &parameter_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 &parameter_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 &parameterName, 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 &parameterName, 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 &parameter_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 &parameter_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 &parameter_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