Skip to content

渲染调度与阶段集合

渲染子应用有自己的调度体系,和主世界的 UpdatePostUpdate 平行运行。

三个调度

调度类型何时运行
RenderStartup一次性渲染子应用首次启动时
ExtractSchedule每帧从主世界提取数据到渲染世界
Render每帧渲染主流程:准备、排队、排序、绘制、清理

ExtractSchedule 特殊——它运行时会临时替换渲染世界的 World,让系统可以同时读取主世界(通过 Extract<T>MainWorld 资源)和写入渲染世界。

Render 调度的阶段集合

Render 调度内部用 RenderSystems(一个 SystemSet)定义了严格的执行顺序。主链是:

ExtractCommands → PrepareMeshes → CreateViews → Specialize → PrepareViews
→ Queue → PhaseSort → Prepare → Render → Cleanup → PostCleanup
集合职责
ExtractCommands应用从 ExtractSchedule 累积的命令
PrepareAssets准备本帧新建/修改/删除的资产(在 ExtractCommands 之后、PrepareMeshes 之前运行)
PrepareMeshes准备 Mesh 数据上传到 GPU
CreateViews创建额外的视图(如阴影贴图的光源视角)
Specialize特化材质网格与阴影视图(按材质参数生成管线变体)
PrepareViews为这些额外视图准备渲染目标与参数
Queue将可见实体排队为渲染阶段条目(Phase Item)
QueueMeshesQueue 的子集,处理 Mesh 排队(依赖 PrepareAssets 完成)
QueueSweepQueue 的子集,清理不可见或换阶段的 Mesh
PhaseSort排序渲染阶段(透明物体需要从远到近)
Prepare根据排序结果准备 GPU 资源、创建 BindGroup
PrepareResourcesPrepare 的子集,初始化 Buffer、Texture、Uniform
PrepareBindGroupsPrepare 的子集,构建 BindGroup(依赖 PrepareResources
Render实际发出 GPU 绘制命令
Cleanup清理本帧的临时渲染资源
PostCleanup销毁标记为 TemporaryRenderEntity 的实体

主链已经 chain() 排好了序;Queue 内部按 QueueMeshes → QueueSweep 链式执行,Prepare 内部按 PrepareResources → PrepareResourcesBatchPhases → PrepareResourcesWritePhaseBuffers → PrepareResourcesCollectPhaseBuffers → PrepareResourcesFlush → PrepareBindGroups 链式执行。你注册系统时用 .in_set(RenderSystems::Xxx) 即可精确插入到对应阶段。

完整示例

rust
struct RenderSchedulePlugin;

impl Plugin for RenderSchedulePlugin {
    fn build(&self, app: &mut App) {
        let render_app = app.sub_app_mut(RenderApp);

        // RenderStartup:仅在渲染子应用首次启动时运行一次
        render_app.add_systems(RenderStartup, init_render_resources);

        // ExtractSchedule:从主世界提取数据到渲染世界
        render_app.add_systems(ExtractSchedule, extract_game_state);

        // Render 调度:按 RenderSystems 集合的顺序执行
        render_app.add_systems(
            Render,
            (
                prepare_my_assets.in_set(RenderSystems::PrepareAssets),
                queue_my_draws.in_set(RenderSystems::Queue),
                sort_my_phase.in_set(RenderSystems::PhaseSort),
                prepare_my_bind_groups.in_set(RenderSystems::Prepare),
                issue_draw_calls.in_set(RenderSystems::Render),
                cleanup_my_resources.in_set(RenderSystems::Cleanup),
            ),
        );
    }
}

Listing 37-2:在 Render 调度的各阶段集合中注册系统

RenderStartup

RenderStartup 只运行一次,适合初始化渲染专用的资源——GPU Buffer、管线缓存、BindGroup 布局等。它在第一帧的 ExtractSchedule 之前执行。

时序关系

帧 N:
  主世界: Update → PostUpdate → Last
                        ↓ (sync)
  渲染世界: ExtractSchedule → Render (各阶段集合依次执行)

帧 N-1 的渲染可能还在 GPU 上执行(流水线并行)

Bevy 默认在独立线程上运行渲染,主世界和渲染世界流水线并行——帧 N 的逻辑和帧 N-1 的渲染同时进行。