Skip to content

@zenfg/inspector 使用指南 ​

@zenfg/inspector 是一个可嵌入、与渲染器无关的 DOM 工作台,用于查看 ZenFG Snapshot 数据。它依赖 @zenfg/snapshot、Cytoscape 和 ELK,不依赖 WebGPU、wgpu、具体引擎或宿主 UI。

通过捕获的图、资源信息和可选计时了解一帧的情况,然后将 Snapshot JSON 与代码一起导出,供人工或 AI 辅助分析。参见分析与验证工作流。

该包负责 Snapshot 校验、迁移、可视化和工作台状态。宿主负责工作台周围的布局、实时捕获策略、文件保留,以及生成 Snapshot 数据的渲染器。

资源和访问统计描述的是图中捕获到的声明。它们不会自动扫描所有着色器绑定,也不会测量 GPU 总内存;工作负载私有的缓冲区可能不会出现在数据中。更明确的声明有助于诊断。参见选择资源声明粒度。

使用 @zenfg/inspector 嵌入 Snapshot 工作台、连接实时捕获、导入诊断、自定义主题,或释放 Inspector 实例。

快速入门 ​

在现有 TypeScript 应用中,使用现代浏览器运行此示例。为宿主元素设置明确尺寸(例如 height: 600px),并提供有效的 Snapshot 捕获数据。调用下面的 mountInspector(host, capture);返回的函数用于移除工作台。

将 Inspector 挂载到宿主元素,并提供可选的实时捕获回调:

ts
import { mountFrameGraphInspector, type FrameGraphCaptureRequest } from '@zenfg/inspector';
import type { FrameGraphSnapshot } from '@zenfg/snapshot';

export function mountInspector(
	host: HTMLElement,
	capture: (request: FrameGraphCaptureRequest) => FrameGraphSnapshot | Promise<FrameGraphSnapshot>,
): () => void {
	const inspector = mountFrameGraphInspector(host, {
		captureSnapshot: capture,
		branding: 'ZenFG Inspector',
	});

	return () => inspector.destroy();
}

宿主元素必须具有非零宽度和高度。FrameGraphInspector 会填满宿主,因此同一工作台既可嵌入工具面板,也可作为全页应用挂载。

mountFrameGraphInspector(host, options) 和 new FrameGraphInspector(options) 都接受 FrameGraphInspectorOptions。Graph 默认隐藏资源声明节点,以突出通道依赖和显式输出。设置 showResourceDeclarations: true 可让声明节点初始可见:

ts
import { FrameGraphInspector } from '@zenfg/inspector';

const inspector = new FrameGraphInspector({
	showResourceDeclarations: true,
});

此选项设置 Graph 的初始可见性。用户可通过工具栏的 Declarations 开关修改;选择会在当前实例的多次捕获和导入之间保留。通过 Graph 搜索或 Show in Graph 定位资源时,会自动显示声明。Resources 表格、详情、内存视图和 Snapshot 导出始终保留完整资源数据。

主题与样式自定义 ​

Inspector 默认使用 Tokyo Night Storm 主题,并提供完整的 Light 预设。可在自有宿主上使用公开的 --zfgi-* 变量,也可传入主题对象并调用 setTheme() 更新单个实例,同时保留图交互状态。动态修改外部 CSS 后,调用 refreshTheme() 以同步 Canvas 图。挂载时会自动读取静态 CSS。

JS 预设、可选 CSS 预设样式表、变量参考、兼容别名和多实例行为,详见主题说明。

常见任务 ​

任务公共 API
挂载到现有元素mountFrameGraphInspector()
创建实例但不追加到页面new FrameGraphInspector() 及其 dom 属性
从宿主请求实时数据captureSnapshot 选项
替换当前捕获setSnapshot()
读取当前规范捕获getSnapshot()
导入并迁移文件importSnapshot()
下载规范 Snapshot JSONdownloadSnapshot()
复制规范 Snapshot JSONcopySnapshotJson()
初始显示资源声明节点showResourceDeclarations 选项(默认 false)
应用预设或自定义主题theme 选项和 setTheme()
外部 CSS 变更后同步图主题refreshTheme()
设置可见的产品品牌标识branding 选项
限制导入文件大小maxImportBytes 选项
限制自动图布局maxGraphElements 选项
释放 DOM、worker 和监听器destroy()

准确选项、默认值、返回类型和生命周期行为见随包源代码及声明中保留的 TSDoc。

常见错误 ​

现象处理方式
Inspector 已挂载但不可见为宿主元素设置非零宽度和高度。
实时捕获始终不可用提供 captureSnapshot,或使用规范数据调用 setSnapshot()。
大型捕获没有图布局谨慎提高 maxGraphElements,或使用表格/Raw 视图。
导入失败后似乎没有变化查看显示的校验反馈;此前有效的捕获会按设计保留。
宿主代码中的旧捕获结果覆盖新结果由 Inspector 管理捕获顺序,不要单独应用异步结果。
卸载后 DOM 或 worker 资源仍存在释放宿主工具时调用 destroy()。

延伸阅读 ​

CPU 与 GPU 捕获 ​

Capture 操作始终同时请求 CPU 和 GPU 计时。数据提供方会收到 FrameGraphCaptureRequest,并须将其中的计时模式转发给运行时。仅捕获帧会收集计时;导入数据和普通帧不受影响。CPU 列、排序、分组汇总和覆盖率包含所有保留节点类型。CPU 执行总耗时与 GPU 时间跨度分别显示。缺失、已裁剪和实际读数为零是不同情况;零读数不表示 CPU 成本为零。

分析并验证一帧 ​

  1. 捕获一帧实际数据,并检查图、资源生命周期和诊断信息。
  2. 查看可用的 CPU/GPU 计时及其覆盖范围。确定要修改什么之前,先定位相关通道和依赖。
  3. 使用工作台下载或复制 Snapshot JSON,并连同相关图声明和渲染器代码一起交给人工或 AI 辅助分析。说明观察到的问题和约束,并使用通道名称与资源 ID 让反馈更精确。Snapshot 描述的是已声明工作,不包含着色器行为或整个引擎的内部情况。
  4. 修改代码后再次捕获。在工作负载和设备条件相近时,比较产生的结构及可用测量结果。

这是一套分析流程,不是内置 AI 集成或自动优化功能。GPU 计时取决于设备支持和节点覆盖情况;没有计时不等于零。外部引擎内部仍不可见。Snapshot 不包含 GPU 资源内容或可回放命令。Inspector 本身不会上传导入的 Snapshot;将导出数据分享给其他工具是用户单独执行的操作。

工作台行为 ​

工作台提供 Overview、Graph、Passes、Resources、Memory 和 Diagnostics 视图,以及所选对象的 Inspector。它支持实时捕获、直接替换 Snapshot、导入文件、支持的旧格式迁移、下载规范文件、复制到剪贴板、筛选、排序、展开分组和图导航。

首次捕获后会打开 Graph,且不选择对象并关闭详情面板。后续捕获若仍包含相同对象,会保留当前视图、筛选条件和选择状态。Pass 选择会根据节点 ID 在保留/裁剪状态之间跟随;若所选对象被移除,则清除选择并关闭详情。这些偏好、分组展开状态和详情宽度仅属于当前 Inspector 实例,不会跨会话保存。

视图用途
Overview显示全帧 GPU 时间跨度、CPU 执行耗时、物理分配估算、保留通道指标、GPU 或 CPU 耗时最长的五个通道、工作组成、资源/资源池摘要和诊断数量。可展开查看捕获元数据及其他 Snapshot 信息。
Graph展示 Frame Flow 结构,可按通道、资源、分组或输出搜索,并提供显式定位和可折叠图例。
Passes查看全部、保留或已裁剪通道,可按类型及名称/ID/分组筛选,并按执行顺序、GPU 或 CPU 排序。紧凑行中仍显示两种计时。独立的 Group Hierarchy 支持展开和路径搜索。
Resources可按名称/ID/分组、类型以及 Transient/Imported/Surface 筛选,并按名称、估算大小和首次使用排序。行内显示简要描述符;完整描述符和分配信息位于详情中。
Memory显示物理分配和别名节省估算、单独的累计资源池摘要,以及可折叠的分配分组和包含首末执行槽的生命周期。支持搜索、按分配/大小排序以及 All/Aliased/Single/Unallocated 筛选。
Diagnostics显示捕获到的所有错误、警告和信息消息,包括重复代码。可按严重级别按钮计数,并按代码/消息搜索;Compilation 详情另行展示可展开的保留根、裁剪原因和执行分段。

列表显示匹配数量和总数,支持连续滚动,并提供 Clear filters。Passes 先按执行顺序排列保留工作,再按录制顺序排列已裁剪工作;没有录制顺序时则按捕获顺序排列。保留表示编译器保留了某通道,并不证明 GPU 实际执行了它。已裁剪工作没有执行顺序、分段或 GPU 计时。Group Hierarchy 的箭头只改变树形结构;Show in Graph 是独立操作。

Diagnostics 会在每种严重级别内部保留捕获顺序;当消息同时引用节点和资源时,会分别提供链接。已裁剪节点的链接与保留节点相同。Diagnostics 标签页显示错误/警告数量。Overview 的 Capture information 中可查看来源、帧和捕获时间;未提供时间戳时显示为未知。Legend 按钮固定在左下角,可滚动面板在其上方展开,不改变画布尺寸和视口。再次点击按钮、使用面板关闭按钮、按 Escape 或点击面板外部即可关闭。 图控件也悬浮在画布上。Search 打开搜索框,Escape 关闭。结果显示对象类型、ID 和可用的分组路径;精确名称和 ID 优先。使用方向键浏览结果,按 Enter 定位当前结果。Display 菜单含 Declarations、Groups 和 Collapse All。缩放控件显示当前比例,提供放大/缩小、100%、Fit selection 和适配整张图的 Fit。这些控件会保留选择状态且不会展开分组。选中分组后,可使用明确的 Expand/Collapse 控件或双击手势。

选择面板包含 Summary、Relations 和 Raw 标签。Summary 说明编译状态、计时覆盖、访问、分配关系和关联诊断。Relations 区分访问事实、依赖、输出来源和分配归属。Raw 显示规范 Snapshot 中所选原始对象及其 JSON 路径,支持按字段/值搜索、折叠,以及无论当前搜索条件如何都复制完整对象。Legacy 导入会明确标记已迁移的规范数据。复制 ID 时不会附带展示标签。

在对象视图中选择对象会打开其详情。Overview 保留选择,同时使用全部宽度。详情面板默认宽 300px,可调整至 480px,并为主视图至少保留 520px。工作区窄于 828px 时使用最大宽度 340px 的模态抽屉,外侧至少留出 24px,并提供背景遮罩、键盘焦点约束和关闭后的焦点恢复。表格和信息布局取决于主内容宽度;空间不足时,辅助表格列会移入详情。方向键和 Home/End 切换标签。Escape 会先关闭最内层活动菜单或详情面板;Examples 宿主会遵循已处理的按键事件。

计时与内存信息解读 ​

计时标签会区分未采集、部分覆盖、完全覆盖、不适用和测得为零。Measured pass sum 是可用通道计时的总和,并显示已计时/符合条件的数量;GPU span 单独显示。不会推测不透明外部工作的耗时。单个计时应在 Passes 中比较;Diagnostics 不会重复展示。

Overview 按耗时排列已测量的通道,并显示其占全部已测量通道总和的比例,包括前五名以外的通道。GPU 覆盖率统计保留的渲染/计算通道;CPU 覆盖率统计所有保留通道。总和为零时不计算百分比。点击通道可在 Passes 中定位;点击 View all passes 会清除 Pass 筛选并打开列表,同时保留排序方式。GPU/CPU 选择及已展开的 Overview 内容随 Inspector 实例保留。

内存数值是估算值,各指标的统计范围不同:

指标含义
瞬态估算声明的逻辑瞬态资源估算大小。
逻辑容量按每个已分配的逻辑瞬态资源计数的分配容量。
物理分配估算分配报告中各物理分配的估算大小,每项只计一次。
别名节省估算在两项数据均已知时,以逻辑容量减去物理分配估算。
空闲保留估算采样时生产者报告的资源池空闲分配;它们可能比当前图存续更久。

报告不可用不等于数值为零。未知的资源/分配大小仍然未知,部分汇总会显示已知大小的覆盖情况。有效的空报告可以具有真实的零总量。这些指标都不是 GPU 总内存或实测峰值。内存汇总始终覆盖整个 Snapshot;筛选只改变可见行和匹配数量。生命周期包含首次和末次执行槽。刻度、网格线和资源条共用稳定的 Snapshot 坐标范围;生命周期缺失时不显示资源条。

内容宽度不小于 1000px 时,列表使用完整表格;低于 1000px 时合并次要列;低于 600px 时改为紧凑行。即使选择面板压缩了主内容宽度,GPU/CPU 计时和资源估算仍保持可见。所有宽度下的内存生命周期都使用完整执行槽范围。分配折叠状态和估算信息会跨捕获保留;搜索会临时展开匹配分配,显式定位会展开目标,但不会改变普通选择行为。

Diagnostics 的严重级别数量始终统计整个 Snapshot;匹配数同时反映搜索条件和严重级别。筛选消息不会筛选 Compilation 详情。Summary 优先显示对象自身测量值,再显示辅助事实,并记住每个对象的展开状态。Relations 将对象选择与定位图标分开。Raw 会高亮匹配字段和值,并始终复制完整规范对象,包括当前隐藏的字段。

Overview 将资源池复用标为累计值:复用/获取计数器覆盖资源池整个生命周期,而不只是当前捕获帧。空闲资源池字节数与当前帧的物理分配估算分开显示。逻辑瞬态估算可能包含仅被已裁剪通道引用的资源,可在 Additional snapshot details 中查看。

Frame Flow 交互 ​

阅读分组 ​

打开 Declarations,可查看位于声明分组内的资源入口;使用 Groups 和展开控件浏览捕获到的层级。跨组使用不会移动入口;捕获的边界关系会计入组的 Inputs/Outputs。Imported 表示调用方拥有的原生存储,不表示从其他诊断分组借用。相同标签仍对应不同分组。

分组描述诊断归属,不决定保留、分配隔离或 GPU 内存独占所有权。共享/别名分配可能同时计入多个分组摘要。完整的显示和选择行为见 Frame Flow 指南。

Graph 是单一的 Frame Flow 视图:资源声明 → 保留通道的依赖 → 显式资源输出。资源入口归属于其声明分组;输出根保持在顶层,并使用编译器提供的最终生产者和初始内容贡献信息。已裁剪通道仍可在列表和详情中查看,但不显示在图中。折叠分组会汇总关系,但不会丢弃底层语义。 Graph 初始隐藏资源声明入口,以便聚焦通道依赖和输出。打开工具栏的 Declarations 开关即可显示入口。隐藏时,声明入口、相关关系(包括初始内容到输出的边)以及仅包含资源的分组都会从布局中移除;通道依赖和生产者到输出的边仍保留。宿主可设置 showResourceDeclarations: true,并通过 FrameGraphInspectorOptions 构造或挂载 Inspector,让声明默认可见;此选项只设置初始可见性。 已知有初始内容贡献的输出显示 With initial contents 或 Initial contents only;不会推断不可用的 Legacy 来源。 该开关会在当前 Inspector 实例的不同视图、捕获和导入之间保持状态。 切换后会适配更新后的图,同时保留选择和分组展开状态。Resources 表格、详情、内存视图和 Snapshot 导出仍包含完整数据。

所有节点均使用单线边框。普通通道为圆角矩形,外部提交为切角矩形,资源入口为椭圆,输出根为向右的标签形状。声明和输出各自使用独立于 Buffer/Texture 的角色颜色;不同通道类别使用不同颜色。Resources 和 Memory 视图仍按资源类型着色。悬停和选择只强调边框,不改变形状、文字颜色或填充。

通道节点先显示名称,随后显示类型、从零开始的执行槽(#n),以及可用时的分段索引(Sn)。横向布局表达依赖关系,不代表实测执行时间或时间线。 入口先显示来源/类型,再显示资源名称;输出先显示用途,再显示名称。长名称会换行,悬停和详情中可查看完整名称。只有同一资源和用途具有不同范围时才显示范围。精确范围和最终来源仍可在悬停/详情中查看。语义缩放会隐藏辅助类型和范围摘要。分组图例描述整个 Snapshot 的 Frame Flow(包括已折叠对象),遵循 Declarations 开关,并在分组展开/折叠时保持稳定。仅含已裁剪节点的类别和未使用资源不会新增图例项。

类别填充使用叠加在画布上的不透明 sRGB 色调:Storm 为 18%,Light 为 8%。各主题节点文字目标对比度至少为 7:1,辅助文字为 4.5:1,识别性边框/符号相对于邻近背景为 3:1。自动检查覆盖两个官方主题及交互状态;自定义 CSS 颜色也必须保持这些对比度关系。

实线表示声明、值和输出来源;虚线表示仅有顺序关系。边上不显示标签。悬停时会显示临时提示:资源入口和边只会关联到具有相同逻辑资源 ID 的可见入口和边,与范围无关。通道、分组和输出节点只高亮自身。这些关联不表示范围相同或存在连续数据流路径,也不会用折叠分组替代隐藏的资源入口。 直接悬停和关联悬停使用相同的强调样式。选择状态使用蓝色描边,不添加辉光。悬停 Summary 或 Relations 中的链接时,会按相同规则在图中预览目标,但不改变选择或移动视图;移开链接或更改/关闭详情面板后,预览会清除。

资源的 Pass accesses 条目只链接通道名称;访问模式、写入内容、producesValue 和可用范围仅作为说明文本显示。通道详情使用相同的访问事实。访问本身不是图关系,不会映射到任意依赖边。Resource Relations 还可按原因和范围链接到各个输出根。

点击入口、边或 Resources 行会选择同一逻辑资源,包括其所有可见入口和边,但不会选择通道、分组或输出。输出仍会选择对应的 Root。其 View resource 操作和其他资源链接也使用相同的资源选择方式。切换到其他资源会打开 Summary;再次选择当前资源则保留活动的详情标签。选择不会切换工作台视图、改变筛选、展开分组或移动视口。手动展开后,隐藏入口会显示为选中;入口隐藏时,其可见跨组边仍保持选中。悬停预览独立于选择状态,选择样式优先,且不会固定工具提示。边提示显示可见端点、资源、不同关系类型和底层关系数量(包括聚合边中的混合类型)。点击边仍会选择其逻辑资源。 Focus relations 会明确强调所选通道直接记录的关系及其可见端点,或可见分组的子树和直接边界邻居。无关内容会淡化;悬停和选择仍清晰可见。聚焦不会根据共享资源 ID 推断连续路径,也不会展开分组、改变选择、移动视口或筛选 Snapshot。关闭后恢复完整图。选择其他对象会更新聚焦;不支持的选择类型或图不可用时,此功能会禁用。 双击分组可展开或折叠,而不会替换当前选择;单击分组选择会短暂等待,以便区分这两种手势。解析结果不可用的 Legacy 输出仍会显示,但不会推断来源边。

显式 Show in … 操作会执行导航:切换视图、清除阻挡目标的筛选、展开必要的祖先分组,并滚动到或居中显示目标。窄屏宿主的抽屉会关闭,以显示目标。图搜索使用相同的显式定位方式。通过图搜索或 Show in Graph 定位资源时,也会打开 Declarations;普通选择和悬停不会改变开关。定位失败时会恢复此前的声明和分组设置。Frame Flow 中不存在的对象会显示说明及列表视图操作;定位对象不会绕过图元素数量上限。普通选择和悬停仍遵循前述行为。

捕获、导入和直接替换共用修订计数器,避免过期的异步结果覆盖更新的数据。导入失败或文件过大时,会保留当前有效捕获和 UI 状态;操作反馈可展开查看完整失败原因。视图在首次激活时渲染新捕获;选择变化只刷新活动视图和详情。内存分组与生命周期坐标按 Snapshot 缓存;只有打开 Raw 时才创建该视图。图布局按需生成;捕获超过 maxGraphElements 时会禁用图并显示说明,表格和 Raw 仍可用。

Snapshot 标签、URL、扩展和诊断内容都通过 DOM 文本 API 设置,不会作为标记或代码执行。apps/site/inspector 中的独立 Site 页面直接挂载同一个包,不会重复添加控件。

使用参考 ​

开源 / MIT 许可