From 94fbbad21cd40f5d5b6ee67e8f1882a5c806e624 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sun, 30 Mar 2025 18:58:03 +1100 Subject: [PATCH] [idd] driver: handle command queue failures gracefully --- idd/LGIdd/CD3D12CommandQueue.cpp | 31 +++++++++++++++++++------------ idd/LGIdd/CD3D12CommandQueue.h | 8 ++++++-- idd/LGIdd/CSwapChainProcessor.cpp | 18 +++++++++++++----- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/idd/LGIdd/CD3D12CommandQueue.cpp b/idd/LGIdd/CD3D12CommandQueue.cpp index d19e7842..5b11a0e3 100644 --- a/idd/LGIdd/CD3D12CommandQueue.cpp +++ b/idd/LGIdd/CD3D12CommandQueue.cpp @@ -33,7 +33,7 @@ bool CD3D12CommandQueue::Init(ID3D12Device3 * device, D3D12_COMMAND_LIST_TYPE ty } m_gfxList->SetName(name); - m_cmdList = m_gfxList; + m_cmdList = m_gfxList; if (!m_cmdList) { DEBUG_ERROR_HR(hr, "Failed to get the CommandList (%ls)", name); @@ -58,13 +58,15 @@ bool CD3D12CommandQueue::Init(ID3D12Device3 * device, D3D12_COMMAND_LIST_TYPE ty { ULONG flags = (callbackMode == FAST) ? WT_EXECUTEINWAITTHREAD : WT_EXECUTEINPERSISTENTTHREAD; - + RegisterWaitForSingleObject( &m_waitHandle, m_event.Get(), [](PVOID param, BOOLEAN timeout){ - if (!timeout) - ((CD3D12CommandQueue*)param)->OnCompletion(); + CD3D12CommandQueue * queue = (CD3D12CommandQueue*)param; + if (timeout) + queue->m_completionResult = false; + queue->OnCompletion(); }, this, INFINITE, @@ -88,28 +90,35 @@ void CD3D12CommandQueue::DeInit() bool CD3D12CommandQueue::Execute() { + m_needsReset = true; + m_completionResult = true; + HRESULT hr = m_gfxList->Close(); if (FAILED(hr)) { + m_completionResult = false; + SetEvent(m_event.Get()); + DEBUG_ERROR_HR(hr, "Failed to close the command list (%ls)", m_name); return false; } ID3D12CommandList * lists[] = { m_cmdList.Get() }; m_queue->ExecuteCommandLists(1, lists); - - m_pending = true; - m_needsReset = true; ++m_fenceValue; - m_fence->SetEventOnCompletion(m_fenceValue, m_event.Get()); - m_queue->Signal(m_fence.Get(), m_fenceValue); + hr = m_fence->SetEventOnCompletion(m_fenceValue, m_event.Get()); if (FAILED(hr)) { + m_completionResult = false; + SetEvent(m_event.Get()); + DEBUG_ERROR_HR(hr, "Failed to set the fence signal (%ls)", m_name); return false; } + m_pending = true; + m_queue->Signal(m_fence.Get(), m_fenceValue); return true; } @@ -134,7 +143,7 @@ bool CD3D12CommandQueue::Reset() return true; HRESULT hr; - + hr = m_allocator->Reset(); if (FAILED(hr)) { @@ -152,5 +161,3 @@ bool CD3D12CommandQueue::Reset() m_needsReset = false; return true; } - - diff --git a/idd/LGIdd/CD3D12CommandQueue.h b/idd/LGIdd/CD3D12CommandQueue.h index 11fae150..425ad8c8 100644 --- a/idd/LGIdd/CD3D12CommandQueue.h +++ b/idd/LGIdd/CD3D12CommandQueue.h @@ -26,15 +26,19 @@ class CD3D12CommandQueue UINT64 m_fenceValue = 0; bool m_needsReset = false; - typedef void (*CompletionFunction)(CD3D12CommandQueue * queue, void * param1, void * param2); + typedef void (*CompletionFunction)(CD3D12CommandQueue * queue, + bool result, void * param1, void * param2); + CompletionFunction m_completionCallback = nullptr; void * m_completionParams[2]; + bool m_completionResult = true; void OnCompletion() { if (m_completionCallback) m_completionCallback( this, + m_completionResult, m_completionParams[0], m_completionParams[1]); m_pending = false; @@ -71,4 +75,4 @@ class CD3D12CommandQueue ComPtr GetCmdQueue() { return m_queue; } ComPtr GetGfxList() { return m_gfxList; } -}; \ No newline at end of file +}; diff --git a/idd/LGIdd/CSwapChainProcessor.cpp b/idd/LGIdd/CSwapChainProcessor.cpp index bb455e7c..dc7a2530 100644 --- a/idd/LGIdd/CSwapChainProcessor.cpp +++ b/idd/LGIdd/CSwapChainProcessor.cpp @@ -71,7 +71,7 @@ void CSwapChainProcessor::SwapChainThread() } void CSwapChainProcessor::SwapChainThreadCore() -{ +{ ComPtr dxgiDevice; HRESULT hr = m_dx11Device->GetDevice().As(&dxgiDevice); if (FAILED(hr)) @@ -153,13 +153,21 @@ void CSwapChainProcessor::SwapChainThreadCore() } } -void CSwapChainProcessor::CompletionFunction(CD3D12CommandQueue * queue, void * param1, void * param2) +void CSwapChainProcessor::CompletionFunction( + CD3D12CommandQueue * queue, bool result, void * param1, void * param2) { UNREFERENCED_PARAMETER(queue); auto sc = (CSwapChainProcessor *)param1; auto fbRes = (CFrameBufferResource*)param2; + // fail gracefully + if (!result) + { + sc->m_devContext->FinalizeFrameBuffer(fbRes->GetFrameIndex()); + return; + } + if (sc->m_dx12Device->IsIndirectCopy()) sc->m_devContext->WriteFrameBuffer( fbRes->GetFrameIndex(), @@ -170,7 +178,7 @@ void CSwapChainProcessor::CompletionFunction(CD3D12CommandQueue * queue, void * bool CSwapChainProcessor::SwapChainNewFrame(ComPtr acquiredBuffer) { - ComPtr texture; + ComPtr texture; HRESULT hr = acquiredBuffer.As(&texture); if (FAILED(hr)) { @@ -221,7 +229,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr acquiredBuffer } copyQueue->SetCompletionCallback(&CompletionFunction, this, fbRes); - + D3D12_TEXTURE_COPY_LOCATION srcLoc = {}; srcLoc.pResource = srcRes->GetRes().Get(); srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; @@ -243,4 +251,4 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr acquiredBuffer copyQueue->Execute(); return true; -} \ No newline at end of file +}