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 {
|
namespace backend { namespace d3d12 {
|
||||||
|
|
||||||
ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
|
ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
|
||||||
: ComputePipelineBase(builder) {
|
: ComputePipelineBase(builder), mDevice(ToBackend(builder->GetDevice())) {
|
||||||
uint32_t compileFlags = 0;
|
uint32_t compileFlags = 0;
|
||||||
#if defined(_DEBUG)
|
#if defined(_DEBUG)
|
||||||
// Enable better shader debugging with the graphics debugging tools.
|
// Enable better shader debugging with the graphics debugging tools.
|
||||||
|
@ -57,6 +57,10 @@ namespace backend { namespace d3d12 {
|
||||||
IID_PPV_ARGS(&mPipelineState));
|
IID_PPV_ARGS(&mPipelineState));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ComputePipeline::~ComputePipeline() {
|
||||||
|
mDevice->ReferenceUntilUnused(mPipelineState);
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<ID3D12PipelineState> ComputePipeline::GetPipelineState() {
|
ComPtr<ID3D12PipelineState> ComputePipeline::GetPipelineState() {
|
||||||
return mPipelineState;
|
return mPipelineState;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,18 @@
|
||||||
|
|
||||||
namespace backend { namespace d3d12 {
|
namespace backend { namespace d3d12 {
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
|
||||||
class ComputePipeline : public ComputePipelineBase {
|
class ComputePipeline : public ComputePipelineBase {
|
||||||
public:
|
public:
|
||||||
ComputePipeline(ComputePipelineBuilder* builder);
|
ComputePipeline(ComputePipelineBuilder* builder);
|
||||||
|
~ComputePipeline();
|
||||||
|
|
||||||
ComPtr<ID3D12PipelineState> GetPipelineState();
|
ComPtr<ID3D12PipelineState> GetPipelineState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ComPtr<ID3D12PipelineState> mPipelineState;
|
ComPtr<ID3D12PipelineState> mPipelineState;
|
||||||
|
Device* mDevice = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace backend::d3d12
|
}} // namespace backend::d3d12
|
||||||
|
|
|
@ -149,6 +149,8 @@ namespace backend { namespace d3d12 {
|
||||||
NextSerial();
|
NextSerial();
|
||||||
WaitForSerial(currentSerial); // Wait for all in-flight commands to finish executing
|
WaitForSerial(currentSerial); // Wait for all in-flight commands to finish executing
|
||||||
TickImpl(); // Call tick one last time so resources are cleaned up
|
TickImpl(); // Call tick one last time so resources are cleaned up
|
||||||
|
ASSERT(mUsedComObjectRefs.Empty());
|
||||||
|
|
||||||
delete mCommandAllocatorManager;
|
delete mCommandAllocatorManager;
|
||||||
delete mDescriptorHeapAllocator;
|
delete mDescriptorHeapAllocator;
|
||||||
delete mMapReadRequestTracker;
|
delete mMapReadRequestTracker;
|
||||||
|
@ -214,6 +216,7 @@ namespace backend { namespace d3d12 {
|
||||||
mCommandAllocatorManager->Tick(lastCompletedSerial);
|
mCommandAllocatorManager->Tick(lastCompletedSerial);
|
||||||
mDescriptorHeapAllocator->Tick(lastCompletedSerial);
|
mDescriptorHeapAllocator->Tick(lastCompletedSerial);
|
||||||
mMapReadRequestTracker->Tick(lastCompletedSerial);
|
mMapReadRequestTracker->Tick(lastCompletedSerial);
|
||||||
|
mUsedComObjectRefs.ClearUpTo(lastCompletedSerial);
|
||||||
ExecuteCommandLists({});
|
ExecuteCommandLists({});
|
||||||
NextSerial();
|
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) {
|
void Device::ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists) {
|
||||||
// If there are pending commands, prepend them to ExecuteCommandLists
|
// If there are pending commands, prepend them to ExecuteCommandLists
|
||||||
if (mPendingCommands.open) {
|
if (mPendingCommands.open) {
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
#include "backend/Device.h"
|
#include "backend/Device.h"
|
||||||
#include "backend/RenderPass.h"
|
#include "backend/RenderPass.h"
|
||||||
#include "backend/ToBackend.h"
|
#include "backend/ToBackend.h"
|
||||||
|
|
||||||
#include "backend/d3d12/d3d12_platform.h"
|
#include "backend/d3d12/d3d12_platform.h"
|
||||||
|
#include "common/SerialQueue.h"
|
||||||
|
|
||||||
namespace backend { namespace d3d12 {
|
namespace backend { namespace d3d12 {
|
||||||
|
|
||||||
|
@ -127,6 +127,8 @@ namespace backend { namespace d3d12 {
|
||||||
void NextSerial();
|
void NextSerial();
|
||||||
void WaitForSerial(uint64_t serial);
|
void WaitForSerial(uint64_t serial);
|
||||||
|
|
||||||
|
void ReferenceUntilUnused(ComPtr<IUnknown> object);
|
||||||
|
|
||||||
void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists);
|
void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -149,6 +151,8 @@ namespace backend { namespace d3d12 {
|
||||||
ComPtr<ID3D12GraphicsCommandList> commandList;
|
ComPtr<ID3D12GraphicsCommandList> commandList;
|
||||||
bool open = false;
|
bool open = false;
|
||||||
} mPendingCommands;
|
} mPendingCommands;
|
||||||
|
|
||||||
|
SerialQueue<ComPtr<IUnknown>> mUsedComObjectRefs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderPass : public RenderPassBase {
|
class RenderPass : public RenderPassBase {
|
||||||
|
|
|
@ -64,7 +64,8 @@ namespace backend { namespace d3d12 {
|
||||||
|
|
||||||
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
|
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
|
||||||
: RenderPipelineBase(builder),
|
: RenderPipelineBase(builder),
|
||||||
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())) {
|
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())),
|
||||||
|
mDevice(ToBackend(builder->GetDevice())) {
|
||||||
uint32_t compileFlags = 0;
|
uint32_t compileFlags = 0;
|
||||||
#if defined(_DEBUG)
|
#if defined(_DEBUG)
|
||||||
// Enable better shader debugging with the graphics debugging tools.
|
// Enable better shader debugging with the graphics debugging tools.
|
||||||
|
@ -171,6 +172,10 @@ namespace backend { namespace d3d12 {
|
||||||
&descriptor, IID_PPV_ARGS(&mPipelineState)));
|
&descriptor, IID_PPV_ARGS(&mPipelineState)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderPipeline::~RenderPipeline() {
|
||||||
|
mDevice->ReferenceUntilUnused(mPipelineState);
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const {
|
D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const {
|
||||||
return mD3d12PrimitiveTopology;
|
return mD3d12PrimitiveTopology;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,12 @@
|
||||||
|
|
||||||
namespace backend { namespace d3d12 {
|
namespace backend { namespace d3d12 {
|
||||||
|
|
||||||
|
class Device;
|
||||||
|
|
||||||
class RenderPipeline : public RenderPipelineBase {
|
class RenderPipeline : public RenderPipelineBase {
|
||||||
public:
|
public:
|
||||||
RenderPipeline(RenderPipelineBuilder* builder);
|
RenderPipeline(RenderPipelineBuilder* builder);
|
||||||
|
~RenderPipeline();
|
||||||
|
|
||||||
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
|
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
|
||||||
ComPtr<ID3D12PipelineState> GetPipelineState();
|
ComPtr<ID3D12PipelineState> GetPipelineState();
|
||||||
|
@ -31,6 +34,8 @@ namespace backend { namespace d3d12 {
|
||||||
private:
|
private:
|
||||||
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
|
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
|
||||||
ComPtr<ID3D12PipelineState> mPipelineState;
|
ComPtr<ID3D12PipelineState> mPipelineState;
|
||||||
|
|
||||||
|
Device* mDevice = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace backend::d3d12
|
}} // namespace backend::d3d12
|
||||||
|
|
Loading…
Reference in New Issue