22using System . Collections . Generic ;
33using System . Runtime . InteropServices ;
44using UnityEngine . Experimental . Rendering . RenderGraphModule ;
5- using static UnityEngine . Rendering . HighDefinition . VolumeGlobalUniqueIDUtils ;
65
76namespace UnityEngine . Rendering . HighDefinition
87{
@@ -122,6 +121,7 @@ public partial class HDRenderPipeline
122121 static int s_MaxMaskVolumeMaskCount ;
123122 RTHandle m_MaskVolumeAtlasSHRTHandle ;
124123
124+ List < MaskVolume . MaskVolumeAtlasKey > keysInAtlas ;
125125 Texture3DAtlasDynamic < MaskVolume . MaskVolumeAtlasKey > maskVolumeAtlas = null ;
126126
127127 bool isClearMaskVolumeAtlasRequested = false ;
@@ -207,6 +207,7 @@ internal void CreateMaskVolumeBuffers()
207207 name : "MaskVolumeAtlasSH"
208208 ) ;
209209
210+ keysInAtlas = new List < MaskVolume . MaskVolumeAtlasKey > ( ) ;
210211 maskVolumeAtlas = new Texture3DAtlasDynamic < MaskVolume . MaskVolumeAtlasKey > ( s_MaskVolumeAtlasResolution , s_MaskVolumeAtlasResolution , s_MaskVolumeAtlasResolution , k_MaxVisibleMaskVolumeCount , m_MaskVolumeAtlasSHRTHandle ) ;
211212 }
212213
@@ -221,6 +222,7 @@ internal void DestroyMaskVolumeBuffers()
221222 if ( m_MaskVolumeAtlasSHRTHandle != null )
222223 RTHandles . Release ( m_MaskVolumeAtlasSHRTHandle ) ;
223224
225+ keysInAtlas = null ;
224226 if ( maskVolumeAtlas != null )
225227 maskVolumeAtlas . Release ( ) ;
226228
@@ -332,36 +334,8 @@ private static void DoPushMaskVolumesGlobalParams(
332334 cmd . SetGlobalTexture ( HDShaderIDs . _MaskVolumeAtlasSH , maskVolumeAtlas ) ;
333335 }
334336
335- internal void ReleaseMaskVolumeFromAtlas ( MaskVolumeHandle volume )
337+ bool EnsureMaskVolumeInAtlas ( CommandBuffer immediateCmd , RenderGraph renderGraph , ref MaskVolumesResources resources , MaskVolumeHandle volume )
336338 {
337- if ( ! m_SupportMaskVolume )
338- return ;
339-
340- MaskVolume . MaskVolumeAtlasKey key = volume . ComputeMaskVolumeAtlasKey ( ) ;
341- MaskVolume . MaskVolumeAtlasKey keyPrevious = volume . GetMaskVolumeAtlasKeyPrevious ( ) ;
342-
343- if ( maskVolumeAtlas . IsTextureSlotAllocated ( key ) ) { maskVolumeAtlas . ReleaseTextureSlot ( key ) ; }
344- if ( maskVolumeAtlas . IsTextureSlotAllocated ( keyPrevious ) ) { maskVolumeAtlas . ReleaseTextureSlot ( keyPrevious ) ; }
345- }
346-
347- internal void EnsureStaleDataIsFlushedFromAtlases ( MaskVolumeHandle volume )
348- {
349- MaskVolume . MaskVolumeAtlasKey key = volume . ComputeMaskVolumeAtlasKey ( ) ;
350- MaskVolume . MaskVolumeAtlasKey keyPrevious = volume . GetMaskVolumeAtlasKeyPrevious ( ) ;
351- if ( ! key . Equals ( keyPrevious ) )
352- {
353- if ( maskVolumeAtlas . IsTextureSlotAllocated ( keyPrevious ) )
354- {
355- maskVolumeAtlas . ReleaseTextureSlot ( keyPrevious ) ;
356- }
357-
358- volume . SetMaskVolumeAtlasKeyPrevious ( key ) ;
359- }
360- }
361-
362- internal bool EnsureMaskVolumeInAtlas ( CommandBuffer immediateCmd , RenderGraph renderGraph , ref MaskVolumesResources resources , MaskVolumeHandle volume )
363- {
364- VolumeGlobalUniqueID id = volume . GetAtlasID ( ) ;
365339 var resolution = volume . GetResolution ( ) ;
366340 int size = resolution . x * resolution . y * resolution . z ;
367341 Debug . Assert ( size > 0 , "MaskVolume: Encountered mask volume with resolution set to zero on all three axes." ) ;
@@ -376,14 +350,13 @@ internal bool EnsureMaskVolumeInAtlas(CommandBuffer immediateCmd, RenderGraph re
376350
377351 if ( isSlotAllocated )
378352 {
353+ // Sync local key list with any allocated slot, no matter if we will actually upload anything to it.
354+ // Needed to identify and free the slot later when no volumes with this key is present in a frame.
355+ if ( ! keysInAtlas . Contains ( key ) )
356+ keysInAtlas . Add ( key ) ;
357+
379358 if ( isUploadNeeded || volume . IsDataUpdated ( ) )
380359 {
381- if ( ! volume . IsDataAssigned ( ) )
382- {
383- ReleaseMaskVolumeFromAtlas ( volume ) ;
384- return false ;
385- }
386-
387360 int sizeSHCoefficientsL0 = size * MaskVolumePayload . GetDataSHL0Stride ( ) ;
388361 Debug . AssertFormat ( volume . DataSHL0Length == sizeSHCoefficientsL0 , "MaskVolume: The mask volume data and its resolution are out of sync! Volume data length is {0}, but resolution * SH stride size is {1}." , volume . DataSHL0Length , sizeSHCoefficientsL0 ) ;
389362
@@ -432,14 +405,13 @@ internal bool EnsureMaskVolumeInAtlas(CommandBuffer immediateCmd, RenderGraph re
432405 }
433406
434407 return true ;
435-
436408 }
437409 return false ;
438410 }
439411
440412 if ( ! isSlotAllocated )
441413 {
442- Debug . LogWarningFormat ( "MaskVolume: Texture Atlas failed to allocate space for texture (id: {0}, width: {1}, height: {2}, depth: {3})" , id , resolution . x , resolution . y , resolution . z ) ;
414+ Debug . LogWarningFormat ( "MaskVolume: Texture Atlas failed to allocate space for texture (id: {0}, width: {1}, height: {2}, depth: {3})" , key . id , resolution . x , resolution . y , resolution . z ) ;
443415 }
444416
445417 return false ;
@@ -497,6 +469,7 @@ internal void ClearMaskVolumeAtlasIfRequested(CommandBuffer immediateCmd, Render
497469 if ( ! isClearMaskVolumeAtlasRequested ) { return ; }
498470 isClearMaskVolumeAtlasRequested = false ;
499471
472+ keysInAtlas . Clear ( ) ;
500473 maskVolumeAtlas . ResetAllocator ( ) ;
501474
502475 if ( renderGraph != null )
@@ -614,7 +587,12 @@ void PrepareVisibleMaskVolumeListBuffers(HDCamera hdCamera, CommandBuffer immedi
614587 {
615588 MaskVolumeHandle volume = volumes [ maskVolumesIndex ] ;
616589
617- var isVisible = volume . parameters . weight >= 1e-5f && volume . IsDataAssigned ( ) ;
590+ var isVisible =
591+ volume . parameters . weight >= 1e-5f &&
592+ #if UNITY_EDITOR
593+ ! volume . IsHiddenInScene ( ) &&
594+ #endif
595+ volume . IsDataAssigned ( ) ;
618596
619597 // When hdCamera is null we are preparing for some view-independent baking, so we consider all valid volumes visible.
620598 if ( isViewDependent && isVisible )
@@ -640,9 +618,27 @@ void PrepareVisibleMaskVolumeListBuffers(HDCamera hdCamera, CommandBuffer immedi
640618 var logVolume = CalculateMaskVolumeLogVolume ( volume . parameters . size ) ;
641619 m_MaskVolumeSortKeys [ sortCount ++ ] = PackMaskVolumeSortKey ( logVolume , maskVolumesIndex ) ;
642620 }
643- else
621+ }
622+
623+ for ( int keyIndex = keysInAtlas . Count - 1 ; keyIndex >= 0 ; keyIndex -- )
624+ {
625+ var key = keysInAtlas [ keyIndex ] ;
626+ var dataIsNeededInAtlas = false ;
627+ for ( int sortIndex = 0 ; sortIndex < sortCount ; sortIndex ++ )
628+ {
629+ var sortKey = m_MaskVolumeSortKeys [ sortIndex ] ;
630+ UnpackMaskVolumeSortKey ( sortKey , out var maskVolumesIndex ) ;
631+ var volumeKey = volumes [ maskVolumesIndex ] . ComputeMaskVolumeAtlasKey ( ) ;
632+ if ( volumeKey . Equals ( key ) )
633+ {
634+ dataIsNeededInAtlas = true ;
635+ break ;
636+ }
637+ }
638+ if ( ! dataIsNeededInAtlas )
644639 {
645- ReleaseMaskVolumeFromAtlas ( volume ) ;
640+ keysInAtlas . RemoveAt ( keyIndex ) ;
641+ maskVolumeAtlas . ReleaseTextureSlot ( key ) ;
646642 }
647643 }
648644
@@ -688,8 +684,6 @@ void PrepareVisibleMaskVolumeListBuffers(HDCamera hdCamera, CommandBuffer immedi
688684
689685 MaskVolumeHandle volume = volumes [ maskVolumesIndex ] ;
690686
691- EnsureStaleDataIsFlushedFromAtlases ( volume ) ;
692-
693687 if ( volumeUploadedToAtlasSHCount < volumeUploadedToAtlasCapacity )
694688 {
695689 bool volumeWasUploaded = EnsureMaskVolumeInAtlas ( immediateCmd , renderGraph , ref maskVolumes . resources , volume ) ;
0 commit comments