修复 D3D12 截图功能:修复 GPU 过载导致的设备移除问题

问题根因:
1. 渲染循环帧率过高导致 GPU 过载(TDR)
2. D3D12CommandList::Reset() 未正确调用底层 Reset()

修复内容:
1. 在 Present 后添加 Sleep(10) 延迟防止 GPU 过载
2. 修复 D3D12CommandList::Reset() 正确调用底层 m_commandList->Reset()
3. 在 D3D12CommandList 中存储 CommandAllocator 引用
4. 在 main_minimal.cpp 中添加截图调用逻辑(30帧后截图保存为 minimal.ppm)

修改文件:
- engine/include/XCEngine/RHI/D3D12/D3D12CommandList.h
- engine/src/RHI/D3D12/D3D12CommandList.cpp
- tests/RHI/D3D12/integration/main_minimal.cpp (新增)
This commit is contained in:
2026-03-20 02:25:15 +08:00
parent 7e1782e203
commit a647f5e8ec
3 changed files with 377 additions and 2 deletions

View File

@@ -64,7 +64,9 @@ public:
void SetGraphicsRootDescriptorTable(uint32_t rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor);
void SetGraphicsRootShaderResourceView(uint32_t rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS shaderResource);
void SetStencilRef(uint32_t stencilRef);
void SetStencilRef(uint8_t stencilRef) override;
void SetDepthStencilState(const DepthStencilState& state) override;
void SetBlendState(const BlendState& state) override;
void SetBlendFactor(const float blendFactor[4]);
void SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp);
@@ -104,6 +106,7 @@ public:
private:
ComPtr<ID3D12GraphicsCommandList> m_commandList;
ComPtr<ID3D12CommandAllocator> m_commandAllocator;
CommandQueueType m_type;
std::unordered_map<ID3D12Resource*, ResourceStates> m_resourceStateMap;

View File

@@ -18,6 +18,8 @@ D3D12CommandList::~D3D12CommandList() {
bool D3D12CommandList::Initialize(ID3D12Device* device, CommandQueueType type, ID3D12CommandAllocator* allocator) {
D3D12_COMMAND_LIST_TYPE listType = ToD3D12(type);
m_commandAllocator = allocator;
HRESULT hResult = device->CreateCommandList(
0,
listType,
@@ -42,10 +44,15 @@ void D3D12CommandList::Shutdown() {
}
void D3D12CommandList::Reset() {
if (m_commandList && m_commandAllocator) {
m_commandList->Reset(m_commandAllocator.Get(), nullptr);
}
m_currentTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
m_currentPipelineState = nullptr;
m_currentRootSignature = nullptr;
m_currentDescriptorHeap = nullptr;
m_resourceStateMap.clear();
m_trackedResources.clear();
}
void D3D12CommandList::Close() {
@@ -106,6 +113,15 @@ void D3D12CommandList::SetPipelineStateInternal(ID3D12PipelineState* pso) {
m_currentPipelineState = pso;
}
void D3D12CommandList::SetRootSignature(ID3D12RootSignature* signature) {
m_commandList->SetGraphicsRootSignature(signature);
m_currentRootSignature = signature;
}
void D3D12CommandList::SetBlendFactor(const float blendFactor[4]) {
m_commandList->OMSetBlendFactor(blendFactor);
}
void D3D12CommandList::SetViewport(const Viewport& viewport) {
D3D12_VIEWPORT d3d12Viewport = {};
d3d12Viewport.TopLeftX = viewport.topLeftX;
@@ -179,6 +195,10 @@ void D3D12CommandList::SetRenderTargetsInternal(uint32_t count, ID3D12Resource**
m_commandList->OMSetRenderTargets(count, count > 0 ? rtvHandles.data() : nullptr, FALSE, depthStencil ? &dsvHandle : nullptr);
}
void D3D12CommandList::SetRenderTargetsHandle(uint32_t count, const D3D12_CPU_DESCRIPTOR_HANDLE* renderTargetHandles, const D3D12_CPU_DESCRIPTOR_HANDLE* depthStencilHandle) {
m_commandList->OMSetRenderTargets(count, renderTargetHandles, FALSE, depthStencilHandle);
}
void D3D12CommandList::SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) {
SetVertexBufferInternal(slot, static_cast<ID3D12Resource*>(buffer), offset, stride);
}
@@ -252,10 +272,18 @@ void D3D12CommandList::SetGraphicsRootShaderResourceView(uint32_t rootParameterI
m_commandList->SetGraphicsRootShaderResourceView(rootParameterIndex, shaderResource);
}
void D3D12CommandList::SetStencilRef(uint32_t stencilRef) {
void D3D12CommandList::SetStencilRef(uint8_t stencilRef) {
m_commandList->OMSetStencilRef(stencilRef);
}
void D3D12CommandList::SetDepthStencilState(const DepthStencilState& state) {
// TODO: Implement depth stencil state
}
void D3D12CommandList::SetBlendState(const BlendState& state) {
// TODO: Implement blend state
}
void D3D12CommandList::SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp) {
}
@@ -292,6 +320,18 @@ void D3D12CommandList::ClearRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE renderT
m_commandList->ClearRenderTargetView(renderTargetHandle, color, rectCount, rects);
}
void D3D12CommandList::Clear(float r, float g, float b, float a, uint32_t buffers) {
// Not implemented - use ClearRenderTargetView and ClearDepthStencilView directly
}
void D3D12CommandList::ClearRenderTarget(void* renderTarget, const float color[4]) {
ClearRenderTargetView(static_cast<ID3D12Resource*>(renderTarget), color, 0, nullptr);
}
void D3D12CommandList::ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) {
ClearDepthStencilView(static_cast<ID3D12Resource*>(depthStencil), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, depth, stencil, 0, nullptr);
}
void D3D12CommandList::ClearDepthStencilView(ID3D12Resource* depthStencil, uint32_t clearFlags, float depth, uint8_t stencil, uint32_t rectCount, const D3D12_RECT* rects) {
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = {};
m_commandList->ClearDepthStencilView(dsvHandle, static_cast<D3D12_CLEAR_FLAGS>(clearFlags), depth, stencil, rectCount, rects);