-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Replace RenderGraph with systems
#22144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 38 commits
fa703f0
7ac2277
2e0c5a6
8ea6a02
e5ca7e2
63388ed
c6a6706
57d84be
f5c54e0
8c01b32
ff8f43f
6342c31
b83663b
790a86d
1958963
1a7a9f4
bad4c5e
6651227
ea05761
ca6343d
f715177
3a9a97f
8d5dc16
cd7baed
6766122
9c80e00
eaa90bb
b1da2ce
23803dd
e99c18a
55a9596
4189f4f
e1ecbf7
3cc28a4
ac21b06
6d4a4b6
b07aed1
415f636
092a5e0
f786942
72fb694
7c8c843
8e4b968
c41b2e1
a012cad
32a6f25
c8a7ab9
bd962c2
e29562b
9238715
17c70cb
7fbbd53
413680e
4506380
69190b3
e360ac8
31e3fe7
86dc215
3f952a0
0a40a47
4e63f8a
c5bbcbd
804b3ed
9d5cd76
3c1df32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,7 @@ bevy_shader = { path = "../bevy_shader", version = "0.19.0-dev" } | |
| bevy_ecs = { path = "../bevy_ecs", version = "0.19.0-dev" } | ||
| bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.19.0-dev" } | ||
| bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.19.0-dev" } | ||
| bevy_post_process = { path = "../bevy_post_process", version = "0.19.0-dev" } | ||
|
||
|
|
||
| # other | ||
| tracing = { version = "0.1", default-features = false, features = ["std"] } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,16 @@ | ||
| use crate::fxaa::fxaa; | ||
| use bevy_app::prelude::*; | ||
| use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer}; | ||
| use bevy_camera::Camera; | ||
| use bevy_core_pipeline::{ | ||
| core_2d::graph::{Core2d, Node2d}, | ||
| core_3d::graph::{Core3d, Node3d}, | ||
| schedule::{Core2d, Core2dSystems, Core3d, Core3dSystems}, | ||
| FullscreenShader, | ||
| }; | ||
| use bevy_ecs::{prelude::*, query::QueryItem}; | ||
| use bevy_image::BevyDefault as _; | ||
| use bevy_reflect::{std_traits::ReflectDefault, Reflect}; | ||
| use bevy_render::{ | ||
| extract_component::{ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin}, | ||
| render_graph::RenderGraphExt, | ||
| render_resource::{ | ||
| binding_types::{sampler, texture_2d, uniform_buffer}, | ||
| *, | ||
|
|
@@ -23,7 +22,7 @@ use bevy_render::{ | |
|
|
||
| mod node; | ||
|
|
||
| pub use node::CasNode; | ||
| pub(crate) use node::cas; | ||
|
|
||
| /// Applies a contrast adaptive sharpening (CAS) filter to the camera. | ||
| /// | ||
|
|
@@ -113,42 +112,17 @@ impl Plugin for CasPlugin { | |
| }; | ||
| render_app | ||
| .add_systems(RenderStartup, init_cas_pipeline) | ||
| .add_systems(Render, prepare_cas_pipelines.in_set(RenderSystems::Prepare)); | ||
|
|
||
| { | ||
| render_app | ||
| .add_render_graph_node::<CasNode>(Core3d, Node3d::ContrastAdaptiveSharpening) | ||
| .add_render_graph_edge( | ||
| Core3d, | ||
| Node3d::Tonemapping, | ||
| Node3d::ContrastAdaptiveSharpening, | ||
| ) | ||
| .add_render_graph_edges( | ||
| Core3d, | ||
| ( | ||
| Node3d::Fxaa, | ||
| Node3d::ContrastAdaptiveSharpening, | ||
| Node3d::EndMainPassPostProcessing, | ||
| ), | ||
| ); | ||
| } | ||
| { | ||
| render_app | ||
| .add_render_graph_node::<CasNode>(Core2d, Node2d::ContrastAdaptiveSharpening) | ||
| .add_render_graph_edge( | ||
| Core2d, | ||
| Node2d::Tonemapping, | ||
| Node2d::ContrastAdaptiveSharpening, | ||
| ) | ||
| .add_render_graph_edges( | ||
| Core2d, | ||
| ( | ||
| Node2d::Fxaa, | ||
| Node2d::ContrastAdaptiveSharpening, | ||
| Node2d::EndMainPassPostProcessing, | ||
| ), | ||
| ); | ||
| } | ||
| .add_systems(Render, prepare_cas_pipelines.in_set(RenderSystems::Prepare)) | ||
| .add_systems( | ||
| Core3d, | ||
| cas.after(fxaa) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reviewer note: fxaa is ordered after tonemapping, so the .after tonemapping here is redundant thus removed
tychedelia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .before(Core3dSystems::EndMainPassPostProcessing), | ||
| ) | ||
| .add_systems( | ||
| Core2d, | ||
| cas.after(fxaa) | ||
| .before(Core2dSystems::EndMainPassPostProcessing), | ||
| ); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,126 +1,97 @@ | ||
| use std::sync::Mutex; | ||
|
|
||
| use crate::contrast_adaptive_sharpening::ViewCasPipeline; | ||
| use bevy_ecs::prelude::*; | ||
| use bevy_render::{ | ||
| diagnostic::RecordDiagnostics, | ||
| extract_component::{ComponentUniforms, DynamicUniformIndex}, | ||
| render_graph::{Node, NodeRunError, RenderGraphContext}, | ||
| render_resource::{ | ||
| BindGroup, BindGroupEntries, BufferId, Operations, PipelineCache, | ||
| RenderPassColorAttachment, RenderPassDescriptor, TextureViewId, | ||
| }, | ||
| renderer::RenderContext, | ||
| renderer::{RenderContext, ViewQuery}, | ||
| view::{ExtractedView, ViewTarget}, | ||
| }; | ||
|
|
||
| use super::{CasPipeline, CasUniform}; | ||
|
|
||
| pub struct CasNode { | ||
| query: QueryState< | ||
| pub(crate) fn cas( | ||
| view: ViewQuery< | ||
| ( | ||
| &'static ViewTarget, | ||
| &'static ViewCasPipeline, | ||
| &'static DynamicUniformIndex<CasUniform>, | ||
| &ViewTarget, | ||
| &ViewCasPipeline, | ||
| &DynamicUniformIndex<CasUniform>, | ||
| ), | ||
| With<ExtractedView>, | ||
| >, | ||
| cached_bind_group: Mutex<Option<(BufferId, TextureViewId, BindGroup)>>, | ||
| } | ||
|
|
||
| impl FromWorld for CasNode { | ||
| fn from_world(world: &mut World) -> Self { | ||
| Self { | ||
| query: QueryState::new(world), | ||
| cached_bind_group: Mutex::new(None), | ||
| sharpening_pipeline: Res<CasPipeline>, | ||
| pipeline_cache: Res<PipelineCache>, | ||
| uniforms: Res<ComponentUniforms<CasUniform>>, | ||
| mut ctx: RenderContext, | ||
| mut cached_bind_group: Local<Option<(BufferId, TextureViewId, BindGroup)>>, | ||
| ) { | ||
| let (target, pipeline, uniform_index) = view.into_inner(); | ||
|
|
||
| let uniforms_id = uniforms.buffer().unwrap().id(); | ||
| let Some(uniforms_binding) = uniforms.binding() else { | ||
| return; | ||
| }; | ||
|
|
||
| let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline.0) else { | ||
| return; | ||
| }; | ||
|
|
||
| let view_target = target.post_process_write(); | ||
| let source = view_target.source; | ||
| let destination = view_target.destination; | ||
|
|
||
| let bind_group = match &mut *cached_bind_group { | ||
| Some((buffer_id, texture_id, bind_group)) | ||
| if source.id() == *texture_id && uniforms_id == *buffer_id => | ||
| { | ||
| bind_group | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Node for CasNode { | ||
| fn update(&mut self, world: &mut World) { | ||
| self.query.update_archetypes(world); | ||
| } | ||
|
|
||
| fn run( | ||
| &self, | ||
| graph: &mut RenderGraphContext, | ||
| render_context: &mut RenderContext, | ||
| world: &World, | ||
| ) -> Result<(), NodeRunError> { | ||
| let view_entity = graph.view_entity(); | ||
| let pipeline_cache = world.resource::<PipelineCache>(); | ||
| let sharpening_pipeline = world.resource::<CasPipeline>(); | ||
| let uniforms = world.resource::<ComponentUniforms<CasUniform>>(); | ||
|
|
||
| let Ok((target, pipeline, uniform_index)) = self.query.get_manual(world, view_entity) | ||
| else { | ||
| return Ok(()); | ||
| }; | ||
|
|
||
| let uniforms_id = uniforms.buffer().unwrap().id(); | ||
| let Some(uniforms) = uniforms.binding() else { | ||
| return Ok(()); | ||
| }; | ||
|
|
||
| let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline.0) else { | ||
| return Ok(()); | ||
| }; | ||
|
|
||
| let diagnostics = render_context.diagnostic_recorder(); | ||
|
|
||
| let view_target = target.post_process_write(); | ||
| let source = view_target.source; | ||
| let destination = view_target.destination; | ||
|
|
||
| let mut cached_bind_group = self.cached_bind_group.lock().unwrap(); | ||
| let bind_group = match &mut *cached_bind_group { | ||
| Some((buffer_id, texture_id, bind_group)) | ||
| if source.id() == *texture_id && uniforms_id == *buffer_id => | ||
| { | ||
| bind_group | ||
| } | ||
| cached_bind_group => { | ||
| let bind_group = render_context.render_device().create_bind_group( | ||
| "cas_bind_group", | ||
| &pipeline_cache.get_bind_group_layout(&sharpening_pipeline.layout), | ||
| &BindGroupEntries::sequential(( | ||
| view_target.source, | ||
| &sharpening_pipeline.sampler, | ||
| uniforms, | ||
| )), | ||
| ); | ||
|
|
||
| let (_, _, bind_group) = | ||
| cached_bind_group.insert((uniforms_id, source.id(), bind_group)); | ||
| bind_group | ||
| } | ||
| }; | ||
|
|
||
| let pass_descriptor = RenderPassDescriptor { | ||
| label: Some("contrast_adaptive_sharpening"), | ||
| color_attachments: &[Some(RenderPassColorAttachment { | ||
| view: destination, | ||
| depth_slice: None, | ||
| resolve_target: None, | ||
| ops: Operations::default(), | ||
| })], | ||
| depth_stencil_attachment: None, | ||
| timestamp_writes: None, | ||
| occlusion_query_set: None, | ||
| }; | ||
|
|
||
| let mut render_pass = render_context | ||
| .command_encoder() | ||
| .begin_render_pass(&pass_descriptor); | ||
| cached => { | ||
| let bind_group = ctx.render_device().create_bind_group( | ||
| "cas_bind_group", | ||
| &pipeline_cache.get_bind_group_layout(&sharpening_pipeline.layout), | ||
| &BindGroupEntries::sequential(( | ||
| view_target.source, | ||
| &sharpening_pipeline.sampler, | ||
| uniforms_binding, | ||
| )), | ||
| ); | ||
|
|
||
| let (_, _, bind_group) = cached.insert((uniforms_id, source.id(), bind_group)); | ||
| bind_group | ||
| } | ||
| }; | ||
|
|
||
| let pass_descriptor = RenderPassDescriptor { | ||
| label: Some("contrast_adaptive_sharpening"), | ||
| color_attachments: &[Some(RenderPassColorAttachment { | ||
| view: destination, | ||
| depth_slice: None, | ||
| resolve_target: None, | ||
| ops: Operations::default(), | ||
| })], | ||
| depth_stencil_attachment: None, | ||
| timestamp_writes: None, | ||
| occlusion_query_set: None, | ||
| }; | ||
|
|
||
| let diagnostics = ctx.diagnostic_recorder(); | ||
| let diagnostics = diagnostics.as_deref(); | ||
| let time_span = diagnostics.time_span(ctx.command_encoder(), "contrast_adaptive_sharpening"); | ||
|
|
||
| { | ||
| let mut render_pass = ctx.command_encoder().begin_render_pass(&pass_descriptor); | ||
| let pass_span = diagnostics.pass_span(&mut render_pass, "contrast_adaptive_sharpening"); | ||
|
|
||
| render_pass.set_pipeline(pipeline); | ||
| render_pass.set_bind_group(0, bind_group, &[uniform_index.index()]); | ||
| render_pass.draw(0..3, 0..1); | ||
|
|
||
| pass_span.end(&mut render_pass); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| time_span.end(ctx.command_encoder()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this makes clean compile a bit worse cus linearizes compilation of these two crates, but its probably fine. could use system sets to avoid it though