Skip to content

Commit

Permalink
Key render phases off the main world view entity, not the render world
Browse files Browse the repository at this point in the history
view entity.

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.
  • Loading branch information
pcwalton committed Dec 23, 2024
1 parent 022c6b1 commit e4b5efa
Show file tree
Hide file tree
Showing 29 changed files with 340 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy_render::{
render_phase::{TrackedRenderPass, ViewBinnedRenderPhases},
render_resource::{CommandEncoderDescriptor, RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget},
view::{ExtractedView, ViewDepthTexture, ViewTarget},
};
use bevy_utils::tracing::error;
#[cfg(feature = "trace")]
Expand All @@ -22,6 +22,7 @@ pub struct MainOpaquePass2dNode;
impl ViewNode for MainOpaquePass2dNode {
type ViewQuery = (
&'static ExtractedCamera,
&'static ExtractedView,
&'static ViewTarget,
&'static ViewDepthTexture,
);
Expand All @@ -30,7 +31,7 @@ impl ViewNode for MainOpaquePass2dNode {
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>,
(camera, target, depth): QueryItem<'w, Self::ViewQuery>,
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>,
world: &'w World,
) -> Result<(), NodeRunError> {
let (Some(opaque_phases), Some(alpha_mask_phases)) = (
Expand All @@ -47,8 +48,8 @@ impl ViewNode for MainOpaquePass2dNode {

let view_entity = graph.view_entity();
let (Some(opaque_phase), Some(alpha_mask_phase)) = (
opaque_phases.get(&view_entity),
alpha_mask_phases.get(&view_entity),
opaque_phases.get(&view.retained_view_entity),
alpha_mask_phases.get(&view.retained_view_entity),
) else {
return Ok(());
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy_render::{
render_phase::ViewSortedRenderPhases,
render_resource::{RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget},
view::{ExtractedView, ViewDepthTexture, ViewTarget},
};
use bevy_utils::tracing::error;
#[cfg(feature = "trace")]
Expand All @@ -19,6 +19,7 @@ pub struct MainTransparentPass2dNode {}
impl ViewNode for MainTransparentPass2dNode {
type ViewQuery = (
&'static ExtractedCamera,
&'static ExtractedView,
&'static ViewTarget,
&'static ViewDepthTexture,
);
Expand All @@ -27,7 +28,7 @@ impl ViewNode for MainTransparentPass2dNode {
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>,
(camera, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>,
(camera, view, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>,
world: &'w World,
) -> Result<(), NodeRunError> {
let Some(transparent_phases) =
Expand All @@ -37,7 +38,7 @@ impl ViewNode for MainTransparentPass2dNode {
};

let view_entity = graph.view_entity();
let Some(transparent_phase) = transparent_phases.get(&view_entity) else {
let Some(transparent_phase) = transparent_phases.get(&view.retained_view_entity) else {
return Ok(());
};

Expand Down
36 changes: 22 additions & 14 deletions crates/bevy_core_pipeline/src/core_2d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@ use core::ops::Range;

use bevy_asset::UntypedAssetId;
use bevy_render::{
batching::gpu_preprocessing::GpuPreprocessingMode, render_phase::PhaseItemBinKey,
batching::gpu_preprocessing::GpuPreprocessingMode,
render_phase::PhaseItemBinKey,
view::{ExtractedView, RetainedViewEntity},
};
use bevy_utils::HashMap;
use bevy_utils::{HashMap, HashSet};
pub use camera_2d::*;
pub use main_opaque_pass_2d_node::*;
pub use main_transparent_pass_2d_node::*;

use crate::{tonemapping::TonemappingNode, upscaling::UpscalingNode};
use bevy_app::{App, Plugin};
use bevy_ecs::{entity::EntityHashSet, prelude::*};
use bevy_ecs::prelude::*;
use bevy_math::FloatOrd;
use bevy_render::{
camera::{Camera, ExtractedCamera},
Expand All @@ -59,7 +61,7 @@ use bevy_render::{
TextureFormat, TextureUsages,
},
renderer::RenderDevice,
sync_world::{MainEntity, RenderEntity},
sync_world::MainEntity,
texture::TextureCache,
view::{Msaa, ViewDepthTexture},
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
Expand Down Expand Up @@ -393,20 +395,24 @@ pub fn extract_core_2d_camera_phases(
mut transparent_2d_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
mut opaque_2d_phases: ResMut<ViewBinnedRenderPhases<Opaque2d>>,
mut alpha_mask_2d_phases: ResMut<ViewBinnedRenderPhases<AlphaMask2d>>,
cameras_2d: Extract<Query<(RenderEntity, &Camera), With<Camera2d>>>,
mut live_entities: Local<EntityHashSet>,
cameras_2d: Extract<Query<(Entity, &Camera), With<Camera2d>>>,
mut live_entities: Local<HashSet<RetainedViewEntity>>,
) {
live_entities.clear();

for (entity, camera) in &cameras_2d {
for (main_entity, camera) in &cameras_2d {
if !camera.is_active {
continue;
}
transparent_2d_phases.insert_or_clear(entity);
opaque_2d_phases.insert_or_clear(entity, GpuPreprocessingMode::None);
alpha_mask_2d_phases.insert_or_clear(entity, GpuPreprocessingMode::None);

live_entities.insert(entity);
// This is the main 2D camera, so we use the first subview index (0).
let retained_view_entity = RetainedViewEntity::new(main_entity.into(), 0);

transparent_2d_phases.insert_or_clear(retained_view_entity);
opaque_2d_phases.insert_or_clear(retained_view_entity, GpuPreprocessingMode::None);
alpha_mask_2d_phases.insert_or_clear(retained_view_entity, GpuPreprocessingMode::None);

live_entities.insert(retained_view_entity);
}

// Clear out all dead views.
Expand All @@ -421,11 +427,13 @@ pub fn prepare_core_2d_depth_textures(
render_device: Res<RenderDevice>,
transparent_2d_phases: Res<ViewSortedRenderPhases<Transparent2d>>,
opaque_2d_phases: Res<ViewBinnedRenderPhases<Opaque2d>>,
views_2d: Query<(Entity, &ExtractedCamera, &Msaa), (With<Camera2d>,)>,
views_2d: Query<(Entity, &ExtractedCamera, &ExtractedView, &Msaa), (With<Camera2d>,)>,
) {
let mut textures = <HashMap<_, _>>::default();
for (view, camera, msaa) in &views_2d {
if !opaque_2d_phases.contains_key(&view) || !transparent_2d_phases.contains_key(&view) {
for (view, camera, extracted_view, msaa) in &views_2d {
if !opaque_2d_phases.contains_key(&extracted_view.retained_view_entity)
|| !transparent_2d_phases.contains_key(&extracted_view.retained_view_entity)
{
continue;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ use crate::{
core_3d::Opaque3d,
skybox::{SkyboxBindGroup, SkyboxPipelineId},
};
use bevy_ecs::{entity::Entity, prelude::World, query::QueryItem};
use bevy_ecs::{prelude::World, query::QueryItem};
use bevy_render::{
camera::ExtractedCamera,
diagnostic::RecordDiagnostics,
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_phase::{TrackedRenderPass, ViewBinnedRenderPhases},
render_resource::{CommandEncoderDescriptor, PipelineCache, RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget, ViewUniformOffset},
view::{ExtractedView, ViewDepthTexture, ViewTarget, ViewUniformOffset},
};
use bevy_utils::tracing::error;
#[cfg(feature = "trace")]
Expand All @@ -24,8 +24,8 @@ use super::AlphaMask3d;
pub struct MainOpaquePass3dNode;
impl ViewNode for MainOpaquePass3dNode {
type ViewQuery = (
Entity,
&'static ExtractedCamera,
&'static ExtractedView,
&'static ViewTarget,
&'static ViewDepthTexture,
Option<&'static SkyboxPipelineId>,
Expand All @@ -38,8 +38,8 @@ impl ViewNode for MainOpaquePass3dNode {
graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>,
(
view,
camera,
extracted_view,
target,
depth,
skybox_pipeline,
Expand All @@ -55,9 +55,10 @@ impl ViewNode for MainOpaquePass3dNode {
return Ok(());
};

let (Some(opaque_phase), Some(alpha_mask_phase)) =
(opaque_phases.get(&view), alpha_mask_phases.get(&view))
else {
let (Some(opaque_phase), Some(alpha_mask_phase)) = (
opaque_phases.get(&extracted_view.retained_view_entity),
alpha_mask_phases.get(&extracted_view.retained_view_entity),
) else {
return Ok(());
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy_render::{
render_phase::ViewSortedRenderPhases,
render_resource::{Extent3d, RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget},
view::{ExtractedView, ViewDepthTexture, ViewTarget},
};
use bevy_utils::tracing::error;
#[cfg(feature = "trace")]
Expand All @@ -22,6 +22,7 @@ pub struct MainTransmissivePass3dNode;
impl ViewNode for MainTransmissivePass3dNode {
type ViewQuery = (
&'static ExtractedCamera,
&'static ExtractedView,
&'static Camera3d,
&'static ViewTarget,
Option<&'static ViewTransmissionTexture>,
Expand All @@ -32,7 +33,7 @@ impl ViewNode for MainTransmissivePass3dNode {
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
(camera, camera_3d, target, transmission, depth): QueryItem<Self::ViewQuery>,
(camera, view, camera_3d, target, transmission, depth): QueryItem<Self::ViewQuery>,
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.view_entity();
Expand All @@ -43,7 +44,7 @@ impl ViewNode for MainTransmissivePass3dNode {
return Ok(());
};

let Some(transmissive_phase) = transmissive_phases.get(&view_entity) else {
let Some(transmissive_phase) = transmissive_phases.get(&view.retained_view_entity) else {
return Ok(());
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy_render::{
render_phase::ViewSortedRenderPhases,
render_resource::{RenderPassDescriptor, StoreOp},
renderer::RenderContext,
view::{ViewDepthTexture, ViewTarget},
view::{ExtractedView, ViewDepthTexture, ViewTarget},
};
use bevy_utils::tracing::error;
#[cfg(feature = "trace")]
Expand All @@ -21,14 +21,15 @@ pub struct MainTransparentPass3dNode;
impl ViewNode for MainTransparentPass3dNode {
type ViewQuery = (
&'static ExtractedCamera,
&'static ExtractedView,
&'static ViewTarget,
&'static ViewDepthTexture,
);
fn run(
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
(camera, target, depth): QueryItem<Self::ViewQuery>,
(camera, view, target, depth): QueryItem<Self::ViewQuery>,
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.view_entity();
Expand All @@ -39,7 +40,7 @@ impl ViewNode for MainTransparentPass3dNode {
return Ok(());
};

let Some(transparent_phase) = transparent_phases.get(&view_entity) else {
let Some(transparent_phase) = transparent_phases.get(&view.retained_view_entity) else {
return Ok(());
};

Expand Down
Loading

0 comments on commit e4b5efa

Please sign in to comment.