2015-01-29 14:46:20 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
DistanceFieldSurfaceCacheLighting . cpp
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2015-02-02 12:03:53 -05:00
# include "RendererPrivate.h"
2015-03-30 17:48:16 -04:00
# include "RendererPrivate.h"
# include "ScenePrivate.h"
# include "UniformBuffer.h"
# include "ShaderParameters.h"
# include "DistanceFieldLightingShared.h"
# include "DistanceFieldSurfaceCacheLighting.h"
# include "DistanceFieldGlobalIllumination.h"
# include "RHICommandList.h"
# include "SceneUtils.h"
2015-02-02 12:03:53 -05:00
2015-01-29 14:46:20 -05:00
float GAOMaxObjectBoundingRadius = 50000 ;
FAutoConsoleVariableRef CVarAOMaxObjectBoundingRadius (
TEXT ( " r.AOMaxObjectBoundingRadius " ) ,
GAOMaxObjectBoundingRadius ,
TEXT ( " Objects larger than this will not contribute to AO calculations, to improve performance. " ) ,
ECVF_Cheat | ECVF_RenderThreadSafe
) ;
2015-02-19 16:20:29 -05:00
int32 GAOLogObjectBufferReallocation = 0 ;
FAutoConsoleVariableRef CVarAOLogObjectBufferReallocation (
TEXT ( " r.AOLogObjectBufferReallocation " ) ,
GAOLogObjectBufferReallocation ,
TEXT ( " " ) ,
ECVF_Cheat | ECVF_RenderThreadSafe
) ;
2015-01-29 14:46:20 -05:00
// Must match equivalent shader defines
int32 FDistanceFieldObjectBuffers : : ObjectDataStride = 16 ;
int32 FDistanceFieldCulledObjectBuffers : : ObjectDataStride = 16 ;
int32 FDistanceFieldCulledObjectBuffers : : ObjectBoxBoundsStride = 5 ;
// In float4's. Must match corresponding usf definition
int32 UploadObjectDataStride = 1 + FDistanceFieldObjectBuffers : : ObjectDataStride ;
class FDistanceFieldUploadDataResource : public FRenderResource
{
public :
FCPUUpdatedBuffer UploadData ;
FDistanceFieldUploadDataResource ( )
{
UploadData . Format = PF_A32B32G32R32F ;
UploadData . Stride = UploadObjectDataStride ;
}
virtual void InitDynamicRHI ( ) override
{
UploadData . Initialize ( ) ;
}
virtual void ReleaseDynamicRHI ( ) override
{
UploadData . Release ( ) ;
}
} ;
TGlobalResource < FDistanceFieldUploadDataResource > GDistanceFieldUploadData ;
class FDistanceFieldUploadIndicesResource : public FRenderResource
{
public :
FCPUUpdatedBuffer UploadIndices ;
FDistanceFieldUploadIndicesResource ( )
{
UploadIndices . Format = PF_R32_UINT ;
UploadIndices . Stride = 1 ;
}
virtual void InitDynamicRHI ( ) override
{
UploadIndices . Initialize ( ) ;
}
virtual void ReleaseDynamicRHI ( ) override
{
UploadIndices . Release ( ) ;
}
} ;
TGlobalResource < FDistanceFieldUploadIndicesResource > GDistanceFieldUploadIndices ;
class FDistanceFieldRemoveIndicesResource : public FRenderResource
{
public :
FCPUUpdatedBuffer RemoveIndices ;
FDistanceFieldRemoveIndicesResource ( )
{
RemoveIndices . Format = PF_R32G32B32A32_UINT ;
RemoveIndices . Stride = 1 ;
}
virtual void InitDynamicRHI ( ) override
{
RemoveIndices . Initialize ( ) ;
}
virtual void ReleaseDynamicRHI ( ) override
{
RemoveIndices . Release ( ) ;
}
} ;
TGlobalResource < FDistanceFieldRemoveIndicesResource > GDistanceFieldRemoveIndices ;
uint32 UpdateObjectsGroupSize = 64 ;
class FUploadObjectsToBufferCS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FUploadObjectsToBufferCS , Global )
public :
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM5 ) & & DoesPlatformSupportDistanceFieldAO ( Platform ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " UPDATEOBJECTS_THREADGROUP_SIZE " ) , UpdateObjectsGroupSize ) ;
}
FUploadObjectsToBufferCS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
NumUploadOperations . Bind ( Initializer . ParameterMap , TEXT ( " NumUploadOperations " ) ) ;
UploadOperationIndices . Bind ( Initializer . ParameterMap , TEXT ( " UploadOperationIndices " ) ) ;
UploadOperationData . Bind ( Initializer . ParameterMap , TEXT ( " UploadOperationData " ) ) ;
ObjectBufferParameters . Bind ( Initializer . ParameterMap ) ;
}
FUploadObjectsToBufferCS ( )
{
}
void SetParameters ( FRHICommandList & RHICmdList , const FScene * Scene , uint32 NumUploadOperationsValue , FShaderResourceViewRHIParamRef InUploadOperationIndices , FShaderResourceViewRHIParamRef InUploadOperationData )
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader ( ) ;
SetShaderValue ( RHICmdList , ShaderRHI , NumUploadOperations , NumUploadOperationsValue ) ;
SetSRVParameter ( RHICmdList , ShaderRHI , UploadOperationIndices , InUploadOperationIndices ) ;
SetSRVParameter ( RHICmdList , ShaderRHI , UploadOperationData , InUploadOperationData ) ;
ObjectBufferParameters . Set ( RHICmdList , ShaderRHI , * ( Scene - > DistanceFieldSceneData . ObjectBuffers ) , Scene - > DistanceFieldSceneData . NumObjectsInBuffer ) ;
}
void UnsetParameters ( FRHICommandList & RHICmdList )
{
ObjectBufferParameters . UnsetParameters ( RHICmdList , GetComputeShader ( ) ) ;
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-01-29 14:46:20 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < NumUploadOperations ;
Ar < < UploadOperationIndices ;
Ar < < UploadOperationData ;
Ar < < ObjectBufferParameters ;
return bShaderHasOutdatedParameters ;
}
private :
FShaderParameter NumUploadOperations ;
FShaderResourceParameter UploadOperationIndices ;
FShaderResourceParameter UploadOperationData ;
FDistanceFieldObjectBufferParameters ObjectBufferParameters ;
} ;
IMPLEMENT_SHADER_TYPE ( , FUploadObjectsToBufferCS , TEXT ( " DistanceFieldSurfaceCacheLightingCompute " ) , TEXT ( " UploadObjectsToBufferCS " ) , SF_Compute ) ;
class FCopyObjectBufferCS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FCopyObjectBufferCS , Global )
public :
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM5 ) & & DoesPlatformSupportDistanceFieldAO ( Platform ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " UPDATEOBJECTS_THREADGROUP_SIZE " ) , UpdateObjectsGroupSize ) ;
}
FCopyObjectBufferCS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
CopyObjectBounds . Bind ( Initializer . ParameterMap , TEXT ( " CopyObjectBounds " ) ) ;
CopyObjectData . Bind ( Initializer . ParameterMap , TEXT ( " CopyObjectData " ) ) ;
ObjectBufferParameters . Bind ( Initializer . ParameterMap ) ;
}
FCopyObjectBufferCS ( )
{
}
void SetParameters ( FRHICommandList & RHICmdList , FDistanceFieldObjectBuffers & ObjectBuffersSource , FDistanceFieldObjectBuffers & ObjectBuffersDest , int32 NumObjectsValue )
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader ( ) ;
CopyObjectBounds . SetBuffer ( RHICmdList , ShaderRHI , ObjectBuffersDest . Bounds ) ;
CopyObjectData . SetBuffer ( RHICmdList , ShaderRHI , ObjectBuffersDest . Data ) ;
ObjectBufferParameters . Set ( RHICmdList , ShaderRHI , ObjectBuffersSource , NumObjectsValue ) ;
}
void UnsetParameters ( FRHICommandList & RHICmdList )
{
ObjectBufferParameters . UnsetParameters ( RHICmdList , GetComputeShader ( ) ) ;
CopyObjectBounds . UnsetUAV ( RHICmdList , GetComputeShader ( ) ) ;
CopyObjectData . UnsetUAV ( RHICmdList , GetComputeShader ( ) ) ;
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-01-29 14:46:20 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < CopyObjectBounds ;
Ar < < CopyObjectData ;
Ar < < ObjectBufferParameters ;
return bShaderHasOutdatedParameters ;
}
private :
FRWShaderParameter CopyObjectBounds ;
FRWShaderParameter CopyObjectData ;
FDistanceFieldObjectBufferParameters ObjectBufferParameters ;
} ;
IMPLEMENT_SHADER_TYPE ( , FCopyObjectBufferCS , TEXT ( " DistanceFieldSurfaceCacheLightingCompute " ) , TEXT ( " CopyObjectBufferCS " ) , SF_Compute ) ;
class FCopySurfelBufferCS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FCopySurfelBufferCS , Global )
public :
static bool ShouldCache ( EShaderPlatform Platform )
{
2015-03-30 17:48:16 -04:00
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM5 ) & & DoesPlatformSupportDistanceFieldGI ( Platform ) ;
2015-01-29 14:46:20 -05:00
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " UPDATEOBJECTS_THREADGROUP_SIZE " ) , UpdateObjectsGroupSize ) ;
}
FCopySurfelBufferCS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
CopyInterpolatedVertexData . Bind ( Initializer . ParameterMap , TEXT ( " CopyInterpolatedVertexData " ) ) ;
CopySurfelData . Bind ( Initializer . ParameterMap , TEXT ( " CopySurfelData " ) ) ;
SurfelBufferParameters . Bind ( Initializer . ParameterMap ) ;
NumSurfels . Bind ( Initializer . ParameterMap , TEXT ( " NumSurfels " ) ) ;
}
FCopySurfelBufferCS ( )
{
}
void SetParameters ( FRHICommandList & RHICmdList , const FSurfelBuffers & SurfelBuffersSource , const FInstancedSurfelBuffers & InstancedSurfelBuffersSource , FSurfelBuffers & SurfelBuffersDest , int32 NumSurfelsValue )
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader ( ) ;
CopyInterpolatedVertexData . SetBuffer ( RHICmdList , ShaderRHI , SurfelBuffersDest . InterpolatedVertexData ) ;
CopySurfelData . SetBuffer ( RHICmdList , ShaderRHI , SurfelBuffersDest . Surfels ) ;
SurfelBufferParameters . Set ( RHICmdList , ShaderRHI , SurfelBuffersSource , InstancedSurfelBuffersSource ) ;
SetShaderValue ( RHICmdList , ShaderRHI , NumSurfels , NumSurfelsValue ) ;
}
void UnsetParameters ( FRHICommandList & RHICmdList )
{
SurfelBufferParameters . UnsetParameters ( RHICmdList , GetComputeShader ( ) ) ;
CopyInterpolatedVertexData . UnsetUAV ( RHICmdList , GetComputeShader ( ) ) ;
CopySurfelData . UnsetUAV ( RHICmdList , GetComputeShader ( ) ) ;
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-01-29 14:46:20 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < CopyInterpolatedVertexData ;
Ar < < CopySurfelData ;
Ar < < SurfelBufferParameters ;
Ar < < NumSurfels ;
return bShaderHasOutdatedParameters ;
}
private :
FRWShaderParameter CopyInterpolatedVertexData ;
FRWShaderParameter CopySurfelData ;
FSurfelBufferParameters SurfelBufferParameters ;
FShaderParameter NumSurfels ;
} ;
IMPLEMENT_SHADER_TYPE ( , FCopySurfelBufferCS , TEXT ( " SurfelTree " ) , TEXT ( " CopySurfelBufferCS " ) , SF_Compute ) ;
class FCopyVPLFluxBufferCS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FCopyVPLFluxBufferCS , Global )
public :
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM5 ) & & DoesPlatformSupportDistanceFieldAO ( Platform ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " UPDATEOBJECTS_THREADGROUP_SIZE " ) , UpdateObjectsGroupSize ) ;
}
FCopyVPLFluxBufferCS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
CopyVPLFlux . Bind ( Initializer . ParameterMap , TEXT ( " CopyVPLFlux " ) ) ;
SurfelBufferParameters . Bind ( Initializer . ParameterMap ) ;
NumSurfels . Bind ( Initializer . ParameterMap , TEXT ( " NumSurfels " ) ) ;
}
FCopyVPLFluxBufferCS ( )
{
}
void SetParameters ( FRHICommandList & RHICmdList , const FSurfelBuffers & SurfelBuffersSource , const FInstancedSurfelBuffers & InstancedSurfelBuffersSource , FInstancedSurfelBuffers & InstancedSurfelBuffersDest , int32 NumSurfelsValue )
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader ( ) ;
CopyVPLFlux . SetBuffer ( RHICmdList , ShaderRHI , InstancedSurfelBuffersDest . VPLFlux ) ;
SurfelBufferParameters . Set ( RHICmdList , ShaderRHI , SurfelBuffersSource , InstancedSurfelBuffersSource ) ;
SetShaderValue ( RHICmdList , ShaderRHI , NumSurfels , NumSurfelsValue ) ;
}
void UnsetParameters ( FRHICommandList & RHICmdList )
{
SurfelBufferParameters . UnsetParameters ( RHICmdList , GetComputeShader ( ) ) ;
CopyVPLFlux . UnsetUAV ( RHICmdList , GetComputeShader ( ) ) ;
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-01-29 14:46:20 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < CopyVPLFlux ;
Ar < < SurfelBufferParameters ;
Ar < < NumSurfels ;
return bShaderHasOutdatedParameters ;
}
private :
FRWShaderParameter CopyVPLFlux ;
FSurfelBufferParameters SurfelBufferParameters ;
FShaderParameter NumSurfels ;
} ;
IMPLEMENT_SHADER_TYPE ( , FCopyVPLFluxBufferCS , TEXT ( " SurfelTree " ) , TEXT ( " CopyVPLFluxBufferCS " ) , SF_Compute ) ;
template < bool bRemoveFromSameBuffer >
class TRemoveObjectsFromBufferCS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( TRemoveObjectsFromBufferCS , Global )
public :
static bool ShouldCache ( EShaderPlatform Platform )
{
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM5 ) & & DoesPlatformSupportDistanceFieldAO ( Platform ) ;
}
static void ModifyCompilationEnvironment ( EShaderPlatform Platform , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Platform , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " UPDATEOBJECTS_THREADGROUP_SIZE " ) , UpdateObjectsGroupSize ) ;
OutEnvironment . SetDefine ( TEXT ( " REMOVE_FROM_SAME_BUFFER " ) , bRemoveFromSameBuffer ? TEXT ( " 1 " ) : TEXT ( " 0 " ) ) ;
}
TRemoveObjectsFromBufferCS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer )
: FGlobalShader ( Initializer )
{
NumRemoveOperations . Bind ( Initializer . ParameterMap , TEXT ( " NumRemoveOperations " ) ) ;
RemoveOperationIndices . Bind ( Initializer . ParameterMap , TEXT ( " RemoveOperationIndices " ) ) ;
ObjectBufferParameters . Bind ( Initializer . ParameterMap ) ;
ObjectBounds2 . Bind ( Initializer . ParameterMap , TEXT ( " ObjectBounds2 " ) ) ;
ObjectData2 . Bind ( Initializer . ParameterMap , TEXT ( " ObjectData2 " ) ) ;
}
TRemoveObjectsFromBufferCS ( )
{
}
void SetParameters (
FRHICommandList & RHICmdList ,
const FScene * Scene ,
uint32 NumRemoveOperationsValue ,
FShaderResourceViewRHIParamRef InRemoveOperationIndices ,
FShaderResourceViewRHIParamRef InObjectBounds2 ,
FShaderResourceViewRHIParamRef InObjectData2 )
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader ( ) ;
SetShaderValue ( RHICmdList , ShaderRHI , NumRemoveOperations , NumRemoveOperationsValue ) ;
SetSRVParameter ( RHICmdList , ShaderRHI , RemoveOperationIndices , InRemoveOperationIndices ) ;
ObjectBufferParameters . Set ( RHICmdList , ShaderRHI , * ( Scene - > DistanceFieldSceneData . ObjectBuffers ) , Scene - > DistanceFieldSceneData . NumObjectsInBuffer ) ;
SetSRVParameter ( RHICmdList , ShaderRHI , ObjectBounds2 , InObjectBounds2 ) ;
SetSRVParameter ( RHICmdList , ShaderRHI , ObjectData2 , InObjectData2 ) ;
}
void UnsetParameters ( FRHICommandList & RHICmdList )
{
ObjectBufferParameters . UnsetParameters ( RHICmdList , GetComputeShader ( ) ) ;
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2015-01-29 14:46:20 -05:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < NumRemoveOperations ;
Ar < < RemoveOperationIndices ;
Ar < < ObjectBufferParameters ;
Ar < < ObjectBounds2 ;
Ar < < ObjectData2 ;
return bShaderHasOutdatedParameters ;
}
private :
FShaderParameter NumRemoveOperations ;
FShaderResourceParameter RemoveOperationIndices ;
FDistanceFieldObjectBufferParameters ObjectBufferParameters ;
FShaderResourceParameter ObjectBounds2 ;
FShaderResourceParameter ObjectData2 ;
} ;
IMPLEMENT_SHADER_TYPE ( template < > , TRemoveObjectsFromBufferCS < true > , TEXT ( " DistanceFieldSurfaceCacheLightingCompute " ) , TEXT ( " RemoveObjectsFromBufferCS " ) , SF_Compute ) ;
IMPLEMENT_SHADER_TYPE ( template < > , TRemoveObjectsFromBufferCS < false > , TEXT ( " DistanceFieldSurfaceCacheLightingCompute " ) , TEXT ( " RemoveObjectsFromBufferCS " ) , SF_Compute ) ;
void FSurfelBufferAllocator : : RemovePrimitive ( const FPrimitiveSceneInfo * Primitive )
{
FPrimitiveSurfelAllocation Allocation ;
if ( Allocations . RemoveAndCopyValue ( Primitive , Allocation ) )
{
bool bMergedWithExisting = false ;
FPrimitiveSurfelFreeEntry FreeEntry ( Allocation . Offset , Allocation . GetTotalNumSurfels ( ) ) ;
// Note: only does one merge
//@todo - keep free list sorted then can binary search
for ( int32 FreeIndex = 0 ; FreeIndex < FreeList . Num ( ) ; FreeIndex + + )
{
if ( FreeList [ FreeIndex ] . Offset = = FreeEntry . Offset + FreeEntry . NumSurfels )
{
FreeList [ FreeIndex ] . Offset = FreeEntry . Offset ;
FreeList [ FreeIndex ] . NumSurfels + = FreeEntry . NumSurfels ;
bMergedWithExisting = true ;
break ;
}
else if ( FreeList [ FreeIndex ] . Offset + FreeList [ FreeIndex ] . NumSurfels = = FreeEntry . Offset )
{
FreeList [ FreeIndex ] . NumSurfels + = FreeEntry . NumSurfels ;
bMergedWithExisting = true ;
break ;
}
}
if ( ! bMergedWithExisting )
{
FreeList . Add ( FreeEntry ) ;
}
}
}
void FSurfelBufferAllocator : : AddPrimitive ( const FPrimitiveSceneInfo * PrimitiveSceneInfo , int32 PrimitiveLOD0Surfels , int32 PrimitiveNumSurfels , int32 NumInstances )
{
int32 BestFreeAllocationIndex = - 1 ;
for ( int32 FreeIndex = 0 ; FreeIndex < FreeList . Num ( ) ; FreeIndex + + )
{
const FPrimitiveSurfelFreeEntry & CurrentFreeEntry = FreeList [ FreeIndex ] ;
if ( CurrentFreeEntry . NumSurfels > = PrimitiveNumSurfels * NumInstances
& & ( BestFreeAllocationIndex = = - 1
| | CurrentFreeEntry . NumSurfels < FreeList [ BestFreeAllocationIndex ] . NumSurfels ) )
{
BestFreeAllocationIndex = FreeIndex ;
}
}
if ( BestFreeAllocationIndex ! = - 1 )
{
FPrimitiveSurfelFreeEntry FreeEntry = FreeList [ BestFreeAllocationIndex ] ;
if ( FreeEntry . NumSurfels = = PrimitiveNumSurfels * NumInstances )
{
// Existing allocation matches exactly, remove it from the free list
FreeList . RemoveAtSwap ( BestFreeAllocationIndex ) ;
}
else
{
// Replace with the remaining free range
FreeList [ BestFreeAllocationIndex ] = FPrimitiveSurfelFreeEntry ( FreeEntry . Offset + PrimitiveNumSurfels * NumInstances , FreeEntry . NumSurfels - PrimitiveNumSurfels * NumInstances ) ;
}
Allocations . Add ( PrimitiveSceneInfo , FPrimitiveSurfelAllocation ( FreeEntry . Offset , PrimitiveLOD0Surfels , PrimitiveNumSurfels , NumInstances ) ) ;
}
else
{
// Add a new allocation to the end of the buffer
Allocations . Add ( PrimitiveSceneInfo , FPrimitiveSurfelAllocation ( NumSurfelsInBuffer , PrimitiveLOD0Surfels , PrimitiveNumSurfels , NumInstances ) ) ;
NumSurfelsInBuffer + = PrimitiveNumSurfels * NumInstances ;
}
}
void UpdateGlobalDistanceFieldObjectRemoves ( FRHICommandListImmediate & RHICmdList , FScene * Scene )
{
FDistanceFieldSceneData & DistanceFieldSceneData = Scene - > DistanceFieldSceneData ;
TArray < FIntRect > RemoveObjectIndices ;
FDistanceFieldObjectBuffers * TemporaryCopySourceBuffers = NULL ;
if ( DistanceFieldSceneData . PendingRemoveOperations . Num ( ) > 0 )
{
2015-02-02 15:02:22 -05:00
TArray < int32 , SceneRenderingAllocator > PendingRemoveOperations ;
2015-01-29 14:46:20 -05:00
for ( int32 RemoveIndex = 0 ; RemoveIndex < DistanceFieldSceneData . PendingRemoveOperations . Num ( ) ; RemoveIndex + + )
{
// Can't dereference the primitive here, it has already been deleted
const FPrimitiveSceneInfo * Primitive = DistanceFieldSceneData . PendingRemoveOperations [ RemoveIndex ] . Primitive ;
DistanceFieldSceneData . SurfelAllocations . RemovePrimitive ( Primitive ) ;
DistanceFieldSceneData . InstancedSurfelAllocations . RemovePrimitive ( Primitive ) ;
PendingRemoveOperations . Append ( DistanceFieldSceneData . PendingRemoveOperations [ RemoveIndex ] . DistanceFieldInstanceIndices ) ;
}
check ( DistanceFieldSceneData . NumObjectsInBuffer > = PendingRemoveOperations . Num ( ) ) ;
// Sort from smallest to largest
PendingRemoveOperations . Sort ( ) ;
// We have multiple remove requests enqueued in PendingRemoveOperations, can only use the RemoveAtSwap version when there won't be collisions
const bool bUseRemoveAtSwap = PendingRemoveOperations . Last ( ) < DistanceFieldSceneData . NumObjectsInBuffer - PendingRemoveOperations . Num ( ) ;
if ( bUseRemoveAtSwap )
{
// Remove everything in parallel in the same buffer with a RemoveAtSwap algorithm
for ( int32 RemovePrimitiveIndex = 0 ; RemovePrimitiveIndex < PendingRemoveOperations . Num ( ) ; RemovePrimitiveIndex + + )
{
DistanceFieldSceneData . NumObjectsInBuffer - - ;
const int32 RemoveIndex = PendingRemoveOperations [ RemovePrimitiveIndex ] ;
const int32 MoveFromIndex = DistanceFieldSceneData . NumObjectsInBuffer ;
check ( RemoveIndex ! = MoveFromIndex ) ;
// Queue a compute shader move
RemoveObjectIndices . Add ( FIntRect ( RemoveIndex , MoveFromIndex , 0 , 0 ) ) ;
// Fixup indices of the primitive that is being moved
FPrimitiveAndInstance & PrimitiveAndInstanceBeingMoved = DistanceFieldSceneData . PrimitiveInstanceMapping [ MoveFromIndex ] ;
check ( PrimitiveAndInstanceBeingMoved . Primitive & & PrimitiveAndInstanceBeingMoved . Primitive - > DistanceFieldInstanceIndices . Num ( ) > 0 ) ;
PrimitiveAndInstanceBeingMoved . Primitive - > DistanceFieldInstanceIndices [ PrimitiveAndInstanceBeingMoved . InstanceIndex ] = RemoveIndex ;
DistanceFieldSceneData . PrimitiveInstanceMapping . RemoveAtSwap ( RemoveIndex ) ;
}
}
else
{
2015-02-19 16:20:29 -05:00
const double StartTime = FPlatformTime : : Seconds ( ) ;
2015-01-29 14:46:20 -05:00
// Have to copy the object data to allow parallel removing
TemporaryCopySourceBuffers = DistanceFieldSceneData . ObjectBuffers ;
DistanceFieldSceneData . ObjectBuffers = new FDistanceFieldObjectBuffers ( ) ;
DistanceFieldSceneData . ObjectBuffers - > MaxObjects = TemporaryCopySourceBuffers - > MaxObjects ;
DistanceFieldSceneData . ObjectBuffers - > Initialize ( ) ;
TArray < FPrimitiveAndInstance > OriginalPrimitiveInstanceMapping = DistanceFieldSceneData . PrimitiveInstanceMapping ;
DistanceFieldSceneData . PrimitiveInstanceMapping . Reset ( ) ;
const int32 NumDestObjects = DistanceFieldSceneData . NumObjectsInBuffer - PendingRemoveOperations . Num ( ) ;
int32 SourceIndex = 0 ;
int32 NextPendingRemoveIndex = 0 ;
for ( int32 DestinationIndex = 0 ; DestinationIndex < NumDestObjects ; DestinationIndex + + )
{
while ( NextPendingRemoveIndex < PendingRemoveOperations . Num ( )
& & PendingRemoveOperations [ NextPendingRemoveIndex ] = = SourceIndex )
{
NextPendingRemoveIndex + + ;
SourceIndex + + ;
}
// Queue a compute shader move
RemoveObjectIndices . Add ( FIntRect ( DestinationIndex , SourceIndex , 0 , 0 ) ) ;
// Fixup indices of the primitive that is being moved
FPrimitiveAndInstance & PrimitiveAndInstanceBeingMoved = OriginalPrimitiveInstanceMapping [ SourceIndex ] ;
check ( PrimitiveAndInstanceBeingMoved . Primitive & & PrimitiveAndInstanceBeingMoved . Primitive - > DistanceFieldInstanceIndices . Num ( ) > 0 ) ;
PrimitiveAndInstanceBeingMoved . Primitive - > DistanceFieldInstanceIndices [ PrimitiveAndInstanceBeingMoved . InstanceIndex ] = DestinationIndex ;
check ( DistanceFieldSceneData . PrimitiveInstanceMapping . Num ( ) = = DestinationIndex ) ;
DistanceFieldSceneData . PrimitiveInstanceMapping . Add ( PrimitiveAndInstanceBeingMoved ) ;
SourceIndex + + ;
}
DistanceFieldSceneData . NumObjectsInBuffer = NumDestObjects ;
2015-02-19 16:20:29 -05:00
if ( GAOLogObjectBufferReallocation )
{
const float ElapsedTime = ( float ) ( FPlatformTime : : Seconds ( ) - StartTime ) ;
UE_LOG ( LogDistanceField , Warning , TEXT ( " Global object buffer realloc %.3fs " ) , ElapsedTime ) ;
}
2015-01-29 14:46:20 -05:00
/*
// Have to remove one at a time while any entries to remove are at the end of the buffer
DistanceFieldSceneData . NumObjectsInBuffer - - ;
const int32 RemoveIndex = DistanceFieldSceneData . PendingRemoveOperations [ ParallelConflictIndex ] ;
const int32 MoveFromIndex = DistanceFieldSceneData . NumObjectsInBuffer ;
if ( RemoveIndex ! = MoveFromIndex )
{
// Queue a compute shader move
RemoveObjectIndices . Add ( FIntRect ( RemoveIndex , MoveFromIndex , 0 , 0 ) ) ;
// Fixup indices of the primitive that is being moved
FPrimitiveAndInstance & PrimitiveAndInstanceBeingMoved = DistanceFieldSceneData . PrimitiveInstanceMapping [ MoveFromIndex ] ;
check ( PrimitiveAndInstanceBeingMoved . Primitive & & PrimitiveAndInstanceBeingMoved . Primitive - > DistanceFieldInstanceIndices . Num ( ) > 0 ) ;
PrimitiveAndInstanceBeingMoved . Primitive - > DistanceFieldInstanceIndices [ PrimitiveAndInstanceBeingMoved . InstanceIndex ] = RemoveIndex ;
}
DistanceFieldSceneData . PrimitiveInstanceMapping . RemoveAtSwap ( RemoveIndex ) ;
DistanceFieldSceneData . PendingRemoveOperations . RemoveAtSwap ( ParallelConflictIndex ) ;
*/
}
PendingRemoveOperations . Reset ( ) ;
DistanceFieldSceneData . PendingRemoveOperations . Reset ( ) ;
if ( RemoveObjectIndices . Num ( ) > 0 )
{
if ( RemoveObjectIndices . Num ( ) > GDistanceFieldRemoveIndices . RemoveIndices . MaxElements )
{
GDistanceFieldRemoveIndices . RemoveIndices . MaxElements = RemoveObjectIndices . Num ( ) * 5 / 4 ;
GDistanceFieldRemoveIndices . RemoveIndices . Release ( ) ;
GDistanceFieldRemoveIndices . RemoveIndices . Initialize ( ) ;
}
void * LockedBuffer = RHILockVertexBuffer ( GDistanceFieldRemoveIndices . RemoveIndices . Buffer , 0 , GDistanceFieldRemoveIndices . RemoveIndices . Buffer - > GetSize ( ) , RLM_WriteOnly ) ;
const uint32 MemcpySize = RemoveObjectIndices . GetTypeSize ( ) * RemoveObjectIndices . Num ( ) ;
check ( GDistanceFieldRemoveIndices . RemoveIndices . Buffer - > GetSize ( ) > = MemcpySize ) ;
FPlatformMemory : : Memcpy ( LockedBuffer , RemoveObjectIndices . GetData ( ) , MemcpySize ) ;
RHIUnlockVertexBuffer ( GDistanceFieldRemoveIndices . RemoveIndices . Buffer ) ;
if ( bUseRemoveAtSwap )
{
check ( ! TemporaryCopySourceBuffers ) ;
TShaderMapRef < TRemoveObjectsFromBufferCS < true > > ComputeShader ( GetGlobalShaderMap ( Scene - > GetFeatureLevel ( ) ) ) ;
RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
ComputeShader - > SetParameters ( RHICmdList , Scene , RemoveObjectIndices . Num ( ) , GDistanceFieldRemoveIndices . RemoveIndices . BufferSRV , NULL , NULL ) ;
DispatchComputeShader ( RHICmdList , * ComputeShader , FMath : : DivideAndRoundUp < uint32 > ( RemoveObjectIndices . Num ( ) , UpdateObjectsGroupSize ) , 1 , 1 ) ;
ComputeShader - > UnsetParameters ( RHICmdList ) ;
}
else
{
check ( TemporaryCopySourceBuffers ) ;
TShaderMapRef < TRemoveObjectsFromBufferCS < false > > ComputeShader ( GetGlobalShaderMap ( Scene - > GetFeatureLevel ( ) ) ) ;
RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
ComputeShader - > SetParameters ( RHICmdList , Scene , RemoveObjectIndices . Num ( ) , GDistanceFieldRemoveIndices . RemoveIndices . BufferSRV , TemporaryCopySourceBuffers - > Bounds . SRV , TemporaryCopySourceBuffers - > Data . SRV ) ;
DispatchComputeShader ( RHICmdList , * ComputeShader , FMath : : DivideAndRoundUp < uint32 > ( RemoveObjectIndices . Num ( ) , UpdateObjectsGroupSize ) , 1 , 1 ) ;
ComputeShader - > UnsetParameters ( RHICmdList ) ;
TemporaryCopySourceBuffers - > Release ( ) ;
delete TemporaryCopySourceBuffers ;
}
}
}
}
2015-04-21 16:33:23 -04:00
/** Gathers the information needed to represent a single object's distance field and appends it to the upload buffers. */
void ProcessPrimitiveUpdate (
bool bIsAddOperation ,
FRHICommandListImmediate & RHICmdList ,
FSceneRenderer & SceneRenderer ,
FPrimitiveSceneInfo * PrimitiveSceneInfo ,
int32 OriginalNumObjects ,
FVector InvTextureDim ,
bool bPrepareForDistanceFieldGI ,
TArray < FMatrix > & ObjectLocalToWorldTransforms ,
TArray < uint32 > & UploadObjectIndices ,
TArray < FVector4 > & UploadObjectData )
{
FScene * Scene = SceneRenderer . Scene ;
FDistanceFieldSceneData & DistanceFieldSceneData = Scene - > DistanceFieldSceneData ;
ObjectLocalToWorldTransforms . Reset ( ) ;
FBox LocalVolumeBounds ;
FIntVector BlockMin ;
FIntVector BlockSize ;
bool bBuiltAsIfTwoSided ;
bool bMeshWasPlane ;
PrimitiveSceneInfo - > Proxy - > GetDistancefieldAtlasData ( LocalVolumeBounds , BlockMin , BlockSize , bBuiltAsIfTwoSided , bMeshWasPlane , ObjectLocalToWorldTransforms ) ;
if ( BlockMin . X > = 0
& & BlockMin . Y > = 0
& & BlockMin . Z > = 0
& & ObjectLocalToWorldTransforms . Num ( ) > 0 )
{
const float BoundingRadius = PrimitiveSceneInfo - > Proxy - > GetBounds ( ) . SphereRadius ;
// Proxy bounds are only useful if single instance
if ( ObjectLocalToWorldTransforms . Num ( ) > 1 | | BoundingRadius < GAOMaxObjectBoundingRadius )
{
FPrimitiveSurfelAllocation Allocation ;
FPrimitiveSurfelAllocation InstancedAllocation ;
if ( bPrepareForDistanceFieldGI )
{
const FPrimitiveSurfelAllocation * AllocationPtr = Scene - > DistanceFieldSceneData . SurfelAllocations . FindAllocation ( PrimitiveSceneInfo ) ;
const FPrimitiveSurfelAllocation * InstancedAllocationPtr = Scene - > DistanceFieldSceneData . InstancedSurfelAllocations . FindAllocation ( PrimitiveSceneInfo ) ;
if ( AllocationPtr )
{
checkSlow ( InstancedAllocationPtr & & InstancedAllocationPtr - > NumInstances = = ObjectLocalToWorldTransforms . Num ( ) ) ;
Allocation = * AllocationPtr ;
InstancedAllocation = * InstancedAllocationPtr ;
extern void GenerateSurfelRepresentation ( FRHICommandListImmediate & RHICmdList , FSceneRenderer & Renderer , FViewInfo & View , FPrimitiveSceneInfo * PrimitiveSceneInfo , const FMatrix & Instance0Transform , FPrimitiveSurfelAllocation & Allocation ) ;
// @todo - support surfel generation without a view
GenerateSurfelRepresentation ( RHICmdList , SceneRenderer , SceneRenderer . Views [ 0 ] , PrimitiveSceneInfo , ObjectLocalToWorldTransforms [ 0 ] , Allocation ) ;
if ( Allocation . NumSurfels = = 0 )
{
InstancedAllocation . NumSurfels = 0 ;
InstancedAllocation . NumInstances = 0 ;
InstancedAllocation . NumLOD0 = 0 ;
}
}
}
if ( bIsAddOperation )
{
DistanceFieldSceneData . NumObjectsInBuffer + = ObjectLocalToWorldTransforms . Num ( ) ;
PrimitiveSceneInfo - > DistanceFieldInstanceIndices . Empty ( ObjectLocalToWorldTransforms . Num ( ) ) ;
}
for ( int32 TransformIndex = 0 ; TransformIndex < ObjectLocalToWorldTransforms . Num ( ) ; TransformIndex + + )
{
const uint32 UploadIndex = bIsAddOperation ? OriginalNumObjects + UploadObjectIndices . Num ( ) : PrimitiveSceneInfo - > DistanceFieldInstanceIndices [ TransformIndex ] ;
if ( bIsAddOperation )
{
const int32 AddIndex = OriginalNumObjects + UploadObjectIndices . Num ( ) ;
DistanceFieldSceneData . PrimitiveInstanceMapping . Add ( FPrimitiveAndInstance ( PrimitiveSceneInfo , TransformIndex ) ) ;
PrimitiveSceneInfo - > DistanceFieldInstanceIndices . Add ( AddIndex ) ;
}
UploadObjectIndices . Add ( UploadIndex ) ;
FMatrix LocalToWorld = ObjectLocalToWorldTransforms [ TransformIndex ] ;
if ( bMeshWasPlane )
{
FVector LocalScales = LocalToWorld . GetScaleVector ( ) ;
FVector AbsLocalScales ( FMath : : Abs ( LocalScales . X ) , FMath : : Abs ( LocalScales . Y ) , FMath : : Abs ( LocalScales . Z ) ) ;
float MidScale = FMath : : Min ( AbsLocalScales . X , AbsLocalScales . Y ) ;
float ScaleAdjust = FMath : : Sign ( LocalScales . Z ) * MidScale / AbsLocalScales . Z ;
// The mesh was determined to be a plane flat in Z during the build process, so we can change the Z scale
// Helps in cases with modular ground pieces with scales of (10, 10, 1) and some triangles just above Z=0
LocalToWorld . SetAxis ( 2 , LocalToWorld . GetScaledAxis ( EAxis : : Z ) * ScaleAdjust ) ;
}
const FMatrix VolumeToWorld = FScaleMatrix ( LocalVolumeBounds . GetExtent ( ) )
* FTranslationMatrix ( LocalVolumeBounds . GetCenter ( ) )
* LocalToWorld ;
const FVector4 ObjectBoundingSphere ( VolumeToWorld . GetOrigin ( ) , VolumeToWorld . GetScaleVector ( ) . Size ( ) ) ;
UploadObjectData . Add ( ObjectBoundingSphere ) ;
const float MaxExtent = LocalVolumeBounds . GetExtent ( ) . GetMax ( ) ;
const FMatrix UniformScaleVolumeToWorld = FScaleMatrix ( MaxExtent )
* FTranslationMatrix ( LocalVolumeBounds . GetCenter ( ) )
* LocalToWorld ;
const FVector InvBlockSize ( 1.0f / BlockSize . X , 1.0f / BlockSize . Y , 1.0f / BlockSize . Z ) ;
//float3 VolumeUV = (VolumePosition / LocalPositionExtent * .5f * UVScale + .5f * UVScale + UVAdd;
const FVector LocalPositionExtent = LocalVolumeBounds . GetExtent ( ) / FVector ( MaxExtent ) ;
const FVector UVScale = FVector ( BlockSize ) * InvTextureDim ;
const float VolumeScale = UniformScaleVolumeToWorld . GetMaximumAxisScale ( ) ;
const FMatrix WorldToVolume = UniformScaleVolumeToWorld . Inverse ( ) ;
// WorldToVolume
UploadObjectData . Add ( * ( FVector4 * ) & WorldToVolume . M [ 0 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & WorldToVolume . M [ 1 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & WorldToVolume . M [ 2 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & WorldToVolume . M [ 3 ] ) ;
// Clamp to texel center by subtracting a half texel in the [-1,1] position space
// LocalPositionExtent
UploadObjectData . Add ( FVector4 ( LocalPositionExtent - InvBlockSize , LocalVolumeBounds . Min . X ) ) ;
// UVScale, VolumeScale and sign gives bGeneratedAsTwoSided
const float WSign = bBuiltAsIfTwoSided ? - 1 : 1 ;
UploadObjectData . Add ( FVector4 ( FVector ( BlockSize ) * InvTextureDim * .5f / LocalPositionExtent , WSign * VolumeScale ) ) ;
// UVAdd
UploadObjectData . Add ( FVector4 ( FVector ( BlockMin ) * InvTextureDim + .5f * UVScale , LocalVolumeBounds . Min . Y ) ) ;
// Box bounds
UploadObjectData . Add ( FVector4 ( LocalVolumeBounds . Max , LocalVolumeBounds . Min . Z ) ) ;
UploadObjectData . Add ( * ( FVector4 * ) & UniformScaleVolumeToWorld . M [ 0 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & UniformScaleVolumeToWorld . M [ 1 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & UniformScaleVolumeToWorld . M [ 2 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & LocalToWorld . M [ 0 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & LocalToWorld . M [ 1 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & LocalToWorld . M [ 2 ] ) ;
UploadObjectData . Add ( * ( FVector4 * ) & LocalToWorld . M [ 3 ] ) ;
UploadObjectData . Add ( FVector4 ( Allocation . Offset , Allocation . NumLOD0 , Allocation . NumSurfels , InstancedAllocation . Offset + InstancedAllocation . NumSurfels * TransformIndex ) ) ;
checkSlow ( UploadObjectData . Num ( ) % UploadObjectDataStride = = 0 ) ;
}
}
else
{
UE_LOG ( LogDistanceField , Log , TEXT ( " Primitive %s %s excluded due to bounding radius %f " ) , * PrimitiveSceneInfo - > Proxy - > GetOwnerName ( ) . ToString ( ) , * PrimitiveSceneInfo - > Proxy - > GetResourceName ( ) . ToString ( ) , BoundingRadius ) ;
}
}
}
2015-01-29 14:46:20 -05:00
void FDeferredShadingSceneRenderer : : UpdateGlobalDistanceFieldObjectBuffers ( FRHICommandListImmediate & RHICmdList )
{
FDistanceFieldSceneData & DistanceFieldSceneData = Scene - > DistanceFieldSceneData ;
if ( GDistanceFieldVolumeTextureAtlas . VolumeTextureRHI
& & ( DistanceFieldSceneData . HasPendingOperations ( ) | | DistanceFieldSceneData . AtlasGeneration ! = GDistanceFieldVolumeTextureAtlas . GetGeneration ( ) ) )
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_UpdateObjectData ) ;
SCOPED_DRAW_EVENT ( RHICmdList , UpdateSceneObjectData ) ;
if ( ! DistanceFieldSceneData . ObjectBuffers )
{
DistanceFieldSceneData . ObjectBuffers = new FDistanceFieldObjectBuffers ( ) ;
}
if ( ! DistanceFieldSceneData . SurfelBuffers )
{
DistanceFieldSceneData . SurfelBuffers = new FSurfelBuffers ( ) ;
}
if ( ! DistanceFieldSceneData . InstancedSurfelBuffers )
{
DistanceFieldSceneData . InstancedSurfelBuffers = new FInstancedSurfelBuffers ( ) ;
}
if ( DistanceFieldSceneData . AtlasGeneration ! = GDistanceFieldVolumeTextureAtlas . GetGeneration ( ) )
{
DistanceFieldSceneData . AtlasGeneration = GDistanceFieldVolumeTextureAtlas . GetGeneration ( ) ;
for ( int32 PrimitiveInstanceIndex = 0 ; PrimitiveInstanceIndex < DistanceFieldSceneData . PrimitiveInstanceMapping . Num ( ) ; PrimitiveInstanceIndex + + )
{
FPrimitiveAndInstance & PrimitiveInstance = DistanceFieldSceneData . PrimitiveInstanceMapping [ PrimitiveInstanceIndex ] ;
// Queue an update of all primitives, since the atlas layout has changed
if ( PrimitiveInstance . InstanceIndex = = 0
& & ! DistanceFieldSceneData . HasPendingRemovePrimitive ( PrimitiveInstance . Primitive )
& & ! DistanceFieldSceneData . PendingAddOperations . Contains ( PrimitiveInstance . Primitive )
& & ! DistanceFieldSceneData . PendingUpdateOperations . Contains ( PrimitiveInstance . Primitive ) )
{
DistanceFieldSceneData . PendingUpdateOperations . Add ( PrimitiveInstance . Primitive ) ;
}
}
}
// Process removes before adds, as the adds will overwrite primitive allocation info in DistanceFieldSceneData.SurfelAllocations
UpdateGlobalDistanceFieldObjectRemoves ( RHICmdList , Scene ) ;
2015-03-31 02:49:33 -04:00
extern int32 GVPLMeshGlobalIllumination ;
2015-01-29 14:46:20 -05:00
TArray < uint32 > UploadObjectIndices ;
TArray < FVector4 > UploadObjectData ;
2015-03-30 17:48:16 -04:00
const bool bPrepareForDistanceFieldGI = GVPLMeshGlobalIllumination & & SupportsDistanceFieldGI ( Scene - > GetFeatureLevel ( ) , Scene - > GetShaderPlatform ( ) ) ;
2015-01-29 14:46:20 -05:00
if ( DistanceFieldSceneData . PendingAddOperations . Num ( ) > 0 | | DistanceFieldSceneData . PendingUpdateOperations . Num ( ) > 0 )
{
TArray < FMatrix > ObjectLocalToWorldTransforms ;
const int32 NumUploadOperations = DistanceFieldSceneData . PendingAddOperations . Num ( ) + DistanceFieldSceneData . PendingUpdateOperations . Num ( ) ;
UploadObjectData . Empty ( NumUploadOperations * UploadObjectDataStride ) ;
UploadObjectIndices . Empty ( NumUploadOperations ) ;
const int32 NumTexelsOneDimX = GDistanceFieldVolumeTextureAtlas . GetSizeX ( ) ;
const int32 NumTexelsOneDimY = GDistanceFieldVolumeTextureAtlas . GetSizeY ( ) ;
const int32 NumTexelsOneDimZ = GDistanceFieldVolumeTextureAtlas . GetSizeZ ( ) ;
const FVector InvTextureDim ( 1.0f / NumTexelsOneDimX , 1.0f / NumTexelsOneDimY , 1.0f / NumTexelsOneDimZ ) ;
int32 OriginalNumObjects = DistanceFieldSceneData . NumObjectsInBuffer ;
int32 OriginalNumSurfels = DistanceFieldSceneData . SurfelAllocations . GetNumSurfelsInBuffer ( ) ;
int32 OriginalNumInstancedSurfels = DistanceFieldSceneData . InstancedSurfelAllocations . GetNumSurfelsInBuffer ( ) ;
2015-03-31 02:49:33 -04:00
2015-01-29 14:46:20 -05:00
2015-03-30 17:48:16 -04:00
if ( bPrepareForDistanceFieldGI )
2015-01-29 14:46:20 -05:00
{
for ( int32 UploadPrimitiveIndex = 0 ; UploadPrimitiveIndex < DistanceFieldSceneData . PendingAddOperations . Num ( ) ; UploadPrimitiveIndex + + )
{
FPrimitiveSceneInfo * PrimitiveSceneInfo = DistanceFieldSceneData . PendingAddOperations [ UploadPrimitiveIndex ] ;
int32 NumInstances = 0 ;
float BoundsSurfaceArea = 0 ;
PrimitiveSceneInfo - > Proxy - > GetDistanceFieldInstanceInfo ( NumInstances , BoundsSurfaceArea ) ;
extern void ComputeNumSurfels ( float BoundsSurfaceArea , int32 & PrimitiveNumSurfels , int32 & PrimitiveLOD0Surfels ) ;
int32 PrimitiveNumSurfels ;
int32 PrimitiveLOD0Surfels ;
ComputeNumSurfels ( BoundsSurfaceArea , PrimitiveNumSurfels , PrimitiveLOD0Surfels ) ;
if ( PrimitiveNumSurfels > 0 & & NumInstances > 0 )
{
const int32 PrimitiveTotalNumSurfels = PrimitiveNumSurfels * NumInstances ;
if ( PrimitiveNumSurfels > 5000 )
{
UE_LOG ( LogDistanceField , Warning , TEXT ( " Primitive %s %s used %u Surfels " ) , * PrimitiveSceneInfo - > Proxy - > GetOwnerName ( ) . ToString ( ) , * PrimitiveSceneInfo - > Proxy - > GetResourceName ( ) . ToString ( ) , PrimitiveNumSurfels ) ;
}
DistanceFieldSceneData . SurfelAllocations . AddPrimitive ( PrimitiveSceneInfo , PrimitiveLOD0Surfels , PrimitiveNumSurfels , 1 ) ;
DistanceFieldSceneData . InstancedSurfelAllocations . AddPrimitive ( PrimitiveSceneInfo , PrimitiveLOD0Surfels , PrimitiveNumSurfels , NumInstances ) ;
}
}
if ( DistanceFieldSceneData . SurfelBuffers - > MaxSurfels < DistanceFieldSceneData . SurfelAllocations . GetNumSurfelsInBuffer ( ) )
{
if ( DistanceFieldSceneData . SurfelBuffers - > MaxSurfels > 0 )
{
// Realloc
FSurfelBuffers * NewSurfelBuffers = new FSurfelBuffers ( ) ;
NewSurfelBuffers - > MaxSurfels = DistanceFieldSceneData . SurfelAllocations . GetNumSurfelsInBuffer ( ) * 5 / 4 ;
NewSurfelBuffers - > Initialize ( ) ;
{
TShaderMapRef < FCopySurfelBufferCS > ComputeShader ( GetGlobalShaderMap ( Scene - > GetFeatureLevel ( ) ) ) ;
RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
ComputeShader - > SetParameters ( RHICmdList , * ( DistanceFieldSceneData . SurfelBuffers ) , * ( DistanceFieldSceneData . InstancedSurfelBuffers ) , * NewSurfelBuffers , OriginalNumSurfels ) ;
DispatchComputeShader ( RHICmdList , * ComputeShader , FMath : : DivideAndRoundUp < uint32 > ( OriginalNumSurfels , UpdateObjectsGroupSize ) , 1 , 1 ) ;
ComputeShader - > UnsetParameters ( RHICmdList ) ;
}
DistanceFieldSceneData . SurfelBuffers - > Release ( ) ;
delete DistanceFieldSceneData . SurfelBuffers ;
DistanceFieldSceneData . SurfelBuffers = NewSurfelBuffers ;
}
else
{
// First time allocate
DistanceFieldSceneData . SurfelBuffers - > MaxSurfels = DistanceFieldSceneData . SurfelAllocations . GetNumSurfelsInBuffer ( ) * 5 / 4 ;
DistanceFieldSceneData . SurfelBuffers - > Initialize ( ) ;
}
}
if ( DistanceFieldSceneData . InstancedSurfelBuffers - > MaxSurfels < DistanceFieldSceneData . InstancedSurfelAllocations . GetNumSurfelsInBuffer ( ) )
{
if ( DistanceFieldSceneData . InstancedSurfelBuffers - > MaxSurfels > 0 )
{
// Realloc
FInstancedSurfelBuffers * NewInstancedSurfelBuffers = new FInstancedSurfelBuffers ( ) ;
NewInstancedSurfelBuffers - > MaxSurfels = DistanceFieldSceneData . InstancedSurfelAllocations . GetNumSurfelsInBuffer ( ) * 5 / 4 ;
NewInstancedSurfelBuffers - > Initialize ( ) ;
{
TShaderMapRef < FCopyVPLFluxBufferCS > ComputeShader ( GetGlobalShaderMap ( Scene - > GetFeatureLevel ( ) ) ) ;
RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
ComputeShader - > SetParameters ( RHICmdList , * ( DistanceFieldSceneData . SurfelBuffers ) , * ( DistanceFieldSceneData . InstancedSurfelBuffers ) , * NewInstancedSurfelBuffers , OriginalNumInstancedSurfels ) ;
DispatchComputeShader ( RHICmdList , * ComputeShader , FMath : : DivideAndRoundUp < uint32 > ( OriginalNumInstancedSurfels , UpdateObjectsGroupSize ) , 1 , 1 ) ;
ComputeShader - > UnsetParameters ( RHICmdList ) ;
}
DistanceFieldSceneData . InstancedSurfelBuffers - > Release ( ) ;
delete DistanceFieldSceneData . InstancedSurfelBuffers ;
DistanceFieldSceneData . InstancedSurfelBuffers = NewInstancedSurfelBuffers ;
}
else
{
// First time allocate
DistanceFieldSceneData . InstancedSurfelBuffers - > MaxSurfels = DistanceFieldSceneData . InstancedSurfelAllocations . GetNumSurfelsInBuffer ( ) * 5 / 4 ;
DistanceFieldSceneData . InstancedSurfelBuffers - > Initialize ( ) ;
}
}
}
2015-04-21 16:33:23 -04:00
for ( int32 UploadPrimitiveIndex = 0 ; UploadPrimitiveIndex < DistanceFieldSceneData . PendingAddOperations . Num ( ) ; UploadPrimitiveIndex + + )
2015-01-29 14:46:20 -05:00
{
2015-04-21 16:33:23 -04:00
FPrimitiveSceneInfo * PrimitiveSceneInfo = DistanceFieldSceneData . PendingAddOperations [ UploadPrimitiveIndex ] ;
2015-01-29 14:46:20 -05:00
2015-04-21 16:33:23 -04:00
ProcessPrimitiveUpdate (
true ,
RHICmdList ,
* this ,
PrimitiveSceneInfo ,
OriginalNumObjects ,
InvTextureDim ,
bPrepareForDistanceFieldGI ,
ObjectLocalToWorldTransforms ,
UploadObjectIndices ,
UploadObjectData ) ;
}
2015-01-29 14:46:20 -05:00
2015-04-21 16:33:23 -04:00
for ( TSet < FPrimitiveSceneInfo * > : : TIterator It ( DistanceFieldSceneData . PendingUpdateOperations ) ; It ; + + It )
{
FPrimitiveSceneInfo * PrimitiveSceneInfo = * It ;
2015-01-29 14:46:20 -05:00
2015-04-21 16:33:23 -04:00
ProcessPrimitiveUpdate (
false ,
RHICmdList ,
* this ,
PrimitiveSceneInfo ,
OriginalNumObjects ,
InvTextureDim ,
bPrepareForDistanceFieldGI ,
ObjectLocalToWorldTransforms ,
UploadObjectIndices ,
UploadObjectData ) ;
2015-01-29 14:46:20 -05:00
}
DistanceFieldSceneData . PendingAddOperations . Reset ( ) ;
2015-04-21 16:33:23 -04:00
DistanceFieldSceneData . PendingUpdateOperations . Empty ( ) ;
2015-01-29 14:46:20 -05:00
if ( DistanceFieldSceneData . ObjectBuffers - > MaxObjects < DistanceFieldSceneData . NumObjectsInBuffer )
{
if ( DistanceFieldSceneData . ObjectBuffers - > MaxObjects > 0 )
{
// Realloc
FDistanceFieldObjectBuffers * NewObjectBuffers = new FDistanceFieldObjectBuffers ( ) ;
NewObjectBuffers - > MaxObjects = DistanceFieldSceneData . NumObjectsInBuffer * 5 / 4 ;
NewObjectBuffers - > Initialize ( ) ;
{
TShaderMapRef < FCopyObjectBufferCS > ComputeShader ( GetGlobalShaderMap ( Scene - > GetFeatureLevel ( ) ) ) ;
RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
ComputeShader - > SetParameters ( RHICmdList , * ( DistanceFieldSceneData . ObjectBuffers ) , * NewObjectBuffers , OriginalNumObjects ) ;
DispatchComputeShader ( RHICmdList , * ComputeShader , FMath : : DivideAndRoundUp < uint32 > ( OriginalNumObjects , UpdateObjectsGroupSize ) , 1 , 1 ) ;
ComputeShader - > UnsetParameters ( RHICmdList ) ;
}
DistanceFieldSceneData . ObjectBuffers - > Release ( ) ;
delete DistanceFieldSceneData . ObjectBuffers ;
DistanceFieldSceneData . ObjectBuffers = NewObjectBuffers ;
}
else
{
// First time allocate
DistanceFieldSceneData . ObjectBuffers - > MaxObjects = DistanceFieldSceneData . NumObjectsInBuffer * 5 / 4 ;
DistanceFieldSceneData . ObjectBuffers - > Initialize ( ) ;
}
}
}
if ( UploadObjectIndices . Num ( ) > 0 )
{
if ( UploadObjectIndices . Num ( ) > GDistanceFieldUploadIndices . UploadIndices . MaxElements )
{
GDistanceFieldUploadIndices . UploadIndices . MaxElements = UploadObjectIndices . Num ( ) * 5 / 4 ;
GDistanceFieldUploadIndices . UploadIndices . Release ( ) ;
GDistanceFieldUploadIndices . UploadIndices . Initialize ( ) ;
GDistanceFieldUploadData . UploadData . MaxElements = UploadObjectIndices . Num ( ) * 5 / 4 ;
GDistanceFieldUploadData . UploadData . Release ( ) ;
GDistanceFieldUploadData . UploadData . Initialize ( ) ;
}
void * LockedBuffer = RHILockVertexBuffer ( GDistanceFieldUploadIndices . UploadIndices . Buffer , 0 , GDistanceFieldUploadIndices . UploadIndices . Buffer - > GetSize ( ) , RLM_WriteOnly ) ;
const uint32 MemcpySize = UploadObjectIndices . GetTypeSize ( ) * UploadObjectIndices . Num ( ) ;
check ( GDistanceFieldUploadIndices . UploadIndices . Buffer - > GetSize ( ) > = MemcpySize ) ;
FPlatformMemory : : Memcpy ( LockedBuffer , UploadObjectIndices . GetData ( ) , MemcpySize ) ;
RHIUnlockVertexBuffer ( GDistanceFieldUploadIndices . UploadIndices . Buffer ) ;
LockedBuffer = RHILockVertexBuffer ( GDistanceFieldUploadData . UploadData . Buffer , 0 , GDistanceFieldUploadData . UploadData . Buffer - > GetSize ( ) , RLM_WriteOnly ) ;
const uint32 MemcpySize2 = UploadObjectData . GetTypeSize ( ) * UploadObjectData . Num ( ) ;
check ( GDistanceFieldUploadData . UploadData . Buffer - > GetSize ( ) > = MemcpySize2 ) ;
FPlatformMemory : : Memcpy ( LockedBuffer , UploadObjectData . GetData ( ) , MemcpySize2 ) ;
RHIUnlockVertexBuffer ( GDistanceFieldUploadData . UploadData . Buffer ) ;
{
TShaderMapRef < FUploadObjectsToBufferCS > ComputeShader ( GetGlobalShaderMap ( Scene - > GetFeatureLevel ( ) ) ) ;
RHICmdList . SetComputeShader ( ComputeShader - > GetComputeShader ( ) ) ;
ComputeShader - > SetParameters ( RHICmdList , Scene , UploadObjectIndices . Num ( ) , GDistanceFieldUploadIndices . UploadIndices . BufferSRV , GDistanceFieldUploadData . UploadData . BufferSRV ) ;
DispatchComputeShader ( RHICmdList , * ComputeShader , FMath : : DivideAndRoundUp < uint32 > ( UploadObjectIndices . Num ( ) , UpdateObjectsGroupSize ) , 1 , 1 ) ;
ComputeShader - > UnsetParameters ( RHICmdList ) ;
}
}
check ( DistanceFieldSceneData . NumObjectsInBuffer = = DistanceFieldSceneData . PrimitiveInstanceMapping . Num ( ) ) ;
DistanceFieldSceneData . VerifyIntegrity ( ) ;
}
}
FString GetObjectBufferMemoryString ( )
{
return FString : : Printf ( TEXT ( " Temp object buffers %.3fMb " ) ,
( GDistanceFieldUploadIndices . UploadIndices . GetSizeBytes ( ) + GDistanceFieldUploadData . UploadData . GetSizeBytes ( ) + GDistanceFieldRemoveIndices . RemoveIndices . GetSizeBytes ( ) ) / 1024.0f / 1024.0f ) ;
2015-04-01 07:20:55 -04:00
}