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 <enga@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
ba66295033
commit
525039ddc6
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
#include "common/Assert.h"
|
#include "common/Assert.h"
|
||||||
#include "common/Log.h"
|
#include "common/Log.h"
|
||||||
#include "dawn_native/AsyncTask.h"
|
|
||||||
#include "dawn_native/CreatePipelineAsyncTask.h"
|
#include "dawn_native/CreatePipelineAsyncTask.h"
|
||||||
#include "dawn_native/d3d12/D3D12Error.h"
|
#include "dawn_native/d3d12/D3D12Error.h"
|
||||||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||||
|
|
|
@ -168,6 +168,12 @@ namespace dawn_native { namespace vulkan {
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, 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() {
|
MaybeError Device::TickImpl() {
|
||||||
RecycleCompletedCommands();
|
RecycleCompletedCommands();
|
||||||
|
|
|
@ -141,6 +141,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
size_t blueprintHash,
|
size_t blueprintHash,
|
||||||
WGPUCreateComputePipelineAsyncCallback callback,
|
WGPUCreateComputePipelineAsyncCallback callback,
|
||||||
void* userdata) override;
|
void* userdata) override;
|
||||||
|
void CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor,
|
||||||
|
size_t blueprintHash,
|
||||||
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
|
void* userdata) override;
|
||||||
|
|
||||||
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
|
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
|
||||||
void GatherQueueFromDevice();
|
void GatherQueueFromDevice();
|
||||||
|
|
|
@ -65,13 +65,16 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPassCache::~RenderPassCache() {
|
RenderPassCache::~RenderPassCache() {
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
for (auto it : mCache) {
|
for (auto it : mCache) {
|
||||||
mDevice->fn.DestroyRenderPass(mDevice->GetVkDevice(), it.second, nullptr);
|
mDevice->fn.DestroyRenderPass(mDevice->GetVkDevice(), it.second, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCache.clear();
|
mCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<VkRenderPass> RenderPassCache::GetRenderPass(const RenderPassCacheQuery& query) {
|
ResultOrError<VkRenderPass> RenderPassCache::GetRenderPass(const RenderPassCacheQuery& query) {
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
auto it = mCache.find(query);
|
auto it = mCache.find(query);
|
||||||
if (it != mCache.end()) {
|
if (it != mCache.end()) {
|
||||||
return VkRenderPass(it->second);
|
return VkRenderPass(it->second);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <mutex>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace dawn_native { namespace vulkan {
|
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
|
// 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
|
// 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.
|
// 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?
|
// TODO(cwallez@chromium.org): Make it an LRU cache somehow?
|
||||||
class RenderPassCache {
|
class RenderPassCache {
|
||||||
public:
|
public:
|
||||||
|
@ -86,6 +88,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
std::unordered_map<RenderPassCacheQuery, VkRenderPass, CacheFuncs, CacheFuncs>;
|
std::unordered_map<RenderPassCacheQuery, VkRenderPass, CacheFuncs, CacheFuncs>;
|
||||||
|
|
||||||
Device* mDevice = nullptr;
|
Device* mDevice = nullptr;
|
||||||
|
|
||||||
|
std::mutex mMutex;
|
||||||
Cache mCache;
|
Cache mCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "dawn_native/vulkan/RenderPipelineVk.h"
|
#include "dawn_native/vulkan/RenderPipelineVk.h"
|
||||||
|
|
||||||
|
#include "dawn_native/CreatePipelineAsyncTask.h"
|
||||||
#include "dawn_native/vulkan/DeviceVk.h"
|
#include "dawn_native/vulkan/DeviceVk.h"
|
||||||
#include "dawn_native/vulkan/FencedDeleter.h"
|
#include "dawn_native/vulkan/FencedDeleter.h"
|
||||||
#include "dawn_native/vulkan/PipelineLayoutVk.h"
|
#include "dawn_native/vulkan/PipelineLayoutVk.h"
|
||||||
|
@ -600,4 +601,16 @@ namespace dawn_native { namespace vulkan {
|
||||||
return mHandle;
|
return mHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderPipeline::CreateAsync(Device* device,
|
||||||
|
const RenderPipelineDescriptor* descriptor,
|
||||||
|
size_t blueprintHash,
|
||||||
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
|
void* userdata) {
|
||||||
|
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
|
||||||
|
std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask =
|
||||||
|
std::make_unique<CreateRenderPipelineAsyncTask>(pipeline, blueprintHash, callback,
|
||||||
|
userdata);
|
||||||
|
CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask));
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::vulkan
|
}} // namespace dawn_native::vulkan
|
||||||
|
|
|
@ -29,6 +29,11 @@ namespace dawn_native { namespace vulkan {
|
||||||
static ResultOrError<Ref<RenderPipeline>> Create(
|
static ResultOrError<Ref<RenderPipeline>> Create(
|
||||||
Device* device,
|
Device* device,
|
||||||
const RenderPipelineDescriptor* descriptor);
|
const RenderPipelineDescriptor* descriptor);
|
||||||
|
static void CreateAsync(Device* device,
|
||||||
|
const RenderPipelineDescriptor* descriptor,
|
||||||
|
size_t blueprintHash,
|
||||||
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
|
void* userdata);
|
||||||
|
|
||||||
VkPipeline GetHandle() const;
|
VkPipeline GetHandle() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue