Skip to content

Commit 141b767

Browse files
pcwaltonickshonpe
andauthored
Key render phases off the main world view entity, not the render world view entity. (#16942)
We won't be able to retain render phases from frame to frame if the keys are unstable. It's not as simple as simply keying off the main world entity, however, because some main world entities extract to multiple render world entities. For example, directional lights extract to multiple shadow cascades, and point lights extract to one view per cubemap face. Therefore, we key off a new type, `RetainedViewEntity`, which contains the main entity plus a *subview ID*. This is part of the preparation for retained bins. --------- Co-authored-by: ickshonpe <[email protected]>
1 parent f004789 commit 141b767

29 files changed

+459
-233
lines changed

crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bevy_render::{
77
render_phase::{TrackedRenderPass, ViewBinnedRenderPhases},
88
render_resource::{CommandEncoderDescriptor, RenderPassDescriptor, StoreOp},
99
renderer::RenderContext,
10-
view::{ViewDepthTexture, ViewTarget},
10+
view::{ExtractedView, ViewDepthTexture, ViewTarget},
1111
};
1212
use tracing::error;
1313
#[cfg(feature = "trace")]
@@ -22,6 +22,7 @@ pub struct MainOpaquePass2dNode;
2222
impl ViewNode for MainOpaquePass2dNode {
2323
type ViewQuery = (
2424
&'static ExtractedCamera,
25+
&'static ExtractedView,
2526
&'static ViewTarget,
2627
&'static ViewDepthTexture,
2728
);
@@ -30,7 +31,7 @@ impl ViewNode for MainOpaquePass2dNode {
3031
&self,
3132
graph: &mut RenderGraphContext,
3233
render_context: &mut RenderContext<'w>,
33-
(camera, target, depth): QueryItem<'w, Self::ViewQuery>,
34+
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>,
3435
world: &'w World,
3536
) -> Result<(), NodeRunError> {
3637
let (Some(opaque_phases), Some(alpha_mask_phases)) = (
@@ -47,8 +48,8 @@ impl ViewNode for MainOpaquePass2dNode {
4748

4849
let view_entity = graph.view_entity();
4950
let (Some(opaque_phase), Some(alpha_mask_phase)) = (
50-
opaque_phases.get(&view_entity),
51-
alpha_mask_phases.get(&view_entity),
51+
opaque_phases.get(&view.retained_view_entity),
52+
alpha_mask_phases.get(&view.retained_view_entity),
5253
) else {
5354
return Ok(());
5455
};

crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bevy_render::{
77
render_phase::ViewSortedRenderPhases,
88
render_resource::{RenderPassDescriptor, StoreOp},
99
renderer::RenderContext,
10-
view::{ViewDepthTexture, ViewTarget},
10+
view::{ExtractedView, ViewDepthTexture, ViewTarget},
1111
};
1212
use tracing::error;
1313
#[cfg(feature = "trace")]
@@ -19,6 +19,7 @@ pub struct MainTransparentPass2dNode {}
1919
impl ViewNode for MainTransparentPass2dNode {
2020
type ViewQuery = (
2121
&'static ExtractedCamera,
22+
&'static ExtractedView,
2223
&'static ViewTarget,
2324
&'static ViewDepthTexture,
2425
);
@@ -27,7 +28,7 @@ impl ViewNode for MainTransparentPass2dNode {
2728
&self,
2829
graph: &mut RenderGraphContext,
2930
render_context: &mut RenderContext<'w>,
30-
(camera, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>,
31+
(camera, view, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>,
3132
world: &'w World,
3233
) -> Result<(), NodeRunError> {
3334
let Some(transparent_phases) =
@@ -37,7 +38,7 @@ impl ViewNode for MainTransparentPass2dNode {
3738
};
3839

3940
let view_entity = graph.view_entity();
40-
let Some(transparent_phase) = transparent_phases.get(&view_entity) else {
41+
let Some(transparent_phase) = transparent_phases.get(&view.retained_view_entity) else {
4142
return Ok(());
4243
};
4344

crates/bevy_core_pipeline/src/core_2d/mod.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,18 @@ pub mod graph {
3333
use core::ops::Range;
3434

3535
use bevy_asset::UntypedAssetId;
36-
use bevy_render::batching::gpu_preprocessing::GpuPreprocessingMode;
37-
use bevy_utils::HashMap;
36+
use bevy_render::{
37+
batching::gpu_preprocessing::GpuPreprocessingMode,
38+
view::{ExtractedView, RetainedViewEntity},
39+
};
40+
use bevy_utils::{HashMap, HashSet};
3841
pub use camera_2d::*;
3942
pub use main_opaque_pass_2d_node::*;
4043
pub use main_transparent_pass_2d_node::*;
4144

4245
use crate::{tonemapping::TonemappingNode, upscaling::UpscalingNode};
4346
use bevy_app::{App, Plugin};
44-
use bevy_ecs::{entity::EntityHashSet, prelude::*};
47+
use bevy_ecs::prelude::*;
4548
use bevy_math::FloatOrd;
4649
use bevy_render::{
4750
camera::{Camera, ExtractedCamera},
@@ -57,7 +60,7 @@ use bevy_render::{
5760
TextureFormat, TextureUsages,
5861
},
5962
renderer::RenderDevice,
60-
sync_world::{MainEntity, RenderEntity},
63+
sync_world::MainEntity,
6164
texture::TextureCache,
6265
view::{Msaa, ViewDepthTexture},
6366
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
@@ -397,20 +400,24 @@ pub fn extract_core_2d_camera_phases(
397400
mut transparent_2d_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
398401
mut opaque_2d_phases: ResMut<ViewBinnedRenderPhases<Opaque2d>>,
399402
mut alpha_mask_2d_phases: ResMut<ViewBinnedRenderPhases<AlphaMask2d>>,
400-
cameras_2d: Extract<Query<(RenderEntity, &Camera), With<Camera2d>>>,
401-
mut live_entities: Local<EntityHashSet>,
403+
cameras_2d: Extract<Query<(Entity, &Camera), With<Camera2d>>>,
404+
mut live_entities: Local<HashSet<RetainedViewEntity>>,
402405
) {
403406
live_entities.clear();
404407

405-
for (entity, camera) in &cameras_2d {
408+
for (main_entity, camera) in &cameras_2d {
406409
if !camera.is_active {
407410
continue;
408411
}
409-
transparent_2d_phases.insert_or_clear(entity);
410-
opaque_2d_phases.insert_or_clear(entity, GpuPreprocessingMode::None);
411-
alpha_mask_2d_phases.insert_or_clear(entity, GpuPreprocessingMode::None);
412412

413-
live_entities.insert(entity);
413+
// This is the main 2D camera, so we use the first subview index (0).
414+
let retained_view_entity = RetainedViewEntity::new(main_entity.into(), 0);
415+
416+
transparent_2d_phases.insert_or_clear(retained_view_entity);
417+
opaque_2d_phases.insert_or_clear(retained_view_entity, GpuPreprocessingMode::None);
418+
alpha_mask_2d_phases.insert_or_clear(retained_view_entity, GpuPreprocessingMode::None);
419+
420+
live_entities.insert(retained_view_entity);
414421
}
415422

416423
// Clear out all dead views.
@@ -425,11 +432,13 @@ pub fn prepare_core_2d_depth_textures(
425432
render_device: Res<RenderDevice>,
426433
transparent_2d_phases: Res<ViewSortedRenderPhases<Transparent2d>>,
427434
opaque_2d_phases: Res<ViewBinnedRenderPhases<Opaque2d>>,
428-
views_2d: Query<(Entity, &ExtractedCamera, &Msaa), (With<Camera2d>,)>,
435+
views_2d: Query<(Entity, &ExtractedCamera, &ExtractedView, &Msaa), (With<Camera2d>,)>,
429436
) {
430437
let mut textures = <HashMap<_, _>>::default();
431-
for (view, camera, msaa) in &views_2d {
432-
if !opaque_2d_phases.contains_key(&view) || !transparent_2d_phases.contains_key(&view) {
438+
for (view, camera, extracted_view, msaa) in &views_2d {
439+
if !opaque_2d_phases.contains_key(&extracted_view.retained_view_entity)
440+
|| !transparent_2d_phases.contains_key(&extracted_view.retained_view_entity)
441+
{
433442
continue;
434443
};
435444

crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use crate::{
22
core_3d::Opaque3d,
33
skybox::{SkyboxBindGroup, SkyboxPipelineId},
44
};
5-
use bevy_ecs::{entity::Entity, prelude::World, query::QueryItem};
5+
use bevy_ecs::{prelude::World, query::QueryItem};
66
use bevy_render::{
77
camera::ExtractedCamera,
88
diagnostic::RecordDiagnostics,
99
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
1010
render_phase::{TrackedRenderPass, ViewBinnedRenderPhases},
1111
render_resource::{CommandEncoderDescriptor, PipelineCache, RenderPassDescriptor, StoreOp},
1212
renderer::RenderContext,
13-
view::{ViewDepthTexture, ViewTarget, ViewUniformOffset},
13+
view::{ExtractedView, ViewDepthTexture, ViewTarget, ViewUniformOffset},
1414
};
1515
use tracing::error;
1616
#[cfg(feature = "trace")]
@@ -24,8 +24,8 @@ use super::AlphaMask3d;
2424
pub struct MainOpaquePass3dNode;
2525
impl ViewNode for MainOpaquePass3dNode {
2626
type ViewQuery = (
27-
Entity,
2827
&'static ExtractedCamera,
28+
&'static ExtractedView,
2929
&'static ViewTarget,
3030
&'static ViewDepthTexture,
3131
Option<&'static SkyboxPipelineId>,
@@ -38,8 +38,8 @@ impl ViewNode for MainOpaquePass3dNode {
3838
graph: &mut RenderGraphContext,
3939
render_context: &mut RenderContext<'w>,
4040
(
41-
view,
4241
camera,
42+
extracted_view,
4343
target,
4444
depth,
4545
skybox_pipeline,
@@ -55,9 +55,10 @@ impl ViewNode for MainOpaquePass3dNode {
5555
return Ok(());
5656
};
5757

58-
let (Some(opaque_phase), Some(alpha_mask_phase)) =
59-
(opaque_phases.get(&view), alpha_mask_phases.get(&view))
60-
else {
58+
let (Some(opaque_phase), Some(alpha_mask_phase)) = (
59+
opaque_phases.get(&extracted_view.retained_view_entity),
60+
alpha_mask_phases.get(&extracted_view.retained_view_entity),
61+
) else {
6162
return Ok(());
6263
};
6364

crates/bevy_core_pipeline/src/core_3d/main_transmissive_pass_3d_node.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bevy_render::{
77
render_phase::ViewSortedRenderPhases,
88
render_resource::{Extent3d, RenderPassDescriptor, StoreOp},
99
renderer::RenderContext,
10-
view::{ViewDepthTexture, ViewTarget},
10+
view::{ExtractedView, ViewDepthTexture, ViewTarget},
1111
};
1212
use core::ops::Range;
1313
use tracing::error;
@@ -22,6 +22,7 @@ pub struct MainTransmissivePass3dNode;
2222
impl ViewNode for MainTransmissivePass3dNode {
2323
type ViewQuery = (
2424
&'static ExtractedCamera,
25+
&'static ExtractedView,
2526
&'static Camera3d,
2627
&'static ViewTarget,
2728
Option<&'static ViewTransmissionTexture>,
@@ -32,7 +33,7 @@ impl ViewNode for MainTransmissivePass3dNode {
3233
&self,
3334
graph: &mut RenderGraphContext,
3435
render_context: &mut RenderContext,
35-
(camera, camera_3d, target, transmission, depth): QueryItem<Self::ViewQuery>,
36+
(camera, view, camera_3d, target, transmission, depth): QueryItem<Self::ViewQuery>,
3637
world: &World,
3738
) -> Result<(), NodeRunError> {
3839
let view_entity = graph.view_entity();
@@ -43,7 +44,7 @@ impl ViewNode for MainTransmissivePass3dNode {
4344
return Ok(());
4445
};
4546

46-
let Some(transmissive_phase) = transmissive_phases.get(&view_entity) else {
47+
let Some(transmissive_phase) = transmissive_phases.get(&view.retained_view_entity) else {
4748
return Ok(());
4849
};
4950

crates/bevy_core_pipeline/src/core_3d/main_transparent_pass_3d_node.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bevy_render::{
77
render_phase::ViewSortedRenderPhases,
88
render_resource::{RenderPassDescriptor, StoreOp},
99
renderer::RenderContext,
10-
view::{ViewDepthTexture, ViewTarget},
10+
view::{ExtractedView, ViewDepthTexture, ViewTarget},
1111
};
1212
use tracing::error;
1313
#[cfg(feature = "trace")]
@@ -21,14 +21,15 @@ pub struct MainTransparentPass3dNode;
2121
impl ViewNode for MainTransparentPass3dNode {
2222
type ViewQuery = (
2323
&'static ExtractedCamera,
24+
&'static ExtractedView,
2425
&'static ViewTarget,
2526
&'static ViewDepthTexture,
2627
);
2728
fn run(
2829
&self,
2930
graph: &mut RenderGraphContext,
3031
render_context: &mut RenderContext,
31-
(camera, target, depth): QueryItem<Self::ViewQuery>,
32+
(camera, view, target, depth): QueryItem<Self::ViewQuery>,
3233
world: &World,
3334
) -> Result<(), NodeRunError> {
3435
let view_entity = graph.view_entity();
@@ -39,7 +40,7 @@ impl ViewNode for MainTransparentPass3dNode {
3940
return Ok(());
4041
};
4142

42-
let Some(transparent_phase) = transparent_phases.get(&view_entity) else {
43+
let Some(transparent_phase) = transparent_phases.get(&view.retained_view_entity) else {
4344
return Ok(());
4445
};
4546

0 commit comments

Comments
 (0)