Avoid redundant creation of RenderPipelineBase in GetCachedRenderPipeline

This patch removes a redundant creation of RenderPipelineBase object
in GetCachedRenderPipeline(). Instead, we directly compute the blueprint
hash from the uninitialized backend render pipeline object.

BUG=dawn:529
TEST=dawn_end2end_tests

Change-Id: I3c7a2acfc01ab9e1e631793030ea06c9ae908aa2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65000
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Jiawei Shao 2021-09-29 00:49:01 +00:00 committed by Dawn LUCI CQ
parent a57c1db878
commit 3c0925b480
24 changed files with 172 additions and 197 deletions

View File

@ -141,11 +141,9 @@ namespace dawn_native {
CreateRenderPipelineAsyncTask::CreateRenderPipelineAsyncTask( CreateRenderPipelineAsyncTask::CreateRenderPipelineAsyncTask(
Ref<RenderPipelineBase> nonInitializedRenderPipeline, Ref<RenderPipelineBase> nonInitializedRenderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) void* userdata)
: mRenderPipeline(std::move(nonInitializedRenderPipeline)), : mRenderPipeline(std::move(nonInitializedRenderPipeline)),
mBlueprintHash(blueprintHash),
mCallback(callback), mCallback(callback),
mUserdata(userdata) { mUserdata(userdata) {
ASSERT(mRenderPipeline != nullptr); ASSERT(mRenderPipeline != nullptr);
@ -160,7 +158,7 @@ namespace dawn_native {
} }
mRenderPipeline->GetDevice()->AddRenderPipelineAsyncCallbackTask( mRenderPipeline->GetDevice()->AddRenderPipelineAsyncCallbackTask(
mRenderPipeline, errorMessage, mCallback, mUserdata, mBlueprintHash); mRenderPipeline, errorMessage, mCallback, mUserdata);
} }
void CreateRenderPipelineAsyncTask::RunAsync( void CreateRenderPipelineAsyncTask::RunAsync(

View File

@ -92,7 +92,6 @@ namespace dawn_native {
class CreateRenderPipelineAsyncTask { class CreateRenderPipelineAsyncTask {
public: public:
CreateRenderPipelineAsyncTask(Ref<RenderPipelineBase> nonInitializedRenderPipeline, CreateRenderPipelineAsyncTask(Ref<RenderPipelineBase> nonInitializedRenderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata); void* userdata);
@ -102,7 +101,6 @@ namespace dawn_native {
private: private:
Ref<RenderPipelineBase> mRenderPipeline; Ref<RenderPipelineBase> mRenderPipeline;
size_t mBlueprintHash;
WGPUCreateRenderPipelineAsyncCallback mCallback; WGPUCreateRenderPipelineAsyncCallback mCallback;
void* mUserdata; void* mUserdata;
}; };

View File

@ -670,20 +670,14 @@ namespace dawn_native {
return std::make_pair(result, blueprintHash); return std::make_pair(result, blueprintHash);
} }
std::pair<Ref<RenderPipelineBase>, size_t> DeviceBase::GetCachedRenderPipeline( Ref<RenderPipelineBase> DeviceBase::GetCachedRenderPipeline(
const RenderPipelineDescriptor* descriptor) { RenderPipelineBase* uninitializedRenderPipeline) {
RenderPipelineBase blueprint(this, descriptor); Ref<RenderPipelineBase> cachedPipeline;
auto iter = mCaches->renderPipelines.find(uninitializedRenderPipeline);
const size_t blueprintHash = blueprint.ComputeContentHash();
blueprint.SetContentHash(blueprintHash);
Ref<RenderPipelineBase> result;
auto iter = mCaches->renderPipelines.find(&blueprint);
if (iter != mCaches->renderPipelines.end()) { if (iter != mCaches->renderPipelines.end()) {
result = *iter; cachedPipeline = *iter;
} }
return cachedPipeline;
return std::make_pair(result, blueprintHash);
} }
Ref<ComputePipelineBase> DeviceBase::AddOrGetCachedComputePipeline( Ref<ComputePipelineBase> DeviceBase::AddOrGetCachedComputePipeline(
@ -700,9 +694,7 @@ namespace dawn_native {
} }
Ref<RenderPipelineBase> DeviceBase::AddOrGetCachedRenderPipeline( Ref<RenderPipelineBase> DeviceBase::AddOrGetCachedRenderPipeline(
Ref<RenderPipelineBase> renderPipeline, Ref<RenderPipelineBase> renderPipeline) {
size_t blueprintHash) {
renderPipeline->SetContentHash(blueprintHash);
auto insertion = mCaches->renderPipelines.insert(renderPipeline.Get()); auto insertion = mCaches->renderPipelines.insert(renderPipeline.Get());
if (insertion.second) { if (insertion.second) {
renderPipeline->SetIsCachedReference(); renderPipeline->SetIsCachedReference();
@ -1261,20 +1253,20 @@ namespace dawn_native {
} }
// This function is overwritten with the async version on the backends // This function is overwritten with the async version on the backends
// that supports creating render pipeline asynchronously // that supports initializing render pipeline asynchronously
void DeviceBase::CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, void DeviceBase::InitializeRenderPipelineAsyncImpl(
size_t blueprintHash, Ref<RenderPipelineBase> renderPipeline,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
Ref<RenderPipelineBase> result; Ref<RenderPipelineBase> result;
std::string errorMessage; std::string errorMessage;
auto resultOrError = CreateRenderPipelineImpl(descriptor); MaybeError maybeError = renderPipeline->Initialize();
if (resultOrError.IsError()) { if (maybeError.IsError()) {
std::unique_ptr<ErrorData> error = resultOrError.AcquireError(); std::unique_ptr<ErrorData> error = maybeError.AcquireError();
errorMessage = error->GetMessage(); errorMessage = error->GetMessage();
} else { } else {
result = AddOrGetCachedRenderPipeline(resultOrError.AcquireSuccess(), blueprintHash); result = AddOrGetCachedRenderPipeline(renderPipeline);
} }
std::unique_ptr<CreateRenderPipelineAsyncCallbackTask> callbackTask = std::unique_ptr<CreateRenderPipelineAsyncCallbackTask> callbackTask =
@ -1333,15 +1325,17 @@ namespace dawn_native {
DAWN_TRY_ASSIGN(layoutRef, ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults( DAWN_TRY_ASSIGN(layoutRef, ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults(
this, *descriptor, &appliedDescriptor)); this, *descriptor, &appliedDescriptor));
auto pipelineAndBlueprintFromCache = GetCachedRenderPipeline(&appliedDescriptor); Ref<RenderPipelineBase> uninitializedRenderPipeline =
if (pipelineAndBlueprintFromCache.first.Get() != nullptr) { CreateUninitializedRenderPipeline(&appliedDescriptor);
return std::move(pipelineAndBlueprintFromCache.first);
Ref<RenderPipelineBase> cachedRenderPipeline =
GetCachedRenderPipeline(uninitializedRenderPipeline.Get());
if (cachedRenderPipeline != nullptr) {
return cachedRenderPipeline;
} }
Ref<RenderPipelineBase> backendObj; DAWN_TRY(uninitializedRenderPipeline->Initialize());
DAWN_TRY_ASSIGN(backendObj, CreateRenderPipelineImpl(&appliedDescriptor)); return AddOrGetCachedRenderPipeline(std::move(uninitializedRenderPipeline));
size_t blueprintHash = pipelineAndBlueprintFromCache.second;
return AddOrGetCachedRenderPipeline(backendObj, blueprintHash);
} }
MaybeError DeviceBase::CreateRenderPipelineAsync(const RenderPipelineDescriptor* descriptor, MaybeError DeviceBase::CreateRenderPipelineAsync(const RenderPipelineDescriptor* descriptor,
@ -1355,22 +1349,25 @@ namespace dawn_native {
// Ref will keep the pipeline layout alive until the end of the function where // Ref will keep the pipeline layout alive until the end of the function where
// the pipeline will take another reference. // the pipeline will take another reference.
Ref<PipelineLayoutBase> layoutRef; Ref<PipelineLayoutBase> layoutRef;
RenderPipelineDescriptor descriptorWithPipelineLayout; RenderPipelineDescriptor appliedDescriptor;
DAWN_TRY_ASSIGN(layoutRef, ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults( DAWN_TRY_ASSIGN(layoutRef, ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults(
this, *descriptor, &descriptorWithPipelineLayout)); this, *descriptor, &appliedDescriptor));
Ref<RenderPipelineBase> uninitializedRenderPipeline =
CreateUninitializedRenderPipeline(&appliedDescriptor);
// Call the callback directly when we can get a cached render pipeline object. // Call the callback directly when we can get a cached render pipeline object.
auto pipelineAndBlueprintFromCache = GetCachedRenderPipeline(&descriptorWithPipelineLayout); Ref<RenderPipelineBase> cachedRenderPipeline =
if (pipelineAndBlueprintFromCache.first.Get() != nullptr) { GetCachedRenderPipeline(uninitializedRenderPipeline.Get());
Ref<RenderPipelineBase> result = std::move(pipelineAndBlueprintFromCache.first); if (cachedRenderPipeline != nullptr) {
callback(WGPUCreatePipelineAsyncStatus_Success, callback(WGPUCreatePipelineAsyncStatus_Success,
reinterpret_cast<WGPURenderPipeline>(result.Detach()), "", userdata); reinterpret_cast<WGPURenderPipeline>(cachedRenderPipeline.Detach()), "",
userdata);
} else { } else {
// Otherwise we will create the pipeline object in CreateRenderPipelineAsyncImpl(), // Otherwise we will create the pipeline object in InitializeRenderPipelineAsyncImpl(),
// where the pipeline object may be created asynchronously and the result will be saved // where the pipeline object may be initialized asynchronously and the result will be
// to mCreatePipelineAsyncTracker. // saved to mCreatePipelineAsyncTracker.
const size_t blueprintHash = pipelineAndBlueprintFromCache.second; InitializeRenderPipelineAsyncImpl(std::move(uninitializedRenderPipeline), callback,
CreateRenderPipelineAsyncImpl(&descriptorWithPipelineLayout, blueprintHash, callback,
userdata); userdata);
} }
@ -1536,6 +1533,11 @@ namespace dawn_native {
return mWorkerTaskPool.get(); return mWorkerTaskPool.get();
} }
Ref<RenderPipelineBase> DeviceBase::CreateUninitializedRenderPipeline(
const RenderPipelineDescriptor* descriptor) {
return CreateUninitializedRenderPipelineImpl(descriptor);
}
void DeviceBase::AddComputePipelineAsyncCallbackTask( void DeviceBase::AddComputePipelineAsyncCallbackTask(
Ref<ComputePipelineBase> pipeline, Ref<ComputePipelineBase> pipeline,
std::string errorMessage, std::string errorMessage,
@ -1584,44 +1586,28 @@ namespace dawn_native {
Ref<RenderPipelineBase> pipeline, Ref<RenderPipelineBase> pipeline,
std::string errorMessage, std::string errorMessage,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata, void* userdata) {
size_t blueprintHash) {
// CreateRenderPipelineAsyncWaitableCallbackTask is declared as an internal class as it // CreateRenderPipelineAsyncWaitableCallbackTask is declared as an internal class as it
// needs to call the private member function DeviceBase::AddOrGetCachedRenderPipeline(). // needs to call the private member function DeviceBase::AddOrGetCachedRenderPipeline().
struct CreateRenderPipelineAsyncWaitableCallbackTask final struct CreateRenderPipelineAsyncWaitableCallbackTask final
: CreateRenderPipelineAsyncCallbackTask { : CreateRenderPipelineAsyncCallbackTask {
CreateRenderPipelineAsyncWaitableCallbackTask( using CreateRenderPipelineAsyncCallbackTask::CreateRenderPipelineAsyncCallbackTask;
Ref<RenderPipelineBase> pipeline,
std::string errorMessage,
WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata,
size_t blueprintHash)
: CreateRenderPipelineAsyncCallbackTask(std::move(pipeline),
errorMessage,
callback,
userdata),
mBlueprintHash(blueprintHash) {
}
void Finish() final { void Finish() final {
// TODO(dawn:529): call AddOrGetCachedRenderPipeline() asynchronously in // TODO(dawn:529): call AddOrGetCachedRenderPipeline() asynchronously in
// CreateRenderPipelineAsyncTaskImpl::Run() when the front-end pipeline cache is // CreateRenderPipelineAsyncTaskImpl::Run() when the front-end pipeline cache is
// thread-safe. // thread-safe.
if (mPipeline.Get() != nullptr) { if (mPipeline.Get() != nullptr) {
mPipeline = mPipeline->GetDevice()->AddOrGetCachedRenderPipeline( mPipeline = mPipeline->GetDevice()->AddOrGetCachedRenderPipeline(mPipeline);
mPipeline, mBlueprintHash);
} }
CreateRenderPipelineAsyncCallbackTask::Finish(); CreateRenderPipelineAsyncCallbackTask::Finish();
} }
private:
size_t mBlueprintHash;
}; };
mCallbackTaskManager->AddCallbackTask( mCallbackTaskManager->AddCallbackTask(
std::make_unique<CreateRenderPipelineAsyncWaitableCallbackTask>( std::make_unique<CreateRenderPipelineAsyncWaitableCallbackTask>(
std::move(pipeline), errorMessage, callback, userdata, blueprintHash)); std::move(pipeline), errorMessage, callback, userdata));
} }
PipelineCompatibilityToken DeviceBase::GetNextPipelineCompatibilityToken() { PipelineCompatibilityToken DeviceBase::GetNextPipelineCompatibilityToken() {

View File

@ -307,8 +307,7 @@ namespace dawn_native {
void AddRenderPipelineAsyncCallbackTask(Ref<RenderPipelineBase> pipeline, void AddRenderPipelineAsyncCallbackTask(Ref<RenderPipelineBase> pipeline,
std::string errorMessage, std::string errorMessage,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata, void* userdata);
size_t blueprintHash);
PipelineCompatibilityToken GetNextPipelineCompatibilityToken(); PipelineCompatibilityToken GetNextPipelineCompatibilityToken();
@ -339,7 +338,7 @@ namespace dawn_native {
const PipelineLayoutDescriptor* descriptor) = 0; const PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( virtual ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) = 0; const QuerySetDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl( virtual Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) = 0; const RenderPipelineDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( virtual ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) = 0; const SamplerDescriptor* descriptor) = 0;
@ -367,19 +366,21 @@ namespace dawn_native {
std::pair<Ref<ComputePipelineBase>, size_t> GetCachedComputePipeline( std::pair<Ref<ComputePipelineBase>, size_t> GetCachedComputePipeline(
const ComputePipelineDescriptor* descriptor); const ComputePipelineDescriptor* descriptor);
std::pair<Ref<RenderPipelineBase>, size_t> GetCachedRenderPipeline( Ref<RenderPipelineBase> GetCachedRenderPipeline(
const RenderPipelineDescriptor* descriptor); RenderPipelineBase* uninitializedRenderPipeline);
Ref<ComputePipelineBase> AddOrGetCachedComputePipeline( Ref<ComputePipelineBase> AddOrGetCachedComputePipeline(
Ref<ComputePipelineBase> computePipeline, Ref<ComputePipelineBase> computePipeline,
size_t blueprintHash); size_t blueprintHash);
Ref<RenderPipelineBase> AddOrGetCachedRenderPipeline(Ref<RenderPipelineBase> renderPipeline, Ref<RenderPipelineBase> AddOrGetCachedRenderPipeline(
size_t blueprintHash); Ref<RenderPipelineBase> renderPipeline);
virtual void CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor, virtual void CreateComputePipelineAsyncImpl(const ComputePipelineDescriptor* descriptor,
size_t blueprintHash, size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback, WGPUCreateComputePipelineAsyncCallback callback,
void* userdata); void* userdata);
virtual void CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, Ref<RenderPipelineBase> CreateUninitializedRenderPipeline(
size_t blueprintHash, const RenderPipelineDescriptor* descriptor);
virtual void InitializeRenderPipelineAsyncImpl(
Ref<RenderPipelineBase> renderPipeline,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata); void* userdata);

View File

@ -554,6 +554,8 @@ namespace dawn_native {
mTargets[i].blend = &mTargetBlend[i]; mTargets[i].blend = &mTargetBlend[i];
} }
} }
SetContentHash(ComputeContentHash());
} }
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag) RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
@ -562,7 +564,19 @@ namespace dawn_native {
// static // static
RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) { RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) {
return new RenderPipelineBase(device, ObjectBase::kError); class ErrorRenderPipeline final : public RenderPipelineBase {
public:
ErrorRenderPipeline(DeviceBase* device)
: RenderPipelineBase(device, ObjectBase::kError) {
}
MaybeError Initialize() override {
UNREACHABLE();
return {};
}
};
return new ErrorRenderPipeline(device);
} }
ObjectType RenderPipelineBase::GetType() const { ObjectType RenderPipelineBase::GetType() const {
@ -900,7 +914,4 @@ namespace dawn_native {
return true; return true;
} }
MaybeError RenderPipelineBase::Initialize() {
return {};
}
} // namespace dawn_native } // namespace dawn_native

View File

@ -105,15 +105,12 @@ namespace dawn_native {
bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const; bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
}; };
// Initialize() should only be called once by the frontend.
virtual MaybeError Initialize() = 0;
private: private:
RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
// CreateRenderPipelineAsyncTask is declared as a friend of RenderPipelineBase as it
// needs to call the private member function RenderPipelineBase::Initialize().
friend class CreateRenderPipelineAsyncTask;
virtual MaybeError Initialize();
// TODO(dawn:529): store all the following members in a FlatRenderPipelineDescriptor object
// Vertex state // Vertex state
uint32_t mVertexBufferCount; uint32_t mVertexBufferCount;
ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> mAttributeLocationsUsed; ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> mAttributeLocationsUsed;

View File

@ -346,9 +346,9 @@ namespace dawn_native { namespace d3d12 {
const QuerySetDescriptor* descriptor) { const QuerySetDescriptor* descriptor) {
return QuerySet::Create(this, descriptor); return QuerySet::Create(this, descriptor);
} }
ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl( Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor); return RenderPipeline::CreateUninitialized(this, descriptor);
} }
ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) { ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return Sampler::Create(this, descriptor); return Sampler::Create(this, descriptor);
@ -382,11 +382,10 @@ namespace dawn_native { namespace d3d12 {
void* userdata) { void* userdata) {
ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
} }
void Device::CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
RenderPipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); RenderPipeline::InitializeAsync(renderPipeline, callback, userdata);
} }
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) { ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {

View File

@ -155,7 +155,7 @@ namespace dawn_native { namespace d3d12 {
const PipelineLayoutDescriptor* descriptor) override; const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override; const QuerySetDescriptor* descriptor) override;
ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl( Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override; const RenderPipelineDescriptor* descriptor) override;
ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) override; const SamplerDescriptor* descriptor) override;
@ -177,8 +177,7 @@ namespace dawn_native { namespace d3d12 {
size_t blueprintHash, size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback, WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) override; void* userdata) override;
void CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) override; void* userdata) override;

View File

@ -316,12 +316,10 @@ namespace dawn_native { namespace d3d12 {
} // anonymous namespace } // anonymous namespace
ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create( Ref<RenderPipeline> RenderPipeline::CreateUninitialized(
Device* device, Device* device,
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor)); return AcquireRef(new RenderPipeline(device, descriptor));
DAWN_TRY(pipeline->Initialize());
return pipeline;
} }
MaybeError RenderPipeline::Initialize() { MaybeError RenderPipeline::Initialize() {
@ -472,14 +470,11 @@ namespace dawn_native { namespace d3d12 {
return inputLayoutDescriptor; return inputLayoutDescriptor;
} }
void RenderPipeline::CreateAsync(Device* device, void RenderPipeline::InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
const RenderPipelineDescriptor* descriptor,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask = std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask =
std::make_unique<CreateRenderPipelineAsyncTask>(pipeline, blueprintHash, callback, std::make_unique<CreateRenderPipelineAsyncTask>(std::move(renderPipeline), callback,
userdata); userdata);
CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask)); CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask));
} }

View File

@ -26,16 +26,15 @@ namespace dawn_native { namespace d3d12 {
class RenderPipeline final : public RenderPipelineBase { class RenderPipeline final : public RenderPipelineBase {
public: public:
static ResultOrError<Ref<RenderPipeline>> Create( static Ref<RenderPipeline> CreateUninitialized(Device* device,
Device* device,
const RenderPipelineDescriptor* descriptor); const RenderPipelineDescriptor* descriptor);
static void CreateAsync(Device* device, static void InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
const RenderPipelineDescriptor* descriptor,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata); void* userdata);
RenderPipeline() = delete; RenderPipeline() = delete;
MaybeError Initialize() override;
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const; D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
ID3D12PipelineState* GetPipelineState() const; ID3D12PipelineState* GetPipelineState() const;
@ -47,7 +46,6 @@ namespace dawn_native { namespace d3d12 {
private: private:
~RenderPipeline() override; ~RenderPipeline() override;
using RenderPipelineBase::RenderPipelineBase; using RenderPipelineBase::RenderPipelineBase;
MaybeError Initialize() override;
D3D12_INPUT_LAYOUT_DESC ComputeInputLayout( D3D12_INPUT_LAYOUT_DESC ComputeInputLayout(
std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors); std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors);

View File

@ -95,7 +95,7 @@ namespace dawn_native { namespace metal {
const PipelineLayoutDescriptor* descriptor) override; const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override; const QuerySetDescriptor* descriptor) override;
ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl( Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override; const RenderPipelineDescriptor* descriptor) override;
ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) override; const SamplerDescriptor* descriptor) override;
@ -117,8 +117,7 @@ namespace dawn_native { namespace metal {
size_t blueprintHash, size_t blueprintHash,
WGPUCreateComputePipelineAsyncCallback callback, WGPUCreateComputePipelineAsyncCallback callback,
void* userdata) override; void* userdata) override;
void CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) override; void* userdata) override;

View File

@ -255,9 +255,9 @@ namespace dawn_native { namespace metal {
const QuerySetDescriptor* descriptor) { const QuerySetDescriptor* descriptor) {
return QuerySet::Create(this, descriptor); return QuerySet::Create(this, descriptor);
} }
ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl( Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor); return RenderPipeline::CreateUninitialized(this, descriptor);
} }
ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) { ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return Sampler::Create(this, descriptor); return Sampler::Create(this, descriptor);
@ -291,11 +291,10 @@ namespace dawn_native { namespace metal {
void* userdata) { void* userdata) {
ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
} }
void Device::CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor, void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
RenderPipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); RenderPipeline::InitializeAsync(renderPipeline, callback, userdata);
} }
ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() { ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {

View File

@ -27,12 +27,10 @@ namespace dawn_native { namespace metal {
class RenderPipeline final : public RenderPipelineBase { class RenderPipeline final : public RenderPipelineBase {
public: public:
static ResultOrError<Ref<RenderPipeline>> Create( static Ref<RenderPipelineBase> CreateUninitialized(
Device* device, Device* device,
const RenderPipelineDescriptor* descriptor); const RenderPipelineDescriptor* descriptor);
static void CreateAsync(Device* device, static void InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
const RenderPipelineDescriptor* descriptor,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata); void* userdata);
@ -50,9 +48,10 @@ namespace dawn_native { namespace metal {
wgpu::ShaderStage GetStagesRequiringStorageBufferLength() const; wgpu::ShaderStage GetStagesRequiringStorageBufferLength() const;
MaybeError Initialize() override;
private: private:
using RenderPipelineBase::RenderPipelineBase; using RenderPipelineBase::RenderPipelineBase;
MaybeError Initialize() override;
MTLVertexDescriptor* MakeVertexDesc(); MTLVertexDescriptor* MakeVertexDesc();

View File

@ -311,12 +311,10 @@ namespace dawn_native { namespace metal {
} // anonymous namespace } // anonymous namespace
// static // static
ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create( Ref<RenderPipelineBase> RenderPipeline::CreateUninitialized(
Device* device, Device* device,
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor)); return AcquireRef(new RenderPipeline(device, descriptor));
DAWN_TRY(pipeline->Initialize());
return pipeline;
} }
MaybeError RenderPipeline::Initialize() { MaybeError RenderPipeline::Initialize() {
@ -502,14 +500,11 @@ namespace dawn_native { namespace metal {
return mtlVertexDescriptor; return mtlVertexDescriptor;
} }
void RenderPipeline::CreateAsync(Device* device, void RenderPipeline::InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
const RenderPipelineDescriptor* descriptor,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask = std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask =
std::make_unique<CreateRenderPipelineAsyncTask>(pipeline, blueprintHash, callback, std::make_unique<CreateRenderPipelineAsyncTask>(std::move(renderPipeline), callback,
userdata); userdata);
CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask)); CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask));
} }

View File

@ -124,7 +124,7 @@ namespace dawn_native { namespace null {
const QuerySetDescriptor* descriptor) { const QuerySetDescriptor* descriptor) {
return AcquireRef(new QuerySet(this, descriptor)); return AcquireRef(new QuerySet(this, descriptor));
} }
ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl( Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
return AcquireRef(new RenderPipeline(this, descriptor)); return AcquireRef(new RenderPipeline(this, descriptor));
} }
@ -359,6 +359,11 @@ namespace dawn_native { namespace null {
return {}; return {};
} }
// RenderPipeline
MaybeError RenderPipeline::Initialize() {
return {};
}
// SwapChain // SwapChain
// static // static

View File

@ -48,7 +48,7 @@ namespace dawn_native { namespace null {
using PipelineLayout = PipelineLayoutBase; using PipelineLayout = PipelineLayoutBase;
class QuerySet; class QuerySet;
class Queue; class Queue;
using RenderPipeline = RenderPipelineBase; class RenderPipeline;
using Sampler = SamplerBase; using Sampler = SamplerBase;
class ShaderModule; class ShaderModule;
class SwapChain; class SwapChain;
@ -135,7 +135,7 @@ namespace dawn_native { namespace null {
const PipelineLayoutDescriptor* descriptor) override; const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override; const QuerySetDescriptor* descriptor) override;
ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl( Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override; const RenderPipelineDescriptor* descriptor) override;
ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) override; const SamplerDescriptor* descriptor) override;
@ -251,6 +251,13 @@ namespace dawn_native { namespace null {
size_t size) override; size_t size) override;
}; };
class RenderPipeline final : public RenderPipelineBase {
public:
using RenderPipelineBase::RenderPipelineBase;
MaybeError Initialize() override;
};
class ShaderModule final : public ShaderModuleBase { class ShaderModule final : public ShaderModuleBase {
public: public:
using ShaderModuleBase::ShaderModuleBase; using ShaderModuleBase::ShaderModuleBase;

View File

@ -142,9 +142,9 @@ namespace dawn_native { namespace opengl {
const QuerySetDescriptor* descriptor) { const QuerySetDescriptor* descriptor) {
return AcquireRef(new QuerySet(this, descriptor)); return AcquireRef(new QuerySet(this, descriptor));
} }
ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl( Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor); return RenderPipeline::CreateUninitialized(this, descriptor);
} }
ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) { ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return AcquireRef(new Sampler(this, descriptor)); return AcquireRef(new Sampler(this, descriptor));

View File

@ -97,7 +97,7 @@ namespace dawn_native { namespace opengl {
const PipelineLayoutDescriptor* descriptor) override; const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override; const QuerySetDescriptor* descriptor) override;
ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl( Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override; const RenderPipelineDescriptor* descriptor) override;
ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) override; const SamplerDescriptor* descriptor) override;

View File

@ -215,12 +215,10 @@ namespace dawn_native { namespace opengl {
} // anonymous namespace } // anonymous namespace
// static // static
ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create( Ref<RenderPipeline> RenderPipeline::CreateUninitialized(
Device* device, Device* device,
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor)); return AcquireRef(new RenderPipeline(device, descriptor));
DAWN_TRY(pipeline->Initialize());
return pipeline;
} }
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor) RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)

View File

@ -29,8 +29,7 @@ namespace dawn_native { namespace opengl {
class RenderPipeline final : public RenderPipelineBase, public PipelineGL { class RenderPipeline final : public RenderPipelineBase, public PipelineGL {
public: public:
static ResultOrError<Ref<RenderPipeline>> Create( static Ref<RenderPipeline> CreateUninitialized(Device* device,
Device* device,
const RenderPipelineDescriptor* descriptor); const RenderPipelineDescriptor* descriptor);
GLenum GetGLPrimitiveTopology() const; GLenum GetGLPrimitiveTopology() const;
@ -39,10 +38,11 @@ namespace dawn_native { namespace opengl {
void ApplyNow(PersistentPipelineState& persistentPipelineState); void ApplyNow(PersistentPipelineState& persistentPipelineState);
MaybeError Initialize() override;
private: private:
RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor); RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
~RenderPipeline() override; ~RenderPipeline() override;
MaybeError Initialize() override;
void CreateVAOForVertexState(); void CreateVAOForVertexState();

View File

@ -132,9 +132,9 @@ namespace dawn_native { namespace vulkan {
const QuerySetDescriptor* descriptor) { const QuerySetDescriptor* descriptor) {
return QuerySet::Create(this, descriptor); return QuerySet::Create(this, descriptor);
} }
ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl( Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor); return RenderPipeline::CreateUninitialized(this, descriptor);
} }
ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) { ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return Sampler::Create(this, descriptor); return Sampler::Create(this, descriptor);
@ -168,11 +168,10 @@ 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, void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
RenderPipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata); RenderPipeline::InitializeAsync(renderPipeline, callback, userdata);
} }
MaybeError Device::TickImpl() { MaybeError Device::TickImpl() {

View File

@ -119,7 +119,7 @@ namespace dawn_native { namespace vulkan {
const PipelineLayoutDescriptor* descriptor) override; const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override; const QuerySetDescriptor* descriptor) override;
ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl( Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override; const RenderPipelineDescriptor* descriptor) override;
ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) override; const SamplerDescriptor* descriptor) override;
@ -141,8 +141,7 @@ 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, void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) override; void* userdata) override;

View File

@ -328,12 +328,10 @@ namespace dawn_native { namespace vulkan {
} // anonymous namespace } // anonymous namespace
// static // static
ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create( Ref<RenderPipeline> RenderPipeline::CreateUninitialized(
Device* device, Device* device,
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor)); return AcquireRef(new RenderPipeline(device, descriptor));
DAWN_TRY(pipeline->Initialize());
return pipeline;
} }
MaybeError RenderPipeline::Initialize() { MaybeError RenderPipeline::Initialize() {
@ -610,14 +608,11 @@ namespace dawn_native { namespace vulkan {
return mHandle; return mHandle;
} }
void RenderPipeline::CreateAsync(Device* device, void RenderPipeline::InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
const RenderPipelineDescriptor* descriptor,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) { void* userdata) {
Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask = std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask =
std::make_unique<CreateRenderPipelineAsyncTask>(pipeline, blueprintHash, callback, std::make_unique<CreateRenderPipelineAsyncTask>(std::move(renderPipeline), callback,
userdata); userdata);
CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask)); CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask));
} }

View File

@ -26,24 +26,22 @@ namespace dawn_native { namespace vulkan {
class RenderPipeline final : public RenderPipelineBase { class RenderPipeline final : public RenderPipelineBase {
public: public:
static ResultOrError<Ref<RenderPipeline>> Create( static Ref<RenderPipeline> CreateUninitialized(Device* device,
Device* device,
const RenderPipelineDescriptor* descriptor); const RenderPipelineDescriptor* descriptor);
static void CreateAsync(Device* device, static void InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
const RenderPipelineDescriptor* descriptor,
size_t blueprintHash,
WGPUCreateRenderPipelineAsyncCallback callback, WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata); void* userdata);
VkPipeline GetHandle() const; VkPipeline GetHandle() const;
MaybeError Initialize() override;
// Dawn API // Dawn API
void SetLabelImpl() override; void SetLabelImpl() override;
private: private:
~RenderPipeline() override; ~RenderPipeline() override;
using RenderPipelineBase::RenderPipelineBase; using RenderPipelineBase::RenderPipelineBase;
MaybeError Initialize() override;
struct PipelineVertexInputStateCreateInfoTemporaryAllocations { struct PipelineVertexInputStateCreateInfoTemporaryAllocations {
std::array<VkVertexInputBindingDescription, kMaxVertexBuffers> bindings; std::array<VkVertexInputBindingDescription, kMaxVertexBuffers> bindings;