2023-11-07 18:20:01 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "LandscapeTextureStreamingManager.h"
# include "Engine/Texture.h"
2023-11-10 13:11:12 -05:00
# include "TextureCompiler.h"
2024-07-26 13:14:54 -04:00
# include "LandscapePrivate.h"
2023-11-07 18:20:01 -05:00
namespace UE : : Landscape
{
// double check that a texture is forced resident
static inline void EnsureTextureForcedResident ( UTexture * Texture )
{
// if other systems mess with this flag, then restore it to what it should be
// Any code that is directly messing with the flag on one of our
// landscape related textures should go through this streaming system instead
if ( ! ensure ( Texture - > bForceMiplevelsToBeResident ) )
{
Texture - > bForceMiplevelsToBeResident = true ;
}
}
}
2024-07-26 13:14:54 -04:00
TArray < FLandscapeTextureStreamingManager * > FLandscapeTextureStreamingManager : : AllStreamingManagers ;
2023-11-07 18:20:01 -05:00
bool FLandscapeTextureStreamingManager : : RequestTextureFullyStreamedIn ( UTexture * Texture , bool bWaitForStreaming )
{
TWeakObjectPtr < UTexture > TexturePtr = Texture ;
FTextureState & State = TextureStates . FindOrAdd ( TexturePtr ) ;
if ( State . RequestCount = = 0 )
{
Texture - > bForceMiplevelsToBeResident = true ;
}
else
{
UE : : Landscape : : EnsureTextureForcedResident ( Texture ) ;
}
State . RequestCount + + ;
if ( IsTextureFullyStreamedIn ( Texture ) )
{
return true ;
}
else if ( bWaitForStreaming )
{
Texture - > WaitForStreaming ( ) ;
return IsTextureFullyStreamedIn ( Texture ) ;
}
return false ;
}
bool FLandscapeTextureStreamingManager : : RequestTextureFullyStreamedInForever ( UTexture * Texture , bool bWaitForStreaming )
{
TWeakObjectPtr < UTexture > TexturePtr = Texture ;
FTextureState & State = TextureStates . FindOrAdd ( TexturePtr ) ;
State . bForever = true ;
Texture - > bForceMiplevelsToBeResident = true ;
if ( IsTextureFullyStreamedIn ( Texture ) )
{
return true ;
}
else if ( bWaitForStreaming )
{
Texture - > WaitForStreaming ( ) ;
return IsTextureFullyStreamedIn ( Texture ) ;
}
return false ;
}
void FLandscapeTextureStreamingManager : : UnrequestTextureFullyStreamedIn ( UTexture * Texture )
{
if ( Texture = = nullptr )
{
return ;
}
TWeakObjectPtr < UTexture > TexturePtr = Texture ;
FTextureState * State = TextureStates . Find ( TexturePtr ) ;
if ( State )
{
if ( State - > RequestCount > 0 )
{
State - > RequestCount - - ;
2024-07-26 13:14:54 -04:00
if ( ! State - > WantsTextureStreamedIn ( ) )
2023-11-07 18:20:01 -05:00
{
2024-07-26 13:14:54 -04:00
// remove state tracking for this texture
2023-11-07 18:20:01 -05:00
TextureStates . Remove ( TexturePtr ) ;
2024-07-26 13:14:54 -04:00
if ( ( AllStreamingManagers . Num ( ) = = 1 ) | | ! AnyStreamingManagerWantsTextureStreamedIn ( TexturePtr ) )
{
// allow stream out
Texture - > bForceMiplevelsToBeResident = false ;
}
else
{
UE : : Landscape : : EnsureTextureForcedResident ( Texture ) ;
}
2023-11-07 18:20:01 -05:00
}
else
{
UE : : Landscape : : EnsureTextureForcedResident ( Texture ) ;
}
}
else
{
2024-07-26 13:14:54 -04:00
UE_LOG ( LogLandscape , Warning , TEXT ( " Texture Streaming Manager received more Unrequests than Requests to stream texture %s " ) , * Texture - > GetName ( ) ) ;
2023-11-07 18:20:01 -05:00
}
}
}
bool FLandscapeTextureStreamingManager : : WaitForTextureStreaming ( )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( LandscapeTextureStreamingaAnager_WaitForTextureStreaming ) ;
bool bFullyStreamed = true ;
for ( auto It = TextureStates . CreateIterator ( ) ; It ; + + It )
{
UTexture * Texture = It . Key ( ) . Get ( ) ;
if ( Texture )
{
UE : : Landscape : : EnsureTextureForcedResident ( Texture ) ;
2023-11-10 13:11:12 -05:00
if ( ! IsTextureFullyStreamedIn ( Texture ) )
2023-11-07 18:20:01 -05:00
{
2023-11-10 13:11:12 -05:00
# if WITH_EDITOR
// in editor, textures can be not compiled yet
FTextureCompilingManager : : Get ( ) . FinishCompilation ( { Texture } ) ;
# endif // WITH_EDITOR
2023-11-07 18:20:01 -05:00
Texture - > WaitForStreaming ( ) ;
}
2023-11-10 13:11:12 -05:00
bFullyStreamed = bFullyStreamed & & IsTextureFullyStreamedIn ( Texture ) ;
2023-11-07 18:20:01 -05:00
}
else
{
// the texture was unloaded... we can remove this entry
It . RemoveCurrent ( ) ;
}
}
return bFullyStreamed ;
}
2024-06-05 16:51:42 -04:00
void FLandscapeTextureStreamingManager : : CleanupPostGarbageCollect ( )
2023-11-07 18:20:01 -05:00
{
for ( auto It = TextureStates . CreateIterator ( ) ; It ; + + It )
{
2024-06-05 16:51:42 -04:00
UTexture * Texture = It . Key ( ) . Get ( ) ;
if ( Texture = = nullptr )
2023-11-07 18:20:01 -05:00
{
It . RemoveCurrent ( ) ;
}
2024-06-05 16:51:42 -04:00
else
{
// reset the texture force resident after garbage collection (which clears it sometimes)
FTextureState & State = It . Value ( ) ;
2024-07-26 13:14:54 -04:00
if ( State . WantsTextureStreamedIn ( ) )
2024-06-05 16:51:42 -04:00
{
Texture - > bForceMiplevelsToBeResident = true ;
}
}
2023-11-07 18:20:01 -05:00
}
}
2024-01-26 12:05:47 -05:00
void FLandscapeTextureStreamingManager : : CheckRequestedTextures ( )
{
# if WITH_EDITOR
if ( UndoDetector . bUndoRedoPerformed )
{
// the force mip levels resident flag sometimes gets cleared on an undo after landscape creation, but we can fix it
// (otherwise we may wait forever for them to become resident)
for ( auto It = TextureStates . CreateIterator ( ) ; It ; + + It )
{
if ( UTexture * Texture = It . Key ( ) . Get ( ) )
{
FTextureState & State = It . Value ( ) ;
2024-07-26 13:14:54 -04:00
if ( State . WantsTextureStreamedIn ( ) )
2024-01-26 12:05:47 -05:00
{
if ( ! Texture - > bForceMiplevelsToBeResident )
{
Texture - > bForceMiplevelsToBeResident = true ;
}
}
}
}
UndoDetector . bUndoRedoPerformed = false ;
}
# endif // WITH_EDITOR
}
2023-11-07 18:20:01 -05:00
bool FLandscapeTextureStreamingManager : : IsTextureFullyStreamedIn ( UTexture * InTexture )
{
return InTexture & &
# if WITH_EDITOR
! InTexture - > IsDefaultTexture ( ) & &
# endif // WITH_EDITOR
! InTexture - > HasPendingInitOrStreaming ( ) & & InTexture - > IsFullyStreamedIn ( ) ;
}
2024-07-26 13:14:54 -04:00
bool FLandscapeTextureStreamingManager : : AnyStreamingManagerWantsTextureStreamedIn ( TWeakObjectPtr < UTexture > TexturePtr )
{
for ( FLandscapeTextureStreamingManager * Manager : AllStreamingManagers )
{
if ( FTextureState * State = Manager - > TextureStates . Find ( TexturePtr ) )
{
if ( State - > WantsTextureStreamedIn ( ) )
{
return true ;
}
}
}
return false ;
}
FLandscapeTextureStreamingManager : : FLandscapeTextureStreamingManager ( )
{
AllStreamingManagers . Add ( this ) ;
}
2023-11-07 18:20:01 -05:00
FLandscapeTextureStreamingManager : : ~ FLandscapeTextureStreamingManager ( )
{
2024-07-26 13:14:54 -04:00
AllStreamingManagers . RemoveSwap ( this , EAllowShrinking : : No ) ;
// there could be some textures still requested, if they were requested "forever".
// since the world is going away, we can re-evaluate whether they should remain streamed or not.
int32 RemainingRequests = 0 ;
for ( auto It = TextureStates . CreateIterator ( ) ; It ; + + It )
2023-11-07 18:20:01 -05:00
{
2024-07-26 13:14:54 -04:00
FTextureState & State = It . Value ( ) ;
if ( State . RequestCount > 0 )
2023-11-07 18:20:01 -05:00
{
2024-07-26 13:14:54 -04:00
RemainingRequests + + ;
}
if ( UTexture * Texture = It . Key ( ) . Get ( ) )
{
if ( ! AnyStreamingManagerWantsTextureStreamedIn ( It . Key ( ) ) )
2023-11-07 18:20:01 -05:00
{
2024-07-26 13:14:54 -04:00
// none of the remaining streaming managers request this texture, we can disable the mip requests
2023-11-07 18:20:01 -05:00
Texture - > bForceMiplevelsToBeResident = false ;
}
}
}
2024-07-26 13:14:54 -04:00
if ( RemainingRequests > 0 )
{
UE_LOG ( LogLandscape , Display , TEXT ( " At destruction, the Landscape Texture Streaming Manager still has streaming requests for %d Textures, this may indicate failure to clean them up. " ) , RemainingRequests ) ;
}
2024-01-26 12:05:47 -05:00
}