| 320 | } |
| 321 | |
| 322 | VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo* pCreateInfo, |
| 323 | const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) { |
| 324 | VkLayerDeviceCreateInfo* chain_info = GetChainInfo(pCreateInfo, VK_LAYER_LINK_INFO); |
| 325 | |
| 326 | auto instance_dispatch = vvl::GetDispatchInstance(gpu); |
| 327 | |
| 328 | PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; |
| 329 | PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; |
| 330 | PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_dispatch->instance, "vkCreateDevice"); |
| 331 | if (fpCreateDevice == nullptr) { |
| 332 | return VK_ERROR_INITIALIZATION_FAILED; |
| 333 | } |
| 334 | chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; |
| 335 | |
| 336 | // use a unique pointer to make sure we destroy this object on error |
| 337 | auto device_dispatch = std::make_unique<vvl::DispatchDevice>(instance_dispatch, gpu, pCreateInfo); |
| 338 | |
| 339 | // This is odd but we need to set the current extensions in all of the |
| 340 | // instance validation objects so that they are available for validating CreateDevice |
| 341 | for (auto& vo : instance_dispatch->object_dispatch) { |
| 342 | if (!vo) { |
| 343 | continue; |
| 344 | } |
| 345 | vo->extensions = device_dispatch->extensions; |
| 346 | } |
| 347 | |
| 348 | bool skip = false; |
| 349 | ErrorObject error_obj(vvl::Func::vkCreateDevice, VulkanTypedHandle(gpu, kVulkanObjectTypePhysicalDevice)); |
| 350 | for (const auto& vo : instance_dispatch->object_dispatch) { |
| 351 | if (!vo) { |
| 352 | continue; |
| 353 | } |
| 354 | skip |= vo->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, error_obj); |
| 355 | if (skip) { |
| 356 | return VK_ERROR_VALIDATION_FAILED_EXT; |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | // Make copy to modify as some ValidationObjects will want to add extensions/features on |
| 361 | // After PreCallValidate incase it is invalid |
| 362 | vku::safe_VkDeviceCreateInfo modified_create_info(pCreateInfo); |
| 363 | |
| 364 | RecordObject record_obj(vvl::Func::vkCreateDevice); |
| 365 | for (auto& vo : instance_dispatch->object_dispatch) { |
| 366 | if (!vo) { |
| 367 | continue; |
| 368 | } |
| 369 | vo->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice, record_obj, &modified_create_info); |
| 370 | } |
| 371 | |
| 372 | VkResult result = fpCreateDevice(gpu, reinterpret_cast<VkDeviceCreateInfo*>(&modified_create_info), pAllocator, pDevice); |
| 373 | |
| 374 | if (result != VK_SUCCESS) { |
| 375 | // From https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/10472 |
| 376 | // While it is not invalid to have unsupported features, we use this time to help the developer bisect what they added that |
| 377 | // caused the error from the driver |
| 378 | // |
| 379 | // Note that VK_ERROR_EXTENSION_NOT_PRESENT will be validated and reported in the Vulkan-Loader |
nothing calls this directly
no test coverage detected