mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[idd] capture: version frame graph changes
This commit is contained in:
@@ -319,7 +319,8 @@ struct CFrameExec::Core : std::enable_shared_from_this<CFrameExec::Core>
|
|||||||
|
|
||||||
CfgResult Init(const CFrameGraph& source,
|
CfgResult Init(const CFrameGraph& source,
|
||||||
const std::shared_ptr<CD3D11Device>& d11Device,
|
const std::shared_ptr<CD3D11Device>& d11Device,
|
||||||
const std::shared_ptr<CD3D12Device>& d12Device, CTexHub& texHub)
|
const std::shared_ptr<CD3D12Device>& d12Device, CTexHub& texHub,
|
||||||
|
bool inheritedFull)
|
||||||
{
|
{
|
||||||
d11 = d11Device;
|
d11 = d11Device;
|
||||||
d12 = d12Device;
|
d12 = d12Device;
|
||||||
@@ -337,6 +338,7 @@ struct CFrameExec::Core : std::enable_shared_from_this<CFrameExec::Core>
|
|||||||
return CfgResult::REJECTED;
|
return CfgResult::REJECTED;
|
||||||
|
|
||||||
unsigned texLeaves = 0;
|
unsigned texLeaves = 0;
|
||||||
|
bool continuous = true;
|
||||||
for (unsigned leaf = 0; leaf < leafCount; ++leaf)
|
for (unsigned leaf = 0; leaf < leafCount; ++leaf)
|
||||||
if (leaves[leaf].tex)
|
if (leaves[leaf].tex)
|
||||||
{
|
{
|
||||||
@@ -347,11 +349,14 @@ struct CFrameExec::Core : std::enable_shared_from_this<CFrameExec::Core>
|
|||||||
d11Node[leaves[leaf].node] |=
|
d11Node[leaves[leaf].node] |=
|
||||||
leaves[leaf].cfg.profile.storage ==
|
leaves[leaf].cfg.profile.storage ==
|
||||||
FrameStorage::D3D11_TEXTURE;
|
FrameStorage::D3D11_TEXTURE;
|
||||||
|
continuous &= leaves[leaf].continuous;
|
||||||
++texLeaves;
|
++texLeaves;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!texLeaves)
|
if (!texLeaves)
|
||||||
return CfgResult::ACCEPTED;
|
return CfgResult::ACCEPTED;
|
||||||
|
Atomic::Store(forceFull, inheritedFull || !continuous,
|
||||||
|
std::memory_order_relaxed);
|
||||||
if (!nodes[0].texRefs || !queue.Init(device.Get(),
|
if (!nodes[0].texRefs || !queue.Init(device.Get(),
|
||||||
D3D12_COMMAND_LIST_TYPE_DIRECT, L"Frame Graph",
|
D3D12_COMMAND_LIST_TYPE_DIRECT, L"Frame Graph",
|
||||||
CD3D12CommandSlot::FAST, EXEC_LANES, false, true))
|
CD3D12CommandSlot::FAST, EXEC_LANES, false, true))
|
||||||
@@ -413,6 +418,12 @@ struct CFrameExec::Core : std::enable_shared_from_this<CFrameExec::Core>
|
|||||||
return CfgResult::ACCEPTED;
|
return CfgResult::ACCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NeedsFull()
|
||||||
|
{
|
||||||
|
CSRWExclusiveLock lock(runLock);
|
||||||
|
return Atomic::Load(forceFull, std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
FrameContentRef Content(uint64_t serial, const D12FrameFormat& format,
|
FrameContentRef Content(uint64_t serial, const D12FrameFormat& format,
|
||||||
uint64_t captureTime, bool full, FrameDamage damage,
|
uint64_t captureTime, bool full, FrameDamage damage,
|
||||||
const RECT * rects, unsigned count)
|
const RECT * rects, unsigned count)
|
||||||
@@ -689,6 +700,7 @@ CfgResult CFrameExec::Prep(const CFrameGraph& graph) noexcept
|
|||||||
{
|
{
|
||||||
std::shared_ptr<CD3D11Device> d11;
|
std::shared_ptr<CD3D11Device> d11;
|
||||||
std::shared_ptr<CD3D12Device> d12;
|
std::shared_ptr<CD3D12Device> d12;
|
||||||
|
std::shared_ptr<Core> active;
|
||||||
CTexHub * hub = nullptr;
|
CTexHub * hub = nullptr;
|
||||||
{
|
{
|
||||||
CSRWSharedLock lock(m_lock);
|
CSRWSharedLock lock(m_lock);
|
||||||
@@ -696,6 +708,7 @@ CfgResult CFrameExec::Prep(const CFrameGraph& graph) noexcept
|
|||||||
return CfgResult::REJECTED;
|
return CfgResult::REJECTED;
|
||||||
d11 = m_d11;
|
d11 = m_d11;
|
||||||
d12 = m_d12;
|
d12 = m_d12;
|
||||||
|
active = m_active;
|
||||||
hub = m_hub;
|
hub = m_hub;
|
||||||
}
|
}
|
||||||
if (!d11 || !d12 || !hub)
|
if (!d11 || !d12 || !hub)
|
||||||
@@ -716,7 +729,8 @@ CfgResult CFrameExec::Prep(const CFrameGraph& graph) noexcept
|
|||||||
CfgResult result = CfgResult::FAILED;
|
CfgResult result = CfgResult::FAILED;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = next->Init(graph, d11, d12, *hub);
|
result = next->Init(graph, d11, d12, *hub,
|
||||||
|
!active || active->NeedsFull());
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ unsigned CFrameGraph::Checkpoint(const FrameProfile& requested)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameGraph::Add(BackendId id, uint32_t epoch, bool required,
|
bool CFrameGraph::Add(BackendId id, uint32_t epoch, bool required,
|
||||||
bool primary, bool tex, const FrameCfg& cfg)
|
bool primary, bool tex, bool continuous, const FrameCfg& cfg)
|
||||||
{
|
{
|
||||||
if (!id || !epoch || !Can(cfg) ||
|
if (!id || !epoch || !Can(cfg) ||
|
||||||
m_leafCount == TRANSPORT_MAX_INSTANCES)
|
m_leafCount == TRANSPORT_MAX_INSTANCES)
|
||||||
@@ -267,6 +267,7 @@ bool CFrameGraph::Add(BackendId id, uint32_t epoch, bool required,
|
|||||||
leaf.required = required;
|
leaf.required = required;
|
||||||
leaf.primary = primary;
|
leaf.primary = primary;
|
||||||
leaf.tex = tex;
|
leaf.tex = tex;
|
||||||
|
leaf.continuous = continuous;
|
||||||
leaf.cfg = cfg;
|
leaf.cfg = cfg;
|
||||||
|
|
||||||
for (unsigned current = node;
|
for (unsigned current = node;
|
||||||
@@ -299,7 +300,8 @@ bool CFrameGraph::Seal()
|
|||||||
|
|
||||||
bool CFrameGraph::Stamp(uint64_t generation)
|
bool CFrameGraph::Stamp(uint64_t generation)
|
||||||
{
|
{
|
||||||
if (!m_sealed || m_generation || !generation)
|
if (!m_sealed || m_generation || !generation ||
|
||||||
|
!m_leafCount || !m_nodeCount)
|
||||||
return false;
|
return false;
|
||||||
m_generation = generation;
|
m_generation = generation;
|
||||||
return true;
|
return true;
|
||||||
@@ -307,12 +309,29 @@ bool CFrameGraph::Stamp(uint64_t generation)
|
|||||||
|
|
||||||
bool CFrameGraph::Same(const GraphCfg& cfg) const
|
bool CFrameGraph::Same(const GraphCfg& cfg) const
|
||||||
{
|
{
|
||||||
return m_sealed && Frame::Same(m_cfg, cfg);
|
return Ready() && Frame::Same(m_cfg, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GraphLeaf * CFrameGraph::FindLeaf(BackendId id, uint32_t epoch,
|
||||||
|
bool tex, const FrameCfg& frame) const
|
||||||
|
{
|
||||||
|
if (!Ready())
|
||||||
|
return nullptr;
|
||||||
|
for (unsigned i = 0; i < m_leafCount; ++i)
|
||||||
|
{
|
||||||
|
const GraphLeaf& leaf = m_leaves[i];
|
||||||
|
if (leaf.id == id &&
|
||||||
|
leaf.epoch == epoch &&
|
||||||
|
leaf.tex == tex &&
|
||||||
|
Frame::Same(leaf.cfg, frame))
|
||||||
|
return &leaf;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFrameGraph::Need(FrameOp op) const
|
bool CFrameGraph::Need(FrameOp op) const
|
||||||
{
|
{
|
||||||
if (!m_sealed || op == FrameOp::SRC)
|
if (!Ready() || op == FrameOp::SRC)
|
||||||
return false;
|
return false;
|
||||||
for (unsigned i = 1; i < m_nodeCount; ++i)
|
for (unsigned i = 1; i < m_nodeCount; ++i)
|
||||||
if (m_nodes[i].op == op && m_nodes[i].refs)
|
if (m_nodes[i].op == op && m_nodes[i].refs)
|
||||||
@@ -322,7 +341,7 @@ bool CFrameGraph::Need(FrameOp op) const
|
|||||||
|
|
||||||
bool CFrameGraph::Want(FrameSignal signal) const
|
bool CFrameGraph::Want(FrameSignal signal) const
|
||||||
{
|
{
|
||||||
if (!m_sealed)
|
if (!Ready())
|
||||||
return false;
|
return false;
|
||||||
for (unsigned i = 0; i < m_leafCount; ++i)
|
for (unsigned i = 0; i < m_leafCount; ++i)
|
||||||
if (m_leaves[i].cfg.profile.signal == signal)
|
if (m_leaves[i].cfg.profile.signal == signal)
|
||||||
@@ -332,7 +351,7 @@ bool CFrameGraph::Want(FrameSignal signal) const
|
|||||||
|
|
||||||
bool CFrameGraph::Shared(unsigned node) const
|
bool CFrameGraph::Shared(unsigned node) const
|
||||||
{
|
{
|
||||||
if (!m_sealed || !node || node >= m_nodeCount ||
|
if (!Ready() || !node || node >= m_nodeCount ||
|
||||||
!m_nodes[node].texRefs)
|
!m_nodes[node].texRefs)
|
||||||
return false;
|
return false;
|
||||||
for (unsigned i = 0; i < m_leafCount; ++i)
|
for (unsigned i = 0; i < m_leafCount; ++i)
|
||||||
@@ -346,7 +365,7 @@ bool CFrameGraph::Shared(unsigned node) const
|
|||||||
bool CFrameGraph::Desc(unsigned nodeIndex,
|
bool CFrameGraph::Desc(unsigned nodeIndex,
|
||||||
const FrameContentRef& content, FrameDesc& desc) const
|
const FrameContentRef& content, FrameDesc& desc) const
|
||||||
{
|
{
|
||||||
if (!content)
|
if (!Ready() || !content)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const D12FrameFormat& source = content->format;
|
const D12FrameFormat& source = content->format;
|
||||||
@@ -358,8 +377,7 @@ bool CFrameGraph::Desc(unsigned nodeIndex,
|
|||||||
if (!validProfile || !Frame::Same(sourceProfile, m_cfg.src))
|
if (!validProfile || !Frame::Same(sourceProfile, m_cfg.src))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_sealed ||
|
if (!nodeIndex ||
|
||||||
!nodeIndex ||
|
|
||||||
nodeIndex >= m_nodeCount ||
|
nodeIndex >= m_nodeCount ||
|
||||||
!content->serial ||
|
!content->serial ||
|
||||||
source.width != m_cfg.srcWidth ||
|
source.width != m_cfg.srcWidth ||
|
||||||
@@ -412,7 +430,7 @@ bool CFrameGraph::Desc(unsigned nodeIndex,
|
|||||||
bool CFrameGraph::Desc(unsigned leaf, const FrameContentRef& content,
|
bool CFrameGraph::Desc(unsigned leaf, const FrameContentRef& content,
|
||||||
LeafDesc& desc) const
|
LeafDesc& desc) const
|
||||||
{
|
{
|
||||||
if (!m_sealed || leaf >= m_leafCount)
|
if (!Ready() || leaf >= m_leafCount)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const GraphLeaf& route = m_leaves[leaf];
|
const GraphLeaf& route = m_leaves[leaf];
|
||||||
@@ -430,12 +448,12 @@ bool CFrameGraph::Desc(unsigned leaf, const FrameContentRef& content,
|
|||||||
|
|
||||||
const GraphNode * CFrameGraph::Nodes(unsigned& count) const
|
const GraphNode * CFrameGraph::Nodes(unsigned& count) const
|
||||||
{
|
{
|
||||||
count = m_sealed ? m_nodeCount : 0;
|
count = Ready() ? m_nodeCount : 0;
|
||||||
return count ? m_nodes : nullptr;
|
return count ? m_nodes : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GraphLeaf * CFrameGraph::Leaves(unsigned& count) const
|
const GraphLeaf * CFrameGraph::Leaves(unsigned& count) const
|
||||||
{
|
{
|
||||||
count = m_sealed ? m_leafCount : 0;
|
count = Ready() ? m_leafCount : 0;
|
||||||
return count ? m_leaves : nullptr;
|
return count ? m_leaves : nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ struct GraphLeaf
|
|||||||
bool required = false;
|
bool required = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
bool tex = false;
|
bool tex = false;
|
||||||
|
// Partial damage remains valid across the preceding graph generation.
|
||||||
|
bool continuous = false;
|
||||||
FrameCfg cfg;
|
FrameCfg cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,10 +154,13 @@ public:
|
|||||||
bool Begin(const GraphCfg& cfg);
|
bool Begin(const GraphCfg& cfg);
|
||||||
bool Can(const FrameCfg& cfg) const;
|
bool Can(const FrameCfg& cfg) const;
|
||||||
bool Add(BackendId id, uint32_t epoch, bool required, bool primary,
|
bool Add(BackendId id, uint32_t epoch, bool required, bool primary,
|
||||||
bool tex, const FrameCfg& cfg);
|
bool tex, bool continuous, const FrameCfg& cfg);
|
||||||
bool Seal();
|
bool Seal();
|
||||||
bool Stamp(uint64_t generation);
|
bool Stamp(uint64_t generation);
|
||||||
|
bool Ready() const { return m_sealed && m_generation; }
|
||||||
bool Same(const GraphCfg& cfg) const;
|
bool Same(const GraphCfg& cfg) const;
|
||||||
|
const GraphLeaf * FindLeaf(BackendId id, uint32_t epoch, bool tex,
|
||||||
|
const FrameCfg& frame) const;
|
||||||
bool Want(FrameSignal signal) const;
|
bool Want(FrameSignal signal) const;
|
||||||
bool Need(FrameOp op) const;
|
bool Need(FrameOp op) const;
|
||||||
bool Shared(unsigned node) const;
|
bool Shared(unsigned node) const;
|
||||||
@@ -165,7 +170,7 @@ public:
|
|||||||
LeafDesc& desc) const;
|
LeafDesc& desc) const;
|
||||||
|
|
||||||
const GraphCfg& Cfg() const { return m_cfg; }
|
const GraphCfg& Cfg() const { return m_cfg; }
|
||||||
uint64_t Generation() const { return m_generation; }
|
uint64_t Generation() const { return Ready() ? m_generation : 0; }
|
||||||
const GraphNode * Nodes(unsigned& count) const;
|
const GraphNode * Nodes(unsigned& count) const;
|
||||||
const GraphLeaf * Leaves(unsigned& count) const;
|
const GraphLeaf * Leaves(unsigned& count) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
static const uint64_t ROUTE_RETRY_DELAY_MS = 500;
|
||||||
|
|
||||||
template<typename T, std::size_t N>
|
template<typename T, std::size_t N>
|
||||||
T& Append(T (&items)[N], unsigned& count)
|
T& Append(T (&items)[N], unsigned& count)
|
||||||
{
|
{
|
||||||
@@ -50,6 +52,13 @@ struct CTexSet
|
|||||||
{
|
{
|
||||||
struct Route
|
struct Route
|
||||||
{
|
{
|
||||||
|
enum class State : uint8_t
|
||||||
|
{
|
||||||
|
ACTIVE,
|
||||||
|
FAULTED,
|
||||||
|
DROPPED,
|
||||||
|
};
|
||||||
|
|
||||||
std::shared_ptr<ITransport> owner;
|
std::shared_ptr<ITransport> owner;
|
||||||
ITexSink * sink = nullptr;
|
ITexSink * sink = nullptr;
|
||||||
BackendId id = 0;
|
BackendId id = 0;
|
||||||
@@ -60,8 +69,7 @@ struct CTexSet
|
|||||||
FrameCfg cfg;
|
FrameCfg cfg;
|
||||||
bool required = false;
|
bool required = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
bool active = false;
|
State state = State::ACTIVE;
|
||||||
bool dropped = false;
|
|
||||||
CfgResult fault = CfgResult::ACCEPTED;
|
CfgResult fault = CfgResult::ACCEPTED;
|
||||||
unsigned calls = 0;
|
unsigned calls = 0;
|
||||||
HANDLE idle = nullptr;
|
HANDLE idle = nullptr;
|
||||||
@@ -184,7 +192,8 @@ bool CTexHub::Enter(const FrameIn& frame, bool lease,
|
|||||||
|
|
||||||
CSRWExclusiveLock lock(set->lock);
|
CSRWExclusiveLock lock(set->lock);
|
||||||
route = Find(*set, frame);
|
route = Find(*set, frame);
|
||||||
if (route >= set->count || !set->routes[route].active || !lease ||
|
if (route >= set->count ||
|
||||||
|
set->routes[route].state != CTexSet::Route::State::ACTIVE || !lease ||
|
||||||
frame.graph != set->generation)
|
frame.graph != set->generation)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -228,6 +237,30 @@ CfgResult CTexHub::Faulted(BackendId id, uint32_t epoch,
|
|||||||
return CfgResult::ACCEPTED;
|
return CfgResult::ACCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CTexHub::Active(uint64_t generation, BackendId id,
|
||||||
|
uint32_t epoch, const FrameCfg& cfg) const
|
||||||
|
{
|
||||||
|
std::shared_ptr<CTexSet> set;
|
||||||
|
{
|
||||||
|
CSRWSharedLock lock(m_lock);
|
||||||
|
set = m_active;
|
||||||
|
}
|
||||||
|
if (!set || !generation || set->generation != generation)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CSRWSharedLock lock(set->lock);
|
||||||
|
for (unsigned i = 0; i < set->count; ++i)
|
||||||
|
{
|
||||||
|
const CTexSet::Route& route = set->routes[i];
|
||||||
|
if (route.id == id &&
|
||||||
|
route.epoch == epoch &&
|
||||||
|
route.state == CTexSet::Route::State::ACTIVE &&
|
||||||
|
Frame::Same(route.cfg, cfg))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CTexHub::Rebind(BackendId id, uint32_t epoch)
|
void CTexHub::Rebind(BackendId id, uint32_t epoch)
|
||||||
{
|
{
|
||||||
if (!id || !epoch)
|
if (!id || !epoch)
|
||||||
@@ -243,6 +276,39 @@ void CTexHub::Rebind(BackendId id, uint32_t epoch)
|
|||||||
m_faults[i] = m_faults[--m_faultCount];
|
m_faults[i] = m_faults[--m_faultCount];
|
||||||
m_faults[m_faultCount] = FaultRec {};
|
m_faults[m_faultCount] = FaultRec {};
|
||||||
}
|
}
|
||||||
|
for (unsigned i = 0; i < m_failureCount;)
|
||||||
|
{
|
||||||
|
if (m_failures[i].id != id || m_failures[i].epoch != epoch)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_failures[i] = m_failures[--m_failureCount];
|
||||||
|
m_failures[m_failureCount] = Failure {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTexHub::Retry(uint64_t now)
|
||||||
|
{
|
||||||
|
bool wake = false;
|
||||||
|
{
|
||||||
|
CSRWExclusiveLock lock(m_lock);
|
||||||
|
for (unsigned i = 0; i < m_faultCount;)
|
||||||
|
{
|
||||||
|
const FaultRec& fault = m_faults[i];
|
||||||
|
if (fault.result != CfgResult::REJECTED || !fault.retryAt ||
|
||||||
|
now < fault.retryAt)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_faults[i] = m_faults[--m_faultCount];
|
||||||
|
m_faults[m_faultCount] = FaultRec {};
|
||||||
|
wake = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wake)
|
||||||
|
Bump();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTexHub::Leave(
|
void CTexHub::Leave(
|
||||||
@@ -267,13 +333,14 @@ void CTexHub::Disable(const std::shared_ptr<CTexSet>& set,
|
|||||||
CTexSet::Route failed;
|
CTexSet::Route failed;
|
||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(set->lock);
|
CSRWExclusiveLock lock(set->lock);
|
||||||
if (route < set->count && !set->routes[route].dropped &&
|
if (route < set->count &&
|
||||||
(set->routes[route].active ||
|
set->routes[route].state != CTexSet::Route::State::DROPPED &&
|
||||||
|
(set->routes[route].state == CTexSet::Route::State::ACTIVE ||
|
||||||
(result == PushResult::FAILED &&
|
(result == PushResult::FAILED &&
|
||||||
set->routes[route].fault == CfgResult::REJECTED)))
|
set->routes[route].fault == CfgResult::REJECTED)))
|
||||||
{
|
{
|
||||||
CTexSet::Route& target = set->routes[route];
|
CTexSet::Route& target = set->routes[route];
|
||||||
target.active = false;
|
target.state = CTexSet::Route::State::FAULTED;
|
||||||
target.fault = result == PushResult::FAILED ?
|
target.fault = result == PushResult::FAILED ?
|
||||||
CfgResult::FAILED : CfgResult::REJECTED;
|
CfgResult::FAILED : CfgResult::REJECTED;
|
||||||
failed.id = target.id;
|
failed.id = target.id;
|
||||||
@@ -291,6 +358,8 @@ void CTexHub::Disable(const std::shared_ptr<CTexSet>& set,
|
|||||||
record.cfg = failed.cfg;
|
record.cfg = failed.cfg;
|
||||||
record.result = result == PushResult::FAILED ?
|
record.result = result == PushResult::FAILED ?
|
||||||
CfgResult::FAILED : CfgResult::REJECTED;
|
CfgResult::FAILED : CfgResult::REJECTED;
|
||||||
|
record.retryAt = result == PushResult::REJECTED ?
|
||||||
|
GetTickCount64() + ROUTE_RETRY_DELAY_MS : 0;
|
||||||
|
|
||||||
bool wake = false;
|
bool wake = false;
|
||||||
{
|
{
|
||||||
@@ -303,6 +372,7 @@ void CTexHub::Disable(const std::shared_ptr<CTexSet>& set,
|
|||||||
m_faults[i].result != CfgResult::FAILED)
|
m_faults[i].result != CfgResult::FAILED)
|
||||||
{
|
{
|
||||||
m_faults[i].result = CfgResult::FAILED;
|
m_faults[i].result = CfgResult::FAILED;
|
||||||
|
m_faults[i].retryAt = 0;
|
||||||
wake = true;
|
wake = true;
|
||||||
}
|
}
|
||||||
if (result != PushResult::FAILED)
|
if (result != PushResult::FAILED)
|
||||||
@@ -438,7 +508,7 @@ CfgResult CTexHub::Prep(const CFrameGraph& graph,
|
|||||||
target.cfg = route.cfg;
|
target.cfg = route.cfg;
|
||||||
target.required = route.required;
|
target.required = route.required;
|
||||||
target.primary = route.primary;
|
target.primary = route.primary;
|
||||||
target.active = true;
|
target.state = CTexSet::Route::State::ACTIVE;
|
||||||
target.idle = CreateEvent(nullptr, TRUE, TRUE, nullptr);
|
target.idle = CreateEvent(nullptr, TRUE, TRUE, nullptr);
|
||||||
if (!target.idle)
|
if (!target.idle)
|
||||||
return CfgResult::FAILED;
|
return CfgResult::FAILED;
|
||||||
@@ -616,9 +686,8 @@ void CTexHub::Drop(BackendId id, uint32_t epoch)
|
|||||||
if (set->routes[i].id == id && set->routes[i].epoch == epoch)
|
if (set->routes[i].id == id && set->routes[i].epoch == epoch)
|
||||||
{
|
{
|
||||||
CTexSet::Route& target = set->routes[i];
|
CTexSet::Route& target = set->routes[i];
|
||||||
changed |= target.active;
|
changed |= target.state == CTexSet::Route::State::ACTIVE;
|
||||||
target.active = false;
|
target.state = CTexSet::Route::State::DROPPED;
|
||||||
target.dropped = true;
|
|
||||||
if (target.calls)
|
if (target.calls)
|
||||||
{
|
{
|
||||||
ResetEvent(target.idle);
|
ResetEvent(target.idle);
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ private:
|
|||||||
uint32_t epoch = 0;
|
uint32_t epoch = 0;
|
||||||
FrameCfg cfg;
|
FrameCfg cfg;
|
||||||
CfgResult result = CfgResult::ACCEPTED;
|
CfgResult result = CfgResult::ACCEPTED;
|
||||||
|
uint64_t retryAt = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Failure
|
struct Failure
|
||||||
@@ -125,6 +126,9 @@ private:
|
|||||||
|
|
||||||
CfgResult Faulted(BackendId id, uint32_t epoch,
|
CfgResult Faulted(BackendId id, uint32_t epoch,
|
||||||
const FrameCfg& cfg) const;
|
const FrameCfg& cfg) const;
|
||||||
|
bool Active(uint64_t generation, BackendId id, uint32_t epoch,
|
||||||
|
const FrameCfg& cfg) const;
|
||||||
|
void Retry(uint64_t now);
|
||||||
bool TakeFailure(BackendId& id, uint32_t& epoch);
|
bool TakeFailure(BackendId& id, uint32_t& epoch);
|
||||||
void Rebind(BackendId id, uint32_t epoch);
|
void Rebind(BackendId id, uint32_t epoch);
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
static const uint64_t RETRY_DELAY_MS = 500;
|
static const uint64_t RETRY_DELAY_MS = 500;
|
||||||
|
static const uint64_t FRAME_RETRY_DELAY_MS = 500;
|
||||||
static const uint64_t SERVICE_RETRY_DELAY_MS = 250;
|
static const uint64_t SERVICE_RETRY_DELAY_MS = 250;
|
||||||
|
static std::atomic<uint64_t> s_graphGeneration = 0;
|
||||||
|
|
||||||
class CSourceEvents final : public ITransportEvents
|
class CSourceEvents final : public ITransportEvents
|
||||||
{
|
{
|
||||||
@@ -135,9 +137,25 @@ void CTransportManager::BumpFrameRev()
|
|||||||
Atomic::Next(m_frameRev, std::memory_order_release);
|
Atomic::Next(m_frameRev, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CTransportManager::NextGraph()
|
void CTransportManager::ScheduleFrameRetry(Entry& entry)
|
||||||
{
|
{
|
||||||
return Seq::Inc(m_graphSerial);
|
CSRWExclusiveLock entryLock(entry.lock);
|
||||||
|
if (!entry.frameRetryAt)
|
||||||
|
entry.frameRetryAt = GetTickCount64() + FRAME_RETRY_DELAY_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransportManager::RetryFrame(Entry& entry, uint64_t now)
|
||||||
|
{
|
||||||
|
bool retry = false;
|
||||||
|
{
|
||||||
|
CSRWExclusiveLock entryLock(entry.lock);
|
||||||
|
if (!entry.frameRetryAt || now < entry.frameRetryAt)
|
||||||
|
return;
|
||||||
|
entry.frameRetryAt = 0;
|
||||||
|
retry = entry.state == State::READY && entry.frameAdded;
|
||||||
|
}
|
||||||
|
if (retry)
|
||||||
|
BumpFrameRev();
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransportManager::~CTransportManager()
|
CTransportManager::~CTransportManager()
|
||||||
@@ -771,6 +789,7 @@ void CTransportManager::RemoveServices(Entry& entry)
|
|||||||
entry.texSink = nullptr;
|
entry.texSink = nullptr;
|
||||||
entry.controlAdded = false;
|
entry.controlAdded = false;
|
||||||
entry.inputAdded = false;
|
entry.inputAdded = false;
|
||||||
|
entry.frameRetryAt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_input.RevokeInteraction(id, epoch);
|
m_input.RevokeInteraction(id, epoch);
|
||||||
@@ -1105,6 +1124,7 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
|
|||||||
bool required = false;
|
bool required = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
bool prepared = false;
|
bool prepared = false;
|
||||||
|
bool selected = false;
|
||||||
bool eligible = false;
|
bool eligible = false;
|
||||||
ITexSink * texSink = nullptr;
|
ITexSink * texSink = nullptr;
|
||||||
FrameProfile profiles[FRAME_PROFILE_MAX] = {};
|
FrameProfile profiles[FRAME_PROFILE_MAX] = {};
|
||||||
@@ -1238,9 +1258,30 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool tex = route.texSink != nullptr;
|
||||||
|
const GraphLeaf * previous = graph.FindLeaf(
|
||||||
|
route.id, route.epoch, tex, candidate);
|
||||||
|
if (previous && previous->required == route.required &&
|
||||||
|
previous->primary == route.primary &&
|
||||||
|
(!tex || m_tex.Active(graph.Generation(),
|
||||||
|
route.id, route.epoch, candidate)))
|
||||||
|
{
|
||||||
|
if (!next.Add(route.id, route.epoch, route.required,
|
||||||
|
route.primary, tex, graph.Same(cfg), candidate))
|
||||||
|
{
|
||||||
|
routeResult = CfgResult::FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
routeResult = CfgResult::ACCEPTED;
|
||||||
|
route.selected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
routeResult = route.transport->Probe(candidate);
|
routeResult = route.transport->Probe(candidate);
|
||||||
if (routeResult == CfgResult::NEXT)
|
if (routeResult == CfgResult::NEXT)
|
||||||
continue;
|
continue;
|
||||||
|
if (routeResult == CfgResult::REJECTED)
|
||||||
|
ScheduleFrameRetry(*route.entry);
|
||||||
if (routeResult != CfgResult::ACCEPTED)
|
if (routeResult != CfgResult::ACCEPTED)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1250,21 +1291,24 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
|
|||||||
route.transport->Abort();
|
route.transport->Abort();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (routeResult == CfgResult::REJECTED)
|
||||||
|
ScheduleFrameRetry(*route.entry);
|
||||||
if (routeResult != CfgResult::ACCEPTED)
|
if (routeResult != CfgResult::ACCEPTED)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!next.Add(route.id, route.epoch, route.required,
|
if (!next.Add(route.id, route.epoch, route.required,
|
||||||
route.primary, route.texSink != nullptr, candidate))
|
route.primary, tex, false, candidate))
|
||||||
{
|
{
|
||||||
route.transport->Abort();
|
route.transport->Abort();
|
||||||
routeResult = CfgResult::FAILED;
|
routeResult = CfgResult::FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
route.prepared = true;
|
route.prepared = true;
|
||||||
|
route.selected = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route.prepared)
|
if (route.selected)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
route.transport->Abort();
|
route.transport->Abort();
|
||||||
@@ -1285,14 +1329,14 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
|
|||||||
result = CfgResult::FAILED;
|
result = CfgResult::FAILED;
|
||||||
|
|
||||||
if (result == CfgResult::ACCEPTED &&
|
if (result == CfgResult::ACCEPTED &&
|
||||||
!next.Stamp(NextGraph()))
|
!next.Stamp(Atomic::Next(s_graphGeneration)))
|
||||||
result = CfgResult::FAILED;
|
result = CfgResult::FAILED;
|
||||||
|
|
||||||
CTexHub::Bind binds[FRAME_MAX_SINKS];
|
CTexHub::Bind binds[FRAME_MAX_SINKS];
|
||||||
unsigned bindCount = 0;
|
unsigned bindCount = 0;
|
||||||
if (result == CfgResult::ACCEPTED)
|
if (result == CfgResult::ACCEPTED)
|
||||||
for (unsigned i = 0; i < routeCount; ++i)
|
for (unsigned i = 0; i < routeCount; ++i)
|
||||||
if (routes[i].prepared)
|
if (routes[i].selected)
|
||||||
{
|
{
|
||||||
CTexHub::Bind& bind = binds[bindCount++];
|
CTexHub::Bind& bind = binds[bindCount++];
|
||||||
bind.owner = routes[i].transport;
|
bind.owner = routes[i].transport;
|
||||||
@@ -1315,8 +1359,15 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
|
|||||||
if (result == CfgResult::ACCEPTED)
|
if (result == CfgResult::ACCEPTED)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < routeCount; ++i)
|
for (unsigned i = 0; i < routeCount; ++i)
|
||||||
|
{
|
||||||
if (routes[i].prepared)
|
if (routes[i].prepared)
|
||||||
routes[i].transport->Commit();
|
routes[i].transport->Commit();
|
||||||
|
if (routes[i].selected)
|
||||||
|
{
|
||||||
|
CSRWExclusiveLock entryLock(routes[i].entry->lock);
|
||||||
|
routes[i].entry->frameRetryAt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
graph = next;
|
graph = next;
|
||||||
m_tex.Commit(texStage);
|
m_tex.Commit(texStage);
|
||||||
if (activationReady)
|
if (activationReady)
|
||||||
@@ -1360,12 +1411,14 @@ ITransport::ProcessResult CTransportManager::Process(
|
|||||||
|
|
||||||
const uint64_t now = GetTickCount64();
|
const uint64_t now = GetTickCount64();
|
||||||
m_recovery.Tick(now);
|
m_recovery.Tick(now);
|
||||||
|
m_tex.Retry(now);
|
||||||
HandleServiceFailures();
|
HandleServiceFailures();
|
||||||
Entry * entries[FRAME_MAX_SINKS] = {};
|
Entry * entries[FRAME_MAX_SINKS] = {};
|
||||||
const unsigned count = Entries(entries);
|
const unsigned count = Entries(entries);
|
||||||
for (unsigned i = 0; i < count; ++i)
|
for (unsigned i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
Entry& entry = *entries[i];
|
Entry& entry = *entries[i];
|
||||||
|
RetryFrame(entry, now);
|
||||||
if (!BeginCall(entry, Call::PROCESS, false))
|
if (!BeginCall(entry, Call::PROCESS, false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ private:
|
|||||||
bool frameLegacy = false;
|
bool frameLegacy = false;
|
||||||
ITexSink * texSink = nullptr;
|
ITexSink * texSink = nullptr;
|
||||||
bool frameAbsent = false;
|
bool frameAbsent = false;
|
||||||
|
uint64_t frameRetryAt = 0;
|
||||||
uint64_t serviceRetryAt = 0;
|
uint64_t serviceRetryAt = 0;
|
||||||
bool exposed = false;
|
bool exposed = false;
|
||||||
bool setupDone = false;
|
bool setupDone = false;
|
||||||
@@ -143,7 +144,6 @@ private:
|
|||||||
bool m_started = false;
|
bool m_started = false;
|
||||||
bool m_stopping = false;
|
bool m_stopping = false;
|
||||||
bool m_stopped = false;
|
bool m_stopped = false;
|
||||||
uint64_t m_graphSerial = 0;
|
|
||||||
|
|
||||||
unsigned Entries(Entry * entries[FRAME_MAX_SINKS]) const;
|
unsigned Entries(Entry * entries[FRAME_MAX_SINKS]) const;
|
||||||
Entry * Primary() const;
|
Entry * Primary() const;
|
||||||
@@ -169,7 +169,8 @@ private:
|
|||||||
void RemoveServices(Entry& entry);
|
void RemoveServices(Entry& entry);
|
||||||
void Expose(Entry& entry);
|
void Expose(Entry& entry);
|
||||||
void BumpFrameRev();
|
void BumpFrameRev();
|
||||||
uint64_t NextGraph();
|
void ScheduleFrameRetry(Entry& entry);
|
||||||
|
void RetryFrame(Entry& entry, uint64_t now);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTransportManager();
|
CTransportManager();
|
||||||
|
|||||||
Reference in New Issue
Block a user