Add FlatComputePipelineDescriptor for CreateComputePipelineAsync

This patch implements the struct FlatComputePipelineDescriptor to
save all the pointer members of ComputePipelineDescriptor in
CreateComputePipelineAsyncTask to better simplify the orignal code
path.

We will also implement FlatRenderPipelineDescriptor in the next
patch, which is more important for CreateRenderPipelineAsync as
there are many more pointer members in RenderPipelineDescriptor
than those in ComputePipelineDescriptor.

BUG=dawn:529

Change-Id: I69ab0dc898f0a6dcc9886d827729e6fd7308bd2d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63280
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao 2021-09-02 00:30:31 +00:00 committed by Dawn LUCI CQ
parent 1f48c97353
commit 305f4df2b5
18 changed files with 127 additions and 110 deletions

View File

@ -19,6 +19,31 @@
namespace dawn_native {
FlatComputePipelineDescriptor::FlatComputePipelineDescriptor(
const ComputePipelineDescriptor* descriptor)
: mLabel(descriptor->label != nullptr ? descriptor->label : ""),
mLayout(descriptor->layout) {
label = mLabel.c_str();
layout = mLayout.Get();
// TODO(dawn:800): Remove after deprecation period.
if (descriptor->compute.module == nullptr && descriptor->computeStage.module != nullptr) {
compute.module = descriptor->computeStage.module;
compute.entryPoint = descriptor->computeStage.entryPoint;
} else {
compute.module = descriptor->compute.module;
compute.entryPoint = descriptor->compute.entryPoint;
}
mComputeModule = compute.module;
mEntryPoint = compute.entryPoint;
}
void FlatComputePipelineDescriptor::SetLayout(Ref<PipelineLayoutBase> appliedLayout) {
mLayout = std::move(appliedLayout);
layout = mLayout.Get();
}
MaybeError ValidateComputePipelineDescriptor(DeviceBase* device,
const ComputePipelineDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) {

View File

@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_COMPUTEPIPELINE_H_
#define DAWNNATIVE_COMPUTEPIPELINE_H_
#include "common/NonCopyable.h"
#include "dawn_native/Pipeline.h"
namespace dawn_native {
@ -22,6 +23,22 @@ namespace dawn_native {
class DeviceBase;
struct EntryPointMetadata;
// We use FlatComputePipelineDescriptor to keep all the members of ComputePipelineDescriptor
// (especially the members in pointers) valid in CreateComputePipelineAsyncTask when the
// creation of the compute pipeline is executed asynchronously.
struct FlatComputePipelineDescriptor : public ComputePipelineDescriptor, public NonMovable {
public:
explicit FlatComputePipelineDescriptor(const ComputePipelineDescriptor* descriptor);
void SetLayout(Ref<PipelineLayoutBase> appliedLayout);
private:
std::string mLabel;
Ref<PipelineLayoutBase> mLayout;
std::string mEntryPoint;
Ref<ShaderModuleBase> mComputeModule;
};
MaybeError ValidateComputePipelineDescriptor(DeviceBase* device,
const ComputePipelineDescriptor* descriptor);

View File

@ -103,7 +103,7 @@ namespace dawn_native {
CreateComputePipelineAsyncTask::CreateComputePipelineAsyncTask(
Ref<ComputePipelineBase> nonInitializedComputePipeline,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata)
@ -111,32 +111,21 @@ namespace dawn_native {
mBlueprintHash(blueprintHash),
mCallback(callback),
mUserdata(userdata),
mLabel(descriptor->label != nullptr ? descriptor->label : ""),
mLayout(descriptor->layout),
mEntryPoint(descriptor->compute.entryPoint),
mComputeShaderModule(descriptor->compute.module) {
mAppliedDescriptor(std::move(descriptor)) {
ASSERT(mComputePipeline != nullptr);
// TODO(jiawei.shao@intel.com): save nextInChain when it is supported in Dawn.
ASSERT(descriptor->nextInChain == nullptr);
ASSERT(mAppliedDescriptor->nextInChain == nullptr);
}
void CreateComputePipelineAsyncTask::Run() {
ComputePipelineDescriptor descriptor;
if (!mLabel.empty()) {
descriptor.label = mLabel.c_str();
}
descriptor.compute.entryPoint = mEntryPoint.c_str();
descriptor.layout = mLayout.Get();
descriptor.compute.module = mComputeShaderModule.Get();
MaybeError maybeError = mComputePipeline->Initialize(&descriptor);
MaybeError maybeError = mComputePipeline->Initialize(mAppliedDescriptor.get());
std::string errorMessage;
if (maybeError.IsError()) {
mComputePipeline = nullptr;
errorMessage = maybeError.AcquireError()->GetMessage();
}
mComputeShaderModule = nullptr;
mComputePipeline->GetDevice()->AddComputePipelineAsyncCallbackTask(
mComputePipeline, errorMessage, mCallback, mUserdata, mBlueprintHash);
}

View File

@ -27,7 +27,7 @@ namespace dawn_native {
class PipelineLayoutBase;
class RenderPipelineBase;
class ShaderModuleBase;
struct ComputePipelineDescriptor;
struct FlatComputePipelineDescriptor;
struct CreatePipelineAsyncCallbackTaskBase : CallbackTask {
CreatePipelineAsyncCallbackTaskBase(std::string errorMessage, void* userData);
@ -69,14 +69,10 @@ namespace dawn_native {
// CreateComputePipelineAsyncTask defines all the inputs and outputs of
// CreateComputePipelineAsync() tasks, which are the same among all the backends.
// TODO(crbug.com/dawn/529): Define a "flat descriptor"
// (like utils::ComboRenderPipelineDescriptor) in ComputePipeline.h that's reused here and for
// caching, etc. ValidateComputePipelineDescriptor() could produce that flat descriptor so that
// it is reused in other places.
class CreateComputePipelineAsyncTask {
public:
CreateComputePipelineAsyncTask(Ref<ComputePipelineBase> nonInitializedComputePipeline,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata);
@ -92,10 +88,7 @@ namespace dawn_native {
WGPUCreateComputePipelineAsyncCallback mCallback;
void* mUserdata;
std::string mLabel;
Ref<PipelineLayoutBase> mLayout;
std::string mEntryPoint;
Ref<ShaderModuleBase> mComputeShaderModule;
std::unique_ptr<FlatComputePipelineDescriptor> mAppliedDescriptor;
};
} // namespace dawn_native

View File

@ -1086,12 +1086,8 @@ namespace dawn_native {
DAWN_TRY(ValidateComputePipelineDescriptor(this, descriptor));
}
// Ref will keep the pipeline layout alive until the end of the function where
// the pipeline will take another reference.
Ref<PipelineLayoutBase> layoutRef;
ComputePipelineDescriptor appliedDescriptor;
DAWN_TRY_ASSIGN(layoutRef, ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
*descriptor, &appliedDescriptor));
FlatComputePipelineDescriptor appliedDescriptor(descriptor);
DAWN_TRY(ValidateLayoutAndSetDefaultLayout(&appliedDescriptor));
auto pipelineAndBlueprintFromCache = GetCachedComputePipeline(&appliedDescriptor);
if (pipelineAndBlueprintFromCache.first.Get() != nullptr) {
@ -1113,15 +1109,12 @@ namespace dawn_native {
DAWN_TRY(ValidateComputePipelineDescriptor(this, descriptor));
}
// Ref will keep the pipeline layout alive until the end of the function where
// the pipeline will take another reference.
Ref<PipelineLayoutBase> layoutRef;
ComputePipelineDescriptor appliedDescriptor;
DAWN_TRY_ASSIGN(layoutRef, ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
*descriptor, &appliedDescriptor));
std::unique_ptr<FlatComputePipelineDescriptor> appliedDescriptor =
std::make_unique<FlatComputePipelineDescriptor>(descriptor);
DAWN_TRY(ValidateLayoutAndSetDefaultLayout(appliedDescriptor.get()));
// Call the callback directly when we can get a cached compute pipeline object.
auto pipelineAndBlueprintFromCache = GetCachedComputePipeline(&appliedDescriptor);
auto pipelineAndBlueprintFromCache = GetCachedComputePipeline(appliedDescriptor.get());
if (pipelineAndBlueprintFromCache.first.Get() != nullptr) {
Ref<ComputePipelineBase> result = std::move(pipelineAndBlueprintFromCache.first);
callback(WGPUCreatePipelineAsyncStatus_Success,
@ -1131,34 +1124,24 @@ namespace dawn_native {
// where the pipeline object may be created asynchronously and the result will be saved
// to mCreatePipelineAsyncTracker.
const size_t blueprintHash = pipelineAndBlueprintFromCache.second;
CreateComputePipelineAsyncImpl(&appliedDescriptor, blueprintHash, callback, userdata);
CreateComputePipelineAsyncImpl(std::move(appliedDescriptor), blueprintHash, callback,
userdata);
}
return {};
}
ResultOrError<Ref<PipelineLayoutBase>>
DeviceBase::ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
const ComputePipelineDescriptor& descriptor,
ComputePipelineDescriptor* outDescriptor) {
Ref<PipelineLayoutBase> layoutRef;
*outDescriptor = descriptor;
// TODO(dawn:800): Remove after deprecation period.
if (outDescriptor->compute.module == nullptr &&
outDescriptor->computeStage.module != nullptr) {
outDescriptor->compute.module = outDescriptor->computeStage.module;
outDescriptor->compute.entryPoint = outDescriptor->computeStage.entryPoint;
}
MaybeError DeviceBase::ValidateLayoutAndSetDefaultLayout(
FlatComputePipelineDescriptor* outDescriptor) {
if (outDescriptor->layout == nullptr) {
Ref<PipelineLayoutBase> layoutRef;
DAWN_TRY_ASSIGN(layoutRef,
PipelineLayoutBase::CreateDefault(
this, {{SingleShaderStage::Compute, outDescriptor->compute.module,
outDescriptor->compute.entryPoint}}));
outDescriptor->layout = layoutRef.Get();
outDescriptor->SetLayout(std::move(layoutRef));
}
return layoutRef;
return {};
}
ResultOrError<Ref<PipelineLayoutBase>>
@ -1181,14 +1164,15 @@ namespace dawn_native {
// This function is overwritten with the async version on the backends
// that supports creating compute pipeline asynchronously
void DeviceBase::CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void DeviceBase::CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
Ref<ComputePipelineBase> result;
std::string errorMessage;
auto resultOrError = CreateComputePipelineImpl(descriptor);
auto resultOrError = CreateComputePipelineImpl(descriptor.get());
if (resultOrError.IsError()) {
std::unique_ptr<ErrorData> error = resultOrError.AcquireError();
errorMessage = error->GetMessage();

View File

@ -46,6 +46,7 @@ namespace dawn_native {
class PersistentCache;
class StagingBufferBase;
struct CallbackTask;
struct FlatComputePipelineDescriptor;
struct InternalPipelineStore;
struct ShaderModuleParseResult;
@ -350,10 +351,8 @@ namespace dawn_native {
ResultOrError<Ref<BindGroupLayoutBase>> CreateEmptyBindGroupLayout();
ResultOrError<Ref<PipelineLayoutBase>>
ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
const ComputePipelineDescriptor& descriptor,
ComputePipelineDescriptor* outDescriptor);
MaybeError ValidateLayoutAndSetDefaultLayout(
FlatComputePipelineDescriptor* appliedDescriptor);
ResultOrError<Ref<PipelineLayoutBase>>
ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults(
const RenderPipelineDescriptor& descriptor,
@ -367,7 +366,8 @@ namespace dawn_native {
size_t blueprintHash);
Ref<RenderPipelineBase> AddOrGetCachedRenderPipeline(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash);
virtual void CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
virtual void CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata);

View File

@ -69,14 +69,14 @@ namespace dawn_native { namespace d3d12 {
}
void ComputePipeline::CreateAsync(Device* device,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
Ref<ComputePipeline> pipeline = AcquireRef(new ComputePipeline(device, descriptor));
Ref<ComputePipeline> pipeline = AcquireRef(new ComputePipeline(device, descriptor.get()));
std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
std::make_unique<CreateComputePipelineAsyncTask>(pipeline, descriptor, blueprintHash,
callback, userdata);
std::make_unique<CreateComputePipelineAsyncTask>(pipeline, std::move(descriptor),
blueprintHash, callback, userdata);
CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
}

View File

@ -29,7 +29,7 @@ namespace dawn_native { namespace d3d12 {
Device* device,
const ComputePipelineDescriptor* descriptor);
static void CreateAsync(Device* device,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata);

View File

@ -373,11 +373,13 @@ namespace dawn_native { namespace d3d12 {
const TextureViewDescriptor* descriptor) {
return TextureView::Create(texture, descriptor);
}
void Device::CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void Device::CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
ComputePipeline::CreateAsync(this, std::move(descriptor), blueprintHash, callback,
userdata);
}
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {

View File

@ -173,7 +173,8 @@ namespace dawn_native { namespace d3d12 {
ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
TextureBase* texture,
const TextureViewDescriptor* descriptor) override;
void CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) override;

View File

@ -31,7 +31,7 @@ namespace dawn_native { namespace metal {
Device* device,
const ComputePipelineDescriptor* descriptor);
static void CreateAsync(Device* device,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata);

View File

@ -69,14 +69,14 @@ namespace dawn_native { namespace metal {
}
void ComputePipeline::CreateAsync(Device* device,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
Ref<ComputePipeline> pipeline = AcquireRef(new ComputePipeline(device, descriptor));
Ref<ComputePipeline> pipeline = AcquireRef(new ComputePipeline(device, descriptor.get()));
std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
std::make_unique<CreateComputePipelineAsyncTask>(pipeline, descriptor, blueprintHash,
callback, userdata);
std::make_unique<CreateComputePipelineAsyncTask>(pipeline, std::move(descriptor),
blueprintHash, callback, userdata);
CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
}

View File

@ -113,7 +113,8 @@ namespace dawn_native { namespace metal {
ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
TextureBase* texture,
const TextureViewDescriptor* descriptor) override;
void CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) override;

View File

@ -267,11 +267,13 @@ namespace dawn_native { namespace metal {
const TextureViewDescriptor* descriptor) {
return TextureView::Create(texture, descriptor);
}
void Device::CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void Device::CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
ComputePipeline::CreateAsync(this, std::move(descriptor), blueprintHash, callback,
userdata);
}
ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {

View File

@ -86,14 +86,14 @@ namespace dawn_native { namespace vulkan {
}
void ComputePipeline::CreateAsync(Device* device,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
Ref<ComputePipeline> pipeline = AcquireRef(new ComputePipeline(device, descriptor));
Ref<ComputePipeline> pipeline = AcquireRef(new ComputePipeline(device, descriptor.get()));
std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
std::make_unique<CreateComputePipelineAsyncTask>(pipeline, descriptor, blueprintHash,
callback, userdata);
std::make_unique<CreateComputePipelineAsyncTask>(pipeline, std::move(descriptor),
blueprintHash, callback, userdata);
CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
}

View File

@ -30,7 +30,7 @@ namespace dawn_native { namespace vulkan {
Device* device,
const ComputePipelineDescriptor* descriptor);
static void CreateAsync(Device* device,
const ComputePipelineDescriptor* descriptor,
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata);

View File

@ -162,11 +162,13 @@ namespace dawn_native { namespace vulkan {
const TextureViewDescriptor* descriptor) {
return TextureView::Create(texture, descriptor);
}
void Device::CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void Device::CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) {
ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
ComputePipeline::CreateAsync(this, std::move(descriptor), blueprintHash, callback,
userdata);
}
MaybeError Device::TickImpl() {

View File

@ -137,7 +137,8 @@ namespace dawn_native { namespace vulkan {
ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
TextureBase* texture,
const TextureViewDescriptor* descriptor) override;
void CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
void CreateComputePipelineAsyncImpl(
std::unique_ptr<FlatComputePipelineDescriptor> descriptor,
size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) override;