• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015-2019 The Khronos Group Inc.
2  * Copyright (c) 2015-2019 Valve Corporation
3  * Copyright (c) 2015-2019 LunarG, Inc.
4  * Copyright (C) 2015-2019 Google Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Mark Lobodzinski <mark@LunarG.com>
19  * Author: John Zulauf <jzulauf@lunarg.com>
20  */
21 
22 #define NOMINMAX
23 
24 #include <math.h>
25 
26 #include "chassis.h"
27 #include "stateless_validation.h"
28 #include "layer_chassis_dispatch.h"
29 
30 static const int MaxParamCheckerStringLength = 256;
31 
32 template <typename T>
in_inclusive_range(const T & value,const T & min,const T & max)33 inline bool in_inclusive_range(const T &value, const T &min, const T &max) {
34     // Using only < for generality and || for early abort
35     return !((value < min) || (max < value));
36 }
37 
validate_string(const char * apiName,const ParameterName & stringName,const std::string & vuid,const char * validateString)38 bool StatelessValidation::validate_string(const char *apiName, const ParameterName &stringName, const std::string &vuid,
39                                           const char *validateString) {
40     bool skip = false;
41 
42     VkStringErrorFlags result = vk_string_validate(MaxParamCheckerStringLength, validateString);
43 
44     if (result == VK_STRING_ERROR_NONE) {
45         return skip;
46     } else if (result & VK_STRING_ERROR_LENGTH) {
47         skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
48                        "%s: string %s exceeds max length %d", apiName, stringName.get_name().c_str(), MaxParamCheckerStringLength);
49     } else if (result & VK_STRING_ERROR_BAD_DATA) {
50         skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid,
51                        "%s: string %s contains invalid characters or is badly formed", apiName, stringName.get_name().c_str());
52     }
53     return skip;
54 }
55 
validate_api_version(uint32_t api_version,uint32_t effective_api_version)56 bool StatelessValidation::validate_api_version(uint32_t api_version, uint32_t effective_api_version) {
57     bool skip = false;
58     uint32_t api_version_nopatch = VK_MAKE_VERSION(VK_VERSION_MAJOR(api_version), VK_VERSION_MINOR(api_version), 0);
59     if (api_version_nopatch != effective_api_version) {
60         if (api_version_nopatch < VK_API_VERSION_1_0) {
61             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
62                             HandleToUint64(instance), kVUIDUndefined,
63                             "Invalid CreateInstance->pCreateInfo->pApplicationInfo.apiVersion number (0x%08x). "
64                             "Using VK_API_VERSION_%" PRIu32 "_%" PRIu32 ".",
65                             api_version, VK_VERSION_MAJOR(effective_api_version), VK_VERSION_MINOR(effective_api_version));
66         } else {
67             skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
68                             HandleToUint64(instance), kVUIDUndefined,
69                             "Unrecognized CreateInstance->pCreateInfo->pApplicationInfo.apiVersion number (0x%08x). "
70                             "Assuming VK_API_VERSION_%" PRIu32 "_%" PRIu32 ".",
71                             api_version, VK_VERSION_MAJOR(effective_api_version), VK_VERSION_MINOR(effective_api_version));
72         }
73     }
74     return skip;
75 }
76 
validate_instance_extensions(const VkInstanceCreateInfo * pCreateInfo)77 bool StatelessValidation::validate_instance_extensions(const VkInstanceCreateInfo *pCreateInfo) {
78     bool skip = false;
79     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
80         skip |= validate_extension_reqs(instance_extensions, "VUID-vkCreateInstance-ppEnabledExtensionNames-01388", "instance",
81                                         pCreateInfo->ppEnabledExtensionNames[i]);
82     }
83 
84     return skip;
85 }
86 
87 template <typename ExtensionState>
extension_state_by_name(const ExtensionState & extensions,const char * extension_name)88 bool extension_state_by_name(const ExtensionState &extensions, const char *extension_name) {
89     if (!extension_name) return false;  // null strings specify nothing
90     auto info = ExtensionState::get_info(extension_name);
91     bool state = info.state ? extensions.*(info.state) : false;  // unknown extensions can't be enabled in extension struct
92     return state;
93 }
94 
manual_PreCallValidateCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)95 bool StatelessValidation::manual_PreCallValidateCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
96                                                                const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
97     bool skip = false;
98     // Note: From the spec--
99     //  Providing a NULL VkInstanceCreateInfo::pApplicationInfo or providing an apiVersion of 0 is equivalent to providing
100     //  an apiVersion of VK_MAKE_VERSION(1, 0, 0).  (a.k.a. VK_API_VERSION_1_0)
101     uint32_t local_api_version = (pCreateInfo->pApplicationInfo && pCreateInfo->pApplicationInfo->apiVersion)
102                                      ? pCreateInfo->pApplicationInfo->apiVersion
103                                      : VK_API_VERSION_1_0;
104     skip |= validate_api_version(local_api_version, api_version);
105     skip |= validate_instance_extensions(pCreateInfo);
106     return skip;
107 }
108 
PostCallRecordCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance,VkResult result)109 void StatelessValidation::PostCallRecordCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
110                                                        const VkAllocationCallbacks *pAllocator, VkInstance *pInstance,
111                                                        VkResult result) {
112     auto instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
113     // Copy extension data into local object
114     if (result != VK_SUCCESS) return;
115     this->instance_extensions = instance_data->instance_extensions;
116 }
117 
PostCallRecordQueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * pPresentInfo,VkResult result)118 void StatelessValidation::PostCallRecordQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo, VkResult result) {
119     for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
120         auto swapchains_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result;
121         if (swapchains_result == VK_SUBOPTIMAL_KHR) {
122             log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
123                     HandleToUint64(pPresentInfo->pSwapchains[i]), kVUID_PVPerfWarn_SuboptimalSwapchain,
124                     "vkQueuePresentKHR: %s :VK_SUBOPTIMAL_KHR was returned. VK_SUBOPTIMAL_KHR - Presentation will still succeed, "
125                     "subject to the window resize behavior, but the swapchain is no longer configured optimally for the surface it "
126                     "targets. Applications should query updated surface information and recreate their swapchain at the next "
127                     "convenient opportunity.",
128                     report_data->FormatHandle(pPresentInfo->pSwapchains[i]).c_str());
129         }
130     }
131 }
132 
PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice,VkResult result)133 void StatelessValidation::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
134                                                      const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
135     auto device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
136     if (result != VK_SUCCESS) return;
137     ValidationObject *validation_data = GetValidationObject(device_data->object_dispatch, LayerObjectTypeParameterValidation);
138     StatelessValidation *stateless_validation = static_cast<StatelessValidation *>(validation_data);
139 
140     // Parmeter validation also uses extension data
141     stateless_validation->device_extensions = this->device_extensions;
142 
143     VkPhysicalDeviceProperties device_properties = {};
144     // Need to get instance and do a getlayerdata call...
145     DispatchGetPhysicalDeviceProperties(physicalDevice, &device_properties);
146     memcpy(&stateless_validation->device_limits, &device_properties.limits, sizeof(VkPhysicalDeviceLimits));
147 
148     if (device_extensions.vk_nv_shading_rate_image) {
149         // Get the needed shading rate image limits
150         auto shading_rate_image_props = lvl_init_struct<VkPhysicalDeviceShadingRateImagePropertiesNV>();
151         auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&shading_rate_image_props);
152         DispatchGetPhysicalDeviceProperties2KHR(physicalDevice, &prop2);
153         phys_dev_ext_props.shading_rate_image_props = shading_rate_image_props;
154     }
155 
156     if (device_extensions.vk_nv_mesh_shader) {
157         // Get the needed mesh shader limits
158         auto mesh_shader_props = lvl_init_struct<VkPhysicalDeviceMeshShaderPropertiesNV>();
159         auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&mesh_shader_props);
160         DispatchGetPhysicalDeviceProperties2KHR(physicalDevice, &prop2);
161         phys_dev_ext_props.mesh_shader_props = mesh_shader_props;
162     }
163 
164     if (device_extensions.vk_nv_ray_tracing) {
165         // Get the needed ray tracing limits
166         auto ray_tracing_props = lvl_init_struct<VkPhysicalDeviceRayTracingPropertiesNV>();
167         auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&ray_tracing_props);
168         DispatchGetPhysicalDeviceProperties2KHR(physicalDevice, &prop2);
169         phys_dev_ext_props.ray_tracing_props = ray_tracing_props;
170     }
171 
172     stateless_validation->phys_dev_ext_props = this->phys_dev_ext_props;
173 
174     // Save app-enabled features in this device's validation object
175     // The enabled features can come from either pEnabledFeatures, or from the pNext chain
176     const auto *features2 = lvl_find_in_chain<VkPhysicalDeviceFeatures2>(pCreateInfo->pNext);
177     safe_VkPhysicalDeviceFeatures2 tmp_features2_state;
178     tmp_features2_state.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
179     if (features2) {
180         tmp_features2_state.features = features2->features;
181     } else if (pCreateInfo->pEnabledFeatures) {
182         tmp_features2_state.features = *pCreateInfo->pEnabledFeatures;
183     } else {
184         tmp_features2_state.features = {};
185     }
186     // Use pCreateInfo->pNext to get full chain
187     tmp_features2_state.pNext = SafePnextCopy(pCreateInfo->pNext);
188     stateless_validation->physical_device_features2 = tmp_features2_state;
189 }
190 
manual_PreCallValidateCreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)191 bool StatelessValidation::manual_PreCallValidateCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
192                                                              const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
193     bool skip = false;
194     bool maint1 = false;
195     bool negative_viewport = false;
196 
197     if ((pCreateInfo->enabledLayerCount > 0) && (pCreateInfo->ppEnabledLayerNames != NULL)) {
198         for (size_t i = 0; i < pCreateInfo->enabledLayerCount; i++) {
199             skip |= validate_string("vkCreateDevice", "pCreateInfo->ppEnabledLayerNames",
200                                     "VUID-VkDeviceCreateInfo-ppEnabledLayerNames-parameter", pCreateInfo->ppEnabledLayerNames[i]);
201         }
202     }
203 
204     if ((pCreateInfo->enabledExtensionCount > 0) && (pCreateInfo->ppEnabledExtensionNames != NULL)) {
205         maint1 = extension_state_by_name(device_extensions, VK_KHR_MAINTENANCE1_EXTENSION_NAME);
206         negative_viewport = extension_state_by_name(device_extensions, VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME);
207 
208         for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
209             skip |= validate_string("vkCreateDevice", "pCreateInfo->ppEnabledExtensionNames",
210                                     "VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-parameter",
211                                     pCreateInfo->ppEnabledExtensionNames[i]);
212             skip |= validate_extension_reqs(device_extensions, "VUID-vkCreateDevice-ppEnabledExtensionNames-01387", "device",
213                                             pCreateInfo->ppEnabledExtensionNames[i]);
214         }
215     }
216 
217     if (maint1 && negative_viewport) {
218         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
219                         "VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-00374",
220                         "VkDeviceCreateInfo->ppEnabledExtensionNames must not simultaneously include VK_KHR_maintenance1 and "
221                         "VK_AMD_negative_viewport_height.");
222     }
223 
224     if (pCreateInfo->pNext != NULL && pCreateInfo->pEnabledFeatures) {
225         // Check for get_physical_device_properties2 struct
226         const auto *features2 = lvl_find_in_chain<VkPhysicalDeviceFeatures2KHR>(pCreateInfo->pNext);
227         if (features2) {
228             // Cannot include VkPhysicalDeviceFeatures2KHR and have non-null pEnabledFeatures
229             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
230                             kVUID_PVError_InvalidUsage,
231                             "VkDeviceCreateInfo->pNext includes a VkPhysicalDeviceFeatures2KHR struct when "
232                             "pCreateInfo->pEnabledFeatures is non-NULL.");
233         }
234     }
235 
236     auto features2 = lvl_find_in_chain<VkPhysicalDeviceFeatures2>(pCreateInfo->pNext);
237     if (features2) {
238         if (!instance_extensions.vk_khr_get_physical_device_properties_2) {
239             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
240                             kVUID_PVError_ExtensionNotEnabled,
241                             "VkDeviceCreateInfo->pNext includes a VkPhysicalDeviceFeatures2 struct, "
242                             "VK_KHR_get_physical_device_properties2 must be enabled when it creates an instance.");
243         }
244     }
245 
246     auto vertex_attribute_divisor_features =
247         lvl_find_in_chain<VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT>(pCreateInfo->pNext);
248     if (vertex_attribute_divisor_features) {
249         bool extension_found = false;
250         for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; ++i) {
251             if (0 == strncmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
252                              VK_MAX_EXTENSION_NAME_SIZE)) {
253                 extension_found = true;
254                 break;
255             }
256         }
257         if (!extension_found) {
258             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
259                             kVUID_PVError_ExtensionNotEnabled,
260                             "VkDeviceCreateInfo->pNext includes a VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT "
261                             "struct, VK_EXT_vertex_attribute_divisor must be enabled when it creates a device.");
262         }
263     }
264 
265     // Validate pCreateInfo->pQueueCreateInfos
266     if (pCreateInfo->pQueueCreateInfos) {
267         std::unordered_set<uint32_t> set;
268 
269         for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; ++i) {
270             const uint32_t requested_queue_family = pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex;
271             if (requested_queue_family == VK_QUEUE_FAMILY_IGNORED) {
272                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
273                                 HandleToUint64(physicalDevice), "VUID-VkDeviceQueueCreateInfo-queueFamilyIndex-00381",
274                                 "vkCreateDevice: pCreateInfo->pQueueCreateInfos[%" PRIu32
275                                 "].queueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, but it is required to provide a valid queue family "
276                                 "index value.",
277                                 i);
278             } else if (set.count(requested_queue_family)) {
279                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
280                                 HandleToUint64(physicalDevice), "VUID-VkDeviceCreateInfo-queueFamilyIndex-00372",
281                                 "vkCreateDevice: pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueFamilyIndex (=%" PRIu32
282                                 ") is not unique within pCreateInfo->pQueueCreateInfos array.",
283                                 i, requested_queue_family);
284             } else {
285                 set.insert(requested_queue_family);
286             }
287 
288             if (pCreateInfo->pQueueCreateInfos[i].pQueuePriorities != nullptr) {
289                 for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; ++j) {
290                     const float queue_priority = pCreateInfo->pQueueCreateInfos[i].pQueuePriorities[j];
291                     if (!(queue_priority >= 0.f) || !(queue_priority <= 1.f)) {
292                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
293                                         HandleToUint64(physicalDevice), "VUID-VkDeviceQueueCreateInfo-pQueuePriorities-00383",
294                                         "vkCreateDevice: pCreateInfo->pQueueCreateInfos[%" PRIu32 "].pQueuePriorities[%" PRIu32
295                                         "] (=%f) is not between 0 and 1 (inclusive).",
296                                         i, j, queue_priority);
297                     }
298                 }
299             }
300         }
301     }
302 
303     return skip;
304 }
305 
require_device_extension(bool flag,char const * function_name,char const * extension_name)306 bool StatelessValidation::require_device_extension(bool flag, char const *function_name, char const *extension_name) {
307     if (!flag) {
308         return log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
309                        kVUID_PVError_ExtensionNotEnabled,
310                        "%s() called even though the %s extension was not enabled for this VkDevice.", function_name,
311                        extension_name);
312     }
313 
314     return false;
315 }
316 
manual_PreCallValidateCreateBuffer(VkDevice device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)317 bool StatelessValidation::manual_PreCallValidateCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
318                                                              const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
319     bool skip = false;
320 
321     const LogMiscParams log_misc{VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, VK_NULL_HANDLE, "vkCreateBuffer"};
322 
323     if (pCreateInfo != nullptr) {
324         skip |= ValidateGreaterThanZero(pCreateInfo->size, "pCreateInfo->size", "VUID-VkBufferCreateInfo-size-00912", log_misc);
325 
326         // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
327         if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
328             // If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
329             if (pCreateInfo->queueFamilyIndexCount <= 1) {
330                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
331                                 "VUID-VkBufferCreateInfo-sharingMode-00914",
332                                 "vkCreateBuffer: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
333                                 "pCreateInfo->queueFamilyIndexCount must be greater than 1.");
334             }
335 
336             // If sharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
337             // queueFamilyIndexCount uint32_t values
338             if (pCreateInfo->pQueueFamilyIndices == nullptr) {
339                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
340                                 "VUID-VkBufferCreateInfo-sharingMode-00913",
341                                 "vkCreateBuffer: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
342                                 "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
343                                 "pCreateInfo->queueFamilyIndexCount uint32_t values.");
344             }
345         }
346 
347         // If flags contains VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT or VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, it must also contain
348         // VK_BUFFER_CREATE_SPARSE_BINDING_BIT
349         if (((pCreateInfo->flags & (VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)) != 0) &&
350             ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
351             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
352                             "VUID-VkBufferCreateInfo-flags-00918",
353                             "vkCreateBuffer: if pCreateInfo->flags contains VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT or "
354                             "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, it must also contain VK_BUFFER_CREATE_SPARSE_BINDING_BIT.");
355         }
356     }
357 
358     return skip;
359 }
360 
manual_PreCallValidateCreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)361 bool StatelessValidation::manual_PreCallValidateCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
362                                                             const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
363     bool skip = false;
364 
365     const LogMiscParams log_misc{VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, VK_NULL_HANDLE, "vkCreateImage"};
366 
367     if (pCreateInfo != nullptr) {
368         // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
369         if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
370             // If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
371             if (pCreateInfo->queueFamilyIndexCount <= 1) {
372                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
373                                 "VUID-VkImageCreateInfo-sharingMode-00942",
374                                 "vkCreateImage(): if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
375                                 "pCreateInfo->queueFamilyIndexCount must be greater than 1.");
376             }
377 
378             // If sharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
379             // queueFamilyIndexCount uint32_t values
380             if (pCreateInfo->pQueueFamilyIndices == nullptr) {
381                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
382                                 "VUID-VkImageCreateInfo-sharingMode-00941",
383                                 "vkCreateImage(): if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
384                                 "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
385                                 "pCreateInfo->queueFamilyIndexCount uint32_t values.");
386             }
387         }
388 
389         skip |= ValidateGreaterThanZero(pCreateInfo->extent.width, "pCreateInfo->extent.width",
390                                         "VUID-VkImageCreateInfo-extent-00944", log_misc);
391         skip |= ValidateGreaterThanZero(pCreateInfo->extent.height, "pCreateInfo->extent.height",
392                                         "VUID-VkImageCreateInfo-extent-00945", log_misc);
393         skip |= ValidateGreaterThanZero(pCreateInfo->extent.depth, "pCreateInfo->extent.depth",
394                                         "VUID-VkImageCreateInfo-extent-00946", log_misc);
395 
396         skip |= ValidateGreaterThanZero(pCreateInfo->mipLevels, "pCreateInfo->mipLevels", "VUID-VkImageCreateInfo-mipLevels-00947",
397                                         log_misc);
398         skip |= ValidateGreaterThanZero(pCreateInfo->arrayLayers, "pCreateInfo->arrayLayers",
399                                         "VUID-VkImageCreateInfo-arrayLayers-00948", log_misc);
400 
401         // InitialLayout must be PREINITIALIZED or UNDEFINED
402         if ((pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED) &&
403             (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED)) {
404             skip |= log_msg(
405                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
406                 "VUID-VkImageCreateInfo-initialLayout-00993",
407                 "vkCreateImage(): initialLayout is %s, must be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED.",
408                 string_VkImageLayout(pCreateInfo->initialLayout));
409         }
410 
411         // If imageType is VK_IMAGE_TYPE_1D, both extent.height and extent.depth must be 1
412         if ((pCreateInfo->imageType == VK_IMAGE_TYPE_1D) &&
413             ((pCreateInfo->extent.height != 1) || (pCreateInfo->extent.depth != 1))) {
414             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
415                             "VUID-VkImageCreateInfo-imageType-00956",
416                             "vkCreateImage(): if pCreateInfo->imageType is VK_IMAGE_TYPE_1D, both pCreateInfo->extent.height and "
417                             "pCreateInfo->extent.depth must be 1.");
418         }
419 
420         if (pCreateInfo->imageType == VK_IMAGE_TYPE_2D) {
421             if (pCreateInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) {
422                 if (pCreateInfo->extent.width != pCreateInfo->extent.height) {
423                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
424                                     VK_NULL_HANDLE, "VUID-VkImageCreateInfo-imageType-00954",
425                                     "vkCreateImage(): pCreateInfo->flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, but "
426                                     "pCreateInfo->extent.width (=%" PRIu32 ") and pCreateInfo->extent.height (=%" PRIu32
427                                     ") are not equal.",
428                                     pCreateInfo->extent.width, pCreateInfo->extent.height);
429                 }
430 
431                 if (pCreateInfo->arrayLayers < 6) {
432                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
433                                     VK_NULL_HANDLE, "VUID-VkImageCreateInfo-imageType-00954",
434                                     "vkCreateImage(): pCreateInfo->flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, but "
435                                     "pCreateInfo->arrayLayers (=%" PRIu32 ") is not greater than or equal to 6.",
436                                     pCreateInfo->arrayLayers);
437                 }
438             }
439 
440             if (pCreateInfo->extent.depth != 1) {
441                 skip |=
442                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
443                             "VUID-VkImageCreateInfo-imageType-00957",
444                             "vkCreateImage(): if pCreateInfo->imageType is VK_IMAGE_TYPE_2D, pCreateInfo->extent.depth must be 1.");
445             }
446         }
447 
448         // 3D image may have only 1 layer
449         if ((pCreateInfo->imageType == VK_IMAGE_TYPE_3D) && (pCreateInfo->arrayLayers != 1)) {
450             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
451                             "VUID-VkImageCreateInfo-imageType-00961",
452                             "vkCreateImage(): if pCreateInfo->imageType is VK_IMAGE_TYPE_3D, pCreateInfo->arrayLayers must be 1.");
453         }
454 
455         // If multi-sample, validate type, usage, tiling and mip levels.
456         if ((pCreateInfo->samples != VK_SAMPLE_COUNT_1_BIT) &&
457             ((pCreateInfo->imageType != VK_IMAGE_TYPE_2D) || (pCreateInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) ||
458              (pCreateInfo->mipLevels != 1) || (pCreateInfo->tiling != VK_IMAGE_TILING_OPTIMAL))) {
459             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
460                             "VUID-VkImageCreateInfo-samples-02257",
461                             "vkCreateImage(): Multi-sample image with incompatible type, usage, tiling, or mips.");
462         }
463 
464         if (0 != (pCreateInfo->usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)) {
465             VkImageUsageFlags legal_flags = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
466                                              VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
467             // At least one of the legal attachment bits must be set
468             if (0 == (pCreateInfo->usage & legal_flags)) {
469                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
470                                 "VUID-VkImageCreateInfo-usage-00966",
471                                 "vkCreateImage(): Transient attachment image without a compatible attachment flag set.");
472             }
473             // No flags other than the legal attachment bits may be set
474             legal_flags |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
475             if (0 != (pCreateInfo->usage & ~legal_flags)) {
476                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
477                                 "VUID-VkImageCreateInfo-usage-00963",
478                                 "vkCreateImage(): Transient attachment image with incompatible usage flags set.");
479             }
480         }
481 
482         // mipLevels must be less than or equal to the number of levels in the complete mipmap chain
483         uint32_t maxDim = std::max(std::max(pCreateInfo->extent.width, pCreateInfo->extent.height), pCreateInfo->extent.depth);
484         // Max mip levels is different for corner-sampled images vs normal images.
485         uint32_t maxMipLevels = (pCreateInfo->flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) ? (uint32_t)(ceil(log2(maxDim)))
486                                                                                              : (uint32_t)(floor(log2(maxDim)) + 1);
487         if (maxDim > 0 && pCreateInfo->mipLevels > maxMipLevels) {
488             skip |=
489                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
490                         "VUID-VkImageCreateInfo-mipLevels-00958",
491                         "vkCreateImage(): pCreateInfo->mipLevels must be less than or equal to "
492                         "floor(log2(max(pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth)))+1.");
493         }
494 
495         if ((pCreateInfo->flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT) && (pCreateInfo->imageType != VK_IMAGE_TYPE_3D)) {
496             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, VK_NULL_HANDLE,
497                             "VUID-VkImageCreateInfo-flags-00950",
498                             "vkCreateImage(): pCreateInfo->flags contains VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT but "
499                             "pCreateInfo->imageType is not VK_IMAGE_TYPE_3D.");
500         }
501 
502         if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && (!physical_device_features.sparseBinding)) {
503             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, VK_NULL_HANDLE,
504                             "VUID-VkImageCreateInfo-flags-00969",
505                             "vkCreateImage(): pCreateInfo->flags contains VK_IMAGE_CREATE_SPARSE_BINDING_BIT, but the "
506                             "VkPhysicalDeviceFeatures::sparseBinding feature is disabled.");
507         }
508 
509         // If flags contains VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT or VK_IMAGE_CREATE_SPARSE_ALIASED_BIT, it must also contain
510         // VK_IMAGE_CREATE_SPARSE_BINDING_BIT
511         if (((pCreateInfo->flags & (VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT)) != 0) &&
512             ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
513             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
514                             "VUID-VkImageCreateInfo-flags-00987",
515                             "vkCreateImage: if pCreateInfo->flags contains VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT or "
516                             "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT, it must also contain VK_IMAGE_CREATE_SPARSE_BINDING_BIT.");
517         }
518 
519         // Check for combinations of attributes that are incompatible with having VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT set
520         if ((pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) {
521             // Linear tiling is unsupported
522             if (VK_IMAGE_TILING_LINEAR == pCreateInfo->tiling) {
523                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
524                                 kVUID_PVError_InvalidUsage,
525                                 "vkCreateImage: if pCreateInfo->flags contains VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT then image "
526                                 "tiling of VK_IMAGE_TILING_LINEAR is not supported");
527             }
528 
529             // Sparse 1D image isn't valid
530             if (VK_IMAGE_TYPE_1D == pCreateInfo->imageType) {
531                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
532                                 "VUID-VkImageCreateInfo-imageType-00970",
533                                 "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 1D image.");
534             }
535 
536             // Sparse 2D image when device doesn't support it
537             if ((VK_FALSE == physical_device_features.sparseResidencyImage2D) && (VK_IMAGE_TYPE_2D == pCreateInfo->imageType)) {
538                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
539                                 "VUID-VkImageCreateInfo-imageType-00971",
540                                 "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 2D image if corresponding "
541                                 "feature is not enabled on the device.");
542             }
543 
544             // Sparse 3D image when device doesn't support it
545             if ((VK_FALSE == physical_device_features.sparseResidencyImage3D) && (VK_IMAGE_TYPE_3D == pCreateInfo->imageType)) {
546                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
547                                 "VUID-VkImageCreateInfo-imageType-00972",
548                                 "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 3D image if corresponding "
549                                 "feature is not enabled on the device.");
550             }
551 
552             // Multi-sample 2D image when device doesn't support it
553             if (VK_IMAGE_TYPE_2D == pCreateInfo->imageType) {
554                 if ((VK_FALSE == physical_device_features.sparseResidency2Samples) &&
555                     (VK_SAMPLE_COUNT_2_BIT == pCreateInfo->samples)) {
556                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
557                                     "VUID-VkImageCreateInfo-imageType-00973",
558                                     "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 2-sample image if "
559                                     "corresponding feature is not enabled on the device.");
560                 } else if ((VK_FALSE == physical_device_features.sparseResidency4Samples) &&
561                            (VK_SAMPLE_COUNT_4_BIT == pCreateInfo->samples)) {
562                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
563                                     "VUID-VkImageCreateInfo-imageType-00974",
564                                     "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 4-sample image if "
565                                     "corresponding feature is not enabled on the device.");
566                 } else if ((VK_FALSE == physical_device_features.sparseResidency8Samples) &&
567                            (VK_SAMPLE_COUNT_8_BIT == pCreateInfo->samples)) {
568                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
569                                     "VUID-VkImageCreateInfo-imageType-00975",
570                                     "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 8-sample image if "
571                                     "corresponding feature is not enabled on the device.");
572                 } else if ((VK_FALSE == physical_device_features.sparseResidency16Samples) &&
573                            (VK_SAMPLE_COUNT_16_BIT == pCreateInfo->samples)) {
574                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
575                                     "VUID-VkImageCreateInfo-imageType-00976",
576                                     "vkCreateImage: cannot specify VK_IMAGE_CREATE_SPARSE_BINDING_BIT for 16-sample image if "
577                                     "corresponding feature is not enabled on the device.");
578                 }
579             }
580         }
581 
582         if (pCreateInfo->usage & VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV) {
583             if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) {
584                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
585                                 "VUID-VkImageCreateInfo-imageType-02082",
586                                 "vkCreateImage: if usage includes VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV, "
587                                 "imageType must be VK_IMAGE_TYPE_2D.");
588             }
589             if (pCreateInfo->samples != VK_SAMPLE_COUNT_1_BIT) {
590                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
591                                 "VUID-VkImageCreateInfo-samples-02083",
592                                 "vkCreateImage: if usage includes VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV, "
593                                 "samples must be VK_SAMPLE_COUNT_1_BIT.");
594             }
595             if (pCreateInfo->tiling != VK_IMAGE_TILING_OPTIMAL) {
596                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
597                                 "VUID-VkImageCreateInfo-tiling-02084",
598                                 "vkCreateImage: if usage includes VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV, "
599                                 "tiling must be VK_IMAGE_TILING_OPTIMAL.");
600             }
601         }
602 
603         if (pCreateInfo->flags & VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV) {
604             if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D && pCreateInfo->imageType != VK_IMAGE_TYPE_3D) {
605                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
606                                 "VUID-VkImageCreateInfo-flags-02050",
607                                 "vkCreateImage: If flags contains VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV, "
608                                 "imageType must be VK_IMAGE_TYPE_2D or VK_IMAGE_TYPE_3D.");
609             }
610 
611             if ((pCreateInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) || FormatIsDepthOrStencil(pCreateInfo->format)) {
612                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
613                                 "VUID-VkImageCreateInfo-flags-02051",
614                                 "vkCreateImage: If flags contains VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV, "
615                                 "it must not also contain VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT and format must "
616                                 "not be a depth/stencil format.");
617             }
618 
619             if (pCreateInfo->imageType == VK_IMAGE_TYPE_2D && (pCreateInfo->extent.width == 1 || pCreateInfo->extent.height == 1)) {
620                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
621                                 "VUID-VkImageCreateInfo-flags-02052",
622                                 "vkCreateImage: If flags contains VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and "
623                                 "imageType is VK_IMAGE_TYPE_2D, extent.width and extent.height must be "
624                                 "greater than 1.");
625             } else if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D &&
626                        (pCreateInfo->extent.width == 1 || pCreateInfo->extent.height == 1 || pCreateInfo->extent.depth == 1)) {
627                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
628                                 "VUID-VkImageCreateInfo-flags-02053",
629                                 "vkCreateImage: If flags contains VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV and "
630                                 "imageType is VK_IMAGE_TYPE_3D, extent.width, extent.height, and extent.depth "
631                                 "must be greater than 1.");
632             }
633         }
634     }
635 
636     return skip;
637 }
638 
manual_PreCallValidateViewport(const VkViewport & viewport,const char * fn_name,const ParameterName & parameter_name,VkDebugReportObjectTypeEXT object_type,uint64_t object=0)639 bool StatelessValidation::manual_PreCallValidateViewport(const VkViewport &viewport, const char *fn_name,
640                                                          const ParameterName &parameter_name,
641                                                          VkDebugReportObjectTypeEXT object_type, uint64_t object = 0) {
642     bool skip = false;
643 
644     // Note: for numerical correctness
645     //       - float comparisons should expect NaN (comparison always false).
646     //       - VkPhysicalDeviceLimits::maxViewportDimensions is uint32_t, not float -> careful.
647 
648     const auto f_lte_u32_exact = [](const float v1_f, const uint32_t v2_u32) {
649         if (std::isnan(v1_f)) return false;
650         if (v1_f <= 0.0f) return true;
651 
652         float intpart;
653         const float fract = modff(v1_f, &intpart);
654 
655         assert(std::numeric_limits<float>::radix == 2);
656         const float u32_max_plus1 = ldexpf(1.0f, 32);  // hopefully exact
657         if (intpart >= u32_max_plus1) return false;
658 
659         uint32_t v1_u32 = static_cast<uint32_t>(intpart);
660         if (v1_u32 < v2_u32)
661             return true;
662         else if (v1_u32 == v2_u32 && fract == 0.0f)
663             return true;
664         else
665             return false;
666     };
667 
668     const auto f_lte_u32_direct = [](const float v1_f, const uint32_t v2_u32) {
669         const float v2_f = static_cast<float>(v2_u32);  // not accurate for > radix^digits; and undefined rounding mode
670         return (v1_f <= v2_f);
671     };
672 
673     // width
674     bool width_healthy = true;
675     const auto max_w = device_limits.maxViewportDimensions[0];
676 
677     if (!(viewport.width > 0.0f)) {
678         width_healthy = false;
679         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-width-01770",
680                         "%s: %s.width (=%f) is not greater than 0.0.", fn_name, parameter_name.get_name().c_str(), viewport.width);
681     } else if (!(f_lte_u32_exact(viewport.width, max_w) || f_lte_u32_direct(viewport.width, max_w))) {
682         width_healthy = false;
683         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-width-01771",
684                         "%s: %s.width (=%f) exceeds VkPhysicalDeviceLimits::maxViewportDimensions[0] (=%" PRIu32 ").", fn_name,
685                         parameter_name.get_name().c_str(), viewport.width, max_w);
686     } else if (!f_lte_u32_exact(viewport.width, max_w) && f_lte_u32_direct(viewport.width, max_w)) {
687         skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, object_type, object, kVUID_PVError_NONE,
688                         "%s: %s.width (=%f) technically exceeds VkPhysicalDeviceLimits::maxViewportDimensions[0] (=%" PRIu32
689                         "), but it is within the static_cast<float>(maxViewportDimensions[0]) limit.",
690                         fn_name, parameter_name.get_name().c_str(), viewport.width, max_w);
691     }
692 
693     // height
694     bool height_healthy = true;
695     const bool negative_height_enabled = api_version >= VK_API_VERSION_1_1 || device_extensions.vk_khr_maintenance1 ||
696                                          device_extensions.vk_amd_negative_viewport_height;
697     const auto max_h = device_limits.maxViewportDimensions[1];
698 
699     if (!negative_height_enabled && !(viewport.height > 0.0f)) {
700         height_healthy = false;
701         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-height-01772",
702                         "%s: %s.height (=%f) is not greater 0.0.", fn_name, parameter_name.get_name().c_str(), viewport.height);
703     } else if (!(f_lte_u32_exact(fabsf(viewport.height), max_h) || f_lte_u32_direct(fabsf(viewport.height), max_h))) {
704         height_healthy = false;
705 
706         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-height-01773",
707                         "%s: Absolute value of %s.height (=%f) exceeds VkPhysicalDeviceLimits::maxViewportDimensions[1] (=%" PRIu32
708                         ").",
709                         fn_name, parameter_name.get_name().c_str(), viewport.height, max_h);
710     } else if (!f_lte_u32_exact(fabsf(viewport.height), max_h) && f_lte_u32_direct(fabsf(viewport.height), max_h)) {
711         height_healthy = false;
712 
713         skip |= log_msg(
714             report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, object_type, object, kVUID_PVError_NONE,
715             "%s: Absolute value of %s.height (=%f) technically exceeds VkPhysicalDeviceLimits::maxViewportDimensions[1] (=%" PRIu32
716             "), but it is within the static_cast<float>(maxViewportDimensions[1]) limit.",
717             fn_name, parameter_name.get_name().c_str(), viewport.height, max_h);
718     }
719 
720     // x
721     bool x_healthy = true;
722     if (!(viewport.x >= device_limits.viewportBoundsRange[0])) {
723         x_healthy = false;
724         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-x-01774",
725                         "%s: %s.x (=%f) is less than VkPhysicalDeviceLimits::viewportBoundsRange[0] (=%f).", fn_name,
726                         parameter_name.get_name().c_str(), viewport.x, device_limits.viewportBoundsRange[0]);
727     }
728 
729     // x + width
730     if (x_healthy && width_healthy) {
731         const float right_bound = viewport.x + viewport.width;
732         if (!(right_bound <= device_limits.viewportBoundsRange[1])) {
733             skip |=
734                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-x-01232",
735                         "%s: %s.x + %s.width (=%f + %f = %f) is greater than VkPhysicalDeviceLimits::viewportBoundsRange[1] (=%f).",
736                         fn_name, parameter_name.get_name().c_str(), parameter_name.get_name().c_str(), viewport.x, viewport.width,
737                         right_bound, device_limits.viewportBoundsRange[1]);
738         }
739     }
740 
741     // y
742     bool y_healthy = true;
743     if (!(viewport.y >= device_limits.viewportBoundsRange[0])) {
744         y_healthy = false;
745         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-y-01775",
746                         "%s: %s.y (=%f) is less than VkPhysicalDeviceLimits::viewportBoundsRange[0] (=%f).", fn_name,
747                         parameter_name.get_name().c_str(), viewport.y, device_limits.viewportBoundsRange[0]);
748     } else if (negative_height_enabled && !(viewport.y <= device_limits.viewportBoundsRange[1])) {
749         y_healthy = false;
750         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-y-01776",
751                         "%s: %s.y (=%f) exceeds VkPhysicalDeviceLimits::viewportBoundsRange[1] (=%f).", fn_name,
752                         parameter_name.get_name().c_str(), viewport.y, device_limits.viewportBoundsRange[1]);
753     }
754 
755     // y + height
756     if (y_healthy && height_healthy) {
757         const float boundary = viewport.y + viewport.height;
758 
759         if (!(boundary <= device_limits.viewportBoundsRange[1])) {
760             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-y-01233",
761                             "%s: %s.y + %s.height (=%f + %f = %f) exceeds VkPhysicalDeviceLimits::viewportBoundsRange[1] (=%f).",
762                             fn_name, parameter_name.get_name().c_str(), parameter_name.get_name().c_str(), viewport.y,
763                             viewport.height, boundary, device_limits.viewportBoundsRange[1]);
764         } else if (negative_height_enabled && !(boundary >= device_limits.viewportBoundsRange[0])) {
765             skip |=
766                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-y-01777",
767                         "%s: %s.y + %s.height (=%f + %f = %f) is less than VkPhysicalDeviceLimits::viewportBoundsRange[0] (=%f).",
768                         fn_name, parameter_name.get_name().c_str(), parameter_name.get_name().c_str(), viewport.y, viewport.height,
769                         boundary, device_limits.viewportBoundsRange[0]);
770         }
771     }
772 
773     if (!device_extensions.vk_ext_depth_range_unrestricted) {
774         // minDepth
775         if (!(viewport.minDepth >= 0.0) || !(viewport.minDepth <= 1.0)) {
776             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-minDepth-01234",
777 
778                             "%s: VK_EXT_depth_range_unrestricted extension is not enabled and %s.minDepth (=%f) is not within the "
779                             "[0.0, 1.0] range.",
780                             fn_name, parameter_name.get_name().c_str(), viewport.minDepth);
781         }
782 
783         // maxDepth
784         if (!(viewport.maxDepth >= 0.0) || !(viewport.maxDepth <= 1.0)) {
785             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object, "VUID-VkViewport-maxDepth-01235",
786 
787                             "%s: VK_EXT_depth_range_unrestricted extension is not enabled and %s.maxDepth (=%f) is not within the "
788                             "[0.0, 1.0] range.",
789                             fn_name, parameter_name.get_name().c_str(), viewport.maxDepth);
790         }
791     }
792 
793     return skip;
794 }
795 
796 struct SampleOrderInfo {
797     VkShadingRatePaletteEntryNV shadingRate;
798     uint32_t width;
799     uint32_t height;
800 };
801 
802 // All palette entries with more than one pixel per fragment
803 static SampleOrderInfo sampleOrderInfos[] = {
804     {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV, 1, 2},
805     {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV, 2, 1},
806     {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV, 2, 2},
807     {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV, 4, 2},
808     {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV, 2, 4},
809     {VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV, 4, 4},
810 };
811 
ValidateCoarseSampleOrderCustomNV(const VkCoarseSampleOrderCustomNV * order)812 bool StatelessValidation::ValidateCoarseSampleOrderCustomNV(const VkCoarseSampleOrderCustomNV *order) {
813     bool skip = false;
814 
815     SampleOrderInfo *sampleOrderInfo;
816     uint32_t infoIdx = 0;
817     for (sampleOrderInfo = nullptr; infoIdx < ARRAY_SIZE(sampleOrderInfos); ++infoIdx) {
818         if (sampleOrderInfos[infoIdx].shadingRate == order->shadingRate) {
819             sampleOrderInfo = &sampleOrderInfos[infoIdx];
820             break;
821         }
822     }
823 
824     if (sampleOrderInfo == nullptr) {
825         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
826                         "VUID-VkCoarseSampleOrderCustomNV-shadingRate-02073",
827                         "VkCoarseSampleOrderCustomNV shadingRate must be a shading rate "
828                         "that generates fragments with more than one pixel.");
829         return skip;
830     }
831 
832     if (order->sampleCount == 0 || (order->sampleCount & (order->sampleCount - 1)) ||
833         !(order->sampleCount & device_limits.framebufferNoAttachmentsSampleCounts)) {
834         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
835                         "VUID-VkCoarseSampleOrderCustomNV-sampleCount-02074",
836                         "VkCoarseSampleOrderCustomNV sampleCount (=%" PRIu32
837                         ") must "
838                         "correspond to a sample count enumerated in VkSampleCountFlags whose corresponding bit "
839                         "is set in framebufferNoAttachmentsSampleCounts.",
840                         order->sampleCount);
841     }
842 
843     if (order->sampleLocationCount != order->sampleCount * sampleOrderInfo->width * sampleOrderInfo->height) {
844         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
845                         "VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02075",
846                         "VkCoarseSampleOrderCustomNV sampleLocationCount (=%" PRIu32
847                         ") must "
848                         "be equal to the product of sampleCount (=%" PRIu32
849                         "), the fragment width for shadingRate "
850                         "(=%" PRIu32 "), and the fragment height for shadingRate (=%" PRIu32 ").",
851                         order->sampleLocationCount, order->sampleCount, sampleOrderInfo->width, sampleOrderInfo->height);
852     }
853 
854     if (order->sampleLocationCount > phys_dev_ext_props.shading_rate_image_props.shadingRateMaxCoarseSamples) {
855         skip |= log_msg(
856             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
857             "VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02076",
858             "VkCoarseSampleOrderCustomNV sampleLocationCount (=%" PRIu32
859             ") must "
860             "be less than or equal to VkPhysicalDeviceShadingRateImagePropertiesNV shadingRateMaxCoarseSamples (=%" PRIu32 ").",
861             order->sampleLocationCount, phys_dev_ext_props.shading_rate_image_props.shadingRateMaxCoarseSamples);
862     }
863 
864     // Accumulate a bitmask tracking which (x,y,sample) tuples are seen. Expect
865     // the first width*height*sampleCount bits to all be set. Note: There is no
866     // guarantee that 64 bits is enough, but practically it's unlikely for an
867     // implementation to support more than 32 bits for samplemask.
868     assert(phys_dev_ext_props.shading_rate_image_props.shadingRateMaxCoarseSamples <= 64);
869     uint64_t sampleLocationsMask = 0;
870     for (uint32_t i = 0; i < order->sampleLocationCount; ++i) {
871         const VkCoarseSampleLocationNV *sampleLoc = &order->pSampleLocations[i];
872         if (sampleLoc->pixelX >= sampleOrderInfo->width) {
873             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
874                             "VUID-VkCoarseSampleLocationNV-pixelX-02078",
875                             "pixelX must be less than the width (in pixels) of the fragment.");
876         }
877         if (sampleLoc->pixelY >= sampleOrderInfo->height) {
878             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
879                             "VUID-VkCoarseSampleLocationNV-pixelY-02079",
880                             "pixelY must be less than the height (in pixels) of the fragment.");
881         }
882         if (sampleLoc->sample >= order->sampleCount) {
883             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
884                             "VUID-VkCoarseSampleLocationNV-sample-02080",
885                             "sample must be less than the number of coverage samples in each pixel belonging to the fragment.");
886         }
887         uint32_t idx = sampleLoc->sample + order->sampleCount * (sampleLoc->pixelX + sampleOrderInfo->width * sampleLoc->pixelY);
888         sampleLocationsMask |= 1ULL << idx;
889     }
890 
891     uint64_t expectedMask = (order->sampleLocationCount == 64) ? ~0ULL : ((1ULL << order->sampleLocationCount) - 1);
892     if (sampleLocationsMask != expectedMask) {
893         skip |= log_msg(
894             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
895             "VUID-VkCoarseSampleOrderCustomNV-pSampleLocations-02077",
896             "The array pSampleLocations must contain exactly one entry for "
897             "every combination of valid values for pixelX, pixelY, and sample in the structure VkCoarseSampleOrderCustomNV.");
898     }
899 
900     return skip;
901 }
902 
manual_PreCallValidateCreateGraphicsPipelines(VkDevice device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkGraphicsPipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)903 bool StatelessValidation::manual_PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache,
904                                                                         uint32_t createInfoCount,
905                                                                         const VkGraphicsPipelineCreateInfo *pCreateInfos,
906                                                                         const VkAllocationCallbacks *pAllocator,
907                                                                         VkPipeline *pPipelines) {
908     bool skip = false;
909 
910     if (pCreateInfos != nullptr) {
911         for (uint32_t i = 0; i < createInfoCount; ++i) {
912             bool has_dynamic_viewport = false;
913             bool has_dynamic_scissor = false;
914             bool has_dynamic_line_width = false;
915             bool has_dynamic_viewport_w_scaling_nv = false;
916             bool has_dynamic_discard_rectangle_ext = false;
917             bool has_dynamic_sample_locations_ext = false;
918             bool has_dynamic_exclusive_scissor_nv = false;
919             bool has_dynamic_shading_rate_palette_nv = false;
920             bool has_dynamic_line_stipple = false;
921             if (pCreateInfos[i].pDynamicState != nullptr) {
922                 const auto &dynamic_state_info = *pCreateInfos[i].pDynamicState;
923                 for (uint32_t state_index = 0; state_index < dynamic_state_info.dynamicStateCount; ++state_index) {
924                     const auto &dynamic_state = dynamic_state_info.pDynamicStates[state_index];
925                     if (dynamic_state == VK_DYNAMIC_STATE_VIEWPORT) has_dynamic_viewport = true;
926                     if (dynamic_state == VK_DYNAMIC_STATE_SCISSOR) has_dynamic_scissor = true;
927                     if (dynamic_state == VK_DYNAMIC_STATE_LINE_WIDTH) has_dynamic_line_width = true;
928                     if (dynamic_state == VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV) has_dynamic_viewport_w_scaling_nv = true;
929                     if (dynamic_state == VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT) has_dynamic_discard_rectangle_ext = true;
930                     if (dynamic_state == VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT) has_dynamic_sample_locations_ext = true;
931                     if (dynamic_state == VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV) has_dynamic_exclusive_scissor_nv = true;
932                     if (dynamic_state == VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV)
933                         has_dynamic_shading_rate_palette_nv = true;
934                     if (dynamic_state == VK_DYNAMIC_STATE_LINE_STIPPLE_EXT) has_dynamic_line_stipple = true;
935                 }
936             }
937 
938             auto feedback_struct = lvl_find_in_chain<VkPipelineCreationFeedbackCreateInfoEXT>(pCreateInfos[i].pNext);
939             if ((feedback_struct != nullptr) &&
940                 (feedback_struct->pipelineStageCreationFeedbackCount != pCreateInfos[i].stageCount)) {
941                 skip |=
942                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
943                             "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02668",
944                             "vkCreateGraphicsPipelines(): in pCreateInfo[%" PRIu32
945                             "], VkPipelineCreationFeedbackEXT::pipelineStageCreationFeedbackCount"
946                             "(=%" PRIu32 ") must equal VkGraphicsPipelineCreateInfo::stageCount(=%" PRIu32 ").",
947                             i, feedback_struct->pipelineStageCreationFeedbackCount, pCreateInfos[i].stageCount);
948             }
949 
950             // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
951 
952             // Collect active stages
953             uint32_t active_shaders = 0;
954             for (uint32_t stages = 0; stages < pCreateInfos[i].stageCount; stages++) {
955                 active_shaders |= pCreateInfos[i].pStages->stage;
956             }
957 
958             if ((active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) &&
959                 (active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && (pCreateInfos[i].pTessellationState != nullptr)) {
960                 skip |= validate_struct_type("vkCreateGraphicsPipelines", "pCreateInfos[i].pTessellationState",
961                                              "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO",
962                                              pCreateInfos[i].pTessellationState,
963                                              VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, false, kVUIDUndefined,
964                                              "VUID-VkPipelineTessellationStateCreateInfo-sType-sType");
965 
966                 const VkStructureType allowed_structs_VkPipelineTessellationStateCreateInfo[] = {
967                     VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO};
968 
969                 skip |= validate_struct_pnext("vkCreateGraphicsPipelines", "pCreateInfos[i].pTessellationState->pNext",
970                                               "VkPipelineTessellationDomainOriginStateCreateInfo",
971                                               pCreateInfos[i].pTessellationState->pNext,
972                                               ARRAY_SIZE(allowed_structs_VkPipelineTessellationStateCreateInfo),
973                                               allowed_structs_VkPipelineTessellationStateCreateInfo, GeneratedVulkanHeaderVersion,
974                                               "VUID-VkPipelineTessellationStateCreateInfo-pNext-pNext");
975 
976                 skip |= validate_reserved_flags("vkCreateGraphicsPipelines", "pCreateInfos[i].pTessellationState->flags",
977                                                 pCreateInfos[i].pTessellationState->flags,
978                                                 "VUID-VkPipelineTessellationStateCreateInfo-flags-zerobitmask");
979             }
980 
981             if (!(active_shaders & VK_SHADER_STAGE_MESH_BIT_NV) && (pCreateInfos[i].pInputAssemblyState != nullptr)) {
982                 skip |= validate_struct_type("vkCreateGraphicsPipelines", "pCreateInfos[i].pInputAssemblyState",
983                                              "VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO",
984                                              pCreateInfos[i].pInputAssemblyState,
985                                              VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, false, kVUIDUndefined,
986                                              "VUID-VkPipelineInputAssemblyStateCreateInfo-sType-sType");
987 
988                 skip |= validate_struct_pnext("vkCreateGraphicsPipelines", "pCreateInfos[i].pInputAssemblyState->pNext", NULL,
989                                               pCreateInfos[i].pInputAssemblyState->pNext, 0, NULL, GeneratedVulkanHeaderVersion,
990                                               "VUID-VkPipelineInputAssemblyStateCreateInfo-pNext-pNext");
991 
992                 skip |= validate_reserved_flags("vkCreateGraphicsPipelines", "pCreateInfos[i].pInputAssemblyState->flags",
993                                                 pCreateInfos[i].pInputAssemblyState->flags,
994                                                 "VUID-VkPipelineInputAssemblyStateCreateInfo-flags-zerobitmask");
995 
996                 skip |= validate_ranged_enum("vkCreateGraphicsPipelines", "pCreateInfos[i].pInputAssemblyState->topology",
997                                              "VkPrimitiveTopology", AllVkPrimitiveTopologyEnums,
998                                              pCreateInfos[i].pInputAssemblyState->topology,
999                                              "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter");
1000 
1001                 skip |= validate_bool32("vkCreateGraphicsPipelines", "pCreateInfos[i].pInputAssemblyState->primitiveRestartEnable",
1002                                         pCreateInfos[i].pInputAssemblyState->primitiveRestartEnable);
1003             }
1004 
1005             if (!(active_shaders & VK_SHADER_STAGE_MESH_BIT_NV) && (pCreateInfos[i].pVertexInputState != nullptr)) {
1006                 auto const &vertex_input_state = pCreateInfos[i].pVertexInputState;
1007 
1008                 if (pCreateInfos[i].pVertexInputState->flags != 0) {
1009                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1010                                     "VUID-VkPipelineVertexInputStateCreateInfo-flags-zerobitmask",
1011                                     "vkCreateGraphicsPipelines: pararameter "
1012                                     "pCreateInfos[%d].pVertexInputState->flags (%u) is reserved and must be zero.",
1013                                     i, vertex_input_state->flags);
1014                 }
1015 
1016                 const VkStructureType allowed_structs_VkPipelineVertexInputStateCreateInfo[] = {
1017                     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT};
1018                 skip |= validate_struct_pnext("vkCreateGraphicsPipelines", "pCreateInfos[i].pVertexInputState->pNext",
1019                                               "VkPipelineVertexInputDivisorStateCreateInfoEXT",
1020                                               pCreateInfos[i].pVertexInputState->pNext, 1,
1021                                               allowed_structs_VkPipelineVertexInputStateCreateInfo, GeneratedVulkanHeaderVersion,
1022                                               "VUID-VkPipelineVertexInputStateCreateInfo-pNext-pNext");
1023                 skip |= validate_struct_type("vkCreateGraphicsPipelines", "pCreateInfos[i].pVertexInputState",
1024                                              "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO", vertex_input_state,
1025                                              VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, false, kVUIDUndefined,
1026                                              "VUID-VkPipelineVertexInputStateCreateInfo-sType-sType");
1027                 skip |=
1028                     validate_array("vkCreateGraphicsPipelines", "pCreateInfos[i].pVertexInputState->vertexBindingDescriptionCount",
1029                                    "pCreateInfos[i].pVertexInputState->pVertexBindingDescriptions",
1030                                    pCreateInfos[i].pVertexInputState->vertexBindingDescriptionCount,
1031                                    &pCreateInfos[i].pVertexInputState->pVertexBindingDescriptions, false, true, kVUIDUndefined,
1032                                    "VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-parameter");
1033 
1034                 skip |= validate_array(
1035                     "vkCreateGraphicsPipelines", "pCreateInfos[i].pVertexInputState->vertexAttributeDescriptionCount",
1036                     "pCreateInfos[i]->pVertexAttributeDescriptions", vertex_input_state->vertexAttributeDescriptionCount,
1037                     &vertex_input_state->pVertexAttributeDescriptions, false, true, kVUIDUndefined,
1038                     "VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-parameter");
1039 
1040                 if (pCreateInfos[i].pVertexInputState->pVertexBindingDescriptions != NULL) {
1041                     for (uint32_t vertexBindingDescriptionIndex = 0;
1042                          vertexBindingDescriptionIndex < pCreateInfos[i].pVertexInputState->vertexBindingDescriptionCount;
1043                          ++vertexBindingDescriptionIndex) {
1044                         skip |= validate_ranged_enum(
1045                             "vkCreateGraphicsPipelines",
1046                             "pCreateInfos[i].pVertexInputState->pVertexBindingDescriptions[j].inputRate", "VkVertexInputRate",
1047                             AllVkVertexInputRateEnums,
1048                             pCreateInfos[i].pVertexInputState->pVertexBindingDescriptions[vertexBindingDescriptionIndex].inputRate,
1049                             "VUID-VkVertexInputBindingDescription-inputRate-parameter");
1050                     }
1051                 }
1052 
1053                 if (pCreateInfos[i].pVertexInputState->pVertexAttributeDescriptions != NULL) {
1054                     for (uint32_t vertexAttributeDescriptionIndex = 0;
1055                          vertexAttributeDescriptionIndex < pCreateInfos[i].pVertexInputState->vertexAttributeDescriptionCount;
1056                          ++vertexAttributeDescriptionIndex) {
1057                         skip |= validate_ranged_enum(
1058                             "vkCreateGraphicsPipelines",
1059                             "pCreateInfos[i].pVertexInputState->pVertexAttributeDescriptions[i].format", "VkFormat",
1060                             AllVkFormatEnums,
1061                             pCreateInfos[i].pVertexInputState->pVertexAttributeDescriptions[vertexAttributeDescriptionIndex].format,
1062                             "VUID-VkVertexInputAttributeDescription-format-parameter");
1063                     }
1064                 }
1065 
1066                 if (vertex_input_state->vertexBindingDescriptionCount > device_limits.maxVertexInputBindings) {
1067                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1068                                     "VUID-VkPipelineVertexInputStateCreateInfo-vertexBindingDescriptionCount-00613",
1069                                     "vkCreateGraphicsPipelines: pararameter "
1070                                     "pCreateInfo[%d].pVertexInputState->vertexBindingDescriptionCount (%u) is "
1071                                     "greater than VkPhysicalDeviceLimits::maxVertexInputBindings (%u).",
1072                                     i, vertex_input_state->vertexBindingDescriptionCount, device_limits.maxVertexInputBindings);
1073                 }
1074 
1075                 if (vertex_input_state->vertexAttributeDescriptionCount > device_limits.maxVertexInputAttributes) {
1076                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1077                                     "VUID-VkPipelineVertexInputStateCreateInfo-vertexAttributeDescriptionCount-00614",
1078                                     "vkCreateGraphicsPipelines: pararameter "
1079                                     "pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptionCount (%u) is "
1080                                     "greater than VkPhysicalDeviceLimits::maxVertexInputAttributes (%u).",
1081                                     i, vertex_input_state->vertexAttributeDescriptionCount, device_limits.maxVertexInputAttributes);
1082                 }
1083 
1084                 std::unordered_set<uint32_t> vertex_bindings(vertex_input_state->vertexBindingDescriptionCount);
1085                 for (uint32_t d = 0; d < vertex_input_state->vertexBindingDescriptionCount; ++d) {
1086                     auto const &vertex_bind_desc = vertex_input_state->pVertexBindingDescriptions[d];
1087                     auto const &binding_it = vertex_bindings.find(vertex_bind_desc.binding);
1088                     if (binding_it != vertex_bindings.cend()) {
1089                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1090                                         "VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616",
1091                                         "vkCreateGraphicsPipelines: parameter "
1092                                         "pCreateInfo[%d].pVertexInputState->pVertexBindingDescription[%d].binding "
1093                                         "(%" PRIu32 ") is not distinct.",
1094                                         i, d, vertex_bind_desc.binding);
1095                     }
1096                     vertex_bindings.insert(vertex_bind_desc.binding);
1097 
1098                     if (vertex_bind_desc.binding >= device_limits.maxVertexInputBindings) {
1099                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1100                                         "VUID-VkVertexInputBindingDescription-binding-00618",
1101                                         "vkCreateGraphicsPipelines: parameter "
1102                                         "pCreateInfos[%u].pVertexInputState->pVertexBindingDescriptions[%u].binding (%u) is "
1103                                         "greater than or equal to VkPhysicalDeviceLimits::maxVertexInputBindings (%u).",
1104                                         i, d, vertex_bind_desc.binding, device_limits.maxVertexInputBindings);
1105                     }
1106 
1107                     if (vertex_bind_desc.stride > device_limits.maxVertexInputBindingStride) {
1108                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1109                                         "VUID-VkVertexInputBindingDescription-stride-00619",
1110                                         "vkCreateGraphicsPipelines: parameter "
1111                                         "pCreateInfos[%u].pVertexInputState->pVertexBindingDescriptions[%u].stride (%u) is greater "
1112                                         "than VkPhysicalDeviceLimits::maxVertexInputBindingStride (%u).",
1113                                         i, d, vertex_bind_desc.stride, device_limits.maxVertexInputBindingStride);
1114                     }
1115                 }
1116 
1117                 std::unordered_set<uint32_t> attribute_locations(vertex_input_state->vertexAttributeDescriptionCount);
1118                 for (uint32_t d = 0; d < vertex_input_state->vertexAttributeDescriptionCount; ++d) {
1119                     auto const &vertex_attrib_desc = vertex_input_state->pVertexAttributeDescriptions[d];
1120                     auto const &location_it = attribute_locations.find(vertex_attrib_desc.location);
1121                     if (location_it != attribute_locations.cend()) {
1122                         skip |= log_msg(
1123                             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1124                             "VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-00617",
1125                             "vkCreateGraphicsPipelines: parameter "
1126                             "pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].location (%u) is not distinct.",
1127                             i, d, vertex_attrib_desc.location);
1128                     }
1129                     attribute_locations.insert(vertex_attrib_desc.location);
1130 
1131                     auto const &binding_it = vertex_bindings.find(vertex_attrib_desc.binding);
1132                     if (binding_it == vertex_bindings.cend()) {
1133                         skip |= log_msg(
1134                             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1135                             "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615",
1136                             "vkCreateGraphicsPipelines: parameter "
1137                             " pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].binding (%u) does not exist "
1138                             "in any pCreateInfo[%d].pVertexInputState->pVertexBindingDescription.",
1139                             i, d, vertex_attrib_desc.binding, i);
1140                     }
1141 
1142                     if (vertex_attrib_desc.location >= device_limits.maxVertexInputAttributes) {
1143                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1144                                         "VUID-VkVertexInputAttributeDescription-location-00620",
1145                                         "vkCreateGraphicsPipelines: parameter "
1146                                         "pCreateInfos[%u].pVertexInputState->pVertexAttributeDescriptions[%u].location (%u) is "
1147                                         "greater than or equal to VkPhysicalDeviceLimits::maxVertexInputAttributes (%u).",
1148                                         i, d, vertex_attrib_desc.location, device_limits.maxVertexInputAttributes);
1149                     }
1150 
1151                     if (vertex_attrib_desc.binding >= device_limits.maxVertexInputBindings) {
1152                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1153                                         "VUID-VkVertexInputAttributeDescription-binding-00621",
1154                                         "vkCreateGraphicsPipelines: parameter "
1155                                         "pCreateInfos[%u].pVertexInputState->pVertexAttributeDescriptions[%u].binding (%u) is "
1156                                         "greater than or equal to VkPhysicalDeviceLimits::maxVertexInputBindings (%u).",
1157                                         i, d, vertex_attrib_desc.binding, device_limits.maxVertexInputBindings);
1158                     }
1159 
1160                     if (vertex_attrib_desc.offset > device_limits.maxVertexInputAttributeOffset) {
1161                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1162                                         "VUID-VkVertexInputAttributeDescription-offset-00622",
1163                                         "vkCreateGraphicsPipelines: parameter "
1164                                         "pCreateInfos[%u].pVertexInputState->pVertexAttributeDescriptions[%u].offset (%u) is "
1165                                         "greater than VkPhysicalDeviceLimits::maxVertexInputAttributeOffset (%u).",
1166                                         i, d, vertex_attrib_desc.offset, device_limits.maxVertexInputAttributeOffset);
1167                     }
1168                 }
1169             }
1170 
1171             if (pCreateInfos[i].pStages != nullptr) {
1172                 bool has_control = false;
1173                 bool has_eval = false;
1174 
1175                 for (uint32_t stage_index = 0; stage_index < pCreateInfos[i].stageCount; ++stage_index) {
1176                     if (pCreateInfos[i].pStages[stage_index].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
1177                         has_control = true;
1178                     } else if (pCreateInfos[i].pStages[stage_index].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
1179                         has_eval = true;
1180                     }
1181                 }
1182 
1183                 // pTessellationState is ignored without both tessellation control and tessellation evaluation shaders stages
1184                 if (has_control && has_eval) {
1185                     if (pCreateInfos[i].pTessellationState == nullptr) {
1186                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1187                                         "VUID-VkGraphicsPipelineCreateInfo-pStages-00731",
1188                                         "vkCreateGraphicsPipelines: if pCreateInfos[%d].pStages includes a tessellation control "
1189                                         "shader stage and a tessellation evaluation shader stage, "
1190                                         "pCreateInfos[%d].pTessellationState must not be NULL.",
1191                                         i, i);
1192                     } else {
1193                         const VkStructureType allowed_type =
1194                             VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
1195                         skip |= validate_struct_pnext(
1196                             "vkCreateGraphicsPipelines",
1197                             ParameterName("pCreateInfos[%i].pTessellationState->pNext", ParameterName::IndexVector{i}),
1198                             "VkPipelineTessellationDomainOriginStateCreateInfo", pCreateInfos[i].pTessellationState->pNext, 1,
1199                             &allowed_type, GeneratedVulkanHeaderVersion, "VUID-VkGraphicsPipelineCreateInfo-pNext-pNext");
1200 
1201                         skip |= validate_reserved_flags(
1202                             "vkCreateGraphicsPipelines",
1203                             ParameterName("pCreateInfos[%i].pTessellationState->flags", ParameterName::IndexVector{i}),
1204                             pCreateInfos[i].pTessellationState->flags,
1205                             "VUID-VkPipelineTessellationStateCreateInfo-flags-zerobitmask");
1206 
1207                         if (pCreateInfos[i].pTessellationState->sType !=
1208                             VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO) {
1209                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1210                                             "VUID-VkPipelineTessellationStateCreateInfo-sType-sType",
1211                                             "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pTessellationState->sType must "
1212                                             "be VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO.",
1213                                             i);
1214                         }
1215 
1216                         if (pCreateInfos[i].pTessellationState->patchControlPoints == 0 ||
1217                             pCreateInfos[i].pTessellationState->patchControlPoints > device_limits.maxTessellationPatchSize) {
1218                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1219                                             "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214",
1220                                             "vkCreateGraphicsPipelines: invalid parameter "
1221                                             "pCreateInfos[%d].pTessellationState->patchControlPoints value %u. patchControlPoints "
1222                                             "should be >0 and <=%u.",
1223                                             i, pCreateInfos[i].pTessellationState->patchControlPoints,
1224                                             device_limits.maxTessellationPatchSize);
1225                         }
1226                     }
1227                 }
1228             }
1229 
1230             // pViewportState, pMultisampleState, pDepthStencilState, and pColorBlendState ignored when rasterization is disabled
1231             if ((pCreateInfos[i].pRasterizationState != nullptr) &&
1232                 (pCreateInfos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
1233                 if (pCreateInfos[i].pViewportState == nullptr) {
1234                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1235                                     VK_NULL_HANDLE, "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00750",
1236                                     "vkCreateGraphicsPipelines: Rasterization is enabled (pCreateInfos[%" PRIu32
1237                                     "].pRasterizationState->rasterizerDiscardEnable is VK_FALSE), but pCreateInfos[%" PRIu32
1238                                     "].pViewportState (=NULL) is not a valid pointer.",
1239                                     i, i);
1240                 } else {
1241                     const auto &viewport_state = *pCreateInfos[i].pViewportState;
1242 
1243                     if (viewport_state.sType != VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO) {
1244                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1245                                         VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-sType-sType",
1246                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1247                                         "].pViewportState->sType is not VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO.",
1248                                         i);
1249                     }
1250 
1251                     const VkStructureType allowed_structs_VkPipelineViewportStateCreateInfo[] = {
1252                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV,
1253                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV,
1254                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV,
1255                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV,
1256                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV,
1257                     };
1258                     skip |= validate_struct_pnext(
1259                         "vkCreateGraphicsPipelines",
1260                         ParameterName("pCreateInfos[%i].pViewportState->pNext", ParameterName::IndexVector{i}),
1261                         "VkPipelineViewportSwizzleStateCreateInfoNV, VkPipelineViewportWScalingStateCreateInfoNV, "
1262                         "VkPipelineViewportExclusiveScissorStateCreateInfoNV, VkPipelineViewportShadingRateImageStateCreateInfoNV, "
1263                         "VkPipelineViewportCoarseSampleOrderStateCreateInfoNV",
1264                         viewport_state.pNext, ARRAY_SIZE(allowed_structs_VkPipelineViewportStateCreateInfo),
1265                         allowed_structs_VkPipelineViewportStateCreateInfo, 65,
1266                         "VUID-VkPipelineViewportStateCreateInfo-pNext-pNext");
1267 
1268                     skip |= validate_reserved_flags(
1269                         "vkCreateGraphicsPipelines",
1270                         ParameterName("pCreateInfos[%i].pViewportState->flags", ParameterName::IndexVector{i}),
1271                         viewport_state.flags, "VUID-VkPipelineViewportStateCreateInfo-flags-zerobitmask");
1272 
1273                     auto exclusive_scissor_struct = lvl_find_in_chain<VkPipelineViewportExclusiveScissorStateCreateInfoNV>(
1274                         pCreateInfos[i].pViewportState->pNext);
1275                     auto shading_rate_image_struct = lvl_find_in_chain<VkPipelineViewportShadingRateImageStateCreateInfoNV>(
1276                         pCreateInfos[i].pViewportState->pNext);
1277                     auto coarse_sample_order_struct = lvl_find_in_chain<VkPipelineViewportCoarseSampleOrderStateCreateInfoNV>(
1278                         pCreateInfos[i].pViewportState->pNext);
1279                     const auto vp_swizzle_struct =
1280                         lvl_find_in_chain<VkPipelineViewportSwizzleStateCreateInfoNV>(pCreateInfos[i].pViewportState->pNext);
1281 
1282                     if (!physical_device_features.multiViewport) {
1283                         if (viewport_state.viewportCount != 1) {
1284                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1285                                             VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1286                                             "vkCreateGraphicsPipelines: The VkPhysicalDeviceFeatures::multiViewport feature is "
1287                                             "disabled, but pCreateInfos[%" PRIu32 "].pViewportState->viewportCount (=%" PRIu32
1288                                             ") is not 1.",
1289                                             i, viewport_state.viewportCount);
1290                         }
1291 
1292                         if (viewport_state.scissorCount != 1) {
1293                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1294                                             VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1295                                             "vkCreateGraphicsPipelines: The VkPhysicalDeviceFeatures::multiViewport feature is "
1296                                             "disabled, but pCreateInfos[%" PRIu32 "].pViewportState->scissorCount (=%" PRIu32
1297                                             ") is not 1.",
1298                                             i, viewport_state.scissorCount);
1299                         }
1300 
1301                         if (exclusive_scissor_struct && (exclusive_scissor_struct->exclusiveScissorCount != 0 &&
1302                                                          exclusive_scissor_struct->exclusiveScissorCount != 1)) {
1303                             skip |=
1304                                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1305                                         VK_NULL_HANDLE,
1306                                         "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02027",
1307                                         "vkCreateGraphicsPipelines: The VkPhysicalDeviceFeatures::multiViewport feature is "
1308                                         "disabled, but pCreateInfos[%" PRIu32
1309                                         "] VkPipelineViewportExclusiveScissorStateCreateInfoNV::exclusiveScissorCount (=%" PRIu32
1310                                         ") is not 1.",
1311                                         i, exclusive_scissor_struct->exclusiveScissorCount);
1312                         }
1313 
1314                         if (shading_rate_image_struct &&
1315                             (shading_rate_image_struct->viewportCount != 0 && shading_rate_image_struct->viewportCount != 1)) {
1316                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1317                                             VK_NULL_HANDLE,
1318                                             "VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-viewportCount-02054",
1319                                             "vkCreateGraphicsPipelines: The VkPhysicalDeviceFeatures::multiViewport feature is "
1320                                             "disabled, but pCreateInfos[%" PRIu32
1321                                             "] VkPipelineViewportShadingRateImageStateCreateInfoNV::viewportCount (=%" PRIu32
1322                                             ") is neither 0 nor 1.",
1323                                             i, shading_rate_image_struct->viewportCount);
1324                         }
1325 
1326                     } else {  // multiViewport enabled
1327                         if (viewport_state.viewportCount == 0) {
1328                             skip |= log_msg(
1329                                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1330                                 VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
1331                                 "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32 "].pViewportState->viewportCount is 0.", i);
1332                         } else if (viewport_state.viewportCount > device_limits.maxViewports) {
1333                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1334                                             VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
1335                                             "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1336                                             "].pViewportState->viewportCount (=%" PRIu32
1337                                             ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
1338                                             i, viewport_state.viewportCount, device_limits.maxViewports);
1339                         }
1340 
1341                         if (viewport_state.scissorCount == 0) {
1342                             skip |= log_msg(
1343                                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1344                                 VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength",
1345                                 "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32 "].pViewportState->scissorCount is 0.", i);
1346                         } else if (viewport_state.scissorCount > device_limits.maxViewports) {
1347                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1348                                             VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219",
1349                                             "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1350                                             "].pViewportState->scissorCount (=%" PRIu32
1351                                             ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
1352                                             i, viewport_state.scissorCount, device_limits.maxViewports);
1353                         }
1354                     }
1355 
1356                     if (exclusive_scissor_struct && exclusive_scissor_struct->exclusiveScissorCount > device_limits.maxViewports) {
1357                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1358                                         VK_NULL_HANDLE,
1359                                         "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02028",
1360                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32 "] exclusiveScissorCount (=%" PRIu32
1361                                         ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
1362                                         i, exclusive_scissor_struct->exclusiveScissorCount, device_limits.maxViewports);
1363                     }
1364 
1365                     if (shading_rate_image_struct && shading_rate_image_struct->viewportCount > device_limits.maxViewports) {
1366                         skip |=
1367                             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1368                                     VK_NULL_HANDLE, "VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-viewportCount-02055",
1369                                     "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1370                                     "] VkPipelineViewportShadingRateImageStateCreateInfoNV viewportCount (=%" PRIu32
1371                                     ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
1372                                     i, shading_rate_image_struct->viewportCount, device_limits.maxViewports);
1373                     }
1374 
1375                     if (viewport_state.scissorCount != viewport_state.viewportCount) {
1376                         skip |=
1377                             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1378                                     VK_NULL_HANDLE, "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220",
1379                                     "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32 "].pViewportState->scissorCount (=%" PRIu32
1380                                     ") is not identical to pCreateInfos[%" PRIu32 "].pViewportState->viewportCount (=%" PRIu32 ").",
1381                                     i, viewport_state.scissorCount, i, viewport_state.viewportCount);
1382                     }
1383 
1384                     if (exclusive_scissor_struct && exclusive_scissor_struct->exclusiveScissorCount != 0 &&
1385                         exclusive_scissor_struct->exclusiveScissorCount != viewport_state.viewportCount) {
1386                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1387                                         VK_NULL_HANDLE,
1388                                         "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02029",
1389                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32 "] exclusiveScissorCount (=%" PRIu32
1390                                         ") must be zero or identical to pCreateInfos[%" PRIu32
1391                                         "].pViewportState->viewportCount (=%" PRIu32 ").",
1392                                         i, exclusive_scissor_struct->exclusiveScissorCount, i, viewport_state.viewportCount);
1393                     }
1394 
1395                     if (shading_rate_image_struct && shading_rate_image_struct->shadingRateImageEnable &&
1396                         shading_rate_image_struct->viewportCount != viewport_state.viewportCount) {
1397                         skip |= log_msg(
1398                             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
1399                             "VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-shadingRateImageEnable-02056",
1400                             "vkCreateGraphicsPipelines: If shadingRateImageEnable is enabled, pCreateInfos[%" PRIu32
1401                             "] "
1402                             "VkPipelineViewportShadingRateImageStateCreateInfoNV viewportCount (=%" PRIu32
1403                             ") must identical to pCreateInfos[%" PRIu32 "].pViewportState->viewportCount (=%" PRIu32 ").",
1404                             i, shading_rate_image_struct->viewportCount, i, viewport_state.viewportCount);
1405                     }
1406 
1407                     if (!has_dynamic_viewport && viewport_state.viewportCount > 0 && viewport_state.pViewports == nullptr) {
1408                         skip |= log_msg(
1409                             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
1410                             "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747",
1411                             "vkCreateGraphicsPipelines: The viewport state is static (pCreateInfos[%" PRIu32
1412                             "].pDynamicState->pDynamicStates does not contain VK_DYNAMIC_STATE_VIEWPORT), but pCreateInfos[%" PRIu32
1413                             "].pViewportState->pViewports (=NULL) is an invalid pointer.",
1414                             i, i);
1415                     }
1416 
1417                     if (!has_dynamic_scissor && viewport_state.scissorCount > 0 && viewport_state.pScissors == nullptr) {
1418                         skip |= log_msg(
1419                             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
1420                             "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748",
1421                             "vkCreateGraphicsPipelines: The scissor state is static (pCreateInfos[%" PRIu32
1422                             "].pDynamicState->pDynamicStates does not contain VK_DYNAMIC_STATE_SCISSOR), but pCreateInfos[%" PRIu32
1423                             "].pViewportState->pScissors (=NULL) is an invalid pointer.",
1424                             i, i);
1425                     }
1426 
1427                     if (!has_dynamic_exclusive_scissor_nv && exclusive_scissor_struct &&
1428                         exclusive_scissor_struct->exclusiveScissorCount > 0 &&
1429                         exclusive_scissor_struct->pExclusiveScissors == nullptr) {
1430                         skip |=
1431                             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1432                                     VK_NULL_HANDLE, "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-pDynamicStates-02030",
1433                                     "vkCreateGraphicsPipelines: The exclusive scissor state is static (pCreateInfos[%" PRIu32
1434                                     "].pDynamicState->pDynamicStates does not contain VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV), but "
1435                                     "pCreateInfos[%" PRIu32 "] pExclusiveScissors (=NULL) is an invalid pointer.",
1436                                     i, i);
1437                     }
1438 
1439                     if (!has_dynamic_shading_rate_palette_nv && shading_rate_image_struct &&
1440                         shading_rate_image_struct->viewportCount > 0 &&
1441                         shading_rate_image_struct->pShadingRatePalettes == nullptr) {
1442                         skip |= log_msg(
1443                             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
1444                             "VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-pDynamicStates-02057",
1445                             "vkCreateGraphicsPipelines: The shading rate palette state is static (pCreateInfos[%" PRIu32
1446                             "].pDynamicState->pDynamicStates does not contain VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV), "
1447                             "but pCreateInfos[%" PRIu32 "] pShadingRatePalettes (=NULL) is an invalid pointer.",
1448                             i, i);
1449                     }
1450 
1451                     if (vp_swizzle_struct) {
1452                         if (vp_swizzle_struct->viewportCount != viewport_state.viewportCount) {
1453                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1454                                             VK_NULL_HANDLE, "VUID-VkPipelineViewportSwizzleStateCreateInfoNV-viewportCount-01215",
1455                                             "vkCreateGraphicsPipelines: The viewport swizzle state vieport count of %" PRIu32
1456                                             " does "
1457                                             "not match the viewport count of %" PRIu32 " in VkPipelineViewportStateCreateInfo.",
1458                                             vp_swizzle_struct->viewportCount, viewport_state.viewportCount);
1459                         }
1460                     }
1461 
1462                     // validate the VkViewports
1463                     if (!has_dynamic_viewport && viewport_state.pViewports) {
1464                         for (uint32_t viewport_i = 0; viewport_i < viewport_state.viewportCount; ++viewport_i) {
1465                             const auto &viewport = viewport_state.pViewports[viewport_i];  // will crash on invalid ptr
1466                             const char *fn_name = "vkCreateGraphicsPipelines";
1467                             skip |= manual_PreCallValidateViewport(viewport, fn_name,
1468                                                                    ParameterName("pCreateInfos[%i].pViewportState->pViewports[%i]",
1469                                                                                  ParameterName::IndexVector{i, viewport_i}),
1470                                                                    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT);
1471                         }
1472                     }
1473 
1474                     if (has_dynamic_viewport_w_scaling_nv && !device_extensions.vk_nv_clip_space_w_scaling) {
1475                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1476                                         VK_NULL_HANDLE, kVUID_PVError_ExtensionNotEnabled,
1477                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1478                                         "].pDynamicState->pDynamicStates contains VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, but "
1479                                         "VK_NV_clip_space_w_scaling extension is not enabled.",
1480                                         i);
1481                     }
1482 
1483                     if (has_dynamic_discard_rectangle_ext && !device_extensions.vk_ext_discard_rectangles) {
1484                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1485                                         VK_NULL_HANDLE, kVUID_PVError_ExtensionNotEnabled,
1486                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1487                                         "].pDynamicState->pDynamicStates contains VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, but "
1488                                         "VK_EXT_discard_rectangles extension is not enabled.",
1489                                         i);
1490                     }
1491 
1492                     if (has_dynamic_sample_locations_ext && !device_extensions.vk_ext_sample_locations) {
1493                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1494                                         VK_NULL_HANDLE, kVUID_PVError_ExtensionNotEnabled,
1495                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1496                                         "].pDynamicState->pDynamicStates contains VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, but "
1497                                         "VK_EXT_sample_locations extension is not enabled.",
1498                                         i);
1499                     }
1500 
1501                     if (has_dynamic_exclusive_scissor_nv && !device_extensions.vk_nv_scissor_exclusive) {
1502                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1503                                         VK_NULL_HANDLE, kVUID_PVError_ExtensionNotEnabled,
1504                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1505                                         "].pDynamicState->pDynamicStates contains VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV, but "
1506                                         "VK_NV_scissor_exclusive extension is not enabled.",
1507                                         i);
1508                     }
1509 
1510                     if (coarse_sample_order_struct &&
1511                         coarse_sample_order_struct->sampleOrderType != VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV &&
1512                         coarse_sample_order_struct->customSampleOrderCount != 0) {
1513                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1514                                         VK_NULL_HANDLE,
1515                                         "VUID-VkPipelineViewportCoarseSampleOrderStateCreateInfoNV-sampleOrderType-02072",
1516                                         "vkCreateGraphicsPipelines: pCreateInfos[%" PRIu32
1517                                         "] "
1518                                         "VkPipelineViewportCoarseSampleOrderStateCreateInfoNV sampleOrderType is not "
1519                                         "VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV and customSampleOrderCount is not 0.",
1520                                         i);
1521                     }
1522 
1523                     if (coarse_sample_order_struct) {
1524                         for (uint32_t order_i = 0; order_i < coarse_sample_order_struct->customSampleOrderCount; ++order_i) {
1525                             skip |= ValidateCoarseSampleOrderCustomNV(&coarse_sample_order_struct->pCustomSampleOrders[order_i]);
1526                         }
1527                     }
1528                 }
1529 
1530                 if (pCreateInfos[i].pMultisampleState == nullptr) {
1531                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1532                                     "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00751",
1533                                     "vkCreateGraphicsPipelines: if pCreateInfos[%d].pRasterizationState->rasterizerDiscardEnable "
1534                                     "is VK_FALSE, pCreateInfos[%d].pMultisampleState must not be NULL.",
1535                                     i, i);
1536                 } else {
1537                     const VkStructureType valid_next_stypes[] = {LvlTypeMap<VkPipelineCoverageModulationStateCreateInfoNV>::kSType,
1538                                                                  LvlTypeMap<VkPipelineCoverageToColorStateCreateInfoNV>::kSType,
1539                                                                  LvlTypeMap<VkPipelineSampleLocationsStateCreateInfoEXT>::kSType};
1540                     const char *valid_struct_names =
1541                         "VkPipelineCoverageModulationStateCreateInfoNV, VkPipelineCoverageToColorStateCreateInfoNV, "
1542                         "VkPipelineSampleLocationsStateCreateInfoEXT";
1543                     skip |= validate_struct_pnext(
1544                         "vkCreateGraphicsPipelines",
1545                         ParameterName("pCreateInfos[%i].pMultisampleState->pNext", ParameterName::IndexVector{i}),
1546                         valid_struct_names, pCreateInfos[i].pMultisampleState->pNext, 3, valid_next_stypes,
1547                         GeneratedVulkanHeaderVersion, "VUID-VkPipelineMultisampleStateCreateInfo-pNext-pNext");
1548 
1549                     skip |= validate_reserved_flags(
1550                         "vkCreateGraphicsPipelines",
1551                         ParameterName("pCreateInfos[%i].pMultisampleState->flags", ParameterName::IndexVector{i}),
1552                         pCreateInfos[i].pMultisampleState->flags, "VUID-VkPipelineMultisampleStateCreateInfo-flags-zerobitmask");
1553 
1554                     skip |= validate_bool32(
1555                         "vkCreateGraphicsPipelines",
1556                         ParameterName("pCreateInfos[%i].pMultisampleState->sampleShadingEnable", ParameterName::IndexVector{i}),
1557                         pCreateInfos[i].pMultisampleState->sampleShadingEnable);
1558 
1559                     skip |= validate_array(
1560                         "vkCreateGraphicsPipelines",
1561                         ParameterName("pCreateInfos[%i].pMultisampleState->rasterizationSamples", ParameterName::IndexVector{i}),
1562                         ParameterName("pCreateInfos[%i].pMultisampleState->pSampleMask", ParameterName::IndexVector{i}),
1563                         pCreateInfos[i].pMultisampleState->rasterizationSamples, &pCreateInfos[i].pMultisampleState->pSampleMask,
1564                         true, false, kVUIDUndefined, kVUIDUndefined);
1565 
1566                     skip |= validate_flags(
1567                         "vkCreateGraphicsPipelines",
1568                         ParameterName("pCreateInfos[%i].pMultisampleState->rasterizationSamples", ParameterName::IndexVector{i}),
1569                         "VkSampleCountFlagBits", AllVkSampleCountFlagBits, pCreateInfos[i].pMultisampleState->rasterizationSamples,
1570                         kRequiredSingleBit, "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-parameter");
1571 
1572                     skip |= validate_bool32(
1573                         "vkCreateGraphicsPipelines",
1574                         ParameterName("pCreateInfos[%i].pMultisampleState->alphaToCoverageEnable", ParameterName::IndexVector{i}),
1575                         pCreateInfos[i].pMultisampleState->alphaToCoverageEnable);
1576 
1577                     skip |= validate_bool32(
1578                         "vkCreateGraphicsPipelines",
1579                         ParameterName("pCreateInfos[%i].pMultisampleState->alphaToOneEnable", ParameterName::IndexVector{i}),
1580                         pCreateInfos[i].pMultisampleState->alphaToOneEnable);
1581 
1582                     if (pCreateInfos[i].pMultisampleState->sType != VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO) {
1583                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1584                                         kVUID_PVError_InvalidStructSType,
1585                                         "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pMultisampleState->sType must be "
1586                                         "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO",
1587                                         i);
1588                     }
1589                     if (pCreateInfos[i].pMultisampleState->sampleShadingEnable == VK_TRUE) {
1590                         if (!physical_device_features.sampleRateShading) {
1591                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1592                                             "VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784",
1593                                             "vkCreateGraphicsPipelines(): parameter "
1594                                             "pCreateInfos[%d].pMultisampleState->sampleShadingEnable.",
1595                                             i);
1596                         }
1597                         // TODO Add documentation issue about when minSampleShading must be in range and when it is ignored
1598                         // For now a "least noise" test *only* when sampleShadingEnable is VK_TRUE.
1599                         if (!in_inclusive_range(pCreateInfos[i].pMultisampleState->minSampleShading, 0.F, 1.0F)) {
1600                             skip |= log_msg(
1601                                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1602                                 "VUID-VkPipelineMultisampleStateCreateInfo-minSampleShading-00786",
1603                                 "vkCreateGraphicsPipelines(): parameter pCreateInfos[%d].pMultisampleState->minSampleShading.", i);
1604                         }
1605                     }
1606 
1607                     const auto *line_state = lvl_find_in_chain<VkPipelineRasterizationLineStateCreateInfoEXT>(
1608                         pCreateInfos[i].pRasterizationState->pNext);
1609 
1610                     if (line_state) {
1611                         if ((line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT ||
1612                              line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT)) {
1613                             if (pCreateInfos[i].pMultisampleState->alphaToCoverageEnable) {
1614                                 skip |=
1615                                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1616                                             "VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766",
1617                                             "vkCreateGraphicsPipelines(): Bresenham/Smooth line rasterization not supported with "
1618                                             "pCreateInfos[%d].pMultisampleState->alphaToCoverageEnable == VK_TRUE.",
1619                                             i);
1620                             }
1621                             if (pCreateInfos[i].pMultisampleState->alphaToOneEnable) {
1622                                 skip |=
1623                                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1624                                             "VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766",
1625                                             "vkCreateGraphicsPipelines(): Bresenham/Smooth line rasterization not supported with "
1626                                             "pCreateInfos[%d].pMultisampleState->alphaToOneEnable == VK_TRUE.",
1627                                             i);
1628                             }
1629                             if (pCreateInfos[i].pMultisampleState->sampleShadingEnable) {
1630                                 skip |=
1631                                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1632                                             "VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766",
1633                                             "vkCreateGraphicsPipelines(): Bresenham/Smooth line rasterization not supported with "
1634                                             "pCreateInfos[%d].pMultisampleState->sampleShadingEnable == VK_TRUE.",
1635                                             i);
1636                             }
1637                         }
1638                         if (line_state->stippledLineEnable && !has_dynamic_line_stipple) {
1639                             if (line_state->lineStippleFactor < 1 || line_state->lineStippleFactor > 256) {
1640                                 skip |=
1641                                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1642                                             "VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
1643                                             "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineStippleFactor = %d must be in the "
1644                                             "range [1,256].",
1645                                             i, line_state->lineStippleFactor);
1646                             }
1647                         }
1648                         const auto *line_features =
1649                             lvl_find_in_chain<VkPhysicalDeviceLineRasterizationFeaturesEXT>(physical_device_features2.pNext);
1650                         if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT &&
1651                             (!line_features || !line_features->rectangularLines)) {
1652                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1653                                             "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768",
1654                                             "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1655                                             "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT requires the rectangularLines feature.",
1656                                             i);
1657                         }
1658                         if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT &&
1659                             (!line_features || !line_features->bresenhamLines)) {
1660                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1661                                             "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769",
1662                                             "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1663                                             "VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT requires the bresenhamLines feature.",
1664                                             i);
1665                         }
1666                         if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT &&
1667                             (!line_features || !line_features->smoothLines)) {
1668                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1669                                             "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770",
1670                                             "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1671                                             "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT requires the smoothLines feature.",
1672                                             i);
1673                         }
1674                         if (line_state->stippledLineEnable) {
1675                             if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT &&
1676                                 (!line_features || !line_features->stippledRectangularLines)) {
1677                                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
1678                                                 0, "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771",
1679                                                 "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1680                                                 "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT with stipple requires the "
1681                                                 "stippledRectangularLines feature.",
1682                                                 i);
1683                             }
1684                             if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT &&
1685                                 (!line_features || !line_features->stippledBresenhamLines)) {
1686                                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
1687                                                 0, "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772",
1688                                                 "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1689                                                 "VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT with stipple requires the "
1690                                                 "stippledBresenhamLines feature.",
1691                                                 i);
1692                             }
1693                             if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT &&
1694                                 (!line_features || !line_features->stippledSmoothLines)) {
1695                                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
1696                                                 0, "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773",
1697                                                 "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1698                                                 "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT with stipple requires the "
1699                                                 "stippledSmoothLines feature.",
1700                                                 i);
1701                             }
1702                             if (line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT &&
1703                                 (!line_features || !line_features->stippledSmoothLines || !device_limits.strictLines)) {
1704                                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
1705                                                 0, "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774",
1706                                                 "vkCreateGraphicsPipelines(): pCreateInfos[%d] lineRasterizationMode = "
1707                                                 "VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT with stipple requires the "
1708                                                 "stippledRectangularLines and strictLines features.",
1709                                                 i);
1710                             }
1711                         }
1712                     }
1713                 }
1714 
1715                 bool uses_color_attachment = false;
1716                 bool uses_depthstencil_attachment = false;
1717                 {
1718                     std::unique_lock<std::mutex> lock(renderpass_map_mutex);
1719                     const auto subpasses_uses_it = renderpasses_states.find(pCreateInfos[i].renderPass);
1720                     if (subpasses_uses_it != renderpasses_states.end()) {
1721                         const auto &subpasses_uses = subpasses_uses_it->second;
1722                         if (subpasses_uses.subpasses_using_color_attachment.count(pCreateInfos[i].subpass))
1723                             uses_color_attachment = true;
1724                         if (subpasses_uses.subpasses_using_depthstencil_attachment.count(pCreateInfos[i].subpass))
1725                             uses_depthstencil_attachment = true;
1726                     }
1727                     lock.unlock();
1728                 }
1729 
1730                 if (pCreateInfos[i].pDepthStencilState != nullptr && uses_depthstencil_attachment) {
1731                     skip |= validate_struct_pnext(
1732                         "vkCreateGraphicsPipelines",
1733                         ParameterName("pCreateInfos[%i].pDepthStencilState->pNext", ParameterName::IndexVector{i}), NULL,
1734                         pCreateInfos[i].pDepthStencilState->pNext, 0, NULL, GeneratedVulkanHeaderVersion,
1735                         "VUID-VkPipelineDepthStencilStateCreateInfo-pNext-pNext");
1736 
1737                     skip |= validate_reserved_flags(
1738                         "vkCreateGraphicsPipelines",
1739                         ParameterName("pCreateInfos[%i].pDepthStencilState->flags", ParameterName::IndexVector{i}),
1740                         pCreateInfos[i].pDepthStencilState->flags, "VUID-VkPipelineDepthStencilStateCreateInfo-flags-zerobitmask");
1741 
1742                     skip |= validate_bool32(
1743                         "vkCreateGraphicsPipelines",
1744                         ParameterName("pCreateInfos[%i].pDepthStencilState->depthTestEnable", ParameterName::IndexVector{i}),
1745                         pCreateInfos[i].pDepthStencilState->depthTestEnable);
1746 
1747                     skip |= validate_bool32(
1748                         "vkCreateGraphicsPipelines",
1749                         ParameterName("pCreateInfos[%i].pDepthStencilState->depthWriteEnable", ParameterName::IndexVector{i}),
1750                         pCreateInfos[i].pDepthStencilState->depthWriteEnable);
1751 
1752                     skip |= validate_ranged_enum(
1753                         "vkCreateGraphicsPipelines",
1754                         ParameterName("pCreateInfos[%i].pDepthStencilState->depthCompareOp", ParameterName::IndexVector{i}),
1755                         "VkCompareOp", AllVkCompareOpEnums, pCreateInfos[i].pDepthStencilState->depthCompareOp,
1756                         "VUID-VkPipelineDepthStencilStateCreateInfo-depthCompareOp-parameter");
1757 
1758                     skip |= validate_bool32(
1759                         "vkCreateGraphicsPipelines",
1760                         ParameterName("pCreateInfos[%i].pDepthStencilState->depthBoundsTestEnable", ParameterName::IndexVector{i}),
1761                         pCreateInfos[i].pDepthStencilState->depthBoundsTestEnable);
1762 
1763                     skip |= validate_bool32(
1764                         "vkCreateGraphicsPipelines",
1765                         ParameterName("pCreateInfos[%i].pDepthStencilState->stencilTestEnable", ParameterName::IndexVector{i}),
1766                         pCreateInfos[i].pDepthStencilState->stencilTestEnable);
1767 
1768                     skip |= validate_ranged_enum(
1769                         "vkCreateGraphicsPipelines",
1770                         ParameterName("pCreateInfos[%i].pDepthStencilState->front.failOp", ParameterName::IndexVector{i}),
1771                         "VkStencilOp", AllVkStencilOpEnums, pCreateInfos[i].pDepthStencilState->front.failOp,
1772                         "VUID-VkStencilOpState-failOp-parameter");
1773 
1774                     skip |= validate_ranged_enum(
1775                         "vkCreateGraphicsPipelines",
1776                         ParameterName("pCreateInfos[%i].pDepthStencilState->front.passOp", ParameterName::IndexVector{i}),
1777                         "VkStencilOp", AllVkStencilOpEnums, pCreateInfos[i].pDepthStencilState->front.passOp,
1778                         "VUID-VkStencilOpState-passOp-parameter");
1779 
1780                     skip |= validate_ranged_enum(
1781                         "vkCreateGraphicsPipelines",
1782                         ParameterName("pCreateInfos[%i].pDepthStencilState->front.depthFailOp", ParameterName::IndexVector{i}),
1783                         "VkStencilOp", AllVkStencilOpEnums, pCreateInfos[i].pDepthStencilState->front.depthFailOp,
1784                         "VUID-VkStencilOpState-depthFailOp-parameter");
1785 
1786                     skip |= validate_ranged_enum(
1787                         "vkCreateGraphicsPipelines",
1788                         ParameterName("pCreateInfos[%i].pDepthStencilState->front.compareOp", ParameterName::IndexVector{i}),
1789                         "VkCompareOp", AllVkCompareOpEnums, pCreateInfos[i].pDepthStencilState->front.compareOp,
1790                         "VUID-VkPipelineDepthStencilStateCreateInfo-depthCompareOp-parameter");
1791 
1792                     skip |= validate_ranged_enum(
1793                         "vkCreateGraphicsPipelines",
1794                         ParameterName("pCreateInfos[%i].pDepthStencilState->back.failOp", ParameterName::IndexVector{i}),
1795                         "VkStencilOp", AllVkStencilOpEnums, pCreateInfos[i].pDepthStencilState->back.failOp,
1796                         "VUID-VkStencilOpState-failOp-parameter");
1797 
1798                     skip |= validate_ranged_enum(
1799                         "vkCreateGraphicsPipelines",
1800                         ParameterName("pCreateInfos[%i].pDepthStencilState->back.passOp", ParameterName::IndexVector{i}),
1801                         "VkStencilOp", AllVkStencilOpEnums, pCreateInfos[i].pDepthStencilState->back.passOp,
1802                         "VUID-VkStencilOpState-passOp-parameter");
1803 
1804                     skip |= validate_ranged_enum(
1805                         "vkCreateGraphicsPipelines",
1806                         ParameterName("pCreateInfos[%i].pDepthStencilState->back.depthFailOp", ParameterName::IndexVector{i}),
1807                         "VkStencilOp", AllVkStencilOpEnums, pCreateInfos[i].pDepthStencilState->back.depthFailOp,
1808                         "VUID-VkStencilOpState-depthFailOp-parameter");
1809 
1810                     skip |= validate_ranged_enum(
1811                         "vkCreateGraphicsPipelines",
1812                         ParameterName("pCreateInfos[%i].pDepthStencilState->back.compareOp", ParameterName::IndexVector{i}),
1813                         "VkCompareOp", AllVkCompareOpEnums, pCreateInfos[i].pDepthStencilState->back.compareOp,
1814                         "VUID-VkPipelineDepthStencilStateCreateInfo-depthCompareOp-parameter");
1815 
1816                     if (pCreateInfos[i].pDepthStencilState->sType != VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) {
1817                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1818                                         kVUID_PVError_InvalidStructSType,
1819                                         "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pDepthStencilState->sType must be "
1820                                         "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO",
1821                                         i);
1822                     }
1823                 }
1824 
1825                 const VkStructureType allowed_structs_VkPipelineColorBlendStateCreateInfo[] = {
1826                     VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT};
1827 
1828                 if (pCreateInfos[i].pColorBlendState != nullptr && uses_color_attachment) {
1829                     skip |= validate_struct_type("vkCreateGraphicsPipelines",
1830                                                  ParameterName("pCreateInfos[%i].pColorBlendState", ParameterName::IndexVector{i}),
1831                                                  "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO",
1832                                                  pCreateInfos[i].pColorBlendState,
1833                                                  VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, false, kVUIDUndefined,
1834                                                  "VUID-VkPipelineColorBlendStateCreateInfo-sType-sType");
1835 
1836                     skip |= validate_struct_pnext(
1837                         "vkCreateGraphicsPipelines",
1838                         ParameterName("pCreateInfos[%i].pColorBlendState->pNext", ParameterName::IndexVector{i}),
1839                         "VkPipelineColorBlendAdvancedStateCreateInfoEXT", pCreateInfos[i].pColorBlendState->pNext,
1840                         ARRAY_SIZE(allowed_structs_VkPipelineColorBlendStateCreateInfo),
1841                         allowed_structs_VkPipelineColorBlendStateCreateInfo, GeneratedVulkanHeaderVersion,
1842                         "VUID-VkPipelineColorBlendStateCreateInfo-pNext-pNext");
1843 
1844                     skip |= validate_reserved_flags(
1845                         "vkCreateGraphicsPipelines",
1846                         ParameterName("pCreateInfos[%i].pColorBlendState->flags", ParameterName::IndexVector{i}),
1847                         pCreateInfos[i].pColorBlendState->flags, "VUID-VkPipelineColorBlendStateCreateInfo-flags-zerobitmask");
1848 
1849                     skip |= validate_bool32(
1850                         "vkCreateGraphicsPipelines",
1851                         ParameterName("pCreateInfos[%i].pColorBlendState->logicOpEnable", ParameterName::IndexVector{i}),
1852                         pCreateInfos[i].pColorBlendState->logicOpEnable);
1853 
1854                     skip |= validate_array(
1855                         "vkCreateGraphicsPipelines",
1856                         ParameterName("pCreateInfos[%i].pColorBlendState->attachmentCount", ParameterName::IndexVector{i}),
1857                         ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments", ParameterName::IndexVector{i}),
1858                         pCreateInfos[i].pColorBlendState->attachmentCount, &pCreateInfos[i].pColorBlendState->pAttachments, false,
1859                         true, kVUIDUndefined, kVUIDUndefined);
1860 
1861                     if (pCreateInfos[i].pColorBlendState->pAttachments != NULL) {
1862                         for (uint32_t attachmentIndex = 0; attachmentIndex < pCreateInfos[i].pColorBlendState->attachmentCount;
1863                              ++attachmentIndex) {
1864                             skip |= validate_bool32("vkCreateGraphicsPipelines",
1865                                                     ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].blendEnable",
1866                                                                   ParameterName::IndexVector{i, attachmentIndex}),
1867                                                     pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].blendEnable);
1868 
1869                             skip |= validate_ranged_enum(
1870                                 "vkCreateGraphicsPipelines",
1871                                 ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].srcColorBlendFactor",
1872                                               ParameterName::IndexVector{i, attachmentIndex}),
1873                                 "VkBlendFactor", AllVkBlendFactorEnums,
1874                                 pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].srcColorBlendFactor,
1875                                 "VUID-VkPipelineColorBlendAttachmentState-srcColorBlendFactor-parameter");
1876 
1877                             skip |= validate_ranged_enum(
1878                                 "vkCreateGraphicsPipelines",
1879                                 ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].dstColorBlendFactor",
1880                                               ParameterName::IndexVector{i, attachmentIndex}),
1881                                 "VkBlendFactor", AllVkBlendFactorEnums,
1882                                 pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].dstColorBlendFactor,
1883                                 "VUID-VkPipelineColorBlendAttachmentState-dstColorBlendFactor-parameter");
1884 
1885                             skip |= validate_ranged_enum(
1886                                 "vkCreateGraphicsPipelines",
1887                                 ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].colorBlendOp",
1888                                               ParameterName::IndexVector{i, attachmentIndex}),
1889                                 "VkBlendOp", AllVkBlendOpEnums,
1890                                 pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].colorBlendOp,
1891                                 "VUID-VkPipelineColorBlendAttachmentState-colorBlendOp-parameter");
1892 
1893                             skip |= validate_ranged_enum(
1894                                 "vkCreateGraphicsPipelines",
1895                                 ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].srcAlphaBlendFactor",
1896                                               ParameterName::IndexVector{i, attachmentIndex}),
1897                                 "VkBlendFactor", AllVkBlendFactorEnums,
1898                                 pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].srcAlphaBlendFactor,
1899                                 "VUID-VkPipelineColorBlendAttachmentState-srcAlphaBlendFactor-parameter");
1900 
1901                             skip |= validate_ranged_enum(
1902                                 "vkCreateGraphicsPipelines",
1903                                 ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].dstAlphaBlendFactor",
1904                                               ParameterName::IndexVector{i, attachmentIndex}),
1905                                 "VkBlendFactor", AllVkBlendFactorEnums,
1906                                 pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].dstAlphaBlendFactor,
1907                                 "VUID-VkPipelineColorBlendAttachmentState-dstAlphaBlendFactor-parameter");
1908 
1909                             skip |= validate_ranged_enum(
1910                                 "vkCreateGraphicsPipelines",
1911                                 ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].alphaBlendOp",
1912                                               ParameterName::IndexVector{i, attachmentIndex}),
1913                                 "VkBlendOp", AllVkBlendOpEnums,
1914                                 pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].alphaBlendOp,
1915                                 "VUID-VkPipelineColorBlendAttachmentState-alphaBlendOp-parameter");
1916 
1917                             skip |=
1918                                 validate_flags("vkCreateGraphicsPipelines",
1919                                                ParameterName("pCreateInfos[%i].pColorBlendState->pAttachments[%i].colorWriteMask",
1920                                                              ParameterName::IndexVector{i, attachmentIndex}),
1921                                                "VkColorComponentFlagBits", AllVkColorComponentFlagBits,
1922                                                pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].colorWriteMask,
1923                                                kOptionalFlags, "VUID-VkPipelineColorBlendAttachmentState-colorWriteMask-parameter");
1924                         }
1925                     }
1926 
1927                     if (pCreateInfos[i].pColorBlendState->sType != VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO) {
1928                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1929                                         kVUID_PVError_InvalidStructSType,
1930                                         "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pColorBlendState->sType must be "
1931                                         "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO",
1932                                         i);
1933                     }
1934 
1935                     // If logicOpEnable is VK_TRUE, logicOp must be a valid VkLogicOp value
1936                     if (pCreateInfos[i].pColorBlendState->logicOpEnable == VK_TRUE) {
1937                         skip |= validate_ranged_enum(
1938                             "vkCreateGraphicsPipelines",
1939                             ParameterName("pCreateInfos[%i].pColorBlendState->logicOp", ParameterName::IndexVector{i}), "VkLogicOp",
1940                             AllVkLogicOpEnums, pCreateInfos[i].pColorBlendState->logicOp,
1941                             "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607");
1942                     }
1943                 }
1944             }
1945 
1946             if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) {
1947                 if (pCreateInfos[i].basePipelineIndex != -1) {
1948                     if (pCreateInfos[i].basePipelineHandle != VK_NULL_HANDLE) {
1949                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1950                                         "VUID-VkGraphicsPipelineCreateInfo-flags-00724",
1951                                         "vkCreateGraphicsPipelines parameter, pCreateInfos->basePipelineHandle, must be "
1952                                         "VK_NULL_HANDLE if pCreateInfos->flags contains the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag "
1953                                         "and pCreateInfos->basePipelineIndex is not -1.");
1954                     }
1955                 }
1956 
1957                 if (pCreateInfos[i].basePipelineHandle != VK_NULL_HANDLE) {
1958                     if (pCreateInfos[i].basePipelineIndex != -1) {
1959                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1960                                         "VUID-VkGraphicsPipelineCreateInfo-flags-00725",
1961                                         "vkCreateGraphicsPipelines parameter, pCreateInfos->basePipelineIndex, must be -1 if "
1962                                         "pCreateInfos->flags contains the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag and "
1963                                         "pCreateInfos->basePipelineHandle is not VK_NULL_HANDLE.");
1964                     }
1965                 }
1966             }
1967 
1968             if (pCreateInfos[i].pRasterizationState) {
1969                 if (!device_extensions.vk_nv_fill_rectangle) {
1970                     if (pCreateInfos[i].pRasterizationState->polygonMode == VK_POLYGON_MODE_FILL_RECTANGLE_NV) {
1971                         skip |=
1972                             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1973                                     "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01414",
1974                                     "vkCreateGraphicsPipelines parameter, VkPolygonMode "
1975                                     "pCreateInfos->pRasterizationState->polygonMode cannot be VK_POLYGON_MODE_FILL_RECTANGLE_NV "
1976                                     "if the extension VK_NV_fill_rectangle is not enabled.");
1977                     } else if ((pCreateInfos[i].pRasterizationState->polygonMode != VK_POLYGON_MODE_FILL) &&
1978                                (physical_device_features.fillModeNonSolid == false)) {
1979                         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1980                                         kVUID_PVError_DeviceFeature,
1981                                         "vkCreateGraphicsPipelines parameter, VkPolygonMode "
1982                                         "pCreateInfos->pRasterizationState->polygonMode cannot be VK_POLYGON_MODE_POINT or "
1983                                         "VK_POLYGON_MODE_LINE if VkPhysicalDeviceFeatures->fillModeNonSolid is false.");
1984                     }
1985                 } else {
1986                     if ((pCreateInfos[i].pRasterizationState->polygonMode != VK_POLYGON_MODE_FILL) &&
1987                         (pCreateInfos[i].pRasterizationState->polygonMode != VK_POLYGON_MODE_FILL_RECTANGLE_NV) &&
1988                         (physical_device_features.fillModeNonSolid == false)) {
1989                         skip |=
1990                             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1991                                     "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507",
1992                                     "vkCreateGraphicsPipelines parameter, VkPolygonMode "
1993                                     "pCreateInfos->pRasterizationState->polygonMode must be VK_POLYGON_MODE_FILL or "
1994                                     "VK_POLYGON_MODE_FILL_RECTANGLE_NV if VkPhysicalDeviceFeatures->fillModeNonSolid is false.");
1995                     }
1996                 }
1997 
1998                 if (!has_dynamic_line_width && !physical_device_features.wideLines &&
1999                     (pCreateInfos[i].pRasterizationState->lineWidth != 1.0f)) {
2000                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 0,
2001                                     "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749",
2002                                     "The line width state is static (pCreateInfos[%" PRIu32
2003                                     "].pDynamicState->pDynamicStates does not contain VK_DYNAMIC_STATE_LINE_WIDTH) and "
2004                                     "VkPhysicalDeviceFeatures::wideLines is disabled, but pCreateInfos[%" PRIu32
2005                                     "].pRasterizationState->lineWidth (=%f) is not 1.0.",
2006                                     i, i, pCreateInfos[i].pRasterizationState->lineWidth);
2007                 }
2008             }
2009 
2010             for (size_t j = 0; j < pCreateInfos[i].stageCount; j++) {
2011                 skip |= validate_string("vkCreateGraphicsPipelines",
2012                                         ParameterName("pCreateInfos[%i].pStages[%i].pName", ParameterName::IndexVector{i, j}),
2013                                         "VUID-VkGraphicsPipelineCreateInfo-pStages-parameter", pCreateInfos[i].pStages[j].pName);
2014             }
2015         }
2016     }
2017 
2018     return skip;
2019 }
2020 
manual_PreCallValidateCreateComputePipelines(VkDevice device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkComputePipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)2021 bool StatelessValidation::manual_PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache,
2022                                                                        uint32_t createInfoCount,
2023                                                                        const VkComputePipelineCreateInfo *pCreateInfos,
2024                                                                        const VkAllocationCallbacks *pAllocator,
2025                                                                        VkPipeline *pPipelines) {
2026     bool skip = false;
2027     for (uint32_t i = 0; i < createInfoCount; i++) {
2028         skip |= validate_string("vkCreateComputePipelines",
2029                                 ParameterName("pCreateInfos[%i].stage.pName", ParameterName::IndexVector{i}),
2030                                 "VUID-VkPipelineShaderStageCreateInfo-pName-parameter", pCreateInfos[i].stage.pName);
2031         auto feedback_struct = lvl_find_in_chain<VkPipelineCreationFeedbackCreateInfoEXT>(pCreateInfos[i].pNext);
2032         if ((feedback_struct != nullptr) && (feedback_struct->pipelineStageCreationFeedbackCount != 1)) {
2033             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
2034                             "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02669",
2035                             "vkCreateComputePipelines(): in pCreateInfo[%" PRIu32
2036                             "], VkPipelineCreationFeedbackEXT::pipelineStageCreationFeedbackCount must equal 1, found %" PRIu32 ".",
2037                             i, feedback_struct->pipelineStageCreationFeedbackCount);
2038         }
2039     }
2040     return skip;
2041 }
2042 
manual_PreCallValidateCreateSampler(VkDevice device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * pSampler)2043 bool StatelessValidation::manual_PreCallValidateCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
2044                                                               const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
2045     bool skip = false;
2046 
2047     if (pCreateInfo != nullptr) {
2048         const auto &features = physical_device_features;
2049         const auto &limits = device_limits;
2050 
2051         if (pCreateInfo->anisotropyEnable == VK_TRUE) {
2052             if (!in_inclusive_range(pCreateInfo->maxAnisotropy, 1.0F, limits.maxSamplerAnisotropy)) {
2053                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2054                                 "VUID-VkSamplerCreateInfo-anisotropyEnable-01071",
2055                                 "vkCreateSampler(): value of %s must be in range [1.0, %f] %s, but %f found.",
2056                                 "pCreateInfo->maxAnisotropy", limits.maxSamplerAnisotropy,
2057                                 "VkPhysicalDeviceLimits::maxSamplerAnistropy", pCreateInfo->maxAnisotropy);
2058             }
2059 
2060             // Anistropy cannot be enabled in sampler unless enabled as a feature
2061             if (features.samplerAnisotropy == VK_FALSE) {
2062                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2063                                 "VUID-VkSamplerCreateInfo-anisotropyEnable-01070",
2064                                 "vkCreateSampler(): Anisotropic sampling feature is not enabled, %s must be VK_FALSE.",
2065                                 "pCreateInfo->anisotropyEnable");
2066             }
2067         }
2068 
2069         if (pCreateInfo->unnormalizedCoordinates == VK_TRUE) {
2070             if (pCreateInfo->minFilter != pCreateInfo->magFilter) {
2071                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2072                                 "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072",
2073                                 "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
2074                                 "pCreateInfo->minFilter (%s) and pCreateInfo->magFilter (%s) must be equal.",
2075                                 string_VkFilter(pCreateInfo->minFilter), string_VkFilter(pCreateInfo->magFilter));
2076             }
2077             if (pCreateInfo->mipmapMode != VK_SAMPLER_MIPMAP_MODE_NEAREST) {
2078                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2079                                 "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073",
2080                                 "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
2081                                 "pCreateInfo->mipmapMode (%s) must be VK_SAMPLER_MIPMAP_MODE_NEAREST.",
2082                                 string_VkSamplerMipmapMode(pCreateInfo->mipmapMode));
2083             }
2084             if (pCreateInfo->minLod != 0.0f || pCreateInfo->maxLod != 0.0f) {
2085                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2086                                 "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074",
2087                                 "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
2088                                 "pCreateInfo->minLod (%f) and pCreateInfo->maxLod (%f) must both be zero.",
2089                                 pCreateInfo->minLod, pCreateInfo->maxLod);
2090             }
2091             if ((pCreateInfo->addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE &&
2092                  pCreateInfo->addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
2093                 (pCreateInfo->addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE &&
2094                  pCreateInfo->addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
2095                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2096                                 "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075",
2097                                 "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
2098                                 "pCreateInfo->addressModeU (%s) and pCreateInfo->addressModeV (%s) must both be "
2099                                 "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE or VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER.",
2100                                 string_VkSamplerAddressMode(pCreateInfo->addressModeU),
2101                                 string_VkSamplerAddressMode(pCreateInfo->addressModeV));
2102             }
2103             if (pCreateInfo->anisotropyEnable == VK_TRUE) {
2104                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2105                                 "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076",
2106                                 "vkCreateSampler(): pCreateInfo->anisotropyEnable and pCreateInfo->unnormalizedCoordinates must "
2107                                 "not both be VK_TRUE.");
2108             }
2109             if (pCreateInfo->compareEnable == VK_TRUE) {
2110                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2111                                 "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077",
2112                                 "vkCreateSampler(): pCreateInfo->compareEnable and pCreateInfo->unnormalizedCoordinates must "
2113                                 "not both be VK_TRUE.");
2114             }
2115         }
2116 
2117         // If compareEnable is VK_TRUE, compareOp must be a valid VkCompareOp value
2118         if (pCreateInfo->compareEnable == VK_TRUE) {
2119             skip |= validate_ranged_enum("vkCreateSampler", "pCreateInfo->compareOp", "VkCompareOp", AllVkCompareOpEnums,
2120                                          pCreateInfo->compareOp, "VUID-VkSamplerCreateInfo-compareEnable-01080");
2121         }
2122 
2123         // If any of addressModeU, addressModeV or addressModeW are VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, borderColor must be a
2124         // valid VkBorderColor value
2125         if ((pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
2126             (pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
2127             (pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
2128             skip |= validate_ranged_enum("vkCreateSampler", "pCreateInfo->borderColor", "VkBorderColor", AllVkBorderColorEnums,
2129                                          pCreateInfo->borderColor, "VUID-VkSamplerCreateInfo-addressModeU-01078");
2130         }
2131 
2132         // If any of addressModeU, addressModeV or addressModeW are VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, the
2133         // VK_KHR_sampler_mirror_clamp_to_edge extension must be enabled
2134         if (!device_extensions.vk_khr_sampler_mirror_clamp_to_edge &&
2135             ((pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE) ||
2136              (pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE) ||
2137              (pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE))) {
2138             skip |=
2139                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2140                         "VUID-VkSamplerCreateInfo-addressModeU-01079",
2141                         "vkCreateSampler(): A VkSamplerAddressMode value is set to VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE "
2142                         "but the VK_KHR_sampler_mirror_clamp_to_edge extension has not been enabled.");
2143         }
2144 
2145         // Checks for the IMG cubic filtering extension
2146         if (device_extensions.vk_img_filter_cubic) {
2147             if ((pCreateInfo->anisotropyEnable == VK_TRUE) &&
2148                 ((pCreateInfo->minFilter == VK_FILTER_CUBIC_IMG) || (pCreateInfo->magFilter == VK_FILTER_CUBIC_IMG))) {
2149                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2150                                 "VUID-VkSamplerCreateInfo-magFilter-01081",
2151                                 "vkCreateSampler(): Anisotropic sampling must not be VK_TRUE when either minFilter or magFilter "
2152                                 "are VK_FILTER_CUBIC_IMG.");
2153             }
2154         }
2155     }
2156 
2157     return skip;
2158 }
2159 
manual_PreCallValidateCreateDescriptorSetLayout(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout)2160 bool StatelessValidation::manual_PreCallValidateCreateDescriptorSetLayout(VkDevice device,
2161                                                                           const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
2162                                                                           const VkAllocationCallbacks *pAllocator,
2163                                                                           VkDescriptorSetLayout *pSetLayout) {
2164     bool skip = false;
2165 
2166     // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
2167     if ((pCreateInfo != nullptr) && (pCreateInfo->pBindings != nullptr)) {
2168         for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i) {
2169             if (pCreateInfo->pBindings[i].descriptorCount != 0) {
2170                 // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and descriptorCount
2171                 // is not 0 and pImmutableSamplers is not NULL, pImmutableSamplers must be a pointer to an array of descriptorCount
2172                 // valid VkSampler handles
2173                 if (((pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
2174                      (pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)) &&
2175                     (pCreateInfo->pBindings[i].pImmutableSamplers != nullptr)) {
2176                     for (uint32_t descriptor_index = 0; descriptor_index < pCreateInfo->pBindings[i].descriptorCount;
2177                          ++descriptor_index) {
2178                         if (pCreateInfo->pBindings[i].pImmutableSamplers[descriptor_index] == VK_NULL_HANDLE) {
2179                             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2180                                             kVUID_PVError_RequiredParameter,
2181                                             "vkCreateDescriptorSetLayout: required parameter "
2182                                             "pCreateInfo->pBindings[%d].pImmutableSamplers[%d] specified as VK_NULL_HANDLE",
2183                                             i, descriptor_index);
2184                         }
2185                     }
2186                 }
2187 
2188                 // If descriptorCount is not 0, stageFlags must be a valid combination of VkShaderStageFlagBits values
2189                 if ((pCreateInfo->pBindings[i].stageFlags != 0) &&
2190                     ((pCreateInfo->pBindings[i].stageFlags & (~AllVkShaderStageFlagBits)) != 0)) {
2191                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2192                                     "VUID-VkDescriptorSetLayoutBinding-descriptorCount-00283",
2193                                     "vkCreateDescriptorSetLayout(): if pCreateInfo->pBindings[%d].descriptorCount is not 0, "
2194                                     "pCreateInfo->pBindings[%d].stageFlags must be a valid combination of VkShaderStageFlagBits "
2195                                     "values.",
2196                                     i, i);
2197                 }
2198             }
2199         }
2200     }
2201     return skip;
2202 }
2203 
manual_PreCallValidateFreeDescriptorSets(VkDevice device,VkDescriptorPool descriptorPool,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets)2204 bool StatelessValidation::manual_PreCallValidateFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
2205                                                                    uint32_t descriptorSetCount,
2206                                                                    const VkDescriptorSet *pDescriptorSets) {
2207     // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
2208     // This is an array of handles, where the elements are allowed to be VK_NULL_HANDLE, and does not require any validation beyond
2209     // validate_array()
2210     return validate_array("vkFreeDescriptorSets", "descriptorSetCount", "pDescriptorSets", descriptorSetCount, &pDescriptorSets,
2211                           true, true, kVUIDUndefined, kVUIDUndefined);
2212 }
2213 
manual_PreCallValidateUpdateDescriptorSets(VkDevice device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)2214 bool StatelessValidation::manual_PreCallValidateUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
2215                                                                      const VkWriteDescriptorSet *pDescriptorWrites,
2216                                                                      uint32_t descriptorCopyCount,
2217                                                                      const VkCopyDescriptorSet *pDescriptorCopies) {
2218     bool skip = false;
2219     // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
2220     if (pDescriptorWrites != NULL) {
2221         for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
2222             // descriptorCount must be greater than 0
2223             if (pDescriptorWrites[i].descriptorCount == 0) {
2224                 skip |=
2225                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2226                             "VUID-VkWriteDescriptorSet-descriptorCount-arraylength",
2227                             "vkUpdateDescriptorSets(): parameter pDescriptorWrites[%d].descriptorCount must be greater than 0.", i);
2228             }
2229 
2230             // dstSet must be a valid VkDescriptorSet handle
2231             skip |= validate_required_handle("vkUpdateDescriptorSets",
2232                                              ParameterName("pDescriptorWrites[%i].dstSet", ParameterName::IndexVector{i}),
2233                                              pDescriptorWrites[i].dstSet);
2234 
2235             if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
2236                 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
2237                 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
2238                 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
2239                 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
2240                 // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
2241                 // VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
2242                 // pImageInfo must be a pointer to an array of descriptorCount valid VkDescriptorImageInfo structures
2243                 if (pDescriptorWrites[i].pImageInfo == nullptr) {
2244                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2245                                     "VUID-VkWriteDescriptorSet-descriptorType-00322",
2246                                     "vkUpdateDescriptorSets(): if pDescriptorWrites[%d].descriptorType is "
2247                                     "VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "
2248                                     "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or "
2249                                     "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, pDescriptorWrites[%d].pImageInfo must not be NULL.",
2250                                     i, i);
2251                 } else if (pDescriptorWrites[i].descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER) {
2252                     // If descriptorType is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
2253                     // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, the imageView and imageLayout
2254                     // members of any given element of pImageInfo must be a valid VkImageView and VkImageLayout, respectively
2255                     for (uint32_t descriptor_index = 0; descriptor_index < pDescriptorWrites[i].descriptorCount;
2256                          ++descriptor_index) {
2257                         skip |= validate_required_handle("vkUpdateDescriptorSets",
2258                                                          ParameterName("pDescriptorWrites[%i].pImageInfo[%i].imageView",
2259                                                                        ParameterName::IndexVector{i, descriptor_index}),
2260                                                          pDescriptorWrites[i].pImageInfo[descriptor_index].imageView);
2261                         skip |= validate_ranged_enum("vkUpdateDescriptorSets",
2262                                                      ParameterName("pDescriptorWrites[%i].pImageInfo[%i].imageLayout",
2263                                                                    ParameterName::IndexVector{i, descriptor_index}),
2264                                                      "VkImageLayout", AllVkImageLayoutEnums,
2265                                                      pDescriptorWrites[i].pImageInfo[descriptor_index].imageLayout, kVUIDUndefined);
2266                     }
2267                 }
2268             } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
2269                        (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
2270                        (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
2271                        (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
2272                 // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2273                 // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, pBufferInfo must be a
2274                 // pointer to an array of descriptorCount valid VkDescriptorBufferInfo structures
2275                 if (pDescriptorWrites[i].pBufferInfo == nullptr) {
2276                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2277                                     "VUID-VkWriteDescriptorSet-descriptorType-00324",
2278                                     "vkUpdateDescriptorSets(): if pDescriptorWrites[%d].descriptorType is "
2279                                     "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "
2280                                     "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "
2281                                     "pDescriptorWrites[%d].pBufferInfo must not be NULL.",
2282                                     i, i);
2283                 } else {
2284                     for (uint32_t descriptorIndex = 0; descriptorIndex < pDescriptorWrites[i].descriptorCount; ++descriptorIndex) {
2285                         skip |= validate_required_handle("vkUpdateDescriptorSets",
2286                                                          ParameterName("pDescriptorWrites[%i].pBufferInfo[%i].buffer",
2287                                                                        ParameterName::IndexVector{i, descriptorIndex}),
2288                                                          pDescriptorWrites[i].pBufferInfo[descriptorIndex].buffer);
2289                     }
2290                 }
2291             } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
2292                        (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
2293                 // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
2294                 // pTexelBufferView must be a pointer to an array of descriptorCount valid VkBufferView handles
2295                 if (pDescriptorWrites[i].pTexelBufferView == nullptr) {
2296                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2297                                     "VUID-VkWriteDescriptorSet-descriptorType-00323",
2298                                     "vkUpdateDescriptorSets(): if pDescriptorWrites[%d].descriptorType is "
2299                                     "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "
2300                                     "pDescriptorWrites[%d].pTexelBufferView must not be NULL.",
2301                                     i, i);
2302                 } else {
2303                     for (uint32_t descriptor_index = 0; descriptor_index < pDescriptorWrites[i].descriptorCount;
2304                          ++descriptor_index) {
2305                         skip |= validate_required_handle("vkUpdateDescriptorSets",
2306                                                          ParameterName("pDescriptorWrites[%i].pTexelBufferView[%i]",
2307                                                                        ParameterName::IndexVector{i, descriptor_index}),
2308                                                          pDescriptorWrites[i].pTexelBufferView[descriptor_index]);
2309                     }
2310                 }
2311             }
2312 
2313             if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
2314                 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)) {
2315                 VkDeviceSize uniformAlignment = device_limits.minUniformBufferOffsetAlignment;
2316                 for (uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) {
2317                     if (pDescriptorWrites[i].pBufferInfo != NULL) {
2318                         if (SafeModulo(pDescriptorWrites[i].pBufferInfo[j].offset, uniformAlignment) != 0) {
2319                             skip |=
2320                                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
2321                                         0, "VUID-VkWriteDescriptorSet-descriptorType-00327",
2322                                         "vkUpdateDescriptorSets(): pDescriptorWrites[%d].pBufferInfo[%d].offset (0x%" PRIxLEAST64
2323                                         ") must be a multiple of device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ".",
2324                                         i, j, pDescriptorWrites[i].pBufferInfo[j].offset, uniformAlignment);
2325                         }
2326                     }
2327                 }
2328             } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
2329                        (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
2330                 VkDeviceSize storageAlignment = device_limits.minStorageBufferOffsetAlignment;
2331                 for (uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) {
2332                     if (pDescriptorWrites[i].pBufferInfo != NULL) {
2333                         if (SafeModulo(pDescriptorWrites[i].pBufferInfo[j].offset, storageAlignment) != 0) {
2334                             skip |=
2335                                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
2336                                         0, "VUID-VkWriteDescriptorSet-descriptorType-00328",
2337                                         "vkUpdateDescriptorSets(): pDescriptorWrites[%d].pBufferInfo[%d].offset (0x%" PRIxLEAST64
2338                                         ") must be a multiple of device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ".",
2339                                         i, j, pDescriptorWrites[i].pBufferInfo[j].offset, storageAlignment);
2340                         }
2341                     }
2342                 }
2343             }
2344         }
2345     }
2346     return skip;
2347 }
2348 
manual_PreCallValidateCreateRenderPass(VkDevice device,const VkRenderPassCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)2349 bool StatelessValidation::manual_PreCallValidateCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
2350                                                                  const VkAllocationCallbacks *pAllocator,
2351                                                                  VkRenderPass *pRenderPass) {
2352     return CreateRenderPassGeneric(device, pCreateInfo, pAllocator, pRenderPass, RENDER_PASS_VERSION_1);
2353 }
2354 
manual_PreCallValidateCreateRenderPass2KHR(VkDevice device,const VkRenderPassCreateInfo2KHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)2355 bool StatelessValidation::manual_PreCallValidateCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo,
2356                                                                      const VkAllocationCallbacks *pAllocator,
2357                                                                      VkRenderPass *pRenderPass) {
2358     return CreateRenderPassGeneric(device, pCreateInfo, pAllocator, pRenderPass, RENDER_PASS_VERSION_2);
2359 }
2360 
manual_PreCallValidateFreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)2361 bool StatelessValidation::manual_PreCallValidateFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
2362                                                                    uint32_t commandBufferCount,
2363                                                                    const VkCommandBuffer *pCommandBuffers) {
2364     bool skip = false;
2365 
2366     // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
2367     // This is an array of handles, where the elements are allowed to be VK_NULL_HANDLE, and does not require any validation beyond
2368     // validate_array()
2369     skip |= validate_array("vkFreeCommandBuffers", "commandBufferCount", "pCommandBuffers", commandBufferCount, &pCommandBuffers,
2370                            true, true, kVUIDUndefined, kVUIDUndefined);
2371     return skip;
2372 }
2373 
manual_PreCallValidateBeginCommandBuffer(VkCommandBuffer commandBuffer,const VkCommandBufferBeginInfo * pBeginInfo)2374 bool StatelessValidation::manual_PreCallValidateBeginCommandBuffer(VkCommandBuffer commandBuffer,
2375                                                                    const VkCommandBufferBeginInfo *pBeginInfo) {
2376     bool skip = false;
2377 
2378     // VkCommandBufferInheritanceInfo validation, due to a 'noautovalidity' of pBeginInfo->pInheritanceInfo in vkBeginCommandBuffer
2379     const char *cmd_name = "vkBeginCommandBuffer";
2380     const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo;
2381 
2382     // Implicit VUs
2383     // validate only sType here; pointer has to be validated in core_validation
2384     const bool kNotRequired = false;
2385     const char *kNoVUID = nullptr;
2386     skip |= validate_struct_type(cmd_name, "pBeginInfo->pInheritanceInfo", "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO",
2387                                  pInfo, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, kNotRequired, kNoVUID,
2388                                  "VUID-VkCommandBufferInheritanceInfo-sType-sType");
2389 
2390     if (pInfo) {
2391         const VkStructureType allowed_structs_VkCommandBufferInheritanceInfo[] = {
2392             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT};
2393         skip |= validate_struct_pnext(
2394             cmd_name, "pBeginInfo->pInheritanceInfo->pNext", "VkCommandBufferInheritanceConditionalRenderingInfoEXT", pInfo->pNext,
2395             ARRAY_SIZE(allowed_structs_VkCommandBufferInheritanceInfo), allowed_structs_VkCommandBufferInheritanceInfo,
2396             GeneratedVulkanHeaderVersion, "VUID-VkCommandBufferInheritanceInfo-pNext-pNext");
2397 
2398         skip |= validate_bool32(cmd_name, "pBeginInfo->pInheritanceInfo->occlusionQueryEnable", pInfo->occlusionQueryEnable);
2399 
2400         // Explicit VUs
2401         if (!physical_device_features.inheritedQueries && pInfo->occlusionQueryEnable == VK_TRUE) {
2402             skip |= log_msg(
2403                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2404                 HandleToUint64(commandBuffer), "VUID-VkCommandBufferInheritanceInfo-occlusionQueryEnable-00056",
2405                 "%s: Inherited queries feature is disabled, but pBeginInfo->pInheritanceInfo->occlusionQueryEnable is VK_TRUE.",
2406                 cmd_name);
2407         }
2408 
2409         if (physical_device_features.inheritedQueries) {
2410             skip |= validate_flags(cmd_name, "pBeginInfo->pInheritanceInfo->queryFlags", "VkQueryControlFlagBits",
2411                                    AllVkQueryControlFlagBits, pInfo->queryFlags, kOptionalFlags,
2412                                    "VUID-VkCommandBufferInheritanceInfo-queryFlags-00057");
2413         } else {  // !inheritedQueries
2414             skip |= validate_reserved_flags(cmd_name, "pBeginInfo->pInheritanceInfo->queryFlags", pInfo->queryFlags,
2415                                             "VUID-VkCommandBufferInheritanceInfo-queryFlags-02788");
2416         }
2417 
2418         if (physical_device_features.pipelineStatisticsQuery) {
2419             skip |= validate_flags(cmd_name, "pBeginInfo->pInheritanceInfo->pipelineStatistics", "VkQueryPipelineStatisticFlagBits",
2420                                    AllVkQueryPipelineStatisticFlagBits, pInfo->pipelineStatistics, kOptionalFlags,
2421                                    "VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-02789");
2422         } else {  // !pipelineStatisticsQuery
2423             skip |= validate_reserved_flags(cmd_name, "pBeginInfo->pInheritanceInfo->pipelineStatistics", pInfo->pipelineStatistics,
2424                                             "VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-00058");
2425         }
2426 
2427         const auto *conditional_rendering = lvl_find_in_chain<VkCommandBufferInheritanceConditionalRenderingInfoEXT>(pInfo->pNext);
2428         if (conditional_rendering) {
2429             const auto *cr_features =
2430                 lvl_find_in_chain<VkPhysicalDeviceConditionalRenderingFeaturesEXT>(physical_device_features2.pNext);
2431             const auto inherited_conditional_rendering = cr_features && cr_features->inheritedConditionalRendering;
2432             if (!inherited_conditional_rendering && conditional_rendering->conditionalRenderingEnable == VK_TRUE) {
2433                 skip |= log_msg(
2434                     report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2435                     HandleToUint64(commandBuffer),
2436                     "VUID-VkCommandBufferInheritanceConditionalRenderingInfoEXT-conditionalRenderingEnable-01977",
2437                     "vkBeginCommandBuffer: Inherited conditional rendering is disabled, but "
2438                     "pBeginInfo->pInheritanceInfo->pNext<VkCommandBufferInheritanceConditionalRenderingInfoEXT> is VK_TRUE.");
2439             }
2440         }
2441     }
2442 
2443     return skip;
2444 }
2445 
manual_PreCallValidateCmdSetViewport(VkCommandBuffer commandBuffer,uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)2446 bool StatelessValidation::manual_PreCallValidateCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport,
2447                                                                uint32_t viewportCount, const VkViewport *pViewports) {
2448     bool skip = false;
2449 
2450     if (!physical_device_features.multiViewport) {
2451         if (firstViewport != 0) {
2452             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2453                             HandleToUint64(commandBuffer), "VUID-vkCmdSetViewport-firstViewport-01224",
2454                             "vkCmdSetViewport: The multiViewport feature is disabled, but firstViewport (=%" PRIu32 ") is not 0.",
2455                             firstViewport);
2456         }
2457         if (viewportCount > 1) {
2458             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2459                             HandleToUint64(commandBuffer), "VUID-vkCmdSetViewport-viewportCount-01225",
2460                             "vkCmdSetViewport: The multiViewport feature is disabled, but viewportCount (=%" PRIu32 ") is not 1.",
2461                             viewportCount);
2462         }
2463     } else {  // multiViewport enabled
2464         const uint64_t sum = static_cast<uint64_t>(firstViewport) + static_cast<uint64_t>(viewportCount);
2465         if (sum > device_limits.maxViewports) {
2466             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2467                             HandleToUint64(commandBuffer), "VUID-vkCmdSetViewport-firstViewport-01223",
2468                             "vkCmdSetViewport: firstViewport + viewportCount (=%" PRIu32 " + %" PRIu32 " = %" PRIu64
2469                             ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
2470                             firstViewport, viewportCount, sum, device_limits.maxViewports);
2471         }
2472     }
2473 
2474     if (pViewports) {
2475         for (uint32_t viewport_i = 0; viewport_i < viewportCount; ++viewport_i) {
2476             const auto &viewport = pViewports[viewport_i];  // will crash on invalid ptr
2477             const char *fn_name = "vkCmdSetViewport";
2478             skip |= manual_PreCallValidateViewport(viewport, fn_name,
2479                                                    ParameterName("pViewports[%i]", ParameterName::IndexVector{viewport_i}),
2480                                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer));
2481         }
2482     }
2483 
2484     return skip;
2485 }
2486 
manual_PreCallValidateCmdSetScissor(VkCommandBuffer commandBuffer,uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)2487 bool StatelessValidation::manual_PreCallValidateCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor,
2488                                                               uint32_t scissorCount, const VkRect2D *pScissors) {
2489     bool skip = false;
2490 
2491     if (!physical_device_features.multiViewport) {
2492         if (firstScissor != 0) {
2493             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2494                             HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-firstScissor-00593",
2495                             "vkCmdSetScissor: The multiViewport feature is disabled, but firstScissor (=%" PRIu32 ") is not 0.",
2496                             firstScissor);
2497         }
2498         if (scissorCount > 1) {
2499             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2500                             HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-scissorCount-00594",
2501                             "vkCmdSetScissor: The multiViewport feature is disabled, but scissorCount (=%" PRIu32 ") is not 1.",
2502                             scissorCount);
2503         }
2504     } else {  // multiViewport enabled
2505         const uint64_t sum = static_cast<uint64_t>(firstScissor) + static_cast<uint64_t>(scissorCount);
2506         if (sum > device_limits.maxViewports) {
2507             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2508                             HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-firstScissor-00592",
2509                             "vkCmdSetScissor: firstScissor + scissorCount (=%" PRIu32 " + %" PRIu32 " = %" PRIu64
2510                             ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
2511                             firstScissor, scissorCount, sum, device_limits.maxViewports);
2512         }
2513     }
2514 
2515     if (pScissors) {
2516         for (uint32_t scissor_i = 0; scissor_i < scissorCount; ++scissor_i) {
2517             const auto &scissor = pScissors[scissor_i];  // will crash on invalid ptr
2518 
2519             if (scissor.offset.x < 0) {
2520                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2521                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-x-00595",
2522                                 "vkCmdSetScissor: pScissors[%" PRIu32 "].offset.x (=%" PRIi32 ") is negative.", scissor_i,
2523                                 scissor.offset.x);
2524             }
2525 
2526             if (scissor.offset.y < 0) {
2527                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2528                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-x-00595",
2529                                 "vkCmdSetScissor: pScissors[%" PRIu32 "].offset.y (=%" PRIi32 ") is negative.", scissor_i,
2530                                 scissor.offset.y);
2531             }
2532 
2533             const int64_t x_sum = static_cast<int64_t>(scissor.offset.x) + static_cast<int64_t>(scissor.extent.width);
2534             if (x_sum > INT32_MAX) {
2535                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2536                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-offset-00596",
2537                                 "vkCmdSetScissor: offset.x + extent.width (=%" PRIi32 " + %" PRIu32 " = %" PRIi64
2538                                 ") of pScissors[%" PRIu32 "] will overflow int32_t.",
2539                                 scissor.offset.x, scissor.extent.width, x_sum, scissor_i);
2540             }
2541 
2542             const int64_t y_sum = static_cast<int64_t>(scissor.offset.y) + static_cast<int64_t>(scissor.extent.height);
2543             if (y_sum > INT32_MAX) {
2544                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2545                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetScissor-offset-00597",
2546                                 "vkCmdSetScissor: offset.y + extent.height (=%" PRIi32 " + %" PRIu32 " = %" PRIi64
2547                                 ") of pScissors[%" PRIu32 "] will overflow int32_t.",
2548                                 scissor.offset.y, scissor.extent.height, y_sum, scissor_i);
2549             }
2550         }
2551     }
2552 
2553     return skip;
2554 }
2555 
manual_PreCallValidateCmdSetLineWidth(VkCommandBuffer commandBuffer,float lineWidth)2556 bool StatelessValidation::manual_PreCallValidateCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
2557     bool skip = false;
2558 
2559     if (!physical_device_features.wideLines && (lineWidth != 1.0f)) {
2560         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2561                         HandleToUint64(commandBuffer), "VUID-vkCmdSetLineWidth-lineWidth-00788",
2562                         "VkPhysicalDeviceFeatures::wideLines is disabled, but lineWidth (=%f) is not 1.0.", lineWidth);
2563     }
2564 
2565     return skip;
2566 }
2567 
manual_PreCallValidateCmdDraw(VkCommandBuffer commandBuffer,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)2568 bool StatelessValidation::manual_PreCallValidateCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
2569                                                         uint32_t firstVertex, uint32_t firstInstance) {
2570     bool skip = false;
2571     if (vertexCount == 0) {
2572         // TODO: Verify against Valid Usage section. I don't see a non-zero vertexCount listed, may need to add that and make
2573         // this an error or leave as is.
2574         skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2575                         kVUID_PVError_RequiredParameter, "vkCmdDraw parameter, uint32_t vertexCount, is 0");
2576     }
2577 
2578     if (instanceCount == 0) {
2579         // TODO: Verify against Valid Usage section. I don't see a non-zero instanceCount listed, may need to add that and make
2580         // this an error or leave as is.
2581         skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2582                         kVUID_PVError_RequiredParameter, "vkCmdDraw parameter, uint32_t instanceCount, is 0");
2583     }
2584     return skip;
2585 }
2586 
manual_PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)2587 bool StatelessValidation::manual_PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
2588                                                                 uint32_t count, uint32_t stride) {
2589     bool skip = false;
2590 
2591     if (!physical_device_features.multiDrawIndirect && ((count > 1))) {
2592         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2593                         kVUID_PVError_DeviceFeature,
2594                         "CmdDrawIndirect(): Device feature multiDrawIndirect disabled: count must be 0 or 1 but is %d", count);
2595     }
2596     return skip;
2597 }
2598 
manual_PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)2599 bool StatelessValidation::manual_PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
2600                                                                        VkDeviceSize offset, uint32_t count, uint32_t stride) {
2601     bool skip = false;
2602     if (!physical_device_features.multiDrawIndirect && ((count > 1))) {
2603         skip |= log_msg(
2604             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, kVUID_PVError_DeviceFeature,
2605             "CmdDrawIndexedIndirect(): Device feature multiDrawIndirect disabled: count must be 0 or 1 but is %d", count);
2606     }
2607     return skip;
2608 }
2609 
manual_PreCallValidateCmdClearAttachments(VkCommandBuffer commandBuffer,uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)2610 bool StatelessValidation::manual_PreCallValidateCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
2611                                                                     const VkClearAttachment *pAttachments, uint32_t rectCount,
2612                                                                     const VkClearRect *pRects) {
2613     bool skip = false;
2614     for (uint32_t rect = 0; rect < rectCount; rect++) {
2615         if (pRects[rect].layerCount == 0) {
2616             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2617                             HandleToUint64(commandBuffer), "VUID-vkCmdClearAttachments-layerCount-01934",
2618                             "CmdClearAttachments(): pRects[%d].layerCount is zero.", rect);
2619         }
2620     }
2621     return skip;
2622 }
2623 
manual_PreCallValidateCmdCopyImage(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageCopy * pRegions)2624 bool StatelessValidation::manual_PreCallValidateCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
2625                                                              VkImageLayout srcImageLayout, VkImage dstImage,
2626                                                              VkImageLayout dstImageLayout, uint32_t regionCount,
2627                                                              const VkImageCopy *pRegions) {
2628     bool skip = false;
2629 
2630     VkImageAspectFlags legal_aspect_flags =
2631         VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT;
2632     if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
2633         legal_aspect_flags |= (VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | VK_IMAGE_ASPECT_PLANE_2_BIT_KHR);
2634     }
2635 
2636     if (pRegions != nullptr) {
2637         if ((pRegions->srcSubresource.aspectMask & legal_aspect_flags) == 0) {
2638             skip |= log_msg(
2639                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2640                 "VUID-VkImageSubresourceLayers-aspectMask-parameter",
2641                 "vkCmdCopyImage() parameter, VkImageAspect pRegions->srcSubresource.aspectMask, is an unrecognized enumerator.");
2642         }
2643         if ((pRegions->dstSubresource.aspectMask & legal_aspect_flags) == 0) {
2644             skip |= log_msg(
2645                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2646                 "VUID-VkImageSubresourceLayers-aspectMask-parameter",
2647                 "vkCmdCopyImage() parameter, VkImageAspect pRegions->dstSubresource.aspectMask, is an unrecognized enumerator.");
2648         }
2649     }
2650     return skip;
2651 }
2652 
manual_PreCallValidateCmdBlitImage(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageBlit * pRegions,VkFilter filter)2653 bool StatelessValidation::manual_PreCallValidateCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage,
2654                                                              VkImageLayout srcImageLayout, VkImage dstImage,
2655                                                              VkImageLayout dstImageLayout, uint32_t regionCount,
2656                                                              const VkImageBlit *pRegions, VkFilter filter) {
2657     bool skip = false;
2658 
2659     VkImageAspectFlags legal_aspect_flags =
2660         VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT;
2661     if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
2662         legal_aspect_flags |= (VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | VK_IMAGE_ASPECT_PLANE_2_BIT_KHR);
2663     }
2664 
2665     if (pRegions != nullptr) {
2666         if ((pRegions->srcSubresource.aspectMask & legal_aspect_flags) == 0) {
2667             skip |= log_msg(
2668                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2669                 kVUID_PVError_UnrecognizedValue,
2670                 "vkCmdBlitImage() parameter, VkImageAspect pRegions->srcSubresource.aspectMask, is an unrecognized enumerator");
2671         }
2672         if ((pRegions->dstSubresource.aspectMask & legal_aspect_flags) == 0) {
2673             skip |= log_msg(
2674                 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2675                 kVUID_PVError_UnrecognizedValue,
2676                 "vkCmdBlitImage() parameter, VkImageAspect pRegions->dstSubresource.aspectMask, is an unrecognized enumerator");
2677         }
2678     }
2679     return skip;
2680 }
2681 
manual_PreCallValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer,VkBuffer srcBuffer,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkBufferImageCopy * pRegions)2682 bool StatelessValidation::manual_PreCallValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
2683                                                                      VkImage dstImage, VkImageLayout dstImageLayout,
2684                                                                      uint32_t regionCount, const VkBufferImageCopy *pRegions) {
2685     bool skip = false;
2686 
2687     VkImageAspectFlags legal_aspect_flags =
2688         VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT;
2689     if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
2690         legal_aspect_flags |= (VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | VK_IMAGE_ASPECT_PLANE_2_BIT_KHR);
2691     }
2692 
2693     if (pRegions != nullptr) {
2694         if ((pRegions->imageSubresource.aspectMask & legal_aspect_flags) == 0) {
2695             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2696                             kVUID_PVError_UnrecognizedValue,
2697                             "vkCmdCopyBufferToImage() parameter, VkImageAspect pRegions->imageSubresource.aspectMask, is an "
2698                             "unrecognized enumerator");
2699         }
2700     }
2701     return skip;
2702 }
2703 
manual_PreCallValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer,VkImage srcImage,VkImageLayout srcImageLayout,VkBuffer dstBuffer,uint32_t regionCount,const VkBufferImageCopy * pRegions)2704 bool StatelessValidation::manual_PreCallValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
2705                                                                      VkImageLayout srcImageLayout, VkBuffer dstBuffer,
2706                                                                      uint32_t regionCount, const VkBufferImageCopy *pRegions) {
2707     bool skip = false;
2708 
2709     VkImageAspectFlags legal_aspect_flags =
2710         VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT;
2711     if (device_extensions.vk_khr_sampler_ycbcr_conversion) {
2712         legal_aspect_flags |= (VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | VK_IMAGE_ASPECT_PLANE_2_BIT_KHR);
2713     }
2714 
2715     if (pRegions != nullptr) {
2716         if ((pRegions->imageSubresource.aspectMask & legal_aspect_flags) == 0) {
2717             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2718                     kVUID_PVError_UnrecognizedValue,
2719                     "vkCmdCopyImageToBuffer parameter, VkImageAspect pRegions->imageSubresource.aspectMask, is an unrecognized "
2720                     "enumerator");
2721         }
2722     }
2723     return skip;
2724 }
2725 
manual_PreCallValidateCmdUpdateBuffer(VkCommandBuffer commandBuffer,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)2726 bool StatelessValidation::manual_PreCallValidateCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
2727                                                                 VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData) {
2728     bool skip = false;
2729 
2730     if (dstOffset & 3) {
2731         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2732                         "VUID-vkCmdUpdateBuffer-dstOffset-00036",
2733                         "vkCmdUpdateBuffer() parameter, VkDeviceSize dstOffset (0x%" PRIxLEAST64 "), is not a multiple of 4.",
2734                         dstOffset);
2735     }
2736 
2737     if ((dataSize <= 0) || (dataSize > 65536)) {
2738         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2739                         "VUID-vkCmdUpdateBuffer-dataSize-00037",
2740                         "vkCmdUpdateBuffer() parameter, VkDeviceSize dataSize (0x%" PRIxLEAST64
2741                         "), must be greater than zero and less than or equal to 65536.",
2742                         dataSize);
2743     } else if (dataSize & 3) {
2744         skip |=
2745             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2746                     "VUID-vkCmdUpdateBuffer-dataSize-00038",
2747                     "vkCmdUpdateBuffer() parameter, VkDeviceSize dataSize (0x%" PRIxLEAST64 "), is not a multiple of 4.", dataSize);
2748     }
2749     return skip;
2750 }
2751 
manual_PreCallValidateCmdFillBuffer(VkCommandBuffer commandBuffer,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)2752 bool StatelessValidation::manual_PreCallValidateCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
2753                                                               VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
2754     bool skip = false;
2755 
2756     if (dstOffset & 3) {
2757         skip |=
2758             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2759                     "VUID-vkCmdFillBuffer-dstOffset-00025",
2760                     "vkCmdFillBuffer() parameter, VkDeviceSize dstOffset (0x%" PRIxLEAST64 "), is not a multiple of 4.", dstOffset);
2761     }
2762 
2763     if (size != VK_WHOLE_SIZE) {
2764         if (size <= 0) {
2765             skip |=
2766                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2767                         "VUID-vkCmdFillBuffer-size-00026",
2768                         "vkCmdFillBuffer() parameter, VkDeviceSize size (0x%" PRIxLEAST64 "), must be greater than zero.", size);
2769         } else if (size & 3) {
2770             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2771                             "VUID-vkCmdFillBuffer-size-00028",
2772                             "vkCmdFillBuffer() parameter, VkDeviceSize size (0x%" PRIxLEAST64 "), is not a multiple of 4.", size);
2773         }
2774     }
2775     return skip;
2776 }
2777 
manual_PreCallValidateCreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchain)2778 bool StatelessValidation::manual_PreCallValidateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
2779                                                                    const VkAllocationCallbacks *pAllocator,
2780                                                                    VkSwapchainKHR *pSwapchain) {
2781     bool skip = false;
2782 
2783     const LogMiscParams log_misc{VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, VK_NULL_HANDLE, "vkCreateSwapchainKHR"};
2784 
2785     if (pCreateInfo != nullptr) {
2786         // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
2787         if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
2788             // If imageSharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
2789             if (pCreateInfo->queueFamilyIndexCount <= 1) {
2790                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2791                                 "VUID-VkSwapchainCreateInfoKHR-imageSharingMode-01278",
2792                                 "vkCreateSwapchainKHR(): if pCreateInfo->imageSharingMode is VK_SHARING_MODE_CONCURRENT, "
2793                                 "pCreateInfo->queueFamilyIndexCount must be greater than 1.");
2794             }
2795 
2796             // If imageSharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
2797             // queueFamilyIndexCount uint32_t values
2798             if (pCreateInfo->pQueueFamilyIndices == nullptr) {
2799                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2800                                 "VUID-VkSwapchainCreateInfoKHR-imageSharingMode-01277",
2801                                 "vkCreateSwapchainKHR(): if pCreateInfo->imageSharingMode is VK_SHARING_MODE_CONCURRENT, "
2802                                 "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
2803                                 "pCreateInfo->queueFamilyIndexCount uint32_t values.");
2804             }
2805         }
2806 
2807         skip |= ValidateGreaterThanZero(pCreateInfo->imageArrayLayers, "pCreateInfo->imageArrayLayers",
2808                                         "VUID-VkSwapchainCreateInfoKHR-imageArrayLayers-01275", log_misc);
2809     }
2810 
2811     return skip;
2812 }
2813 
manual_PreCallValidateQueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * pPresentInfo)2814 bool StatelessValidation::manual_PreCallValidateQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
2815     bool skip = false;
2816 
2817     if (pPresentInfo && pPresentInfo->pNext) {
2818         const auto *present_regions = lvl_find_in_chain<VkPresentRegionsKHR>(pPresentInfo->pNext);
2819         if (present_regions) {
2820             // TODO: This and all other pNext extension dependencies should be added to code-generation
2821             skip |= require_device_extension(device_extensions.vk_khr_incremental_present, "vkQueuePresentKHR",
2822                                              VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
2823             if (present_regions->swapchainCount != pPresentInfo->swapchainCount) {
2824                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2825                                 kVUID_PVError_InvalidUsage,
2826                                 "QueuePresentKHR(): pPresentInfo->swapchainCount has a value of %i but VkPresentRegionsKHR "
2827                                 "extension swapchainCount is %i. These values must be equal.",
2828                                 pPresentInfo->swapchainCount, present_regions->swapchainCount);
2829             }
2830             skip |= validate_struct_pnext("QueuePresentKHR", "pCreateInfo->pNext->pNext", NULL, present_regions->pNext, 0, NULL,
2831                                           GeneratedVulkanHeaderVersion, "VUID-VkPresentInfoKHR-pNext-pNext");
2832             skip |= validate_array("QueuePresentKHR", "pCreateInfo->pNext->swapchainCount", "pCreateInfo->pNext->pRegions",
2833                                    present_regions->swapchainCount, &present_regions->pRegions, true, false, kVUIDUndefined,
2834                                    kVUIDUndefined);
2835             for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) {
2836                 skip |= validate_array("QueuePresentKHR", "pCreateInfo->pNext->pRegions[].rectangleCount",
2837                                        "pCreateInfo->pNext->pRegions[].pRectangles", present_regions->pRegions[i].rectangleCount,
2838                                        &present_regions->pRegions[i].pRectangles, true, false, kVUIDUndefined, kVUIDUndefined);
2839             }
2840         }
2841     }
2842 
2843     return skip;
2844 }
2845 
2846 #ifdef VK_USE_PLATFORM_WIN32_KHR
manual_PreCallValidateCreateWin32SurfaceKHR(VkInstance instance,const VkWin32SurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)2847 bool StatelessValidation::manual_PreCallValidateCreateWin32SurfaceKHR(VkInstance instance,
2848                                                                       const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
2849                                                                       const VkAllocationCallbacks *pAllocator,
2850                                                                       VkSurfaceKHR *pSurface) {
2851     bool skip = false;
2852 
2853     if (pCreateInfo->hwnd == nullptr) {
2854         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
2855                         "VUID-VkWin32SurfaceCreateInfoKHR-hwnd-01308",
2856                         "vkCreateWin32SurfaceKHR(): hwnd must be a valid Win32 HWND but hwnd is NULL.");
2857     }
2858 
2859     return skip;
2860 }
2861 #endif  // VK_USE_PLATFORM_WIN32_KHR
2862 
manual_PreCallValidateCreateDescriptorPool(VkDevice device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)2863 bool StatelessValidation::manual_PreCallValidateCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
2864                                                                      const VkAllocationCallbacks *pAllocator,
2865                                                                      VkDescriptorPool *pDescriptorPool) {
2866     bool skip = false;
2867 
2868     if (pCreateInfo) {
2869         if (pCreateInfo->maxSets <= 0) {
2870             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
2871                             VK_NULL_HANDLE, "VUID-VkDescriptorPoolCreateInfo-maxSets-00301",
2872                             "vkCreateDescriptorPool(): pCreateInfo->maxSets is not greater than 0.");
2873         }
2874 
2875         if (pCreateInfo->pPoolSizes) {
2876             for (uint32_t i = 0; i < pCreateInfo->poolSizeCount; ++i) {
2877                 if (pCreateInfo->pPoolSizes[i].descriptorCount <= 0) {
2878                     skip |= log_msg(
2879                         report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, VK_NULL_HANDLE,
2880                         "VUID-VkDescriptorPoolSize-descriptorCount-00302",
2881                         "vkCreateDescriptorPool(): pCreateInfo->pPoolSizes[%" PRIu32 "].descriptorCount is not greater than 0.", i);
2882                 }
2883                 if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT &&
2884                     (pCreateInfo->pPoolSizes[i].descriptorCount % 4) != 0) {
2885                     skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
2886                                     VK_NULL_HANDLE, "VUID-VkDescriptorPoolSize-type-02218",
2887                                     "vkCreateDescriptorPool(): pCreateInfo->pPoolSizes[%" PRIu32
2888                                     "].type is VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT "
2889                                     " and pCreateInfo->pPoolSizes[%" PRIu32 "].descriptorCount is not a multiple of 4.",
2890                                     i, i);
2891                 }
2892             }
2893         }
2894     }
2895 
2896     return skip;
2897 }
2898 
manual_PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)2899 bool StatelessValidation::manual_PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX,
2900                                                             uint32_t groupCountY, uint32_t groupCountZ) {
2901     bool skip = false;
2902 
2903     if (groupCountX > device_limits.maxComputeWorkGroupCount[0]) {
2904         skip |=
2905             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2906                     HandleToUint64(commandBuffer), "VUID-vkCmdDispatch-groupCountX-00386",
2907                     "vkCmdDispatch(): groupCountX (%" PRIu32 ") exceeds device limit maxComputeWorkGroupCount[0] (%" PRIu32 ").",
2908                     groupCountX, device_limits.maxComputeWorkGroupCount[0]);
2909     }
2910 
2911     if (groupCountY > device_limits.maxComputeWorkGroupCount[1]) {
2912         skip |=
2913             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2914                     HandleToUint64(commandBuffer), "VUID-vkCmdDispatch-groupCountY-00387",
2915                     "vkCmdDispatch(): groupCountY (%" PRIu32 ") exceeds device limit maxComputeWorkGroupCount[1] (%" PRIu32 ").",
2916                     groupCountY, device_limits.maxComputeWorkGroupCount[1]);
2917     }
2918 
2919     if (groupCountZ > device_limits.maxComputeWorkGroupCount[2]) {
2920         skip |=
2921             log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2922                     HandleToUint64(commandBuffer), "VUID-vkCmdDispatch-groupCountZ-00388",
2923                     "vkCmdDispatch(): groupCountZ (%" PRIu32 ") exceeds device limit maxComputeWorkGroupCount[2] (%" PRIu32 ").",
2924                     groupCountZ, device_limits.maxComputeWorkGroupCount[2]);
2925     }
2926 
2927     return skip;
2928 }
2929 
manual_PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset)2930 bool StatelessValidation::manual_PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
2931                                                                     VkDeviceSize offset) {
2932     bool skip = false;
2933 
2934     if ((offset % 4) != 0) {
2935         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2936                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchIndirect-offset-02710",
2937                         "vkCmdDispatchIndirect(): offset (%" PRIu64 ") must be a multiple of 4.", offset);
2938     }
2939     return skip;
2940 }
2941 
manual_PreCallValidateCmdDispatchBaseKHR(VkCommandBuffer commandBuffer,uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)2942 bool StatelessValidation::manual_PreCallValidateCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX,
2943                                                                    uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX,
2944                                                                    uint32_t groupCountY, uint32_t groupCountZ) {
2945     bool skip = false;
2946 
2947     // Paired if {} else if {} tests used to avoid any possible uint underflow
2948     uint32_t limit = device_limits.maxComputeWorkGroupCount[0];
2949     if (baseGroupX >= limit) {
2950         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2951                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchBase-baseGroupX-00421",
2952                         "vkCmdDispatch(): baseGroupX (%" PRIu32
2953                         ") equals or exceeds device limit maxComputeWorkGroupCount[0] (%" PRIu32 ").",
2954                         baseGroupX, limit);
2955     } else if (groupCountX > (limit - baseGroupX)) {
2956         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2957                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchBase-groupCountX-00424",
2958                         "vkCmdDispatchBaseKHR(): baseGroupX (%" PRIu32 ") + groupCountX (%" PRIu32
2959                         ") exceeds device limit maxComputeWorkGroupCount[0] (%" PRIu32 ").",
2960                         baseGroupX, groupCountX, limit);
2961     }
2962 
2963     limit = device_limits.maxComputeWorkGroupCount[1];
2964     if (baseGroupY >= limit) {
2965         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2966                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchBase-baseGroupX-00422",
2967                         "vkCmdDispatch(): baseGroupY (%" PRIu32
2968                         ") equals or exceeds device limit maxComputeWorkGroupCount[1] (%" PRIu32 ").",
2969                         baseGroupY, limit);
2970     } else if (groupCountY > (limit - baseGroupY)) {
2971         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2972                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchBase-groupCountY-00425",
2973                         "vkCmdDispatchBaseKHR(): baseGroupY (%" PRIu32 ") + groupCountY (%" PRIu32
2974                         ") exceeds device limit maxComputeWorkGroupCount[1] (%" PRIu32 ").",
2975                         baseGroupY, groupCountY, limit);
2976     }
2977 
2978     limit = device_limits.maxComputeWorkGroupCount[2];
2979     if (baseGroupZ >= limit) {
2980         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2981                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchBase-baseGroupZ-00423",
2982                         "vkCmdDispatch(): baseGroupZ (%" PRIu32
2983                         ") equals or exceeds device limit maxComputeWorkGroupCount[2] (%" PRIu32 ").",
2984                         baseGroupZ, limit);
2985     } else if (groupCountZ > (limit - baseGroupZ)) {
2986         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2987                         HandleToUint64(commandBuffer), "VUID-vkCmdDispatchBase-groupCountZ-00426",
2988                         "vkCmdDispatchBaseKHR(): baseGroupZ (%" PRIu32 ") + groupCountZ (%" PRIu32
2989                         ") exceeds device limit maxComputeWorkGroupCount[2] (%" PRIu32 ").",
2990                         baseGroupZ, groupCountZ, limit);
2991     }
2992 
2993     return skip;
2994 }
2995 
manual_PreCallValidateCmdSetExclusiveScissorNV(VkCommandBuffer commandBuffer,uint32_t firstExclusiveScissor,uint32_t exclusiveScissorCount,const VkRect2D * pExclusiveScissors)2996 bool StatelessValidation::manual_PreCallValidateCmdSetExclusiveScissorNV(VkCommandBuffer commandBuffer,
2997                                                                          uint32_t firstExclusiveScissor,
2998                                                                          uint32_t exclusiveScissorCount,
2999                                                                          const VkRect2D *pExclusiveScissors) {
3000     bool skip = false;
3001 
3002     if (!physical_device_features.multiViewport) {
3003         if (firstExclusiveScissor != 0) {
3004             skip |=
3005                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3006                         HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02035",
3007                         "vkCmdSetExclusiveScissorNV: The multiViewport feature is disabled, but firstExclusiveScissor (=%" PRIu32
3008                         ") is not 0.",
3009                         firstExclusiveScissor);
3010         }
3011         if (exclusiveScissorCount > 1) {
3012             skip |=
3013                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3014                         HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-exclusiveScissorCount-02036",
3015                         "vkCmdSetExclusiveScissorNV: The multiViewport feature is disabled, but exclusiveScissorCount (=%" PRIu32
3016                         ") is not 1.",
3017                         exclusiveScissorCount);
3018         }
3019     } else {  // multiViewport enabled
3020         const uint64_t sum = static_cast<uint64_t>(firstExclusiveScissor) + static_cast<uint64_t>(exclusiveScissorCount);
3021         if (sum > device_limits.maxViewports) {
3022             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3023                             HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02034",
3024                             "vkCmdSetExclusiveScissorNV: firstExclusiveScissor + exclusiveScissorCount (=%" PRIu32 " + %" PRIu32
3025                             " = %" PRIu64 ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
3026                             firstExclusiveScissor, exclusiveScissorCount, sum, device_limits.maxViewports);
3027         }
3028     }
3029 
3030     if (firstExclusiveScissor >= device_limits.maxViewports) {
3031         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3032                         HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02033",
3033                         "vkCmdSetExclusiveScissorNV: firstExclusiveScissor (=%" PRIu32 ") must be less than maxViewports (=%" PRIu32
3034                         ").",
3035                         firstExclusiveScissor, device_limits.maxViewports);
3036     }
3037 
3038     if (pExclusiveScissors) {
3039         for (uint32_t scissor_i = 0; scissor_i < exclusiveScissorCount; ++scissor_i) {
3040             const auto &scissor = pExclusiveScissors[scissor_i];  // will crash on invalid ptr
3041 
3042             if (scissor.offset.x < 0) {
3043                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3044                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-x-02037",
3045                                 "vkCmdSetExclusiveScissorNV: pScissors[%" PRIu32 "].offset.x (=%" PRIi32 ") is negative.",
3046                                 scissor_i, scissor.offset.x);
3047             }
3048 
3049             if (scissor.offset.y < 0) {
3050                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3051                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-x-02037",
3052                                 "vkCmdSetExclusiveScissorNV: pScissors[%" PRIu32 "].offset.y (=%" PRIi32 ") is negative.",
3053                                 scissor_i, scissor.offset.y);
3054             }
3055 
3056             const int64_t x_sum = static_cast<int64_t>(scissor.offset.x) + static_cast<int64_t>(scissor.extent.width);
3057             if (x_sum > INT32_MAX) {
3058                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3059                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-offset-02038",
3060                                 "vkCmdSetExclusiveScissorNV: offset.x + extent.width (=%" PRIi32 " + %" PRIu32 " = %" PRIi64
3061                                 ") of pScissors[%" PRIu32 "] will overflow int32_t.",
3062                                 scissor.offset.x, scissor.extent.width, x_sum, scissor_i);
3063             }
3064 
3065             const int64_t y_sum = static_cast<int64_t>(scissor.offset.y) + static_cast<int64_t>(scissor.extent.height);
3066             if (y_sum > INT32_MAX) {
3067                 skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3068                                 HandleToUint64(commandBuffer), "VUID-vkCmdSetExclusiveScissorNV-offset-02039",
3069                                 "vkCmdSetExclusiveScissorNV: offset.y + extent.height (=%" PRIi32 " + %" PRIu32 " = %" PRIi64
3070                                 ") of pScissors[%" PRIu32 "] will overflow int32_t.",
3071                                 scissor.offset.y, scissor.extent.height, y_sum, scissor_i);
3072             }
3073         }
3074     }
3075 
3076     return skip;
3077 }
3078 
manual_PreCallValidateCmdSetViewportShadingRatePaletteNV(VkCommandBuffer commandBuffer,uint32_t firstViewport,uint32_t viewportCount,const VkShadingRatePaletteNV * pShadingRatePalettes)3079 bool StatelessValidation::manual_PreCallValidateCmdSetViewportShadingRatePaletteNV(
3080     VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount,
3081     const VkShadingRatePaletteNV *pShadingRatePalettes) {
3082     bool skip = false;
3083 
3084     if (!physical_device_features.multiViewport) {
3085         if (firstViewport != 0) {
3086             skip |=
3087                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3088                         HandleToUint64(commandBuffer), "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02068",
3089                         "vkCmdSetViewportShadingRatePaletteNV: The multiViewport feature is disabled, but firstViewport (=%" PRIu32
3090                         ") is not 0.",
3091                         firstViewport);
3092         }
3093         if (viewportCount > 1) {
3094             skip |=
3095                 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3096                         HandleToUint64(commandBuffer), "VUID-vkCmdSetViewportShadingRatePaletteNV-viewportCount-02069",
3097                         "vkCmdSetViewportShadingRatePaletteNV: The multiViewport feature is disabled, but viewportCount (=%" PRIu32
3098                         ") is not 1.",
3099                         viewportCount);
3100         }
3101     }
3102 
3103     if (firstViewport >= device_limits.maxViewports) {
3104         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3105                         HandleToUint64(commandBuffer), "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02066",
3106                         "vkCmdSetViewportShadingRatePaletteNV: firstViewport (=%" PRIu32
3107                         ") must be less than maxViewports (=%" PRIu32 ").",
3108                         firstViewport, device_limits.maxViewports);
3109     }
3110 
3111     const uint64_t sum = static_cast<uint64_t>(firstViewport) + static_cast<uint64_t>(viewportCount);
3112     if (sum > device_limits.maxViewports) {
3113         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3114                         HandleToUint64(commandBuffer), "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02067",
3115                         "vkCmdSetViewportShadingRatePaletteNV: firstViewport + viewportCount (=%" PRIu32 " + %" PRIu32 " = %" PRIu64
3116                         ") is greater than VkPhysicalDeviceLimits::maxViewports (=%" PRIu32 ").",
3117                         firstViewport, viewportCount, sum, device_limits.maxViewports);
3118     }
3119 
3120     return skip;
3121 }
3122 
manual_PreCallValidateCmdSetCoarseSampleOrderNV(VkCommandBuffer commandBuffer,VkCoarseSampleOrderTypeNV sampleOrderType,uint32_t customSampleOrderCount,const VkCoarseSampleOrderCustomNV * pCustomSampleOrders)3123 bool StatelessValidation::manual_PreCallValidateCmdSetCoarseSampleOrderNV(VkCommandBuffer commandBuffer,
3124                                                                           VkCoarseSampleOrderTypeNV sampleOrderType,
3125                                                                           uint32_t customSampleOrderCount,
3126                                                                           const VkCoarseSampleOrderCustomNV *pCustomSampleOrders) {
3127     bool skip = false;
3128 
3129     if (sampleOrderType != VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV && customSampleOrderCount != 0) {
3130         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3131                         HandleToUint64(commandBuffer), "VUID-vkCmdSetCoarseSampleOrderNV-sampleOrderType-02081",
3132                         "vkCmdSetCoarseSampleOrderNV: If sampleOrderType is not VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV, "
3133                         "customSampleOrderCount must be 0.");
3134     }
3135 
3136     for (uint32_t order_i = 0; order_i < customSampleOrderCount; ++order_i) {
3137         skip |= ValidateCoarseSampleOrderCustomNV(&pCustomSampleOrders[order_i]);
3138     }
3139 
3140     return skip;
3141 }
3142 
manual_PreCallValidateCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer,uint32_t taskCount,uint32_t firstTask)3143 bool StatelessValidation::manual_PreCallValidateCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount,
3144                                                                    uint32_t firstTask) {
3145     bool skip = false;
3146 
3147     if (taskCount > phys_dev_ext_props.mesh_shader_props.maxDrawMeshTasksCount) {
3148         skip |= log_msg(
3149             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3150             HandleToUint64(commandBuffer), "VUID-vkCmdDrawMeshTasksNV-taskCount-02119",
3151             "vkCmdDrawMeshTasksNV() parameter, uint32_t taskCount (0x%" PRIxLEAST32
3152             "), must be less than or equal to VkPhysicalDeviceMeshShaderPropertiesNV::maxDrawMeshTasksCount (0x%" PRIxLEAST32 ").",
3153             taskCount, phys_dev_ext_props.mesh_shader_props.maxDrawMeshTasksCount);
3154     }
3155 
3156     return skip;
3157 }
3158 
manual_PreCallValidateCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)3159 bool StatelessValidation::manual_PreCallValidateCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer,
3160                                                                            VkDeviceSize offset, uint32_t drawCount,
3161                                                                            uint32_t stride) {
3162     bool skip = false;
3163     static const int condition_multiples = 0b0011;
3164     if (offset & condition_multiples) {
3165         skip |= log_msg(
3166             report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3167             HandleToUint64(commandBuffer), "VUID-vkCmdDrawMeshTasksIndirectNV-offset-02710",
3168             "vkCmdDrawMeshTasksIndirectNV() parameter, VkDeviceSize offset (0x%" PRIxLEAST64 "), is not a multiple of 4.", offset);
3169     }
3170     if (drawCount > 1 && ((stride & condition_multiples) || stride < sizeof(VkDrawMeshTasksIndirectCommandNV))) {
3171         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3172                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02146",
3173                         "vkCmdDrawMeshTasksIndirectNV() parameter, uint32_t stride (0x%" PRIxLEAST32
3174                         "), is not a multiple of 4 or smaller than sizeof (VkDrawMeshTasksIndirectCommandNV).",
3175                         stride);
3176     }
3177     if (!physical_device_features.multiDrawIndirect && ((drawCount > 1))) {
3178         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3179                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02718",
3180                         "vkCmdDrawMeshTasksIndirectNV(): Device feature multiDrawIndirect disabled: count must be 0 or 1 but is %d",
3181                         drawCount);
3182     }
3183 
3184     return skip;
3185 }
3186 
manual_PreCallValidateCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)3187 bool StatelessValidation::manual_PreCallValidateCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer,
3188                                                                                 VkDeviceSize offset, VkBuffer countBuffer,
3189                                                                                 VkDeviceSize countBufferOffset,
3190                                                                                 uint32_t maxDrawCount, uint32_t stride) {
3191     bool skip = false;
3192 
3193     if (offset & 3) {
3194         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3195                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawMeshTasksIndirectCountNV-offset-02710",
3196                         "vkCmdDrawMeshTasksIndirectCountNV() parameter, VkDeviceSize offset (0x%" PRIxLEAST64
3197                         "), is not a multiple of 4.",
3198                         offset);
3199     }
3200 
3201     if (countBufferOffset & 3) {
3202         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3203                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawMeshTasksIndirectCountNV-countBufferOffset-02716",
3204                         "vkCmdDrawMeshTasksIndirectCountNV() parameter, VkDeviceSize countBufferOffset (0x%" PRIxLEAST64
3205                         "), is not a multiple of 4.",
3206                         countBufferOffset);
3207     }
3208 
3209     return skip;
3210 }
3211 
manual_PreCallValidateCreateQueryPool(VkDevice device,const VkQueryPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkQueryPool * pQueryPool)3212 bool StatelessValidation::manual_PreCallValidateCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
3213                                                                 const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
3214     bool skip = false;
3215 
3216     // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
3217     if (pCreateInfo != nullptr) {
3218         // If queryType is VK_QUERY_TYPE_PIPELINE_STATISTICS, pipelineStatistics must be a valid combination of
3219         // VkQueryPipelineStatisticFlagBits values
3220         if ((pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) && (pCreateInfo->pipelineStatistics != 0) &&
3221             ((pCreateInfo->pipelineStatistics & (~AllVkQueryPipelineStatisticFlagBits)) != 0)) {
3222             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
3223                             "VUID-VkQueryPoolCreateInfo-queryType-00792",
3224                             "vkCreateQueryPool(): if pCreateInfo->queryType is VK_QUERY_TYPE_PIPELINE_STATISTICS, "
3225                             "pCreateInfo->pipelineStatistics must be a valid combination of VkQueryPipelineStatisticFlagBits "
3226                             "values.");
3227         }
3228     }
3229     return skip;
3230 }
3231 
manual_PreCallValidateEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)3232 bool StatelessValidation::manual_PreCallValidateEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
3233                                                                                    const char *pLayerName, uint32_t *pPropertyCount,
3234                                                                                    VkExtensionProperties *pProperties) {
3235     return validate_array("vkEnumerateDeviceExtensionProperties", "pPropertyCount", "pProperties", pPropertyCount, &pProperties,
3236                           true, false, false, kVUIDUndefined, "VUID-vkEnumerateDeviceExtensionProperties-pProperties-parameter");
3237 }
3238 
PostCallRecordCreateRenderPass(VkDevice device,const VkRenderPassCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass,VkResult result)3239 void StatelessValidation::PostCallRecordCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
3240                                                          const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass,
3241                                                          VkResult result) {
3242     if (result != VK_SUCCESS) return;
3243     RecordRenderPass(*pRenderPass, pCreateInfo);
3244 }
3245 
PostCallRecordCreateRenderPass2KHR(VkDevice device,const VkRenderPassCreateInfo2KHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass,VkResult result)3246 void StatelessValidation::PostCallRecordCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo,
3247                                                              const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass,
3248                                                              VkResult result) {
3249     // Track the state necessary for checking vkCreateGraphicsPipeline (subpass usage of depth and color attachments)
3250     if (result != VK_SUCCESS) return;
3251     RecordRenderPass(*pRenderPass, pCreateInfo);
3252 }
3253 
PostCallRecordDestroyRenderPass(VkDevice device,VkRenderPass renderPass,const VkAllocationCallbacks * pAllocator)3254 void StatelessValidation::PostCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
3255                                                           const VkAllocationCallbacks *pAllocator) {
3256     // Track the state necessary for checking vkCreateGraphicsPipeline (subpass usage of depth and color attachments)
3257     std::unique_lock<std::mutex> lock(renderpass_map_mutex);
3258     renderpasses_states.erase(renderPass);
3259 }
3260 
manual_PreCallValidateAllocateMemory(VkDevice device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMemory)3261 bool StatelessValidation::manual_PreCallValidateAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
3262                                                                const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
3263     bool skip = false;
3264 
3265     if (pAllocateInfo) {
3266         auto chained_prio_struct = lvl_find_in_chain<VkMemoryPriorityAllocateInfoEXT>(pAllocateInfo->pNext);
3267         if (chained_prio_struct && (chained_prio_struct->priority < 0.0f || chained_prio_struct->priority > 1.0f)) {
3268             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
3269                             "VUID-VkMemoryPriorityAllocateInfoEXT-priority-02602",
3270                             "priority (=%f) must be between `0` and `1`, inclusive.", chained_prio_struct->priority);
3271         }
3272     }
3273     return skip;
3274 }
3275 
ValidateGeometryTrianglesNV(const VkGeometryTrianglesNV & triangles,VkDebugReportObjectTypeEXT object_type,uint64_t object_handle,const char * func_name) const3276 bool StatelessValidation::ValidateGeometryTrianglesNV(const VkGeometryTrianglesNV &triangles,
3277                                                       VkDebugReportObjectTypeEXT object_type, uint64_t object_handle,
3278                                                       const char *func_name) const {
3279     bool skip = false;
3280 
3281     if (triangles.vertexFormat != VK_FORMAT_R32G32B32_SFLOAT && triangles.vertexFormat != VK_FORMAT_R16G16B16_SFLOAT &&
3282         triangles.vertexFormat != VK_FORMAT_R16G16B16_SNORM && triangles.vertexFormat != VK_FORMAT_R32G32_SFLOAT &&
3283         triangles.vertexFormat != VK_FORMAT_R16G16_SFLOAT && triangles.vertexFormat != VK_FORMAT_R16G16_SNORM) {
3284         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3285                         "VUID-VkGeometryTrianglesNV-vertexFormat-02430", "%s", func_name);
3286     } else {
3287         uint32_t vertex_component_size = 0;
3288         if (triangles.vertexFormat == VK_FORMAT_R32G32B32_SFLOAT || triangles.vertexFormat == VK_FORMAT_R32G32_SFLOAT) {
3289             vertex_component_size = 4;
3290         } else if (triangles.vertexFormat == VK_FORMAT_R16G16B16_SFLOAT || triangles.vertexFormat == VK_FORMAT_R16G16B16_SNORM ||
3291                    triangles.vertexFormat == VK_FORMAT_R16G16_SFLOAT || triangles.vertexFormat == VK_FORMAT_R16G16_SNORM) {
3292             vertex_component_size = 2;
3293         }
3294         if (vertex_component_size > 0 && SafeModulo(triangles.vertexOffset, vertex_component_size) != 0) {
3295             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3296                             "VUID-VkGeometryTrianglesNV-vertexOffset-02429", "%s", func_name);
3297         }
3298     }
3299 
3300     if (triangles.indexType != VK_INDEX_TYPE_UINT32 && triangles.indexType != VK_INDEX_TYPE_UINT16 &&
3301         triangles.indexType != VK_INDEX_TYPE_NONE_NV) {
3302         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3303                         "VUID-VkGeometryTrianglesNV-indexType-02433", "%s", func_name);
3304     } else {
3305         uint32_t index_element_size = 0;
3306         if (triangles.indexType == VK_INDEX_TYPE_UINT32) {
3307             index_element_size = 4;
3308         } else if (triangles.indexType == VK_INDEX_TYPE_UINT16) {
3309             index_element_size = 2;
3310         }
3311         if (index_element_size > 0 && SafeModulo(triangles.indexOffset, index_element_size) != 0) {
3312             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3313                             "VUID-VkGeometryTrianglesNV-indexOffset-02432", "%s", func_name);
3314         }
3315     }
3316     if (triangles.indexType == VK_INDEX_TYPE_NONE_NV) {
3317         if (triangles.indexCount != 0) {
3318             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3319                             "VUID-VkGeometryTrianglesNV-indexCount-02436", "%s", func_name);
3320         }
3321         if (triangles.indexData != VK_NULL_HANDLE) {
3322             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3323                             "VUID-VkGeometryTrianglesNV-indexData-02434", "%s", func_name);
3324         }
3325     }
3326 
3327     if (SafeModulo(triangles.transformOffset, 16) != 0) {
3328         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3329                         "VUID-VkGeometryTrianglesNV-transformOffset-02438", "%s", func_name);
3330     }
3331 
3332     return skip;
3333 }
3334 
ValidateGeometryAABBNV(const VkGeometryAABBNV & aabbs,VkDebugReportObjectTypeEXT object_type,uint64_t object_handle,const char * func_name) const3335 bool StatelessValidation::ValidateGeometryAABBNV(const VkGeometryAABBNV &aabbs, VkDebugReportObjectTypeEXT object_type,
3336                                                  uint64_t object_handle, const char *func_name) const {
3337     bool skip = false;
3338 
3339     if (SafeModulo(aabbs.offset, 8) != 0) {
3340         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3341                         "VUID-VkGeometryAABBNV-offset-02440", "%s", func_name);
3342     }
3343     if (SafeModulo(aabbs.stride, 8) != 0) {
3344         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3345                         "VUID-VkGeometryAABBNV-stride-02441", "%s", func_name);
3346     }
3347 
3348     return skip;
3349 }
3350 
ValidateGeometryNV(const VkGeometryNV & geometry,VkDebugReportObjectTypeEXT object_type,uint64_t object_handle,const char * func_name) const3351 bool StatelessValidation::ValidateGeometryNV(const VkGeometryNV &geometry, VkDebugReportObjectTypeEXT object_type,
3352                                              uint64_t object_handle, const char *func_name) const {
3353     bool skip = false;
3354     if (geometry.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_NV) {
3355         skip = ValidateGeometryTrianglesNV(geometry.geometry.triangles, object_type, object_handle, func_name);
3356     } else if (geometry.geometryType == VK_GEOMETRY_TYPE_AABBS_NV) {
3357         skip = ValidateGeometryAABBNV(geometry.geometry.aabbs, object_type, object_handle, func_name);
3358     }
3359     return skip;
3360 }
3361 
ValidateAccelerationStructureInfoNV(const VkAccelerationStructureInfoNV & info,VkDebugReportObjectTypeEXT object_type,uint64_t object_handle,const char * func_name) const3362 bool StatelessValidation::ValidateAccelerationStructureInfoNV(const VkAccelerationStructureInfoNV &info,
3363                                                               VkDebugReportObjectTypeEXT object_type, uint64_t object_handle,
3364                                                               const char *func_name) const {
3365     bool skip = false;
3366     if (info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV && info.geometryCount != 0) {
3367         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3368                         "VUID-VkAccelerationStructureInfoNV-type-02425",
3369                         "VkAccelerationStructureInfoNV: If type is VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV then "
3370                         "geometryCount must be 0.");
3371     }
3372     if (info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV && info.instanceCount != 0) {
3373         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3374                         "VUID-VkAccelerationStructureInfoNV-type-02426",
3375                         "VkAccelerationStructureInfoNV: If type is VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV then "
3376                         "instanceCount must be 0.");
3377     }
3378     if (info.flags & VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV &&
3379         info.flags & VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV) {
3380         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3381                         "VUID-VkAccelerationStructureInfoNV-flags-02592",
3382                         "VkAccelerationStructureInfoNV: If flags has the VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV"
3383                         "bit set, then it must not have the VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV bit set.");
3384     }
3385     if (info.geometryCount > phys_dev_ext_props.ray_tracing_props.maxGeometryCount) {
3386         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3387                         "VUID-VkAccelerationStructureInfoNV-geometryCount-02422",
3388                         "VkAccelerationStructureInfoNV: geometryCount must be less than or equal to "
3389                         "VkPhysicalDeviceRayTracingPropertiesNV::maxGeometryCount.");
3390     }
3391     if (info.instanceCount > phys_dev_ext_props.ray_tracing_props.maxInstanceCount) {
3392         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3393                         "VUID-VkAccelerationStructureInfoNV-instanceCount-02423",
3394                         "VkAccelerationStructureInfoNV: instanceCount must be less than or equal to "
3395                         "VkPhysicalDeviceRayTracingPropertiesNV::maxInstanceCount.");
3396     }
3397     if (info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV && info.geometryCount > 0) {
3398         uint64_t total_triangle_count = 0;
3399         for (uint32_t i = 0; i < info.geometryCount; i++) {
3400             const VkGeometryNV &geometry = info.pGeometries[i];
3401 
3402             skip |= ValidateGeometryNV(geometry, object_type, object_handle, func_name);
3403 
3404             if (geometry.geometryType != VK_GEOMETRY_TYPE_TRIANGLES_NV) {
3405                 continue;
3406             }
3407             total_triangle_count += geometry.geometry.triangles.indexCount / 3;
3408         }
3409         if (total_triangle_count > phys_dev_ext_props.ray_tracing_props.maxTriangleCount) {
3410             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle,
3411                             "VUID-VkAccelerationStructureInfoNV-maxTriangleCount-02424",
3412                             "VkAccelerationStructureInfoNV: The total number of triangles in all geometries must be less than "
3413                             "or equal to VkPhysicalDeviceRayTracingPropertiesNV::maxTriangleCount.");
3414         }
3415     }
3416     if (info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV && info.geometryCount > 1) {
3417         const VkGeometryTypeNV first_geometry_type = info.pGeometries[0].geometryType;
3418         for (uint32_t i = 1; i < info.geometryCount; i++) {
3419             const VkGeometryNV &geometry = info.pGeometries[i];
3420             if (geometry.geometryType != first_geometry_type) {
3421                 // TODO: update fake VUID below with the real one once it is generated.
3422                 skip |=
3423                     log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
3424                             0, "UNASSIGNED-VkAccelerationStructureInfoNV-pGeometries-XXXX",
3425                             "VkAccelerationStructureInfoNV: info.pGeometries[%d].geometryType does not match "
3426                             "info.pGeometries[0].geometryType.",
3427                             i);
3428             }
3429         }
3430     }
3431     return skip;
3432 }
3433 
manual_PreCallValidateCreateAccelerationStructureNV(VkDevice device,const VkAccelerationStructureCreateInfoNV * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkAccelerationStructureNV * pAccelerationStructure)3434 bool StatelessValidation::manual_PreCallValidateCreateAccelerationStructureNV(
3435     VkDevice device, const VkAccelerationStructureCreateInfoNV *pCreateInfo, const VkAllocationCallbacks *pAllocator,
3436     VkAccelerationStructureNV *pAccelerationStructure) {
3437     bool skip = false;
3438 
3439     if (pCreateInfo) {
3440         if ((pCreateInfo->compactedSize != 0) &&
3441             ((pCreateInfo->info.geometryCount != 0) || (pCreateInfo->info.instanceCount != 0))) {
3442             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
3443                             "VUID-VkAccelerationStructureCreateInfoNV-compactedSize-02421",
3444                             "vkCreateAccelerationStructureNV(): pCreateInfo->compactedSize nonzero (%" PRIu64
3445                             ") with info.geometryCount (%" PRIu32 ") or info.instanceCount (%" PRIu32 ") nonzero.",
3446                             pCreateInfo->compactedSize, pCreateInfo->info.geometryCount, pCreateInfo->info.instanceCount);
3447         }
3448 
3449         skip |= ValidateAccelerationStructureInfoNV(pCreateInfo->info, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT, 0,
3450                                                     "vkCreateAccelerationStructureNV()");
3451     }
3452 
3453     return skip;
3454 }
3455 
manual_PreCallValidateCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,const VkAccelerationStructureInfoNV * pInfo,VkBuffer instanceData,VkDeviceSize instanceOffset,VkBool32 update,VkAccelerationStructureNV dst,VkAccelerationStructureNV src,VkBuffer scratch,VkDeviceSize scratchOffset)3456 bool StatelessValidation::manual_PreCallValidateCmdBuildAccelerationStructureNV(
3457     VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset,
3458     VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset) {
3459     bool skip = false;
3460 
3461     if (pInfo != nullptr) {
3462         skip |= ValidateAccelerationStructureInfoNV(*pInfo, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
3463                                                     HandleToUint64(dst), "vkCmdBuildAccelerationStructureNV()");
3464     }
3465 
3466     return skip;
3467 }
3468 
manual_PreCallValidateGetAccelerationStructureHandleNV(VkDevice device,VkAccelerationStructureNV accelerationStructure,size_t dataSize,void * pData)3469 bool StatelessValidation::manual_PreCallValidateGetAccelerationStructureHandleNV(VkDevice device,
3470                                                                                  VkAccelerationStructureNV accelerationStructure,
3471                                                                                  size_t dataSize, void *pData) {
3472     bool skip = false;
3473     if (dataSize < 8) {
3474         skip = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
3475                        HandleToUint64(accelerationStructure), "VUID-vkGetAccelerationStructureHandleNV-dataSize-02240",
3476                        "vkGetAccelerationStructureHandleNV(): dataSize must be greater than or equal to 8.");
3477     }
3478     return skip;
3479 }
3480 
manual_PreCallValidateCreateRayTracingPipelinesNV(VkDevice device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkRayTracingPipelineCreateInfoNV * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)3481 bool StatelessValidation::manual_PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache,
3482                                                                             uint32_t createInfoCount,
3483                                                                             const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
3484                                                                             const VkAllocationCallbacks *pAllocator,
3485                                                                             VkPipeline *pPipelines) {
3486     bool skip = false;
3487 
3488     for (uint32_t i = 0; i < createInfoCount; i++) {
3489         auto feedback_struct = lvl_find_in_chain<VkPipelineCreationFeedbackCreateInfoEXT>(pCreateInfos[i].pNext);
3490         if ((feedback_struct != nullptr) && (feedback_struct->pipelineStageCreationFeedbackCount != pCreateInfos[i].stageCount)) {
3491             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, VK_NULL_HANDLE,
3492                             "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02670",
3493                             "vkCreateRayTracingPipelinesNV(): in pCreateInfo[%" PRIu32
3494                             "], VkPipelineCreationFeedbackEXT::pipelineStageCreationFeedbackCount"
3495                             "(=%" PRIu32 ") must equal VkRayTracingPipelineCreateInfoNV::stageCount(=%" PRIu32 ").",
3496                             i, feedback_struct->pipelineStageCreationFeedbackCount, pCreateInfos[i].stageCount);
3497         }
3498     }
3499 
3500     return skip;
3501 }
3502 
3503 #ifdef VK_USE_PLATFORM_WIN32_KHR
PreCallValidateGetDeviceGroupSurfacePresentModes2EXT(VkDevice device,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkDeviceGroupPresentModeFlagsKHR * pModes)3504 bool StatelessValidation::PreCallValidateGetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
3505                                                                                const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
3506                                                                                VkDeviceGroupPresentModeFlagsKHR *pModes) {
3507     bool skip = false;
3508     if (!device_extensions.vk_khr_swapchain)
3509         skip |= OutputExtensionError("vkGetDeviceGroupSurfacePresentModes2EXT", VK_KHR_SWAPCHAIN_EXTENSION_NAME);
3510     if (!device_extensions.vk_khr_get_surface_capabilities_2)
3511         skip |= OutputExtensionError("vkGetDeviceGroupSurfacePresentModes2EXT", VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
3512     if (!device_extensions.vk_khr_surface)
3513         skip |= OutputExtensionError("vkGetDeviceGroupSurfacePresentModes2EXT", VK_KHR_SURFACE_EXTENSION_NAME);
3514     if (!device_extensions.vk_khr_get_physical_device_properties_2)
3515         skip |=
3516             OutputExtensionError("vkGetDeviceGroupSurfacePresentModes2EXT", VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3517     if (!device_extensions.vk_ext_full_screen_exclusive)
3518         skip |= OutputExtensionError("vkGetDeviceGroupSurfacePresentModes2EXT", VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME);
3519     skip |= validate_struct_type(
3520         "vkGetDeviceGroupSurfacePresentModes2EXT", "pSurfaceInfo", "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR",
3521         pSurfaceInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, true,
3522         "VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter", "VUID-VkPhysicalDeviceSurfaceInfo2KHR-sType-sType");
3523     if (pSurfaceInfo != NULL) {
3524         const VkStructureType allowed_structs_VkPhysicalDeviceSurfaceInfo2KHR[] = {
3525             VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT,
3526             VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT};
3527 
3528         skip |= validate_struct_pnext("vkGetDeviceGroupSurfacePresentModes2EXT", "pSurfaceInfo->pNext",
3529                                       "VkSurfaceFullScreenExclusiveInfoEXT, VkSurfaceFullScreenExclusiveWin32InfoEXT",
3530                                       pSurfaceInfo->pNext, ARRAY_SIZE(allowed_structs_VkPhysicalDeviceSurfaceInfo2KHR),
3531                                       allowed_structs_VkPhysicalDeviceSurfaceInfo2KHR, GeneratedVulkanHeaderVersion,
3532                                       "VUID-VkPhysicalDeviceSurfaceInfo2KHR-pNext-pNext");
3533 
3534         skip |= validate_required_handle("vkGetDeviceGroupSurfacePresentModes2EXT", "pSurfaceInfo->surface", pSurfaceInfo->surface);
3535     }
3536     return skip;
3537 }
3538 #endif
3539 
manual_PreCallValidateCreateFramebuffer(VkDevice device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * pFramebuffer)3540 bool StatelessValidation::manual_PreCallValidateCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
3541                                                                   const VkAllocationCallbacks *pAllocator,
3542                                                                   VkFramebuffer *pFramebuffer) {
3543     // Validation for pAttachments which is excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
3544     bool skip = false;
3545     if ((pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR) == 0) {
3546         skip |= validate_array("vkCreateFramebuffer", "attachmentCount", "pAttachments", pCreateInfo->attachmentCount,
3547                                &pCreateInfo->pAttachments, false, true, kVUIDUndefined, kVUIDUndefined);
3548     }
3549     return skip;
3550 }
3551 
manual_PreCallValidateCmdSetLineStippleEXT(VkCommandBuffer commandBuffer,uint32_t lineStippleFactor,uint16_t lineStipplePattern)3552 bool StatelessValidation::manual_PreCallValidateCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
3553                                                                      uint16_t lineStipplePattern) {
3554     bool skip = false;
3555 
3556     if (lineStippleFactor < 1 || lineStippleFactor > 256) {
3557         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3558                         HandleToUint64(commandBuffer), "VUID-vkCmdSetLineStippleEXT-lineStippleFactor-02776",
3559                         "vkCmdSetLineStippleEXT::lineStippleFactor=%d is not in [1,256].", lineStippleFactor);
3560     }
3561 
3562     return skip;
3563 }
3564 
manual_PreCallValidateCmdBindIndexBuffer(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkIndexType indexType)3565 bool StatelessValidation::manual_PreCallValidateCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer,
3566                                                                    VkDeviceSize offset, VkIndexType indexType) {
3567     bool skip = false;
3568 
3569     if (indexType == VK_INDEX_TYPE_NONE_NV) {
3570         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3571                         HandleToUint64(commandBuffer), "VUID-vkCmdBindIndexBuffer-indexType-02507",
3572                         "vkCmdBindIndexBuffer() indexType must not be VK_INDEX_TYPE_NONE_NV.");
3573     }
3574 
3575     const auto *index_type_uint8_features =
3576         lvl_find_in_chain<VkPhysicalDeviceIndexTypeUint8FeaturesEXT>(physical_device_features2.pNext);
3577     if (indexType == VK_INDEX_TYPE_UINT8_EXT && !index_type_uint8_features->indexTypeUint8) {
3578         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3579                         HandleToUint64(commandBuffer), "VUID-vkCmdBindIndexBuffer-indexType-02765",
3580                         "vkCmdBindIndexBuffer() indexType is VK_INDEX_TYPE_UINT8_EXT but indexTypeUint8 feature is not enabled.");
3581     }
3582 
3583     return skip;
3584 }
3585