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-11-11 19:22:36 -04:00
static FRDGPassHandlesByPipeline GetPassesByPipeline ( const FRDGPass * Pass )
{
check ( Pass ) ;
FRDGPassHandlesByPipeline Passes ;
Passes [ Pass - > GetPipeline ( ) ] = Pass - > GetHandle ( ) ;
return Passes ;
}
2021-01-13 16:51:48 -04:00
FUniformBufferStaticBindings FRDGParameterStruct : : GetStaticUniformBuffers ( ) 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 ;
2020-12-07 17:42:32 -04:00
const FUniformBufferBinding & UniformBuffer = * reinterpret_cast < const FUniformBufferBinding * > ( const_cast < uint8 * > ( Contents + MemberOffset ) ) ;
2020-01-24 18:07:01 -05:00
2020-12-07 17:42:32 -04:00
if ( UniformBuffer & & UniformBuffer . IsStatic ( ) )
2020-01-24 18:07:01 -05:00
{
2020-12-07 17:42:32 -04:00
GlobalUniformBuffers . AddUniformBuffer ( UniformBuffer . GetUniformBuffer ( ) ) ;
2020-01-24 18:07:01 -05:00
}
}
2020-12-07 17:42:32 -04:00
EnumerateUniformBuffers ( [ & ] ( FRDGUniformBufferBinding UniformBuffer )
2020-09-24 00:43:27 -04:00
{
2020-12-07 17:42:32 -04:00
if ( UniformBuffer . IsStatic ( ) )
2020-09-24 00:43:27 -04:00
{
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 ;
2020-12-04 12:07:09 -04:00
RenderPassInfo . SubpassHint = RenderTargets . SubpassHint ;
RenderPassInfo . MultiViewCount = RenderTargets . MultiViewCount ;
RenderPassInfo . FoveationTexture = RenderTargets . FoveationTexture ? RenderTargets . FoveationTexture - > GetRHI ( ) : nullptr ;
2020-09-24 00:43:27 -04:00
return RenderPassInfo ;
2020-07-06 18:58:26 -04:00
}
2020-11-11 19:22:36 -04:00
uint32 GetTypeHash ( FRDGBarrierBatchBeginId Id )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
static_assert ( sizeof ( Id . Passes ) = = 4 , " Hash expects the Passes array to be 4 bytes (2 uint16's). " ) ;
uint32 Hash = * ( const uint32 * ) Id . Passes . GetData ( ) ;
return ( Hash < < GetRHIPipelineCount ( ) ) | uint32 ( Id . PipelinesAfter ) ;
2020-07-06 18:58:26 -04:00
}
2020-11-11 19:22:36 -04:00
FRDGTransitionQueue : : FRDGTransitionQueue ( uint32 ReservedCount )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
Queue . Reserve ( ReservedCount ) ;
2020-07-06 18:58:26 -04:00
}
2020-11-11 19:22:36 -04:00
void FRDGTransitionQueue : : Insert ( const FRHITransition * Transition , ERHICreateTransitionFlags TransitionFlags )
{
if ( ! EnumHasAnyFlags ( TransitionFlags , ERHICreateTransitionFlags : : NoFence ) )
{
QueueWithFences . Add ( Transition ) ;
}
else
{
Queue . Add ( Transition ) ;
}
}
void FRDGTransitionQueue : : Begin ( FRHIComputeCommandList & RHICmdList )
{
if ( Queue . Num ( ) | | QueueWithFences . Num ( ) )
{
// Fence signals happen last.
Queue . Append ( QueueWithFences ) ;
RHICmdList . BeginTransitions ( Queue ) ;
Queue . Empty ( ) ;
QueueWithFences . Empty ( ) ;
}
}
void FRDGTransitionQueue : : End ( FRHIComputeCommandList & RHICmdList )
{
if ( Queue . Num ( ) | | QueueWithFences . Num ( ) )
{
// Fence waits happen first.
Queue . Insert ( QueueWithFences , 0 ) ;
RHICmdList . EndTransitions ( Queue ) ;
Queue . Empty ( ) ;
QueueWithFences . Empty ( ) ;
}
}
FRDGBarrierBatchBegin : : FRDGBarrierBatchBegin ( ERHIPipeline InPipelinesToBegin , ERHIPipeline InPipelinesToEnd , const TCHAR * InDebugName , const FRDGPass * InDebugPass )
: FRDGBarrierBatchBegin ( InPipelinesToBegin , InPipelinesToEnd , InDebugName , GetPassesByPipeline ( InDebugPass ) )
2020-07-06 18:58:26 -04:00
{ }
2020-11-11 19:22:36 -04:00
FRDGBarrierBatchBegin : : FRDGBarrierBatchBegin ( ERHIPipeline InPipelinesToBegin , ERHIPipeline InPipelinesToEnd , const TCHAR * InDebugName , FRDGPassHandlesByPipeline InDebugPasses )
: PipelinesToBegin ( InPipelinesToBegin )
, PipelinesToEnd ( InPipelinesToEnd )
# if RDG_ENABLE_DEBUG
, DebugPasses ( InDebugPasses )
, DebugName ( InDebugName )
, DebugPipelinesToBegin ( InPipelinesToBegin )
, DebugPipelinesToEnd ( InPipelinesToEnd )
# endif
2020-07-06 18:58:26 -04:00
{
2020-09-24 00:43:27 -04:00
# if RDG_ENABLE_DEBUG
2020-11-11 19:22:36 -04:00
for ( ERHIPipeline Pipeline : GetRHIPipelines ( ) )
{
// We should have provided corresponding debug passes to match the pipeline flags.
check ( InDebugPasses [ Pipeline ] . IsValid ( ) = = EnumHasAllFlags ( InPipelinesToBegin , Pipeline ) ) ;
}
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 )
{
Transitions . Add ( Info ) ;
2020-11-11 19:22:36 -04:00
bTransitionNeeded = true ;
2020-09-24 00:43:27 -04:00
# if STATS
GRDGStatTransitionCount + + ;
# endif
# if RDG_ENABLE_DEBUG
2020-11-11 19:22:36 -04:00
DebugResources . Add ( Resource ) ;
2020-09-24 00:43:27 -04:00
# endif
2020-07-06 18:58:26 -04:00
}
2020-11-11 19:22:36 -04:00
void FRDGBarrierBatchBegin : : Submit ( FRHIComputeCommandList & RHICmdList , ERHIPipeline Pipeline , FRDGTransitionQueue & TransitionsToBegin )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
// Submit may be called once for each pipe. The first to submit creates the transition.
if ( ! Transition & & bTransitionNeeded )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
Transition = RHICreateTransition ( PipelinesToBegin , PipelinesToEnd , TransitionFlags , Transitions ) ;
}
2020-07-06 18:58:26 -04:00
2020-11-11 19:22:36 -04:00
if ( Transition )
{
check ( EnumHasAnyFlags ( PipelinesToBegin , Pipeline ) ) ;
EnumRemoveFlags ( PipelinesToBegin , Pipeline ) ;
TransitionsToBegin . Insert ( Transition , TransitionFlags ) ;
}
2020-09-24 00:43:27 -04:00
# if STATS
2020-11-11 19:22:36 -04:00
GRDGStatTransitionBatchCount + + ;
2020-09-24 00:43:27 -04:00
# endif
2020-07-06 18:58:26 -04:00
}
2020-11-11 19:22:36 -04:00
void FRDGBarrierBatchBegin : : Submit ( FRHIComputeCommandList & RHICmdList , ERHIPipeline Pipeline )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
FRDGTransitionQueue TransitionsToBegin ;
Submit ( RHICmdList , Pipeline , TransitionsToBegin ) ;
TransitionsToBegin . Begin ( RHICmdList ) ;
2020-09-24 00:43:27 -04:00
}
2020-07-06 18:58:26 -04:00
void FRDGBarrierBatchEnd : : AddDependency ( FRDGBarrierBatchBegin * BeginBatch )
{
2020-12-07 18:45:31 -04:00
# if RDG_ENABLE_DEBUG
check ( BeginBatch ) ;
for ( ERHIPipeline Pipeline : GetRHIPipelines ( ) )
{
const FRDGPassHandle BeginPassHandle = BeginBatch - > DebugPasses [ Pipeline ] ;
if ( BeginPassHandle . IsValid ( ) )
{
checkf ( BeginPassHandle < = PassHandle , TEXT ( " A transition end batch for pass %d is dependent on begin batch for pass %d. " ) , PassHandle . GetIndex ( ) , BeginPassHandle . GetIndex ( ) ) ;
}
}
# endif
2020-07-06 18:58:26 -04:00
Dependencies . AddUnique ( BeginBatch ) ;
}
2020-11-11 19:22:36 -04:00
void FRDGBarrierBatchEnd : : Submit ( FRHIComputeCommandList & RHICmdList , ERHIPipeline Pipeline )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
FRDGTransitionQueue Transitions ( Dependencies . Num ( ) ) ;
2020-07-06 18:58:26 -04:00
for ( FRDGBarrierBatchBegin * Dependent : Dependencies )
{
2020-11-11 19:22:36 -04:00
if ( EnumHasAnyFlags ( Dependent - > PipelinesToEnd , Pipeline ) )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
check ( Dependent - > Transition ) ;
EnumRemoveFlags ( Dependent - > PipelinesToEnd , Pipeline ) ;
Transitions . Insert ( Dependent - > Transition , Dependent - > TransitionFlags ) ;
2020-07-06 18:58:26 -04:00
}
}
2020-11-11 19:22:36 -04:00
Transitions . End ( RHICmdList ) ;
2020-07-06 18:58:26 -04:00
}
2020-09-24 00:43:27 -04:00
FRDGBarrierBatchBegin & FRDGPass : : GetPrologueBarriersToBegin ( FRDGAllocator & Allocator )
{
if ( ! PrologueBarriersToBegin )
{
2020-11-11 19:22:36 -04:00
PrologueBarriersToBegin = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( Pipeline , Pipeline , TEXT ( " Prologue " ) , this ) ;
2020-09-24 00:43:27 -04:00
}
return * PrologueBarriersToBegin ;
}
FRDGBarrierBatchBegin & FRDGPass : : GetEpilogueBarriersToBeginForGraphics ( FRDGAllocator & Allocator )
{
if ( ! EpilogueBarriersToBeginForGraphics )
{
2020-11-11 19:22:36 -04:00
EpilogueBarriersToBeginForGraphics = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( Pipeline , ERHIPipeline : : Graphics , GetEpilogueBarriersToBeginDebugName ( ERHIPipeline : : Graphics ) , this ) ;
2020-09-24 00:43:27 -04:00
}
return * EpilogueBarriersToBeginForGraphics ;
}
FRDGBarrierBatchBegin & FRDGPass : : GetEpilogueBarriersToBeginForAsyncCompute ( FRDGAllocator & Allocator )
{
if ( ! EpilogueBarriersToBeginForAsyncCompute )
{
2020-11-11 19:22:36 -04:00
EpilogueBarriersToBeginForAsyncCompute = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( Pipeline , ERHIPipeline : : AsyncCompute , GetEpilogueBarriersToBeginDebugName ( ERHIPipeline : : AsyncCompute ) , this ) ;
2020-09-24 00:43:27 -04:00
}
return * EpilogueBarriersToBeginForAsyncCompute ;
}
2020-11-11 19:22:36 -04:00
FRDGBarrierBatchBegin & FRDGPass : : GetEpilogueBarriersToBeginForAll ( FRDGAllocator & Allocator )
{
if ( ! EpilogueBarriersToBeginForAll )
{
EpilogueBarriersToBeginForAll = Allocator . AllocNoDestruct < FRDGBarrierBatchBegin > ( Pipeline , ERHIPipeline : : All , GetEpilogueBarriersToBeginDebugName ( ERHIPipeline : : AsyncCompute ) , this ) ;
}
return * EpilogueBarriersToBeginForAll ;
}
FRDGBarrierBatchEnd & FRDGPass : : GetPrologueBarriersToEnd ( FRDGAllocator & Allocator )
{
if ( ! PrologueBarriersToEnd )
{
2020-12-07 18:45:31 -04:00
PrologueBarriersToEnd = Allocator . AllocNoDestruct < FRDGBarrierBatchEnd > ( Handle ) ;
2020-11-11 19:22:36 -04:00
}
return * PrologueBarriersToEnd ;
}
FRDGBarrierBatchEnd & FRDGPass : : GetEpilogueBarriersToEnd ( FRDGAllocator & Allocator )
{
if ( ! EpilogueBarriersToEnd )
{
2020-12-07 18:45:31 -04:00
EpilogueBarriersToEnd = Allocator . AllocNoDestruct < FRDGBarrierBatchEnd > ( Handle ) ;
2020-11-11 19:22:36 -04:00
}
return * EpilogueBarriersToEnd ;
}
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 ) ;
2021-01-13 16:51:48 -04:00
RHICmdList . SetStaticUniformBuffers ( ParameterStruct . GetStaticUniformBuffers ( ) ) ;
2019-06-11 18:27:07 -04:00
ExecuteImpl ( RHICmdList ) ;
}