From 525039ddc6d8fe313f523e303e3df6c8a51ef970 Mon Sep 17 00:00:00 2001 From: Jiawei Shao Date: Fri, 24 Sep 2021 00:40:57 +0000 Subject: [PATCH] Vulkan: Support creating render pipeline asynchronously This patch implements the asynchronous path of creating render pipeline on Vulkan backend. This patch also makes the access to the member mCache of Vulkan::RenderPassCache thread-safe as it can be accessed in different threads simultaneously. BUG=dawn:529 TEST=dawn_end2end_tests Change-Id: I74c799935ef46405275585cb5dccfcb552a48aa4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64840 Reviewed-by: Austin Eng Commit-Queue: Jiawei Shao --- src/dawn_native/d3d12/RenderPipelineD3D12.cpp | 1 - src/dawn_native/vulkan/DeviceVk.cpp | 6 ++++++ src/dawn_native/vulkan/DeviceVk.h | 4 ++++ src/dawn_native/vulkan/RenderPassCache.cpp | 3 +++ src/dawn_native/vulkan/RenderPassCache.h | 4 ++++ src/dawn_native/vulkan/RenderPipelineVk.cpp | 13 +++++++++++++ src/dawn_native/vulkan/RenderPipelineVk.h | 5 +++++ 7 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp index 75de2b36e3..c9c63f5f10 100644 --- a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp +++ b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp @@ -16,7 +16,6 @@ #include "common/Assert.h" #include "common/Log.h" -#include "dawn_native/AsyncTask.h" #include "dawn_native/CreatePipelineAsyncTask.h" #include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DeviceD3D12.h" diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp index 45b98c8c45..0663d789f6 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -168,6 +168,12 @@ namespace dawn_native { namespace vulkan { void* userdata) { ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); } + void Device::CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, + size_t blueprintHash, + WGPUCreateRenderPipelineAsyncCallback callback, + void* userdata) { + RenderPipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); + } MaybeError Device::TickImpl() { RecycleCompletedCommands(); diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h index e053ebf1c2..44d9366438 100644 --- a/src/dawn_native/vulkan/DeviceVk.h +++ b/src/dawn_native/vulkan/DeviceVk.h @@ -141,6 +141,10 @@ namespace dawn_native { namespace vulkan { size_t blueprintHash, WGPUCreateComputePipelineAsyncCallback callback, void* userdata) override; + void CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, + size_t blueprintHash, + WGPUCreateRenderPipelineAsyncCallback callback, + void* userdata) override; ResultOrError CreateDevice(VkPhysicalDevice physicalDevice); void GatherQueueFromDevice(); diff --git a/src/dawn_native/vulkan/RenderPassCache.cpp b/src/dawn_native/vulkan/RenderPassCache.cpp index ed2bc42c25..c9ce6e91bd 100644 --- a/src/dawn_native/vulkan/RenderPassCache.cpp +++ b/src/dawn_native/vulkan/RenderPassCache.cpp @@ -65,13 +65,16 @@ namespace dawn_native { namespace vulkan { } RenderPassCache::~RenderPassCache() { + std::lock_guard lock(mMutex); for (auto it : mCache) { mDevice->fn.DestroyRenderPass(mDevice->GetVkDevice(), it.second, nullptr); } + mCache.clear(); } ResultOrError RenderPassCache::GetRenderPass(const RenderPassCacheQuery& query) { + std::lock_guard lock(mMutex); auto it = mCache.find(query); if (it != mCache.end()) { return VkRenderPass(it->second); diff --git a/src/dawn_native/vulkan/RenderPassCache.h b/src/dawn_native/vulkan/RenderPassCache.h index 4ee944105d..6cfb1df5d2 100644 --- a/src/dawn_native/vulkan/RenderPassCache.h +++ b/src/dawn_native/vulkan/RenderPassCache.h @@ -25,6 +25,7 @@ #include #include +#include #include namespace dawn_native { namespace vulkan { @@ -63,6 +64,7 @@ namespace dawn_native { namespace vulkan { // render pass. We always arrange the order of attachments in "color-depthstencil-resolve" order // when creating render pass and framebuffer so that we can always make sure the order of // attachments in the rendering pipeline matches the one of the framebuffer. + // All the operations on RenderPassCache are guaranteed to be thread-safe. // TODO(cwallez@chromium.org): Make it an LRU cache somehow? class RenderPassCache { public: @@ -86,6 +88,8 @@ namespace dawn_native { namespace vulkan { std::unordered_map; Device* mDevice = nullptr; + + std::mutex mMutex; Cache mCache; }; diff --git a/src/dawn_native/vulkan/RenderPipelineVk.cpp b/src/dawn_native/vulkan/RenderPipelineVk.cpp index 7276cc43a1..9fa582d870 100644 --- a/src/dawn_native/vulkan/RenderPipelineVk.cpp +++ b/src/dawn_native/vulkan/RenderPipelineVk.cpp @@ -14,6 +14,7 @@ #include "dawn_native/vulkan/RenderPipelineVk.h" +#include "dawn_native/CreatePipelineAsyncTask.h" #include "dawn_native/vulkan/DeviceVk.h" #include "dawn_native/vulkan/FencedDeleter.h" #include "dawn_native/vulkan/PipelineLayoutVk.h" @@ -600,4 +601,16 @@ namespace dawn_native { namespace vulkan { return mHandle; } + void RenderPipeline::CreateAsync(Device* device, + const RenderPipelineDescriptor* descriptor, + size_t blueprintHash, + WGPUCreateRenderPipelineAsyncCallback callback, + void* userdata) { + Ref pipeline = AcquireRef(new RenderPipeline(device, descriptor)); + std::unique_ptr asyncTask = + std::make_unique(pipeline, blueprintHash, callback, + userdata); + CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask)); + } + }} // namespace dawn_native::vulkan diff --git a/src/dawn_native/vulkan/RenderPipelineVk.h b/src/dawn_native/vulkan/RenderPipelineVk.h index 6a9207f8bb..15f7a9be8d 100644 --- a/src/dawn_native/vulkan/RenderPipelineVk.h +++ b/src/dawn_native/vulkan/RenderPipelineVk.h @@ -29,6 +29,11 @@ namespace dawn_native { namespace vulkan { static ResultOrError> Create( Device* device, const RenderPipelineDescriptor* descriptor); + static void CreateAsync(Device* device, + const RenderPipelineDescriptor* descriptor, + size_t blueprintHash, + WGPUCreateRenderPipelineAsyncCallback callback, + void* userdata); VkPipeline GetHandle() const;