[idd] transport: route immutable texture frames

This commit is contained in:
Geoffrey McRae
2026-08-13 17:33:32 +10:00
parent ba7a037f23
commit deb963774e
16 changed files with 1207 additions and 37 deletions

View File

@@ -66,11 +66,12 @@ bool Frame::Valid(FrameDamage damage, const RECT * rects, unsigned count,
void CFrameGraph::Reset()
{
m_cfg = GraphCfg {};
m_nodeCount = 0;
m_leafCount = 0;
m_begun = false;
m_sealed = false;
m_cfg = GraphCfg {};
m_generation = 0;
m_nodeCount = 0;
m_leafCount = 0;
m_begun = false;
m_sealed = false;
}
bool CFrameGraph::Begin(const GraphCfg& cfg)
@@ -288,6 +289,14 @@ bool CFrameGraph::Seal()
return true;
}
bool CFrameGraph::Stamp(uint64_t generation)
{
if (!m_sealed || m_generation || !generation)
return false;
m_generation = generation;
return true;
}
bool CFrameGraph::Same(const GraphCfg& cfg) const
{
return m_sealed && Frame::Same(m_cfg, cfg);

View File

@@ -131,6 +131,7 @@ private:
GraphCfg m_cfg;
GraphNode m_nodes[FRAME_GRAPH_MAX_NODES] = {};
GraphLeaf m_leaves[TRANSPORT_MAX_INSTANCES] = {};
uint64_t m_generation = 0;
unsigned m_nodeCount = 0;
unsigned m_leafCount = 0;
bool m_begun = false;
@@ -150,6 +151,7 @@ public:
bool Add(BackendId id, uint32_t epoch, bool required, bool primary,
const FrameCfg& cfg);
bool Seal();
bool Stamp(uint64_t generation);
bool Same(const GraphCfg& cfg) const;
bool Want(FrameSignal signal) const;
bool Need(FrameOp op) const;
@@ -158,6 +160,7 @@ public:
LeafDesc& desc) const;
const GraphCfg& Cfg() const { return m_cfg; }
uint64_t Generation() const { return m_generation; }
const GraphNode * Nodes(unsigned& count) const;
const GraphLeaf * Leaves(unsigned& count) const;
};

View File

@@ -48,6 +48,22 @@ static uint64_t NextPool()
return Atomic::Next(next);
}
static bool ValidTime(const FrameTime& time)
{
if (!time.postStart ||
(!time.gpuValid && (time.gpuStart || time.gpuEnd)) ||
(!time.readyValid && time.readyAt))
return false;
if (time.gpuValid && (!time.gpuStart ||
time.gpuStart < time.postStart ||
time.gpuEnd < time.gpuStart))
return false;
if (time.readyValid && (!time.readyAt ||
time.readyAt < (time.gpuValid ? time.gpuEnd : time.postStart)))
return false;
return true;
}
static bool ValidFrame(const FrameProfile& profile,
const D3D12_RESOURCE_DESC& resource, const FrameDesc& frame)
{
@@ -279,7 +295,8 @@ struct CTexCore
CFrameTex::CFrameTex(uint64_t graphValue, uint64_t poolValue,
unsigned nodeValue, unsigned slotValue, uint64_t versionValue,
const FrameProfile& profileValue,
const FrameDesc& frameValue, const ComPtr<ID3D12Resource>& res,
const FrameDesc& frameValue, const FrameTime& timeValue,
const ComPtr<ID3D12Resource>& res,
const D12Sync& sync, D3D12_RESOURCE_STATES state, bool sharedValue) :
m_res(res),
m_sync(sync),
@@ -291,7 +308,8 @@ CFrameTex::CFrameTex(uint64_t graphValue, uint64_t poolValue,
slot(slotValue),
version(versionValue),
profile(profileValue),
frame(frameValue)
frame(frameValue),
time(timeValue)
{
}
@@ -359,13 +377,19 @@ ID3D12Resource * TexWrite::Get() const
resource.Get() : nullptr;
}
bool TexWrite::Seal(const FrameDesc& frame, const D12Sync& sync,
TexLease& lease)
bool TexWrite::Seal(const FrameDesc& frame, const FrameTime& time,
const D12Sync& sync, TexLease& lease)
{
if (!m_core || !sync.Valid())
return false;
const std::shared_ptr<CTexCore> core = m_core;
if (!ValidTime(time))
{
core->Fail(m_index, m_version, sync);
Clear();
return false;
}
ComPtr<ID3D12Resource> resource;
FrameDesc desc = frame;
if (!core->Info(m_index, m_version, resource) ||
@@ -390,8 +414,8 @@ bool TexWrite::Seal(const FrameDesc& frame, const D12Sync& sync,
}
CFrameTex * raw = new (std::nothrow) CFrameTex(core->graph, core->id,
core->node, m_index, m_version, core->profile, desc, resource, sync,
core->read, core->shared);
core->node, m_index, m_version, core->profile, desc, time, resource,
sync, core->read, core->shared);
if (!raw)
{
core->Drop(index, generation);

View File

@@ -37,6 +37,18 @@ enum class TexResult : uint8_t
FAILED,
};
// Immutable producer boundaries for one node product. A transport adds its
// own transfer or encode timing without rewriting these common values.
struct FrameTime
{
uint64_t postStart = 0;
uint64_t gpuStart = 0;
uint64_t gpuEnd = 0;
uint64_t readyAt = 0;
bool gpuValid = false;
bool readyValid = false;
};
// An immutable, pool-owned D3D12 graph product. Node zero is deliberately
// excluded because it aliases the acquired IddCx surface.
class CFrameTex final
@@ -51,7 +63,8 @@ private:
CFrameTex(uint64_t graph, uint64_t pool, unsigned node, unsigned slot,
uint64_t version, const FrameProfile& profile, const FrameDesc& frame,
const ComPtr<ID3D12Resource>& res, const D12Sync& sync,
const FrameTime& time, const ComPtr<ID3D12Resource>& res,
const D12Sync& sync,
D3D12_RESOURCE_STATES state, bool shared);
public:
@@ -65,6 +78,7 @@ public:
const uint64_t version;
const FrameProfile profile;
const FrameDesc frame;
const FrameTime time;
ID3D12Resource * Get() const { return m_res.Get(); }
const D12Sync& Sync() const { return m_sync; }
@@ -126,7 +140,8 @@ public:
ID3D12Resource * Get() const;
// Seal only after producer commands restore the texture to the pool's
// configured immutable state and Execute returns this exact sync point.
bool Seal(const FrameDesc& frame, const D12Sync& sync, TexLease& lease);
bool Seal(const FrameDesc& frame, const FrameTime& time,
const D12Sync& sync, TexLease& lease);
void Cancel();
};

View File

@@ -533,17 +533,29 @@ void CSwapChainProcessor::QueueGraph(const D12FrameFormat& source,
source, checkpoint, m_dx11Device->IsSoftware(),
m_renderAdapter, cfg))
return;
if (m_haveGraphCfg && Frame::Same(m_graphCfg, cfg))
CTransportManager& transport = m_devContext->GetTransport();
const uint64_t revision = transport.FrameRev();
if (m_haveGraphCfg && m_graphRev == revision &&
Frame::Same(m_graphCfg, cfg))
return;
m_graphCfg = cfg;
m_haveGraphCfg = true;
m_graphPending = true;
m_graphRev = revision;
m_graphRetryAt = 0;
}
void CSwapChainProcessor::CfgGraph()
{
CTransportManager& transport = m_devContext->GetTransport();
const uint64_t revision = transport.FrameRev();
if (m_haveGraphCfg && revision != m_graphRev)
{
m_graphRev = revision;
m_graphPending = true;
m_graphRetryAt = 0;
}
if (!m_graphPending)
return;
@@ -553,7 +565,7 @@ void CSwapChainProcessor::CfgGraph()
m_graphPending = false;
const CfgResult result =
m_devContext->GetTransport().Cfg(m_graphCfg, m_graph);
transport.Cfg(m_graphCfg, m_graphRev, m_graph);
if (result == CfgResult::ACCEPTED)
{
m_graphRetryAt = 0;

View File

@@ -61,6 +61,7 @@ private:
GraphCfg m_graphCfg;
bool m_haveGraphCfg = false;
bool m_graphPending = false;
uint64_t m_graphRev = 0;
uint64_t m_graphRetryAt = 0;
CPostProcessor m_postProcessors[CAPTURE_PIPELINE_SLOTS];
std::unique_ptr<CFrameProcessor> m_frameProcessor;