Convert basic example cases to use RenderStartup
.
This commit is contained in:
parent
33bed5dd70
commit
5c7dd2eec3
@ -27,7 +27,7 @@ use bevy::{
|
|||||||
sync_component::SyncComponentPlugin,
|
sync_component::SyncComponentPlugin,
|
||||||
sync_world::{MainEntityHashMap, RenderEntity},
|
sync_world::{MainEntityHashMap, RenderEntity},
|
||||||
view::{ExtractedView, RenderVisibleEntities, ViewTarget},
|
view::{ExtractedView, RenderVisibleEntities, ViewTarget},
|
||||||
Extract, Render, RenderApp, RenderSystems,
|
Extract, Render, RenderApp, RenderStartup, RenderSystems,
|
||||||
},
|
},
|
||||||
sprite::{
|
sprite::{
|
||||||
extract_mesh2d, DrawMesh2d, Material2dBindGroupId, Mesh2dPipeline, Mesh2dPipelineKey,
|
extract_mesh2d, DrawMesh2d, Material2dBindGroupId, Mesh2dPipeline, Mesh2dPipelineKey,
|
||||||
@ -132,14 +132,16 @@ pub struct ColoredMesh2dPipeline {
|
|||||||
shader: Handle<Shader>,
|
shader: Handle<Shader>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for ColoredMesh2dPipeline {
|
fn init_colored_mesh_2d_pipeline(
|
||||||
fn from_world(world: &mut World) -> Self {
|
mut commands: Commands,
|
||||||
Self {
|
mesh2d_pipeline: Res<Mesh2dPipeline>,
|
||||||
mesh2d_pipeline: Mesh2dPipeline::from_world(world),
|
colored_mesh2d_shader: Res<ColoredMesh2dShader>,
|
||||||
// Get the shader from the shader resource we inserted in the plugin.
|
) {
|
||||||
shader: world.resource::<ColoredMesh2dShader>().0.clone(),
|
commands.insert_resource(ColoredMesh2dPipeline {
|
||||||
}
|
mesh2d_pipeline: mesh2d_pipeline.clone(),
|
||||||
}
|
// Clone the shader from the shader resource we inserted in the plugin.
|
||||||
|
shader: colored_mesh2d_shader.0.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// We implement `SpecializedPipeline` to customize the default rendering from `Mesh2dPipeline`
|
// We implement `SpecializedPipeline` to customize the default rendering from `Mesh2dPipeline`
|
||||||
@ -307,6 +309,7 @@ impl Plugin for ColoredMesh2dPlugin {
|
|||||||
.add_render_command::<Transparent2d, DrawColoredMesh2d>()
|
.add_render_command::<Transparent2d, DrawColoredMesh2d>()
|
||||||
.init_resource::<SpecializedRenderPipelines<ColoredMesh2dPipeline>>()
|
.init_resource::<SpecializedRenderPipelines<ColoredMesh2dPipeline>>()
|
||||||
.init_resource::<RenderColoredMesh2dInstances>()
|
.init_resource::<RenderColoredMesh2dInstances>()
|
||||||
|
.add_systems(RenderStartup, init_colored_mesh_2d_pipeline)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
ExtractSchedule,
|
ExtractSchedule,
|
||||||
extract_colored_mesh2d.after(extract_mesh2d),
|
extract_colored_mesh2d.after(extract_mesh2d),
|
||||||
@ -316,13 +319,6 @@ impl Plugin for ColoredMesh2dPlugin {
|
|||||||
queue_colored_mesh2d.in_set(RenderSystems::QueueMeshes),
|
queue_colored_mesh2d.in_set(RenderSystems::QueueMeshes),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
|
||||||
// Register our custom pipeline
|
|
||||||
app.get_sub_app_mut(RenderApp)
|
|
||||||
.unwrap()
|
|
||||||
.init_resource::<ColoredMesh2dPipeline>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the [`ColoredMesh2d`] marker component into the render app
|
/// Extract the [`ColoredMesh2d`] marker component into the render app
|
||||||
|
@ -12,7 +12,7 @@ use bevy::{
|
|||||||
render_resource::{binding_types::texture_storage_2d, *},
|
render_resource::{binding_types::texture_storage_2d, *},
|
||||||
renderer::{RenderContext, RenderDevice},
|
renderer::{RenderContext, RenderDevice},
|
||||||
texture::GpuImage,
|
texture::GpuImage,
|
||||||
Render, RenderApp, RenderSystems,
|
Render, RenderApp, RenderStartup, RenderSystems,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -103,20 +103,17 @@ impl Plugin for GameOfLifeComputePlugin {
|
|||||||
// for operation on by the compute shader and display on the sprite.
|
// for operation on by the compute shader and display on the sprite.
|
||||||
app.add_plugins(ExtractResourcePlugin::<GameOfLifeImages>::default());
|
app.add_plugins(ExtractResourcePlugin::<GameOfLifeImages>::default());
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
render_app.add_systems(
|
render_app
|
||||||
Render,
|
.add_systems(RenderStartup, init_game_of_life_pipeline)
|
||||||
prepare_bind_group.in_set(RenderSystems::PrepareBindGroups),
|
.add_systems(
|
||||||
);
|
Render,
|
||||||
|
prepare_bind_group.in_set(RenderSystems::PrepareBindGroups),
|
||||||
|
);
|
||||||
|
|
||||||
let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||||
render_graph.add_node(GameOfLifeLabel, GameOfLifeNode::default());
|
render_graph.add_node(GameOfLifeLabel, GameOfLifeNode::default());
|
||||||
render_graph.add_node_edge(GameOfLifeLabel, bevy::render::graph::CameraDriverLabel);
|
render_graph.add_node_edge(GameOfLifeLabel, bevy::render::graph::CameraDriverLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
|
||||||
render_app.init_resource::<GameOfLifePipeline>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource, Clone, ExtractResource)]
|
#[derive(Resource, Clone, ExtractResource)]
|
||||||
@ -157,40 +154,41 @@ struct GameOfLifePipeline {
|
|||||||
update_pipeline: CachedComputePipelineId,
|
update_pipeline: CachedComputePipelineId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for GameOfLifePipeline {
|
fn init_game_of_life_pipeline(
|
||||||
fn from_world(world: &mut World) -> Self {
|
mut commands: Commands,
|
||||||
let render_device = world.resource::<RenderDevice>();
|
render_device: Res<RenderDevice>,
|
||||||
let texture_bind_group_layout = render_device.create_bind_group_layout(
|
asset_server: Res<AssetServer>,
|
||||||
"GameOfLifeImages",
|
pipeline_cache: Res<PipelineCache>,
|
||||||
&BindGroupLayoutEntries::sequential(
|
) {
|
||||||
ShaderStages::COMPUTE,
|
let texture_bind_group_layout = render_device.create_bind_group_layout(
|
||||||
(
|
"GameOfLifeImages",
|
||||||
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::ReadOnly),
|
&BindGroupLayoutEntries::sequential(
|
||||||
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly),
|
ShaderStages::COMPUTE,
|
||||||
),
|
(
|
||||||
|
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::ReadOnly),
|
||||||
|
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
let shader = world.load_asset(SHADER_ASSET_PATH);
|
);
|
||||||
let pipeline_cache = world.resource::<PipelineCache>();
|
let shader = asset_server.load(SHADER_ASSET_PATH);
|
||||||
let init_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
let init_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
||||||
layout: vec![texture_bind_group_layout.clone()],
|
layout: vec![texture_bind_group_layout.clone()],
|
||||||
shader: shader.clone(),
|
shader: shader.clone(),
|
||||||
entry_point: Some(Cow::from("init")),
|
entry_point: Some(Cow::from("init")),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
||||||
layout: vec![texture_bind_group_layout.clone()],
|
layout: vec![texture_bind_group_layout.clone()],
|
||||||
shader,
|
shader,
|
||||||
entry_point: Some(Cow::from("update")),
|
entry_point: Some(Cow::from("update")),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
GameOfLifePipeline {
|
commands.insert_resource(GameOfLifePipeline {
|
||||||
texture_bind_group_layout,
|
texture_bind_group_layout,
|
||||||
init_pipeline,
|
init_pipeline,
|
||||||
update_pipeline,
|
update_pipeline,
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GameOfLifeState {
|
enum GameOfLifeState {
|
||||||
|
@ -55,7 +55,7 @@ use bevy::{
|
|||||||
renderer::RenderContext,
|
renderer::RenderContext,
|
||||||
sync_world::MainEntity,
|
sync_world::MainEntity,
|
||||||
view::{ExtractedView, RenderVisibleEntities, RetainedViewEntity, ViewTarget},
|
view::{ExtractedView, RenderVisibleEntities, RetainedViewEntity, ViewTarget},
|
||||||
Extract, Render, RenderApp, RenderDebugFlags, RenderSystems,
|
Extract, Render, RenderApp, RenderDebugFlags, RenderStartup, RenderSystems,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use nonmax::NonMaxU32;
|
use nonmax::NonMaxU32;
|
||||||
@ -127,6 +127,7 @@ impl Plugin for MeshStencilPhasePlugin {
|
|||||||
.init_resource::<DrawFunctions<Stencil3d>>()
|
.init_resource::<DrawFunctions<Stencil3d>>()
|
||||||
.add_render_command::<Stencil3d, DrawMesh3dStencil>()
|
.add_render_command::<Stencil3d, DrawMesh3dStencil>()
|
||||||
.init_resource::<ViewSortedRenderPhases<Stencil3d>>()
|
.init_resource::<ViewSortedRenderPhases<Stencil3d>>()
|
||||||
|
.add_systems(RenderStartup, init_stencil_pipeline)
|
||||||
.add_systems(ExtractSchedule, extract_camera_phases)
|
.add_systems(ExtractSchedule, extract_camera_phases)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
@ -143,16 +144,6 @@ impl Plugin for MeshStencilPhasePlugin {
|
|||||||
// Tell the node to run after the main pass
|
// Tell the node to run after the main pass
|
||||||
.add_render_graph_edges(Core3d, (Node3d::MainOpaquePass, CustomDrawPassLabel));
|
.add_render_graph_edges(Core3d, (Node3d::MainOpaquePass, CustomDrawPassLabel));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
|
||||||
// We need to get the render app from the main app
|
|
||||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
// The pipeline needs the RenderDevice to be created and it's only available once plugins
|
|
||||||
// are initialized
|
|
||||||
render_app.init_resource::<StencilPipeline>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
@ -167,13 +158,15 @@ struct StencilPipeline {
|
|||||||
shader_handle: Handle<Shader>,
|
shader_handle: Handle<Shader>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for StencilPipeline {
|
fn init_stencil_pipeline(
|
||||||
fn from_world(world: &mut World) -> Self {
|
mut commands: Commands,
|
||||||
Self {
|
mesh_pipeline: Res<MeshPipeline>,
|
||||||
mesh_pipeline: MeshPipeline::from_world(world),
|
asset_server: Res<AssetServer>,
|
||||||
shader_handle: world.resource::<AssetServer>().load(SHADER_ASSET_PATH),
|
) {
|
||||||
}
|
commands.insert_resource(StencilPipeline {
|
||||||
}
|
mesh_pipeline: mesh_pipeline.clone(),
|
||||||
|
shader_handle: asset_server.load(SHADER_ASSET_PATH),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// For more information on how SpecializedMeshPipeline work, please look at the
|
// For more information on how SpecializedMeshPipeline work, please look at the
|
||||||
|
@ -32,7 +32,7 @@ use bevy::{
|
|||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
sync_world::MainEntity,
|
sync_world::MainEntity,
|
||||||
view::{ExtractedView, NoFrustumCulling, NoIndirectDrawing},
|
view::{ExtractedView, NoFrustumCulling, NoIndirectDrawing},
|
||||||
Render, RenderApp, RenderSystems,
|
Render, RenderApp, RenderStartup, RenderSystems,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
@ -102,6 +102,7 @@ impl Plugin for CustomMaterialPlugin {
|
|||||||
app.sub_app_mut(RenderApp)
|
app.sub_app_mut(RenderApp)
|
||||||
.add_render_command::<Transparent3d, DrawCustom>()
|
.add_render_command::<Transparent3d, DrawCustom>()
|
||||||
.init_resource::<SpecializedMeshPipelines<CustomPipeline>>()
|
.init_resource::<SpecializedMeshPipelines<CustomPipeline>>()
|
||||||
|
.add_systems(RenderStartup, init_custom_pipeline)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
(
|
(
|
||||||
@ -110,10 +111,6 @@ impl Plugin for CustomMaterialPlugin {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
|
||||||
app.sub_app_mut(RenderApp).init_resource::<CustomPipeline>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Pod, Zeroable)]
|
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||||
@ -203,15 +200,15 @@ struct CustomPipeline {
|
|||||||
mesh_pipeline: MeshPipeline,
|
mesh_pipeline: MeshPipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for CustomPipeline {
|
fn init_custom_pipeline(
|
||||||
fn from_world(world: &mut World) -> Self {
|
mut commands: Commands,
|
||||||
let mesh_pipeline = world.resource::<MeshPipeline>();
|
asset_server: Res<AssetServer>,
|
||||||
|
mesh_pipeline: Res<MeshPipeline>,
|
||||||
CustomPipeline {
|
) {
|
||||||
shader: world.load_asset(SHADER_ASSET_PATH),
|
commands.insert_resource(CustomPipeline {
|
||||||
mesh_pipeline: mesh_pipeline.clone(),
|
shader: asset_server.load(SHADER_ASSET_PATH),
|
||||||
}
|
mesh_pipeline: mesh_pipeline.clone(),
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecializedMeshPipeline for CustomPipeline {
|
impl SpecializedMeshPipeline for CustomPipeline {
|
||||||
|
@ -39,7 +39,7 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
view::NoIndirectDrawing,
|
view::NoIndirectDrawing,
|
||||||
view::{self, ExtractedView, RenderVisibleEntities, ViewTarget, VisibilityClass},
|
view::{self, ExtractedView, RenderVisibleEntities, ViewTarget, VisibilityClass},
|
||||||
Render, RenderApp, RenderSystems,
|
Render, RenderApp, RenderStartup, RenderSystems,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -118,20 +118,12 @@ impl Plugin for CustomRenderedMeshPipelinePlugin {
|
|||||||
.init_resource::<SpecializedMeshPipelines<CustomMeshPipeline>>()
|
.init_resource::<SpecializedMeshPipelines<CustomMeshPipeline>>()
|
||||||
// We need to use a custom draw command so we need to register it
|
// We need to use a custom draw command so we need to register it
|
||||||
.add_render_command::<Opaque3d, DrawSpecializedPipelineCommands>()
|
.add_render_command::<Opaque3d, DrawSpecializedPipelineCommands>()
|
||||||
|
.add_systems(RenderStartup, init_custom_mesh_pipeline)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
queue_custom_mesh_pipeline.in_set(RenderSystems::Queue),
|
queue_custom_mesh_pipeline.in_set(RenderSystems::Queue),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
|
||||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
// Creating this pipeline needs the RenderDevice and RenderQueue
|
|
||||||
// which are only available once rendering plugins are initialized.
|
|
||||||
render_app.init_resource::<CustomMeshPipeline>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A marker component that represents an entity that is to be rendered using
|
/// A marker component that represents an entity that is to be rendered using
|
||||||
@ -174,15 +166,17 @@ struct CustomMeshPipeline {
|
|||||||
shader_handle: Handle<Shader>,
|
shader_handle: Handle<Shader>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for CustomMeshPipeline {
|
fn init_custom_mesh_pipeline(
|
||||||
fn from_world(world: &mut World) -> Self {
|
mut commands: Commands,
|
||||||
// Load the shader
|
asset_server: Res<AssetServer>,
|
||||||
let shader_handle: Handle<Shader> = world.resource::<AssetServer>().load(SHADER_ASSET_PATH);
|
mesh_pipeline: Res<MeshPipeline>,
|
||||||
Self {
|
) {
|
||||||
mesh_pipeline: MeshPipeline::from_world(world),
|
// Load the shader
|
||||||
shader_handle,
|
let shader_handle: Handle<Shader> = asset_server.load(SHADER_ASSET_PATH);
|
||||||
}
|
commands.insert_resource(CustomMeshPipeline {
|
||||||
}
|
mesh_pipeline: mesh_pipeline.clone(),
|
||||||
|
shader_handle,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecializedMeshPipeline for CustomMeshPipeline {
|
impl SpecializedMeshPipeline for CustomMeshPipeline {
|
||||||
|
Loading…
Reference in New Issue
Block a user