@@ -475,58 +475,59 @@ void CullUnusedRenderGraphPasses()
475475 return ;
476476
477477 // Must come first
478- // TODO make another subfunction CullRenderGraphPassesWithNoSideEffect() for this first step of the culling stage
479- var ctx = contextData ;
478+ CullRenderGraphPassesWithNoSideEffect ( ) ;
480479
481- // Cull all passes first
482- ctx . CullAllPasses ( true ) ;
483-
484- // Flood fill downstream algorithm using BFS,
485- // starting from the passes with side effects (writting to imported texture, not allowed to be culled, globals modification...)
486- // to all their dependencies
487- while ( m_HasSideEffectPassIdCullingStack . Count != 0 )
488- {
489- int passId = m_HasSideEffectPassIdCullingStack . Pop ( ) ;
480+ // Second step of the algorithm that comes later
481+ CullRenderGraphPassesWritingOnlyUnusedResources ( ) ;
482+ }
483+ }
490484
491- ref var passData = ref ctx . passData . ElementAt ( passId ) ;
485+ void CullRenderGraphPassesWithNoSideEffect ( )
486+ {
487+ var ctx = contextData ;
492488
493- // We already found this node through another dependency chain
494- if ( ! passData . culled ) continue ;
489+ // Cull all passes first
490+ ctx . CullAllPasses ( true ) ;
495491
496- // Flow upstream from this node
497- foreach ( ref readonly var input in passData . Inputs ( ctx ) )
498- {
499- ref var inputVersionedDataRes = ref ctx . resources [ input . resource ] ;
492+ // Flood fill downstream algorithm using BFS,
493+ // starting from the passes with side effects (writting to imported texture, not allowed to be culled, globals modification...)
494+ // to all their dependencies
495+ while ( m_HasSideEffectPassIdCullingStack . Count != 0 )
496+ {
497+ int passId = m_HasSideEffectPassIdCullingStack . Pop ( ) ;
500498
501- if ( inputVersionedDataRes . written )
502- {
503- m_HasSideEffectPassIdCullingStack . Push ( inputVersionedDataRes . writePassId ) ;
504- }
505- }
499+ ref var passData = ref ctx . passData . ElementAt ( passId ) ;
506500
507- // We need this node, don't cull it
508- passData . culled = false ;
509- }
501+ // We already found this node through another dependency chain
502+ if ( ! passData . culled ) continue ;
510503
511- // Update graph based on freshly culled nodes, remove any connection to them
512- // We start from the latest passes to the first ones as we might need to decrement the version number of unwritten resources
513- var numPasses = ctx . passData . Length ;
514- for ( int passIndex = numPasses - 1 ; passIndex >= 0 ; passIndex -- )
504+ // Flow upstream from this node
505+ foreach ( ref readonly var input in passData . Inputs ( ctx ) )
515506 {
516- ref readonly var pass = ref ctx . passData . ElementAt ( passIndex ) ;
507+ ref var inputVersionedDataRes = ref ctx . resources [ input . resource ] ;
517508
518- // Remove the connections from the list so they won't be visited again
519- if ( pass . culled )
509+ if ( inputVersionedDataRes . written )
520510 {
521- pass . DisconnectFromResources ( ctx ) ;
511+ m_HasSideEffectPassIdCullingStack . Push ( inputVersionedDataRes . writePassId ) ;
522512 }
523513 }
524514
525- // Second step of the algorithm, must come after
526- // TODO: The resources culling step is currently disabled due to an issue: https://jira.unity3d.com/projects/SRP/issues/SRP-897
527- // Renabled the resource culling step after addressing the depth attachment problem above.
528- // Renabled the relevent tests
529- // CullRenderGraphPassesWritingOnlyUnusedResources();
515+ // We need this node, don't cull it
516+ passData . culled = false ;
517+ }
518+
519+ // Update graph based on freshly culled nodes, remove any connection to them
520+ // We start from the latest passes to the first ones as we might need to decrement the version number of unwritten resources
521+ var numPasses = ctx . passData . Length ;
522+ for ( int passIndex = numPasses - 1 ; passIndex >= 0 ; passIndex -- )
523+ {
524+ ref readonly var pass = ref ctx . passData . ElementAt ( passIndex ) ;
525+
526+ // Remove the connections from the list so they won't be visited again
527+ if ( pass . culled )
528+ {
529+ pass . DisconnectFromResources ( ctx ) ;
530+ }
530531 }
531532 }
532533
@@ -581,24 +582,25 @@ void CullRenderGraphPassesWritingOnlyUnusedResources()
581582 producerData . culled = true ;
582583 producerData . DisconnectFromResources ( ctx , unusedVersionedResourceIdCullingStack , type ) ;
583584 }
584- else // Producer is (still) necessary, but we might need to remove the read of the previous version coming implicitly with the write of the current version
585+ else
585586 {
587+ // Producer is still necessary for now, but if the previous version is only implicitly read by it to write the unused resource
588+ // then we can consider this version useless as well and add it to the stack.
589+ // We purposefully keep the connection between the producer and this resource nevertheless to ensure proper lifetime handling and attachment setup.
590+ // A more optimal approach memory-wise would be to cut the dependency, decrease the latestVersionNumber of the resource and release it earlier
591+ // but we then need to create a transient resource with the right attachment properties and attach it to the non-culled producer or the native render pass setup will be incorrect.
592+
586593 // We always add written resource to the stack so versionedIndex > 0
587594 var prevVersionedRes = new ResourceHandle ( unusedResource , unusedResource . version - 1 ) ;
588595
589- // If no explicit read is requested by the user (AccessFlag.Write only), we need to remove the implicit read
590- // so that we cut cleanly the connection between previous version of the resource and current producer
591596 bool isImplicitRead = graph . m_RenderPasses [ producerData . passId ] . implicitReadsList . Contains ( prevVersionedRes ) ;
592597
593598 if ( isImplicitRead )
594599 {
595600 ref var prevVersionedDataRes = ref ctx . resources [ prevVersionedRes ] ;
596601
597- // Notify the previous version of this resource that it is not read anymore by this pass
598- prevVersionedDataRes . RemoveReadingPass ( ctx , prevVersionedRes , producerData . passId ) ;
599-
600- // We also need to add the previous version of the resource to the stack IF no other pass than current producer needed it
601- if ( prevVersionedDataRes . written && prevVersionedDataRes . numReaders == 0 )
602+ // We add the previous version of the resource to the stack IF no other pass than current producer needs it
603+ if ( prevVersionedDataRes . written && prevVersionedDataRes . numReaders == 1 )
602604 {
603605 unusedVersionedResourceIdCullingStack . Push ( prevVersionedRes ) ;
604606 }
0 commit comments