From e36a671537037465c6eb2269a5838e192ddefd61 Mon Sep 17 00:00:00 2001 From: Rob Hughes Date: Mon, 14 Sep 2026 14:06:04 +0100 Subject: [PATCH] Fix application info and device creation cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [AI-generated 🤖] Accept omitted application info and treat API version zero as Vulkan 1.0. Create application info in the owned safe copy before version promotion, without modifying the caller's input. If Device construction or publication fails after the Vulkan device has been created, release the tracking lock, clean up the underlying device with the original allocator, and clear the output handle. Translate allocation failures to VK_ERROR_OUT_OF_HOST_MEMORY and other exceptions to VK_ERROR_INITIALIZATION_FAILED. --- source_common/framework/manual_functions.cpp | 54 +++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/source_common/framework/manual_functions.cpp b/source_common/framework/manual_functions.cpp index a7bcbe6..ac5e210 100644 --- a/source_common/framework/manual_functions.cpp +++ b/source_common/framework/manual_functions.cpp @@ -30,6 +30,7 @@ * implementations on a per-layer basis if needed. */ #include +#include #include #include #include @@ -226,7 +227,11 @@ APIVersion getInstanceAPIVersion(PFN_vkGetInstanceProcAddr fpGetProcAddr) /* See header for documentation. */ APIVersion getApplicationAPIVersion(const VkInstanceCreateInfo* pCreateInfo) { - uint32_t apiVersion = pCreateInfo->pApplicationInfo->apiVersion; + uint32_t apiVersion = pCreateInfo->pApplicationInfo ? pCreateInfo->pApplicationInfo->apiVersion : 0; + if (apiVersion == 0) + { + apiVersion = VK_API_VERSION_1_0; + } uint32_t major = VK_API_VERSION_MAJOR(apiVersion); uint32_t minor = VK_API_VERSION_MINOR(apiVersion); return {major, minor}; @@ -988,7 +993,11 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance(const VkInsta vku::safe_VkInstanceCreateInfo safeCreateInfo(pCreateInfo); auto* newCreateInfo = reinterpret_cast(&safeCreateInfo); - // Patch updated application info + // Patch only the owned copy; Vulkan permits the application info to be absent. + if (!safeCreateInfo.pApplicationInfo) + { + safeCreateInfo.pApplicationInfo = new vku::safe_VkApplicationInfo(); + } safeCreateInfo.pApplicationInfo->apiVersion = VK_MAKE_API_VERSION(0, newVersion.first, newVersion.second, 0); // Enable extra extensions @@ -1115,13 +1124,44 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDevice(VkPhysicalDevic return res; } - auto device = std::make_unique(layer, physicalDevice, *pDevice, fpGetDeviceProcAddr, *newCreateInfo); + std::unique_ptr device; + VkResult publicationResult = VK_SUCCESS; + try + { + device = std::make_unique(layer, physicalDevice, *pDevice, fpGetDeviceProcAddr, *newCreateInfo); - // Retake the lock to access layer-wide global store - lock.lock(); - Device::store(*pDevice, std::move(device)); + // Retake the lock to access layer-wide global store. + lock.lock(); + Device::store(*pDevice, std::move(device)); + return VK_SUCCESS; + } + catch (const std::bad_alloc&) + { + publicationResult = VK_ERROR_OUT_OF_HOST_MEMORY; + } + catch (...) + { + publicationResult = VK_ERROR_INITIALIZATION_FAILED; + } - return VK_SUCCESS; + // The downstream device exists, but no usable layer device was published. + // Release local state and call the driver without holding the tracking lock. + if (lock.owns_lock()) + { + lock.unlock(); + } + device.reset(); + auto fpDestroyDevice = reinterpret_cast(fpGetDeviceProcAddr(*pDevice, "vkDestroyDevice")); + if (fpDestroyDevice) + { + fpDestroyDevice(*pDevice, pAllocator); + } + else + { + LAYER_ERR("Cannot destroy an unpublished device: vkDestroyDevice is unavailable"); + } + *pDevice = VK_NULL_HANDLE; + return publicationResult; } /* See Vulkan API for documentation. */