Bevy 深度渲染管线重构:DepthAttachment 更名与 DepthStencilAttachment 迁移指南
本篇指南围绕 Bevy 渲染管线为支持模板(Stencil)而进行的深度附加体(Depth Attachment)类型重构展开:原 DepthAttachment 更名为 DepthStencilViewAttachment、新增 DepthStencilAttachment 包装类型、ViewDepthTexture 更名为 ViewDepthStencilTexture,以及 ViewPrepassTextures::depth 字段类型变更。读完后,你将能够理解深度/模板纹视图的多视图模型(combined / depth-only / stencil-only)、各类型的构造与调用方式,并将自定义渲染 Pass 与 Prepass 相关代码平滑迁移到新 API。
该变更集在仓库中对应迁移指南 _release-content/migration-guides/depth_attachment_changes.md(关联 PR 24725),标题为 “Changes have been made to DepthAttachment, ViewDepthTexture and ViewPrepassTextures::depth to accommodate stencil support”。下面逐条拆解这些变更,并结合当前仓库源码给出可验证的实现细节。
四项核心变更总览
| 变更前 | 变更后 | 变化要点 |
|---|---|---|
DepthAttachment |
DepthStencilViewAttachment |
内部从单个 TextureView 改为持有 DepthStencilViews;构造时需区分 combined depth-stencil、depth-only、stencil-only 三类视图,并额外提供模板面(stencil)的清除值 |
| (无对应高层封装) | 新增 DepthStencilAttachment |
持有 CachedTexture、对应的 DepthStencilViewAttachment,以及可选的上帧深度纹理与视图 |
ViewDepthTexture |
ViewDepthStencilTexture |
内部从 Texture 改为持有 DepthStencilAttachment |
ViewPrepassTextures::depth: Option<ColorAttachment> |
ViewPrepassTextures::depth: Option<DepthStencilAttachment> |
深度 Prepass 产物由颜色附加体类型改为深度模板附加体类型 |
这一组变更的共同目标是“accommodate stencil support”(适配模板功能支持),即让 Bevy 的深度纹理体系从“只关心深度”扩展为“同时管理深度与模板两个面(aspect)”。
DepthStencilViews:深度模板纹视图的多视图模型
所有变更的核心是新增的枚举 DepthStencilViews,定义于 crates/bevy_render/src/texture/texture_attachment.rs:
/// Depth and stencil views of a depth texture.
///
/// Texture views with single depth or stencil aspect can be read in shaders.
/// Texture views with all aspect is renderable.
#[derive(Clone)]
pub enum DepthStencilViews {
/// The texture only has depth aspect.
DepthOnly { depth_view: TextureView },
/// The texture only has stencil aspect.
StencilOnly { stencil_view: TextureView },
/// The texture has combined depth and stencil.
DepthStencil {
/// A texture view with both depth and stencil aspects, renderable,
/// but can't be used as a binding resource.
combined_view: TextureView,
/// A texture view with depth only aspect, sample type `unfilterable-float`
/// or `depth` in shaders, not renderable.
depth_view: TextureView,
/// A texture view with stencil only aspect, sample type `uint` in shaders,
/// not renderable.
stencil_view: TextureView,
},
}
这里体现了 WebGPU 深度格式的基本规则:同一张深度模板纹理可以派生出多种 TextureView,而不同视图的用途互斥——
- combined_view(全 aspect 视图):可渲染(renderable),用于作为
RenderPassDepthStencilAttachment挂载到渲染 Pass,但不能作为着色器绑定资源; - depth_view(单 depth aspect 视图):可在着色器中以
unfilterable-float/depth采样类型读取,但不可用于渲染; - stencil_view(单 stencil aspect 视图):可在着色器中以
uint采样类型读取,但不可用于渲染。
这正是原文档末尾给出的迁移建议的底层原因:为确保对将来自定义深度格式(如 combined depth-stencil 格式、stencil-only 格式)的兼容性,应当根据视图的实际用途,选择单 aspect 视图(用于着色器资源绑定)还是全 aspect 视图(用于渲染附加体)。
视图的获取接口
crates/bevy_render/src/texture/texture_attachment.rs 中提供了三个访问器,分别对应三类用途:
impl DepthStencilViews {
/// 返回可绑定的 depth-only 视图(StencilOnly 变体返回 None)
pub fn depth_only_view(&self) -> Option<&TextureView> { ... }
/// 返回可绑定的 stencil-only 视图(DepthOnly 变体返回 None)
pub fn stencil_only_view(&self) -> Option<&TextureView> { ... }
/// 返回可渲染的视图:DepthStencil 变体返回 combined_view,
/// DepthOnly / StencilOnly 变体返回各自的单视图
pub fn attachment_view(&self) -> &TextureView { ... }
}
在自定义 Pass 中的典型用法因此变得清晰:要在着色器里采样上一帧深度,取 depth_only_view();要把该纹挂载为 Pass 的附加体,取 attachment_view()。
视图如何从纹自动派生
DepthStencilViews::from_texture(crates/bevy_render/src/texture/texture_attachment.rs)根据纹理格式的通道决定生成哪个变体:
TextureChannel::DEPTH_STENCIL:创建默认描述符的combined_view,再分别以wgpu::TextureAspect::DepthOnly和wgpu::TextureAspect::StencilOnly创建depth_view与stencil_view;TextureChannel::DEPTH:生成DepthOnly变体;TextureChannel::STENCIL:生成StencilOnly变体;- 其他格式:直接
panic!,信息为 “Can't create depth attachment. Texture format is not a depth-stencil format.”。
也就是说,新 API 会在构造期强制校验纹理格式必须是深度/模板格式,而非深度格式在运行到该分支时才会暴露问题。
DepthStencilViewAttachment:更名后的 DepthAttachment
原来的 DepthAttachment 现更名为 DepthStencilViewAttachment(crates/bevy_render/src/texture/texture_attachment.rs):
/// A wrapper for a [`TextureView`] that is used as a [`RenderPassDepthStencilAttachment`].
#[derive(Clone)]
pub struct DepthStencilViewAttachment {
pub depth_stencil_views: DepthStencilViews,
depth_stencil_data: DepthStencilData,
}
与旧实现相比有两个实质变化:
- 持有
DepthStencilViews而非单一TextureView:需要为 combined depth-stencil、depth-only、stencil-only 三种用途分别提供对应视图; - 新增模板清除值:构造函数同时接收
depth_clear_value: Option<f32>与stencil_clear_value: Option<u32>:
impl DepthStencilViewAttachment {
pub fn new(
depth_stencil_views: DepthStencilViews,
depth_clear_value: Option<f32>,
stencil_clear_value: Option<u32>,
) -> Self { ... }
内部通过私有枚举 DepthStencilData(crates/bevy_render/src/texture/texture_attachment.rs)按视图变体分别记录 depth 与 stencil 各自的清除值及“首次调用”原子标志,实现两个面独立的首次清除语义:
get_attachment(store: StoreOp):首次调用且提供了对应清除值时,对该面执行LoadOp::Clear,否则LoadOp::Load;深度面或模板面中未提供清除值的一侧不会参与清除。从源码结构看,is_first_call标志通过fetch_and(store != StoreOp::Store, ...)更新,即StoreOp::Discard表示内容被丢弃后仍保持“首次”状态,下次使用时会再次清除;prepare_for_new_frame():把本帧标记为“未使用”,从而在下一帧首次使用时触发清除(见 crates/bevy_render/src/texture/texture_attachment.rs)。
对只关心深度的旧代码,迁移方式是:构造时传 stencil_clear_value: None,行为与原先的深度清除逻辑保持一致。
新增的 DepthStencilAttachment 高层封装
DepthStencilAttachment(crates/bevy_render/src/texture/texture_attachment.rs)是本次变更引入的新类型:
/// A wrapper for a [`CachedTexture`] that is used as a depth
/// [`RenderPassDepthStencilAttachment`].
#[derive(Clone)]
pub struct DepthStencilAttachment {
pub texture: CachedTexture,
pub previous_frame_texture: Option<CachedTexture>,
depth_stencil_view_attachment: DepthStencilViewAttachment,
pub previous_frame_depth_stencil_views: Option<DepthStencilViews>,
}
它按原文档的描述,包含“一个 CachedTexture、其对应的 DepthStencilViewAttachment,以及可选的上帧深度纹理和视图”。关键点:
new(texture, previous_frame_texture, depth_clear_value, stencil_clear_value):当提供previous_frame_texture时,会对其调用DepthStencilViews::from_texture生成previous_frame_depth_stencil_views,供时序类渲染技术(如需要读取上帧深度的 TAAO、动态 Mipmap 生成等)直接绑定;depth_stencil_views():暴露当前帧的&DepthStencilViews;get_attachment(store):委托给内部的DepthStencilViewAttachment,签名带StoreOp参数;prepare_for_new_frame():同样委托,用于帧间清除状态管理。
previous_frame_texture 字段与同文件中的 ColorAttachment(crates/bevy_render/src/texture/texture_attachment.rs)的 previous_frame_texture 设计相呼应,使深度附件也能统一支持双缓冲式“上帧纹”访问。
ViewDepthTexture 更名:ViewDepthStencilTexture
相机主 Pass 使用的深度纹组件 ViewDepthTexture 更名为 ViewDepthStencilTexture,定义于 crates/bevy_render/src/view/mod.rs:
#[derive(Component)]
pub struct ViewDepthStencilTexture {
pub attachment: DepthStencilAttachment,
}
impl ViewDepthStencilTexture {
pub fn new(
texture: CachedTexture,
depth_clear_value: Option<f32>,
stencil_clear_value: Option<u32>,
) -> Self {
let attachment =
DepthStencilAttachment::new(texture, None, depth_clear_value, stencil_clear_value);
Self { attachment }
}
pub fn texture(&self) -> &Texture {
&self.attachment.texture.texture
}
pub fn get_attachment(&self, store: StoreOp) -> RenderPassDepthStencilAttachment<'_> {
self.attachment.get_attachment(store)
}
}
迁移要点:
- ECS 查询中所有
&ViewDepthTexture/With<ViewDepthTexture>等用法需替换为&ViewDepthStencilTexture; - 需要底层
Texture的地方可继续调用texture(); - 挂载到 Pass 时通过
get_attachment(store)获取,CachedTexture与视图细节收敛到attachment字段内部。
仓库内已有调用方完成了这一迁移,可作为参照:3D 主 Pass 的纹准备在 crates/bevy_core_pipeline/src/core_3d/mod.rs 中插入 ViewDepthStencilTexture::new(...),2D 主 Pass 同理见 crates/bevy_core_pipeline/src/core_2d/mod.rs;延迟渲染 Pass 则在 crates/bevy_core_pipeline/src/deferred/node.rs 中通过 &ViewDepthStencilTexture 查询并将 &ViewDepthStencilTexture 传入绑定组构建函数;主不透明/透明 Pass 的节点(如 crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs、crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs)的静态查询列表也已改用 &ViewDepthStencilTexture。
ViewPrepassTextures::depth 类型变更
Prepass 产物组件 ViewPrepassTextures 定义于 crates/bevy_core_pipeline/src/prepass/mod.rs:
/// Textures that are written to by the prepass.
///
/// This component will only be present if any of the relevant prepass
/// components are also present.
#[derive(Component)]
pub struct ViewPrepassTextures {
/// The depth texture generated by the prepass.
/// Exists only if [`DepthPrepass`] is added to the [`ViewTarget`]
pub depth: Option<DepthStencilAttachment>,
/// The normals texture generated by the prepass.
pub normal: Option<ColorAttachment>,
/// The motion vectors texture generated by the prepass.
pub motion_vectors: Option<ColorAttachment>,
/// The deferred gbuffer generated by the deferred pass.
pub deferred: Option<ColorAttachment>,
/// A texture that specifies the deferred lighting pass id for a material.
pub deferred_lighting_pass_id: Option<ColorAttachment>,
/// The size of the textures.
pub size: Extent3d,
}
原文档指出 depth 字段从 Option<ColorAttachment> 变为 Option<DepthStencilAttachment>。这意味着此前借道颜色附加体类型持有深度 Prepass 产物的写法被取消,深度 Prepass 的纹现在具有完整的深度/模板视图语义。组件同时提供两个便捷访问器,把 DepthStencilViews 的接口“上浮”到 Prepass 层面(crates/bevy_core_pipeline/src/prepass/mod.rs):
impl ViewPrepassTextures {
pub fn depth_only_view(&self) -> Option<&TextureView> {
self.depth
.as_ref()
.and_then(|t| t.depth_stencil_views().depth_only_view())
}
pub fn previous_depth_only_view(&self) -> Option<&TextureView> {
self.depth.as_ref().and_then(|t| {
t.previous_frame_depth_stencil_views
.as_ref()
.and_then(|views| views.depth_only_view())
})
}
...
}
即:绑定着色器资源时用 depth_only_view() / previous_depth_only_view() 获取单 aspect 视图,而不是直接拿 default view 去绑定——这与开头“按用途选视图”的兼容性建议一脉相承。仓库内的实际使用示例见动态 Mipmap 生成的实验性深度路径 crates/bevy_core_pipeline/src/mip_generation/experimental/depth.rs,其中同时查询了当前帧与上一帧的深度视图;模板视图的消费方还包括 crates/bevy_pbr/src/render/light.rs 中对 DepthStencilViews 的引用(光影/阴影路径下按视图类型分别取用)。
迁移检查清单
对下游自定义 Pass 或扩展渲染插件,可按以下清单迁移:
- 类型替换:
DepthAttachment→DepthStencilViewAttachment;ViewDepthTexture→ViewDepthStencilTexture(包括With<...>、Without<...>过滤器与查询元组中的引用); - 构造参数补全:涉及深度附件构造的位置,为
depth_clear_value之外补充stencil_clear_value参数;纯深度场景传None即可; - 视图选择:凡原来直接把深度
TextureView绑进着色器的代码,改为取depth_only_view()(单 aspect、可绑定);作为渲染附加体挂载的代码,走get_attachment(store)或attachment_view()(全 aspect、可渲染); - Prepass 深度访问:
ViewPrepassTextures::depth不再是ColorAttachment,取纹请用.depth_stencil_views(),取可绑定视图请用depth_only_view()/previous_depth_only_view(); - 格式前提:传给这些类型的
CachedTexture必须是深度或模板格式,否则DepthStencilViews::from_texture会 panic。
小结
本次变更把 Bevy 的深度附加体系从“单一深度视图”重构为“深度/模板双面、多视图”模型:DepthStencilViews 按纹理格式自动派生 combined / depth-only / stencil-only 三类视图并明确各自的可渲染/可绑定边界;DepthStencilViewAttachment 为两个面提供独立的首次清除语义;DepthStencilAttachment 在更高层封装 CachedTexture 与上帧视图,支撑双缓冲式时序技术。核心实现集中在 crates/bevy_render/src/texture/texture_attachment.rs 与 crates/bevy_render/src/view/mod.rs,Prepass 侧的落地见 crates/bevy_core_pipeline/src/prepass/mod.rs,配合迁移指南 _release-content/migration-guides/depth_attachment_changes.md 即可完整完成自定义渲染代码的升级。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00