2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-07-16 13:08:56 -04:00
# include "RenderGraphValidation.h"
2023-01-27 14:54:10 -05:00
# include "RenderGraphEvent.h"
2020-07-06 18:58:26 -04:00
# include "RenderGraphPrivate.h"
2020-09-24 00:43:27 -04:00
# include "MultiGPU.h"
2023-01-27 14:54:10 -05:00
# include "RenderGraphPass.h"
2019-07-16 13:08:56 -04:00
# if RDG_ENABLE_DEBUG
2020-07-06 18:58:26 -04:00
namespace
{
2020-09-24 00:43:27 -04:00
const ERHIAccess AccessMaskCopy = ERHIAccess : : CopySrc | ERHIAccess : : CopyDest | ERHIAccess : : CPURead ;
2020-11-05 11:20:37 -04:00
const ERHIAccess AccessMaskCompute = ERHIAccess : : SRVCompute | ERHIAccess : : UAVCompute ;
const ERHIAccess AccessMaskRaster = ERHIAccess : : ResolveSrc | ERHIAccess : : ResolveDst | ERHIAccess : : DSVRead | ERHIAccess : : DSVWrite | ERHIAccess : : RTV | ERHIAccess : : SRVGraphics | ERHIAccess : : UAVGraphics | ERHIAccess : : Present | ERHIAccess : : VertexOrIndexBuffer ;
const ERHIAccess AccessMaskComputeOrRaster = ERHIAccess : : IndirectArgs ;
2020-09-24 00:43:27 -04:00
2020-11-18 18:25:03 -04:00
/** Validates that only one builder instance exists at any time. This is currently a requirement for state tracking and allocation lifetimes. */
bool GRDGBuilderActive = false ;
2021-02-18 20:06:45 -04:00
2020-07-06 18:58:26 -04:00
} //! namespace
2019-07-16 13:08:56 -04:00
2020-11-17 17:04:48 -04:00
struct FRDGResourceDebugData
{
/** Boolean to track at runtime whether a resource is actually used by the lambda of a pass or not, to detect unnecessary resource dependencies on passes. */
bool bIsActuallyUsedByPass = false ;
/** Boolean to track at pass execution whether the underlying RHI resource is allowed to be accessed. */
bool bAllowRHIAccess = false ;
} ;
void FRDGResource : : MarkResourceAsUsed ( )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateRHIAccess ( ) ;
2021-04-06 12:38:10 -04:00
GetDebugData ( ) . bIsActuallyUsedByPass = true ;
2020-11-17 17:04:48 -04:00
}
void FRDGResource : : ValidateRHIAccess ( ) const
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-04-06 12:38:10 -04:00
check ( DebugData ) ;
2024-09-03 11:39:06 -04:00
checkf ( DebugData - > bAllowRHIAccess | | GRDGAllowRHIAccess | | GRDGAllowRHIAccessAsync ,
2021-04-06 12:38:10 -04:00
TEXT ( " Accessing the RHI resource of %s at this time is not allowed. If you hit this check in pass, " )
TEXT ( " that is due to this resource not being referenced in the parameters of your pass. " ) ,
Name ) ;
2020-11-17 17:04:48 -04:00
}
FRDGResourceDebugData & FRDGResource : : GetDebugData ( ) const
{
2023-03-17 23:05:14 -04:00
check ( GRDGValidation ! = 0 ) ;
2020-11-17 17:04:48 -04:00
check ( DebugData ) ;
return * DebugData ;
}
2022-03-25 11:19:10 -04:00
struct FRDGViewableResourceDebugData
2020-11-17 17:04:48 -04:00
{
/** Pointer towards the pass that is the first to produce it, for even more convenient error message. */
const FRDGPass * FirstProducer = nullptr ;
/** Count the number of times it has been used by a pass (without culling). */
uint32 PassAccessCount = 0 ;
/** Tracks whether this resource was clobbered by the builder prior to use. */
bool bHasBeenClobbered = false ;
} ;
2022-03-25 11:19:10 -04:00
FRDGViewableResourceDebugData & FRDGViewableResource : : GetViewableDebugData ( ) const
2020-11-17 17:04:48 -04:00
{
2023-03-17 23:05:14 -04:00
check ( GRDGValidation ! = 0 ) ;
2022-03-25 11:19:10 -04:00
check ( ViewableDebugData ) ;
return * ViewableDebugData ;
2020-11-17 17:04:48 -04:00
}
struct FRDGTextureDebugData
{
/** Tracks whether a UAV has ever been allocated to catch when TexCreate_UAV was unneeded. */
bool bHasNeededUAV = false ;
/** Tracks whether has ever been bound as a render target to catch when TexCreate_RenderTargetable was unneeded. */
bool bHasBeenBoundAsRenderTarget = false ;
} ;
FRDGTextureDebugData & FRDGTexture : : GetTextureDebugData ( ) const
{
2023-03-17 23:05:14 -04:00
check ( GRDGValidation ! = 0 ) ;
2020-11-17 17:04:48 -04:00
check ( TextureDebugData ) ;
return * TextureDebugData ;
}
struct FRDGBufferDebugData
{
/** Tracks state changes in order of execution. */
2020-11-18 18:25:03 -04:00
TArray < TPair < FRDGPassHandle , FRDGSubresourceState > , FRDGArrayAllocator > States ;
2020-11-17 17:04:48 -04:00
} ;
FRDGBufferDebugData & FRDGBuffer : : GetBufferDebugData ( ) const
{
2023-03-17 23:05:14 -04:00
check ( GRDGValidation ! = 0 ) ;
2020-11-17 17:04:48 -04:00
check ( BufferDebugData ) ;
return * BufferDebugData ;
}
void FRDGUniformBuffer : : MarkResourceAsUsed ( )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
FRDGResource : : MarkResourceAsUsed ( ) ;
// Individual resources can't be culled from a uniform buffer, so we have to mark them all as used.
ParameterStruct . Enumerate ( [ ] ( FRDGParameter Parameter )
{
if ( FRDGResourceRef Resource = Parameter . GetAsResource ( ) )
{
Resource - > MarkResourceAsUsed ( ) ;
}
} ) ;
}
2024-09-03 11:39:06 -04:00
FRDGUserValidation : : FRDGUserValidation ( FRDGAllocator & InAllocator )
2020-11-17 17:04:48 -04:00
: Allocator ( InAllocator )
2020-11-18 18:25:03 -04:00
{
checkf ( ! GRDGBuilderActive , TEXT ( " Another FRDGBuilder already exists on the stack. Only one builder can be created at a time. This builder instance should be merged into the parent one. " ) ) ;
GRDGBuilderActive = true ;
}
2020-10-23 16:26:52 -04:00
2019-07-16 13:08:56 -04:00
FRDGUserValidation : : ~ FRDGUserValidation ( )
{
checkf ( bHasExecuted , TEXT ( " Render graph execution is required to ensure consistency with immediate mode. " ) ) ;
}
void FRDGUserValidation : : ExecuteGuard ( const TCHAR * Operation , const TCHAR * ResourceName )
{
checkf ( ! bHasExecuted , TEXT ( " Render graph operation '%s' with resource '%s' must be performed prior to graph execution. " ) , Operation , ResourceName ) ;
}
2020-11-17 17:04:48 -04:00
void FRDGUserValidation : : ValidateCreateResource ( FRDGResourceRef Resource )
2019-07-16 13:08:56 -04:00
{
2020-11-17 17:04:48 -04:00
check ( Resource ) ;
2020-11-18 18:25:03 -04:00
Resource - > DebugData = Allocator . Alloc < FRDGResourceDebugData > ( ) ;
2021-04-06 12:38:10 -04:00
bool bAlreadyInSet = false ;
ResourceMap . Emplace ( Resource , & bAlreadyInSet ) ;
check ( ! bAlreadyInSet ) ;
2020-11-17 17:04:48 -04:00
}
2022-03-25 11:19:10 -04:00
void FRDGUserValidation : : ValidateCreateViewableResource ( FRDGViewableResource * Resource )
2020-11-17 17:04:48 -04:00
{
ValidateCreateResource ( Resource ) ;
2024-01-22 11:04:48 -05:00
Resource - > ViewableDebugData = Allocator . AllocNoDestruct < FRDGViewableResourceDebugData > ( ) ;
2020-11-17 17:04:48 -04:00
}
void FRDGUserValidation : : ValidateCreateTexture ( FRDGTextureRef Texture )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2022-03-25 11:19:10 -04:00
ValidateCreateViewableResource ( Texture ) ;
2024-01-22 11:04:48 -05:00
Texture - > TextureDebugData = Allocator . AllocNoDestruct < FRDGTextureDebugData > ( ) ;
2020-07-06 18:58:26 -04:00
if ( GRDGDebug )
2019-09-14 09:45:25 -04:00
{
TrackedTextures . Add ( Texture ) ;
}
2019-07-16 13:08:56 -04:00
}
2019-09-14 09:45:25 -04:00
void FRDGUserValidation : : ValidateCreateBuffer ( FRDGBufferRef Buffer )
2019-07-16 13:08:56 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2022-03-25 11:19:10 -04:00
ValidateCreateViewableResource ( Buffer ) ;
2023-08-25 14:19:21 -04:00
checkf ( Buffer - > Desc . GetSize ( ) > 0 | | Buffer - > NumElementsCallback , TEXT ( " Creating buffer '%s' is zero bytes in size. " ) , Buffer - > Name ) ;
2020-11-18 18:25:03 -04:00
Buffer - > BufferDebugData = Allocator . Alloc < FRDGBufferDebugData > ( ) ;
2020-07-06 18:58:26 -04:00
if ( GRDGDebug )
2019-09-14 09:45:25 -04:00
{
TrackedBuffers . Add ( Buffer ) ;
}
2019-07-16 13:08:56 -04:00
}
2020-11-17 17:04:48 -04:00
void FRDGUserValidation : : ValidateCreateSRV ( FRDGTextureSRVRef SRV )
2019-09-14 09:45:25 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateCreateResource ( SRV ) ;
2019-09-14 09:45:25 -04:00
}
2020-11-17 17:04:48 -04:00
void FRDGUserValidation : : ValidateCreateSRV ( FRDGBufferSRVRef SRV )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateCreateResource ( SRV ) ;
}
void FRDGUserValidation : : ValidateCreateUAV ( FRDGTextureUAVRef UAV )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateCreateResource ( UAV ) ;
}
void FRDGUserValidation : : ValidateCreateUAV ( FRDGBufferUAVRef UAV )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateCreateResource ( UAV ) ;
}
void FRDGUserValidation : : ValidateCreateUniformBuffer ( FRDGUniformBufferRef UniformBuffer )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateCreateResource ( UniformBuffer ) ;
}
void FRDGUserValidation : : ValidateRegisterExternalTexture (
const TRefCountPtr < IPooledRenderTarget > & ExternalPooledTexture ,
const TCHAR * Name ,
ERDGTextureFlags Flags )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2023-08-28 17:50:38 -04:00
checkf ( Name ! = nullptr , TEXT ( " Attempted to register external texture with NULL name. " ) ) ;
2020-11-17 17:04:48 -04:00
checkf ( ExternalPooledTexture . IsValid ( ) , TEXT ( " Attempted to register NULL external texture. " ) ) ;
ExecuteGuard ( TEXT ( " RegisterExternalTexture " ) , Name ) ;
}
void FRDGUserValidation : : ValidateRegisterExternalBuffer ( const TRefCountPtr < FRDGPooledBuffer > & ExternalPooledBuffer , const TCHAR * Name , ERDGBufferFlags Flags )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2023-08-28 17:50:38 -04:00
checkf ( Name ! = nullptr , TEXT ( " Attempted to register external buffer with NULL name. " ) ) ;
2020-11-17 17:04:48 -04:00
checkf ( ExternalPooledBuffer . IsValid ( ) , TEXT ( " Attempted to register NULL external buffer. " ) ) ;
ExecuteGuard ( TEXT ( " RegisterExternalBuffer " ) , Name ) ;
}
void FRDGUserValidation : : ValidateRegisterExternalTexture ( FRDGTextureRef Texture )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateCreateTexture ( Texture ) ;
}
void FRDGUserValidation : : ValidateRegisterExternalBuffer ( FRDGBufferRef Buffer )
2019-09-14 09:45:25 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2019-09-14 09:45:25 -04:00
ValidateCreateBuffer ( Buffer ) ;
2020-11-17 17:04:48 -04:00
}
void FRDGUserValidation : : ValidateCreateTexture ( const FRDGTextureDesc & Desc , const TCHAR * Name , ERDGTextureFlags Flags )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2023-08-28 17:50:38 -04:00
checkf ( Name ! = nullptr , TEXT ( " Creating a texture requires a valid debug name. " ) ) ;
2020-11-17 17:04:48 -04:00
ExecuteGuard ( TEXT ( " CreateTexture " ) , Name ) ;
2022-01-04 04:43:28 -05:00
// Make sure the descriptor is supported by the RHI.
check ( FRDGTextureDesc : : CheckValidity ( Desc , Name ) ) ;
2021-07-27 15:27:05 -04:00
// Can't create back buffer textures
checkf ( ! EnumHasAnyFlags ( Desc . Flags , ETextureCreateFlags : : Presentable ) , TEXT ( " Illegal to create texture %s with presentable flag. " ) , Name ) ;
2020-11-17 17:04:48 -04:00
2021-05-24 14:25:19 -04:00
const bool bCanHaveUAV = EnumHasAnyFlags ( Desc . Flags , TexCreate_UAV ) ;
2020-11-17 17:04:48 -04:00
const bool bIsMSAA = Desc . NumSamples > 1 ;
// D3D11 doesn't allow creating a UAV on MSAA texture.
const bool bIsUAVForMSAATexture = bIsMSAA & & bCanHaveUAV ;
checkf ( ! bIsUAVForMSAATexture , TEXT ( " TexCreate_UAV is not allowed on MSAA texture %s. " ) , Name ) ;
2022-04-25 13:00:12 -04:00
checkf ( ! EnumHasAnyFlags ( Flags , ERDGTextureFlags : : SkipTracking ) , TEXT ( " Cannot create texture %s with the SkipTracking flag. Only registered textures can use this flag. " ) , Name ) ;
2020-11-17 17:04:48 -04:00
}
void FRDGUserValidation : : ValidateCreateBuffer ( const FRDGBufferDesc & Desc , const TCHAR * Name , ERDGBufferFlags Flags )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2023-08-28 17:50:38 -04:00
checkf ( Name ! = nullptr , TEXT ( " Creating a buffer requires a valid debug name. " ) ) ;
2020-11-17 17:04:48 -04:00
ExecuteGuard ( TEXT ( " CreateBuffer " ) , Name ) ;
2022-05-06 15:44:23 -04:00
if ( EnumHasAllFlags ( Desc . Usage , EBufferUsageFlags : : StructuredBuffer | EBufferUsageFlags : : ByteAddressBuffer ) )
2020-11-17 17:04:48 -04:00
{
checkf ( Desc . BytesPerElement = = 4 , TEXT ( " Creating buffer '%s' as a structured buffer that is also byte addressable, BytesPerElement must be 4! Instead it is %d " ) , Name , Desc . BytesPerElement ) ;
}
2022-04-25 13:00:12 -04:00
checkf ( ! EnumHasAnyFlags ( Flags , ERDGBufferFlags : : SkipTracking ) , TEXT ( " Cannot create buffer %s with the SkipTracking flag. Only registered buffers can use this flag. " ) , Name ) ;
2020-11-17 17:04:48 -04:00
}
void FRDGUserValidation : : ValidateCreateSRV ( const FRDGTextureSRVDesc & Desc )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
FRDGTextureRef Texture = Desc . Texture ;
checkf ( Texture , TEXT ( " Texture SRV created with a null texture. " ) ) ;
ExecuteGuard ( TEXT ( " CreateSRV " ) , Texture - > Name ) ;
2022-05-03 08:29:15 -04:00
check ( FRDGTextureSRVDesc : : CheckValidity ( Texture - > Desc , Desc , Texture - > Name ) ) ;
2020-11-17 17:04:48 -04:00
}
void FRDGUserValidation : : ValidateCreateSRV ( const FRDGBufferSRVDesc & Desc )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
FRDGBufferRef Buffer = Desc . Buffer ;
checkf ( Buffer , TEXT ( " Buffer SRV created with a null buffer. " ) ) ;
ExecuteGuard ( TEXT ( " CreateSRV " ) , Buffer - > Name ) ;
}
void FRDGUserValidation : : ValidateCreateUAV ( const FRDGTextureUAVDesc & Desc )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
FRDGTextureRef Texture = Desc . Texture ;
checkf ( Texture , TEXT ( " Texture UAV created with a null texture. " ) ) ;
ExecuteGuard ( TEXT ( " CreateUAV " ) , Texture - > Name ) ;
2021-04-30 11:28:17 -04:00
2021-04-30 13:21:16 -04:00
checkf ( Texture - > Desc . Flags & TexCreate_UAV , TEXT ( " Attempted to create UAV from texture %s which was not created with TexCreate_UAV " ) , Texture - > Name ) ;
2020-11-17 17:04:48 -04:00
checkf ( Desc . MipLevel < Texture - > Desc . NumMips , TEXT ( " Failed to create UAV at mip %d: the texture %s has only %d mip levels. " ) , Desc . MipLevel , Texture - > Name , Texture - > Desc . NumMips ) ;
}
void FRDGUserValidation : : ValidateCreateUAV ( const FRDGBufferUAVDesc & Desc )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
FRDGBufferRef Buffer = Desc . Buffer ;
checkf ( Buffer , TEXT ( " Buffer UAV created with a null buffer. " ) ) ;
ExecuteGuard ( TEXT ( " CreateUAV " ) , Buffer - > Name ) ;
}
void FRDGUserValidation : : ValidateCreateUniformBuffer ( const void * ParameterStruct , const FShaderParametersMetadata * Metadata )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
check ( Metadata ) ;
const TCHAR * Name = Metadata - > GetShaderVariableName ( ) ;
checkf ( ParameterStruct , TEXT ( " Uniform buffer '%s' created with null parameters. " ) , Name ) ;
ExecuteGuard ( TEXT ( " CreateUniformBuffer " ) , Name ) ;
}
2021-05-25 20:46:17 -04:00
void FRDGUserValidation : : ValidateUploadBuffer ( FRDGBufferRef Buffer , const void * InitialData , uint64 InitialDataSize )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-05-25 20:46:17 -04:00
check ( Buffer ) ;
checkf ( ! Buffer - > bQueuedForUpload , TEXT ( " Buffer %s already has an upload queued. Only one upload can be done for each graph. " ) , Buffer - > Name ) ;
check ( InitialData | | InitialDataSize = = 0 ) ;
}
2022-04-25 13:00:12 -04:00
2021-09-01 03:08:48 -04:00
void FRDGUserValidation : : ValidateUploadBuffer ( FRDGBufferRef Buffer , const void * InitialData , uint64 InitialDataSize , const FRDGBufferInitialDataFreeCallback & InitialDataFreeCallback )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-09-01 03:08:48 -04:00
check ( Buffer ) ;
checkf ( ! Buffer - > bQueuedForUpload , TEXT ( " Buffer %s already has an upload queued. Only one upload can be done for each graph. " ) , Buffer - > Name ) ;
check ( ( InitialData | | InitialDataSize = = 0 ) & & InitialDataFreeCallback ) ;
2023-08-28 11:28:40 -04:00
}
void FRDGUserValidation : : ValidateUploadBuffer ( FRDGBufferRef Buffer , const FRDGBufferInitialDataFillCallback & InitialDataFillCallback )
{
if ( ! GRDGValidation )
{
return ;
}
check ( Buffer ) ;
checkf ( ! Buffer - > bQueuedForUpload , TEXT ( " Buffer %s already has an upload queued. Only one upload can be done for each graph. " ) , Buffer - > Name ) ;
check ( InitialDataFillCallback ) ;
2021-09-01 03:08:48 -04:00
}
2021-05-25 20:46:17 -04:00
2021-06-07 12:19:06 -04:00
void FRDGUserValidation : : ValidateUploadBuffer ( FRDGBufferRef Buffer , const FRDGBufferInitialDataCallback & InitialDataCallback , const FRDGBufferInitialDataSizeCallback & InitialDataSizeCallback )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-06-07 12:19:06 -04:00
check ( Buffer ) ;
checkf ( ! Buffer - > bQueuedForUpload , TEXT ( " Buffer %s already has an upload queued. Only one upload can be done for each graph. " ) , Buffer - > Name ) ;
check ( InitialDataCallback & & InitialDataSizeCallback ) ;
}
2021-09-01 03:08:48 -04:00
void FRDGUserValidation : : ValidateUploadBuffer ( FRDGBufferRef Buffer , const FRDGBufferInitialDataCallback & InitialDataCallback , const FRDGBufferInitialDataSizeCallback & InitialDataSizeCallback , const FRDGBufferInitialDataFreeCallback & InitialDataFreeCallback )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-09-01 03:08:48 -04:00
check ( Buffer ) ;
checkf ( ! Buffer - > bQueuedForUpload , TEXT ( " Buffer %s already has an upload queued. Only one upload can be done for each graph. " ) , Buffer - > Name ) ;
check ( InitialDataCallback & & InitialDataSizeCallback & & InitialDataFreeCallback ) ;
}
2023-11-09 21:34:39 -05:00
void FRDGUserValidation : : ValidateCommitBuffer ( FRDGBufferRef Buffer , uint64 CommitSizeInBytes )
{
if ( ! GRDGValidation )
{
return ;
}
check ( Buffer ) ;
checkf ( EnumHasAnyFlags ( Buffer - > Desc . Usage , BUF_ReservedResource ) , TEXT ( " Buffer %s is not marked as reserved and thus cannot be queued for reserved resource commit. " ) , Buffer - > Name ) ;
checkf ( Buffer - > IsExternal ( ) , TEXT ( " Only external buffers support commit operation. It is expected that reserved resource commit mechanism is only used when perserving buffer contents is required. " ) ) ;
checkf ( CommitSizeInBytes > 0 , TEXT ( " Attempted to set a reserved buffer commit size of 0 for buffer %s " ) , Buffer - > Name ) ;
}
2020-11-17 17:04:48 -04:00
void FRDGUserValidation : : ValidateExtractTexture ( FRDGTextureRef Texture , TRefCountPtr < IPooledRenderTarget > * OutTexturePtr )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateExtractResource ( Texture ) ;
checkf ( OutTexturePtr , TEXT ( " Texture %s was extracted, but the output texture pointer is null. " ) , Texture - > Name ) ;
}
void FRDGUserValidation : : ValidateExtractBuffer ( FRDGBufferRef Buffer , TRefCountPtr < FRDGPooledBuffer > * OutBufferPtr )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ValidateExtractResource ( Buffer ) ;
checkf ( OutBufferPtr , TEXT ( " Texture %s was extracted, but the output texture pointer is null. " ) , Buffer - > Name ) ;
2019-09-14 09:45:25 -04:00
}
2022-03-25 11:19:10 -04:00
void FRDGUserValidation : : ValidateExtractResource ( FRDGViewableResource * Resource )
2019-07-16 13:08:56 -04:00
{
check ( Resource ) ;
2021-05-25 20:46:17 -04:00
checkf ( Resource - > bProduced | | Resource - > bExternal | | Resource - > bQueuedForUpload ,
2019-07-16 13:08:56 -04:00
TEXT ( " Unable to queue the extraction of the resource %s because it has not been produced by any pass. " ) ,
Resource - > Name ) ;
/** Increment pass access counts for externally registered buffers and textures to avoid
* emitting a ' produced but never used ' warning . We don ' t have the history of registered
* resources to be able to emit a proper warning .
*/
2022-03-25 11:19:10 -04:00
Resource - > GetViewableDebugData ( ) . PassAccessCount + + ;
2019-07-16 13:08:56 -04:00
}
2022-03-25 11:19:10 -04:00
void FRDGUserValidation : : ValidateConvertToExternalResource ( FRDGViewableResource * Resource )
2021-05-19 17:54:58 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-05-19 17:54:58 -04:00
check ( Resource ) ;
checkf ( ! bHasExecuteBegun | | ! Resource - > bTransient ,
TEXT ( " Unable to convert resource %s to external because passes in the graph have already executed. " ) ,
Resource - > Name ) ;
}
2023-01-18 06:10:35 -05:00
void FRDGUserValidation : : ValidateConvertToExternalUniformBuffer ( FRDGUniformBuffer * UniformBuffer )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2023-01-18 06:10:35 -05:00
check ( UniformBuffer ) ;
checkf ( ! bHasExecuteBegun ,
TEXT ( " Unable to convert uniform buffer %s to external because passes in the graph have already executed. " ) ,
UniformBuffer - > GetLayoutName ( ) ) ;
}
2022-03-25 11:19:10 -04:00
void FRDGUserValidation : : RemoveUnusedWarning ( FRDGViewableResource * Resource )
2019-07-16 13:08:56 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2019-07-16 13:08:56 -04:00
check ( Resource ) ;
2020-11-17 17:04:48 -04:00
ExecuteGuard ( TEXT ( " RemoveUnusedResourceWarning " ) , Resource - > Name ) ;
2019-09-14 09:45:25 -04:00
// Removes 'produced but not used' warning.
2022-03-25 11:19:10 -04:00
Resource - > GetViewableDebugData ( ) . PassAccessCount + + ;
2019-09-14 09:45:25 -04:00
// Removes 'not used' warning.
2020-11-17 17:04:48 -04:00
Resource - > GetDebugData ( ) . bIsActuallyUsedByPass = true ;
2020-07-06 18:58:26 -04:00
}
2022-03-25 11:19:10 -04:00
bool FRDGUserValidation : : TryMarkForClobber ( FRDGViewableResource * Resource ) const
2020-07-06 18:58:26 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return false ;
}
2020-11-17 17:04:48 -04:00
check ( Resource ) ;
2022-03-25 11:19:10 -04:00
FRDGViewableResourceDebugData & DebugData = Resource - > GetViewableDebugData ( ) ;
2020-11-17 17:04:48 -04:00
2022-03-30 11:30:02 -04:00
const bool bClobber = ! DebugData . bHasBeenClobbered & & ! Resource - > bExternal & & ! Resource - > bQueuedForUpload & & IsDebugAllowedForResource ( Resource - > Name ) ;
2020-07-06 18:58:26 -04:00
if ( bClobber )
{
2020-11-17 17:04:48 -04:00
DebugData . bHasBeenClobbered = true ;
2020-07-06 18:58:26 -04:00
}
return bClobber ;
2019-07-16 13:08:56 -04:00
}
2020-11-17 17:04:48 -04:00
void FRDGUserValidation : : ValidateGetPooledTexture ( FRDGTextureRef Texture ) const
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
check ( Texture ) ;
checkf ( Texture - > bExternal , TEXT ( " GetPooledTexture called on texture %s, but it is not external. Call PreallocateTexture or register as an external texture instead. " ) , Texture - > Name ) ;
}
void FRDGUserValidation : : ValidateGetPooledBuffer ( FRDGBufferRef Buffer ) const
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
check ( Buffer ) ;
checkf ( Buffer - > bExternal , TEXT ( " GetPooledBuffer called on buffer %s, but it is not external. Call PreallocateBuffer or register as an external buffer instead. " ) , Buffer - > Name ) ;
}
2022-03-25 11:19:10 -04:00
void FRDGUserValidation : : ValidateSetAccessFinal ( FRDGViewableResource * Resource , ERHIAccess AccessFinal )
2020-11-17 17:04:48 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-04-06 11:45:09 -04:00
check ( Resource ) ;
2020-11-17 17:04:48 -04:00
check ( AccessFinal ! = ERHIAccess : : Unknown & & IsValidAccess ( AccessFinal ) ) ;
2021-04-06 11:45:09 -04:00
checkf ( Resource - > bExternal | | Resource - > bExtracted , TEXT ( " Cannot set final access on non-external resource '%s' unless it is first extracted or preallocated. " ) , Resource - > Name ) ;
2022-04-25 13:00:12 -04:00
checkf ( Resource - > AccessModeState . Mode = = FRDGViewableResource : : EAccessMode : : Internal , TEXT ( " Cannot set final access on a resource in external access mode: %s. " ) , Resource - > Name ) ;
2020-11-17 17:04:48 -04:00
}
2022-04-25 13:00:12 -04:00
void FRDGUserValidation : : ValidateUseExternalAccessMode ( FRDGViewableResource * Resource , ERHIAccess ReadOnlyAccess , ERHIPipeline Pipelines )
2020-11-17 17:04:48 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2021-04-06 11:45:09 -04:00
check ( Resource ) ;
2022-04-25 13:00:12 -04:00
check ( Pipelines ! = ERHIPipeline : : None ) ;
const auto & AccessModeState = Resource - > AccessModeState ;
checkf ( ! AccessModeState . bLocked , TEXT ( " Resource is locked in external access mode by the SkipTracking resource flag: %s. " ) , Resource - > Name ) ;
2022-05-02 18:31:37 -04:00
checkf ( IsReadOnlyExclusiveAccess ( ReadOnlyAccess ) , TEXT ( " A read only access is required when use external access mode. (Resource: %s, Access: %s, Pipelines: %s) " ) , Resource - > Name , * GetRHIAccessName ( ReadOnlyAccess ) , * GetRHIPipelineName ( Pipelines ) ) ;
2022-04-25 13:00:12 -04:00
checkf (
AccessModeState . Mode = = FRDGViewableResource : : EAccessMode : : Internal | |
( AccessModeState . Access = = ReadOnlyAccess & & AccessModeState . Pipelines = = Pipelines ) ,
TEXT ( " UseExternalAccessMode called on a resource that is already in external access mode, but different parameters were used. \n " )
TEXT ( " Resource: %s \n " )
TEXT ( " \t Existing Access: %s, Requested Access: %s \n " )
TEXT ( " \t Existing Pipelines: %s, Requested Pipelines: %s \n " ) ,
Resource - > Name , * GetRHIAccessName ( AccessModeState . Access ) , * GetRHIAccessName ( ReadOnlyAccess ) , * GetRHIPipelineName ( AccessModeState . Pipelines ) , * GetRHIPipelineName ( Pipelines ) ) ;
2022-05-02 18:31:37 -04:00
checkf ( EnumHasAnyFlags ( Pipelines , ERHIPipeline : : Graphics ) | | ! EnumHasAnyFlags ( ReadOnlyAccess , AccessMaskRaster ) ,
TEXT ( " Raster access flags were specified for external access but the graphics pipe was not specified. \n " )
TEXT ( " Resource: %s \n " )
TEXT ( " \t Requested Access: %s \n " )
TEXT ( " \t Requested Pipelines: %s \n " ) ,
Resource - > Name , * GetRHIAccessName ( ReadOnlyAccess ) , * GetRHIPipelineName ( Pipelines ) ) ;
2021-04-06 11:45:09 -04:00
}
2022-04-25 13:00:12 -04:00
void FRDGUserValidation : : ValidateUseInternalAccessMode ( FRDGViewableResource * Resource )
2021-04-06 11:45:09 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2022-04-25 13:00:12 -04:00
check ( Resource ) ;
2021-04-06 11:45:09 -04:00
2022-04-25 13:00:12 -04:00
const auto & AccessModeState = Resource - > AccessModeState ;
checkf ( ! AccessModeState . bLocked , TEXT ( " Resource is locked in external access mode by the SkipTracking resource flag: %s. " ) , Resource - > Name ) ;
}
void FRDGUserValidation : : ValidateExternalAccess ( FRDGViewableResource * Resource , ERHIAccess Access , const FRDGPass * Pass )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2022-04-25 13:00:12 -04:00
const auto & AccessModeState = Resource - > AccessModeState ;
ensureMsgf ( EnumHasAnyFlags ( AccessModeState . Access , Access ) ,
TEXT ( " Resource %s is in external access mode and is valid for access with the following states: %s, but is being used in pass %s with access %s. " ) ,
Resource - > Name , * GetRHIAccessName ( AccessModeState . Access ) , Pass - > GetName ( ) , * GetRHIAccessName ( Access ) ) ;
ensureMsgf ( EnumHasAnyFlags ( AccessModeState . Pipelines , Pass - > GetPipeline ( ) ) ,
TEXT ( " Resource %s is in external access mode and is valid for access on the following pipelines: %s, but is being used on the %s pipe in pass %s. " ) ,
Resource - > Name , * GetRHIPipelineName ( AccessModeState . Pipelines ) , * GetRHIPipelineName ( Pass - > GetPipeline ( ) ) , Pass - > GetName ( ) ) ;
2020-11-17 17:04:48 -04:00
}
2022-05-16 11:02:52 -04:00
void FRDGUserValidation : : ValidateAddSubresourceAccess ( FRDGViewableResource * Resource , const FRDGSubresourceState & Subresource , ERHIAccess Access )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2022-05-16 11:02:52 -04:00
const bool bOldAccessMergeable = EnumHasAnyFlags ( Subresource . Access , GRHIMergeableAccessMask ) | | Subresource . Access = = ERHIAccess : : Unknown ;
const bool bNewAccessMergeable = EnumHasAnyFlags ( Access , GRHIMergeableAccessMask ) ;
checkf ( bOldAccessMergeable | | bNewAccessMergeable | | Subresource . Access = = Access ,
TEXT ( " Resource %s has incompatible access states specified for the same subresource. AccessBefore: %s, AccessAfter: %s. " ) ,
Resource - > Name , * GetRHIAccessName ( Subresource . Access ) , * GetRHIAccessName ( Access ) ) ;
}
2020-11-17 17:04:48 -04:00
void FRDGUserValidation : : ValidateAddPass ( const FRDGEventName & Name , ERDGPassFlags Flags )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
ExecuteGuard ( TEXT ( " AddPass " ) , Name . GetTCHAR ( ) ) ;
checkf ( ! EnumHasAnyFlags ( Flags , ERDGPassFlags : : Copy | ERDGPassFlags : : Compute | ERDGPassFlags : : AsyncCompute | ERDGPassFlags : : Raster ) ,
TEXT ( " Pass %s may not specify any of the (Copy, Compute, AsyncCompute, Raster) flags, because it has no parameters. Use None instead. " ) , Name . GetTCHAR ( ) ) ;
}
void FRDGUserValidation : : ValidateAddPass ( const void * ParameterStruct , const FShaderParametersMetadata * Metadata , const FRDGEventName & Name , ERDGPassFlags Flags )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-11-17 17:04:48 -04:00
checkf ( ParameterStruct , TEXT ( " Pass '%s' created with null parameters. " ) , Name . GetTCHAR ( ) ) ;
ExecuteGuard ( TEXT ( " AddPass " ) , Name . GetTCHAR ( ) ) ;
2021-02-18 20:06:45 -04:00
checkf ( EnumHasAnyFlags ( Flags , ERDGPassFlags : : Raster | ERDGPassFlags : : Compute | ERDGPassFlags : : AsyncCompute | ERDGPassFlags : : Copy ) ,
2020-11-17 17:04:48 -04:00
TEXT ( " Pass %s must specify at least one of the following flags: (Copy, Compute, AsyncCompute, Raster) " ) , Name . GetTCHAR ( ) ) ;
checkf ( ! EnumHasAllFlags ( Flags , ERDGPassFlags : : Compute | ERDGPassFlags : : AsyncCompute ) ,
TEXT ( " Pass %s specified both Compute and AsyncCompute. They are mutually exclusive. " ) , Name . GetTCHAR ( ) ) ;
checkf ( ! EnumHasAllFlags ( Flags , ERDGPassFlags : : Raster | ERDGPassFlags : : AsyncCompute ) ,
TEXT ( " Pass %s specified both Raster and AsyncCompute. They are mutually exclusive. " ) , Name . GetTCHAR ( ) ) ;
checkf ( ! EnumHasAllFlags ( Flags , ERDGPassFlags : : SkipRenderPass ) | | EnumHasAllFlags ( Flags , ERDGPassFlags : : Raster ) ,
2023-08-31 08:56:30 -04:00
TEXT ( " Pass %s specified SkipRenderPass without Raster. Only raster passes support this flag. " ) , Name . GetTCHAR ( ) ) ;
2021-04-12 15:36:14 -04:00
checkf ( ! EnumHasAllFlags ( Flags , ERDGPassFlags : : NeverMerge ) | | EnumHasAllFlags ( Flags , ERDGPassFlags : : Raster ) ,
2023-08-31 08:56:30 -04:00
TEXT ( " Pass %s specified NeverMerge without Raster. Only raster passes support this flag. " ) , Name . GetTCHAR ( ) ) ;
2020-11-17 17:04:48 -04:00
}
2019-09-14 09:45:25 -04:00
void FRDGUserValidation : : ValidateAddPass ( const FRDGPass * Pass , bool bSkipPassAccessMarking )
2019-07-16 13:08:56 -04:00
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2019-07-16 13:08:56 -04:00
const FRenderTargetBindingSlots * RenderTargetBindingSlots = nullptr ;
2020-07-06 18:58:26 -04:00
// Pass flags are validated as early as possible by the builder in AddPass.
const ERDGPassFlags PassFlags = Pass - > GetFlags ( ) ;
2020-09-24 00:43:27 -04:00
const FRDGParameterStruct PassParameters = Pass - > GetParameters ( ) ;
2019-07-16 13:08:56 -04:00
const TCHAR * PassName = Pass - > GetName ( ) ;
2020-07-06 18:58:26 -04:00
const bool bIsRaster = EnumHasAnyFlags ( PassFlags , ERDGPassFlags : : Raster ) ;
const bool bIsCopy = EnumHasAnyFlags ( PassFlags , ERDGPassFlags : : Copy ) ;
2020-09-24 00:43:27 -04:00
const bool bIsAnyCompute = EnumHasAnyFlags ( PassFlags , ERDGPassFlags : : Compute | ERDGPassFlags : : AsyncCompute ) ;
const bool bSkipRenderPass = EnumHasAnyFlags ( PassFlags , ERDGPassFlags : : SkipRenderPass ) ;
2019-09-14 09:45:25 -04:00
2022-03-25 11:19:10 -04:00
const auto MarkAsProduced = [ & ] ( FRDGViewableResource * Resource )
2019-09-14 09:45:25 -04:00
{
2020-07-06 18:58:26 -04:00
if ( ! bSkipPassAccessMarking )
2019-09-14 09:45:25 -04:00
{
2022-03-25 11:19:10 -04:00
auto & Debug = Resource - > GetViewableDebugData ( ) ;
2020-11-17 17:04:48 -04:00
if ( ! Debug . FirstProducer )
2020-07-06 18:58:26 -04:00
{
Debug . FirstProducer = Pass ;
}
Debug . PassAccessCount + + ;
2019-09-14 09:45:25 -04:00
}
2020-07-06 18:58:26 -04:00
} ;
2019-07-16 13:08:56 -04:00
2022-03-25 11:19:10 -04:00
const auto MarkAsConsumed = [ & ] ( FRDGViewableResource * Resource )
2019-07-16 13:08:56 -04:00
{
2021-05-25 20:46:17 -04:00
ensureMsgf ( Resource - > bProduced | | Resource - > bExternal | | Resource - > bQueuedForUpload ,
2020-07-06 18:58:26 -04:00
TEXT ( " Pass %s has a read dependency on %s, but it was never written to. " ) ,
PassName , Resource - > Name ) ;
if ( ! bSkipPassAccessMarking )
{
2022-03-25 11:19:10 -04:00
Resource - > GetViewableDebugData ( ) . PassAccessCount + + ;
2020-07-06 18:58:26 -04:00
}
} ;
2021-04-06 12:38:10 -04:00
const auto CheckValidResource = [ & ] ( FRDGResourceRef Resource )
2020-09-24 00:43:27 -04:00
{
2021-04-06 12:38:10 -04:00
checkf ( ResourceMap . Contains ( Resource ) , TEXT ( " Resource at %p registered with pass %s is not part of the graph and is likely a dangling pointer or garbage value. " ) , Resource , Pass - > GetName ( ) ) ;
2020-09-24 00:43:27 -04:00
} ;
2023-01-24 07:02:08 -05:00
const auto CheckComputeOrRaster = [ & ] ( FRDGResourceRef Resource )
2020-07-06 18:58:26 -04:00
{
2023-01-24 07:02:08 -05:00
ensureMsgf ( bIsAnyCompute | | bIsRaster , TEXT ( " Pass %s, parameter %s is valid for Raster or (Async)Compute, but neither flag is set. " ) , PassName , Resource - > Name ) ;
2020-07-06 18:58:26 -04:00
} ;
2020-09-24 00:43:27 -04:00
bool bCanProduce = false ;
2020-07-06 18:58:26 -04:00
2022-03-25 11:19:10 -04:00
const auto CheckResourceAccess = [ & ] ( FRDGViewableResource * Resource , ERHIAccess Access )
2021-04-02 20:35:50 -04:00
{
checkf ( bIsCopy | | ! EnumHasAnyFlags ( Access , AccessMaskCopy ) , TEXT ( " Pass '%s' uses resource '%s' with access '%s' containing states which require the 'ERDGPass::Copy' flag. " ) , Pass - > GetName ( ) , Resource - > Name , * GetRHIAccessName ( Access ) ) ;
checkf ( bIsAnyCompute | | ! EnumHasAnyFlags ( Access , AccessMaskCompute ) , TEXT ( " Pass '%s' uses resource '%s' with access '%s' containing states which require the 'ERDGPass::Compute' or 'ERDGPassFlags::AsyncCompute' flag. " ) , Pass - > GetName ( ) , Resource - > Name , * GetRHIAccessName ( Access ) ) ;
checkf ( bIsRaster | | ! EnumHasAnyFlags ( Access , AccessMaskRaster ) , TEXT ( " Pass '%s' uses resource '%s' with access '%s' containing states which require the 'ERDGPass::Raster' flag. " ) , Pass - > GetName ( ) , Resource - > Name , * GetRHIAccessName ( Access ) ) ;
checkf ( bIsAnyCompute | | bIsRaster | | ! EnumHasAnyFlags ( Access , AccessMaskComputeOrRaster ) , TEXT ( " Pass '%s' uses resource '%s' with access '%s' containing states which require the 'ERDGPassFlags::Compute' or 'ERDGPassFlags::AsyncCompute' or 'ERDGPass::Raster' flag. " ) , Pass - > GetName ( ) , Resource - > Name , * GetRHIAccessName ( Access ) ) ;
} ;
const auto CheckBufferAccess = [ & ] ( FRDGBufferRef Buffer , ERHIAccess Access )
{
CheckResourceAccess ( Buffer , Access ) ;
if ( IsWritableAccess ( Access ) )
{
2022-04-25 13:00:12 -04:00
MarkAsProduced ( Buffer ) ;
2021-04-06 11:45:09 -04:00
bCanProduce = true ;
2021-04-02 20:35:50 -04:00
}
} ;
const auto CheckTextureAccess = [ & ] ( FRDGTextureRef Texture , ERHIAccess Access )
{
CheckResourceAccess ( Texture , Access ) ;
if ( IsWritableAccess ( Access ) )
{
2022-04-25 13:00:12 -04:00
MarkAsProduced ( Texture ) ;
2021-04-06 11:45:09 -04:00
bCanProduce = true ;
2021-04-02 20:35:50 -04:00
}
} ;
2020-09-24 00:43:27 -04:00
PassParameters . Enumerate ( [ & ] ( FRDGParameter Parameter )
2020-07-06 18:58:26 -04:00
{
2021-04-06 12:38:10 -04:00
if ( Parameter . IsResource ( ) )
2020-09-24 00:43:27 -04:00
{
2021-04-06 12:38:10 -04:00
if ( FRDGResourceRef Resource = Parameter . GetAsResource ( ) )
2020-09-24 00:43:27 -04:00
{
2021-04-06 12:38:10 -04:00
CheckValidResource ( Resource ) ;
2020-09-24 00:43:27 -04:00
}
}
2019-07-16 13:08:56 -04:00
switch ( Parameter . GetType ( ) )
{
case UBMT_RDG_TEXTURE :
{
if ( FRDGTextureRef Texture = Parameter . GetAsTexture ( ) )
{
2019-09-14 09:45:25 -04:00
MarkAsConsumed ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
}
break ;
case UBMT_RDG_TEXTURE_SRV :
2024-04-23 17:02:48 -04:00
case UBMT_RDG_TEXTURE_NON_PIXEL_SRV :
2019-07-16 13:08:56 -04:00
{
if ( FRDGTextureSRVRef SRV = Parameter . GetAsTextureSRV ( ) )
{
2019-09-14 09:45:25 -04:00
FRDGTextureRef Texture = SRV - > GetParent ( ) ;
2023-01-24 07:02:08 -05:00
CheckComputeOrRaster ( Texture ) ;
2019-09-14 09:45:25 -04:00
MarkAsConsumed ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
}
break ;
case UBMT_RDG_TEXTURE_UAV :
{
2020-09-24 00:43:27 -04:00
bCanProduce = true ;
2019-07-16 13:08:56 -04:00
if ( FRDGTextureUAVRef UAV = Parameter . GetAsTextureUAV ( ) )
{
2019-09-14 09:45:25 -04:00
FRDGTextureRef Texture = UAV - > GetParent ( ) ;
2023-01-24 07:02:08 -05:00
CheckComputeOrRaster ( Texture ) ;
2022-04-25 13:00:12 -04:00
MarkAsProduced ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
}
break ;
case UBMT_RDG_BUFFER_SRV :
{
if ( FRDGBufferSRVRef SRV = Parameter . GetAsBufferSRV ( ) )
{
2019-09-14 09:45:25 -04:00
FRDGBufferRef Buffer = SRV - > GetParent ( ) ;
2023-01-24 07:02:08 -05:00
CheckComputeOrRaster ( Buffer ) ;
2019-09-14 09:45:25 -04:00
MarkAsConsumed ( Buffer ) ;
2019-07-16 13:08:56 -04:00
}
}
break ;
case UBMT_RDG_BUFFER_UAV :
{
2020-09-24 00:43:27 -04:00
bCanProduce = true ;
2019-07-16 13:08:56 -04:00
if ( FRDGBufferUAVRef UAV = Parameter . GetAsBufferUAV ( ) )
{
2019-09-14 09:45:25 -04:00
FRDGBufferRef Buffer = UAV - > GetParent ( ) ;
2023-01-24 07:02:08 -05:00
CheckComputeOrRaster ( Buffer ) ;
2022-04-25 13:00:12 -04:00
MarkAsProduced ( Buffer ) ;
2019-09-14 09:45:25 -04:00
}
}
break ;
2020-09-24 00:43:27 -04:00
case UBMT_RDG_TEXTURE_ACCESS :
2019-09-14 09:45:25 -04:00
{
2021-04-02 20:35:50 -04:00
FRDGTextureAccess TextureAccess = Parameter . GetAsTextureAccess ( ) ;
bCanProduce | = IsWritableAccess ( TextureAccess . GetAccess ( ) ) ;
2020-09-24 00:43:27 -04:00
2021-04-02 20:35:50 -04:00
if ( TextureAccess )
2019-09-14 09:45:25 -04:00
{
2021-04-02 20:35:50 -04:00
CheckTextureAccess ( TextureAccess . GetTexture ( ) , TextureAccess . GetAccess ( ) ) ;
}
}
break ;
case UBMT_RDG_TEXTURE_ACCESS_ARRAY :
{
const FRDGTextureAccessArray & TextureAccessArray = Parameter . GetAsTextureAccessArray ( ) ;
2020-09-24 00:43:27 -04:00
2021-04-06 11:45:09 -04:00
for ( FRDGTextureAccess TextureAccess : TextureAccessArray )
2021-04-02 20:35:50 -04:00
{
2021-04-06 11:45:09 -04:00
CheckTextureAccess ( TextureAccess . GetTexture ( ) , TextureAccess . GetAccess ( ) ) ;
2019-09-14 09:45:25 -04:00
}
}
break ;
2020-09-24 00:43:27 -04:00
case UBMT_RDG_BUFFER_ACCESS :
2019-09-14 09:45:25 -04:00
{
2021-04-02 20:35:50 -04:00
FRDGBufferAccess BufferAccess = Parameter . GetAsBufferAccess ( ) ;
2020-09-24 00:43:27 -04:00
2021-04-02 20:35:50 -04:00
if ( BufferAccess )
2019-09-14 09:45:25 -04:00
{
2021-04-02 20:35:50 -04:00
CheckBufferAccess ( BufferAccess . GetBuffer ( ) , BufferAccess . GetAccess ( ) ) ;
}
}
break ;
case UBMT_RDG_BUFFER_ACCESS_ARRAY :
{
const FRDGBufferAccessArray & BufferAccessArray = Parameter . GetAsBufferAccessArray ( ) ;
2020-09-24 00:43:27 -04:00
2021-04-06 11:45:09 -04:00
for ( FRDGBufferAccess BufferAccess : BufferAccessArray )
2021-04-02 20:35:50 -04:00
{
2021-04-06 11:45:09 -04:00
CheckBufferAccess ( BufferAccess . GetBuffer ( ) , BufferAccess . GetAccess ( ) ) ;
2019-07-16 13:08:56 -04:00
}
}
break ;
case UBMT_RENDER_TARGET_BINDING_SLOTS :
{
2020-07-06 18:58:26 -04:00
RenderTargetBindingSlots = & Parameter . GetAsRenderTargetBindingSlots ( ) ;
2020-09-24 00:43:27 -04:00
bCanProduce = true ;
2019-07-16 13:08:56 -04:00
}
break ;
}
2020-09-24 00:43:27 -04:00
} ) ;
checkf ( bCanProduce | | EnumHasAnyFlags ( PassFlags , ERDGPassFlags : : NeverCull ) | | PassParameters . HasExternalOutputs ( ) ,
TEXT ( " Pass '%s' has no graph parameters defined on its parameter struct and did not specify 'NeverCull'. The pass will always be culled. " ) , PassName ) ;
2019-07-16 13:08:56 -04:00
/** Validate that raster passes have render target binding slots and compute passes don't. */
if ( RenderTargetBindingSlots )
{
2020-07-06 18:58:26 -04:00
checkf ( bIsRaster , TEXT ( " Pass '%s' has render target binding slots but is not set to 'Raster'. " ) , PassName ) ;
2019-07-16 13:08:56 -04:00
}
else
{
2020-09-24 00:43:27 -04:00
checkf ( ! bIsRaster | | bSkipRenderPass , TEXT ( " Pass '%s' is set to 'Raster' but is missing render target binding slots. Use 'SkipRenderPass' if this is desired. " ) , PassName ) ;
2019-07-16 13:08:56 -04:00
}
/** Validate render target / depth stencil binding usage. */
if ( RenderTargetBindingSlots )
{
const auto & RenderTargets = RenderTargetBindingSlots - > Output ;
{
2021-03-05 18:33:15 -04:00
if ( FRDGTextureRef Texture = RenderTargetBindingSlots - > ShadingRateTexture )
2021-03-05 16:16:14 -04:00
{
2021-04-06 12:38:10 -04:00
CheckValidResource ( Texture ) ;
2021-03-05 16:16:14 -04:00
MarkAsConsumed ( Texture ) ;
}
2019-07-16 13:08:56 -04:00
const auto & DepthStencil = RenderTargetBindingSlots - > DepthStencil ;
2020-09-24 00:43:27 -04:00
const auto CheckDepthStencil = [ & ] ( FRDGTextureRef Texture )
2019-07-16 13:08:56 -04:00
{
// Depth stencil only supports one mip, since there isn't actually a way to select the mip level.
check ( Texture - > Desc . NumMips = = 1 ) ;
2021-04-06 12:38:10 -04:00
CheckValidResource ( Texture ) ;
2019-07-16 13:08:56 -04:00
if ( DepthStencil . GetDepthStencilAccess ( ) . IsAnyWrite ( ) )
{
2022-04-25 13:00:12 -04:00
MarkAsProduced ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
else
{
2019-09-14 09:45:25 -04:00
MarkAsConsumed ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
2020-09-24 00:43:27 -04:00
} ;
FRDGTextureRef Texture = DepthStencil . GetTexture ( ) ;
if ( Texture )
{
checkf (
EnumHasAnyFlags ( Texture - > Desc . Flags , TexCreate_DepthStencilTargetable | TexCreate_DepthStencilResolveTarget ) ,
TEXT ( " Pass '%s' attempted to bind texture '%s' as a depth stencil render target, but the texture has not been created with TexCreate_DepthStencilTargetable. " ) ,
PassName , Texture - > Name ) ;
CheckDepthStencil ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
}
const uint32 RenderTargetCount = RenderTargets . Num ( ) ;
{
/** Tracks the number of contiguous, non-null textures in the render target output array. */
2021-06-23 17:51:32 -04:00
uint32 ValidRenderTargetCount = RenderTargetCount ;
2019-07-16 13:08:56 -04:00
for ( uint32 RenderTargetIndex = 0 ; RenderTargetIndex < RenderTargetCount ; + + RenderTargetIndex )
{
const FRenderTargetBinding & RenderTarget = RenderTargets [ RenderTargetIndex ] ;
2020-09-24 00:43:27 -04:00
FRDGTextureRef Texture = RenderTarget . GetTexture ( ) ;
FRDGTextureRef ResolveTexture = RenderTarget . GetResolveTexture ( ) ;
if ( ResolveTexture & & ResolveTexture ! = Texture )
2019-07-16 13:08:56 -04:00
{
2020-09-24 00:43:27 -04:00
checkf ( RenderTarget . GetTexture ( ) , TEXT ( " Pass %s specified resolve target '%s' with a null render target. " ) , PassName , ResolveTexture - > Name ) ;
2019-07-23 17:49:47 -04:00
ensureMsgf (
2020-09-24 00:43:27 -04:00
EnumHasAnyFlags ( ResolveTexture - > Desc . Flags , TexCreate_ResolveTargetable ) ,
TEXT ( " Pass '%s' attempted to bind texture '%s' as a render target, but the texture has not been created with TexCreate_ResolveTargetable. " ) ,
PassName , ResolveTexture - > Name ) ;
2021-04-06 12:38:10 -04:00
CheckValidResource ( Texture ) ;
2022-04-25 13:00:12 -04:00
MarkAsProduced ( ResolveTexture ) ;
2020-09-24 00:43:27 -04:00
}
if ( Texture )
{
ensureMsgf (
EnumHasAnyFlags ( Texture - > Desc . Flags , TexCreate_RenderTargetable | TexCreate_ResolveTargetable ) ,
2019-07-23 17:49:47 -04:00
TEXT ( " Pass '%s' attempted to bind texture '%s' as a render target, but the texture has not been created with TexCreate_RenderTargetable. " ) ,
PassName , Texture - > Name ) ;
2021-04-06 12:38:10 -04:00
CheckValidResource ( Texture ) ;
2019-07-23 17:49:47 -04:00
2019-07-16 13:08:56 -04:00
/** Mark the pass as a producer for render targets with a store action. */
2022-04-25 13:00:12 -04:00
MarkAsProduced ( Texture ) ;
2019-07-16 13:08:56 -04:00
}
else
{
/** Found end of contiguous interval of valid render targets. */
ValidRenderTargetCount = RenderTargetIndex ;
break ;
}
}
/** Validate that no holes exist in the render target output array. Render targets must be bound contiguously. */
for ( uint32 RenderTargetIndex = ValidRenderTargetCount ; RenderTargetIndex < RenderTargetCount ; + + RenderTargetIndex )
{
const FRenderTargetBinding & RenderTarget = RenderTargets [ RenderTargetIndex ] ;
2020-09-24 00:43:27 -04:00
checkf ( RenderTarget . GetTexture ( ) = = nullptr & & RenderTarget . GetResolveTexture ( ) = = nullptr , TEXT ( " Render targets must be packed. No empty spaces in the array. " ) ) ;
2019-07-16 13:08:56 -04:00
}
}
}
}
void FRDGUserValidation : : ValidateExecuteBegin ( )
{
checkf ( ! bHasExecuted , TEXT ( " Render graph execution should only happen once to ensure consistency with immediate mode. " ) ) ;
2021-05-19 17:54:58 -04:00
check ( ! bHasExecuteBegun ) ;
bHasExecuteBegun = true ;
2019-07-16 13:08:56 -04:00
}
void FRDGUserValidation : : ValidateExecuteEnd ( )
{
2021-05-19 17:54:58 -04:00
check ( bHasExecuteBegun ) ;
2020-10-23 16:26:52 -04:00
2019-07-16 13:08:56 -04:00
bHasExecuted = true ;
2021-07-13 12:38:27 -04:00
GRDGBuilderActive = false ;
2019-07-16 13:08:56 -04:00
2023-03-17 23:05:14 -04:00
if ( GRDGDebug & & GRDGValidation )
2019-07-16 13:08:56 -04:00
{
2022-03-25 11:19:10 -04:00
auto ValidateResourceAtExecuteEnd = [ ] ( const FRDGViewableResource * Resource )
2019-07-16 13:08:56 -04:00
{
2022-03-25 11:19:10 -04:00
const auto & ViewableDebugData = Resource - > GetViewableDebugData ( ) ;
const bool bProducedButNeverUsed = ViewableDebugData . PassAccessCount = = 1 & & ViewableDebugData . FirstProducer ;
2019-09-14 09:45:25 -04:00
if ( bProducedButNeverUsed )
{
2020-11-30 13:16:32 -04:00
check ( Resource - > bProduced | | Resource - > bExternal | | Resource - > bExtracted ) ;
2019-09-14 09:45:25 -04:00
EmitRDGWarningf (
TEXT ( " Resource %s has been produced by the pass %s, but never used by another pass. " ) ,
2022-03-25 11:19:10 -04:00
Resource - > Name , ViewableDebugData . FirstProducer - > GetName ( ) ) ;
2019-09-14 09:45:25 -04:00
}
} ;
for ( const FRDGTextureRef Texture : TrackedTextures )
{
ValidateResourceAtExecuteEnd ( Texture ) ;
2022-03-25 11:19:10 -04:00
const auto & ViewableDebugData = Texture - > GetViewableDebugData ( ) ;
2020-11-17 17:04:48 -04:00
const auto & TextureDebugData = Texture - > GetTextureDebugData ( ) ;
2019-09-14 09:45:25 -04:00
2022-03-25 11:19:10 -04:00
const bool bHasBeenProducedByGraph = ! Texture - > bExternal & & ViewableDebugData . PassAccessCount > 0 ;
2020-11-17 17:04:48 -04:00
if ( bHasBeenProducedByGraph & & ! TextureDebugData . bHasNeededUAV & & EnumHasAnyFlags ( Texture - > Desc . Flags , TexCreate_UAV ) )
2019-09-14 09:45:25 -04:00
{
EmitRDGWarningf (
TEXT ( " Resource %s first produced by the pass %s had the TexCreate_UAV flag, but no UAV has been used. " ) ,
2022-03-25 11:19:10 -04:00
Texture - > Name , ViewableDebugData . FirstProducer - > GetName ( ) ) ;
2019-09-14 09:45:25 -04:00
}
2020-11-17 17:04:48 -04:00
if ( bHasBeenProducedByGraph & & ! TextureDebugData . bHasBeenBoundAsRenderTarget & & EnumHasAnyFlags ( Texture - > Desc . Flags , TexCreate_RenderTargetable ) )
2019-09-14 09:45:25 -04:00
{
EmitRDGWarningf (
TEXT ( " Resource %s first produced by the pass %s had the TexCreate_RenderTargetable flag, but has never been bound as a render target of a pass. " ) ,
2022-03-25 11:19:10 -04:00
Texture - > Name , ViewableDebugData . FirstProducer - > GetName ( ) ) ;
2019-09-14 09:45:25 -04:00
}
}
for ( const FRDGBufferRef Buffer : TrackedBuffers )
{
ValidateResourceAtExecuteEnd ( Buffer ) ;
2019-07-16 13:08:56 -04:00
}
}
2019-09-14 09:45:25 -04:00
TrackedTextures . Empty ( ) ;
TrackedBuffers . Empty ( ) ;
2019-07-16 13:08:56 -04:00
}
void FRDGUserValidation : : ValidateExecutePassBegin ( const FRDGPass * Pass )
{
2023-03-17 23:05:14 -04:00
if ( bParallelExecuteEnabled | | ! GRDGValidation )
2021-07-13 12:38:27 -04:00
{
return ;
}
2019-09-14 09:45:25 -04:00
2019-07-16 13:08:56 -04:00
SetAllowRHIAccess ( Pass , true ) ;
2019-09-14 09:45:25 -04:00
2020-07-06 18:58:26 -04:00
if ( GRDGDebug )
2019-09-14 09:45:25 -04:00
{
2020-12-07 17:42:32 -04:00
Pass - > GetParameters ( ) . EnumerateUniformBuffers ( [ & ] ( FRDGUniformBufferBinding UniformBuffer )
2019-09-14 09:45:25 -04:00
{
2020-09-24 00:43:27 -04:00
// Global uniform buffers are always marked as used, because FShader traversal doesn't know about them.
2020-12-07 17:42:32 -04:00
if ( UniformBuffer . IsStatic ( ) )
2019-09-14 09:45:25 -04:00
{
2020-09-24 00:43:27 -04:00
UniformBuffer - > MarkResourceAsUsed ( ) ;
}
} ) ;
2021-04-02 20:35:50 -04:00
const auto ValidateTextureAccess = [ ] ( FRDGTextureRef Texture , ERHIAccess Access )
{
if ( EnumHasAnyFlags ( Access , ERHIAccess : : UAVMask ) )
{
Texture - > GetTextureDebugData ( ) . bHasNeededUAV = true ;
}
if ( EnumHasAnyFlags ( Access , ERHIAccess : : RTV | ERHIAccess : : DSVRead | ERHIAccess : : DSVWrite ) )
{
Texture - > GetTextureDebugData ( ) . bHasBeenBoundAsRenderTarget = true ;
}
Texture - > MarkResourceAsUsed ( ) ;
} ;
2020-09-24 00:43:27 -04:00
Pass - > GetParameters ( ) . Enumerate ( [ & ] ( FRDGParameter Parameter )
{
switch ( Parameter . GetType ( ) )
{
case UBMT_RDG_TEXTURE_UAV :
2019-09-14 09:45:25 -04:00
if ( FRDGTextureUAVRef UAV = Parameter . GetAsTextureUAV ( ) )
{
FRDGTextureRef Texture = UAV - > Desc . Texture ;
2020-11-17 17:04:48 -04:00
Texture - > GetTextureDebugData ( ) . bHasNeededUAV = true ;
2019-09-14 09:45:25 -04:00
}
2020-09-24 00:43:27 -04:00
break ;
case UBMT_RDG_TEXTURE_ACCESS :
2021-04-02 20:35:50 -04:00
if ( FRDGTextureAccess TextureAccess = Parameter . GetAsTextureAccess ( ) )
2020-09-24 00:43:27 -04:00
{
2021-04-02 20:35:50 -04:00
ValidateTextureAccess ( TextureAccess . GetTexture ( ) , TextureAccess . GetAccess ( ) ) ;
}
break ;
case UBMT_RDG_TEXTURE_ACCESS_ARRAY :
{
const FRDGTextureAccessArray & TextureAccessArray = Parameter . GetAsTextureAccessArray ( ) ;
2021-04-06 11:45:09 -04:00
for ( FRDGTextureAccess TextureAccess : TextureAccessArray )
2021-04-02 20:35:50 -04:00
{
2021-04-06 11:45:09 -04:00
ValidateTextureAccess ( TextureAccess . GetTexture ( ) , TextureAccess . GetAccess ( ) ) ;
2020-10-26 12:05:19 -04:00
}
}
break ;
case UBMT_RDG_BUFFER_ACCESS :
if ( FRDGBufferRef Buffer = Parameter . GetAsBuffer ( ) )
{
Buffer - > MarkResourceAsUsed ( ) ;
2020-09-24 00:43:27 -04:00
}
break ;
2021-04-02 20:35:50 -04:00
case UBMT_RDG_BUFFER_ACCESS_ARRAY :
2021-04-06 11:45:09 -04:00
for ( FRDGBufferAccess BufferAccess : Parameter . GetAsBufferAccessArray ( ) )
2021-04-02 20:35:50 -04:00
{
2021-04-06 11:45:09 -04:00
BufferAccess - > MarkResourceAsUsed ( ) ;
2021-04-02 20:35:50 -04:00
}
break ;
2020-09-24 00:43:27 -04:00
case UBMT_RENDER_TARGET_BINDING_SLOTS :
2019-09-14 09:45:25 -04:00
{
2020-07-06 18:58:26 -04:00
const FRenderTargetBindingSlots & RenderTargets = Parameter . GetAsRenderTargetBindingSlots ( ) ;
2019-09-14 09:45:25 -04:00
2020-07-06 18:58:26 -04:00
RenderTargets . Enumerate ( [ & ] ( FRenderTargetBinding RenderTarget )
2019-09-14 09:45:25 -04:00
{
2020-09-24 00:43:27 -04:00
FRDGTextureRef Texture = RenderTarget . GetTexture ( ) ;
2020-11-17 17:04:48 -04:00
Texture - > GetTextureDebugData ( ) . bHasBeenBoundAsRenderTarget = true ;
2020-09-24 00:43:27 -04:00
Texture - > MarkResourceAsUsed ( ) ;
2020-07-06 18:58:26 -04:00
} ) ;
2019-09-14 09:45:25 -04:00
2020-07-06 18:58:26 -04:00
if ( FRDGTextureRef Texture = RenderTargets . DepthStencil . GetTexture ( ) )
2019-09-14 09:45:25 -04:00
{
2020-11-17 17:04:48 -04:00
Texture - > GetTextureDebugData ( ) . bHasBeenBoundAsRenderTarget = true ;
2020-09-24 00:43:27 -04:00
Texture - > MarkResourceAsUsed ( ) ;
2019-09-14 09:45:25 -04:00
}
2021-03-05 16:16:14 -04:00
2021-03-05 18:33:15 -04:00
if ( FRDGTextureRef Texture = RenderTargets . ShadingRateTexture )
2021-03-05 16:16:14 -04:00
{
Texture - > MarkResourceAsUsed ( ) ;
2021-03-17 12:44:59 -04:00
}
2019-09-14 09:45:25 -04:00
}
2020-09-24 00:43:27 -04:00
break ;
}
} ) ;
2020-07-06 18:58:26 -04:00
}
2019-07-16 13:08:56 -04:00
}
void FRDGUserValidation : : ValidateExecutePassEnd ( const FRDGPass * Pass )
{
2023-03-17 23:05:14 -04:00
if ( bParallelExecuteEnabled | | ! GRDGValidation )
2021-07-13 12:38:27 -04:00
{
return ;
}
2019-07-16 13:08:56 -04:00
SetAllowRHIAccess ( Pass , false ) ;
2020-09-24 00:43:27 -04:00
const FRDGParameterStruct PassParameters = Pass - > GetParameters ( ) ;
2019-07-16 13:08:56 -04:00
2020-07-06 18:58:26 -04:00
if ( GRDGDebug )
2019-07-16 13:08:56 -04:00
{
uint32 TrackedResourceCount = 0 ;
uint32 UsedResourceCount = 0 ;
2020-09-24 00:43:27 -04:00
PassParameters . Enumerate ( [ & ] ( FRDGParameter Parameter )
2019-07-16 13:08:56 -04:00
{
if ( Parameter . IsResource ( ) )
{
if ( FRDGResourceRef Resource = Parameter . GetAsResource ( ) )
{
TrackedResourceCount + + ;
2020-11-17 17:04:48 -04:00
UsedResourceCount + = Resource - > GetDebugData ( ) . bIsActuallyUsedByPass ? 1 : 0 ;
2019-07-16 13:08:56 -04:00
}
}
2020-09-24 00:43:27 -04:00
} ) ;
2019-07-16 13:08:56 -04:00
if ( TrackedResourceCount ! = UsedResourceCount )
{
FString WarningMessage = FString : : Printf (
2019-09-14 09:45:25 -04:00
TEXT ( " '%d' of the '%d' resources of the pass '%s' were not actually used. " ) ,
2019-07-16 13:08:56 -04:00
TrackedResourceCount - UsedResourceCount , TrackedResourceCount , Pass - > GetName ( ) ) ;
2020-09-24 00:43:27 -04:00
PassParameters . Enumerate ( [ & ] ( FRDGParameter Parameter )
2019-07-16 13:08:56 -04:00
{
if ( Parameter . IsResource ( ) )
{
if ( const FRDGResourceRef Resource = Parameter . GetAsResource ( ) )
{
2020-11-17 17:04:48 -04:00
if ( ! Resource - > GetDebugData ( ) . bIsActuallyUsedByPass )
2019-07-16 13:08:56 -04:00
{
WarningMessage + = FString : : Printf ( TEXT ( " \n %s " ) , Resource - > Name ) ;
}
}
}
2020-09-24 00:43:27 -04:00
} ) ;
2019-07-16 13:08:56 -04:00
EmitRDGWarning ( WarningMessage ) ;
}
}
2020-09-24 00:43:27 -04:00
PassParameters . Enumerate ( [ & ] ( FRDGParameter Parameter )
2019-07-16 13:08:56 -04:00
{
if ( Parameter . IsResource ( ) )
{
2020-07-06 18:58:26 -04:00
if ( FRDGResourceRef Resource = Parameter . GetAsResource ( ) )
2019-07-16 13:08:56 -04:00
{
2020-11-17 17:04:48 -04:00
Resource - > GetDebugData ( ) . bIsActuallyUsedByPass = false ;
2019-07-16 13:08:56 -04:00
}
}
2020-09-24 00:43:27 -04:00
} ) ;
2019-07-16 13:08:56 -04:00
}
void FRDGUserValidation : : SetAllowRHIAccess ( const FRDGPass * Pass , bool bAllowAccess )
{
2023-03-17 23:05:14 -04:00
if ( ! GRDGValidation )
{
return ;
}
2020-09-24 00:43:27 -04:00
Pass - > GetParameters ( ) . Enumerate ( [ & ] ( FRDGParameter Parameter )
2019-07-16 13:08:56 -04:00
{
if ( Parameter . IsResource ( ) )
{
if ( FRDGResourceRef Resource = Parameter . GetAsResource ( ) )
{
2020-11-17 17:04:48 -04:00
Resource - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
2019-07-16 13:08:56 -04:00
}
}
2021-05-04 11:53:08 -04:00
else if ( Parameter . IsBufferAccessArray ( ) )
{
for ( FRDGBufferAccess BufferAccess : Parameter . GetAsBufferAccessArray ( ) )
{
BufferAccess - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
}
}
else if ( Parameter . IsTextureAccessArray ( ) )
{
for ( FRDGTextureAccess TextureAccess : Parameter . GetAsTextureAccessArray ( ) )
{
TextureAccess - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
}
}
2019-09-14 09:45:25 -04:00
else if ( Parameter . IsRenderTargetBindingSlots ( ) )
2019-07-16 13:08:56 -04:00
{
2020-07-06 18:58:26 -04:00
const FRenderTargetBindingSlots & RenderTargets = Parameter . GetAsRenderTargetBindingSlots ( ) ;
2019-07-16 13:08:56 -04:00
2020-07-06 18:58:26 -04:00
RenderTargets . Enumerate ( [ & ] ( FRenderTargetBinding RenderTarget )
2019-07-16 13:08:56 -04:00
{
2020-11-17 17:04:48 -04:00
RenderTarget . GetTexture ( ) - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
2020-09-24 00:43:27 -04:00
if ( FRDGTextureRef ResolveTexture = RenderTarget . GetResolveTexture ( ) )
{
2020-11-17 17:04:48 -04:00
ResolveTexture - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
2020-09-24 00:43:27 -04:00
}
2020-07-06 18:58:26 -04:00
} ) ;
2019-07-16 13:08:56 -04:00
2020-07-06 18:58:26 -04:00
if ( FRDGTextureRef Texture = RenderTargets . DepthStencil . GetTexture ( ) )
2019-07-16 13:08:56 -04:00
{
2020-11-17 17:04:48 -04:00
Texture - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
2019-07-16 13:08:56 -04:00
}
2021-03-05 16:16:14 -04:00
2024-04-24 06:43:38 -04:00
if ( FRDGTextureRef ResolveTexture = RenderTargets . DepthStencil . GetResolveTexture ( ) )
{
ResolveTexture - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
}
2021-03-05 18:33:15 -04:00
if ( FRDGTexture * Texture = RenderTargets . ShadingRateTexture )
2021-03-05 16:16:14 -04:00
{
Texture - > GetDebugData ( ) . bAllowRHIAccess = bAllowAccess ;
}
2019-07-16 13:08:56 -04:00
}
2020-09-24 00:43:27 -04:00
} ) ;
2019-07-16 13:08:56 -04:00
}
2020-07-06 18:58:26 -04:00
FRDGBarrierValidation : : FRDGBarrierValidation ( const FRDGPassRegistry * InPasses , const FRDGEventName & InGraphName )
: Passes ( InPasses )
, GraphName ( InGraphName . GetTCHAR ( ) )
{
check ( Passes ) ;
}
2020-09-24 00:43:27 -04:00
void FRDGBarrierValidation : : ValidateBarrierBatchBegin ( const FRDGPass * Pass , const FRDGBarrierBatchBegin & Batch )
2020-07-06 18:58:26 -04:00
{
if ( ! GRDGTransitionLog )
{
return ;
}
2020-11-11 19:22:36 -04:00
FResourceMap * ResourceMap = BatchMap . Find ( & Batch ) ;
2020-07-06 18:58:26 -04:00
2020-11-11 19:22:36 -04:00
if ( ! ResourceMap )
2020-07-06 18:58:26 -04:00
{
2020-11-11 19:22:36 -04:00
ResourceMap = & BatchMap . Emplace ( & Batch ) ;
2020-07-06 18:58:26 -04:00
2020-11-11 19:22:36 -04:00
for ( int32 Index = 0 ; Index < Batch . Transitions . Num ( ) ; + + Index )
2020-07-06 18:58:26 -04:00
{
2022-03-25 11:19:10 -04:00
FRDGViewableResource * Resource = Batch . DebugTransitionResources [ Index ] ;
2024-01-22 11:04:48 -05:00
const FRDGTransitionInfo & Transition = Batch . Transitions [ Index ] ;
2020-11-11 19:22:36 -04:00
2022-03-25 11:19:10 -04:00
if ( Resource - > Type = = ERDGViewableResourceType : : Texture )
2020-11-11 19:22:36 -04:00
{
ResourceMap - > Textures . FindOrAdd ( static_cast < FRDGTextureRef > ( Resource ) ) . Add ( Transition ) ;
}
else
{
2022-03-25 11:19:10 -04:00
check ( Resource - > Type = = ERDGViewableResourceType : : Buffer ) ;
2020-11-11 19:22:36 -04:00
ResourceMap - > Buffers . Emplace ( static_cast < FRDGBufferRef > ( Resource ) , Transition ) ;
}
2020-07-06 18:58:26 -04:00
}
2021-03-17 12:44:59 -04:00
for ( int32 Index = 0 ; Index < Batch . Aliases . Num ( ) ; + + Index )
{
ResourceMap - > Aliases . Emplace ( Batch . DebugAliasingResources [ Index ] , Batch . Aliases [ Index ] ) ;
}
2020-07-06 18:58:26 -04:00
}
2021-03-17 12:44:59 -04:00
if ( ! IsDebugAllowedForGraph ( GraphName ) | | ! IsDebugAllowedForPass ( Pass - > GetName ( ) ) )
2020-07-06 18:58:26 -04:00
{
return ;
}
bool bFoundFirst = false ;
const auto LogHeader = [ & ] ( )
{
if ( ! bFoundFirst )
{
bFoundFirst = true ;
2022-05-02 18:31:37 -04:00
UE_LOG ( LogRDG , Display , TEXT ( " [%s(Index: %d, Pipeline: %s): Batch: (%p) %s] (Begin): " ) , Pass - > GetName ( ) , Pass - > GetHandle ( ) . GetIndex ( ) , * GetRHIPipelineName ( Pass - > GetPipeline ( ) ) , & Batch , Batch . DebugName ) ;
2020-07-06 18:58:26 -04:00
}
} ;
2021-03-17 12:44:59 -04:00
for ( const auto & KeyValue : ResourceMap - > Aliases )
{
const FRHITransientAliasingInfo & Info = KeyValue . Value ;
if ( Info . IsAcquire ( ) )
{
2022-03-25 11:19:10 -04:00
FRDGViewableResource * Resource = KeyValue . Key ;
2021-03-17 12:44:59 -04:00
if ( IsDebugAllowedForResource ( Resource - > Name ) )
{
LogHeader ( ) ;
UE_LOG ( LogRDG , Display , TEXT ( " \t RDG(%p) RHI(%p) %s - Acquire " ) , Resource , Resource - > GetRHIUnchecked ( ) , Resource - > Name ) ;
}
}
}
2020-11-11 19:22:36 -04:00
for ( const auto & Pair : ResourceMap - > Textures )
2020-07-06 18:58:26 -04:00
{
FRDGTextureRef Texture = Pair . Key ;
2021-03-17 12:44:59 -04:00
if ( ! IsDebugAllowedForResource ( Texture - > Name ) )
{
continue ;
}
2020-07-06 18:58:26 -04:00
const auto & Transitions = Pair . Value ;
2021-03-17 12:44:59 -04:00
if ( Transitions . Num ( ) )
2020-07-06 18:58:26 -04:00
{
LogHeader ( ) ;
2021-03-17 12:44:59 -04:00
UE_LOG ( LogRDG , Display , TEXT ( " \t RDG(%p) RHI(%p) %s: " ) , Texture , Texture - > GetRHIUnchecked ( ) , Texture - > Name ) ;
2020-07-06 18:58:26 -04:00
}
const FRDGTextureSubresourceLayout SubresourceLayout = Texture - > GetSubresourceLayout ( ) ;
2024-01-22 11:04:48 -05:00
for ( const FRDGTransitionInfo & Transition : Transitions )
2020-07-06 18:58:26 -04:00
{
2024-01-22 11:04:48 -05:00
UE_LOG ( LogRDG , Display , TEXT ( " \t \t Mip(%d), Array(%d), Slice(%d): [%s, %s] -> [%s, %s] " ) ,
2024-08-19 12:34:52 -04:00
Transition . Texture . MipIndex , Transition . Texture . ArraySlice , Transition . Texture . PlaneSlice ,
* GetRHIAccessName ( ( ERHIAccess ) Transition . AccessBefore ) ,
2024-04-15 17:15:11 -04:00
* GetRHIPipelineName ( Batch . PipelinesToBegin ) ,
2024-08-19 12:34:52 -04:00
* GetRHIAccessName ( ( ERHIAccess ) Transition . AccessAfter ) ,
2024-04-15 17:15:11 -04:00
* GetRHIPipelineName ( Batch . PipelinesToEnd ) ) ;
2020-07-06 18:58:26 -04:00
}
}
2021-03-17 12:44:59 -04:00
for ( const auto & Pair : ResourceMap - > Buffers )
2020-07-06 18:58:26 -04:00
{
2021-03-17 12:44:59 -04:00
FRDGBufferRef Buffer = Pair . Key ;
2024-01-22 11:04:48 -05:00
const FRDGTransitionInfo & Transition = Pair . Value ;
2021-03-17 12:44:59 -04:00
if ( ! IsDebugAllowedForResource ( Buffer - > Name ) )
2020-07-06 18:58:26 -04:00
{
2021-03-17 12:44:59 -04:00
continue ;
2020-07-06 18:58:26 -04:00
}
2021-03-17 12:44:59 -04:00
LogHeader ( ) ;
UE_LOG ( LogRDG , Display , TEXT ( " \t RDG(%p) RHI(%p) %s: [%s, %s] -> [%s, %s] " ) ,
Buffer ,
Buffer - > GetRHIUnchecked ( ) ,
Buffer - > Name ,
2024-08-19 12:34:52 -04:00
* GetRHIAccessName ( ( ERHIAccess ) Transition . AccessBefore ) ,
2024-04-15 17:15:11 -04:00
* GetRHIPipelineName ( Batch . PipelinesToBegin ) ,
2024-08-19 12:34:52 -04:00
* GetRHIAccessName ( ( ERHIAccess ) Transition . AccessAfter ) ,
2024-04-15 17:15:11 -04:00
* GetRHIPipelineName ( Batch . PipelinesToEnd ) ) ;
2020-07-06 18:58:26 -04:00
}
}
2020-09-24 00:43:27 -04:00
void FRDGBarrierValidation : : ValidateBarrierBatchEnd ( const FRDGPass * Pass , const FRDGBarrierBatchEnd & Batch )
2020-07-06 18:58:26 -04:00
{
2020-09-24 00:43:27 -04:00
if ( ! GRDGTransitionLog | | ! IsDebugAllowedForGraph ( GraphName ) | | ! IsDebugAllowedForPass ( Pass - > GetName ( ) ) )
2020-07-06 18:58:26 -04:00
{
return ;
}
2021-03-17 12:44:59 -04:00
const bool bAllowedForPass = IsDebugAllowedForGraph ( GraphName ) & & IsDebugAllowedForPass ( Pass - > GetName ( ) ) ;
bool bFoundFirst = false ;
2020-07-06 18:58:26 -04:00
2022-05-02 18:31:37 -04:00
const FRDGBarrierBatchEndId Id = Batch . GetId ( ) ;
2020-07-06 18:58:26 -04:00
for ( const FRDGBarrierBatchBegin * Dependent : Batch . Dependencies )
{
2022-05-02 18:31:37 -04:00
if ( ! Batch . IsPairedWith ( * Dependent ) )
2020-07-06 18:58:26 -04:00
{
continue ;
}
const FResourceMap & ResourceMap = BatchMap . FindChecked ( Dependent ) ;
TArray < FRDGTextureRef > Textures ;
if ( ResourceMap . Textures . Num ( ) )
{
ResourceMap . Textures . GetKeys ( Textures ) ;
}
TArray < FRDGBufferRef > Buffers ;
if ( ResourceMap . Buffers . Num ( ) )
{
ResourceMap . Buffers . GetKeys ( Buffers ) ;
}
2021-03-17 12:44:59 -04:00
const auto LogHeader = [ & ] ( )
2020-07-06 18:58:26 -04:00
{
2021-03-17 12:44:59 -04:00
if ( ! bFoundFirst )
2020-07-06 18:58:26 -04:00
{
2021-03-17 12:44:59 -04:00
bFoundFirst = true ;
2022-05-02 18:31:37 -04:00
UE_LOG ( LogRDG , Display , TEXT ( " [%s(Index: %d, Pipeline: %s) Batch: (%p) %s] (End): " ) , Pass - > GetName ( ) , Pass - > GetHandle ( ) . GetIndex ( ) , * GetRHIPipelineName ( Pass - > GetPipeline ( ) ) , Dependent , Dependent - > DebugName ) ;
2020-07-06 18:58:26 -04:00
}
2021-03-17 12:44:59 -04:00
} ;
2020-07-06 18:58:26 -04:00
for ( FRDGTextureRef Texture : Textures )
{
2020-11-11 19:22:36 -04:00
if ( IsDebugAllowedForResource ( Texture - > Name ) )
{
2021-03-17 12:44:59 -04:00
LogHeader ( ) ;
UE_LOG ( LogRDG , Display , TEXT ( " \t RDG(%p) RHI(%p) %s - End: " ) , Texture , Texture - > GetRHIUnchecked ( ) , Texture - > Name ) ;
2020-11-11 19:22:36 -04:00
}
2020-07-06 18:58:26 -04:00
}
for ( FRDGBufferRef Buffer : Buffers )
{
2020-11-11 19:22:36 -04:00
if ( IsDebugAllowedForResource ( Buffer - > Name ) )
{
2021-03-17 12:44:59 -04:00
LogHeader ( ) ;
UE_LOG ( LogRDG , Display , TEXT ( " \t RDG(%p) RHI(%p) %s - End " ) , Buffer , Buffer - > GetRHIUnchecked ( ) , Buffer - > Name ) ;
}
}
2022-05-02 18:31:37 -04:00
bFoundFirst = false ;
2020-07-06 18:58:26 -04:00
}
}
2023-01-27 14:54:10 -05:00
# endif