@@ -322,6 +322,85 @@ public override int GetHashCode()
322322 }
323323 #endregion
324324
325+ class RenderGraphTexturePool
326+ {
327+ // Dictionary tracks resources by hash and stores resources with same hash in a List (list instead of a stack because we need to be able to remove stale allocations).
328+ Dictionary < int , List < ( RTHandle resource , int frameIndex ) > > m_ResourcePool = new Dictionary < int , List < ( RTHandle resource , int frameIndex ) > > ( ) ;
329+ static int s_CurrentFrameIndex ;
330+
331+ public void ReleaseResource ( int hash , RTHandle rt , int currentFrameIndex )
332+ {
333+ if ( ! m_ResourcePool . TryGetValue ( hash , out var list ) )
334+ {
335+ list = new List < ( RTHandle rt , int frameIndex ) > ( ) ;
336+ m_ResourcePool . Add ( hash , list ) ;
337+ }
338+
339+ list . Add ( ( rt , currentFrameIndex ) ) ;
340+ }
341+
342+ public bool TryGetResource ( int hashCode , out RTHandle rt )
343+ {
344+ if ( m_ResourcePool . TryGetValue ( hashCode , out var list ) && list . Count > 0 )
345+ {
346+ rt = list [ list . Count - 1 ] . resource ;
347+ list . RemoveAt ( list . Count - 1 ) ; // O(1) since it's the last element.
348+ return true ;
349+ }
350+
351+ rt = null ;
352+ return false ;
353+ }
354+
355+ public void PurgeUnusedResources ( int currentFrameIndex )
356+ {
357+ // Update the frame index for the lambda. Static because we don't want to capture.
358+ s_CurrentFrameIndex = currentFrameIndex ;
359+
360+ foreach ( var kvp in m_ResourcePool )
361+ {
362+ var list = kvp . Value ;
363+ list . RemoveAll ( obj =>
364+ {
365+ if ( obj . frameIndex < s_CurrentFrameIndex )
366+ {
367+ obj . resource . Release ( ) ;
368+ return true ;
369+ }
370+ return false ;
371+ } ) ;
372+ }
373+ }
374+
375+ public void Cleanup ( )
376+ {
377+ foreach ( var kvp in m_ResourcePool )
378+ {
379+ foreach ( var res in kvp . Value )
380+ {
381+ res . resource . Release ( ) ;
382+ }
383+ }
384+ }
385+
386+ public void LogResources ( RenderGraphLogger logger )
387+ {
388+ List < string > allocationList = new List < string > ( ) ;
389+ foreach ( var kvp in m_ResourcePool )
390+ {
391+ foreach ( var res in kvp . Value )
392+ {
393+ allocationList . Add ( res . resource . rt . name ) ;
394+ }
395+ }
396+
397+ allocationList . Sort ( ) ;
398+ int index = 0 ;
399+ foreach ( var element in allocationList )
400+ logger . LogLine ( "[{0}] {1}" , index ++ , element ) ;
401+ }
402+ }
403+
325404 /// <summary>
326405 /// The RenderGraphResourceRegistry holds all resource allocated during Render Graph execution.
327406 /// </summary>
@@ -393,17 +472,19 @@ internal ComputeBufferResource(ComputeBuffer computeBuffer, bool imported)
393472 #endregion
394473
395474 DynamicArray < TextureResource > m_TextureResources = new DynamicArray < TextureResource > ( ) ;
396- Dictionary < int , Stack < RTHandle > > m_TexturePool = new Dictionary < int , Stack < RTHandle > > ( ) ;
475+ RenderGraphTexturePool m_TexturePool = new RenderGraphTexturePool ( ) ;
397476 DynamicArray < RendererListResource > m_RendererListResources = new DynamicArray < RendererListResource > ( ) ;
398477 DynamicArray < ComputeBufferResource > m_ComputeBufferResources = new DynamicArray < ComputeBufferResource > ( ) ;
399478 RTHandleSystem m_RTHandleSystem = new RTHandleSystem ( ) ;
400479 RenderGraphDebugParams m_RenderGraphDebug ;
401480 RenderGraphLogger m_Logger ;
481+ int m_CurrentFrameIndex ;
402482
403483 RTHandle m_CurrentBackbuffer ;
404484
405485 // Diagnostic only
406- List < ( int , RTHandle ) > m_AllocatedTextures = new List < ( int , RTHandle ) > ( ) ;
486+ // This list allows us to determine if all textures were correctly released in the frame.
487+ List < ( int , RTHandle ) > m_FrameAllocatedTextures = new List < ( int , RTHandle ) > ( ) ;
407488
408489 #region Public Interface
409490 /// <summary>
@@ -470,8 +551,10 @@ internal RenderGraphResourceRegistry(bool supportMSAA, MSAASamples initialSample
470551 m_Logger = logger ;
471552 }
472553
473- internal void SetRTHandleReferenceSize ( int width , int height , MSAASamples msaaSamples )
554+ internal void BeginRender ( int width , int height , MSAASamples msaaSamples , int currentFrameIndex )
474555 {
556+ m_CurrentFrameIndex = currentFrameIndex ;
557+ // Update RTHandleSystem with size for this rendering pass.
475558 m_RTHandleSystem . SetReferenceSize ( width , height , msaaSamples ) ;
476559 }
477560
@@ -618,7 +701,7 @@ void CreateTextureForPass(ref TextureResource resource)
618701#if DEVELOPMENT_BUILD || UNITY_EDITOR
619702 if ( hashCode != - 1 )
620703 {
621- m_AllocatedTextures . Add ( ( hashCode , resource . rt ) ) ;
704+ m_FrameAllocatedTextures . Add ( ( hashCode , resource . rt ) ) ;
622705 }
623706#endif
624707
@@ -675,16 +758,10 @@ internal void ReleaseTexture(RenderGraphContext rgContext, TextureHandle resourc
675758
676759 void ReleaseTextureResource ( int hash , RTHandle rt )
677760 {
678- if ( ! m_TexturePool . TryGetValue ( hash , out var stack ) )
679- {
680- stack = new Stack < RTHandle > ( ) ;
681- m_TexturePool . Add ( hash , stack ) ;
682- }
683-
684- stack . Push ( rt ) ;
761+ m_TexturePool . ReleaseResource ( hash , rt , m_CurrentFrameIndex ) ;
685762
686763#if DEVELOPMENT_BUILD || UNITY_EDITOR
687- m_AllocatedTextures . Remove ( ( hash , rt ) ) ;
764+ m_FrameAllocatedTextures . Remove ( ( hash , rt ) ) ;
688765#endif
689766 }
690767
@@ -746,14 +823,7 @@ void ValidateRendererListDesc(in RendererListDesc desc)
746823
747824 bool TryGetRenderTarget ( int hashCode , out RTHandle rt )
748825 {
749- if ( m_TexturePool . TryGetValue ( hashCode , out var stack ) && stack . Count > 0 )
750- {
751- rt = stack . Pop ( ) ;
752- return true ;
753- }
754-
755- rt = null ;
756- return false ;
826+ return m_TexturePool . TryGetResource ( hashCode , out rt ) ;
757827 }
758828
759829 internal void CreateRendererLists ( List < RendererListHandle > rendererLists )
@@ -778,11 +848,11 @@ internal void Clear(bool onException)
778848 m_ComputeBufferResources . Clear ( ) ;
779849
780850#if DEVELOPMENT_BUILD || UNITY_EDITOR
781- if ( m_AllocatedTextures . Count != 0 && ! onException )
851+ if ( m_FrameAllocatedTextures . Count != 0 && ! onException )
782852 {
783- string logMessage = "RenderGraph: Not all textures were released." ;
853+ string logMessage = "RenderGraph: Not all textures were released. This can be caused by a textures being allocated but never read by any pass. " ;
784854
785- List < ( int , RTHandle ) > tempList = new List < ( int , RTHandle ) > ( m_AllocatedTextures ) ;
855+ List < ( int , RTHandle ) > tempList = new List < ( int , RTHandle ) > ( m_FrameAllocatedTextures ) ;
786856 foreach ( var value in tempList )
787857 {
788858 logMessage = $ "{ logMessage } \n \t { value . Item2 . name } ";
@@ -792,10 +862,15 @@ internal void Clear(bool onException)
792862 Debug . LogWarning ( logMessage ) ;
793863 }
794864
795- // If an error occurred during execution, it's expected that textures are not all release so we clear the trakcing list.
865+ // If an error occurred during execution, it's expected that textures are not all released so we clear the tracking list.
796866 if ( onException )
797- m_AllocatedTextures . Clear ( ) ;
867+ m_FrameAllocatedTextures . Clear ( ) ;
798868#endif
869+
870+ // TODO RENDERGRAPH: Might not be ideal to purge stale resources every frame.
871+ // In case users enable/disable features along a level it might provoke performance spikes when things are reallocated...
872+ // Will be much better when we have actual resource aliasing and we can manage memory more efficiently.
873+ m_TexturePool . PurgeUnusedResources ( m_CurrentFrameIndex ) ;
799874 }
800875
801876 internal void ResetRTHandleReferenceSize ( int width , int height )
@@ -805,13 +880,7 @@ internal void ResetRTHandleReferenceSize(int width, int height)
805880
806881 internal void Cleanup ( )
807882 {
808- foreach ( var value in m_TexturePool )
809- {
810- foreach ( var rt in value . Value )
811- {
812- m_RTHandleSystem . Release ( rt ) ;
813- }
814- }
883+ m_TexturePool . Cleanup ( ) ;
815884 }
816885
817886 void LogTextureCreation ( RTHandle rt , bool cleared )
@@ -836,19 +905,7 @@ void LogResources()
836905 {
837906 m_Logger . LogLine ( "==== Allocated Resources ====\n " ) ;
838907
839- List < string > allocationList = new List < string > ( ) ;
840- foreach ( var stack in m_TexturePool )
841- {
842- foreach ( var rt in stack . Value )
843- {
844- allocationList . Add ( rt . rt . name ) ;
845- }
846- }
847-
848- allocationList . Sort ( ) ;
849- int index = 0 ;
850- foreach ( var element in allocationList )
851- m_Logger . LogLine ( "[{0}] {1}" , index ++ , element ) ;
908+ m_TexturePool . LogResources ( m_Logger ) ;
852909 }
853910 }
854911
0 commit comments