mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-20 14:22:00 +00:00
[idd] avoid release frame timeouts during replug
Drop frames when the LGMP queue is full instead of blocking while holding an IddCx surface. Always finish every acquired frame, including duplicate frame numbers, so replug teardown cannot trigger the release-frame watchdog.
This commit is contained in:
@@ -923,13 +923,19 @@ void CIndirectDeviceContext::LGMPTimer()
|
||||
ResendCursor();
|
||||
}
|
||||
|
||||
bool CIndirectDeviceContext::FrameBufferAvailable() const
|
||||
{
|
||||
return m_lgmp && m_frameQueue &&
|
||||
lgmpHostQueuePending(m_frameQueue) < LGMP_Q_FRAME_LEN;
|
||||
}
|
||||
|
||||
CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrameBuffer(
|
||||
unsigned pitch, const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
|
||||
const RECT * dirtyRects, unsigned nbDirtyRects)
|
||||
{
|
||||
PreparedFrameBuffer result = {};
|
||||
|
||||
if (!m_lgmp || !m_frameQueue)
|
||||
if (!FrameBufferAvailable())
|
||||
return result;
|
||||
|
||||
if (m_width != dstFormat.desc.Width ||
|
||||
@@ -988,10 +994,6 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
||||
|
||||
KVMFRFrame * fi = m_frame[m_frameIndex];
|
||||
|
||||
// wait until there is room in the queue
|
||||
while (lgmpHostQueuePending(m_frameQueue) == LGMP_Q_FRAME_LEN)
|
||||
Sleep(0);
|
||||
|
||||
if (dstFormat.format == FRAME_TYPE_INVALID)
|
||||
{
|
||||
DEBUG_ERROR("Unsupported frame format, skipping frame");
|
||||
|
||||
@@ -210,6 +210,7 @@ public:
|
||||
uint8_t* mem;
|
||||
};
|
||||
|
||||
bool FrameBufferAvailable() const;
|
||||
PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch, const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat, const RECT * dirtyRects, unsigned nbDirtyRects);
|
||||
bool PublishFrameBuffer(unsigned frameIndex);
|
||||
void WriteFrameBuffer(unsigned frameIndex, void* src, size_t offset, size_t len, bool setWritePos) const;
|
||||
|
||||
@@ -226,18 +226,18 @@ bool CSwapChainProcessor::SwapChainThreadCore()
|
||||
lastFrameNumber = frameNumber;
|
||||
if (!SwapChainNewFrame(surface, dirtyRectCount, colorSpace, sdrWhiteLevel))
|
||||
DEBUG_WARN("Failed to submit frame");
|
||||
}
|
||||
|
||||
// report that all GPU processing for this frame has been queued
|
||||
hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// A lost path is normal (mode change/topology rebuild); Windows
|
||||
// reassigns a fresh swap chain. Just exit and let it.
|
||||
if (hr != STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY)
|
||||
DEBUG_ERROR_HR(hr, "IddCxSwapChainFinishedProcessingFrame Failed");
|
||||
break;
|
||||
}
|
||||
|
||||
// Every acquired frame must be finished before the next acquire, even if
|
||||
// its presentation number was a duplicate and no work was submitted.
|
||||
hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// A lost path is normal (mode change/topology rebuild); Windows
|
||||
// reassigns a fresh swap chain. Just exit and let it.
|
||||
if (hr != STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY)
|
||||
DEBUG_ERROR_HR(hr, "IddCxSwapChainFinishedProcessingFrame Failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -339,6 +339,11 @@ static FrameType GetFrameType(DXGI_FORMAT format)
|
||||
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
||||
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel)
|
||||
{
|
||||
// Never hold an IddCx frame waiting for a slow or disconnected client. In
|
||||
// particular, monitor departure cannot complete until the frame is released.
|
||||
if (!m_devContext->FrameBufferAvailable())
|
||||
return true;
|
||||
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
HRESULT hr = acquiredBuffer.As(&texture);
|
||||
if (FAILED(hr))
|
||||
@@ -532,8 +537,10 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
||||
frameDirtyRects,
|
||||
frameDirtyRectCount);
|
||||
|
||||
// The LGMP timer can fill the queue with a subscriber resend after the early
|
||||
// availability check. Treat this as a dropped frame rather than an error.
|
||||
if (!buffer.mem)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
CFrameBufferResource * fbRes = m_fbPool.Get(buffer,
|
||||
(size_t)layout.Footprint.RowPitch * dstFormat.desc.Height);
|
||||
|
||||
Reference in New Issue
Block a user