2020-07-07 14:29:30 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
2020-07-06 18:58:26 -04:00
/*=============================================================================
VirtualShadowMap . h :
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "VirtualShadowMapCacheManager.h"
# include "RendererModule.h"
# include "RenderGraphUtils.h"
# include "RHIGPUReadback.h"
2020-08-25 10:06:54 -04:00
# include "ScenePrivate.h"
2020-07-06 18:58:26 -04:00
# include "HAL/FileManager.h"
2020-08-25 10:06:54 -04:00
# include "PrimitiveSceneInfo.h"
2020-07-06 18:58:26 -04:00
static TAutoConsoleVariable < int32 > CVarAccumulateStats (
2021-02-18 13:44:36 -04:00
TEXT ( " r.Shadow.Virtual.AccumulateStats " ) ,
2020-07-06 18:58:26 -04:00
0 ,
TEXT ( " AccumulateStats " ) ,
ECVF_RenderThreadSafe
) ;
static TAutoConsoleVariable < int32 > CVarCacheVirtualSMs (
2021-02-18 13:44:36 -04:00
TEXT ( " r.Shadow.Virtual.Cache " ) ,
2021-03-15 22:06:28 -04:00
1 ,
2020-07-06 18:58:26 -04:00
TEXT ( " Turn on to enable caching " ) ,
ECVF_RenderThreadSafe
) ;
2020-12-16 17:57:13 -04:00
void FVirtualShadowMapCacheEntry : : UpdateClipmap (
int32 VirtualShadowMapId ,
const FMatrix & WorldToLight ,
FIntPoint PageSpaceLocation ,
2021-05-27 17:36:27 -04:00
float LevelRadius ,
float ViewCenterZ ,
float ViewRadiusZ )
2020-07-06 18:58:26 -04:00
{
2021-05-27 17:36:27 -04:00
bool bCacheValid = ( CurrentVirtualShadowMapId ! = INDEX_NONE ) ;
2020-07-06 18:58:26 -04:00
2021-05-27 17:36:27 -04:00
if ( bCacheValid & & WorldToLight ! = Clipmap . WorldToLight )
2020-07-06 18:58:26 -04:00
{
2021-05-27 17:36:27 -04:00
bCacheValid = false ;
//UE_LOG(LogRenderer, Display, TEXT("Invalidated clipmap level (VSM %d) due to light movement"), VirtualShadowMapId);
2020-07-06 18:58:26 -04:00
}
2021-05-27 17:36:27 -04:00
#if 0
// Disable cache panning for directional lights (debug)
if ( bCacheValid )
{
bCacheValid = bCacheValid & & PageSpaceLocation . X = = PrevPageSpaceLocation . X ;
bCacheValid = bCacheValid & & PageSpaceLocation . Y = = PrevPageSpaceLocation . Y ;
if ( ! bCacheValid )
{
//UE_LOG(LogRenderer, Display, TEXT("Invalidated clipmap level (VSM %d) with page space location %d,%d (Prev %d, %d)"),
// VirtualShadowMapId, PageSpaceLocation.X, PageSpaceLocation.Y, PrevPageSpaceLocation.X, PrevPageSpaceLocation.Y);
}
}
# endif
// Invalidate if the new Z radius strayed too close/outside the guardband of the cached shadow map
if ( bCacheValid )
{
float DeltaZ = FMath : : Abs ( ViewCenterZ - Clipmap . ViewCenterZ ) ;
if ( ( DeltaZ + LevelRadius ) > 0.9f * Clipmap . ViewRadiusZ )
{
bCacheValid = false ;
//UE_LOG(LogRenderer, Display, TEXT("Invalidated clipmap level (VSM %d) due to depth range movement"), VirtualShadowMapId);
}
}
if ( bCacheValid )
{
PrevVirtualShadowMapId = CurrentVirtualShadowMapId ;
}
else
{
// New cached level
PrevVirtualShadowMapId = INDEX_NONE ;
Clipmap . WorldToLight = WorldToLight ;
Clipmap . ViewCenterZ = ViewCenterZ ;
Clipmap . ViewRadiusZ = ViewRadiusZ ;
}
PrevPageSpaceLocation = CurrentPageSpaceLocation ;
2020-07-06 18:58:26 -04:00
CurrentVirtualShadowMapId = VirtualShadowMapId ;
CurrentPageSpaceLocation = PageSpaceLocation ;
}
2021-05-27 17:36:27 -04:00
void FVirtualShadowMapCacheEntry : : UpdateLocal ( int32 VirtualShadowMapId , const FWholeSceneProjectedShadowInitializer & InCacheValidKey )
2020-07-06 18:58:26 -04:00
{
// Swap previous frame data over.
PrevPageSpaceLocation = CurrentPageSpaceLocation ;
PrevVirtualShadowMapId = CurrentVirtualShadowMapId ;
// Check cache validity based of shadow setup
2021-05-27 17:36:27 -04:00
if ( ! LocalCacheValidKey . IsCachedShadowValid ( InCacheValidKey ) )
2020-07-06 18:58:26 -04:00
{
2020-12-16 17:57:13 -04:00
PrevVirtualShadowMapId = INDEX_NONE ;
//UE_LOG(LogRenderer, Display, TEXT("Invalidated!"));
2020-07-06 18:58:26 -04:00
}
2021-05-27 17:36:27 -04:00
LocalCacheValidKey = InCacheValidKey ;
2020-07-06 18:58:26 -04:00
CurrentVirtualShadowMapId = VirtualShadowMapId ;
2020-12-16 17:57:13 -04:00
PrevPageSpaceLocation = CurrentPageSpaceLocation = FIntPoint ( 0 , 0 ) ;
2020-07-06 18:58:26 -04:00
}
TSharedPtr < FVirtualShadowMapCacheEntry > FVirtualShadowMapArrayCacheManager : : FindCreateCacheEntry ( int32 LightSceneId , int32 CascadeIndex )
{
if ( CVarCacheVirtualSMs . GetValueOnRenderThread ( ) = = 0 )
{
return nullptr ;
}
const FIntPoint Key ( LightSceneId , CascadeIndex ) ;
if ( TSharedPtr < FVirtualShadowMapCacheEntry > * VirtualShadowMapCacheEntry = CacheEntries . Find ( Key ) )
{
return * VirtualShadowMapCacheEntry ;
}
// Add to current frame / active set.
TSharedPtr < FVirtualShadowMapCacheEntry > & NewVirtualShadowMapCacheEntry = CacheEntries . Add ( Key ) ;
// Copy data if available
if ( TSharedPtr < FVirtualShadowMapCacheEntry > * PrevVirtualShadowMapCacheEntry = PrevCacheEntries . Find ( Key ) )
{
NewVirtualShadowMapCacheEntry = * PrevVirtualShadowMapCacheEntry ;
}
else
{
NewVirtualShadowMapCacheEntry = TSharedPtr < FVirtualShadowMapCacheEntry > ( new FVirtualShadowMapCacheEntry ) ;
}
// return entry
return NewVirtualShadowMapCacheEntry ;
}
class FVirtualSmCopyStatsCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER ( FVirtualSmCopyStatsCS ) ;
SHADER_USE_PARAMETER_STRUCT ( FVirtualSmCopyStatsCS , FGlobalShader )
public :
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
SHADER_PARAMETER_RDG_BUFFER_SRV ( StructuredBuffer < uint > , InStatsBuffer )
SHADER_PARAMETER_RDG_BUFFER_UAV ( RWBuffer < uint > , AccumulatedStatsBufferOut )
SHADER_PARAMETER ( uint32 , NumStats )
END_SHADER_PARAMETER_STRUCT ( )
static bool ShouldCompilePermutation ( const FGlobalShaderPermutationParameters & Parameters )
{
return IsFeatureLevelSupported ( Parameters . Platform , ERHIFeatureLevel : : SM5 ) ;
}
static void ModifyCompilationEnvironment ( const FGlobalShaderPermutationParameters & Parameters , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Parameters , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " MAX_STAT_FRAMES " ) , FVirtualShadowMapArrayCacheManager : : MaxStatFrames ) ;
}
} ;
IMPLEMENT_GLOBAL_SHADER ( FVirtualSmCopyStatsCS , " /Engine/Private/VirtualShadowMaps/CopyStats.usf " , " CopyStatsCS " , SF_Compute ) ;
2021-03-24 16:27:31 -04:00
void FVirtualShadowMapArrayCacheManager : : ExtractFrameData ( bool bEnableCaching , FVirtualShadowMapArray & VirtualShadowMapArray , FRDGBuilder & GraphBuilder )
2020-07-06 18:58:26 -04:00
{
2021-03-23 21:23:57 -04:00
// Drop all refs.
PrevBuffers = FVirtualShadowMapArrayFrameData ( ) ;
PrevUniformParameters . NumShadowMaps = 0 ;
2021-03-25 18:19:54 -04:00
if ( bEnableCaching & & VirtualShadowMapArray . IsAllocated ( ) )
2020-07-06 18:58:26 -04:00
{
2021-03-25 18:19:54 -04:00
bool bExtractPageTable = false ;
// HZB and associated page table are needed by next frame even when VSM physical page caching is disabled
if ( VirtualShadowMapArray . HZBPhysical )
{
bExtractPageTable = true ;
GraphBuilder . QueueTextureExtraction ( VirtualShadowMapArray . HZBPhysical , & PrevBuffers . HZBPhysical ) ;
PrevBuffers . HZBMetadata = VirtualShadowMapArray . HZBMetadata ;
}
if ( CVarCacheVirtualSMs . GetValueOnRenderThread ( ) ! = 0 )
{
bExtractPageTable = true ;
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . PageFlagsRDG , & PrevBuffers . PageFlags ) ;
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . HPageFlagsRDG , & PrevBuffers . HPageFlags ) ;
2020-08-25 10:06:54 -04:00
2021-03-25 18:19:54 -04:00
GraphBuilder . QueueTextureExtraction ( VirtualShadowMapArray . PhysicalPagePoolRDG , & PrevBuffers . PhysicalPagePool ) ;
2021-02-25 05:03:27 -04:00
2021-03-25 18:19:54 -04:00
if ( VirtualShadowMapArray . PhysicalPagePoolHw )
{
GraphBuilder . QueueTextureExtraction ( VirtualShadowMapArray . PhysicalPagePoolHw , & PrevBuffers . PhysicalPagePoolHw ) ;
}
else
{
PrevBuffers . PhysicalPagePoolHw = TRefCountPtr < IPooledRenderTarget > ( ) ;
}
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . PhysicalPageMetaDataRDG , & PrevBuffers . PhysicalPageMetaData ) ;
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . DynamicCasterPageFlagsRDG , & PrevBuffers . DynamicCasterPageFlags ) ;
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . ShadowMapProjectionDataRDG , & PrevBuffers . ShadowMapProjectionDataBuffer ) ;
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . PageRectBoundsRDG , & PrevBuffers . PageRectBounds ) ;
// Move cache entries to previous frame, this implicitly removes any that were not used
PrevCacheEntries = CacheEntries ;
PrevUniformParameters = VirtualShadowMapArray . UniformParameters ;
2021-02-22 14:47:36 -04:00
}
2021-02-25 05:03:27 -04:00
2021-03-25 18:19:54 -04:00
if ( bExtractPageTable )
{
GraphBuilder . QueueBufferExtraction ( VirtualShadowMapArray . PageTableRDG , & PrevBuffers . PageTable ) ;
}
2020-07-06 18:58:26 -04:00
}
else
{
PrevCacheEntries . Empty ( ) ;
}
CacheEntries . Reset ( ) ;
2021-03-08 23:14:54 -04:00
// Drop any references embedded in the uniform parameters this frame.
// We'll reestablish them when we reimport the extracted resources next frame
PrevUniformParameters . ProjectionData = nullptr ;
PrevUniformParameters . PageTable = nullptr ;
PrevUniformParameters . PhysicalPagePool = nullptr ;
PrevUniformParameters . PhysicalPagePoolHw = nullptr ;
2020-09-24 00:43:27 -04:00
FRDGBufferRef AccumulatedStatsBufferRDG = nullptr ;
2020-07-06 18:58:26 -04:00
// Note: stats accumulation thing is here because it needs to persist over frames.
if ( ! AccumulatedStatsBuffer . IsValid ( ) )
{
2021-02-18 13:44:36 -04:00
AccumulatedStatsBufferRDG = GraphBuilder . CreateBuffer ( FRDGBufferDesc : : CreateBufferDesc ( 4 , 1 + FVirtualShadowMapArray : : NumStats * MaxStatFrames ) , TEXT ( " Shadow.Virtual.AccumulatedStatsBuffer " ) ) ; // TODO: Can't be a structured buffer as EnqueueCopy is only defined for vertex buffers
2020-07-06 18:58:26 -04:00
AddClearUAVPass ( GraphBuilder , GraphBuilder . CreateUAV ( AccumulatedStatsBufferRDG , PF_R32_UINT ) , 0 ) ;
2021-04-06 11:45:09 -04:00
AccumulatedStatsBuffer = GraphBuilder . ConvertToExternalBuffer ( AccumulatedStatsBufferRDG ) ;
2020-09-24 00:43:27 -04:00
}
else
{
2021-02-18 13:44:36 -04:00
AccumulatedStatsBufferRDG = GraphBuilder . RegisterExternalBuffer ( AccumulatedStatsBuffer , TEXT ( " Shadow.Virtual.AccumulatedStatsBuffer " ) ) ;
2020-07-06 18:58:26 -04:00
}
if ( IsAccumulatingStats ( ) )
{
// Initialize/clear
if ( ! bAccumulatingStats )
{
AddClearUAVPass ( GraphBuilder , GraphBuilder . CreateUAV ( AccumulatedStatsBufferRDG , PF_R32_UINT ) , 0 ) ;
bAccumulatingStats = true ;
}
FVirtualSmCopyStatsCS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FVirtualSmCopyStatsCS : : FParameters > ( ) ;
2020-11-09 15:47:39 -04:00
PassParameters - > InStatsBuffer = GraphBuilder . CreateSRV ( VirtualShadowMapArray . StatsBufferRDG , PF_R32_UINT ) ;
2020-07-06 18:58:26 -04:00
PassParameters - > AccumulatedStatsBufferOut = GraphBuilder . CreateUAV ( AccumulatedStatsBufferRDG , PF_R32_UINT ) ;
PassParameters - > NumStats = FVirtualShadowMapArray : : NumStats ;
auto ComputeShader = GetGlobalShaderMap ( GMaxRHIFeatureLevel ) - > GetShader < FVirtualSmCopyStatsCS > ( ) ;
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " Copy Stats " ) ,
ComputeShader ,
PassParameters ,
FIntVector ( 1 , 1 , 1 )
) ;
}
else if ( bAccumulatingStats )
{
bAccumulatingStats = false ;
2020-09-24 00:43:27 -04:00
2021-02-18 13:44:36 -04:00
GPUBufferReadback = new FRHIGPUBufferReadback ( TEXT ( " Shadow.Virtual.AccumulatedStatsBuffer " ) ) ;
2020-09-24 00:43:27 -04:00
AddEnqueueCopyPass ( GraphBuilder , GPUBufferReadback , AccumulatedStatsBufferRDG , 0u ) ;
2020-07-06 18:58:26 -04:00
}
if ( GPUBufferReadback & & GPUBufferReadback - > IsReady ( ) )
{
TArray < uint32 > Tmp ;
Tmp . AddDefaulted ( 1 + FVirtualShadowMapArray : : NumStats * MaxStatFrames ) ;
{
const uint32 * BufferPtr = ( const uint32 * ) GPUBufferReadback - > Lock ( ( 1 + FVirtualShadowMapArray : : NumStats * MaxStatFrames ) * sizeof ( uint32 ) ) ;
FPlatformMemory : : Memcpy ( Tmp . GetData ( ) , BufferPtr , Tmp . Num ( ) * Tmp . GetTypeSize ( ) ) ;
GPUBufferReadback - > Unlock ( ) ;
delete GPUBufferReadback ;
GPUBufferReadback = nullptr ;
}
2021-02-18 13:44:36 -04:00
FString FileName = TEXT ( " VirtualShadowMapCacheStats.csv " ) ; // FString::Printf(TEXT("%s.csv"), *FileNameToUse);
2020-07-06 18:58:26 -04:00
FArchive * FileToLogTo = IFileManager : : Get ( ) . CreateFileWriter ( * FileName , false ) ;
ensure ( FileToLogTo ) ;
if ( FileToLogTo )
{
static const FString StatNames [ FVirtualShadowMapArray : : NumStats ] =
{
TEXT ( " Allocated " ) ,
TEXT ( " Cached " ) ,
TEXT ( " Dynamic " ) ,
TEXT ( " NumSms " ) ,
TEXT ( " RandRobin " ) ,
} ;
// Print header
FString StringToPrint ;
for ( const FString & StatName : StatNames )
{
if ( ! StringToPrint . IsEmpty ( ) )
{
StringToPrint + = TEXT ( " , " ) ;
}
StringToPrint + = StatName ;
}
StringToPrint + = TEXT ( " \n " ) ;
FileToLogTo - > Serialize ( TCHAR_TO_ANSI ( * StringToPrint ) , StringToPrint . Len ( ) ) ;
uint32 Num = Tmp [ 0 ] ;
for ( uint32 Ind = 0 ; Ind < Num ; + + Ind )
{
StringToPrint . Empty ( ) ;
for ( uint32 StatInd = 0 ; StatInd < FVirtualShadowMapArray : : NumStats ; + + StatInd )
{
if ( ! StringToPrint . IsEmpty ( ) )
{
StringToPrint + = TEXT ( " , " ) ;
}
StringToPrint + = FString : : Printf ( TEXT ( " %d " ) , Tmp [ 1 + Ind * FVirtualShadowMapArray : : NumStats + StatInd ] ) ;
}
StringToPrint + = TEXT ( " \n " ) ;
FileToLogTo - > Serialize ( TCHAR_TO_ANSI ( * StringToPrint ) , StringToPrint . Len ( ) ) ;
}
FileToLogTo - > Close ( ) ;
}
}
}
bool FVirtualShadowMapArrayCacheManager : : IsValid ( )
{
return CVarCacheVirtualSMs . GetValueOnRenderThread ( ) ! = 0
2021-03-23 21:23:57 -04:00
& & PrevBuffers . PageTable
& & PrevBuffers . PageFlags
& & ( PrevBuffers . PhysicalPagePool | | PrevBuffers . PhysicalPagePoolHw )
& & PrevBuffers . PhysicalPageMetaData
& & PrevBuffers . DynamicCasterPageFlags ;
2020-07-06 18:58:26 -04:00
}
bool FVirtualShadowMapArrayCacheManager : : IsAccumulatingStats ( )
{
return CVarAccumulateStats . GetValueOnRenderThread ( ) ! = 0 ;
}
2020-08-25 10:06:54 -04:00
2021-06-14 13:42:46 -04:00
void FVirtualShadowMapArrayCacheManager : : ProcessRemovedPrimives ( FRDGBuilder & GraphBuilder , const FGPUScene & GPUScene , const TArray < FPrimitiveSceneInfo * > & RemovedPrimitiveSceneInfos )
2020-08-25 10:06:54 -04:00
{
2021-03-23 21:23:57 -04:00
if ( CVarCacheVirtualSMs . GetValueOnRenderThread ( ) ! = 0 & & RemovedPrimitiveSceneInfos . Num ( ) > 0 & & PrevBuffers . DynamicCasterPageFlags . IsValid ( ) )
2020-08-25 10:06:54 -04:00
{
2021-06-14 13:42:46 -04:00
TArray < FInstanceSceneDataRange , SceneRenderingAllocator > InstanceRangesLarge ;
TArray < FInstanceSceneDataRange , SceneRenderingAllocator > InstanceRangesSmall ;
2021-06-10 15:46:35 -04:00
2020-08-25 10:06:54 -04:00
for ( const FPrimitiveSceneInfo * PrimitiveSceneInfo : RemovedPrimitiveSceneInfos )
{
2021-06-14 13:42:46 -04:00
if ( PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) ! = INDEX_NONE )
2020-08-25 10:06:54 -04:00
{
2021-06-14 13:42:46 -04:00
const int32 NumInstanceSceneDataEntries = PrimitiveSceneInfo - > GetNumInstanceSceneDataEntries ( ) ;
if ( NumInstanceSceneDataEntries > = 8u )
2021-01-21 13:38:01 -04:00
{
2021-06-14 13:42:46 -04:00
InstanceRangesLarge . Add ( FInstanceSceneDataRange { PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) , NumInstanceSceneDataEntries } ) ;
2021-01-21 13:38:01 -04:00
}
else
{
2021-06-14 13:42:46 -04:00
InstanceRangesSmall . Add ( FInstanceSceneDataRange { PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) , NumInstanceSceneDataEntries } ) ;
2021-01-21 13:38:01 -04:00
}
2020-08-25 10:06:54 -04:00
}
}
2021-01-21 13:38:01 -04:00
ProcessInstanceRangeInvalidation ( GraphBuilder , InstanceRangesLarge , InstanceRangesSmall , GPUScene ) ;
2020-08-25 10:06:54 -04:00
}
}
2020-10-27 13:40:36 -04:00
void FVirtualShadowMapArrayCacheManager : : ProcessPrimitivesToUpdate ( FRDGBuilder & GraphBuilder , const FScene & Scene )
2020-08-25 10:06:54 -04:00
{
const FGPUScene & GPUScene = Scene . GPUScene ;
if ( IsValid ( ) & & GPUScene . PrimitivesToUpdate . Num ( ) > 0 )
{
// TODO: As a slight CPU optimization just pass primitive ID list and use instance ranges stored in GPU scene
2021-06-14 13:42:46 -04:00
TArray < FInstanceSceneDataRange , SceneRenderingAllocator > InstanceRangesLarge ;
TArray < FInstanceSceneDataRange , SceneRenderingAllocator > InstanceRangesSmall ;
2021-06-10 15:46:35 -04:00
2020-08-25 10:06:54 -04:00
for ( const int32 PrimitiveId : GPUScene . PrimitivesToUpdate )
{
2021-06-10 15:46:35 -04:00
// There may possibly be IDs that are out of range if they were marked for update and then removed.
if ( PrimitiveId < Scene . Primitives . Num ( ) )
2020-08-25 10:06:54 -04:00
{
2021-06-10 15:46:35 -04:00
EPrimitiveDirtyState PrimitiveDirtyState = GPUScene . GetPrimitiveDirtyState ( PrimitiveId ) ;
// SKIP if marked for Add, because this means it has no previous location to invalidate.
// SKIP if transform has not changed, as this means no invalidation needs to take place.
if ( ! EnumHasAnyFlags ( PrimitiveDirtyState , EPrimitiveDirtyState : : Added ) & & EnumHasAnyFlags ( PrimitiveDirtyState , EPrimitiveDirtyState : : ChangedTransform ) )
2020-08-25 10:06:54 -04:00
{
2021-06-10 15:46:35 -04:00
const FPrimitiveSceneInfo * PrimitiveSceneInfo = Scene . Primitives [ PrimitiveId ] ;
2021-06-14 13:42:46 -04:00
if ( PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) ! = INDEX_NONE )
2021-01-21 13:38:01 -04:00
{
2021-06-14 13:42:46 -04:00
int32 NumInstanceSceneDataEntries = PrimitiveSceneInfo - > GetNumInstanceSceneDataEntries ( ) ;
if ( NumInstanceSceneDataEntries > = 8u )
2021-06-10 15:46:35 -04:00
{
2021-06-14 13:42:46 -04:00
InstanceRangesLarge . Add ( FInstanceSceneDataRange { PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) , NumInstanceSceneDataEntries } ) ;
2021-06-10 15:46:35 -04:00
}
else
{
2021-06-14 13:42:46 -04:00
InstanceRangesSmall . Add ( FInstanceSceneDataRange { PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) , NumInstanceSceneDataEntries } ) ;
2021-06-10 15:46:35 -04:00
}
2021-01-21 13:38:01 -04:00
}
2020-08-25 10:06:54 -04:00
}
}
}
2021-01-21 13:38:01 -04:00
ProcessInstanceRangeInvalidation ( GraphBuilder , InstanceRangesLarge , InstanceRangesSmall , GPUScene ) ;
2020-08-25 10:06:54 -04:00
}
}
/**
* Compute shader to project and invalidate the rectangles of given instances .
*/
class FVirtualSmInvalidateInstancePagesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER ( FVirtualSmInvalidateInstancePagesCS ) ;
SHADER_USE_PARAMETER_STRUCT ( FVirtualSmInvalidateInstancePagesCS , FGlobalShader )
2021-01-21 13:38:01 -04:00
class FLargeSmallDim : SHADER_PERMUTATION_BOOL ( " PROCESS_LARGE_INSTANCE_COUNT_RANGES " ) ;
using FPermutationDomain = TShaderPermutationDomain < FLargeSmallDim > ;
2020-08-25 10:06:54 -04:00
public :
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
2021-03-08 23:14:54 -04:00
SHADER_PARAMETER_RDG_UNIFORM_BUFFER ( FVirtualShadowMapUniformParameters , VirtualShadowMap )
2021-06-14 13:42:46 -04:00
SHADER_PARAMETER_RDG_BUFFER_SRV ( StructuredBuffer < FInstanceSceneDataRange > , InstanceSceneRanges )
2020-08-25 10:06:54 -04:00
SHADER_PARAMETER ( uint32 , NumRemovedItems )
SHADER_PARAMETER_RDG_BUFFER_SRV ( StructuredBuffer < uint > , PageFlags )
SHADER_PARAMETER_RDG_BUFFER_SRV ( StructuredBuffer < uint > , HPageFlags )
SHADER_PARAMETER_RDG_BUFFER_SRV ( StructuredBuffer < uint4 > , PageRectBounds )
SHADER_PARAMETER_RDG_BUFFER_UAV ( RWStructuredBuffer < uint > , OutDynamicCasterFlags )
SHADER_PARAMETER_SRV ( StructuredBuffer < float4 > , GPUSceneInstanceSceneData )
SHADER_PARAMETER_SRV ( StructuredBuffer < float4 > , GPUScenePrimitiveSceneData )
SHADER_PARAMETER ( uint32 , GPUSceneFrameNumber )
2021-06-14 13:42:46 -04:00
SHADER_PARAMETER ( uint32 , InstanceSceneDataSOAStride )
2020-08-25 10:06:54 -04:00
END_SHADER_PARAMETER_STRUCT ( )
static constexpr int Cs1dGroupSizeX = 64 ;
static bool ShouldCompilePermutation ( const FGlobalShaderPermutationParameters & Parameters )
{
return IsFeatureLevelSupported ( Parameters . Platform , ERHIFeatureLevel : : SM5 ) ;
}
static void ModifyCompilationEnvironment ( const FGlobalShaderPermutationParameters & Parameters , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Parameters , OutEnvironment ) ;
FVirtualShadowMapArray : : SetShaderDefines ( OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " CS_1D_GROUP_SIZE_X " ) , Cs1dGroupSizeX ) ;
OutEnvironment . SetDefine ( TEXT ( " USE_GLOBAL_GPU_SCENE_DATA " ) , 1 ) ;
OutEnvironment . SetDefine ( TEXT ( " VF_SUPPORTS_PRIMITIVE_SCENE_DATA " ) , 1 ) ;
// OutEnvironment.SetDefine(TEXT("MAX_STAT_FRAMES"), FVirtualShadowMapArrayCacheManager::MaxStatFrames);
}
} ;
IMPLEMENT_GLOBAL_SHADER ( FVirtualSmInvalidateInstancePagesCS , " /Engine/Private/VirtualShadowMaps/CacheManagement.usf " , " VirtualSmInvalidateInstancePagesCS " , SF_Compute ) ;
2021-03-08 23:14:54 -04:00
TRDGUniformBufferRef < FVirtualShadowMapUniformParameters > FVirtualShadowMapArrayCacheManager : : GetPreviousUniformBuffer ( FRDGBuilder & GraphBuilder ) const
{
FVirtualShadowMapUniformParameters * VersionedParameters = GraphBuilder . AllocParameters < FVirtualShadowMapUniformParameters > ( ) ;
* VersionedParameters = PrevUniformParameters ;
return GraphBuilder . CreateUniformBuffer ( VersionedParameters ) ;
}
2021-06-14 13:42:46 -04:00
void FVirtualShadowMapArrayCacheManager : : ProcessInstanceRangeInvalidation ( FRDGBuilder & GraphBuilder , const TArray < FInstanceSceneDataRange , SceneRenderingAllocator > & InstanceRangesLarge , const TArray < FInstanceSceneDataRange , SceneRenderingAllocator > & InstanceRangesSmall , const FGPUScene & GPUScene )
2020-08-25 10:06:54 -04:00
{
2021-03-08 23:14:54 -04:00
auto RegExtCreateSrv = [ & GraphBuilder ] ( const TRefCountPtr < FRDGPooledBuffer > & Buffer , const TCHAR * Name ) - > FRDGBufferSRVRef
{
return GraphBuilder . CreateSRV ( GraphBuilder . RegisterExternalBuffer ( Buffer , Name ) ) ;
} ;
// Update references in our last frame uniform buffer with reimported resources for this frame
2021-03-23 21:23:57 -04:00
PrevUniformParameters . ProjectionData = RegExtCreateSrv ( PrevBuffers . ShadowMapProjectionDataBuffer , TEXT ( " Shadow.Virtual.PrevProjectionData " ) ) ;
PrevUniformParameters . PageTable = RegExtCreateSrv ( PrevBuffers . PageTable , TEXT ( " Shadow.Virtual.PrevPageTable " ) ) ;
2021-03-08 23:14:54 -04:00
// Unused in this path
2021-05-20 13:24:00 -04:00
PrevUniformParameters . PhysicalPagePool = GSystemTextures . GetZeroUIntDummy ( GraphBuilder ) ;
PrevUniformParameters . PhysicalPagePoolHw = GSystemTextures . GetBlackDummy ( GraphBuilder ) ;
2021-03-08 23:14:54 -04:00
2021-05-25 20:46:17 -04:00
FRDGBufferRef InstanceRangesSmallRDG = ! InstanceRangesSmall . IsEmpty ( ) ? CreateStructuredBuffer ( GraphBuilder , TEXT ( " Shadow.Virtual.InstanceRangesSmall " ) , InstanceRangesSmall ) : nullptr ;
FRDGBufferRef InstanceRangesLargeRDG = ! InstanceRangesLarge . IsEmpty ( ) ? CreateStructuredBuffer ( GraphBuilder , TEXT ( " Shadow.Virtual.InstanceRangesSmall " ) , InstanceRangesLarge ) : nullptr ;
2021-05-05 13:20:09 -04:00
2021-01-21 13:38:01 -04:00
if ( InstanceRangesSmall . Num ( ) )
2020-08-25 10:06:54 -04:00
{
2021-01-21 13:38:01 -04:00
RDG_EVENT_SCOPE ( GraphBuilder , " ProcessInstanceRangeInvalidation [%d small-ranges] " , InstanceRangesSmall . Num ( ) ) ;
2020-10-27 13:40:36 -04:00
2020-11-09 15:47:39 -04:00
FVirtualSmInvalidateInstancePagesCS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FVirtualSmInvalidateInstancePagesCS : : FParameters > ( ) ;
2021-03-08 23:14:54 -04:00
PassParameters - > VirtualShadowMap = GetPreviousUniformBuffer ( GraphBuilder ) ;
2021-05-05 13:20:09 -04:00
2021-06-14 13:42:46 -04:00
PassParameters - > InstanceSceneRanges = GraphBuilder . CreateSRV ( InstanceRangesSmallRDG ) ;
2021-01-21 13:38:01 -04:00
PassParameters - > NumRemovedItems = InstanceRangesSmall . Num ( ) ;
2020-08-25 10:06:54 -04:00
2021-03-23 21:23:57 -04:00
PassParameters - > PageFlags = RegExtCreateSrv ( PrevBuffers . PageFlags , TEXT ( " Shadow.Virtual.PrevPageFlags " ) ) ;
PassParameters - > HPageFlags = RegExtCreateSrv ( PrevBuffers . HPageFlags , TEXT ( " Shadow.Virtual.PrevHPageFlags " ) ) ;
PassParameters - > PageRectBounds = RegExtCreateSrv ( PrevBuffers . PageRectBounds , TEXT ( " Shadow.Virtual.PrevPageRectBounds " ) ) ;
2020-08-25 10:06:54 -04:00
2021-03-23 21:23:57 -04:00
FRDGBufferRef DynamicCasterFlagsRDG = GraphBuilder . RegisterExternalBuffer ( PrevBuffers . DynamicCasterPageFlags , TEXT ( " Shadow.Virtual.PrevDynamicCasterFlags " ) ) ;
2020-10-27 13:40:36 -04:00
PassParameters - > OutDynamicCasterFlags = GraphBuilder . CreateUAV ( DynamicCasterFlagsRDG ) ;
2020-08-25 10:06:54 -04:00
2021-06-14 13:42:46 -04:00
PassParameters - > GPUSceneInstanceSceneData = GPUScene . InstanceSceneDataBuffer . SRV ;
2020-10-27 13:40:36 -04:00
PassParameters - > GPUScenePrimitiveSceneData = GPUScene . PrimitiveBuffer . SRV ;
2020-11-19 05:23:44 -04:00
PassParameters - > GPUSceneFrameNumber = GPUScene . GetSceneFrameNumber ( ) ;
2021-06-14 13:42:46 -04:00
PassParameters - > InstanceSceneDataSOAStride = GPUScene . InstanceSceneDataSOAStride ;
2020-08-25 10:06:54 -04:00
2021-01-21 13:38:01 -04:00
FVirtualSmInvalidateInstancePagesCS : : FPermutationDomain PermutationVector ;
PermutationVector . Set < FVirtualSmInvalidateInstancePagesCS : : FLargeSmallDim > ( 0 ) ;
auto ComputeShader = GetGlobalShaderMap ( GMaxRHIFeatureLevel ) - > GetShader < FVirtualSmInvalidateInstancePagesCS > ( PermutationVector ) ;
2020-08-25 10:06:54 -04:00
2020-10-27 13:40:36 -04:00
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " VirtualSmInvalidateInstancePagesCS " ) ,
ComputeShader ,
PassParameters ,
2021-01-21 13:38:01 -04:00
FIntVector ( FMath : : DivideAndRoundUp ( InstanceRangesSmall . Num ( ) , FVirtualSmInvalidateInstancePagesCS : : Cs1dGroupSizeX ) , 1 , 1 )
) ;
}
if ( InstanceRangesLarge . Num ( ) )
{
RDG_EVENT_SCOPE ( GraphBuilder , " ProcessInstanceRangeInvalidation [%d large-ranges] " , InstanceRangesLarge . Num ( ) ) ;
FVirtualSmInvalidateInstancePagesCS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FVirtualSmInvalidateInstancePagesCS : : FParameters > ( ) ;
2021-03-08 23:14:54 -04:00
PassParameters - > VirtualShadowMap = GetPreviousUniformBuffer ( GraphBuilder ) ;
2021-06-14 13:42:46 -04:00
PassParameters - > InstanceSceneRanges = GraphBuilder . CreateSRV ( InstanceRangesLargeRDG ) ;
2021-01-21 13:38:01 -04:00
PassParameters - > NumRemovedItems = InstanceRangesLarge . Num ( ) ;
2021-03-23 21:23:57 -04:00
PassParameters - > PageFlags = RegExtCreateSrv ( PrevBuffers . PageFlags , TEXT ( " Shadow.Virtual.PrevPageFlags " ) ) ;
PassParameters - > HPageFlags = RegExtCreateSrv ( PrevBuffers . HPageFlags , TEXT ( " Shadow.Virtual.PrevHPageFlags " ) ) ;
PassParameters - > PageRectBounds = RegExtCreateSrv ( PrevBuffers . PageRectBounds , TEXT ( " Shadow.Virtual.PrevPageRectBounds " ) ) ;
2021-01-21 13:38:01 -04:00
2021-03-23 21:23:57 -04:00
FRDGBufferRef DynamicCasterFlagsRDG = GraphBuilder . RegisterExternalBuffer ( PrevBuffers . DynamicCasterPageFlags , TEXT ( " Shadow.Virtual.PrevDynamicCasterFlags " ) ) ;
2021-01-21 13:38:01 -04:00
PassParameters - > OutDynamicCasterFlags = GraphBuilder . CreateUAV ( DynamicCasterFlagsRDG ) ;
2021-06-14 13:42:46 -04:00
PassParameters - > GPUSceneInstanceSceneData = GPUScene . InstanceSceneDataBuffer . SRV ;
2021-01-21 13:38:01 -04:00
PassParameters - > GPUScenePrimitiveSceneData = GPUScene . PrimitiveBuffer . SRV ;
PassParameters - > GPUSceneFrameNumber = GPUScene . GetSceneFrameNumber ( ) ;
2021-06-14 13:42:46 -04:00
PassParameters - > InstanceSceneDataSOAStride = GPUScene . InstanceSceneDataSOAStride ;
2021-01-21 13:38:01 -04:00
FVirtualSmInvalidateInstancePagesCS : : FPermutationDomain PermutationVector ;
PermutationVector . Set < FVirtualSmInvalidateInstancePagesCS : : FLargeSmallDim > ( 1 ) ;
auto ComputeShader = GetGlobalShaderMap ( GMaxRHIFeatureLevel ) - > GetShader < FVirtualSmInvalidateInstancePagesCS > ( PermutationVector ) ;
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " VirtualSmInvalidateInstancePagesCS " ) ,
ComputeShader ,
PassParameters ,
FIntVector ( InstanceRangesLarge . Num ( ) , 1 , 1 )
2020-10-27 13:40:36 -04:00
) ;
2020-08-25 10:06:54 -04:00
}
}