mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
move mesh uniform construction out of Core3d (#16188)
# Objective gpu based mesh uniform construction in the `GpuPreprocessNode` is currently in `Core3d`. The node iterates all views and schedules the uniform construction for each. so - when there are multiple 3d cameras, it runs multiple times on each view - if a view wants to render meshes but doesn't use the `Core3d` graph, the camera must run later than at least one `Core3d`-based camera (or add the node to its own graph, duplicating the work) - If views want to share mesh uniforms there is no way to avoid running the preprocessing for every view ## Solution - move the node to the top level of the rendergraph, before the camera driver node - make the `PreprocessBindGroup` `clone`able, and add a `SkipGpuPreprocessing` component to allow opting out per view
This commit is contained in:
parent
cd2d14c0fd
commit
262f471934
1 changed files with 24 additions and 14 deletions
|
@ -10,11 +10,10 @@ use core::num::NonZero;
|
||||||
|
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_asset::{load_internal_asset, Handle};
|
use bevy_asset::{load_internal_asset, Handle};
|
||||||
use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
|
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{Has, QueryState},
|
query::{Has, QueryState, Without},
|
||||||
schedule::{common_conditions::resource_exists, IntoSystemConfigs as _},
|
schedule::{common_conditions::resource_exists, IntoSystemConfigs as _},
|
||||||
system::{lifetimeless::Read, Commands, Res, ResMut, Resource},
|
system::{lifetimeless::Read, Commands, Res, ResMut, Resource},
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
|
@ -24,7 +23,8 @@ use bevy_render::{
|
||||||
BatchedInstanceBuffers, GpuPreprocessingSupport, IndirectParameters,
|
BatchedInstanceBuffers, GpuPreprocessingSupport, IndirectParameters,
|
||||||
IndirectParametersBuffer, PreprocessWorkItem,
|
IndirectParametersBuffer, PreprocessWorkItem,
|
||||||
},
|
},
|
||||||
render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext},
|
graph::CameraDriverLabel,
|
||||||
|
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
binding_types::{storage_buffer, storage_buffer_read_only, uniform_buffer},
|
binding_types::{storage_buffer, storage_buffer_read_only, uniform_buffer},
|
||||||
BindGroup, BindGroupEntries, BindGroupLayout, BindingResource, BufferBinding,
|
BindGroup, BindGroupEntries, BindGroupLayout, BindingResource, BufferBinding,
|
||||||
|
@ -65,12 +65,15 @@ pub struct GpuMeshPreprocessPlugin {
|
||||||
|
|
||||||
/// The render node for the mesh uniform building pass.
|
/// The render node for the mesh uniform building pass.
|
||||||
pub struct GpuPreprocessNode {
|
pub struct GpuPreprocessNode {
|
||||||
view_query: QueryState<(
|
view_query: QueryState<
|
||||||
Entity,
|
(
|
||||||
Read<PreprocessBindGroup>,
|
Entity,
|
||||||
Read<ViewUniformOffset>,
|
Read<PreprocessBindGroup>,
|
||||||
Has<GpuCulling>,
|
Read<ViewUniformOffset>,
|
||||||
)>,
|
Has<GpuCulling>,
|
||||||
|
),
|
||||||
|
Without<SkipGpuPreprocess>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The compute shader pipelines for the mesh uniform building pass.
|
/// The compute shader pipelines for the mesh uniform building pass.
|
||||||
|
@ -108,9 +111,14 @@ bitflags! {
|
||||||
/// The compute shader bind group for the mesh uniform building pass.
|
/// The compute shader bind group for the mesh uniform building pass.
|
||||||
///
|
///
|
||||||
/// This goes on the view.
|
/// This goes on the view.
|
||||||
#[derive(Component)]
|
#[derive(Component, Clone)]
|
||||||
pub struct PreprocessBindGroup(BindGroup);
|
pub struct PreprocessBindGroup(BindGroup);
|
||||||
|
|
||||||
|
/// Stops the `GpuPreprocessNode` attempting to generate the buffer for this view
|
||||||
|
/// useful to avoid duplicating effort if the bind group is shared between views
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct SkipGpuPreprocess;
|
||||||
|
|
||||||
impl Plugin for GpuMeshPreprocessPlugin {
|
impl Plugin for GpuMeshPreprocessPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
load_internal_asset!(
|
load_internal_asset!(
|
||||||
|
@ -136,10 +144,12 @@ impl Plugin for GpuMeshPreprocessPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stitch the node in.
|
// Stitch the node in.
|
||||||
|
let gpu_preprocess_node = GpuPreprocessNode::from_world(render_app.world_mut());
|
||||||
|
let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||||
|
render_graph.add_node(NodePbr::GpuPreprocess, gpu_preprocess_node);
|
||||||
|
render_graph.add_node_edge(NodePbr::GpuPreprocess, CameraDriverLabel);
|
||||||
|
|
||||||
render_app
|
render_app
|
||||||
.add_render_graph_node::<GpuPreprocessNode>(Core3d, NodePbr::GpuPreprocess)
|
|
||||||
.add_render_graph_edges(Core3d, (NodePbr::GpuPreprocess, Node3d::Prepass))
|
|
||||||
.add_render_graph_edges(Core3d, (NodePbr::GpuPreprocess, NodePbr::ShadowPass))
|
|
||||||
.init_resource::<PreprocessPipelines>()
|
.init_resource::<PreprocessPipelines>()
|
||||||
.init_resource::<SpecializedComputePipelines<PreprocessPipeline>>()
|
.init_resource::<SpecializedComputePipelines<PreprocessPipeline>>()
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
@ -200,7 +210,7 @@ impl Node for GpuPreprocessNode {
|
||||||
// Grab the index buffer for this view.
|
// Grab the index buffer for this view.
|
||||||
let Some(index_buffer) = index_buffers.get(&view) else {
|
let Some(index_buffer) = index_buffers.get(&view) else {
|
||||||
warn!("The preprocessing index buffer wasn't present");
|
warn!("The preprocessing index buffer wasn't present");
|
||||||
return Ok(());
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Select the right pipeline, depending on whether GPU culling is in
|
// Select the right pipeline, depending on whether GPU culling is in
|
||||||
|
|
Loading…
Reference in a new issue