1010//!
1111//! Per-view cluster buffers are each view's own independent storage so that views cannot stomp
1212//! one another's clustered light lists under single-submit semantics. Per-view state is keyed by
13- //! [`OcclusionViewId `] and created lazily on first use; retired explicitly when a secondary RT
13+ //! [`ViewId `] and created lazily on first use; retired explicitly when a secondary RT
1414//! camera is destroyed.
1515//!
1616//! Per-draw resources follow the same ownership model: one grow-on-demand slab per
17- //! [`OcclusionViewId `], created lazily so no view can exhaust another view's per-draw capacity.
17+ //! [`ViewId `], created lazily so no view can exhaust another view's per-draw capacity.
1818
1919use std:: sync:: atomic:: { AtomicBool , Ordering } ;
2020use std:: sync:: Arc ;
@@ -25,7 +25,7 @@ use parking_lot::Mutex;
2525use crate :: backend:: cluster_gpu:: { ClusterBufferRefs , CLUSTER_PARAMS_UNIFORM_SIZE } ;
2626use crate :: gpu:: frame_globals:: { FrameGpuUniforms , SkyboxSpecularUniformParams } ;
2727use crate :: gpu:: GpuLimits ;
28- use crate :: render_graph:: OcclusionViewId ;
28+ use crate :: render_graph:: ViewId ;
2929
3030use super :: frame_gpu:: {
3131 EmptyMaterialBindGroup , FrameGpuResources , PerViewSceneSnapshotSyncParams ,
@@ -163,12 +163,12 @@ pub struct FrameResourceManager {
163163 pub ( crate ) empty_material : Option < EmptyMaterialBindGroup > ,
164164 /// Per-view cluster buffers, frame uniform buffer, and `@group(0)` bind group.
165165 ///
166- /// Created lazily on first use per [`OcclusionViewId `]; retired when a secondary RT camera
166+ /// Created lazily on first use per [`ViewId `]; retired when a secondary RT camera
167167 /// is destroyed via [`Self::retire_per_view_frame`].
168168 per_view_frame : PerViewResourceMap < PerViewFrameState > ,
169169 /// One grow-on-demand per-draw slab per stable render-view identity.
170170 ///
171- /// Created lazily; keyed by [`OcclusionViewId `] so secondary RT cameras never compete
171+ /// Created lazily; keyed by [`ViewId `] so secondary RT cameras never compete
172172 /// with the main view (or each other) for buffer space.
173173 per_view_draw : PerViewResourceMap < Mutex < PerDrawResources > > ,
174174 /// Shared `@group(2)` bind group layout, reflected once at attach time.
@@ -347,7 +347,7 @@ impl FrameResourceManager {
347347 /// when cluster buffers cannot be allocated for the given viewport.
348348 pub fn per_view_frame_or_create (
349349 & mut self ,
350- view_id : OcclusionViewId ,
350+ view_id : ViewId ,
351351 device : & wgpu:: Device ,
352352 layout : PreRecordViewResourceLayout ,
353353 ) -> Option < & mut PerViewFrameState > {
@@ -470,26 +470,31 @@ impl FrameResourceManager {
470470 }
471471
472472 /// Returns the per-view frame state for `view_id`, or `None` if not yet created.
473- pub fn per_view_frame ( & self , view_id : OcclusionViewId ) -> Option < & PerViewFrameState > {
473+ pub fn per_view_frame ( & self , view_id : ViewId ) -> Option < & PerViewFrameState > {
474474 self . per_view_frame . get ( view_id)
475475 }
476476
477477 /// Frees per-view cluster buffers and bind group for a view that is no longer active.
478478 ///
479479 /// Call alongside [`Self::retire_per_view_per_draw`] when a secondary RT camera is destroyed.
480480 /// Has no effect if the view was never allocated.
481- pub fn retire_per_view_frame ( & mut self , view_id : OcclusionViewId ) {
481+ pub fn retire_per_view_frame ( & mut self , view_id : ViewId ) {
482482 if self . per_view_frame . retire ( view_id) {
483483 logger:: debug!( "per-view frame state: retired for view {view_id:?}" ) ;
484484 }
485485 }
486486
487+ /// Number of live per-view frame-state entries.
488+ pub fn per_view_frame_count ( & self ) -> usize {
489+ self . per_view_frame . len ( )
490+ }
491+
487492 /// Returns the per-draw slab for the given view, creating it if it does not yet exist.
488493 ///
489494 /// Returns `None` when the manager has not been attached (no device limits / layout available).
490495 pub fn per_view_per_draw_or_create (
491496 & mut self ,
492- view_id : OcclusionViewId ,
497+ view_id : ViewId ,
493498 device : & wgpu:: Device ,
494499 ) -> Option < & Mutex < PerDrawResources > > {
495500 profiling:: scope!( "render::ensure_per_view_per_draw" ) ;
@@ -503,26 +508,31 @@ impl FrameResourceManager {
503508 }
504509
505510 /// Returns the per-draw slab for the given view, or `None` if it has not been created yet.
506- pub fn per_view_per_draw ( & self , view_id : OcclusionViewId ) -> Option < & Mutex < PerDrawResources > > {
511+ pub fn per_view_per_draw ( & self , view_id : ViewId ) -> Option < & Mutex < PerDrawResources > > {
507512 self . per_view_draw . get ( view_id)
508513 }
509514
510515 /// Frees the per-draw slab for a view that is no longer active (e.g. render-texture camera destroyed).
511516 ///
512517 /// Has no effect if the view was never allocated.
513- pub fn retire_per_view_per_draw ( & mut self , view_id : OcclusionViewId ) {
518+ pub fn retire_per_view_per_draw ( & mut self , view_id : ViewId ) {
514519 if self . per_view_draw . retire ( view_id) {
515520 logger:: debug!( "per-draw slab: retired slab for view {view_id:?}" ) ;
516521 }
517522 }
518523
524+ /// Number of live per-view per-draw slabs.
525+ pub fn per_view_per_draw_count ( & self ) -> usize {
526+ self . per_view_draw . len ( )
527+ }
528+
519529 /// Returns the per-view scratch slot used for per-draw uniform packing, creating it on first use.
520530 ///
521- /// Keyed per [`OcclusionViewId `] so parallel per-view recording cannot alias the same scratch
531+ /// Keyed per [`ViewId `] so parallel per-view recording cannot alias the same scratch
522532 /// across rayon workers.
523533 pub fn per_view_per_draw_scratch_or_create (
524534 & mut self ,
525- view_id : OcclusionViewId ,
535+ view_id : ViewId ,
526536 ) -> & Mutex < PerViewPerDrawScratch > {
527537 profiling:: scope!( "render::ensure_per_view_per_draw_scratch" ) ;
528538 self . per_view_per_draw_scratch
@@ -535,7 +545,7 @@ impl FrameResourceManager {
535545 /// Returns the per-view scratch slot, or `None` if it has not been created yet.
536546 pub fn per_view_per_draw_scratch (
537547 & self ,
538- view_id : OcclusionViewId ,
548+ view_id : ViewId ,
539549 ) -> Option < & Mutex < PerViewPerDrawScratch > > {
540550 self . per_view_per_draw_scratch . get ( view_id)
541551 }
@@ -544,12 +554,24 @@ impl FrameResourceManager {
544554 ///
545555 /// Call alongside [`Self::retire_per_view_per_draw`] and [`Self::retire_per_view_frame`] when a
546556 /// secondary RT camera is destroyed. Has no effect if the view was never allocated.
547- pub fn retire_per_view_per_draw_scratch ( & mut self , view_id : OcclusionViewId ) {
557+ pub fn retire_per_view_per_draw_scratch ( & mut self , view_id : ViewId ) {
548558 if self . per_view_per_draw_scratch . retire ( view_id) {
549559 logger:: debug!( "per-draw slab scratch: retired for view {view_id:?}" ) ;
550560 }
551561 }
552562
563+ /// Number of live per-view CPU scratch slots.
564+ pub fn per_view_per_draw_scratch_count ( & self ) -> usize {
565+ self . per_view_per_draw_scratch . len ( )
566+ }
567+
568+ /// Retires all view-scoped frame resources for `view_id`.
569+ pub fn retire_view ( & mut self , view_id : ViewId ) {
570+ self . retire_per_view_frame ( view_id) ;
571+ self . retire_per_view_per_draw ( view_id) ;
572+ self . retire_per_view_per_draw_scratch ( view_id) ;
573+ }
574+
553575 /// Fills the light scratch buffer from [`SceneCoordinator`] (active render spaces only,
554576 /// clustered ordering, capped at [`super::MAX_LIGHTS`]).
555577 ///
@@ -690,7 +712,7 @@ impl FrameResourceManager {
690712 /// The snapshot must already have been provisioned by [`Self::per_view_frame_or_create`].
691713 pub fn copy_scene_depth_snapshot_for_view (
692714 & self ,
693- view_id : OcclusionViewId ,
715+ view_id : ViewId ,
694716 encoder : & mut wgpu:: CommandEncoder ,
695717 source_depth : & wgpu:: Texture ,
696718 viewport : ( u32 , u32 ) ,
@@ -709,7 +731,7 @@ impl FrameResourceManager {
709731 /// The snapshot must already have been provisioned by [`Self::per_view_frame_or_create`].
710732 pub fn copy_scene_color_snapshot_for_view (
711733 & self ,
712- view_id : OcclusionViewId ,
734+ view_id : ViewId ,
713735 encoder : & mut wgpu:: CommandEncoder ,
714736 source_color : & wgpu:: Texture ,
715737 viewport : ( u32 , u32 ) ,
@@ -770,19 +792,17 @@ mod tests {
770792 #[ test]
771793 fn new_manager_has_no_per_view_draw ( ) {
772794 let mgr = FrameResourceManager :: new ( ) ;
773- assert ! ( mgr. per_view_per_draw( OcclusionViewId :: Main ) . is_none( ) ) ;
774- assert ! ( mgr
775- . per_view_per_draw( OcclusionViewId :: OffscreenRenderTexture ( 42 ) )
776- . is_none( ) ) ;
795+ let secondary = ViewId :: secondary_camera ( RenderSpaceId ( 42 ) , 0 ) ;
796+ assert ! ( mgr. per_view_per_draw( ViewId :: Main ) . is_none( ) ) ;
797+ assert ! ( mgr. per_view_per_draw( secondary) . is_none( ) ) ;
777798 }
778799
779800 #[ test]
780801 fn new_manager_has_no_per_view_frame ( ) {
781802 let mgr = FrameResourceManager :: new ( ) ;
782- assert ! ( mgr. per_view_frame( OcclusionViewId :: Main ) . is_none( ) ) ;
783- assert ! ( mgr
784- . per_view_frame( OcclusionViewId :: OffscreenRenderTexture ( 42 ) )
785- . is_none( ) ) ;
803+ let secondary = ViewId :: secondary_camera ( RenderSpaceId ( 42 ) , 0 ) ;
804+ assert ! ( mgr. per_view_frame( ViewId :: Main ) . is_none( ) ) ;
805+ assert ! ( mgr. per_view_frame( secondary) . is_none( ) ) ;
786806 }
787807
788808 /// Shared pre-record work deduplicates only the cluster allocation shape, not snapshot needs.
@@ -831,10 +851,12 @@ mod tests {
831851 #[ test]
832852 fn retire_nonexistent_is_noop ( ) {
833853 let mut mgr = FrameResourceManager :: new ( ) ;
834- mgr. retire_per_view_per_draw ( OcclusionViewId :: Main ) ;
835- mgr. retire_per_view_per_draw ( OcclusionViewId :: OffscreenRenderTexture ( 99 ) ) ;
836- mgr. retire_per_view_frame ( OcclusionViewId :: Main ) ;
837- mgr. retire_per_view_frame ( OcclusionViewId :: OffscreenRenderTexture ( 99 ) ) ;
854+ let secondary = ViewId :: secondary_camera ( RenderSpaceId ( 99 ) , 0 ) ;
855+ mgr. retire_per_view_per_draw ( ViewId :: Main ) ;
856+ mgr. retire_per_view_per_draw ( secondary) ;
857+ mgr. retire_per_view_frame ( ViewId :: Main ) ;
858+ mgr. retire_per_view_frame ( secondary) ;
859+ mgr. retire_view ( secondary) ;
838860 }
839861
840862 fn make_light_data ( color_x : f32 ) -> LightData {
0 commit comments