2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-06-11 18:27:07 -04:00
# include "RenderGraphPass.h"
2020-07-06 18:58:26 -04:00
# include "RenderGraphPrivate.h"
# include "RenderGraphUtils.h"
2019-06-11 18:27:07 -04:00
2020-09-24 00:43:27 -04:00
FUniformBufferStaticBindings FRDGParameterStruct : : GetGlobalUniformBuffers ( ) const
2020-01-24 18:07:01 -05:00
{
FUniformBufferStaticBindings GlobalUniformBuffers ;
2020-09-24 00:43:27 -04:00
for ( uint32 Index = 0 , Count = Layout - > UniformBuffers . Num ( ) ; Index < Count ; + + Index )
2020-01-24 18:07:01 -05:00
{
2020-09-24 00:43:27 -04:00
const uint32 MemberOffset = Layout - > UniformBuffers [ Index ] . MemberOffset ;
FRHIUniformBuffer * UniformBufferPtr = * reinterpret_cast < FUniformBufferRHIRef * > ( const_cast < uint8 * > ( Contents + MemberOffset ) ) ;
2020-01-24 18:07:01 -05:00
2020-09-24 00:43:27 -04:00
if ( UniformBufferPtr & & UniformBufferPtr - > IsGlobal ( ) )
2020-01-24 18:07:01 -05:00
{
2020-09-24 00:43:27 -04:00
GlobalUniformBuffers . AddUniformBuffer ( UniformBufferPtr ) ;
2020-01-24 18:07:01 -05:00
}
}
2020-09-24 00:43:27 -04:00
EnumerateUniformBuffers ( [ & ] ( FRDGUniformBufferRef UniformBuffer )
{
if ( UniformBuffer - > IsGlobal ( ) )
{
GlobalUniformBuffers . AddUniformBuffer ( UniformBuffer - > GetRHI ( ) ) ;
}
} ) ;
2020-01-24 18:07:01 -05:00
return GlobalUniformBuffers ;
}
2020-09-24 00:43:27 -04:00
FRHIRenderPassInfo FRDGParameterStruct : : GetRenderPassInfo ( ) const
2020-07-06 18:58:26 -04:00
{
2020-09-24 00:43:27 -04:00
const FRenderTargetBindingSlots & RenderTargets = GetRenderTargets ( ) ;
FRHIRenderPassInfo RenderPassInfo ;
uint32 SampleCount = 0 ;
uint32 RenderTargetIndex = 0 ;
RenderTargets . Enumerate ( [ & ] ( FRenderTargetBinding RenderTarget )
{
FRDGTextureRef Texture = RenderTarget . GetTexture ( ) ;
FRDGTextureRef ResolveTexture = RenderTarget . GetResolveTexture ( ) ;
ERenderTargetStoreAction StoreAction = EnumHasAnyFlags ( Texture - > Desc . Flags , TexCreate_Memoryless ) ? ERenderTargetStoreAction : : ENoAction : ERenderTargetStoreAction : : EStore ;
if ( ResolveTexture )
{
// Silently skip the resolve if the resolve texture is the same as the render target texture.
if ( ResolveTexture ! = Texture )
{
StoreAction = ERenderTargetStoreAction : : EMultisampleResolve ;
}
else
{
ResolveTexture = nullptr ;
}
}
auto & ColorRenderTarget = RenderPassInfo . ColorRenderTargets [ RenderTargetIndex ] ;
ColorRenderTarget . RenderTarget = Texture - > GetRHI ( ) ;
ColorRenderTarget . ResolveTarget = ResolveTexture ? ResolveTexture - > GetRHI ( ) : nullptr ;
ColorRenderTarget . ArraySlice = RenderTarget . GetArraySlice ( ) ;
ColorRenderTarget . MipIndex = RenderTarget . GetMipIndex ( ) ;
ColorRenderTarget . Action = MakeRenderTargetActions ( RenderTarget . GetLoadAction ( ) , StoreAction ) ;
SampleCount | = ColorRenderTarget . RenderTarget - > GetNumSamples ( ) ;
+ + RenderTargetIndex ;
} ) ;
const FDepthStencilBinding & DepthStencil = RenderTargets . DepthStencil ;
if ( FRDGTextureRef Texture = DepthStencil . GetTexture ( ) )
{
const FExclusiveDepthStencil ExclusiveDepthStencil = DepthStencil . GetDepthStencilAccess ( ) ;
const ERenderTargetStoreAction StoreAction = EnumHasAnyFlags ( Texture - > Desc . Flags , TexCreate_Memoryless ) ? ERenderTargetStoreAction : : ENoAction : ERenderTargetStoreAction : : EStore ;
const ERenderTargetStoreAction DepthStoreAction = ExclusiveDepthStencil . IsUsingDepth ( ) ? StoreAction : ERenderTargetStoreAction : : ENoAction ;
const ERenderTargetStoreAction StencilStoreAction = ExclusiveDepthStencil . IsUsingStencil ( ) ? StoreAction : ERenderTargetStoreAction : : ENoAction ;
auto & DepthStencilTarget = RenderPassInfo . DepthStencilRenderTarget ;
DepthStencilTarget . DepthStencilTarget = Texture - > GetRHI ( ) ;
DepthStencilTarget . Action = MakeDepthStencilTargetActions (
MakeRenderTargetActions ( DepthStencil . GetDepthLoadAction ( ) , DepthStoreAction ) ,
MakeRenderTargetActions ( DepthStencil . GetStencilLoadAction ( ) , StencilStoreAction ) ) ;
DepthStencilTarget . ExclusiveDepthStencil = ExclusiveDepthStencil ;
SampleCount | = DepthStencilTarget . DepthStencilTarget - > GetNumSamples ( ) ;
}
RenderPassInfo . bIsMSAA = SampleCount > 1 ;
RenderPassInfo . ResolveParameters = RenderTargets . ResolveRect ;
RenderPassInfo . ResolveParameters . SourceAccessFinal = ERHIAccess : : RTV ;
RenderPassInfo . ResolveParameters . DestAccessFinal = ERHIAccess : : ResolveDst ;
RenderPassInfo . NumOcclusionQueries = RenderTargets . NumOcclusionQueries ;
RenderPassInfo . bOcclusionQueries = RenderTargets . NumOcclusionQueries > 0 ;
return RenderPassInfo ;
2020-07-06 18:58:26 -04:00
}
2020-09-24 00:43:27 -04:00
FRDGBarrierBatch : : FRDGBarrierBatch ( const FRDGPass * InPass , const TCHAR * InName )
: Pipeline ( InPass - > GetPipeline ( ) )
# if RDG_ENABLE_DEBUG
, Pass ( InPass )
, Name ( InName )
# endif
{ }
2020-07-06 18:58:26 -04:00
void FRDGBarrierBatch : : SetSubmitted ( )
{
check ( ! bSubmitted ) ;
bSubmitted = true ;
}
FString FRDGBarrierBatch : : GetName ( ) const
{
2020-09-24 00:43:27 -04:00
# if RDG_ENABLE_DEBUG
return FString : : Printf ( TEXT ( " [%s(%s)]: %s " ) , Pass - > GetName ( ) , * GetRHIPipelineName ( Pass - > GetPipeline ( ) ) , Name ) ;
# else
return { } ;
# endif
2020-07-06 18:58:26 -04:00
}
2020-09-24 00:43:27 -04:00
FRDGBarrierBatchBegin : : FRDGBarrierBatchBegin ( const FRDGPass * InPass , const TCHAR * InName , TOptional < ERHIPipeline > InOverridePipelineToEnd )
2020-07-06 18:58:26 -04:00
: FRDGBarrierBatch ( InPass , InName )
, OverridePipelineToEnd ( InOverridePipelineToEnd )
{ }
FRDGBarrierBatchBegin : : ~ FRDGBarrierBatchBegin ( )
{
2020-09-24 00:43:27 -04:00
# if RDG_ENABLE_DEBUG
2020-07-06 18:58:26 -04:00
checkf ( ! Resources . Num ( ) & & ! Transitions . Num ( ) , TEXT ( " Begin barrier batch has unsubmitted transitions. " ) ) ;
checkf ( ! Transition , TEXT ( " Begin barrier batch %s is currently active and was never ended. " ) , * GetName ( ) ) ;
2020-09-24 00:43:27 -04:00
# endif
2020-07-06 18:58:26 -04:00
}
void FRDGBarrierBatchBegin : : AddTransition ( FRDGParentResourceRef Resource , const FRHITransitionInfo & Info )
{
2020-09-24 00:43:27 -04:00
check ( Resource & & Info . Resource ) ;
2020-07-06 18:58:26 -04:00
checkf ( ! IsSubmitted ( ) , TEXT ( " Attempting to add transition for resource '%s' into begin batch '%s', when the begin batch has already been submitted. " ) , Resource - > Name , * GetName ( ) ) ;
Transitions . Add ( Info ) ;
2020-09-24 00:43:27 -04:00
# if STATS
GRDGStatTransitionCount + + ;
# endif
# if RDG_ENABLE_DEBUG
Resources . Add ( Resource ) ;
# endif
2020-07-06 18:58:26 -04:00
}
void FRDGBarrierBatchBegin : : Submit ( FRHIComputeCommandList & RHICmdList )
{
SetSubmitted ( ) ;
check ( ! Transition ) ;
if ( Transitions . Num ( ) | | bUseCrossPipelineFence )
{
2020-09-24 00:43:27 -04:00
const ERHIPipeline PassPipeline = GetPipeline ( ) ;
2020-07-06 18:58:26 -04:00
2020-09-24 00:43:27 -04:00
ERHICreateTransitionFlags Flags = ERHICreateTransitionFlags : : NoFence ;
2020-07-06 18:58:26 -04:00
if ( bUseCrossPipelineFence )
{
2020-09-24 00:43:27 -04:00
Flags = ERHICreateTransitionFlags : : None ;
2020-07-06 18:58:26 -04:00
}
2020-09-24 00:43:27 -04:00
const ERHIPipeline DstPipeline = OverridePipelineToEnd ? OverridePipelineToEnd . GetValue ( ) : PassPipeline ;
Transition = RHICreateTransition ( PassPipeline , DstPipeline , Flags , Transitions ) ;
2020-07-06 18:58:26 -04:00
2020-09-24 00:43:27 -04:00
RHICmdList . BeginTransitions ( MakeArrayView ( & Transition , 1 ) ) ;
2020-07-06 18:58:26 -04:00
Transitions . Empty ( ) ;
2020-09-24 00:43:27 -04:00
# if RDG_ENABLE_DEBUG
2020-07-06 18:58:26 -04:00
Resources . Empty ( ) ;
2020-09-24 00:43:27 -04:00
# endif
# if STATS
GRDGStatTransitionBatchCount + + ;
# endif
2020-07-06 18:58:26 -04:00
}
}
FRDGBarrierBatchEnd : : ~ FRDGBarrierBatchEnd ( )
{
checkf ( ! Dependencies . Num ( ) , TEXT ( " End barrier batch has unsubmitted dependencies. " ) ) ;
}
2020-09-24 00:43:27 -04:00
void FRDGBarrierBatchEnd : : ReserveMemory ( uint32 ExpectedDependencyCount )
{
Dependencies . Reserve ( ExpectedDependencyCount ) ;
}
2020-07-06 18:58:26 -04:00
void FRDGBarrierBatchEnd : : AddDependency ( FRDGBarrierBatchBegin * BeginBatch )
{
check ( BeginBatch ) ;
checkf ( ! IsSubmitted ( ) , TEXT ( " Attempting to add a dependency on begin batch '%s' into end batch '%s', when the end batch has already been submitted. " ) , * BeginBatch - > GetName ( ) , * GetName ( ) ) ;
Dependencies . AddUnique ( BeginBatch ) ;
}
void FRDGBarrierBatchEnd : : Submit ( FRHIComputeCommandList & RHICmdList )
{
SetSubmitted ( ) ;
TArray < const FRHITransition * , SceneRenderingAllocator > Transitions ;
Transitions . Reserve ( Dependencies . Num ( ) ) ;
// Process dependencies with cross-pipeline fences first.
for ( FRDGBarrierBatchBegin * Dependent : Dependencies )
{
check ( Dependent - > IsSubmitted ( ) ) ;
if ( Dependent - > Transition & & Dependent - > bUseCrossPipelineFence )
{
Transitions . Add ( Dependent - > Transition ) ;
Dependent - > Transition = nullptr ;
}
}
for ( FRDGBarrierBatchBegin * Dependent : Dependencies )
{
if ( Dependent - > Transition )
{
Transitions . Add ( Dependent - > Transition ) ;
Dependent - > Transition = nullptr ;
}
}
Dependencies . Empty ( ) ;
if ( Transitions . Num ( ) )
{
2020-09-24 00:43:27 -04:00
RHICmdList . EndTransitions ( Transitions ) ;
2020-07-06 18:58:26 -04:00
}
}
2020-09-24 00:43:27 -04:00
FRDGBarrierBatchBegin & FRDGPass : : GetPrologueBarriersToBegin ( FRDGAllocator & Allocator )
{
if ( ! PrologueBarriersToBegin )
{
PrologueBarriersToBegin = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( this , TEXT ( " Prologue " ) ) ;
}
return * PrologueBarriersToBegin ;
}
FRDGBarrierBatchEnd & FRDGPass : : GetPrologueBarriersToEnd ( FRDGAllocator & Allocator )
{
if ( ! PrologueBarriersToEnd )
{
PrologueBarriersToEnd = Allocator . AllocNoDestruct < FRDGBarrierBatchEnd > ( this , TEXT ( " Prologue " ) ) ;
}
return * PrologueBarriersToEnd ;
}
FRDGBarrierBatchBegin & FRDGPass : : GetEpilogueBarriersToBeginForGraphics ( FRDGAllocator & Allocator )
{
if ( ! EpilogueBarriersToBeginForGraphics )
{
EpilogueBarriersToBeginForGraphics = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( this , TEXT ( " Epilogue (For Graphics) " ) , ERHIPipeline : : Graphics ) ;
}
return * EpilogueBarriersToBeginForGraphics ;
}
FRDGBarrierBatchBegin & FRDGPass : : GetEpilogueBarriersToBeginForAsyncCompute ( FRDGAllocator & Allocator )
{
if ( ! EpilogueBarriersToBeginForAsyncCompute )
{
EpilogueBarriersToBeginForAsyncCompute = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( this , TEXT ( " Epilogue (For AsyncCompute) " ) , ERHIPipeline : : AsyncCompute ) ;
}
return * EpilogueBarriersToBeginForAsyncCompute ;
}
2019-06-11 18:27:07 -04:00
FRDGPass : : FRDGPass (
FRDGEventName & & InName ,
2020-09-24 00:43:27 -04:00
FRDGParameterStruct InParameterStruct ,
2020-07-06 18:58:26 -04:00
ERDGPassFlags InFlags )
: Name ( Forward < FRDGEventName & & > ( InName ) )
2019-06-11 18:27:07 -04:00
, ParameterStruct ( InParameterStruct )
2020-07-06 18:58:26 -04:00
, Flags ( InFlags )
2020-09-24 00:43:27 -04:00
, Pipeline ( EnumHasAnyFlags ( Flags , ERDGPassFlags : : AsyncCompute ) ? ERHIPipeline : : AsyncCompute : ERHIPipeline : : Graphics )
2019-09-14 09:45:25 -04:00
{ }
2019-06-11 18:27:07 -04:00
2020-09-24 00:43:27 -04:00
# if RDG_ENABLE_DEBUG
const TCHAR * FRDGPass : : GetName ( ) const
{
// When in debug runtime mode, use the full path name.
if ( ! FullPathIfDebug . IsEmpty ( ) )
{
return * FullPathIfDebug ;
}
else
{
return Name . GetTCHAR ( ) ;
}
}
# endif
void FRDGPass : : Execute ( FRHIComputeCommandList & RHICmdList )
2019-06-11 18:27:07 -04:00
{
2020-07-06 18:58:26 -04:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FRDGPass_Execute ) ;
2020-09-24 00:43:27 -04:00
RHICmdList . SetGlobalUniformBuffers ( ParameterStruct . GetGlobalUniformBuffers ( ) ) ;
2019-06-11 18:27:07 -04:00
ExecuteImpl ( RHICmdList ) ;
}