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