[idd] network: recover video after display reconfiguration

Reset reusable D3D12 command queues before rebuilding the encoder.

Treat a committed frame graph as recovery from transient device loss.
This commit is contained in:
Geoffrey McRae
2026-10-01 10:18:15 +10:00
parent 2f981a9a60
commit da5af3d478
2 changed files with 41 additions and 16 deletions

View File

@@ -141,7 +141,29 @@ void CD3D12CommandSlot::DeInit()
m_cmdList.Reset();
m_gfxList.Reset();
m_allocator.Reset();
m_queue = nullptr;
for (UINT i = 0; i < MAX_FENCE_WAITS; ++i)
{
m_fenceWaits[i].fence.Reset();
m_fenceWaits[i].value = 0;
}
m_queue = nullptr;
m_name = nullptr;
m_needsReset = false;
m_fenceTarget = 0;
m_fenceWaitCount = 0;
m_completionCallback = nullptr;
m_completionParams[0] = nullptr;
m_completionParams[1] = nullptr;
m_completionResult = true;
m_queryBase = 0;
m_timingActive = false;
m_timestampFrequency = 0;
m_calibrationGPU = 0;
m_calibrationCPU = 0;
Atomic::Store(m_submitted, false, std::memory_order_release);
Atomic::Store(m_state, STATE_FREE, std::memory_order_release);
}
bool CD3D12CommandSlot::Acquire()
@@ -505,6 +527,9 @@ void CD3D12CommandQueue::DeInit()
m_queue.Reset();
m_timingSupported = false;
m_qpcFrequency = 0;
m_fenceValue = 0;
m_name = nullptr;
Atomic::Store(m_failed, false, std::memory_order_release);
}
CD3D12CommandSlot * CD3D12CommandQueue::Try(UINT slotIndex)

View File

@@ -1607,6 +1607,15 @@ struct CNetworkVideo::Impl
LG_NET_VIDEO_STATUS_WIRE_SIZE);
}
void FailNL(uint32_t detail)
{
m_failed = true;
m_frames.clear();
for (PeerState& peer : m_peers)
if (peer.subscribed)
QueueStatusNL(peer, LG_NET_VIDEO_STATE_ERROR, detail);
}
void DropPeerFramesNL(PeerState& peer)
{
// Finish a frame once any of its fragments have been accepted. Replacing
@@ -1934,7 +1943,7 @@ struct CNetworkVideo::Impl
{
CSRWExclusiveLock lock(m_lock);
if (m_encoder.Busy() || m_frames.empty() || !m_started ||
m_stopped || !m_active || !HasSubscribersNL())
m_stopped || m_failed || !m_active || !HasSubscribersNL())
return false;
pending = std::move(m_frames.front());
m_frames.pop_front();
@@ -1952,10 +1961,7 @@ struct CNetworkVideo::Impl
return true;
CSRWExclusiveLock lock(m_lock);
m_failed = true;
for (PeerState& peer : m_peers)
if (peer.subscribed)
QueueStatusNL(peer, LG_NET_VIDEO_STATE_ERROR, 3);
FailNL(3);
return false;
}
@@ -2368,21 +2374,14 @@ void CNetworkVideo::Process(uint64_t nowMs)
else
{
CSRWExclusiveLock lock(m_impl->m_lock);
m_impl->m_failed = true;
for (Impl::PeerState& peer : m_impl->m_peers)
if (peer.subscribed)
m_impl->QueueStatusNL(
peer, LG_NET_VIDEO_STATE_ERROR, 4);
m_impl->FailNL(4);
}
}
else if (state == D12SyncState::FAILED)
{
m_impl->m_encoder.Reset();
CSRWExclusiveLock lock(m_impl->m_lock);
m_impl->m_failed = true;
for (Impl::PeerState& peer : m_impl->m_peers)
if (peer.subscribed)
m_impl->QueueStatusNL(peer, LG_NET_VIDEO_STATE_ERROR, 5);
m_impl->FailNL(5);
}
}
@@ -2432,7 +2431,7 @@ CfgResult CNetworkVideo::Probe(const FrameCfg& cfg) const
if (!m_impl)
return CfgResult::FAILED;
CSRWSharedLock lock(m_impl->m_lock);
if (m_impl->m_stopped || m_impl->m_failed)
if (m_impl->m_stopped)
return CfgResult::FAILED;
if (!Frame::Valid(cfg.mode) || !cfg.width || !cfg.height ||
cfg.width > MAX_WIDTH || cfg.height > MAX_HEIGHT ||
@@ -2475,6 +2474,7 @@ void CNetworkVideo::Commit()
m_impl->m_pendingCfg = {};
m_impl->m_active = true;
m_impl->m_pending = false;
m_impl->m_failed = false;
m_impl->m_changing = false;
m_impl->m_configEpoch = Next64(m_impl->m_configEpoch);
m_impl->m_frames.clear();