2019-12-26 15:33:43 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-08-21 08:57:14 -04:00
2020-08-11 01:36:57 -04:00
# include "RuntimeVirtualTextureBuildStreamingMips.h"
2019-08-21 08:57:14 -04:00
# include "Components/RuntimeVirtualTextureComponent.h"
2020-09-01 14:07:48 -04:00
# include "ContentStreaming.h"
2019-08-21 08:57:14 -04:00
# include "Engine/TextureRenderTarget2D.h"
# include "Misc/ScopedSlowTask.h"
2019-09-22 16:27:41 -04:00
# include "RendererInterface.h"
# include "RenderTargetPool.h"
2019-08-21 09:38:23 -04:00
# include "SceneInterface.h"
2020-10-26 16:44:44 -04:00
# include "RenderGraphBuilder.h"
2019-08-21 08:57:14 -04:00
# include "VT/RuntimeVirtualTexture.h"
# include "VT/RuntimeVirtualTextureRender.h"
2020-04-15 10:23:37 -04:00
# include "VT/VirtualTextureBuilder.h"
2023-02-23 01:23:57 -05:00
# include "SceneUtils.h"
2019-08-21 08:57:14 -04:00
2019-09-22 16:27:41 -04:00
namespace
{
/** Container for render resources needed to render the runtime virtual texture. */
2020-08-11 01:36:57 -04:00
class FTileRenderResources : public FRenderResource
2019-09-22 16:27:41 -04:00
{
public :
2020-08-11 01:36:57 -04:00
FTileRenderResources ( int32 InTileSize , int32 InNumTilesX , int32 InNumTilesY , int32 InNumLayers , TArrayView < EPixelFormat > const & InLayerFormats )
2020-04-07 12:40:55 -04:00
: TileSize ( InTileSize )
, NumLayers ( InNumLayers )
, TotalSizeBytes ( 0 )
2019-09-22 16:27:41 -04:00
{
2020-04-07 12:40:55 -04:00
LayerFormats . SetNumZeroed ( InNumLayers ) ;
LayerOffsets . SetNumZeroed ( InNumLayers ) ;
for ( int32 Layer = 0 ; Layer < NumLayers ; + + Layer )
{
2024-01-10 16:32:21 -05:00
check ( InLayerFormats [ Layer ] = = PF_G16 | | InLayerFormats [ Layer ] = = PF_B8G8R8A8 | | InLayerFormats [ Layer ] = = PF_DXT1 | | InLayerFormats [ Layer ] = = PF_DXT5 | | InLayerFormats [ Layer ] = = PF_BC4
| | InLayerFormats [ Layer ] = = PF_BC5 | | InLayerFormats [ Layer ] = = PF_R5G6B5_UNORM | | InLayerFormats [ Layer ] = = PF_B5G5R5A1_UNORM ) ;
LayerFormats [ Layer ] = InLayerFormats [ Layer ] = = PF_G16 | | InLayerFormats [ Layer ] = = PF_BC4 ? PF_G16 : PF_B8G8R8A8 ;
2020-04-07 12:40:55 -04:00
LayerOffsets [ Layer ] = TotalSizeBytes ;
TotalSizeBytes + = CalculateImageBytes ( InTileSize , InTileSize , 0 , LayerFormats [ Layer ] ) * InNumTilesX * InNumTilesY ;
}
2019-09-22 16:27:41 -04:00
}
//~ Begin FRenderResource Interface.
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2019-09-22 16:27:41 -04:00
{
RenderTargets . Init ( nullptr , NumLayers ) ;
StagingTextures . Init ( nullptr , NumLayers ) ;
for ( int32 Layer = 0 ; Layer < NumLayers ; + + Layer )
{
2022-05-10 17:13:37 -04:00
FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create2D ( TEXT ( " FTileRenderResources " ) , TileSize , TileSize , LayerFormats [ Layer ] ) ;
Desc . SetFlags ( ETextureCreateFlags : : RenderTargetable ) ;
RenderTargets [ Layer ] = RHICreateTexture ( Desc ) ;
Desc . SetFlags ( ETextureCreateFlags : : CPUReadback ) ;
2024-05-09 10:05:44 -04:00
// The staging texture will only ever be in CopyDest state so set it right away :
Desc . SetInitialState ( ERHIAccess : : CopyDest ) ;
2022-05-10 17:13:37 -04:00
StagingTextures [ Layer ] = RHICreateTexture ( Desc ) ;
2019-09-22 16:27:41 -04:00
}
2023-01-19 06:13:08 -05:00
Fence = RHICreateGPUFence ( TEXT ( " Runtime Virtual Texture Build " ) ) ;
2019-09-22 16:27:41 -04:00
}
virtual void ReleaseRHI ( ) override
{
RenderTargets . Empty ( ) ;
StagingTextures . Empty ( ) ;
Fence . SafeRelease ( ) ;
}
//~ End FRenderResource Interface.
2020-04-07 12:40:55 -04:00
int32 GetNumLayers ( ) const { return NumLayers ; }
2020-09-24 00:43:27 -04:00
int64 GetTotalSizeBytes ( ) const { return TotalSizeBytes ; }
2020-04-07 12:40:55 -04:00
EPixelFormat GetLayerFormat ( int32 Index ) const { return LayerFormats [ Index ] ; }
2020-09-24 00:43:27 -04:00
int64 GetLayerOffset ( int32 Index ) const { return LayerOffsets [ Index ] ; }
2020-04-07 12:40:55 -04:00
2024-02-22 11:38:35 -05:00
FRHITexture * GetRenderTarget ( int32 Index ) const { return Index < NumLayers ? RenderTargets [ Index ] : nullptr ; }
FRHITexture * GetStagingTexture ( int32 Index ) const { return Index < NumLayers ? StagingTextures [ Index ] : nullptr ; }
2019-09-22 16:27:41 -04:00
FRHIGPUFence * GetFence ( ) const { return Fence ; }
private :
int32 TileSize ;
2020-04-07 12:40:55 -04:00
int32 NumLayers ;
2020-09-24 00:43:27 -04:00
int64 TotalSizeBytes ;
2020-04-07 12:40:55 -04:00
TArray < EPixelFormat > LayerFormats ;
2020-09-24 00:43:27 -04:00
TArray < int64 > LayerOffsets ;
2019-09-22 16:27:41 -04:00
2024-02-22 11:38:35 -05:00
TArray < FTextureRHIRef > RenderTargets ;
TArray < FTextureRHIRef > StagingTextures ;
2019-09-22 16:27:41 -04:00
FGPUFenceRHIRef Fence ;
} ;
/** Templatized helper function for copying a rendered tile to the final composited image data. */
template < typename T >
2020-06-23 18:40:00 -04:00
void TCopyTile ( T * SrcPixels , int32 TileSize , int32 SrcStride , T * DestPixels , int32 DestStride , int32 DestLayerStride , FIntPoint const & DestPos )
2019-09-22 16:27:41 -04:00
{
for ( int32 y = 0 ; y < TileSize ; y + + )
{
memcpy (
2021-01-14 19:42:15 -04:00
DestPixels + ( SIZE_T ) DestStride * ( ( SIZE_T ) DestPos [ 1 ] + ( SIZE_T ) y ) + DestPos [ 0 ] ,
2020-06-23 18:40:00 -04:00
SrcPixels + SrcStride * y ,
2019-09-22 16:27:41 -04:00
TileSize * sizeof ( T ) ) ;
}
}
/** Function for copying a rendered tile to the final composited image data. Needs ERuntimeVirtualTextureMaterialType to know what type of data is being copied. */
2020-06-23 18:40:00 -04:00
void CopyTile ( void * SrcPixels , int32 TileSize , int32 SrcStride , void * DestPixels , int32 DestStride , int32 DestLayerStride , FIntPoint const & DestPos , EPixelFormat Format )
2019-09-22 16:27:41 -04:00
{
2020-04-07 12:40:55 -04:00
check ( Format = = PF_G16 | | Format = = PF_B8G8R8A8 ) ;
if ( Format = = PF_G16 )
2019-09-22 16:27:41 -04:00
{
2020-06-23 18:40:00 -04:00
TCopyTile ( ( uint16 * ) SrcPixels , TileSize , SrcStride , ( uint16 * ) DestPixels , DestStride , DestLayerStride , DestPos ) ;
2019-09-22 16:27:41 -04:00
}
2020-04-07 12:40:55 -04:00
else if ( Format = = PF_B8G8R8A8 )
2019-09-22 16:27:41 -04:00
{
2020-06-23 18:40:00 -04:00
TCopyTile ( ( FColor * ) SrcPixels , TileSize , SrcStride , ( FColor * ) DestPixels , DestStride , DestLayerStride , DestPos ) ;
2019-09-22 16:27:41 -04:00
}
}
}
2019-08-21 08:57:14 -04:00
namespace RuntimeVirtualTexture
{
2019-08-21 09:38:23 -04:00
bool HasStreamedMips ( URuntimeVirtualTextureComponent * InComponent )
2023-02-23 01:23:57 -05:00
{
EShadingPath ShadingPath = ( InComponent & & InComponent - > GetScene ( ) ) ? InComponent - > GetScene ( ) - > GetShadingPath ( ) : EShadingPath : : Deferred ;
return HasStreamedMips ( ShadingPath , InComponent ) ;
}
bool HasStreamedMips ( EShadingPath ShadingPath , URuntimeVirtualTextureComponent * InComponent )
2019-08-21 08:57:14 -04:00
{
if ( InComponent = = nullptr )
{
return false ;
}
2020-04-14 13:33:06 -04:00
if ( InComponent - > GetVirtualTexture ( ) = = nullptr | | InComponent - > GetStreamingTexture ( ) = = nullptr )
2019-08-21 08:57:14 -04:00
{
return false ;
}
2020-04-15 10:23:37 -04:00
if ( InComponent - > NumStreamingMips ( ) < = 0 )
2019-08-21 08:57:14 -04:00
{
return false ;
}
2023-02-23 01:23:57 -05:00
if ( ShadingPath = = EShadingPath : : Mobile & & ! InComponent - > GetStreamingTexture ( ) - > bSeparateTextureForMobile )
{
return false ;
}
2019-08-21 08:57:14 -04:00
return true ;
}
2023-02-23 01:23:57 -05:00
2024-01-10 16:32:21 -05:00
bool BuildStreamedMips ( URuntimeVirtualTextureComponent * InComponent , FLinearColor const & FixedColor )
2019-08-21 08:57:14 -04:00
{
2023-02-23 01:23:57 -05:00
EShadingPath ShadingPath = ( InComponent & & InComponent - > GetScene ( ) ) ? InComponent - > GetScene ( ) - > GetShadingPath ( ) : EShadingPath : : Deferred ;
2024-01-10 16:32:21 -05:00
return BuildStreamedMips ( ShadingPath , InComponent , FixedColor ) ;
2023-02-23 01:23:57 -05:00
}
2024-01-10 16:32:21 -05:00
bool BuildStreamedMips ( EShadingPath ShadingPath , URuntimeVirtualTextureComponent * InComponent , FLinearColor const & FixedColor )
2023-02-23 01:23:57 -05:00
{
2024-04-19 05:54:18 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( BuildStreamedMips ) ;
2023-02-23 01:23:57 -05:00
if ( ! HasStreamedMips ( ShadingPath , InComponent ) )
2019-08-21 08:57:14 -04:00
{
return true ;
}
URuntimeVirtualTexture * RuntimeVirtualTexture = InComponent - > GetVirtualTexture ( ) ;
FSceneInterface * Scene = InComponent - > GetScene ( ) ;
const uint32 VirtualTextureSceneIndex = RuntimeVirtualTexture : : GetRuntimeVirtualTextureSceneIndex_GameThread ( InComponent ) ;
2020-06-23 18:40:00 -04:00
const FTransform Transform = InComponent - > GetComponentTransform ( ) ;
2020-03-17 23:19:30 -04:00
const FBox Bounds = InComponent - > Bounds . GetBox ( ) ;
2019-08-21 08:57:14 -04:00
FVTProducerDescription VTDesc ;
2020-09-24 00:43:27 -04:00
RuntimeVirtualTexture - > GetProducerDescription ( VTDesc , URuntimeVirtualTexture : : FInitSettings ( ) , Transform ) ;
2019-08-21 08:57:14 -04:00
const int32 TileSize = VTDesc . TileSize ;
const int32 TileBorderSize = VTDesc . TileBorderSize ;
const int32 TextureSizeX = VTDesc . WidthInBlocks * VTDesc . BlockWidthInTiles * TileSize ;
const int32 TextureSizeY = VTDesc . HeightInBlocks * VTDesc . BlockHeightInTiles * TileSize ;
const int32 MaxLevel = ( int32 ) FMath : : CeilLogTwo ( FMath : : Max ( VTDesc . BlockWidthInTiles , VTDesc . BlockHeightInTiles ) ) ;
2020-04-15 10:23:37 -04:00
const int32 RenderLevel = FMath : : Max ( MaxLevel - InComponent - > NumStreamingMips ( ) + 1 , 0 ) ;
2019-09-22 16:27:41 -04:00
const int32 ImageSizeX = FMath : : Max ( TileSize , TextureSizeX > > RenderLevel ) ;
const int32 ImageSizeY = FMath : : Max ( TileSize , TextureSizeY > > RenderLevel ) ;
const int32 NumTilesX = ImageSizeX / TileSize ;
const int32 NumTilesY = ImageSizeY / TileSize ;
const int32 NumLayers = RuntimeVirtualTexture - > GetLayerCount ( ) ;
2019-08-21 08:57:14 -04:00
const ERuntimeVirtualTextureMaterialType MaterialType = RuntimeVirtualTexture - > GetMaterialType ( ) ;
2020-04-07 12:40:55 -04:00
TArray < EPixelFormat , TInlineAllocator < 4 > > LayerFormats ;
for ( int32 Layer = 0 ; Layer < NumLayers ; + + Layer )
{
LayerFormats . Add ( RuntimeVirtualTexture - > GetLayerFormat ( Layer ) ) ;
}
2019-08-21 08:57:14 -04:00
// Spin up slow task UI
2024-04-15 19:31:17 -04:00
const float TaskWorkRender = static_cast < float > ( NumTilesX * NumTilesY ) ;
2022-02-28 17:59:11 -05:00
const float TextureBuildTaskMultiplier = 0.25f ;
2020-09-01 14:07:48 -04:00
const float TaskWorkBuildBulkData = TaskWorkRender * TextureBuildTaskMultiplier ;
2020-04-15 10:23:37 -04:00
FScopedSlowTask Task ( TaskWorkRender + TaskWorkBuildBulkData , FText : : AsCultureInvariant ( InComponent - > GetStreamingTexture ( ) - > GetName ( ) ) ) ;
2019-08-21 08:57:14 -04:00
Task . MakeDialog ( true ) ;
// Allocate render targets for rendering out the runtime virtual texture tiles
2020-08-11 01:36:57 -04:00
FTileRenderResources RenderTileResources ( TileSize , NumTilesX , NumTilesY , NumLayers , LayerFormats ) ;
2019-09-22 16:27:41 -04:00
BeginInitResource ( & RenderTileResources ) ;
2019-08-21 08:57:14 -04:00
2022-06-22 20:21:16 -04:00
int64 RenderTileResourcesBytes = RenderTileResources . GetTotalSizeBytes ( ) ;
UE_LOG ( LogVirtualTexturing , Display , TEXT ( " Allocating %uMiB for RenderTileResourcesBytes " ) , ( uint32 ) ( RenderTileResourcesBytes / ( 1024 * 1024 ) ) ) ;
2019-09-22 16:27:41 -04:00
// Final pixels will contain image data for each virtual texture layer in order
TArray64 < uint8 > FinalPixels ;
2022-06-22 20:21:16 -04:00
FinalPixels . SetNumUninitialized ( RenderTileResourcesBytes ) ;
2019-08-21 08:57:14 -04:00
Render Command Pipe Implementation and API
Render Command Pipes dedicated asynchronous task pipes for render commands. Users can easily define new pipes and enqueue commands into them. Pipes can be synchronized using a scope to run serial render commands on the render thread, but initially pipes cannot be synchronized individually with each other. Render command overhead is reduced by recording command lambdas into MPSC queues which are serviced by the task graph; both for pipes and for the render thread. This reduces the task overhead as commands are no longer 1-to-1 with tasks.
Pipe behavior is controlled with new CVars. `r.RenderCommandPipeMode` controls overall behavior:
0 - Legacy render thread tasks,
1 - Render thread MPSC queue,
2 - Render thread and async pipe MPSC queues.
To define a Render Command Pipe, use DEFINE_RENDER_COMMAND_PIPE(MyPipe), or DECLARE_RENDER_COMMAND_PIPE(MyPipe, MODULE_API) to declare an extern reference.
Enqueue a command into the pipe like so:
ENQUEUE_RENDER_COMMAND(MyCommand)(UE::RenderCommandPipe::MyPipe, [] (FRHICommandList&) {}).
Omitting a pipe will fallback to the 'general' pipe which is the render thread.
Eventually pipes need to be synced back to the general pipe for scene renders and other GPU work. On the game thread timeline, use UE::RenderCommandPipe::FSyncScope to synchronize the pipes. This waits for pipes and disables recording of new pipe commands until the scope completes, at which point pipe recording is restarted. This creates a 'sync point', so render commands issued prior to a sync scope will be waited on at the start of the scope, and render commands issued after the scope ends will not be able to start until the render thread finishes processing prior commands.
#rb christopher.waters, luke.thatcher
[CL 27074956 by zach bethel in ue5-main branch]
2023-08-14 12:52:45 -04:00
UE : : RenderCommandPipe : : FSyncScope SyncScope ;
2024-05-09 10:05:44 -04:00
ERHIAccess RenderTargetsCurrentState = ERHIAccess : : RTV ;
Render Command Pipe Implementation and API
Render Command Pipes dedicated asynchronous task pipes for render commands. Users can easily define new pipes and enqueue commands into them. Pipes can be synchronized using a scope to run serial render commands on the render thread, but initially pipes cannot be synchronized individually with each other. Render command overhead is reduced by recording command lambdas into MPSC queues which are serviced by the task graph; both for pipes and for the render thread. This reduces the task overhead as commands are no longer 1-to-1 with tasks.
Pipe behavior is controlled with new CVars. `r.RenderCommandPipeMode` controls overall behavior:
0 - Legacy render thread tasks,
1 - Render thread MPSC queue,
2 - Render thread and async pipe MPSC queues.
To define a Render Command Pipe, use DEFINE_RENDER_COMMAND_PIPE(MyPipe), or DECLARE_RENDER_COMMAND_PIPE(MyPipe, MODULE_API) to declare an extern reference.
Enqueue a command into the pipe like so:
ENQUEUE_RENDER_COMMAND(MyCommand)(UE::RenderCommandPipe::MyPipe, [] (FRHICommandList&) {}).
Omitting a pipe will fallback to the 'general' pipe which is the render thread.
Eventually pipes need to be synced back to the general pipe for scene renders and other GPU work. On the game thread timeline, use UE::RenderCommandPipe::FSyncScope to synchronize the pipes. This waits for pipes and disables recording of new pipe commands until the scope completes, at which point pipe recording is restarted. This creates a 'sync point', so render commands issued prior to a sync scope will be waited on at the start of the scope, and render commands issued after the scope ends will not be able to start until the render thread finishes processing prior commands.
#rb christopher.waters, luke.thatcher
[CL 27074956 by zach bethel in ue5-main branch]
2023-08-14 12:52:45 -04:00
2019-09-22 16:27:41 -04:00
// Iterate over all tiles and render/store each one to the final image
for ( int32 TileY = 0 ; TileY < NumTilesY & & ! Task . ShouldCancel ( ) ; TileY + + )
2019-08-21 08:57:14 -04:00
{
2020-08-11 01:36:57 -04:00
for ( int32 TileX = 0 ; TileX < NumTilesX ; TileX + + )
{
2019-08-21 08:57:14 -04:00
// Render tile
2020-09-01 14:07:48 -04:00
Task . EnterProgressFrame ( ) ;
2019-08-21 08:57:14 -04:00
const FBox2D UVRange = FBox2D (
2019-09-22 16:27:41 -04:00
FVector2D ( ( float ) TileX / ( float ) NumTilesX , ( float ) TileY / ( float ) NumTilesY ) ,
FVector2D ( ( float ) ( TileX + 1 ) / ( float ) NumTilesX , ( float ) ( TileY + 1 ) / ( float ) NumTilesY ) ) ;
2019-08-21 08:57:14 -04:00
2020-09-01 14:07:48 -04:00
// Stream textures for this tile. This triggers a render flush internally.
//todo[vt]: Batch groups of streaming locations and render commands to reduce number of flushes.
const FVector StreamingWorldPos = Transform . TransformPosition ( FVector ( UVRange . GetCenter ( ) , 0.5f ) ) ;
IStreamingManager : : Get ( ) . Tick ( 0.f ) ;
2022-07-12 11:18:47 -04:00
IStreamingManager : : Get ( ) . AddViewLocation ( StreamingWorldPos ) ;
2020-09-01 14:07:48 -04:00
IStreamingManager : : Get ( ) . StreamAllResources ( 0 ) ;
2019-09-22 16:27:41 -04:00
ENQUEUE_RENDER_COMMAND ( BakeStreamingTextureTileCommand ) ( [
Scene , VirtualTextureSceneIndex ,
& RenderTileResources ,
MaterialType , NumLayers ,
2020-03-17 23:19:30 -04:00
Transform , Bounds , UVRange ,
2019-09-22 16:27:41 -04:00
RenderLevel , MaxLevel ,
TileX , TileY ,
TileSize , ImageSizeX , ImageSizeY ,
& FinalPixels ,
2024-05-09 10:05:44 -04:00
FixedColor , & RenderTargetsCurrentState ] ( FRHICommandListImmediate & RHICmdList )
2019-08-21 08:57:14 -04:00
{
2019-09-22 16:27:41 -04:00
const FBox2D TileBox ( FVector2D ( 0 , 0 ) , FVector2D ( TileSize , TileSize ) ) ;
const FIntRect TileRect ( 0 , 0 , TileSize , TileSize ) ;
2020-10-26 16:44:44 -04:00
{
FRDGBuilder GraphBuilder ( RHICmdList ) ;
2019-08-21 08:57:14 -04:00
2021-01-14 20:15:23 -04:00
RuntimeVirtualTexture : : FRenderPageBatchDesc Desc ;
Desc . Scene = Scene - > GetRenderScene ( ) ;
Desc . RuntimeVirtualTextureMask = 1 < < VirtualTextureSceneIndex ;
Desc . UVToWorld = Transform ;
Desc . WorldBounds = Bounds ;
Desc . MaterialType = MaterialType ;
2024-04-15 19:31:17 -04:00
Desc . MaxLevel = IntCastChecked < uint8 > ( MaxLevel ) ;
2021-01-14 20:15:23 -04:00
Desc . bClearTextures = true ;
Desc . bIsThumbnails = false ;
2024-01-10 16:32:21 -05:00
Desc . FixedColor = FixedColor ;
2021-01-14 20:15:23 -04:00
Desc . NumPageDescs = 1 ;
2024-05-09 10:05:44 -04:00
for ( int32 Layer = 0 ; Layer < NumLayers ; Layer + + )
{
Desc . Targets [ Layer ] . Texture = RenderTileResources . GetRenderTarget ( Layer ) ;
Desc . Targets [ Layer ] . TextureAccessBefore = RenderTargetsCurrentState ;
// Leave the render targets in CopySrc state since we'll read from them right after, to avoid a useless transition :
Desc . Targets [ Layer ] . TextureAccessAfter = ERHIAccess : : CopySrc ;
Desc . PageDescs [ 0 ] . DestBox [ Layer ] = TileBox ;
}
2021-01-14 20:15:23 -04:00
Desc . PageDescs [ 0 ] . UVRange = UVRange ;
2024-04-15 19:31:17 -04:00
Desc . PageDescs [ 0 ] . vLevel = IntCastChecked < uint8 > ( RenderLevel ) ;
2021-01-14 20:15:23 -04:00
RuntimeVirtualTexture : : RenderPagesStandAlone ( GraphBuilder , Desc ) ;
GraphBuilder . Execute ( ) ;
2019-08-21 08:57:14 -04:00
}
2019-09-22 16:27:41 -04:00
// Copy to staging
for ( int32 Layer = 0 ; Layer < NumLayers ; Layer + + )
{
RHICmdList . CopyTexture ( RenderTileResources . GetRenderTarget ( Layer ) , RenderTileResources . GetStagingTexture ( Layer ) , FRHICopyTextureInfo ( ) ) ;
}
2024-05-09 10:05:44 -04:00
RenderTargetsCurrentState = ERHIAccess : : CopySrc ;
2019-09-22 16:27:41 -04:00
2022-10-14 22:20:40 -04:00
RenderTileResources . GetFence ( ) - > Clear ( ) ;
2019-09-22 16:27:41 -04:00
RHICmdList . WriteGPUFence ( RenderTileResources . GetFence ( ) ) ;
// Read back tile data and copy into final destination
for ( int32 Layer = 0 ; Layer < NumLayers ; Layer + + )
{
void * TilePixels = nullptr ;
int32 OutWidth , OutHeight ;
2021-01-14 20:15:23 -04:00
RHICmdList . MapStagingSurface ( RenderTileResources . GetStagingTexture ( Layer ) , RenderTileResources . GetFence ( ) , TilePixels , OutWidth , OutHeight ) ;
2019-09-22 16:27:41 -04:00
check ( TilePixels ! = nullptr ) ;
2020-06-23 18:40:00 -04:00
check ( OutHeight = = TileSize ) ;
2019-09-22 16:27:41 -04:00
2020-09-24 00:43:27 -04:00
const int64 LayerOffset = RenderTileResources . GetLayerOffset ( Layer ) ;
2020-04-07 12:40:55 -04:00
const EPixelFormat LayerFormat = RenderTileResources . GetLayerFormat ( Layer ) ;
const FIntPoint DestPos ( TileX * TileSize , TileY * TileSize ) ;
2020-06-23 18:40:00 -04:00
CopyTile ( TilePixels , TileSize , OutWidth , FinalPixels . GetData ( ) + LayerOffset , ImageSizeX , ImageSizeX * ImageSizeY , DestPos , LayerFormat ) ;
2019-09-22 16:27:41 -04:00
RHICmdList . UnmapStagingSurface ( RenderTileResources . GetStagingTexture ( Layer ) ) ;
}
} ) ;
2019-08-21 08:57:14 -04:00
}
}
2020-04-14 13:33:06 -04:00
BeginReleaseResource ( & RenderTileResources ) ;
2020-09-01 14:07:48 -04:00
FlushRenderingCommands ( ) ;
2019-08-21 08:57:14 -04:00
if ( Task . ShouldCancel ( ) )
{
return false ;
}
// Place final pixel data into the runtime virtual texture
Task . EnterProgressFrame ( TaskWorkBuildBulkData ) ;
2020-04-14 13:33:06 -04:00
2023-02-23 01:23:57 -05:00
InComponent - > InitializeStreamingTexture ( ShadingPath , ImageSizeX , ImageSizeY , ( uint8 * ) FinalPixels . GetData ( ) ) ;
2019-08-21 08:57:14 -04:00
return true ;
}
}