mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-21 06:42:02 +00:00
[idd] accumulate damage from dropped frames
This commit is contained in:
@@ -357,19 +357,65 @@ static FrameType GetFrameType(DXGI_FORMAT format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSwapChainProcessor::SetFullPendingDamage()
|
||||||
|
{
|
||||||
|
m_hasPendingDamage = true;
|
||||||
|
m_nbPendingDirtyRects = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSwapChainProcessor::AccumulateFrameDamage(
|
||||||
|
const RECT * dirtyRects, unsigned nbDirtyRects)
|
||||||
|
{
|
||||||
|
if (nbDirtyRects > LG_MAX_DIRTY_RECTS)
|
||||||
|
nbDirtyRects = 0;
|
||||||
|
|
||||||
|
if (!m_hasPendingDamage)
|
||||||
|
{
|
||||||
|
m_hasPendingDamage = true;
|
||||||
|
m_nbPendingDirtyRects = nbDirtyRects;
|
||||||
|
if (nbDirtyRects)
|
||||||
|
memcpy(m_pendingDirtyRects, dirtyRects,
|
||||||
|
nbDirtyRects * sizeof(*m_pendingDirtyRects));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero dirty rectangles represents full-frame damage. Once any skipped
|
||||||
|
// frame requires a full update, no later rectangles can narrow it again.
|
||||||
|
if (m_nbPendingDirtyRects == 0 || nbDirtyRects == 0)
|
||||||
|
{
|
||||||
|
m_nbPendingDirtyRects = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_nbPendingDirtyRects + nbDirtyRects > LG_MAX_DIRTY_RECTS)
|
||||||
|
{
|
||||||
|
m_nbPendingDirtyRects = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m_pendingDirtyRects + m_nbPendingDirtyRects, dirtyRects,
|
||||||
|
nbDirtyRects * sizeof(*m_pendingDirtyRects));
|
||||||
|
m_nbPendingDirtyRects += nbDirtyRects;
|
||||||
|
}
|
||||||
|
|
||||||
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
||||||
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel)
|
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel)
|
||||||
{
|
{
|
||||||
// Never hold an IddCx frame waiting for a slow or disconnected client. In
|
// Preserve the fast drop path: never hold an IddCx frame while waiting for
|
||||||
// particular, monitor departure cannot complete until the frame is released.
|
// a slow or disconnected client. We have not read its rectangles, so force
|
||||||
|
// the next published frame to invalidate the entire image.
|
||||||
if (!m_devContext->FrameBufferAvailable())
|
if (!m_devContext->FrameBufferAvailable())
|
||||||
|
{
|
||||||
|
SetFullPendingDamage();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<ID3D11Texture2D> texture;
|
ComPtr<ID3D11Texture2D> texture;
|
||||||
HRESULT hr = acquiredBuffer.As(&texture);
|
HRESULT hr = acquiredBuffer.As(&texture);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR_HR(hr, "Failed to obtain the ID3D11Texture2D from the acquiredBuffer");
|
DEBUG_ERROR_HR(hr, "Failed to obtain the ID3D11Texture2D from the acquiredBuffer");
|
||||||
|
SetFullPendingDamage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,6 +423,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
if (!srcRes)
|
if (!srcRes)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to get a CInteropResource from the pool");
|
DEBUG_ERROR("Failed to get a CInteropResource from the pool");
|
||||||
|
SetFullPendingDamage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,6 +457,14 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC srcDesc = srcRes->GetRes()->GetDesc();
|
D3D12_RESOURCE_DESC srcDesc = srcRes->GetRes()->GetDesc();
|
||||||
|
AccumulateFrameDamage(
|
||||||
|
srcRes->GetDirtyRects(), srcRes->GetDirtyRectCount());
|
||||||
|
|
||||||
|
// Never hold an IddCx frame waiting for a slow or disconnected client. Read
|
||||||
|
// and retain its damage first so the next published frame remains complete.
|
||||||
|
if (!m_devContext->FrameBufferAvailable())
|
||||||
|
return true;
|
||||||
|
|
||||||
D12FrameFormat srcFormat = {};
|
D12FrameFormat srcFormat = {};
|
||||||
srcFormat.desc = srcDesc;
|
srcFormat.desc = srcDesc;
|
||||||
srcFormat.width = (unsigned)srcDesc.Width;
|
srcFormat.width = (unsigned)srcDesc.Width;
|
||||||
@@ -492,7 +547,10 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (postProcessFormatChanged)
|
if (postProcessFormatChanged)
|
||||||
|
{
|
||||||
m_nbDirtyRects = 0;
|
m_nbDirtyRects = 0;
|
||||||
|
SetFullPendingDamage();
|
||||||
|
}
|
||||||
|
|
||||||
const D12FrameFormat& dstFormat = m_postProcessor.GetOutputFormat();
|
const D12FrameFormat& dstFormat = m_postProcessor.GetOutputFormat();
|
||||||
|
|
||||||
@@ -509,12 +567,10 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
|
|
||||||
RECT currentDirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
RECT currentDirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
||||||
RECT frameDirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
RECT frameDirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
||||||
unsigned nbDirtyRects = srcRes->GetDirtyRectCount();
|
unsigned nbDirtyRects = m_nbPendingDirtyRects;
|
||||||
if (nbDirtyRects > ARRAYSIZE(currentDirtyRects))
|
if (nbDirtyRects)
|
||||||
nbDirtyRects = 0;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
memcpy(currentDirtyRects, srcRes->GetDirtyRects(), nbDirtyRects * sizeof(*currentDirtyRects));
|
memcpy(currentDirtyRects, m_pendingDirtyRects, nbDirtyRects * sizeof(*currentDirtyRects));
|
||||||
memcpy(frameDirtyRects, currentDirtyRects, nbDirtyRects * sizeof(*frameDirtyRects));
|
memcpy(frameDirtyRects, currentDirtyRects, nbDirtyRects * sizeof(*frameDirtyRects));
|
||||||
}
|
}
|
||||||
unsigned frameDirtyRectCount = nbDirtyRects;
|
unsigned frameDirtyRectCount = nbDirtyRects;
|
||||||
@@ -543,7 +599,11 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
computeQueue->GetGfxList(), copySrcResource,
|
computeQueue->GetGfxList(), copySrcResource,
|
||||||
currentDirtyRects, &nbDirtyRects);
|
currentDirtyRects, &nbDirtyRects);
|
||||||
|
|
||||||
computeQueue->Execute();
|
if (!computeQueue->Execute())
|
||||||
|
{
|
||||||
|
SetFullPendingDamage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
copyQueue->WaitFor(*computeQueue);
|
copyQueue->WaitFor(*computeQueue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -569,6 +629,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
if (!fbRes)
|
if (!fbRes)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to get a CFrameBufferResource from the pool");
|
DEBUG_ERROR("Failed to get a CFrameBufferResource from the pool");
|
||||||
|
SetFullPendingDamage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,13 +669,25 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
CopyDirtyRect(copyQueue->GetGfxList(), &dstLoc, &srcLoc, *rect);
|
CopyDirtyRect(copyQueue->GetGfxList(), &dstLoc, &srcLoc, *rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(m_dirtyRects, currentDirtyRects, nbDirtyRects * sizeof(*m_dirtyRects));
|
|
||||||
m_nbDirtyRects = nbDirtyRects;
|
|
||||||
|
|
||||||
if (!copyQueue->Execute())
|
if (!copyQueue->Execute())
|
||||||
|
{
|
||||||
|
SetFullPendingDamage();
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return m_devContext->PublishFrameBuffer(buffer.frameIndex);
|
if (!m_devContext->PublishFrameBuffer(buffer.frameIndex))
|
||||||
|
{
|
||||||
|
SetFullPendingDamage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m_dirtyRects, currentDirtyRects,
|
||||||
|
nbDirtyRects * sizeof(*m_dirtyRects));
|
||||||
|
m_nbDirtyRects = nbDirtyRects;
|
||||||
|
m_hasPendingDamage = false;
|
||||||
|
m_nbPendingDirtyRects = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD CALLBACK CSwapChainProcessor::_CursorThread(LPVOID arg)
|
DWORD CALLBACK CSwapChainProcessor::_CursorThread(LPVOID arg)
|
||||||
|
|||||||
@@ -61,9 +61,20 @@ private:
|
|||||||
BYTE* m_shapeBuffer;
|
BYTE* m_shapeBuffer;
|
||||||
DWORD m_lastShapeId = 0;
|
DWORD m_lastShapeId = 0;
|
||||||
|
|
||||||
|
// Output-space damage from the previous published frame. The shared-memory
|
||||||
|
// frame buffers alternate, so this must be copied along with the current
|
||||||
|
// damage to bring the older target buffer up to date.
|
||||||
RECT m_dirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
RECT m_dirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
||||||
unsigned m_nbDirtyRects = 0;
|
unsigned m_nbDirtyRects = 0;
|
||||||
|
|
||||||
|
// Source-space damage accumulated since the last published frame. Frames
|
||||||
|
// can be dropped while the LGMP queue is full, but their damage must be
|
||||||
|
// included in the next frame sent to the client. A count of zero represents
|
||||||
|
// full-frame damage when m_hasPendingDamage is set.
|
||||||
|
RECT m_pendingDirtyRects[LG_MAX_DIRTY_RECTS] = {};
|
||||||
|
unsigned m_nbPendingDirtyRects = 0;
|
||||||
|
bool m_hasPendingDamage = true;
|
||||||
|
|
||||||
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
||||||
void SwapChainThread();
|
void SwapChainThread();
|
||||||
bool SwapChainThreadCore();
|
bool SwapChainThreadCore();
|
||||||
@@ -74,6 +85,8 @@ private:
|
|||||||
|
|
||||||
static void CompletionFunction(
|
static void CompletionFunction(
|
||||||
CD3D12CommandQueue * queue, bool result, void * param1, void * param2);
|
CD3D12CommandQueue * queue, bool result, void * param1, void * param2);
|
||||||
|
void AccumulateFrameDamage(const RECT * dirtyRects, unsigned nbDirtyRects);
|
||||||
|
void SetFullPendingDamage();
|
||||||
bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
||||||
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel);
|
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user