Use RenderStartup in bevy_gizmos. (#19898)

# Objective

- Progress towards #19887.

## Solution

- Convert `FromWorld` impls into systems that run in `RenderStartup`.
- Add an ordering constraint to ensure that necessary resources exist.

## Testing

- Ran `2d_gizmos` and `3d_gizmos` examples and it still worked.
This commit is contained in:
andriyDev 2025-07-02 13:38:37 -07:00 committed by GitHub
parent b79b8133c8
commit e70f84536a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 73 additions and 101 deletions

View File

@ -124,7 +124,7 @@ use {
}, },
renderer::RenderDevice, renderer::RenderDevice,
sync_world::{MainEntity, TemporaryRenderEntity}, sync_world::{MainEntity, TemporaryRenderEntity},
Extract, ExtractSchedule, Render, RenderApp, RenderSystems, Extract, ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,
}, },
bytemuck::cast_slice, bytemuck::cast_slice,
}; };
@ -176,6 +176,8 @@ impl Plugin for GizmoPlugin {
#[cfg(feature = "bevy_render")] #[cfg(feature = "bevy_render")]
if let Some(render_app) = app.get_sub_app_mut(RenderApp) { if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.add_systems(RenderStartup, init_line_gizmo_uniform_bind_group_layout);
render_app.add_systems( render_app.add_systems(
Render, Render,
prepare_line_gizmo_bind_group.in_set(RenderSystems::PrepareBindGroups), prepare_line_gizmo_bind_group.in_set(RenderSystems::PrepareBindGroups),
@ -199,26 +201,6 @@ impl Plugin for GizmoPlugin {
tracing::warn!("bevy_render feature is enabled but RenderApp was not detected. Are you sure you loaded GizmoPlugin after RenderPlugin?"); tracing::warn!("bevy_render feature is enabled but RenderApp was not detected. Are you sure you loaded GizmoPlugin after RenderPlugin?");
} }
} }
#[cfg(feature = "bevy_render")]
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
let render_device = render_app.world().resource::<RenderDevice>();
let line_layout = render_device.create_bind_group_layout(
"LineGizmoUniform layout",
&BindGroupLayoutEntries::single(
ShaderStages::VERTEX,
uniform_buffer::<LineGizmoUniform>(true),
),
);
render_app.insert_resource(LineGizmoUniformBindgroupLayout {
layout: line_layout,
});
}
} }
/// A extension trait adding `App::init_gizmo_group` and `App::insert_gizmo_config`. /// A extension trait adding `App::init_gizmo_group` and `App::insert_gizmo_config`.
@ -415,6 +397,24 @@ fn update_gizmo_meshes<Config: GizmoConfigGroup>(
} }
} }
#[cfg(feature = "bevy_render")]
fn init_line_gizmo_uniform_bind_group_layout(
mut commands: Commands,
render_device: Res<RenderDevice>,
) {
let line_layout = render_device.create_bind_group_layout(
"LineGizmoUniform layout",
&BindGroupLayoutEntries::single(
ShaderStages::VERTEX,
uniform_buffer::<LineGizmoUniform>(true),
),
);
commands.insert_resource(LineGizmoUniformBindgroupLayout {
layout: line_layout,
});
}
#[cfg(feature = "bevy_render")] #[cfg(feature = "bevy_render")]
fn extract_gizmo_data( fn extract_gizmo_data(
mut commands: Commands, mut commands: Commands,

View File

@ -1,23 +1,21 @@
use crate::{ use crate::{
config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig}, config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig},
line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo, init_line_gizmo_uniform_bind_group_layout, line_gizmo_vertex_buffer_layouts,
DrawLineJointGizmo, GizmoRenderSystems, GpuLineGizmo, LineGizmoUniformBindgroupLayout, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo, DrawLineJointGizmo, GizmoRenderSystems,
SetLineGizmoBindGroup, GpuLineGizmo, LineGizmoUniformBindgroupLayout, SetLineGizmoBindGroup,
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_embedded_asset, Handle}; use bevy_asset::{load_embedded_asset, AssetServer, Handle};
use bevy_core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT}; use bevy_core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT};
use bevy_ecs::{ use bevy_ecs::{
prelude::Entity, prelude::Entity,
resource::Resource, resource::Resource,
schedule::IntoScheduleConfigs, schedule::IntoScheduleConfigs,
system::{Query, Res, ResMut}, system::{Commands, Query, Res, ResMut},
world::{FromWorld, World},
}; };
use bevy_image::BevyDefault as _; use bevy_image::BevyDefault as _;
use bevy_math::FloatOrd; use bevy_math::FloatOrd;
use bevy_render::sync_world::MainEntity;
use bevy_render::{ use bevy_render::{
render_asset::{prepare_assets, RenderAssets}, render_asset::{prepare_assets, RenderAssets},
render_phase::{ render_phase::{
@ -28,6 +26,7 @@ use bevy_render::{
view::{ExtractedView, Msaa, RenderLayers, ViewTarget}, view::{ExtractedView, Msaa, RenderLayers, ViewTarget},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderSystems,
}; };
use bevy_render::{sync_world::MainEntity, RenderStartup};
use bevy_sprite::{Mesh2dPipeline, Mesh2dPipelineKey, SetMesh2dViewBindGroup}; use bevy_sprite::{Mesh2dPipeline, Mesh2dPipelineKey, SetMesh2dViewBindGroup};
use bevy_utils::default; use bevy_utils::default;
use tracing::error; use tracing::error;
@ -55,6 +54,10 @@ impl Plugin for LineGizmo2dPlugin {
bevy_sprite::queue_material2d_meshes::<bevy_sprite::ColorMaterial>, bevy_sprite::queue_material2d_meshes::<bevy_sprite::ColorMaterial>,
), ),
) )
.add_systems(
RenderStartup,
init_line_gizmo_pipelines.after(init_line_gizmo_uniform_bind_group_layout),
)
.add_systems( .add_systems(
Render, Render,
(queue_line_gizmos_2d, queue_line_joint_gizmos_2d) (queue_line_gizmos_2d, queue_line_joint_gizmos_2d)
@ -62,15 +65,6 @@ impl Plugin for LineGizmo2dPlugin {
.after(prepare_assets::<GpuLineGizmo>), .after(prepare_assets::<GpuLineGizmo>),
); );
} }
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<LineGizmoPipeline>();
render_app.init_resource::<LineJointGizmoPipeline>();
}
} }
#[derive(Clone, Resource)] #[derive(Clone, Resource)]
@ -80,17 +74,22 @@ struct LineGizmoPipeline {
shader: Handle<Shader>, shader: Handle<Shader>,
} }
impl FromWorld for LineGizmoPipeline { fn init_line_gizmo_pipelines(
fn from_world(render_world: &mut World) -> Self { mut commands: Commands,
LineGizmoPipeline { mesh_2d_pipeline: Res<Mesh2dPipeline>,
mesh_pipeline: render_world.resource::<Mesh2dPipeline>().clone(), uniform_bind_group_layout: Res<LineGizmoUniformBindgroupLayout>,
uniform_layout: render_world asset_server: Res<AssetServer>,
.resource::<LineGizmoUniformBindgroupLayout>() ) {
.layout commands.insert_resource(LineGizmoPipeline {
.clone(), mesh_pipeline: mesh_2d_pipeline.clone(),
shader: load_embedded_asset!(render_world, "lines.wgsl"), uniform_layout: uniform_bind_group_layout.layout.clone(),
} shader: load_embedded_asset!(asset_server.as_ref(), "lines.wgsl"),
} });
commands.insert_resource(LineJointGizmoPipeline {
mesh_pipeline: mesh_2d_pipeline.clone(),
uniform_layout: uniform_bind_group_layout.layout.clone(),
shader: load_embedded_asset!(asset_server.as_ref(), "line_joints.wgsl"),
});
} }
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
@ -178,19 +177,6 @@ struct LineJointGizmoPipeline {
shader: Handle<Shader>, shader: Handle<Shader>,
} }
impl FromWorld for LineJointGizmoPipeline {
fn from_world(render_world: &mut World) -> Self {
LineJointGizmoPipeline {
mesh_pipeline: render_world.resource::<Mesh2dPipeline>().clone(),
uniform_layout: render_world
.resource::<LineGizmoUniformBindgroupLayout>()
.layout
.clone(),
shader: load_embedded_asset!(render_world, "line_joints.wgsl"),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
struct LineJointGizmoPipelineKey { struct LineJointGizmoPipelineKey {
mesh_key: Mesh2dPipelineKey, mesh_key: Mesh2dPipelineKey,

View File

@ -1,11 +1,11 @@
use crate::{ use crate::{
config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig}, config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig},
line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo, init_line_gizmo_uniform_bind_group_layout, line_gizmo_vertex_buffer_layouts,
DrawLineJointGizmo, GizmoRenderSystems, GpuLineGizmo, LineGizmoUniformBindgroupLayout, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo, DrawLineJointGizmo, GizmoRenderSystems,
SetLineGizmoBindGroup, GpuLineGizmo, LineGizmoUniformBindgroupLayout, SetLineGizmoBindGroup,
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_embedded_asset, Handle}; use bevy_asset::{load_embedded_asset, AssetServer, Handle};
use bevy_core_pipeline::{ use bevy_core_pipeline::{
core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT}, core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT},
oit::OrderIndependentTransparencySettings, oit::OrderIndependentTransparencySettings,
@ -17,12 +17,10 @@ use bevy_ecs::{
query::Has, query::Has,
resource::Resource, resource::Resource,
schedule::IntoScheduleConfigs, schedule::IntoScheduleConfigs,
system::{Query, Res, ResMut}, system::{Commands, Query, Res, ResMut},
world::{FromWorld, World},
}; };
use bevy_image::BevyDefault as _; use bevy_image::BevyDefault as _;
use bevy_pbr::{MeshPipeline, MeshPipelineKey, SetMeshViewBindGroup}; use bevy_pbr::{MeshPipeline, MeshPipelineKey, SetMeshViewBindGroup};
use bevy_render::sync_world::MainEntity;
use bevy_render::{ use bevy_render::{
render_asset::{prepare_assets, RenderAssets}, render_asset::{prepare_assets, RenderAssets},
render_phase::{ render_phase::{
@ -33,6 +31,7 @@ use bevy_render::{
view::{ExtractedView, Msaa, RenderLayers, ViewTarget}, view::{ExtractedView, Msaa, RenderLayers, ViewTarget},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderSystems,
}; };
use bevy_render::{sync_world::MainEntity, RenderStartup};
use bevy_utils::default; use bevy_utils::default;
use tracing::error; use tracing::error;
@ -53,6 +52,10 @@ impl Plugin for LineGizmo3dPlugin {
Render, Render,
GizmoRenderSystems::QueueLineGizmos3d.in_set(RenderSystems::Queue), GizmoRenderSystems::QueueLineGizmos3d.in_set(RenderSystems::Queue),
) )
.add_systems(
RenderStartup,
init_line_gizmo_pipelines.after(init_line_gizmo_uniform_bind_group_layout),
)
.add_systems( .add_systems(
Render, Render,
(queue_line_gizmos_3d, queue_line_joint_gizmos_3d) (queue_line_gizmos_3d, queue_line_joint_gizmos_3d)
@ -60,15 +63,6 @@ impl Plugin for LineGizmo3dPlugin {
.after(prepare_assets::<GpuLineGizmo>), .after(prepare_assets::<GpuLineGizmo>),
); );
} }
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<LineGizmoPipeline>();
render_app.init_resource::<LineJointGizmoPipeline>();
}
} }
#[derive(Clone, Resource)] #[derive(Clone, Resource)]
@ -78,17 +72,22 @@ struct LineGizmoPipeline {
shader: Handle<Shader>, shader: Handle<Shader>,
} }
impl FromWorld for LineGizmoPipeline { fn init_line_gizmo_pipelines(
fn from_world(render_world: &mut World) -> Self { mut commands: Commands,
LineGizmoPipeline { mesh_pipeline: Res<MeshPipeline>,
mesh_pipeline: render_world.resource::<MeshPipeline>().clone(), uniform_bind_group_layout: Res<LineGizmoUniformBindgroupLayout>,
uniform_layout: render_world asset_server: Res<AssetServer>,
.resource::<LineGizmoUniformBindgroupLayout>() ) {
.layout commands.insert_resource(LineGizmoPipeline {
.clone(), mesh_pipeline: mesh_pipeline.clone(),
shader: load_embedded_asset!(render_world, "lines.wgsl"), uniform_layout: uniform_bind_group_layout.layout.clone(),
} shader: load_embedded_asset!(asset_server.as_ref(), "lines.wgsl"),
} });
commands.insert_resource(LineJointGizmoPipeline {
mesh_pipeline: mesh_pipeline.clone(),
uniform_layout: uniform_bind_group_layout.layout.clone(),
shader: load_embedded_asset!(asset_server.as_ref(), "line_joints.wgsl"),
});
} }
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
@ -173,19 +172,6 @@ struct LineJointGizmoPipeline {
shader: Handle<Shader>, shader: Handle<Shader>,
} }
impl FromWorld for LineJointGizmoPipeline {
fn from_world(render_world: &mut World) -> Self {
LineJointGizmoPipeline {
mesh_pipeline: render_world.resource::<MeshPipeline>().clone(),
uniform_layout: render_world
.resource::<LineGizmoUniformBindgroupLayout>()
.layout
.clone(),
shader: load_embedded_asset!(render_world, "line_joints.wgsl"),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
struct LineJointGizmoPipelineKey { struct LineJointGizmoPipelineKey {
view_key: MeshPipelineKey, view_key: MeshPipelineKey,