|  | // Copyright 2017 The Dawn Authors | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #include "dawn_native/vulkan/FencedDeleter.h" | 
|  |  | 
|  | #include "dawn_native/vulkan/DeviceVk.h" | 
|  |  | 
|  | namespace dawn_native { namespace vulkan { | 
|  |  | 
|  | FencedDeleter::FencedDeleter(Device* device) : mDevice(device) { | 
|  | } | 
|  |  | 
|  | FencedDeleter::~FencedDeleter() { | 
|  | ASSERT(mBuffersToDelete.Empty()); | 
|  | ASSERT(mDescriptorPoolsToDelete.Empty()); | 
|  | ASSERT(mFramebuffersToDelete.Empty()); | 
|  | ASSERT(mImagesToDelete.Empty()); | 
|  | ASSERT(mImageViewsToDelete.Empty()); | 
|  | ASSERT(mMemoriesToDelete.Empty()); | 
|  | ASSERT(mPipelinesToDelete.Empty()); | 
|  | ASSERT(mPipelineLayoutsToDelete.Empty()); | 
|  | ASSERT(mQueryPoolsToDelete.Empty()); | 
|  | ASSERT(mRenderPassesToDelete.Empty()); | 
|  | ASSERT(mSamplersToDelete.Empty()); | 
|  | ASSERT(mSemaphoresToDelete.Empty()); | 
|  | ASSERT(mShaderModulesToDelete.Empty()); | 
|  | ASSERT(mSurfacesToDelete.Empty()); | 
|  | ASSERT(mSwapChainsToDelete.Empty()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkBuffer buffer) { | 
|  | mBuffersToDelete.Enqueue(buffer, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkDescriptorPool pool) { | 
|  | mDescriptorPoolsToDelete.Enqueue(pool, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkDeviceMemory memory) { | 
|  | mMemoriesToDelete.Enqueue(memory, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkFramebuffer framebuffer) { | 
|  | mFramebuffersToDelete.Enqueue(framebuffer, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkImage image) { | 
|  | mImagesToDelete.Enqueue(image, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkImageView view) { | 
|  | mImageViewsToDelete.Enqueue(view, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkPipeline pipeline) { | 
|  | mPipelinesToDelete.Enqueue(pipeline, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkPipelineLayout layout) { | 
|  | mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkQueryPool querypool) { | 
|  | mQueryPoolsToDelete.Enqueue(querypool, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkRenderPass renderPass) { | 
|  | mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkSampler sampler) { | 
|  | mSamplersToDelete.Enqueue(sampler, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkSemaphore semaphore) { | 
|  | mSemaphoresToDelete.Enqueue(semaphore, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkShaderModule module) { | 
|  | mShaderModulesToDelete.Enqueue(module, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkSurfaceKHR surface) { | 
|  | mSurfacesToDelete.Enqueue(surface, mDevice->GetPendingCommandSerial()); | 
|  | } | 
|  |  | 
|  | void FencedDeleter::DeleteWhenUnused(VkSwapchainKHR swapChain) { | 
|  | mSwapChainsToDelete.Enqueue(swapChain, mDevice->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 (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 (VkSampler sampler : mSamplersToDelete.IterateUpTo(completedSerial)) { | 
|  | mDevice->fn.DestroySampler(vkDevice, sampler, nullptr); | 
|  | } | 
|  | mSamplersToDelete.ClearUpTo(completedSerial); | 
|  | } | 
|  |  | 
|  | }}  // namespace dawn_native::vulkan |