mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 00:31:31 +00:00
[idd] pipeline: overlap independent frame copies
This commit is contained in:
@@ -55,6 +55,61 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CSRWSharedLock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SRWLOCK * m_lock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CSRWSharedLock(SRWLOCK * lock) : m_lock(lock)
|
||||||
|
{
|
||||||
|
AcquireSRWLockShared(m_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CSRWSharedLock()
|
||||||
|
{
|
||||||
|
ReleaseSRWLockShared(m_lock);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPublishPending
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SRWLOCK * m_lock;
|
||||||
|
bool * m_pending;
|
||||||
|
HANDLE m_event;
|
||||||
|
bool m_active = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CPublishPending(SRWLOCK * lock, bool * pending, HANDLE event) :
|
||||||
|
m_lock(lock),
|
||||||
|
m_pending(pending),
|
||||||
|
m_event(event)
|
||||||
|
{
|
||||||
|
AcquireSRWLockExclusive(m_lock);
|
||||||
|
*m_pending = true;
|
||||||
|
ResetEvent(m_event);
|
||||||
|
ReleaseSRWLockExclusive(m_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CPublishPending()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AcquireSRWLockExclusive(m_lock);
|
||||||
|
*m_pending = false;
|
||||||
|
SetEvent(m_event);
|
||||||
|
ReleaseSRWLockExclusive(m_lock);
|
||||||
|
m_active = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static bool FrameMetadataChanged(const D12FrameFormat& previous,
|
static bool FrameMetadataChanged(const D12FrameFormat& previous,
|
||||||
const D12FrameFormat& current)
|
const D12FrameFormat& current)
|
||||||
{
|
{
|
||||||
@@ -92,6 +147,7 @@ CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContex
|
|||||||
m_candidateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
m_candidateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||||
m_candidateAvailableEvent.Attach(
|
m_candidateAvailableEvent.Attach(
|
||||||
CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||||
|
m_copySubmitEvent.Attach(CreateEvent(nullptr, TRUE, TRUE, nullptr));
|
||||||
m_publishTimer.Attach(CreateWaitableTimerExW(nullptr, nullptr,
|
m_publishTimer.Attach(CreateWaitableTimerExW(nullptr, nullptr,
|
||||||
CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS));
|
CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS));
|
||||||
if (!m_publishTimer.Get())
|
if (!m_publishTimer.Get())
|
||||||
@@ -104,8 +160,8 @@ CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContex
|
|||||||
bool CSwapChainProcessor::Start()
|
bool CSwapChainProcessor::Start()
|
||||||
{
|
{
|
||||||
if (!m_terminateEvent.Get() || !m_candidateEvent.Get() ||
|
if (!m_terminateEvent.Get() || !m_candidateEvent.Get() ||
|
||||||
!m_candidateAvailableEvent.Get() || !m_publishTimer.Get() ||
|
!m_candidateAvailableEvent.Get() || !m_copySubmitEvent.Get() ||
|
||||||
!m_cursorDataEvent.Get() || !m_shapeBuffer)
|
!m_publishTimer.Get() || !m_cursorDataEvent.Get() || !m_shapeBuffer)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize swap chain worker resources");
|
DEBUG_ERROR("Failed to initialize swap chain worker resources");
|
||||||
return false;
|
return false;
|
||||||
@@ -1203,13 +1259,49 @@ void CSwapChainProcessor::SignalCandidateState()
|
|||||||
SetEvent(m_candidateAvailableEvent.Get());
|
SetEvent(m_candidateAvailableEvent.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSwapChainProcessor::ExecuteCandidateCopy(
|
||||||
|
CD3D12CommandSlot * copySlot)
|
||||||
|
{
|
||||||
|
HANDLE waitHandles[] =
|
||||||
|
{
|
||||||
|
m_terminateEvent.Get(),
|
||||||
|
m_copySubmitEvent.Get(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
AcquireSRWLockExclusive(&m_copySubmitLock);
|
||||||
|
if (!m_publishPending)
|
||||||
|
{
|
||||||
|
const bool result = copySlot->Execute();
|
||||||
|
ReleaseSRWLockExclusive(&m_copySubmitLock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
ReleaseSRWLockExclusive(&m_copySubmitLock);
|
||||||
|
|
||||||
|
const DWORD result = WaitForMultipleObjects(
|
||||||
|
ARRAYSIZE(waitHandles), waitHandles, FALSE, INFINITE);
|
||||||
|
if (result == WAIT_OBJECT_0 + 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
copySlot->Cancel();
|
||||||
|
if (result != WAIT_OBJECT_0)
|
||||||
|
DEBUG_ERROR_HR(HRESULT_FROM_WIN32(GetLastError()),
|
||||||
|
"Failed while waiting to submit a frame candidate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CSwapChainProcessor::PublishNewestCandidate(
|
bool CSwapChainProcessor::PublishNewestCandidate(
|
||||||
const CFrameScheduler::Schedule& schedule, bool periodic,
|
const CFrameScheduler::Schedule& schedule, bool periodic,
|
||||||
uint64_t publishStart)
|
uint64_t publishStart)
|
||||||
{
|
{
|
||||||
// Once a deadline is due, submit transport work before allowing another
|
// Once a deadline is due, prevent newly recorded preparation work from
|
||||||
// preparation to enqueue on the same physical copy queue.
|
// being submitted ahead of the transport copy. The short submission gate
|
||||||
CSRWExclusiveLock pipelineLock(&m_pipelineLock);
|
// allows a preparation which is already submitting to finish first.
|
||||||
|
CPublishPending publishPending(
|
||||||
|
&m_copySubmitLock, &m_publishPending, m_copySubmitEvent.Get());
|
||||||
|
CSRWSharedLock pipelineLock(&m_pipelineLock);
|
||||||
|
|
||||||
int selectedCandidate = -1;
|
int selectedCandidate = -1;
|
||||||
uint64_t newestSequence = 0;
|
uint64_t newestSequence = 0;
|
||||||
@@ -1394,7 +1486,9 @@ bool CSwapChainProcessor::PublishNewestCandidate(
|
|||||||
}
|
}
|
||||||
ReleaseSRWLockExclusive(&m_damageLock);
|
ReleaseSRWLockExclusive(&m_damageLock);
|
||||||
|
|
||||||
if (!copySlot->Execute())
|
const bool submitted = copySlot->Execute();
|
||||||
|
publishPending.Clear();
|
||||||
|
if (!submitted)
|
||||||
{
|
{
|
||||||
// The logical damage state was advanced before submission. Force a full
|
// The logical damage state was advanced before submission. Force a full
|
||||||
// repair whether submission failed or its callback reported the failure.
|
// repair whether submission failed or its callback reported the failure.
|
||||||
@@ -1778,7 +1872,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
|
|
||||||
FrameCandidate& candidate = m_candidates[candidateIndex];
|
FrameCandidate& candidate = m_candidates[candidateIndex];
|
||||||
|
|
||||||
CSRWExclusiveLock pipelineLock(&m_pipelineLock);
|
CSRWSharedLock pipelineLock(&m_pipelineLock);
|
||||||
CPostProcessor& postProcessor = m_postProcessors[candidateIndex];
|
CPostProcessor& postProcessor = m_postProcessors[candidateIndex];
|
||||||
const D12FrameFormat& dstFormat = postProcessor.GetOutputFormat();
|
const D12FrameFormat& dstFormat = postProcessor.GetOutputFormat();
|
||||||
|
|
||||||
@@ -1935,7 +2029,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
copySrcResource.Get());
|
copySrcResource.Get());
|
||||||
copySlot->EndTiming();
|
copySlot->EndTiming();
|
||||||
|
|
||||||
if (!copySlot->Execute())
|
if (!ExecuteCandidateCopy(copySlot))
|
||||||
{
|
{
|
||||||
if (!copySlot->HasSubmittedWork())
|
if (!copySlot->HasSubmittedWork())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -99,15 +99,21 @@ private:
|
|||||||
// An active tail records only damage received after its candidate snapshot.
|
// An active tail records only damage received after its candidate snapshot.
|
||||||
FrameCandidate m_candidates[LGMP_Q_FRAME_LEN];
|
FrameCandidate m_candidates[LGMP_Q_FRAME_LEN];
|
||||||
CandidateDamageTail m_candidateDamageTail[LGMP_Q_FRAME_LEN];
|
CandidateDamageTail m_candidateDamageTail[LGMP_Q_FRAME_LEN];
|
||||||
SRWLOCK m_candidateLock = SRWLOCK_INIT;
|
SRWLOCK m_candidateLock = SRWLOCK_INIT;
|
||||||
SRWLOCK m_damageLock = SRWLOCK_INIT;
|
SRWLOCK m_damageLock = SRWLOCK_INIT;
|
||||||
SRWLOCK m_pipelineLock = SRWLOCK_INIT;
|
// Reconfiguration is exclusive while per-candidate recording is shared.
|
||||||
uint64_t m_candidateSequence = 0;
|
SRWLOCK m_pipelineLock = SRWLOCK_INIT;
|
||||||
|
// Capture holds this only across submission; the publisher uses it to
|
||||||
|
// close the gate before recording deadline work.
|
||||||
|
SRWLOCK m_copySubmitLock = SRWLOCK_INIT;
|
||||||
|
uint64_t m_candidateSequence = 0;
|
||||||
|
bool m_publishPending = false;
|
||||||
|
|
||||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[3];
|
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_thread[3];
|
||||||
Wrappers::Event m_terminateEvent;
|
Wrappers::Event m_terminateEvent;
|
||||||
Wrappers::Event m_candidateEvent;
|
Wrappers::Event m_candidateEvent;
|
||||||
Wrappers::Event m_candidateAvailableEvent;
|
Wrappers::Event m_candidateAvailableEvent;
|
||||||
|
Wrappers::Event m_copySubmitEvent;
|
||||||
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_publishTimer;
|
Wrappers::HandleT<Wrappers::HandleTraits::HANDLENullTraits> m_publishTimer;
|
||||||
|
|
||||||
Wrappers::Event m_cursorDataEvent;
|
Wrappers::Event m_cursorDataEvent;
|
||||||
@@ -154,6 +160,7 @@ private:
|
|||||||
unsigned candidateIndex, size_t frameSize);
|
unsigned candidateIndex, size_t frameSize);
|
||||||
void ResetCandidates();
|
void ResetCandidates();
|
||||||
void SignalCandidateState();
|
void SignalCandidateState();
|
||||||
|
bool ExecuteCandidateCopy(CD3D12CommandSlot * copySlot);
|
||||||
|
|
||||||
static DWORD CALLBACK _CursorThread(LPVOID arg);
|
static DWORD CALLBACK _CursorThread(LPVOID arg);
|
||||||
bool QueryHWCursor();
|
bool QueryHWCursor();
|
||||||
|
|||||||
Reference in New Issue
Block a user