D3D12: Keep a reference to pipelines until unused
Previously we would remove the reference to pipelines in the destructor of the d3d12::*Pipeline objects which could cause the D3D12 pipeline state to be destroyed while still used by in-flight commands. Add a global queue of ComPtrs to keep alive in the d3d12::Device to fix this.
This commit is contained in:
parent
57f7bc750a
commit
cf0ac7570d
|
@ -24,7 +24,7 @@
|
|||
namespace backend { namespace d3d12 {
|
||||
|
||||
ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
|
||||
: ComputePipelineBase(builder) {
|
||||
: ComputePipelineBase(builder), mDevice(ToBackend(builder->GetDevice())) {
|
||||
uint32_t compileFlags = 0;
|
||||
#if defined(_DEBUG)
|
||||
// Enable better shader debugging with the graphics debugging tools.
|
||||
|
@ -57,6 +57,10 @@ namespace backend { namespace d3d12 {
|
|||
IID_PPV_ARGS(&mPipelineState));
|
||||
}
|
||||
|
||||
ComputePipeline::~ComputePipeline() {
|
||||
mDevice->ReferenceUntilUnused(mPipelineState);
|
||||
}
|
||||
|
||||
ComPtr<ID3D12PipelineState> ComputePipeline::GetPipelineState() {
|
||||
return mPipelineState;
|
||||
}
|
||||
|
|
|
@ -21,14 +21,18 @@
|
|||
|
||||
namespace backend { namespace d3d12 {
|
||||
|
||||
class Device;
|
||||
|
||||
class ComputePipeline : public ComputePipelineBase {
|
||||
public:
|
||||
ComputePipeline(ComputePipelineBuilder* builder);
|
||||
~ComputePipeline();
|
||||
|
||||
ComPtr<ID3D12PipelineState> GetPipelineState();
|
||||
|
||||
private:
|
||||
ComPtr<ID3D12PipelineState> mPipelineState;
|
||||
Device* mDevice = nullptr;
|
||||
};
|
||||
|
||||
}} // namespace backend::d3d12
|
||||
|
|
|
@ -149,6 +149,8 @@ namespace backend { namespace d3d12 {
|
|||
NextSerial();
|
||||
WaitForSerial(currentSerial); // Wait for all in-flight commands to finish executing
|
||||
TickImpl(); // Call tick one last time so resources are cleaned up
|
||||
ASSERT(mUsedComObjectRefs.Empty());
|
||||
|
||||
delete mCommandAllocatorManager;
|
||||
delete mDescriptorHeapAllocator;
|
||||
delete mMapReadRequestTracker;
|
||||
|
@ -214,6 +216,7 @@ namespace backend { namespace d3d12 {
|
|||
mCommandAllocatorManager->Tick(lastCompletedSerial);
|
||||
mDescriptorHeapAllocator->Tick(lastCompletedSerial);
|
||||
mMapReadRequestTracker->Tick(lastCompletedSerial);
|
||||
mUsedComObjectRefs.ClearUpTo(lastCompletedSerial);
|
||||
ExecuteCommandLists({});
|
||||
NextSerial();
|
||||
}
|
||||
|
@ -234,6 +237,10 @@ namespace backend { namespace d3d12 {
|
|||
}
|
||||
}
|
||||
|
||||
void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
|
||||
mUsedComObjectRefs.Enqueue(object, mSerial);
|
||||
}
|
||||
|
||||
void Device::ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists) {
|
||||
// If there are pending commands, prepend them to ExecuteCommandLists
|
||||
if (mPendingCommands.open) {
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "backend/Device.h"
|
||||
#include "backend/RenderPass.h"
|
||||
#include "backend/ToBackend.h"
|
||||
|
||||
#include "backend/d3d12/d3d12_platform.h"
|
||||
#include "common/SerialQueue.h"
|
||||
|
||||
namespace backend { namespace d3d12 {
|
||||
|
||||
|
@ -127,6 +127,8 @@ namespace backend { namespace d3d12 {
|
|||
void NextSerial();
|
||||
void WaitForSerial(uint64_t serial);
|
||||
|
||||
void ReferenceUntilUnused(ComPtr<IUnknown> object);
|
||||
|
||||
void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists);
|
||||
|
||||
private:
|
||||
|
@ -149,6 +151,8 @@ namespace backend { namespace d3d12 {
|
|||
ComPtr<ID3D12GraphicsCommandList> commandList;
|
||||
bool open = false;
|
||||
} mPendingCommands;
|
||||
|
||||
SerialQueue<ComPtr<IUnknown>> mUsedComObjectRefs;
|
||||
};
|
||||
|
||||
class RenderPass : public RenderPassBase {
|
||||
|
|
|
@ -64,7 +64,8 @@ namespace backend { namespace d3d12 {
|
|||
|
||||
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
|
||||
: RenderPipelineBase(builder),
|
||||
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())) {
|
||||
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())),
|
||||
mDevice(ToBackend(builder->GetDevice())) {
|
||||
uint32_t compileFlags = 0;
|
||||
#if defined(_DEBUG)
|
||||
// Enable better shader debugging with the graphics debugging tools.
|
||||
|
@ -171,6 +172,10 @@ namespace backend { namespace d3d12 {
|
|||
&descriptor, IID_PPV_ARGS(&mPipelineState)));
|
||||
}
|
||||
|
||||
RenderPipeline::~RenderPipeline() {
|
||||
mDevice->ReferenceUntilUnused(mPipelineState);
|
||||
}
|
||||
|
||||
D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const {
|
||||
return mD3d12PrimitiveTopology;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,12 @@
|
|||
|
||||
namespace backend { namespace d3d12 {
|
||||
|
||||
class Device;
|
||||
|
||||
class RenderPipeline : public RenderPipelineBase {
|
||||
public:
|
||||
RenderPipeline(RenderPipelineBuilder* builder);
|
||||
~RenderPipeline();
|
||||
|
||||
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
|
||||
ComPtr<ID3D12PipelineState> GetPipelineState();
|
||||
|
@ -31,6 +34,8 @@ namespace backend { namespace d3d12 {
|
|||
private:
|
||||
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
|
||||
ComPtr<ID3D12PipelineState> mPipelineState;
|
||||
|
||||
Device* mDevice = nullptr;
|
||||
};
|
||||
|
||||
}} // namespace backend::d3d12
|
||||
|
|
Loading…
Reference in New Issue