[idd] capture: log committed frame graph

This commit is contained in:
Geoffrey McRae
2026-08-14 01:56:41 +10:00
parent 1dcab65ab9
commit 879b8429e7
3 changed files with 201 additions and 2 deletions

View File

@@ -20,6 +20,8 @@
#include "capture/CFrameGraph.h" #include "capture/CFrameGraph.h"
#include "CDebug.h"
#include <cstring> #include <cstring>
bool Frame::Same(const GraphCfg& left, const GraphCfg& right) bool Frame::Same(const GraphCfg& left, const GraphCfg& right)
@@ -64,6 +66,68 @@ bool Frame::Valid(FrameDamage damage, const RECT * rects, unsigned count,
return false; return false;
} }
static const char * OpName(FrameOp op)
{
switch (op)
{
case FrameOp::SRC: return "src";
case FrameOp::CAL: return "cal";
case FrameOp::LUT: return "lut";
case FrameOp::SCALE: return "scale";
case FrameOp::SDR: return "sdr";
case FrameOp::SCRGB: return "scrgb";
case FrameOp::HDR10: return "hdr10";
}
return "?";
}
static const char * PixelName(FramePixel pixel)
{
switch (pixel)
{
case FramePixel::BGRA8: return "bgra8";
case FramePixel::RGBA8: return "rgba8";
case FramePixel::RGB10A2: return "rgb10";
case FramePixel::RGBA16F: return "rgba16f";
}
return "?";
}
static const char * SignalName(FrameSignal signal)
{
switch (signal)
{
case FrameSignal::SRGB: return "srgb";
case FrameSignal::PQ_BT2020: return "pq";
case FrameSignal::SCRGB_LINEAR: return "scrgb";
}
return "?";
}
static const char * StorageName(FrameStorage storage)
{
switch (storage)
{
case FrameStorage::D3D11_TEXTURE: return "d3d11";
case FrameStorage::D3D12_TEXTURE: return "d3d12";
default: return "?";
}
}
static void Branch(char * result, const bool * ancestry,
unsigned depth, bool last)
{
char * current = result;
for (unsigned i = 0; i < depth; ++i)
{
const char * segment = ancestry[i] ? " " : "| ";
memcpy(current, segment, 3);
current += 3;
}
memcpy(current, last ? "`- " : "+- ", 3);
current[3] = 0;
}
void CFrameGraph::Reset() void CFrameGraph::Reset()
{ {
m_cfg = GraphCfg {}; m_cfg = GraphCfg {};
@@ -307,6 +371,95 @@ bool CFrameGraph::Stamp(uint64_t generation)
return true; return true;
} }
void CFrameGraph::LogNode(unsigned node, const GraphRouteName * routes,
unsigned routeCount, bool * ancestry, unsigned depth, bool last) const
{
char branch[FRAME_GRAPH_MAX_NODES * 3 + 4];
Branch(branch, ancestry, depth, last);
const GraphNode& item = m_nodes[node];
switch (item.op)
{
case FrameOp::SRC:
DEBUG_INFO("%ssrc %s/%s", branch,
PixelName(item.profile.pixel), SignalName(item.profile.signal));
break;
case FrameOp::SDR:
case FrameOp::SCRGB:
DEBUG_INFO("%snative %s", branch, PixelName(item.profile.pixel));
break;
case FrameOp::SCALE:
DEBUG_INFO("%sscale %ux%u %s/%s", branch,
item.width, item.height, PixelName(item.profile.pixel),
SignalName(item.profile.signal));
break;
default:
DEBUG_INFO("%s%s %s/%s", branch, OpName(item.op),
PixelName(item.profile.pixel), SignalName(item.profile.signal));
break;
}
unsigned children = 0;
for (unsigned child = 1; child < m_nodeCount; ++child)
if (m_nodes[child].refs && m_nodes[child].parent == node)
++children;
for (unsigned leaf = 0; leaf < m_leafCount; ++leaf)
if (m_leaves[leaf].node == node)
++children;
ancestry[depth] = last;
unsigned emitted = 0;
for (unsigned child = 1; child < m_nodeCount; ++child)
if (m_nodes[child].refs && m_nodes[child].parent == node)
LogNode(child, routes, routeCount, ancestry, depth + 1,
++emitted == children);
for (unsigned leaf = 0; leaf < m_leafCount; ++leaf)
{
const GraphLeaf& endpoint = m_leaves[leaf];
if (endpoint.node != node)
continue;
const wchar_t * name = L"transport";
for (unsigned route = 0; routes && route < routeCount; ++route)
if (routes[route].id == endpoint.id &&
routes[route].epoch == endpoint.epoch &&
routes[route].name)
{
name = routes[route].name;
break;
}
Branch(branch, ancestry, depth + 1, ++emitted == children);
DEBUG_INFO("%s%ls:%u %s", branch, name, endpoint.id,
StorageName(endpoint.cfg.profile.storage));
}
}
void CFrameGraph::Log(const GraphRouteName * routes,
unsigned routeCount) const
{
if (!Ready() || routeCount > TRANSPORT_MAX_INSTANCES ||
(routeCount && !routes))
return;
const unsigned long long generation =
static_cast<unsigned long long>(m_generation);
const char * mode = m_cfg.mode == GpuMode::HARDWARE ? "hw" : "sw";
if (m_cfg.srcWidth == m_cfg.width && m_cfg.srcHeight == m_cfg.height)
DEBUG_INFO("Frame graph g=%llu mode=%s %ux%u", generation, mode,
m_cfg.srcWidth, m_cfg.srcHeight);
else
DEBUG_INFO("Frame graph g=%llu mode=%s %ux%u -> %ux%u",
generation, mode, m_cfg.srcWidth, m_cfg.srcHeight,
m_cfg.width, m_cfg.height);
bool ancestry[FRAME_GRAPH_MAX_NODES] = {};
LogNode(0, routes, routeCount, ancestry, 0, true);
}
bool CFrameGraph::Same(const GraphCfg& cfg) const bool CFrameGraph::Same(const GraphCfg& cfg) const
{ {
return Ready() && Frame::Same(m_cfg, cfg); return Ready() && Frame::Same(m_cfg, cfg);

View File

@@ -96,6 +96,13 @@ struct GraphLeaf
FrameCfg cfg; FrameCfg cfg;
}; };
struct GraphRouteName
{
BackendId id = 0;
uint32_t epoch = 0;
const wchar_t * name = nullptr;
};
// All products derived from one capture retain the same immutable content. // All products derived from one capture retain the same immutable content.
// It contains no acquired IddCx or Direct3D resource. // It contains no acquired IddCx or Direct3D resource.
struct FrameContent struct FrameContent
@@ -148,6 +155,8 @@ private:
unsigned height, unsigned height,
const FrameProfile& profile); const FrameProfile& profile);
unsigned Checkpoint(const FrameProfile& profile); unsigned Checkpoint(const FrameProfile& profile);
void LogNode(unsigned node, const GraphRouteName * routes,
unsigned routeCount, bool * ancestry, unsigned depth, bool last) const;
public: public:
void Reset(); void Reset();
@@ -158,6 +167,7 @@ public:
bool Seal(); bool Seal();
bool Stamp(uint64_t generation); bool Stamp(uint64_t generation);
bool Ready() const { return m_sealed && m_generation; } bool Ready() const { return m_sealed && m_generation; }
void Log(const GraphRouteName * routes, unsigned routeCount) const;
bool Same(const GraphCfg& cfg) const; bool Same(const GraphCfg& cfg) const;
const GraphLeaf * FindLeaf(BackendId id, uint32_t epoch, bool tex, const GraphLeaf * FindLeaf(BackendId id, uint32_t epoch, bool tex,
const FrameCfg& frame) const; const FrameCfg& frame) const;

View File

@@ -1127,6 +1127,8 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
bool selected = false; bool selected = false;
bool eligible = false; bool eligible = false;
ITexSink * texSink = nullptr; ITexSink * texSink = nullptr;
std::wstring name;
CfgResult outcome = CfgResult::NEXT;
FrameProfile profiles[FRAME_PROFILE_MAX] = {}; FrameProfile profiles[FRAME_PROFILE_MAX] = {};
unsigned profileCount = 0; unsigned profileCount = 0;
}; };
@@ -1175,6 +1177,7 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
route.required = entry.required; route.required = entry.required;
route.primary = entry.primary; route.primary = entry.primary;
route.texSink = entry.texSink; route.texSink = entry.texSink;
route.name = entry.config.kind;
state = entry.state; state = entry.state;
frameAbsent = entry.frameAbsent; frameAbsent = entry.frameAbsent;
frameAdded = entry.frameAdded; frameAdded = entry.frameAdded;
@@ -1186,14 +1189,20 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
{ {
if (!route.required && if (!route.required &&
(frameAbsent || state == State::FAILED)) (frameAbsent || state == State::FAILED))
{
if (frameAbsent)
route.outcome = CfgResult::REJECTED;
continue; continue;
}
result = frameAbsent ? CfgResult::REJECTED : result = frameAbsent ? CfgResult::REJECTED :
(state == State::FAILED ? CfgResult::FAILED : CfgResult::RETRY); (state == State::FAILED ? CfgResult::FAILED : CfgResult::RETRY);
route.outcome = result;
break; break;
} }
if (route.texSink && !activation) if (route.texSink && !activation)
{ {
route.eligible = false; route.eligible = false;
route.outcome = CfgResult::REJECTED;
if (route.required) if (route.required)
{ {
result = CfgResult::REJECTED; result = CfgResult::REJECTED;
@@ -1309,9 +1318,14 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
} }
if (route.selected) if (route.selected)
{
route.outcome = CfgResult::ACCEPTED;
continue; continue;
}
route.transport->Abort(); route.transport->Abort();
route.outcome = routeResult == CfgResult::NEXT ?
CfgResult::REJECTED : routeResult;
if (routeResult == CfgResult::RETRY) if (routeResult == CfgResult::RETRY)
{ {
result = CfgResult::RETRY; result = CfgResult::RETRY;
@@ -1319,8 +1333,7 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
} }
if (route.required) if (route.required)
{ {
result = routeResult == CfgResult::NEXT ? result = route.outcome;
CfgResult::REJECTED : routeResult;
break; break;
} }
} }
@@ -1346,6 +1359,7 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
} }
bool activationReady = false; bool activationReady = false;
bool committed = false;
if (result == CfgResult::ACCEPTED && activation) if (result == CfgResult::ACCEPTED && activation)
{ {
result = activation->Prep(next); result = activation->Prep(next);
@@ -1372,6 +1386,7 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
m_tex.Commit(texStage); m_tex.Commit(texStage);
if (activationReady) if (activationReady)
activation->Commit(); activation->Commit();
committed = true;
} }
else else
{ {
@@ -1386,6 +1401,27 @@ CfgResult CTransportManager::Cfg(const GraphCfg& cfg,
for (unsigned i = routeCount; i > 0; --i) for (unsigned i = routeCount; i > 0; --i)
EndCall(*routes[i - 1].entry, routes[i - 1].transport); EndCall(*routes[i - 1].entry, routes[i - 1].transport);
EndPhase(); EndPhase();
if (committed)
{
GraphRouteName logRoutes[FRAME_MAX_SINKS];
unsigned logRouteCount = 0;
for (unsigned route = 0; route < routeCount; ++route)
if (routes[route].selected)
{
GraphRouteName& label = logRoutes[logRouteCount++];
label.id = routes[route].id;
label.epoch = routes[route].epoch;
label.name = routes[route].name.c_str();
}
next.Log(logRoutes, logRouteCount);
}
if (result == CfgResult::ACCEPTED || result == CfgResult::REJECTED)
for (unsigned i = 0; i < routeCount; ++i)
if (routes[i].outcome == CfgResult::REJECTED)
DEBUG_INFO("Frame route rejected %ls:%u",
routes[i].name.empty() ? L"transport" : routes[i].name.c_str(),
routes[i].id);
return result; return result;
} }