Destroy/free objects when configuration fails. Prior to this, we were leaking objects after failing to configure them. The sole exception was `VkDescriptorSet`; failed descriptor sets are automatically returned to the pool. Now all objects are destroyed or freed when creation fails.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm index fb20ebf..7e8d55a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
@@ -59,7 +59,10 @@ // Command buffers start out in a VK_NOT_READY config result VkResult cbRslt = mvkCmdBuff->getConfigurationResult(); - if (rslt == VK_SUCCESS && cbRslt != VK_NOT_READY) { rslt = cbRslt; } + if (cbRslt != VK_NOT_READY) { + if (rslt == VK_SUCCESS) { rslt = cbRslt; } + freeCommandBuffers(1, &pCmdBuffer[cbIdx]); + } } return rslt; }
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index f0e1824..1fecb88 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -174,6 +174,7 @@ MVKInstance* mvkInst = new MVKInstance(pCreateInfo); *pInstance = mvkInst->getVkInstance(); VkResult rslt = mvkInst->getConfigurationResult(); + if (rslt < 0) { *pInstance = nullptr; mvkInst->destroy(); } MVKTraceVulkanCallEnd(); return rslt; } @@ -313,6 +314,7 @@ MVKDevice* mvkDev = new MVKDevice(mvkPD, pCreateInfo); *pDevice = mvkDev->getVkDevice(); VkResult rslt = mvkDev->getConfigurationResult(); + if (rslt < 0) { *pDevice = nullptr; mvkDev->destroy(); } MVKTraceVulkanCallEnd(); return rslt; } @@ -428,6 +430,7 @@ MVKDeviceMemory* mvkMem = mvkDev->allocateMemory(pAllocateInfo, pAllocator); VkResult rslt = mvkMem->getConfigurationResult(); *pMem = (VkDeviceMemory)((rslt == VK_SUCCESS) ? mvkMem : VK_NULL_HANDLE); + if (rslt != VK_SUCCESS) { mvkDev->freeMemory(mvkMem, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -618,6 +621,7 @@ MVKFence* mvkFence = mvkDev->createFence(pCreateInfo, pAllocator); *pFence = (VkFence)mvkFence; VkResult rslt = mvkFence->getConfigurationResult(); + if (rslt < 0) { *pFence = VK_NULL_HANDLE; mvkDev->destroyFence(mvkFence, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -680,6 +684,7 @@ MVKSemaphore* mvkSem4 = mvkDev->createSemaphore(pCreateInfo, pAllocator); *pSemaphore = (VkSemaphore)mvkSem4; VkResult rslt = mvkSem4->getConfigurationResult(); + if (rslt < 0) { *pSemaphore = VK_NULL_HANDLE; mvkDev->destroySemaphore(mvkSem4, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -706,6 +711,7 @@ MVKEvent* mvkEvent = mvkDev->createEvent(pCreateInfo, pAllocator); *pEvent = (VkEvent)mvkEvent; VkResult rslt = mvkEvent->getConfigurationResult(); + if (rslt < 0) { *pEvent = VK_NULL_HANDLE; mvkDev->destroyEvent(mvkEvent, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -765,6 +771,7 @@ MVKQueryPool* mvkQP = mvkDev->createQueryPool(pCreateInfo, pAllocator); *pQueryPool = (VkQueryPool)mvkQP; VkResult rslt = mvkQP->getConfigurationResult(); + if (rslt < 0) { *pQueryPool = VK_NULL_HANDLE; mvkDev->destroyQueryPool(mvkQP, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -808,6 +815,7 @@ MVKBuffer* mvkBuff = mvkDev->createBuffer(pCreateInfo, pAllocator); *pBuffer = (VkBuffer)mvkBuff; VkResult rslt = mvkBuff->getConfigurationResult(); + if (rslt < 0) { *pBuffer = VK_NULL_HANDLE; mvkDev->destroyBuffer(mvkBuff, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -834,6 +842,7 @@ MVKBufferView* mvkBuffView = mvkDev->createBufferView(pCreateInfo, pAllocator); *pView = (VkBufferView)mvkBuffView; VkResult rslt = mvkBuffView->getConfigurationResult(); + if (rslt < 0) { *pView = VK_NULL_HANDLE; mvkDev->destroyBufferView(mvkBuffView, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -860,6 +869,7 @@ MVKImage* mvkImg = mvkDev->createImage(pCreateInfo, pAllocator); *pImage = (VkImage)mvkImg; VkResult rslt = mvkImg->getConfigurationResult(); + if (rslt < 0) { *pImage = VK_NULL_HANDLE; mvkDev->destroyImage(mvkImg, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -898,6 +908,7 @@ MVKImageView* mvkImgView = mvkDev->createImageView(pCreateInfo, pAllocator); *pView = (VkImageView)mvkImgView; VkResult rslt = mvkImgView->getConfigurationResult(); + if (rslt < 0) { *pView = VK_NULL_HANDLE; mvkDev->destroyImageView(mvkImgView, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -924,6 +935,7 @@ MVKShaderModule* mvkShdrMod = mvkDev->createShaderModule(pCreateInfo, pAllocator); *pShaderModule = (VkShaderModule)mvkShdrMod; VkResult rslt = mvkShdrMod->getConfigurationResult(); + if (rslt < 0) { *pShaderModule = VK_NULL_HANDLE; mvkDev->destroyShaderModule(mvkShdrMod, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -950,6 +962,7 @@ MVKPipelineCache* mvkPLC = mvkDev->createPipelineCache(pCreateInfo, pAllocator); *pPipelineCache = (VkPipelineCache)mvkPLC; VkResult rslt = mvkPLC->getConfigurationResult(); + if (rslt < 0) { *pPipelineCache = VK_NULL_HANDLE; mvkDev->destroyPipelineCache(mvkPLC, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1043,6 +1056,7 @@ MVKPipelineLayout* mvkPLL = mvkDev->createPipelineLayout(pCreateInfo, pAllocator); *pPipelineLayout = (VkPipelineLayout)mvkPLL; VkResult rslt = mvkPLL->getConfigurationResult(); + if (rslt < 0) { *pPipelineLayout = VK_NULL_HANDLE; mvkDev->destroyPipelineLayout(mvkPLL, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1069,6 +1083,7 @@ MVKSampler* mvkSamp = mvkDev->createSampler(pCreateInfo, pAllocator); *pSampler = (VkSampler)mvkSamp; VkResult rslt = mvkSamp->getConfigurationResult(); + if (rslt < 0) { *pSampler = VK_NULL_HANDLE; mvkDev->destroySampler(mvkSamp, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1095,6 +1110,7 @@ MVKDescriptorSetLayout* mvkDSL = mvkDev->createDescriptorSetLayout(pCreateInfo, pAllocator); *pSetLayout = (VkDescriptorSetLayout)mvkDSL; VkResult rslt = mvkDSL->getConfigurationResult(); + if (rslt < 0) { *pSetLayout = VK_NULL_HANDLE; mvkDev->destroyDescriptorSetLayout(mvkDSL, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1121,6 +1137,7 @@ MVKDescriptorPool* mvkDP = mvkDev->createDescriptorPool(pCreateInfo, pAllocator); *pDescriptorPool = (VkDescriptorPool)mvkDP; VkResult rslt = mvkDP->getConfigurationResult(); + if (rslt < 0) { *pDescriptorPool = VK_NULL_HANDLE; mvkDev->destroyDescriptorPool(mvkDP, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1198,6 +1215,7 @@ MVKFramebuffer* mvkFB = mvkDev->createFramebuffer(pCreateInfo, pAllocator); *pFramebuffer = (VkFramebuffer)mvkFB; VkResult rslt = mvkFB->getConfigurationResult(); + if (rslt < 0) { *pFramebuffer = VK_NULL_HANDLE; mvkDev->destroyFramebuffer(mvkFB, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1224,6 +1242,7 @@ MVKRenderPass* mvkRendPass = mvkDev->createRenderPass(pCreateInfo, pAllocator); *pRenderPass = (VkRenderPass)mvkRendPass; VkResult rslt = mvkRendPass->getConfigurationResult(); + if (rslt < 0) { *pRenderPass = VK_NULL_HANDLE; mvkDev->destroyRenderPass(mvkRendPass, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -1261,6 +1280,7 @@ MVKCommandPool* mvkCmdPool = mvkDev->createCommandPool(pCreateInfo, pAllocator); *pCmdPool = (VkCommandPool)mvkCmdPool; VkResult rslt = mvkCmdPool->getConfigurationResult(); + if (rslt < 0) { *pCmdPool = VK_NULL_HANDLE; mvkDev->destroyCommandPool(mvkCmdPool, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -2146,6 +2166,10 @@ pAllocator); *pDescriptorUpdateTemplate = (VkDescriptorUpdateTemplate)mvkDUT; VkResult rslt = mvkDUT->getConfigurationResult(); + if (rslt < 0) { + *pDescriptorUpdateTemplate = VK_NULL_HANDLE; + mvkDev->destroyDescriptorUpdateTemplate(mvkDUT, pAllocator); + } MVKTraceVulkanCallEnd(); return rslt; } @@ -2194,6 +2218,10 @@ MVKSamplerYcbcrConversion* mvkSampConv = mvkDev->createSamplerYcbcrConversion(pCreateInfo, pAllocator); *pYcbcrConversion = (VkSamplerYcbcrConversion)mvkSampConv; VkResult rslt = mvkSampConv->getConfigurationResult(); + if (rslt < 0) { + *pYcbcrConversion = VK_NULL_HANDLE; + mvkDev->destroySamplerYcbcrConversion(mvkSampConv, pAllocator); + } MVKTraceVulkanCallEnd(); return rslt; } @@ -2267,6 +2295,7 @@ MVKRenderPass* mvkRendPass = mvkDev->createRenderPass(pCreateInfo, pAllocator); *pRenderPass = (VkRenderPass)mvkRendPass; VkResult rslt = mvkRendPass->getConfigurationResult(); + if (rslt < 0) { *pRenderPass = VK_NULL_HANDLE; mvkDev->destroyRenderPass(mvkRendPass, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -2423,6 +2452,7 @@ MVKSwapchain* mvkSwpChn = mvkDev->createSwapchain(pCreateInfo, pAllocator); *pSwapchain = (VkSwapchainKHR)(mvkSwpChn); VkResult rslt = mvkSwpChn->getConfigurationResult(); + if (rslt < 0) { *pSwapchain = VK_NULL_HANDLE; mvkDev->destroySwapchain(mvkSwpChn, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -2647,6 +2677,7 @@ MVKDebugReportCallback* mvkDRCB = mvkInst->createDebugReportCallback(pCreateInfo, pAllocator); *pCallback = (VkDebugReportCallbackEXT)mvkDRCB; VkResult rslt = mvkDRCB->getConfigurationResult(); + if (rslt < 0) { *pCallback = VK_NULL_HANDLE; mvkInst->destroyDebugReportCallback(mvkDRCB, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -2814,6 +2845,7 @@ MVKDebugUtilsMessenger* mvkDUM = mvkInst->createDebugUtilsMessenger(pCreateInfo, pAllocator); *pMessenger = (VkDebugUtilsMessengerEXT)mvkDUM; VkResult rslt = mvkDUM->getConfigurationResult(); + if (rslt < 0) { *pMessenger = VK_NULL_HANDLE; mvkInst->destroyDebugUtilsMessenger(mvkDUM, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -2890,6 +2922,7 @@ MVKSurface* mvkSrfc = mvkInst->createSurface(pCreateInfo, pAllocator); *pSurface = (VkSurfaceKHR)mvkSrfc; VkResult rslt = mvkSrfc->getConfigurationResult(); + if (rslt < 0) { *pSurface = VK_NULL_HANDLE; mvkInst->destroySurface(mvkSrfc, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; } @@ -2934,6 +2967,7 @@ MVKSurface* mvkSrfc = mvkInst->createSurface(pCreateInfo, pAllocator); *pSurface = (VkSurfaceKHR)mvkSrfc; VkResult rslt = mvkSrfc->getConfigurationResult(); + if (rslt < 0) { *pSurface = VK_NULL_HANDLE; mvkInst->destroySurface(mvkSrfc, pAllocator); } MVKTraceVulkanCallEnd(); return rslt; }