Rust 运行时概念
系统边界
图负责管理已声明的依赖、保留、瞬态资源分配和诊断信息。应用负责设备、队列、表面、呈现、管线、导入的存储,以及设备丢失策略。Snapshot 是独立的可移植协议。
录制与执行
无论编译成功还是失败,编译都会消耗这次录制。句柄和访问令牌仅在所属录制中有效。编译器会保留录制顺序的稳定子序列,不会重排或合并节点。不同帧之间的关系由应用策略和队列顺序决定,不会自动进行跨帧分析。
编译后的帧会独占借用其图,执行时则会消耗该帧。每个呈现帧都应获取并导入一张新的表面纹理。回调是同步的;可选的 GPU 回读是单独的操作。
资源与内容
瞬态存储由图负责管理并纳入资源池;导入资源借用调用方拥有的原生存储,图不会将其纳入资源池,也不会销毁它。每个组合边界只需导入一次共享存储。解析出的瞬态对象必须留在接收它的回调内。需要在之后继续使用的结果,必须存放在导入的存储中。
选择资源声明粒度
声明能够表达依赖、图分配或可观察结果的资源即可。工作负载私有的权重、uniform 和临时工作区可以在内部绑定。这不会放宽对图可见资源在访问声明、初始化和生命周期方面的完整要求。Inspector 统计的是资源声明,不是每个着色器绑定,也不是 GPU 物理内存分配总量。
内容有效性
瞬态资源和表面资源的内容初始均未定义。导入资源必须明确选择其初始内容状态。读取和保留式写入要求整个规范化范围内的内容均已定义。覆盖式写入表示调用方保证每条执行路径都会完整写入;部分写入、条件写入、稀疏写入或原子写入都需要保留原内容。清除附件会覆盖内容,加载附件会保留内容,丢弃则会使内容变为未定义。省略视图的层数时,会选取剩余的所有层;显式指定 D2 视图时,必须只选一层。
依赖与保留
写后读依赖(RAW)会传递值,也可以保留其生产节点。其他排序冲突不会让原本不可达的工作变得可观察。保留根会保留呈现、输出、回读、调试捕获、持久状态或实际副作用所需的最终范围。根范围中存在未定义或已丢弃的内容时,即使未启用报告,编译也会以 FG1004 失败。
根的身份由资源、原因和规范化范围共同确定;彼此重叠但不同的范围仍分别处理。空根会被拒绝。根不会转移资源所有权,也不会让瞬态对象在执行结束后继续有效。
生命周期与分配
保留节点对瞬态资源的首次和末次访问决定其生命周期。生命周期不重叠且兼容的资源可以共用同一分配。作用域用于划定分配别名共享和跨次执行复用的范围;省略作用域时使用默认区域。作用域不拥有资源,无需通过 Drop 清理,清空资源池后仍可继续使用。导入资源和表面资源不会进入资源池。系统不提供自动内存预算或驱逐策略。
在两次执行之间维护资源池;帧和编译计划对图的借用会强制遵守这一边界。驱逐谓词是不会被存储的 FnMut;它会收到借用的物理描述符视图,这些视图仅在当前回调期间有效。每个保留的物理实例都会访问一次,顺序未指定。选择过程会在修改资源池前完成;若发生栈展开,资源池保持不变,但谓词产生的外部副作用不会回滚。这些视图不公开 GPU 对象、内部键或稳定的实例 ID。清空操作仍保留原有的“清空全部”含义;如需只选择默认区域,请使用 info.scope.is_none()。
执行通过参数和预检校验后,资源池年龄递增一次。空执行以及随后失败的执行也计入;获取某个实例时会将其年龄重置为零。编译、资源池维护、应用帧索引和 GPU 完成状态都不会增加年龄。执行退出时(包括失败时)都会归还瞬态资源。驱逐时销毁原生资源不会等待完成;wgpu 会延后回收已提交工作所需的资源。描述符中的字节数只是估算值,不代表驱动实际驻留量,也不代表显存会立即释放。
集成层级
尽可能使用结构化原生通道;需要在图拥有的编码器上执行自定义工作时,使用命令集成;由渲染器自行拥有编码器时,使用外部提交。命令回调不得结束或提交图拥有的编码器。所有已声明的工作都应共享同一设备和队列,并准确声明资源访问。
执行片段
保留的外部提交会关闭并提交前一个图片段,调用同步回调,然后开始下一个片段。回调返回前必须将已声明的外部工作加入队列。这会对队列提交排序,但它不是 GPU 完成栅栏,也无法回滚已经提交的工作。
诊断边界
报告、计时和资源池计数器均为可选项,彼此独立。普通执行不会收集计时数据。CPU 计时测量同步操作的实际经过时间,并非线程 CPU 使用时间;GPU 计时只覆盖保留的渲染或计算通道。不要把 CPU 和 GPU 耗时相加当作帧时间。应从同一次执行中导出彼此对应的报告。Snapshot 不包含 GPU 命令或资源内容;其线协议由 Snapshot 规范定义。