diff --git a/BUILD.gn b/BUILD.gn index 0d06dafd42..09635389b1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -260,6 +260,8 @@ source_set("libdawn_native_sources") { "src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h", "src/dawn_native/d3d12/ComputePipelineD3D12.cpp", "src/dawn_native/d3d12/ComputePipelineD3D12.h", + "src/dawn_native/d3d12/D3D12Error.cpp", + "src/dawn_native/d3d12/D3D12Error.h", "src/dawn_native/d3d12/D3D12Info.cpp", "src/dawn_native/d3d12/D3D12Info.h", "src/dawn_native/d3d12/DescriptorHeapAllocator.cpp", diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp index f2299f83f2..a0a208305f 100644 --- a/src/dawn_native/d3d12/BufferD3D12.cpp +++ b/src/dawn_native/d3d12/BufferD3D12.cpp @@ -18,6 +18,7 @@ #include "common/Constants.h" #include "common/Math.h" #include "dawn_native/d3d12/CommandRecordingContext.h" +#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DeviceD3D12.h" namespace dawn_native { namespace d3d12 { @@ -217,8 +218,9 @@ namespace dawn_native { namespace d3d12 { MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) { mWrittenMappedRange = {0, GetSize()}; - ASSERT_SUCCESS(GetD3D12Resource()->Map(0, &mWrittenMappedRange, - reinterpret_cast(mappedPointer))); + DAWN_TRY(CheckHRESULT(GetD3D12Resource()->Map(0, &mWrittenMappedRange, + reinterpret_cast(mappedPointer)), + "D3D12 map at creation")); return {}; } @@ -226,7 +228,9 @@ namespace dawn_native { namespace d3d12 { mWrittenMappedRange = {}; D3D12_RANGE readRange = {0, GetSize()}; char* data = nullptr; - ASSERT_SUCCESS(GetD3D12Resource()->Map(0, &readRange, reinterpret_cast(&data))); + DAWN_TRY( + CheckHRESULT(GetD3D12Resource()->Map(0, &readRange, reinterpret_cast(&data)), + "D3D12 map read async")); // There is no need to transition the resource to a new state: D3D12 seems to make the GPU // writes available when the fence is passed. MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapRequestTracker(); @@ -237,8 +241,9 @@ namespace dawn_native { namespace d3d12 { MaybeError Buffer::MapWriteAsyncImpl(uint32_t serial) { mWrittenMappedRange = {0, GetSize()}; char* data = nullptr; - ASSERT_SUCCESS( - GetD3D12Resource()->Map(0, &mWrittenMappedRange, reinterpret_cast(&data))); + DAWN_TRY(CheckHRESULT( + GetD3D12Resource()->Map(0, &mWrittenMappedRange, reinterpret_cast(&data)), + "D3D12 map write async")); // There is no need to transition the resource to a new state: D3D12 seems to make the CPU // writes available on queue submission. MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapRequestTracker(); diff --git a/src/dawn_native/d3d12/CommandAllocatorManager.cpp b/src/dawn_native/d3d12/CommandAllocatorManager.cpp index 90f7a5a895..8c6029e5c3 100644 --- a/src/dawn_native/d3d12/CommandAllocatorManager.cpp +++ b/src/dawn_native/d3d12/CommandAllocatorManager.cpp @@ -14,6 +14,7 @@ #include "dawn_native/d3d12/CommandAllocatorManager.h" +#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "common/Assert.h" @@ -26,12 +27,12 @@ namespace dawn_native { namespace d3d12 { mFreeAllocators.set(); } - ComPtr CommandAllocatorManager::ReserveCommandAllocator() { + ResultOrError CommandAllocatorManager::ReserveCommandAllocator() { // If there are no free allocators, get the oldest serial in flight and wait on it if (mFreeAllocators.none()) { const uint64_t firstSerial = mInFlightCommandAllocators.FirstSerial(); - device->WaitForSerial(firstSerial); - Tick(firstSerial); + DAWN_TRY(device->WaitForSerial(firstSerial)); + DAWN_TRY(Tick(firstSerial)); } ASSERT(mFreeAllocators.any()); @@ -42,8 +43,10 @@ namespace dawn_native { namespace d3d12 { if (firstFreeIndex >= mAllocatorCount) { ASSERT(firstFreeIndex == mAllocatorCount); mAllocatorCount++; - ASSERT_SUCCESS(device->GetD3D12Device()->CreateCommandAllocator( - D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocators[firstFreeIndex]))); + DAWN_TRY(CheckHRESULT(device->GetD3D12Device()->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&mCommandAllocators[firstFreeIndex])), + "D3D12 create command allocator")); } // Mark the command allocator as used @@ -53,17 +56,17 @@ namespace dawn_native { namespace d3d12 { // ExecuteCommandLists mInFlightCommandAllocators.Enqueue({mCommandAllocators[firstFreeIndex], firstFreeIndex}, device->GetPendingCommandSerial()); - - return mCommandAllocators[firstFreeIndex]; + return mCommandAllocators[firstFreeIndex].Get(); } - void CommandAllocatorManager::Tick(uint64_t lastCompletedSerial) { + MaybeError CommandAllocatorManager::Tick(uint64_t lastCompletedSerial) { // Reset all command allocators that are no longer in flight for (auto it : mInFlightCommandAllocators.IterateUpTo(lastCompletedSerial)) { - ASSERT_SUCCESS(it.commandAllocator->Reset()); + DAWN_TRY(CheckHRESULT(it.commandAllocator->Reset(), "D3D12 reset command allocator")); mFreeAllocators.set(it.index); } mInFlightCommandAllocators.ClearUpTo(lastCompletedSerial); + return {}; } }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/CommandAllocatorManager.h b/src/dawn_native/d3d12/CommandAllocatorManager.h index fd7c8ce27d..654d3be467 100644 --- a/src/dawn_native/d3d12/CommandAllocatorManager.h +++ b/src/dawn_native/d3d12/CommandAllocatorManager.h @@ -18,6 +18,7 @@ #include "dawn_native/d3d12/d3d12_platform.h" #include "common/SerialQueue.h" +#include "dawn_native/Error.h" #include @@ -31,8 +32,8 @@ namespace dawn_native { namespace d3d12 { // A CommandAllocator that is reserved must be used on the next ExecuteCommandLists // otherwise its commands may be reset before execution has completed on the GPU - ComPtr ReserveCommandAllocator(); - void Tick(uint64_t lastCompletedSerial); + ResultOrError ReserveCommandAllocator(); + MaybeError Tick(uint64_t lastCompletedSerial); private: Device* device; diff --git a/src/dawn_native/d3d12/CommandRecordingContext.cpp b/src/dawn_native/d3d12/CommandRecordingContext.cpp index eb4ec7bab9..4d927b8322 100644 --- a/src/dawn_native/d3d12/CommandRecordingContext.cpp +++ b/src/dawn_native/d3d12/CommandRecordingContext.cpp @@ -13,28 +13,28 @@ // limitations under the License. #include "dawn_native/d3d12/CommandRecordingContext.h" #include "dawn_native/d3d12/CommandAllocatorManager.h" +#include "dawn_native/d3d12/D3D12Error.h" namespace dawn_native { namespace d3d12 { MaybeError CommandRecordingContext::Open(ID3D12Device* d3d12Device, CommandAllocatorManager* commandAllocationManager) { ASSERT(!IsOpen()); + ID3D12CommandAllocator* commandAllocator; + DAWN_TRY_ASSIGN(commandAllocator, commandAllocationManager->ReserveCommandAllocator()); if (mD3d12CommandList != nullptr) { - const HRESULT hr = mD3d12CommandList->Reset( - commandAllocationManager->ReserveCommandAllocator().Get(), nullptr); - if (FAILED(hr)) { + MaybeError error = CheckHRESULT(mD3d12CommandList->Reset(commandAllocator, nullptr), + "D3D12 resetting command list"); + if (error.IsError()) { mD3d12CommandList.Reset(); - return DAWN_DEVICE_LOST_ERROR("Error resetting command list."); + DAWN_TRY(std::move(error)); } } else { ComPtr d3d12GraphicsCommandList; - const HRESULT hr = d3d12Device->CreateCommandList( - 0, D3D12_COMMAND_LIST_TYPE_DIRECT, - commandAllocationManager->ReserveCommandAllocator().Get(), nullptr, - IID_PPV_ARGS(&d3d12GraphicsCommandList)); - if (FAILED(hr)) { - return DAWN_DEVICE_LOST_ERROR("Error creating a direct command list."); - } + DAWN_TRY(CheckHRESULT( + d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator, + nullptr, IID_PPV_ARGS(&d3d12GraphicsCommandList)), + "D3D12 creating direct command list")); mD3d12CommandList = std::move(d3d12GraphicsCommandList); } @@ -46,10 +46,11 @@ namespace dawn_native { namespace d3d12 { ResultOrError CommandRecordingContext::Close() { ASSERT(IsOpen()); mIsOpen = false; - const HRESULT hr = mD3d12CommandList->Close(); - if (FAILED(hr)) { + MaybeError error = + CheckHRESULT(mD3d12CommandList->Close(), "D3D12 closing pending command list"); + if (error.IsError()) { mD3d12CommandList.Reset(); - return DAWN_DEVICE_LOST_ERROR("Error closing pending command list."); + DAWN_TRY(std::move(error)); } return mD3d12CommandList.Get(); } diff --git a/src/dawn_native/d3d12/D3D12Error.cpp b/src/dawn_native/d3d12/D3D12Error.cpp new file mode 100644 index 0000000000..38bde463f1 --- /dev/null +++ b/src/dawn_native/d3d12/D3D12Error.cpp @@ -0,0 +1,29 @@ +// Copyright 2019 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/d3d12/D3D12Error.h" + +#include + +namespace dawn_native { namespace d3d12 { + MaybeError CheckHRESULT(HRESULT result, const char* context) { + if (DAWN_LIKELY(SUCCEEDED(result))) { + return {}; + } + + std::string message = std::string(context) + " failed with " + std::to_string(result); + return DAWN_DEVICE_LOST_ERROR(message); + } + +}} // namespace dawn_native::d3d12 \ No newline at end of file diff --git a/src/dawn_native/d3d12/D3D12Error.h b/src/dawn_native/d3d12/D3D12Error.h new file mode 100644 index 0000000000..b5f5eb7380 --- /dev/null +++ b/src/dawn_native/d3d12/D3D12Error.h @@ -0,0 +1,28 @@ +// Copyright 2019 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. + +#ifndef DAWNNATIVE_D3D12_D3D12ERROR_H_ +#define DAWNNATIVE_D3D12_D3D12ERROR_H_ + +#include +#include "dawn_native/Error.h" + +namespace dawn_native { namespace d3d12 { + + // Returns a success only if result of HResult is success + MaybeError CheckHRESULT(HRESULT result, const char* context); + +}} // namespace dawn_native::d3d12 + +#endif // DAWNNATIVE_D3D12_D3D12ERROR_H_ \ No newline at end of file diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp index 914100ffc6..f1b2e3120f 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -25,6 +25,7 @@ #include "dawn_native/d3d12/CommandAllocatorManager.h" #include "dawn_native/d3d12/CommandBufferD3D12.h" #include "dawn_native/d3d12/ComputePipelineD3D12.h" +#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DescriptorHeapAllocator.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h" #include "dawn_native/d3d12/PlatformFunctions.h" @@ -56,10 +57,14 @@ namespace dawn_native { namespace d3d12 { D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - ASSERT_SUCCESS(mD3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue))); + DAWN_TRY( + CheckHRESULT(mD3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)), + "D3D12 create command queue")); + + DAWN_TRY(CheckHRESULT(mD3d12Device->CreateFence(mLastSubmittedSerial, D3D12_FENCE_FLAG_NONE, + IID_PPV_ARGS(&mFence)), + "D3D12 create fence")); - ASSERT_SUCCESS(mD3d12Device->CreateFence(mLastSubmittedSerial, D3D12_FENCE_FLAG_NONE, - IID_PPV_ARGS(&mFence))); mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); ASSERT(mFenceEvent != nullptr); @@ -70,7 +75,7 @@ namespace dawn_native { namespace d3d12 { mResourceAllocator = std::make_unique(this); mResourceAllocatorManager = std::make_unique(this); - NextSerial(); + DAWN_TRY(NextSerial()); // Initialize indirect commands D3D12_INDIRECT_ARGUMENT_DESC argumentDesc = {}; @@ -103,8 +108,9 @@ namespace dawn_native { namespace d3d12 { // Immediately forget about all pending commands mPendingCommands.Release(); - NextSerial(); - WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing + ConsumedError(NextSerial()); + // Wait for all in-flight commands to finish executing + ConsumedError(WaitForSerial(mLastSubmittedSerial)); // Call tick one last time so resources are cleaned up. Ignore the return value so we can // continue shutting down in an orderly fashion. @@ -207,27 +213,29 @@ namespace dawn_native { namespace d3d12 { mDynamicUploader->Deallocate(mCompletedSerial); mResourceAllocator->Tick(mCompletedSerial); - mCommandAllocatorManager->Tick(mCompletedSerial); + DAWN_TRY(mCommandAllocatorManager->Tick(mCompletedSerial)); mDescriptorHeapAllocator->Deallocate(mCompletedSerial); mMapRequestTracker->Tick(mCompletedSerial); mUsedComObjectRefs.ClearUpTo(mCompletedSerial); DAWN_TRY(ExecuteCommandContext(nullptr)); - NextSerial(); - + DAWN_TRY(NextSerial()); return {}; } - void Device::NextSerial() { + MaybeError Device::NextSerial() { mLastSubmittedSerial++; - ASSERT_SUCCESS(mCommandQueue->Signal(mFence.Get(), mLastSubmittedSerial)); + return CheckHRESULT(mCommandQueue->Signal(mFence.Get(), mLastSubmittedSerial), + "D3D12 command queue signal fence"); } - void Device::WaitForSerial(uint64_t serial) { + MaybeError Device::WaitForSerial(uint64_t serial) { mCompletedSerial = mFence->GetCompletedValue(); if (mCompletedSerial < serial) { - ASSERT_SUCCESS(mFence->SetEventOnCompletion(serial, mFenceEvent)); + DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(serial, mFenceEvent), + "D3D12 set event on completion")); WaitForSingleObject(mFenceEvent, INFINITE); } + return {}; } void Device::ReferenceUntilUnused(ComPtr object) { @@ -279,14 +287,14 @@ namespace dawn_native { namespace d3d12 { } ResultOrError Device::CreatePipelineLayoutImpl( const PipelineLayoutDescriptor* descriptor) { - return new PipelineLayout(this, descriptor); + return PipelineLayout::Create(this, descriptor); } ResultOrError Device::CreateQueueImpl() { return new Queue(this); } ResultOrError Device::CreateRenderPipelineImpl( const RenderPipelineDescriptor* descriptor) { - return new RenderPipeline(this, descriptor); + return RenderPipeline::Create(this, descriptor); } ResultOrError Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) { return new Sampler(this, descriptor); diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h index c499eeb298..0a00da293b 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.h +++ b/src/dawn_native/d3d12/DeviceD3D12.h @@ -73,8 +73,8 @@ namespace dawn_native { namespace d3d12 { ResultOrError GetPendingCommandContext(); Serial GetPendingCommandSerial() const override; - void NextSerial(); - void WaitForSerial(Serial serial); + MaybeError NextSerial(); + MaybeError WaitForSerial(Serial serial); void ReferenceUntilUnused(ComPtr object); diff --git a/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp b/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp index 2ec24b59ab..1210bb8d60 100644 --- a/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp +++ b/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp @@ -95,7 +95,7 @@ namespace dawn_native { namespace d3d12 { // TODO(cwallez@chromium.org) Currently we force the CPU to wait for the GPU to be finished // with the buffer. Ideally the synchronization should be all done on the GPU. - mDevice->WaitForSerial(mBufferSerials[mCurrentBuffer]); + ASSERT(mDevice->WaitForSerial(mBufferSerials[mCurrentBuffer]).IsSuccess()); return DAWN_SWAP_CHAIN_NO_ERROR; } @@ -105,7 +105,7 @@ namespace dawn_native { namespace d3d12 { ASSERT_SUCCESS(mSwapChain->Present(1, 0)); // TODO(cwallez@chromium.org): Make the serial ticking implicit. - mDevice->NextSerial(); + ASSERT(mDevice->NextSerial().IsSuccess()); mBufferSerials[mCurrentBuffer] = mDevice->GetPendingCommandSerial(); return DAWN_SWAP_CHAIN_NO_ERROR; diff --git a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp index 1b8a219e0f..6c38e68c5d 100644 --- a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp +++ b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp @@ -17,6 +17,7 @@ #include "common/Assert.h" #include "common/BitSetIterator.h" #include "dawn_native/d3d12/BindGroupLayoutD3D12.h" +#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/PlatformFunctions.h" @@ -54,8 +55,17 @@ namespace dawn_native { namespace d3d12 { } } // anonymous namespace - PipelineLayout::PipelineLayout(Device* device, const PipelineLayoutDescriptor* descriptor) - : PipelineLayoutBase(device, descriptor) { + ResultOrError PipelineLayout::Create( + Device* device, + const PipelineLayoutDescriptor* descriptor) { + std::unique_ptr layout = + std::make_unique(device, descriptor); + DAWN_TRY(layout->Initialize()); + return layout.release(); + } + + MaybeError PipelineLayout::Initialize() { + Device* device = ToBackend(GetDevice()); D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2 + kMaxDynamicBufferCount]; // A root parameter is one of these types @@ -148,11 +158,15 @@ namespace dawn_native { namespace d3d12 { ComPtr signature; ComPtr error; - ASSERT_SUCCESS(device->GetFunctions()->d3d12SerializeRootSignature( - &rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); - ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature( - 0, signature->GetBufferPointer(), signature->GetBufferSize(), - IID_PPV_ARGS(&mRootSignature))); + DAWN_TRY(CheckHRESULT( + device->GetFunctions()->d3d12SerializeRootSignature( + &rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error), + "D3D12 serialize root signature")); + DAWN_TRY(CheckHRESULT(device->GetD3D12Device()->CreateRootSignature( + 0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_PPV_ARGS(&mRootSignature)), + "D3D12 create root signature")); + return {}; } uint32_t PipelineLayout::GetCbvUavSrvRootParameterIndex(uint32_t group) const { diff --git a/src/dawn_native/d3d12/PipelineLayoutD3D12.h b/src/dawn_native/d3d12/PipelineLayoutD3D12.h index b2ee9e6bbd..1d6c7e56b9 100644 --- a/src/dawn_native/d3d12/PipelineLayoutD3D12.h +++ b/src/dawn_native/d3d12/PipelineLayoutD3D12.h @@ -25,7 +25,8 @@ namespace dawn_native { namespace d3d12 { class PipelineLayout : public PipelineLayoutBase { public: - PipelineLayout(Device* device, const PipelineLayoutDescriptor* descriptor); + static ResultOrError Create(Device* device, + const PipelineLayoutDescriptor* descriptor); uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const; uint32_t GetSamplerRootParameterIndex(uint32_t group) const; @@ -36,6 +37,8 @@ namespace dawn_native { namespace d3d12 { ComPtr GetRootSignature() const; private: + using PipelineLayoutBase::PipelineLayoutBase; + MaybeError Initialize(); std::array mCbvUavSrvRootParameterInfo; std::array mSamplerRootParameterInfo; std::array, kMaxBindGroups> diff --git a/src/dawn_native/d3d12/QueueD3D12.cpp b/src/dawn_native/d3d12/QueueD3D12.cpp index ccda50ccc1..8c50bd78b9 100644 --- a/src/dawn_native/d3d12/QueueD3D12.cpp +++ b/src/dawn_native/d3d12/QueueD3D12.cpp @@ -15,6 +15,7 @@ #include "dawn_native/d3d12/QueueD3D12.h" #include "dawn_native/d3d12/CommandBufferD3D12.h" +#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DeviceD3D12.h" namespace dawn_native { namespace d3d12 { @@ -35,7 +36,7 @@ namespace dawn_native { namespace d3d12 { DAWN_TRY(device->ExecuteCommandContext(&mCommandContext)); - device->NextSerial(); + DAWN_TRY(device->NextSerial()); return {}; } diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp index 92c286535a..82fd037d05 100644 --- a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp +++ b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp @@ -15,6 +15,7 @@ #include "dawn_native/d3d12/RenderPipelineD3D12.h" #include "common/Assert.h" +#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h" #include "dawn_native/d3d12/PlatformFunctions.h" @@ -288,9 +289,17 @@ namespace dawn_native { namespace d3d12 { } // anonymous namespace - RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor) - : RenderPipelineBase(device, descriptor), - mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())) { + ResultOrError RenderPipeline::Create( + Device* device, + const RenderPipelineDescriptor* descriptor) { + std::unique_ptr pipeline = + std::make_unique(device, descriptor); + DAWN_TRY(pipeline->Initialize(descriptor)); + return pipeline.release(); + } + + MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor* descriptor) { + Device* device = ToBackend(GetDevice()); uint32_t compileFlags = 0; #if defined(_DEBUG) // Enable better shader debugging with the graphics debugging tools. @@ -391,8 +400,12 @@ namespace dawn_native { namespace d3d12 { descriptorD3D12.SampleDesc.Count = GetSampleCount(); descriptorD3D12.SampleDesc.Quality = 0; - ASSERT_SUCCESS(device->GetD3D12Device()->CreateGraphicsPipelineState( - &descriptorD3D12, IID_PPV_ARGS(&mPipelineState))); + mD3d12PrimitiveTopology = D3D12PrimitiveTopology(GetPrimitiveTopology()); + + DAWN_TRY(CheckHRESULT(device->GetD3D12Device()->CreateGraphicsPipelineState( + &descriptorD3D12, IID_PPV_ARGS(&mPipelineState)), + "D3D12 create graphics pipeline state")); + return {}; } RenderPipeline::~RenderPipeline() { diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.h b/src/dawn_native/d3d12/RenderPipelineD3D12.h index b9c9029eef..affd5fe733 100644 --- a/src/dawn_native/d3d12/RenderPipelineD3D12.h +++ b/src/dawn_native/d3d12/RenderPipelineD3D12.h @@ -25,13 +25,16 @@ namespace dawn_native { namespace d3d12 { class RenderPipeline : public RenderPipelineBase { public: - RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor); + static ResultOrError Create(Device* device, + const RenderPipelineDescriptor* descriptor); ~RenderPipeline(); D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const; ComPtr GetPipelineState(); private: + using RenderPipelineBase::RenderPipelineBase; + MaybeError Initialize(const RenderPipelineDescriptor* descriptor); D3D12_INPUT_LAYOUT_DESC ComputeInputLayout( std::array* inputElementDescriptors);