| // Copyright 2017 The Dawn & Tint Authors | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // 1. Redistributions of source code must retain the above copyright notice, this | |
| // list of conditions and the following disclaimer. | |
| // | |
| // 2. Redistributions in binary form must reproduce the above copyright notice, | |
| // this list of conditions and the following disclaimer in the documentation | |
| // and/or other materials provided with the distribution. | |
| // | |
| // 3. Neither the name of the copyright holder nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #include "dawn/native/vulkan/FencedDeleter.h" | |
| #include "dawn/native/Queue.h" | |
| #include "dawn/native/vulkan/DeviceVk.h" | |
| namespace dawn::native::vulkan { | |
| FencedDeleter::FencedDeleter(Device* device) : mDevice(device) {} | |
| FencedDeleter::~FencedDeleter() { | |
| DAWN_ASSERT(mBuffersToDelete.Empty()); | |
| DAWN_ASSERT(mDescriptorPoolsToDelete.Empty()); | |
| DAWN_ASSERT(mFencesToDelete.Empty()); | |
| DAWN_ASSERT(mFramebuffersToDelete.Empty()); | |
| DAWN_ASSERT(mImagesToDelete.Empty()); | |
| DAWN_ASSERT(mImageViewsToDelete.Empty()); | |
| DAWN_ASSERT(mMemoriesToDelete.Empty()); | |
| DAWN_ASSERT(mPipelinesToDelete.Empty()); | |
| DAWN_ASSERT(mPipelineLayoutsToDelete.Empty()); | |
| DAWN_ASSERT(mQueryPoolsToDelete.Empty()); | |
| DAWN_ASSERT(mRenderPassesToDelete.Empty()); | |
| DAWN_ASSERT(mSamplerYcbcrConversionsToDelete.Empty()); | |
| DAWN_ASSERT(mSamplersToDelete.Empty()); | |
| DAWN_ASSERT(mSemaphoresToDelete.Empty()); | |
| DAWN_ASSERT(mShaderModulesToDelete.Empty()); | |
| DAWN_ASSERT(mSurfacesToDelete.Empty()); | |
| DAWN_ASSERT(mSwapChainsToDelete.Empty()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkBuffer buffer) { | |
| mBuffersToDelete.Enqueue(buffer, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkDescriptorPool pool) { | |
| mDescriptorPoolsToDelete.Enqueue(pool, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkDeviceMemory memory) { | |
| mMemoriesToDelete.Enqueue(memory, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkFence fence) { | |
| mFencesToDelete.Enqueue(fence, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkFramebuffer framebuffer) { | |
| mFramebuffersToDelete.Enqueue(framebuffer, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkImage image) { | |
| mImagesToDelete.Enqueue(image, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkImageView view) { | |
| mImageViewsToDelete.Enqueue(view, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkPipeline pipeline) { | |
| mPipelinesToDelete.Enqueue(pipeline, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkPipelineLayout layout) { | |
| mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkQueryPool querypool) { | |
| mQueryPoolsToDelete.Enqueue(querypool, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkRenderPass renderPass) { | |
| mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkSamplerYcbcrConversion samplerYcbcrConversion) { | |
| mSamplerYcbcrConversionsToDelete.Enqueue(samplerYcbcrConversion, | |
| mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkSampler sampler) { | |
| mSamplersToDelete.Enqueue(sampler, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkSemaphore semaphore) { | |
| mSemaphoresToDelete.Enqueue(semaphore, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkShaderModule module) { | |
| mShaderModulesToDelete.Enqueue(module, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkSurfaceKHR surface) { | |
| mSurfacesToDelete.Enqueue(surface, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::DeleteWhenUnused(VkSwapchainKHR swapChain) { | |
| mSwapChainsToDelete.Enqueue(swapChain, mDevice->GetQueue()->GetPendingCommandSerial()); | |
| } | |
| void FencedDeleter::Tick(ExecutionSerial completedSerial) { | |
| VkDevice vkDevice = mDevice->GetVkDevice(); | |
| VkInstance instance = mDevice->GetVkInstance(); | |
| // Buffers and images must be deleted before memories because it is invalid to free memory | |
| // that still have resources bound to it. | |
| for (VkBuffer buffer : mBuffersToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyBuffer(vkDevice, buffer, nullptr); | |
| } | |
| mBuffersToDelete.ClearUpTo(completedSerial); | |
| for (VkImage image : mImagesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyImage(vkDevice, image, nullptr); | |
| } | |
| mImagesToDelete.ClearUpTo(completedSerial); | |
| for (VkDeviceMemory memory : mMemoriesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.FreeMemory(vkDevice, memory, nullptr); | |
| } | |
| mMemoriesToDelete.ClearUpTo(completedSerial); | |
| for (VkPipelineLayout layout : mPipelineLayoutsToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyPipelineLayout(vkDevice, layout, nullptr); | |
| } | |
| mPipelineLayoutsToDelete.ClearUpTo(completedSerial); | |
| for (VkRenderPass renderPass : mRenderPassesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyRenderPass(vkDevice, renderPass, nullptr); | |
| } | |
| mRenderPassesToDelete.ClearUpTo(completedSerial); | |
| for (VkFence fence : mFencesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyFence(vkDevice, fence, nullptr); | |
| } | |
| mFencesToDelete.ClearUpTo(completedSerial); | |
| for (VkFramebuffer framebuffer : mFramebuffersToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyFramebuffer(vkDevice, framebuffer, nullptr); | |
| } | |
| mFramebuffersToDelete.ClearUpTo(completedSerial); | |
| for (VkImageView view : mImageViewsToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyImageView(vkDevice, view, nullptr); | |
| } | |
| mImageViewsToDelete.ClearUpTo(completedSerial); | |
| for (VkShaderModule module : mShaderModulesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyShaderModule(vkDevice, module, nullptr); | |
| } | |
| mShaderModulesToDelete.ClearUpTo(completedSerial); | |
| for (VkPipeline pipeline : mPipelinesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyPipeline(vkDevice, pipeline, nullptr); | |
| } | |
| mPipelinesToDelete.ClearUpTo(completedSerial); | |
| // Vulkan swapchains must be destroyed before their corresponding VkSurface | |
| for (VkSwapchainKHR swapChain : mSwapChainsToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroySwapchainKHR(vkDevice, swapChain, nullptr); | |
| } | |
| mSwapChainsToDelete.ClearUpTo(completedSerial); | |
| for (VkSurfaceKHR surface : mSurfacesToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroySurfaceKHR(instance, surface, nullptr); | |
| } | |
| mSurfacesToDelete.ClearUpTo(completedSerial); | |
| for (VkSemaphore semaphore : mSemaphoresToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroySemaphore(vkDevice, semaphore, nullptr); | |
| } | |
| mSemaphoresToDelete.ClearUpTo(completedSerial); | |
| for (VkDescriptorPool pool : mDescriptorPoolsToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyDescriptorPool(vkDevice, pool, nullptr); | |
| } | |
| mDescriptorPoolsToDelete.ClearUpTo(completedSerial); | |
| for (VkQueryPool pool : mQueryPoolsToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroyQueryPool(vkDevice, pool, nullptr); | |
| } | |
| mQueryPoolsToDelete.ClearUpTo(completedSerial); | |
| for (VkSamplerYcbcrConversion samplerYcbcrConversion : | |
| mSamplerYcbcrConversionsToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroySamplerYcbcrConversion(vkDevice, samplerYcbcrConversion, nullptr); | |
| } | |
| mSamplerYcbcrConversionsToDelete.ClearUpTo(completedSerial); | |
| for (VkSampler sampler : mSamplersToDelete.IterateUpTo(completedSerial)) { | |
| mDevice->fn.DestroySampler(vkDevice, sampler, nullptr); | |
| } | |
| mSamplersToDelete.ClearUpTo(completedSerial); | |
| } | |
| } // namespace dawn::native::vulkan |