Skip to content

Commit

Permalink
Move the stage that acquires a new texture from the swap chain as late
Browse files Browse the repository at this point in the history
as possible in the rendering pipeline.

Currently, we retrieve a new texture from the pipeline in
`prepare_windows`, which executes during the `ManageViews` rendering
phase. This is inefficient if we're GPU bound, because `ManageViews`
happens before `queue_material_meshes` and
`batch_and_prepare_binned_render_phase` among other frequently-slow
systems. Retrieving a new texture from the swap chain can block for
considerable time, during which we don't want the CPU to be sitting
idle. Additionally, we don't want the GPU to be sitting idle while the
CPU works on `queue_material_meshes` and so forth.

This commit fixes the issue by moving the acquisition of a new swap
chain texture late in the pipeline, to a new phase `PrepareWindows` that
occurs right before render graph evaluation. Because render graph
evaluation needs to bind the swap chain textures in order to issue
drawing commands, this is the last possible moment where it's safe to do
so.
  • Loading branch information
pcwalton committed Dec 25, 2024
1 parent 6a4e0c8 commit 02602fc
Show file tree
Hide file tree
Showing 16 changed files with 61 additions and 36 deletions.
4 changes: 3 additions & 1 deletion crates/bevy_core_pipeline/src/auto_exposure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ impl Plugin for AutoExposurePlugin {
.add_systems(
Render,
(
prepare_buffers.in_set(RenderSet::Prepare),
prepare_buffers
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows),
queue_view_auto_exposure_pipelines.in_set(RenderSet::Queue),
),
)
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_core_pipeline/src/bloom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ impl Plugin for BloomPlugin {
.add_systems(
Render,
(
prepare_downsampling_pipeline.in_set(RenderSet::Prepare),
prepare_upsampling_pipeline.in_set(RenderSet::Prepare),
prepare_downsampling_pipeline
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows),
prepare_upsampling_pipeline
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows),
prepare_bloom_textures.in_set(RenderSet::PrepareResources),
prepare_bloom_bind_groups.in_set(RenderSet::PrepareBindGroups),
),
Expand Down
16 changes: 7 additions & 9 deletions crates/bevy_core_pipeline/src/dof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ use smallvec::SmallVec;
use crate::{
core_3d::{
graph::{Core3d, Node3d},
Camera3d, DEPTH_TEXTURE_SAMPLING_SUPPORTED,
prepare_core_3d_depth_textures, Camera3d, DEPTH_TEXTURE_SAMPLING_SUPPORTED,
},
fullscreen_vertex_shader::fullscreen_shader_vertex_state,
};
Expand Down Expand Up @@ -226,20 +226,18 @@ impl Plugin for DepthOfFieldPlugin {
.add_systems(
Render,
(
configure_depth_of_field_view_targets,
prepare_auxiliary_depth_of_field_textures,
prepare_depth_of_field_view_bind_group_layouts,
prepare_depth_of_field_pipelines,
)
.after(prepare_view_targets)
.in_set(RenderSet::ManageViews),
.in_set(RenderSet::PrepareWindows),
)
.add_systems(
Render,
(
prepare_depth_of_field_view_bind_group_layouts,
prepare_depth_of_field_pipelines,
)
.chain()
.in_set(RenderSet::Prepare),
configure_depth_of_field_view_targets
.before(prepare_core_3d_depth_textures)
.in_set(RenderSet::PrepareResources),
)
.add_systems(
Render,
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_core_pipeline/src/tonemapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use bevy_render::{
},
renderer::RenderDevice,
texture::{FallbackImage, GpuImage},
view::{ExtractedView, ViewTarget, ViewUniform},
view::{prepare_view_targets, ExtractedView, ViewTarget, ViewUniform},
Render, RenderApp, RenderSet,
};
#[cfg(not(feature = "tonemapping_luts"))]
Expand Down Expand Up @@ -117,7 +117,9 @@ impl Plugin for TonemappingPlugin {
.init_resource::<SpecializedRenderPipelines<TonemappingPipeline>>()
.add_systems(
Render,
prepare_view_tonemapping_pipelines.in_set(RenderSet::Prepare),
prepare_view_tonemapping_pipelines
.in_set(RenderSet::Prepare)
.after(prepare_view_targets),
);
}

Expand Down
1 change: 1 addition & 0 deletions crates/bevy_core_pipeline/src/upscaling/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ impl Plugin for UpscalingPlugin {
// See https://github.com/bevyengine/bevy/issues/14770 for more context.
prepare_view_upscaling_pipelines
.in_set(RenderSet::Prepare)
.after(RenderSet::PrepareWindows)
.ambiguous_with_all(),
);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/deferred/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl Plugin for DeferredPbrLightingPlugin {
.init_resource::<SpecializedRenderPipelines<DeferredLightingLayout>>()
.add_systems(
Render,
(prepare_deferred_lighting_pipelines.in_set(RenderSet::Prepare),),
prepare_deferred_lighting_pipelines.in_set(RenderSet::Prepare),
)
.add_render_graph_node::<ViewNodeRunner<DeferredOpaquePass3dPbrLightingNode>>(
Core3d,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/meshlet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ impl Plugin for MeshletPlugin {
perform_pending_meshlet_mesh_writes.in_set(RenderSet::PrepareAssets),
configure_meshlet_views
.after(prepare_view_targets)
.in_set(RenderSet::ManageViews),
.in_set(RenderSet::PrepareWindows),
prepare_meshlet_per_frame_resources.in_set(RenderSet::PrepareResources),
prepare_meshlet_view_bind_groups.in_set(RenderSet::PrepareBindGroups),
),
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/render/gpu_preprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl Plugin for GpuMeshPreprocessPlugin {
.add_systems(
Render,
(
prepare_preprocess_pipelines.in_set(RenderSet::Prepare),
prepare_preprocess_pipelines.in_set(RenderSet::Prepare).after(RenderSet::PrepareWindows),
prepare_preprocess_bind_groups
.run_if(
resource_exists::<BatchedInstanceBuffers<MeshUniform, MeshInputUniform>>,
Expand Down
7 changes: 3 additions & 4 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use bevy_render::{
renderer::{RenderAdapter, RenderDevice, RenderQueue},
texture::DefaultImageSampler,
view::{
prepare_view_targets, NoFrustumCulling, NoIndirectDrawing, RenderVisibilityRanges,
ViewTarget, ViewUniformOffset, ViewVisibility, VisibilityRange,
NoFrustumCulling, NoIndirectDrawing, RenderVisibilityRanges, ViewTarget, ViewUniformOffset,
ViewVisibility, VisibilityRange,
},
Extract,
};
Expand Down Expand Up @@ -217,8 +217,7 @@ impl Plugin for MeshRenderPlugin {
gpu_preprocessing::write_batched_instance_buffers::<MeshPipeline>
.in_set(RenderSet::PrepareResourcesFlush),
gpu_preprocessing::delete_old_work_item_buffers::<MeshPipeline>
.in_set(RenderSet::ManageViews)
.after(prepare_view_targets),
.in_set(RenderSet::PrepareResources),
collect_meshes_for_gpu_building
.in_set(RenderSet::PrepareAssets)
.after(allocator::allocate_and_free_meshes)
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_pbr/src/ssao/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ impl Plugin for ScreenSpaceAmbientOcclusionPlugin {
.add_systems(
Render,
(
prepare_ssao_pipelines.in_set(RenderSet::Prepare),
prepare_ssao_pipelines
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows),
prepare_ssao_textures.in_set(RenderSet::PrepareResources),
prepare_ssao_bind_groups.in_set(RenderSet::PrepareBindGroups),
),
Expand Down
9 changes: 7 additions & 2 deletions crates/bevy_pbr/src/volumetric_fog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,15 @@ impl Plugin for VolumetricFogPlugin {
.add_systems(
Render,
(
render::prepare_volumetric_fog_pipelines.in_set(RenderSet::Prepare),
render::prepare_volumetric_fog_uniforms.in_set(RenderSet::Prepare),
render::prepare_volumetric_fog_pipelines
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows),
render::prepare_volumetric_fog_uniforms
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows),
render::prepare_view_depth_textures_for_volumetric_fog
.in_set(RenderSet::Prepare)
.before(RenderSet::PrepareWindows)
.before(prepare_core_3d_depth_textures),
),
);
Expand Down
12 changes: 7 additions & 5 deletions crates/bevy_render/src/batching/gpu_preprocessing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use nonmax::NonMaxU32;
use wgpu::{BindingResource, BufferUsages, DownlevelFlags, Features};

use crate::{
camera::ExtractedCamera,
render_phase::{
BinnedPhaseItem, BinnedRenderPhaseBatch, BinnedRenderPhaseBatchSets,
CachedRenderPipelinePhaseItem, PhaseItemBinKey as _, PhaseItemExtraIndex, SortedPhaseItem,
Expand All @@ -24,7 +25,7 @@ use crate::{
},
render_resource::{BufferVec, GpuArrayBufferable, RawBufferVec, UninitBufferVec},
renderer::{RenderAdapter, RenderDevice, RenderQueue},
view::{ExtractedView, NoIndirectDrawing, ViewTarget},
view::{ExtractedView, NoIndirectDrawing},
Render, RenderApp, RenderSet,
};

Expand Down Expand Up @@ -491,14 +492,15 @@ pub fn clear_batched_gpu_instance_buffers<GFBD>(
/// A system that removes GPU preprocessing work item buffers that correspond to
/// deleted [`ViewTarget`]s.
///
/// This is a separate system from [`clear_batched_gpu_instance_buffers`]
/// because [`ViewTarget`]s aren't created until after the extraction phase is
/// completed.
/// View targets aren't created until the [`RenderSet::PrepareWindows`] phase,
/// so we can't issue a query for them directly. Instead, we search for
/// [`ExtractedView`]s, which the [`crate::view::prepare_view_targets`] system
/// will attach [`ViewTarget`]s to.
pub fn delete_old_work_item_buffers<GFBD>(
mut gpu_batched_instance_buffers: ResMut<
BatchedInstanceBuffers<GFBD::BufferData, GFBD::BufferInputData>,
>,
view_targets: Query<Entity, With<ViewTarget>>,
view_targets: Query<Entity, With<ExtractedView>>,
) where
GFBD: GetFullBatchData,
{
Expand Down
13 changes: 12 additions & 1 deletion crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ pub enum RenderSet {
PrepareResourcesFlush,
/// A sub-set within [`Prepare`](RenderSet::Prepare) for constructing bind groups, or other data that relies on render resources prepared in [`PrepareResources`](RenderSet::PrepareResources).
PrepareBindGroups,
/// A sub-set within [`Prepare`](RenderSet::Prepare) for acquiring the new
/// swap chain buffer.
///
/// This may block on the GPU finishing the last frame, so it should be as
/// late as possible in order to pipeline the maximum amount of CPU work.
PrepareWindows,
/// Actual rendering happens here.
/// In most cases, only the render backend should insert resources here.
Render,
Expand Down Expand Up @@ -196,7 +202,12 @@ impl Render {
.after(prepare_assets::<RenderMesh>),
);
schedule.configure_sets(
(PrepareResources, PrepareResourcesFlush, PrepareBindGroups)
(
PrepareResources,
PrepareResourcesFlush,
PrepareBindGroups,
PrepareWindows,
)
.chain()
.in_set(Prepare),
);
Expand Down
7 changes: 3 additions & 4 deletions crates/bevy_render/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,13 @@ impl Plugin for ViewPlugin {
.in_set(RenderSet::ManageViews)
.before(create_surfaces),
prepare_view_attachments
.in_set(RenderSet::ManageViews)
.in_set(RenderSet::PrepareWindows)
.before(prepare_view_targets)
.after(prepare_windows),
prepare_view_targets
.in_set(RenderSet::ManageViews)
.in_set(RenderSet::PrepareWindows)
.after(prepare_windows)
.after(crate::render_asset::prepare_assets::<GpuImage>)
.ambiguous_with(crate::camera::sort_cameras), // doesn't use `sorted_camera_index_for_target`
.after(crate::render_asset::prepare_assets::<GpuImage>),
prepare_view_uniforms.in_set(RenderSet::PrepareResources),
),
);
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/view/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Plugin for WindowRenderPlugin {
.run_if(need_surface_configuration)
.before(prepare_windows),
)
.add_systems(Render, prepare_windows.in_set(RenderSet::ManageViews));
.add_systems(Render, prepare_windows.in_set(RenderSet::PrepareWindows));
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/view/window/screenshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ impl Plugin for ScreenshotPlugin {
prepare_screenshots
.after(prepare_view_attachments)
.before(prepare_view_targets)
.in_set(RenderSet::ManageViews),
.in_set(RenderSet::PrepareWindows),
);
}
}
Expand Down

0 comments on commit 02602fc

Please sign in to comment.