2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2018-12-11 22:25:04 -05:00
/*=============================================================================
MeshPassProcessor . cpp :
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "MeshPassProcessor.h"
# include "SceneUtils.h"
# include "SceneRendering.h"
# include "Logging/LogMacros.h"
2021-04-27 23:50:55 -04:00
# include "RendererModule.h"
2018-12-11 22:25:04 -05:00
# include "SceneCore.h"
# include "ScenePrivate.h"
# include "SceneInterface.h"
# include "MeshPassProcessor.inl"
2019-01-16 14:28:24 -05:00
# include "PipelineStateCache.h"
2020-01-24 18:07:01 -05:00
# include "RayTracing/RayTracingMaterialHitShaders.h"
2020-02-06 13:13:41 -05:00
# include "Hash/CityHash.h"
2021-04-27 23:50:55 -04:00
FRWLock FGraphicsMinimalPipelineStateId : : PersistentIdTableLock ;
2020-02-06 13:13:41 -05:00
FGraphicsMinimalPipelineStateId : : PersistentTableType FGraphicsMinimalPipelineStateId : : PersistentIdTable ;
2018-12-11 22:25:04 -05:00
2021-04-27 23:50:55 -04:00
# if MESH_DRAW_COMMAND_DEBUG_DATA
std : : atomic < int32 > FGraphicsMinimalPipelineStateId : : LocalPipelineIdTableSize ( 0 ) ;
std : : atomic < int32 > FGraphicsMinimalPipelineStateId : : CurrentLocalPipelineIdTableSize ( 0 ) ;
# endif //MESH_DRAW_COMMAND_DEBUG_DATA
2020-02-06 13:13:41 -05:00
bool FGraphicsMinimalPipelineStateId : : NeedsShaderInitialisation = true ;
2018-12-11 22:25:04 -05:00
2019-01-21 18:04:59 -05:00
const FMeshDrawCommandSortKey FMeshDrawCommandSortKey : : Default = { { 0 } } ;
2018-12-11 22:25:04 -05:00
2019-01-15 13:24:31 -05:00
int32 GEmitMeshDrawEvent = 0 ;
static FAutoConsoleVariableRef CVarEmitMeshDrawEvent (
TEXT ( " r.EmitMeshDrawEvents " ) ,
GEmitMeshDrawEvent ,
TEXT ( " Emits a GPU event around each drawing policy draw call. /n " )
TEXT ( " Useful for seeing stats about each draw call, however it greatly distorts total time and time per draw call. " ) ,
ECVF_RenderThreadSafe
) ;
2019-04-08 18:20:01 -04:00
static TAutoConsoleVariable < int32 > CVarSafeStateLookup (
TEXT ( " r.SafeStateLookup " ) ,
1 ,
TEXT ( " Forces new-style safe state lookup for easy runtime perf comparison \n " ) ,
ECVF_Scalability | ECVF_RenderThreadSafe ) ;
2018-12-11 22:25:04 -05:00
class FReadOnlyMeshDrawSingleShaderBindings : public FMeshDrawShaderBindingsLayout
{
public :
FReadOnlyMeshDrawSingleShaderBindings ( const FMeshDrawShaderBindingsLayout & InLayout , const uint8 * InData ) :
FMeshDrawShaderBindingsLayout ( InLayout )
{
Data = InData ;
}
2019-06-17 13:39:07 -04:00
inline FRHIUniformBuffer * const * GetUniformBufferStart ( ) const
2018-12-11 22:25:04 -05:00
{
2019-06-17 13:39:07 -04:00
return ( FRHIUniformBuffer * * ) ( Data + GetUniformBufferOffset ( ) ) ;
2018-12-11 22:25:04 -05:00
}
2019-06-17 13:39:07 -04:00
inline FRHISamplerState * * GetSamplerStart ( ) const
2018-12-11 22:25:04 -05:00
{
const uint8 * SamplerDataStart = Data + GetSamplerOffset ( ) ;
2019-06-17 13:39:07 -04:00
return ( FRHISamplerState * * ) SamplerDataStart ;
2018-12-11 22:25:04 -05:00
}
2019-06-17 13:39:07 -04:00
inline FRHIResource * * GetSRVStart ( ) const
2018-12-11 22:25:04 -05:00
{
const uint8 * SRVDataStart = Data + GetSRVOffset ( ) ;
2019-06-17 13:39:07 -04:00
return ( FRHIResource * * ) SRVDataStart ;
2018-12-11 22:25:04 -05:00
}
2019-02-14 08:36:29 -05:00
inline const uint8 * GetSRVTypeStart ( ) const
2018-12-11 22:25:04 -05:00
{
2019-02-14 08:36:29 -05:00
const uint8 * SRVTypeDataStart = Data + GetSRVTypeOffset ( ) ;
return SRVTypeDataStart ;
2018-12-11 22:25:04 -05:00
}
inline const uint8 * GetLooseDataStart ( ) const
{
const uint8 * LooseDataStart = Data + GetLooseDataOffset ( ) ;
return LooseDataStart ;
}
private :
const uint8 * Data ;
} ;
2019-10-01 13:03:04 -04:00
template < class RHICmdListType , class RHIShaderType >
2018-12-11 22:25:04 -05:00
void FMeshDrawShaderBindings : : SetShaderBindings (
2019-10-01 13:03:04 -04:00
RHICmdListType & RHICmdList ,
2018-12-11 22:25:04 -05:00
RHIShaderType Shader ,
const FReadOnlyMeshDrawSingleShaderBindings & RESTRICT SingleShaderBindings ,
FShaderBindingState & RESTRICT ShaderBindingState )
{
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * const * RESTRICT UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
2018-12-11 22:25:04 -05:00
const FShaderParameterInfo * RESTRICT UniformBufferParameters = SingleShaderBindings . ParameterMapInfo . UniformBuffers . GetData ( ) ;
const int32 NumUniformBuffers = SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ;
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < NumUniformBuffers ; UniformBufferIndex + + )
{
FShaderParameterInfo Parameter = UniformBufferParameters [ UniformBufferIndex ] ;
2019-09-28 08:19:35 -04:00
checkSlow ( Parameter . BaseIndex < UE_ARRAY_COUNT ( ShaderBindingState . UniformBuffers ) ) ;
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
2018-12-11 22:25:04 -05:00
if ( UniformBuffer ! = ShaderBindingState . UniformBuffers [ Parameter . BaseIndex ] )
{
RHICmdList . SetShaderUniformBuffer ( Shader , Parameter . BaseIndex , UniformBuffer ) ;
ShaderBindingState . UniformBuffers [ Parameter . BaseIndex ] = UniformBuffer ;
ShaderBindingState . MaxUniformBufferUsed = FMath : : Max ( ( int32 ) Parameter . BaseIndex , ShaderBindingState . MaxUniformBufferUsed ) ;
}
}
2019-06-17 13:39:07 -04:00
FRHISamplerState * const * RESTRICT SamplerBindings = SingleShaderBindings . GetSamplerStart ( ) ;
2018-12-11 22:25:04 -05:00
const FShaderParameterInfo * RESTRICT TextureSamplerParameters = SingleShaderBindings . ParameterMapInfo . TextureSamplers . GetData ( ) ;
const int32 NumTextureSamplers = SingleShaderBindings . ParameterMapInfo . TextureSamplers . Num ( ) ;
for ( int32 SamplerIndex = 0 ; SamplerIndex < NumTextureSamplers ; SamplerIndex + + )
{
FShaderParameterInfo Parameter = TextureSamplerParameters [ SamplerIndex ] ;
2019-09-28 08:19:35 -04:00
checkSlow ( Parameter . BaseIndex < UE_ARRAY_COUNT ( ShaderBindingState . Samplers ) ) ;
2019-06-11 18:27:07 -04:00
FRHISamplerState * Sampler = ( FRHISamplerState * ) SamplerBindings [ SamplerIndex ] ;
2018-12-11 22:25:04 -05:00
if ( Sampler ! = ShaderBindingState . Samplers [ Parameter . BaseIndex ] )
{
RHICmdList . SetShaderSampler ( Shader , Parameter . BaseIndex , Sampler ) ;
ShaderBindingState . Samplers [ Parameter . BaseIndex ] = Sampler ;
ShaderBindingState . MaxSamplerUsed = FMath : : Max ( ( int32 ) Parameter . BaseIndex , ShaderBindingState . MaxSamplerUsed ) ;
}
}
2019-02-14 08:36:29 -05:00
const uint8 * RESTRICT SRVType = SingleShaderBindings . GetSRVTypeStart ( ) ;
2019-06-17 13:39:07 -04:00
FRHIResource * const * RESTRICT SRVBindings = SingleShaderBindings . GetSRVStart ( ) ;
2018-12-11 22:25:04 -05:00
const FShaderParameterInfo * RESTRICT SRVParameters = SingleShaderBindings . ParameterMapInfo . SRVs . GetData ( ) ;
2019-02-14 08:36:29 -05:00
const uint32 NumSRVs = SingleShaderBindings . ParameterMapInfo . SRVs . Num ( ) ;
2018-12-11 22:25:04 -05:00
2019-02-14 08:36:29 -05:00
for ( uint32 SRVIndex = 0 ; SRVIndex < NumSRVs ; SRVIndex + + )
2018-12-11 22:25:04 -05:00
{
FShaderParameterInfo Parameter = SRVParameters [ SRVIndex ] ;
2019-09-28 08:19:35 -04:00
checkSlow ( Parameter . BaseIndex < UE_ARRAY_COUNT ( ShaderBindingState . SRVs ) ) ;
2018-12-11 22:25:04 -05:00
2019-02-14 08:36:29 -05:00
uint32 TypeByteIndex = SRVIndex / 8 ;
2020-01-09 18:11:45 -05:00
uint32 TypeBitIndex = SRVIndex % 8 ;
2019-02-14 08:36:29 -05:00
if ( SRVType [ TypeByteIndex ] & ( 1 < < TypeBitIndex ) )
2018-12-11 22:25:04 -05:00
{
2019-06-11 18:27:07 -04:00
FRHIShaderResourceView * SRV = ( FRHIShaderResourceView * ) SRVBindings [ SRVIndex ] ;
2019-02-14 08:36:29 -05:00
if ( SRV ! = ShaderBindingState . SRVs [ Parameter . BaseIndex ] )
{
RHICmdList . SetShaderResourceViewParameter ( Shader , Parameter . BaseIndex , SRV ) ;
ShaderBindingState . SRVs [ Parameter . BaseIndex ] = SRV ;
ShaderBindingState . MaxSRVUsed = FMath : : Max ( ( int32 ) Parameter . BaseIndex , ShaderBindingState . MaxSRVUsed ) ;
}
2018-12-11 22:25:04 -05:00
}
2019-02-14 08:36:29 -05:00
else
2018-12-11 22:25:04 -05:00
{
2019-06-17 13:39:07 -04:00
FRHITexture * Texture = ( FRHITexture * ) SRVBindings [ SRVIndex ] ;
2019-02-14 08:36:29 -05:00
if ( Texture ! = ShaderBindingState . Textures [ Parameter . BaseIndex ] )
{
RHICmdList . SetShaderTexture ( Shader , Parameter . BaseIndex , Texture ) ;
ShaderBindingState . Textures [ Parameter . BaseIndex ] = Texture ;
ShaderBindingState . MaxTextureUsed = FMath : : Max ( ( int32 ) Parameter . BaseIndex , ShaderBindingState . MaxTextureUsed ) ;
}
2018-12-11 22:25:04 -05:00
}
}
const uint8 * LooseDataStart = SingleShaderBindings . GetLooseDataStart ( ) ;
for ( const FShaderLooseParameterBufferInfo & LooseParameterBuffer : SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers )
{
for ( FShaderParameterInfo Parameter : LooseParameterBuffer . Parameters )
{
RHICmdList . SetShaderParameter (
Shader ,
2020-02-06 13:13:41 -05:00
LooseParameterBuffer . BaseIndex ,
2018-12-11 22:25:04 -05:00
Parameter . BaseIndex ,
Parameter . Size ,
LooseDataStart
) ;
LooseDataStart + = Parameter . Size ;
}
}
}
2019-10-01 13:03:04 -04:00
template < class RHICmdListType , class RHIShaderType >
2018-12-18 21:41:17 -05:00
void FMeshDrawShaderBindings : : SetShaderBindings (
2019-10-01 13:03:04 -04:00
RHICmdListType & RHICmdList ,
2018-12-18 21:41:17 -05:00
RHIShaderType Shader ,
const FReadOnlyMeshDrawSingleShaderBindings & RESTRICT SingleShaderBindings )
{
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * const * RESTRICT UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
2018-12-18 21:41:17 -05:00
const FShaderParameterInfo * RESTRICT UniformBufferParameters = SingleShaderBindings . ParameterMapInfo . UniformBuffers . GetData ( ) ;
const int32 NumUniformBuffers = SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ;
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < NumUniformBuffers ; UniformBufferIndex + + )
{
FShaderParameterInfo Parameter = UniformBufferParameters [ UniformBufferIndex ] ;
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
2018-12-18 21:41:17 -05:00
RHICmdList . SetShaderUniformBuffer ( Shader , Parameter . BaseIndex , UniformBuffer ) ;
}
2019-06-17 13:39:07 -04:00
FRHISamplerState * const * RESTRICT SamplerBindings = SingleShaderBindings . GetSamplerStart ( ) ;
2018-12-18 21:41:17 -05:00
const FShaderParameterInfo * RESTRICT TextureSamplerParameters = SingleShaderBindings . ParameterMapInfo . TextureSamplers . GetData ( ) ;
const int32 NumTextureSamplers = SingleShaderBindings . ParameterMapInfo . TextureSamplers . Num ( ) ;
for ( int32 SamplerIndex = 0 ; SamplerIndex < NumTextureSamplers ; SamplerIndex + + )
{
FShaderParameterInfo Parameter = TextureSamplerParameters [ SamplerIndex ] ;
2019-06-11 18:27:07 -04:00
FRHISamplerState * Sampler = ( FRHISamplerState * ) SamplerBindings [ SamplerIndex ] ;
2018-12-18 21:41:17 -05:00
RHICmdList . SetShaderSampler ( Shader , Parameter . BaseIndex , Sampler ) ;
}
2019-02-14 08:36:29 -05:00
const uint8 * RESTRICT SRVType = SingleShaderBindings . GetSRVTypeStart ( ) ;
2019-06-17 13:39:07 -04:00
FRHIResource * const * RESTRICT SRVBindings = SingleShaderBindings . GetSRVStart ( ) ;
2018-12-18 21:41:17 -05:00
const FShaderParameterInfo * RESTRICT SRVParameters = SingleShaderBindings . ParameterMapInfo . SRVs . GetData ( ) ;
2019-02-14 08:36:29 -05:00
const uint32 NumSRVs = SingleShaderBindings . ParameterMapInfo . SRVs . Num ( ) ;
2018-12-18 21:41:17 -05:00
2019-02-14 08:36:29 -05:00
for ( uint32 SRVIndex = 0 ; SRVIndex < NumSRVs ; SRVIndex + + )
2018-12-18 21:41:17 -05:00
{
FShaderParameterInfo Parameter = SRVParameters [ SRVIndex ] ;
2019-02-14 08:36:29 -05:00
uint32 TypeByteIndex = SRVIndex / 8 ;
2020-01-09 18:11:45 -05:00
uint32 TypeBitIndex = SRVIndex % 8 ;
2018-12-18 21:41:17 -05:00
2019-02-14 08:36:29 -05:00
if ( SRVType [ TypeByteIndex ] & ( 1 < < TypeBitIndex ) )
2018-12-18 21:41:17 -05:00
{
2019-06-11 18:27:07 -04:00
FRHIShaderResourceView * SRV = ( FRHIShaderResourceView * ) SRVBindings [ SRVIndex ] ;
2018-12-18 21:41:17 -05:00
RHICmdList . SetShaderResourceViewParameter ( Shader , Parameter . BaseIndex , SRV ) ;
}
else
{
2019-06-17 13:39:07 -04:00
FRHITexture * Texture = ( FRHITexture * ) SRVBindings [ SRVIndex ] ;
2019-02-14 08:36:29 -05:00
RHICmdList . SetShaderTexture ( Shader , Parameter . BaseIndex , Texture ) ;
2018-12-18 21:41:17 -05:00
}
}
const uint8 * LooseDataStart = SingleShaderBindings . GetLooseDataStart ( ) ;
for ( const FShaderLooseParameterBufferInfo & LooseParameterBuffer : SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers )
{
for ( FShaderParameterInfo Parameter : LooseParameterBuffer . Parameters )
{
RHICmdList . SetShaderParameter (
Shader ,
2020-02-06 13:13:41 -05:00
LooseParameterBuffer . BaseIndex ,
2018-12-18 21:41:17 -05:00
Parameter . BaseIndex ,
Parameter . Size ,
LooseDataStart
) ;
LooseDataStart + = Parameter . Size ;
}
}
}
# if RHI_RAYTRACING
2020-01-24 18:07:01 -05:00
2019-03-07 11:25:32 -05:00
void FMeshDrawShaderBindings : : SetRayTracingShaderBindingsForHitGroup (
2020-01-24 18:07:01 -05:00
FRayTracingLocalShaderBindingWriter * BindingWriter ,
2020-09-24 00:43:27 -04:00
uint32 InstanceIndex ,
2019-03-07 11:25:32 -05:00
uint32 SegmentIndex ,
uint32 HitGroupIndex ,
uint32 ShaderSlot ) const
2018-12-18 21:41:17 -05:00
{
check ( ShaderLayouts . Num ( ) = = 1 ) ;
FReadOnlyMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ 0 ] , GetData ( ) ) ;
2019-01-08 06:18:40 -05:00
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * const * RESTRICT UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
2018-12-18 21:41:17 -05:00
const FShaderParameterInfo * RESTRICT UniformBufferParameters = SingleShaderBindings . ParameterMapInfo . UniformBuffers . GetData ( ) ;
2020-01-24 18:07:01 -05:00
const int32 NumUniformBufferParameters = SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ;
2018-12-18 21:41:17 -05:00
2019-01-08 06:18:40 -05:00
checkf ( SingleShaderBindings . ParameterMapInfo . TextureSamplers . Num ( ) = = 0 , TEXT ( " Texture sampler parameters are not supported for ray tracing. UniformBuffers must be used for all resource binding. " ) ) ;
checkf ( SingleShaderBindings . ParameterMapInfo . SRVs . Num ( ) = = 0 , TEXT ( " SRV parameters are not supported for ray tracing. UniformBuffers must be used for all resource binding. " ) ) ;
2019-06-11 18:27:07 -04:00
2020-01-24 18:07:01 -05:00
// Measure parameter memory requirements
2019-06-11 18:27:07 -04:00
2020-01-24 18:07:01 -05:00
int32 MaxUniformBufferUsed = - 1 ;
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < NumUniformBufferParameters ; UniformBufferIndex + + )
{
FShaderParameterInfo Parameter = UniformBufferParameters [ UniformBufferIndex ] ;
const FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
2020-09-24 14:30:14 -04:00
MaxUniformBufferUsed = FMath : : Max ( ( int32 ) Parameter . BaseIndex , MaxUniformBufferUsed ) ;
}
2020-01-24 18:07:01 -05:00
const uint32 NumUniformBuffersToSet = MaxUniformBufferUsed + 1 ;
2020-02-06 13:13:41 -05:00
const TMemoryImageArray < FShaderLooseParameterBufferInfo > & LooseParameterBuffers = SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers ;
2020-01-24 18:07:01 -05:00
uint32 LooseParameterDataSize = 0 ;
2019-06-11 18:27:07 -04:00
if ( LooseParameterBuffers . Num ( ) )
{
check ( LooseParameterBuffers . Num ( ) < = 1 ) ;
const FShaderLooseParameterBufferInfo & LooseParameterBuffer = SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers [ 0 ] ;
2020-02-06 13:13:41 -05:00
check ( LooseParameterBuffer . BaseIndex = = 0 ) ;
2019-06-11 18:27:07 -04:00
for ( int32 LooseParameterIndex = 0 ; LooseParameterIndex < LooseParameterBuffer . Parameters . Num ( ) ; LooseParameterIndex + + )
{
FShaderParameterInfo LooseParameter = LooseParameterBuffer . Parameters [ LooseParameterIndex ] ;
LooseParameterDataSize = FMath : : Max < uint32 > ( LooseParameterDataSize , LooseParameter . BaseIndex + LooseParameter . Size ) ;
}
2020-01-24 18:07:01 -05:00
}
2019-06-11 18:27:07 -04:00
2020-01-24 18:07:01 -05:00
// Allocate and fill bindings
2019-06-11 18:27:07 -04:00
2020-01-24 18:07:01 -05:00
const uint32 UserData = 0 ; // UserData could be used to store material ID or any other kind of per-material constant. This can be retrieved in hit shaders via GetHitGroupUserData().
FRayTracingLocalShaderBindings & Bindings = BindingWriter - > AddWithInlineParameters ( NumUniformBuffersToSet , LooseParameterDataSize ) ;
Bindings . InstanceIndex = InstanceIndex ;
Bindings . SegmentIndex = SegmentIndex ;
Bindings . ShaderSlot = ShaderSlot ;
Bindings . ShaderIndexInPipeline = HitGroupIndex ;
Bindings . UserData = UserData ;
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < NumUniformBufferParameters ; UniformBufferIndex + + )
{
FShaderParameterInfo Parameter = UniformBufferParameters [ UniformBufferIndex ] ;
const FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
Bindings . UniformBuffers [ Parameter . BaseIndex ] = const_cast < FRHIUniformBuffer * > ( UniformBuffer ) ;
}
if ( LooseParameterBuffers . Num ( ) )
{
const FShaderLooseParameterBufferInfo & LooseParameterBuffer = SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers [ 0 ] ;
2019-06-11 18:27:07 -04:00
const uint8 * LooseDataOffset = SingleShaderBindings . GetLooseDataStart ( ) ;
for ( int32 LooseParameterIndex = 0 ; LooseParameterIndex < LooseParameterBuffer . Parameters . Num ( ) ; LooseParameterIndex + + )
{
FShaderParameterInfo LooseParameter = LooseParameterBuffer . Parameters [ LooseParameterIndex ] ;
2020-01-24 18:07:01 -05:00
FMemory : : Memcpy ( Bindings . LooseParameterData + LooseParameter . BaseIndex , LooseDataOffset , LooseParameter . Size ) ;
2019-06-11 18:27:07 -04:00
LooseDataOffset + = LooseParameter . Size ;
}
}
2018-12-18 21:41:17 -05:00
}
2020-01-24 18:07:01 -05:00
2018-12-18 21:41:17 -05:00
# endif // RHI_RAYTRACING
2019-02-18 13:18:45 -05:00
FGraphicsMinimalPipelineStateId FGraphicsMinimalPipelineStateId : : GetPersistentId ( const FGraphicsMinimalPipelineStateInitializer & InPipelineState )
2018-12-11 22:25:04 -05:00
{
2020-02-06 13:13:41 -05:00
Experimental : : FHashElementId TableId ;
auto hash = PersistentIdTable . ComputeHash ( InPipelineState ) ;
{
2021-04-27 23:50:55 -04:00
FRWScopeLock Lock ( PersistentIdTableLock , SLT_ReadOnly ) ;
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
# if UE_BUILD_DEBUG
FGraphicsMinimalPipelineStateInitializer PipelineStateDebug = FGraphicsMinimalPipelineStateInitializer ( InPipelineState ) ;
check ( GetTypeHash ( PipelineStateDebug ) = = GetTypeHash ( InPipelineState ) ) ;
check ( PipelineStateDebug = = InPipelineState ) ;
# endif
2021-04-27 23:50:55 -04:00
TableId = PersistentIdTable . FindIdByHash ( hash , InPipelineState ) ;
if ( ! TableId . IsValid ( ) )
{
Lock . ReleaseReadOnlyLockAndAcquireWriteLock_USE_WITH_CAUTION ( ) ;
TableId = PersistentIdTable . FindOrAddIdByHash ( hash , InPipelineState , FRefCountedGraphicsMinimalPipelineState ( ) ) ;
}
2020-02-06 13:13:41 -05:00
FRefCountedGraphicsMinimalPipelineState & Value = PersistentIdTable . GetByElementId ( TableId ) . Value ;
2021-04-27 23:50:55 -04:00
2020-02-06 13:13:41 -05:00
if ( Value . RefNum = = 0 & & ! NeedsShaderInitialisation )
2020-09-24 14:30:14 -04:00
{
2020-02-06 13:13:41 -05:00
NeedsShaderInitialisation = true ;
2020-09-24 14:30:14 -04:00
}
2020-02-06 13:13:41 -05:00
Value . RefNum + + ;
2018-12-11 22:25:04 -05:00
}
2020-02-06 13:13:41 -05:00
checkf ( TableId . GetIndex ( ) < ( MAX_uint32 > > 2 ) , TEXT ( " Persistent FGraphicsMinimalPipelineStateId table overflow! " ) ) ;
2018-12-11 22:25:04 -05:00
2019-02-18 13:18:45 -05:00
FGraphicsMinimalPipelineStateId Ret ;
Ret . bValid = 1 ;
2019-05-16 16:08:59 -04:00
Ret . bComesFromLocalPipelineStateSet = 0 ;
2020-02-06 13:13:41 -05:00
Ret . SetElementIndex = TableId . GetIndex ( ) ;
2019-02-18 13:18:45 -05:00
return Ret ;
}
2020-02-06 13:13:41 -05:00
void FGraphicsMinimalPipelineStateId : : InitializePersistentIds ( )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( InitializePersistentMdcIds ) ;
2021-04-27 23:50:55 -04:00
FRWScopeLock WriteLock ( PersistentIdTableLock , SLT_Write ) ;
2020-02-06 13:13:41 -05:00
if ( NeedsShaderInitialisation )
{
for ( TPair < const FGraphicsMinimalPipelineStateInitializer , FRefCountedGraphicsMinimalPipelineState > & Element : PersistentIdTable )
{
Element . Key . BoundShaderState . LazilyInitShaders ( ) ;
}
NeedsShaderInitialisation = false ;
}
}
2019-02-18 21:37:54 -05:00
void FGraphicsMinimalPipelineStateId : : RemovePersistentId ( FGraphicsMinimalPipelineStateId Id )
{
2019-05-16 16:08:59 -04:00
check ( ! Id . bComesFromLocalPipelineStateSet & & Id . bValid ) ;
2019-02-18 21:37:54 -05:00
{
2021-04-27 23:50:55 -04:00
FRWScopeLock WriteLock ( PersistentIdTableLock , SLT_Write ) ;
2020-02-06 13:13:41 -05:00
FRefCountedGraphicsMinimalPipelineState & RefCountedStateInitializer = PersistentIdTable . GetByElementId ( Id . SetElementIndex ) . Value ;
2020-09-24 14:30:14 -04:00
check ( RefCountedStateInitializer . RefNum > 0 ) ;
- - RefCountedStateInitializer . RefNum ;
2020-02-06 13:13:41 -05:00
if ( RefCountedStateInitializer . RefNum = = 0 )
2020-09-24 14:30:14 -04:00
{
2020-02-06 13:13:41 -05:00
PersistentIdTable . RemoveByElementId ( Id . SetElementIndex ) ;
}
2019-02-18 21:37:54 -05:00
}
}
2020-02-06 13:13:41 -05:00
FGraphicsMinimalPipelineStateId FGraphicsMinimalPipelineStateId : : GetPipelineStateId ( const FGraphicsMinimalPipelineStateInitializer & InPipelineState , FGraphicsMinimalPipelineStateSet & InOutPassSet , bool & InNeedsShaderInitialisation )
2019-02-18 13:18:45 -05:00
{
FGraphicsMinimalPipelineStateId Ret ;
Ret . bValid = 1 ;
2020-09-24 14:30:14 -04:00
Ret . bComesFromLocalPipelineStateSet = 1 ;
2020-02-06 13:13:41 -05:00
# if UE_BUILD_DEBUG
2020-09-24 14:30:14 -04:00
FGraphicsMinimalPipelineStateInitializer PipelineStateDebug = FGraphicsMinimalPipelineStateInitializer ( InPipelineState ) ;
check ( GetTypeHash ( PipelineStateDebug ) = = GetTypeHash ( InPipelineState ) ) ;
check ( PipelineStateDebug = = InPipelineState ) ;
2020-02-06 13:13:41 -05:00
# endif
2020-09-24 14:30:14 -04:00
Experimental : : FHashElementId TableIndex = InOutPassSet . FindOrAddId ( InPipelineState ) ;
2020-02-06 13:13:41 -05:00
# if UE_BUILD_DEBUG
2020-09-24 14:30:14 -04:00
check ( InOutPassSet . GetByElementId ( TableIndex ) = = InPipelineState ) ;
2020-02-06 13:13:41 -05:00
# endif
2020-09-24 14:30:14 -04:00
InNeedsShaderInitialisation = InNeedsShaderInitialisation | | InPipelineState . BoundShaderState . NeedsShaderInitialisation ( ) ;
2019-02-18 13:18:45 -05:00
2020-02-06 13:13:41 -05:00
checkf ( TableIndex . GetIndex ( ) < ( MAX_uint32 > > 2 ) , TEXT ( " One frame FGraphicsMinimalPipelineStateId table overflow! " ) ) ;
Ret . SetElementIndex = TableIndex . GetIndex ( ) ;
2019-02-18 13:18:45 -05:00
return Ret ;
}
2019-05-16 16:08:59 -04:00
void FGraphicsMinimalPipelineStateId : : ResetLocalPipelineIdTableSize ( )
2019-04-08 18:20:01 -04:00
{
2021-04-27 23:50:55 -04:00
# if MESH_DRAW_COMMAND_DEBUG_DATA
int32 CapturedPipelineIdTableSize ;
do
{
CapturedPipelineIdTableSize = CurrentLocalPipelineIdTableSize ;
} while ( ! CurrentLocalPipelineIdTableSize . compare_exchange_strong ( CapturedPipelineIdTableSize , 0 ) ) ;
LocalPipelineIdTableSize = CapturedPipelineIdTableSize ;
# endif //MESH_DRAW_COMMAND_DEBUG_DATA
2019-04-08 18:20:01 -04:00
}
2019-05-16 16:08:59 -04:00
void FGraphicsMinimalPipelineStateId : : AddSizeToLocalPipelineIdTableSize ( SIZE_T Size )
2019-04-08 18:20:01 -04:00
{
2021-04-27 23:50:55 -04:00
# if MESH_DRAW_COMMAND_DEBUG_DATA
2019-05-16 16:08:59 -04:00
CurrentLocalPipelineIdTableSize + = int32 ( Size ) ;
2021-04-27 23:50:55 -04:00
# endif
2018-12-11 22:25:04 -05:00
}
FMeshDrawShaderBindings : : ~ FMeshDrawShaderBindings ( )
{
2019-07-08 16:42:59 -04:00
Release ( ) ;
2018-12-11 22:25:04 -05:00
}
void FMeshDrawShaderBindings : : Initialize ( FMeshProcessorShaders Shaders )
{
2020-02-06 13:13:41 -05:00
const int32 NumShaderFrequencies = ( Shaders . VertexShader . IsValid ( ) ? 1 : 0 ) +
( Shaders . PixelShader . IsValid ( ) ? 1 : 0 ) +
( Shaders . GeometryShader . IsValid ( ) ? 1 : 0 ) +
( Shaders . ComputeShader . IsValid ( ) ? 1 : 0 )
2018-12-18 21:41:17 -05:00
# if RHI_RAYTRACING
2020-02-06 13:13:41 -05:00
+ ( Shaders . RayHitGroupShader . IsValid ( ) ? 1 : 0 )
2018-12-18 21:41:17 -05:00
# endif
;
2018-12-11 22:25:04 -05:00
ShaderLayouts . Empty ( NumShaderFrequencies ) ;
int32 ShaderBindingDataSize = 0 ;
2020-02-06 13:13:41 -05:00
if ( Shaders . VertexShader . IsValid ( ) )
2018-12-18 21:41:17 -05:00
{
ShaderLayouts . Add ( FMeshDrawShaderBindingsLayout ( Shaders . VertexShader ) ) ;
ShaderBindingDataSize + = ShaderLayouts . Last ( ) . GetDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
check ( ShaderFrequencyBits < ( 1 < < SF_Vertex ) ) ;
ShaderFrequencyBits | = ( 1 < < SF_Vertex ) ;
2018-12-18 21:41:17 -05:00
}
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
if ( Shaders . PixelShader . IsValid ( ) )
2018-12-11 22:25:04 -05:00
{
ShaderLayouts . Add ( FMeshDrawShaderBindingsLayout ( Shaders . PixelShader ) ) ;
ShaderBindingDataSize + = ShaderLayouts . Last ( ) . GetDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
check ( ShaderFrequencyBits < ( 1 < < SF_Pixel ) ) ;
ShaderFrequencyBits | = ( 1 < < SF_Pixel ) ;
2018-12-11 22:25:04 -05:00
}
2020-02-06 13:13:41 -05:00
if ( Shaders . GeometryShader . IsValid ( ) )
2018-12-11 22:25:04 -05:00
{
ShaderLayouts . Add ( FMeshDrawShaderBindingsLayout ( Shaders . GeometryShader ) ) ;
ShaderBindingDataSize + = ShaderLayouts . Last ( ) . GetDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
check ( ShaderFrequencyBits < ( 1 < < SF_Geometry ) ) ;
ShaderFrequencyBits | = ( 1 < < SF_Geometry ) ;
2018-12-11 22:25:04 -05:00
}
2020-02-06 13:13:41 -05:00
if ( Shaders . ComputeShader . IsValid ( ) )
2018-12-18 21:41:17 -05:00
{
ShaderLayouts . Add ( FMeshDrawShaderBindingsLayout ( Shaders . ComputeShader ) ) ;
ShaderBindingDataSize + = ShaderLayouts . Last ( ) . GetDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
check ( ShaderFrequencyBits < ( 1 < < SF_Compute ) ) ;
ShaderFrequencyBits | = ( 1 < < SF_Compute ) ;
2018-12-18 21:41:17 -05:00
}
# if RHI_RAYTRACING
2020-02-06 13:13:41 -05:00
if ( Shaders . RayHitGroupShader . IsValid ( ) )
2018-12-18 21:41:17 -05:00
{
ShaderLayouts . Add ( FMeshDrawShaderBindingsLayout ( Shaders . RayHitGroupShader ) ) ;
ShaderBindingDataSize + = ShaderLayouts . Last ( ) . GetDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
check ( ShaderFrequencyBits < ( 1 < < SF_RayHitGroup ) ) ;
ShaderFrequencyBits | = ( 1 < < SF_RayHitGroup ) ;
2018-12-18 21:41:17 -05:00
}
# endif
2018-12-11 22:25:04 -05:00
checkSlow ( ShaderLayouts . Num ( ) = = NumShaderFrequencies ) ;
if ( ShaderBindingDataSize > 0 )
{
AllocateZeroed ( ShaderBindingDataSize ) ;
}
}
2019-02-14 08:36:29 -05:00
void FMeshDrawShaderBindings : : Finalize ( const FMeshProcessorShaders * ShadersForDebugging )
2018-12-11 22:25:04 -05:00
{
# if VALIDATE_MESH_COMMAND_BINDINGS
2019-02-14 08:36:29 -05:00
if ( ! ShadersForDebugging )
{
return ;
}
2018-12-11 22:25:04 -05:00
const uint8 * ShaderBindingDataPtr = GetData ( ) ;
2020-02-06 13:13:41 -05:00
uint32 ShaderFrequencyBitIndex = ~ 0 ;
2018-12-11 22:25:04 -05:00
for ( int32 ShaderBindingsIndex = 0 ; ShaderBindingsIndex < ShaderLayouts . Num ( ) ; ShaderBindingsIndex + + )
{
2020-02-06 13:13:41 -05:00
EShaderFrequency Frequency = SF_NumFrequencies ;
while ( true )
{
ShaderFrequencyBitIndex + + ;
if ( ( ShaderFrequencyBits & ( 1 < < ShaderFrequencyBitIndex ) ) ! = 0 )
{
Frequency = EShaderFrequency ( ShaderFrequencyBitIndex ) ;
break ;
}
}
check ( Frequency < SF_NumFrequencies ) ;
2018-12-11 22:25:04 -05:00
const FMeshDrawShaderBindingsLayout & ShaderLayout = ShaderLayouts [ ShaderBindingsIndex ] ;
2020-07-06 18:58:26 -04:00
TShaderRef < FShader > Shader = ShadersForDebugging - > GetShader ( Frequency ) ;
2020-02-06 13:13:41 -05:00
check ( Shader . IsValid ( ) ) ;
const FVertexFactoryType * VFType = Shader . GetVertexFactoryType ( ) ;
2018-12-11 22:25:04 -05:00
FReadOnlyMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayout , ShaderBindingDataPtr ) ;
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * const * UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
2018-12-11 22:25:04 -05:00
for ( int32 BindingIndex = 0 ; BindingIndex < ShaderLayout . ParameterMapInfo . UniformBuffers . Num ( ) ; BindingIndex + + )
{
FShaderParameterInfo ParameterInfo = ShaderLayout . ParameterMapInfo . UniformBuffers [ BindingIndex ] ;
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * UniformBufferValue = UniformBufferBindings [ BindingIndex ] ;
2018-12-11 22:25:04 -05:00
if ( ! UniformBufferValue )
{
// Search the automatically bound uniform buffers for more context if available
const FShaderParametersMetadata * AutomaticallyBoundUniformBufferStruct = Shader - > FindAutomaticallyBoundUniformBufferStruct ( ParameterInfo . BaseIndex ) ;
if ( AutomaticallyBoundUniformBufferStruct )
{
2020-12-07 17:43:21 -04:00
ensureMsgf (
UniformBufferValue | | EnumHasAnyFlags ( AutomaticallyBoundUniformBufferStruct - > GetBindingFlags ( ) , EUniformBufferBindingFlags : : Static ) ,
TEXT ( " Shader %s with vertex factory %s never set automatically bound uniform buffer at BaseIndex %i. Expected buffer of type %s. This can cause GPU hangs, depending on how the shader uses it. " ) ,
2020-02-06 13:13:41 -05:00
Shader . GetType ( ) - > GetName ( ) ,
VFType ? VFType - > GetName ( ) : TEXT ( " nullptr " ) ,
2018-12-11 22:25:04 -05:00
ParameterInfo . BaseIndex ,
AutomaticallyBoundUniformBufferStruct - > GetStructTypeName ( ) ) ;
}
else
{
ensureMsgf ( UniformBufferValue , TEXT ( " Shader %s with vertex factory %s never set uniform buffer at BaseIndex %i. This can cause GPU hangs, depending on how the shader uses it. " ) ,
2020-02-06 13:13:41 -05:00
VFType ? VFType - > GetName ( ) : TEXT ( " nullptr " ) ,
Shader . GetType ( ) - > GetName ( ) ,
2018-12-11 22:25:04 -05:00
ParameterInfo . BaseIndex ) ;
}
}
}
2019-06-17 13:39:07 -04:00
FRHISamplerState * const * SamplerBindings = SingleShaderBindings . GetSamplerStart ( ) ;
2018-12-11 22:25:04 -05:00
for ( int32 BindingIndex = 0 ; BindingIndex < ShaderLayout . ParameterMapInfo . TextureSamplers . Num ( ) ; BindingIndex + + )
{
FShaderParameterInfo ParameterInfo = ShaderLayout . ParameterMapInfo . TextureSamplers [ BindingIndex ] ;
2019-06-11 18:27:07 -04:00
const FRHISamplerState * SamplerValue = SamplerBindings [ BindingIndex ] ;
2018-12-11 22:25:04 -05:00
ensureMsgf ( SamplerValue , TEXT ( " Shader %s with vertex factory %s never set sampler at BaseIndex %u. This can cause GPU hangs, depending on how the shader uses it. " ) ,
2020-02-06 13:13:41 -05:00
Shader . GetType ( ) - > GetName ( ) ,
VFType ? VFType - > GetName ( ) : TEXT ( " nullptr " ) ,
2018-12-11 22:25:04 -05:00
ParameterInfo . BaseIndex ) ;
}
2019-02-14 08:36:29 -05:00
const uint8 * RESTRICT SRVType = SingleShaderBindings . GetSRVTypeStart ( ) ;
2019-06-17 13:39:07 -04:00
FRHIResource * const * RESTRICT SRVBindings = SingleShaderBindings . GetSRVStart ( ) ;
2019-02-14 08:36:29 -05:00
const FShaderParameterInfo * RESTRICT SRVParameters = SingleShaderBindings . ParameterMapInfo . SRVs . GetData ( ) ;
const uint32 NumSRVs = SingleShaderBindings . ParameterMapInfo . SRVs . Num ( ) ;
2018-12-11 22:25:04 -05:00
2019-02-14 08:36:29 -05:00
for ( uint32 SRVIndex = 0 ; SRVIndex < NumSRVs ; SRVIndex + + )
2018-12-11 22:25:04 -05:00
{
2019-02-14 08:36:29 -05:00
FShaderParameterInfo Parameter = SRVParameters [ SRVIndex ] ;
uint32 TypeByteIndex = SRVIndex / 8 ;
2020-01-09 18:11:45 -05:00
uint32 TypeBitIndex = SRVIndex % 8 ;
2019-02-14 08:36:29 -05:00
if ( SRVType [ TypeByteIndex ] & ( 1 < < TypeBitIndex ) )
{
2019-06-11 18:27:07 -04:00
FRHIShaderResourceView * SRV = ( FRHIShaderResourceView * ) SRVBindings [ SRVIndex ] ;
2019-02-14 08:36:29 -05:00
ensureMsgf ( SRV , TEXT ( " Shader %s with vertex factory %s never set SRV at BaseIndex %u. This can cause GPU hangs, depending on how the shader uses it. " ) ,
2020-02-06 13:13:41 -05:00
Shader . GetType ( ) - > GetName ( ) ,
VFType ? VFType - > GetName ( ) : TEXT ( " nullptr " ) ,
2019-02-14 08:36:29 -05:00
Parameter . BaseIndex ) ;
}
else
{
2019-06-17 13:39:07 -04:00
FRHITexture * Texture = ( FRHITexture * ) SRVBindings [ SRVIndex ] ;
2019-02-14 08:36:29 -05:00
ensureMsgf ( Texture , TEXT ( " Shader %s with vertex factory %s never set texture at BaseIndex %u. This can cause GPU hangs, depending on how the shader uses it. " ) ,
2020-02-06 13:13:41 -05:00
Shader . GetType ( ) - > GetName ( ) ,
VFType ? VFType - > GetName ( ) : TEXT ( " nullptr " ) ,
2019-02-14 08:36:29 -05:00
Parameter . BaseIndex ) ;
}
2018-12-11 22:25:04 -05:00
}
ShaderBindingDataPtr + = ShaderLayout . GetDataSizeBytes ( ) ;
}
# endif
}
void FMeshDrawShaderBindings : : CopyFrom ( const FMeshDrawShaderBindings & Other )
{
2019-07-08 16:42:59 -04:00
Release ( ) ;
2018-12-11 22:25:04 -05:00
ShaderLayouts = Other . ShaderLayouts ;
2020-02-06 13:13:41 -05:00
ShaderFrequencyBits = Other . ShaderFrequencyBits ;
2018-12-11 22:25:04 -05:00
Allocate ( Other . Size ) ;
2020-02-06 13:13:41 -05:00
if ( Other . UsesInlineStorage ( ) )
{
Data = Other . Data ;
}
else
{
2020-09-24 14:30:14 -04:00
FPlatformMemory : : Memcpy ( GetData ( ) , Other . GetData ( ) , Size ) ;
2020-02-06 13:13:41 -05:00
}
2018-12-11 22:25:04 -05:00
# if VALIDATE_UNIFORM_BUFFER_LIFETIME
uint8 * ShaderBindingDataPtr = GetData ( ) ;
for ( int32 ShaderBindingsIndex = 0 ; ShaderBindingsIndex < ShaderLayouts . Num ( ) ; ShaderBindingsIndex + + )
{
FMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ ShaderBindingsIndex ] , ShaderBindingDataPtr ) ;
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * * RESTRICT UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
2019-01-04 12:30:36 -05:00
const int32 NumUniformBuffers = SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ;
2018-12-11 22:25:04 -05:00
2019-01-04 12:30:36 -05:00
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < NumUniformBuffers ; UniformBufferIndex + + )
2018-12-11 22:25:04 -05:00
{
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
2018-12-11 22:25:04 -05:00
if ( UniformBuffer )
{
UniformBuffer - > NumMeshCommandReferencesForDebugging + + ;
}
}
ShaderBindingDataPtr + = ShaderLayouts [ ShaderBindingsIndex ] . GetDataSizeBytes ( ) ;
}
# endif
}
2019-07-08 16:42:59 -04:00
void FMeshDrawShaderBindings : : Release ( )
{
# if VALIDATE_UNIFORM_BUFFER_LIFETIME
uint8 * ShaderBindingDataPtr = GetData ( ) ;
for ( int32 ShaderBindingsIndex = 0 ; ShaderBindingsIndex < ShaderLayouts . Num ( ) ; ShaderBindingsIndex + + )
{
FMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ ShaderBindingsIndex ] , ShaderBindingDataPtr ) ;
FRHIUniformBuffer * * RESTRICT UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
const int32 NumUniformBuffers = SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ;
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < NumUniformBuffers ; UniformBufferIndex + + )
{
FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
if ( UniformBuffer )
{
UniformBuffer - > NumMeshCommandReferencesForDebugging - - ;
check ( UniformBuffer - > NumMeshCommandReferencesForDebugging > = 0 ) ;
}
}
ShaderBindingDataPtr + = ShaderLayouts [ ShaderBindingsIndex ] . GetDataSizeBytes ( ) ;
}
# endif
2020-02-06 13:13:41 -05:00
if ( Size > sizeof ( FData ) )
2019-07-08 16:42:59 -04:00
{
2020-02-06 13:13:41 -05:00
delete [ ] Data . GetHeapData ( ) ;
2019-07-08 16:42:59 -04:00
}
Size = 0 ;
2020-02-06 13:13:41 -05:00
Data . SetHeapData ( nullptr ) ;
2019-07-08 16:42:59 -04:00
}
2019-06-11 18:27:07 -04:00
void FMeshDrawCommand : : SetShaders ( FRHIVertexDeclaration * VertexDeclaration , const FMeshProcessorShaders & Shaders , FGraphicsMinimalPipelineStateInitializer & PipelineState )
2018-12-11 22:25:04 -05:00
{
2020-02-06 13:13:41 -05:00
PipelineState . BoundShaderState = FMinimalBoundShaderStateInput ( ) ;
PipelineState . BoundShaderState . VertexDeclarationRHI = VertexDeclaration ;
2020-10-22 19:19:16 -04:00
checkf ( Shaders . VertexShader . IsValid ( ) , TEXT ( " Can't render without a vertex shader " ) ) ;
2020-02-06 13:13:41 -05:00
if ( Shaders . VertexShader . IsValid ( ) )
{
checkSlow ( Shaders . VertexShader - > GetFrequency ( ) = = SF_Vertex ) ;
PipelineState . BoundShaderState . VertexShaderResource = Shaders . VertexShader . GetResource ( ) ;
PipelineState . BoundShaderState . VertexShaderIndex = Shaders . VertexShader - > GetResourceIndex ( ) ;
2020-10-22 19:19:16 -04:00
check ( PipelineState . BoundShaderState . VertexShaderResource - > IsValidShaderIndex ( PipelineState . BoundShaderState . VertexShaderIndex ) ) ;
2020-02-06 13:13:41 -05:00
}
if ( Shaders . PixelShader . IsValid ( ) )
{
checkSlow ( Shaders . PixelShader - > GetFrequency ( ) = = SF_Pixel ) ;
PipelineState . BoundShaderState . PixelShaderResource = Shaders . PixelShader . GetResource ( ) ;
PipelineState . BoundShaderState . PixelShaderIndex = Shaders . PixelShader - > GetResourceIndex ( ) ;
2020-10-22 19:19:16 -04:00
check ( PipelineState . BoundShaderState . PixelShaderResource - > IsValidShaderIndex ( PipelineState . BoundShaderState . PixelShaderIndex ) ) ;
2020-02-06 13:13:41 -05:00
}
2019-02-14 10:54:25 -05:00
# if PLATFORM_SUPPORTS_GEOMETRY_SHADERS
2020-02-06 13:13:41 -05:00
if ( Shaders . GeometryShader . IsValid ( ) )
{
checkSlow ( Shaders . GeometryShader - > GetFrequency ( ) = = SF_Geometry ) ;
PipelineState . BoundShaderState . GeometryShaderResource = Shaders . GeometryShader . GetResource ( ) ;
PipelineState . BoundShaderState . GeometryShaderIndex = Shaders . GeometryShader - > GetResourceIndex ( ) ;
2020-10-22 19:19:16 -04:00
check ( PipelineState . BoundShaderState . GeometryShaderResource - > IsValidShaderIndex ( PipelineState . BoundShaderState . GeometryShaderIndex ) ) ;
2020-02-06 13:13:41 -05:00
}
# endif // PLATFORM_SUPPORTS_GEOMETRY_SHADERS
2018-12-11 22:25:04 -05:00
ShaderBindings . Initialize ( Shaders ) ;
}
2018-12-18 21:41:17 -05:00
# if RHI_RAYTRACING
2019-03-07 11:25:32 -05:00
void FRayTracingMeshCommand : : SetShaders ( const FMeshProcessorShaders & Shaders )
2018-12-11 22:25:04 -05:00
{
2020-02-06 13:13:41 -05:00
check ( Shaders . RayHitGroupShader . IsValid ( ) )
MaterialShaderIndex = Shaders . RayHitGroupShader . GetRayTracingMaterialLibraryIndex ( ) ;
2020-09-01 14:07:48 -04:00
MaterialShader = Shaders . RayHitGroupShader . GetRayTracingShader ( ) ;
2018-12-18 21:41:17 -05:00
ShaderBindings . Initialize ( Shaders ) ;
}
# endif // RHI_RAYTRACING
2019-02-14 08:36:29 -05:00
void FMeshDrawCommand : : SetDrawParametersAndFinalize (
const FMeshBatch & MeshBatch ,
int32 BatchElementIndex ,
2019-02-18 13:18:45 -05:00
FGraphicsMinimalPipelineStateId PipelineId ,
const FMeshProcessorShaders * ShadersForDebugging )
2018-12-18 21:41:17 -05:00
{
const FMeshBatchElement & BatchElement = MeshBatch . Elements [ BatchElementIndex ] ;
2018-12-11 22:25:04 -05:00
check ( ! BatchElement . IndexBuffer | | ( BatchElement . IndexBuffer & & BatchElement . IndexBuffer - > IsInitialized ( ) & & BatchElement . IndexBuffer - > IndexBufferRHI ) ) ;
2020-02-06 13:13:41 -05:00
IndexBuffer = BatchElement . IndexBuffer ? BatchElement . IndexBuffer - > IndexBufferRHI . GetReference ( ) : nullptr ;
2018-12-11 22:25:04 -05:00
FirstIndex = BatchElement . FirstIndex ;
NumPrimitives = BatchElement . NumPrimitives ;
2019-01-17 05:02:52 -05:00
NumInstances = BatchElement . NumInstances ;
2019-02-14 08:36:29 -05:00
if ( NumPrimitives > 0 )
{
VertexParams . BaseVertexIndex = BatchElement . BaseVertexIndex ;
VertexParams . NumVertices = BatchElement . MaxVertexIndex - BatchElement . MinVertexIndex + 1 ;
checkf ( ! BatchElement . IndirectArgsBuffer , TEXT ( " FMeshBatchElement::NumPrimitives must be set to 0 when a IndirectArgsBuffer is used " ) ) ;
}
else
{
checkf ( BatchElement . IndirectArgsBuffer , TEXT ( " It is only valid to set BatchElement.NumPrimitives == 0 when a IndirectArgsBuffer is used " ) ) ;
2019-06-09 12:56:41 -04:00
IndirectArgs . Buffer = BatchElement . IndirectArgsBuffer ;
IndirectArgs . Offset = BatchElement . IndirectArgsOffset ;
2019-02-14 08:36:29 -05:00
}
2018-12-11 22:25:04 -05:00
2019-02-18 13:18:45 -05:00
Finalize ( PipelineId , ShadersForDebugging ) ;
2018-12-11 22:25:04 -05:00
}
void FMeshDrawShaderBindings : : SetOnCommandList ( FRHICommandList & RHICmdList , FBoundShaderStateInput Shaders , FShaderBindingState * StateCacheShaderBindings ) const
{
const uint8 * ShaderBindingDataPtr = GetData ( ) ;
2020-02-06 13:13:41 -05:00
uint32 ShaderFrequencyBitIndex = ~ 0 ;
2018-12-11 22:25:04 -05:00
for ( int32 ShaderBindingsIndex = 0 ; ShaderBindingsIndex < ShaderLayouts . Num ( ) ; ShaderBindingsIndex + + )
{
2020-02-06 13:13:41 -05:00
EShaderFrequency Frequency = SF_NumFrequencies ;
while ( true )
{
ShaderFrequencyBitIndex + + ;
if ( ( ShaderFrequencyBits & ( 1 < < ShaderFrequencyBitIndex ) ) ! = 0 )
{
Frequency = EShaderFrequency ( ShaderFrequencyBitIndex ) ;
break ;
}
}
check ( Frequency < SF_NumFrequencies ) ;
2018-12-11 22:25:04 -05:00
FReadOnlyMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ ShaderBindingsIndex ] , ShaderBindingDataPtr ) ;
FShaderBindingState & ShaderBindingState = StateCacheShaderBindings [ Frequency ] ;
if ( Frequency = = SF_Vertex )
{
SetShaderBindings ( RHICmdList , Shaders . VertexShaderRHI , SingleShaderBindings , ShaderBindingState ) ;
}
else if ( Frequency = = SF_Pixel )
{
SetShaderBindings ( RHICmdList , Shaders . PixelShaderRHI , SingleShaderBindings , ShaderBindingState ) ;
}
else if ( Frequency = = SF_Geometry )
{
SetShaderBindings ( RHICmdList , Shaders . GeometryShaderRHI , SingleShaderBindings , ShaderBindingState ) ;
}
else
{
checkf ( 0 , TEXT ( " Unknown shader frequency " ) ) ;
}
ShaderBindingDataPtr + = ShaderLayouts [ ShaderBindingsIndex ] . GetDataSizeBytes ( ) ;
}
}
2020-08-11 01:36:57 -04:00
void FMeshDrawShaderBindings : : SetOnCommandList ( FRHIComputeCommandList & RHICmdList , FRHIComputeShader * Shader , FShaderBindingState * StateCacheShaderBindings ) const
2019-10-01 13:03:04 -04:00
{
check ( ShaderLayouts . Num ( ) = = 1 ) ;
FReadOnlyMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ 0 ] , GetData ( ) ) ;
2020-02-06 13:13:41 -05:00
check ( ShaderFrequencyBits & ( 1 < < SF_Compute ) ) ;
2019-10-01 13:03:04 -04:00
2020-08-11 01:36:57 -04:00
if ( StateCacheShaderBindings ! = nullptr )
{
SetShaderBindings ( RHICmdList , Shader , SingleShaderBindings , * StateCacheShaderBindings ) ;
}
else
{
SetShaderBindings ( RHICmdList , Shader , SingleShaderBindings ) ;
}
2019-10-01 13:03:04 -04:00
}
2018-12-11 22:25:04 -05:00
bool FMeshDrawShaderBindings : : MatchesForDynamicInstancing ( const FMeshDrawShaderBindings & Rhs ) const
{
2020-02-06 13:13:41 -05:00
if ( ShaderFrequencyBits ! = Rhs . ShaderFrequencyBits )
2020-09-24 00:43:27 -04:00
{
2018-12-11 22:25:04 -05:00
return false ;
}
2020-02-06 13:13:41 -05:00
if ( ShaderLayouts . Num ( ) ! = Rhs . ShaderLayouts . Num ( ) )
{
return false ;
2020-09-24 00:43:27 -04:00
}
2020-02-06 13:13:41 -05:00
for ( int Index = 0 ; Index < ShaderLayouts . Num ( ) ; Index + + )
2020-09-24 00:43:27 -04:00
{
2020-02-06 13:13:41 -05:00
if ( ! ( ShaderLayouts [ Index ] = = Rhs . ShaderLayouts [ Index ] ) )
2020-09-24 00:43:27 -04:00
{
return false ;
}
2020-02-06 13:13:41 -05:00
}
2018-12-11 22:25:04 -05:00
const uint8 * ShaderBindingDataPtr = GetData ( ) ;
const uint8 * OtherShaderBindingDataPtr = Rhs . GetData ( ) ;
for ( int32 ShaderBindingsIndex = 0 ; ShaderBindingsIndex < ShaderLayouts . Num ( ) ; ShaderBindingsIndex + + )
{
FReadOnlyMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ ShaderBindingsIndex ] , ShaderBindingDataPtr ) ;
FReadOnlyMeshDrawSingleShaderBindings OtherSingleShaderBindings ( Rhs . ShaderLayouts [ ShaderBindingsIndex ] , OtherShaderBindingDataPtr ) ;
2020-02-06 13:13:41 -05:00
if ( SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers . Num ( ) )
2018-12-11 22:25:04 -05:00
{
2020-02-06 13:13:41 -05:00
const uint8 * LooseBindings = SingleShaderBindings . GetLooseDataStart ( ) ;
const uint8 * OtherLooseBindings = OtherSingleShaderBindings . GetLooseDataStart ( ) ;
2020-06-23 18:40:00 -04:00
const uint32 LooseLength = SingleShaderBindings . GetLooseDataSizeBytes ( ) ;
const uint32 OtherLength = OtherSingleShaderBindings . GetLooseDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
2020-06-23 18:40:00 -04:00
if ( LooseLength ! = OtherLength )
2020-02-06 13:13:41 -05:00
{
2020-06-23 18:40:00 -04:00
return false ;
2020-02-06 13:13:41 -05:00
}
2020-06-23 18:40:00 -04:00
if ( memcmp ( LooseBindings , OtherLooseBindings , LooseLength ) ! = 0 )
2020-02-06 13:13:41 -05:00
{
return false ;
}
}
FRHISamplerState * const * SamplerBindings = SingleShaderBindings . GetSamplerStart ( ) ;
FRHISamplerState * const * OtherSamplerBindings = OtherSingleShaderBindings . GetSamplerStart ( ) ;
for ( int32 SamplerIndex = 0 ; SamplerIndex < SingleShaderBindings . ParameterMapInfo . TextureSamplers . Num ( ) ; SamplerIndex + + )
{
const FRHIResource * Sampler = SamplerBindings [ SamplerIndex ] ;
const FRHIResource * OtherSampler = OtherSamplerBindings [ SamplerIndex ] ;
if ( Sampler ! = OtherSampler )
{
return false ;
}
}
FRHIResource * const * SrvBindings = SingleShaderBindings . GetSRVStart ( ) ;
FRHIResource * const * OtherSrvBindings = SingleShaderBindings . GetSRVStart ( ) ;
for ( int32 SrvIndex = 0 ; SrvIndex < SingleShaderBindings . ParameterMapInfo . SRVs . Num ( ) ; SrvIndex + + )
{
const FRHIResource * Srv = SrvBindings [ SrvIndex ] ;
const FRHIResource * OtherSrv = OtherSrvBindings [ SrvIndex ] ;
if ( Srv ! = OtherSrv )
2020-09-24 00:43:27 -04:00
{
return false ;
}
2018-12-11 22:25:04 -05:00
}
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * const * UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
FRHIUniformBuffer * const * OtherUniformBufferBindings = OtherSingleShaderBindings . GetUniformBufferStart ( ) ;
2018-12-11 22:25:04 -05:00
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ; UniformBufferIndex + + )
{
2019-06-17 13:39:07 -04:00
const FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
const FRHIUniformBuffer * OtherUniformBuffer = OtherUniformBufferBindings [ UniformBufferIndex ] ;
2018-12-11 22:25:04 -05:00
if ( UniformBuffer ! = OtherUniformBuffer )
{
return false ;
}
}
ShaderBindingDataPtr + = ShaderLayouts [ ShaderBindingsIndex ] . GetDataSizeBytes ( ) ;
OtherShaderBindingDataPtr + = Rhs . ShaderLayouts [ ShaderBindingsIndex ] . GetDataSizeBytes ( ) ;
}
return true ;
2019-05-10 09:48:55 -04:00
}
uint32 FMeshDrawShaderBindings : : GetDynamicInstancingHash ( ) const
{
2020-02-06 13:13:41 -05:00
//add and initialize any leftover padding within the struct to avoid unstable keys
struct FHashKey
2019-05-10 09:48:55 -04:00
{
2020-02-06 13:13:41 -05:00
uint32 LooseParametersHash = 0 ;
uint32 UniformBufferHash = 0 ;
uint16 Size ;
uint16 Frequencies ;
static inline uint32 PointerHash ( const void * Key )
{
# if PLATFORM_64BITS
// Ignoring the lower 4 bits since they are likely zero anyway.
// Higher bits are more significant in 64 bit builds.
return reinterpret_cast < UPTRINT > ( Key ) > > 4 ;
# else
return reinterpret_cast < UPTRINT > ( Key ) ;
# endif
} ;
static inline uint32 HashCombine ( uint32 A , uint32 B )
2020-09-24 00:43:27 -04:00
{
2020-02-06 13:13:41 -05:00
return A ^ ( B + 0x9e3779b9 + ( A < < 6 ) + ( A > > 2 ) ) ;
2020-09-24 00:43:27 -04:00
}
2020-02-06 13:13:41 -05:00
} HashKey ;
HashKey . Size = Size ;
HashKey . Frequencies = ShaderFrequencyBits ;
2019-05-10 09:48:55 -04:00
const uint8 * ShaderBindingDataPtr = GetData ( ) ;
for ( int32 ShaderBindingsIndex = 0 ; ShaderBindingsIndex < ShaderLayouts . Num ( ) ; ShaderBindingsIndex + + )
{
FReadOnlyMeshDrawSingleShaderBindings SingleShaderBindings ( ShaderLayouts [ ShaderBindingsIndex ] , ShaderBindingDataPtr ) ;
2020-02-06 13:13:41 -05:00
if ( SingleShaderBindings . ParameterMapInfo . LooseParameterBuffers . Num ( ) )
2019-05-10 09:48:55 -04:00
{
2020-02-06 13:13:41 -05:00
const uint8 * LooseBindings = SingleShaderBindings . GetLooseDataStart ( ) ;
2020-04-08 10:43:02 -04:00
uint32 Length = SingleShaderBindings . GetLooseDataSizeBytes ( ) ;
2020-02-06 13:13:41 -05:00
HashKey . LooseParametersHash = uint32 ( CityHash64 ( ( const char * ) LooseBindings , Length ) ) ;
}
FRHISamplerState * const * SamplerBindings = SingleShaderBindings . GetSamplerStart ( ) ;
for ( int32 SamplerIndex = 0 ; SamplerIndex < SingleShaderBindings . ParameterMapInfo . TextureSamplers . Num ( ) ; SamplerIndex + + )
{
const FRHIResource * Sampler = SamplerBindings [ SamplerIndex ] ;
HashKey . LooseParametersHash = FHashKey : : HashCombine ( FHashKey : : PointerHash ( Sampler ) , HashKey . LooseParametersHash ) ;
}
FRHIResource * const * SrvBindings = SingleShaderBindings . GetSRVStart ( ) ;
for ( int32 SrvIndex = 0 ; SrvIndex < SingleShaderBindings . ParameterMapInfo . SRVs . Num ( ) ; SrvIndex + + )
{
const FRHIResource * Srv = SrvBindings [ SrvIndex ] ;
HashKey . LooseParametersHash = FHashKey : : HashCombine ( FHashKey : : PointerHash ( Srv ) , HashKey . LooseParametersHash ) ;
2019-05-10 09:48:55 -04:00
}
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * const * UniformBufferBindings = SingleShaderBindings . GetUniformBufferStart ( ) ;
2019-05-10 09:48:55 -04:00
for ( int32 UniformBufferIndex = 0 ; UniformBufferIndex < SingleShaderBindings . ParameterMapInfo . UniformBuffers . Num ( ) ; UniformBufferIndex + + )
{
2019-06-17 13:39:07 -04:00
const FRHIUniformBuffer * UniformBuffer = UniformBufferBindings [ UniformBufferIndex ] ;
2020-02-06 13:13:41 -05:00
HashKey . UniformBufferHash = FHashKey : : HashCombine ( FHashKey : : PointerHash ( UniformBuffer ) , HashKey . UniformBufferHash ) ;
2019-05-10 09:48:55 -04:00
}
ShaderBindingDataPtr + = ShaderLayouts [ ShaderBindingsIndex ] . GetDataSizeBytes ( ) ;
}
2020-02-06 13:13:41 -05:00
return uint32 ( CityHash64 ( ( char * ) & HashKey , sizeof ( FHashKey ) ) ) ;
2019-05-10 09:48:55 -04:00
}
2018-12-11 22:25:04 -05:00
2020-12-10 14:32:50 -04:00
void FMeshDrawCommand : : SubmitDrawBegin (
2018-12-11 22:25:04 -05:00
const FMeshDrawCommand & RESTRICT MeshDrawCommand ,
2019-05-16 16:08:59 -04:00
const FGraphicsMinimalPipelineStateSet & GraphicsMinimalPipelineStateSet ,
2021-01-20 06:49:41 -04:00
FRHIBuffer * ScenePrimitiveIdsBuffer ,
2018-12-11 22:25:04 -05:00
int32 PrimitiveIdOffset ,
2019-02-01 16:42:04 -05:00
uint32 InstanceFactor ,
FRHICommandList & RHICmdList ,
2018-12-11 22:25:04 -05:00
FMeshDrawCommandStateCache & RESTRICT StateCache )
{
checkSlow ( MeshDrawCommand . CachedPipelineId . IsValid ( ) ) ;
2021-02-25 05:03:27 -04:00
// GPUCULL_TODO: Can't do this check as the VFs are created with GMaxRHIFeatureLevel (so may support PrimitiveIdStreamIndex even for preview platforms)
2021-01-19 08:25:03 -04:00
// Want to be sure that we supply GPU-scene instance data if required.
2021-02-25 05:03:27 -04:00
// checkSlow(MeshDrawCommand.PrimitiveIdStreamIndex == -1 || ScenePrimitiveIdsBuffer != nullptr);
2020-12-10 14:32:50 -04:00
const FGraphicsMinimalPipelineStateInitializer & MeshPipelineState = MeshDrawCommand . CachedPipelineId . GetPipelineState ( GraphicsMinimalPipelineStateSet ) ;
2018-12-11 22:25:04 -05:00
2019-06-09 12:56:41 -04:00
if ( MeshDrawCommand . CachedPipelineId . GetId ( ) ! = StateCache . PipelineId )
{
2020-02-06 13:13:41 -05:00
FGraphicsPipelineStateInitializer GraphicsPSOInit = MeshPipelineState . AsGraphicsPipelineStateInitializer ( ) ;
2019-06-09 12:56:41 -04:00
RHICmdList . ApplyCachedRenderTargets ( GraphicsPSOInit ) ;
SetGraphicsPipelineState ( RHICmdList , GraphicsPSOInit ) ;
StateCache . SetPipelineState ( MeshDrawCommand . CachedPipelineId . GetId ( ) ) ;
}
if ( MeshDrawCommand . StencilRef ! = StateCache . StencilRef )
{
RHICmdList . SetStencilRef ( MeshDrawCommand . StencilRef ) ;
StateCache . StencilRef = MeshDrawCommand . StencilRef ;
}
for ( int32 VertexBindingIndex = 0 ; VertexBindingIndex < MeshDrawCommand . VertexStreams . Num ( ) ; VertexBindingIndex + + )
{
const FVertexInputStream & Stream = MeshDrawCommand . VertexStreams [ VertexBindingIndex ] ;
if ( MeshDrawCommand . PrimitiveIdStreamIndex ! = - 1 & & Stream . StreamIndex = = MeshDrawCommand . PrimitiveIdStreamIndex )
2018-12-11 22:25:04 -05:00
{
2019-06-09 12:56:41 -04:00
RHICmdList . SetStreamSource ( Stream . StreamIndex , ScenePrimitiveIdsBuffer , PrimitiveIdOffset ) ;
StateCache . VertexStreams [ Stream . StreamIndex ] = Stream ;
2018-12-11 22:25:04 -05:00
}
2019-06-09 12:56:41 -04:00
else if ( StateCache . VertexStreams [ Stream . StreamIndex ] ! = Stream )
2019-06-09 12:54:20 -04:00
{
2019-06-09 12:56:41 -04:00
RHICmdList . SetStreamSource ( Stream . StreamIndex , Stream . VertexBuffer , Stream . Offset ) ;
StateCache . VertexStreams [ Stream . StreamIndex ] = Stream ;
2019-06-09 12:54:20 -04:00
}
2019-06-09 12:56:41 -04:00
}
2019-06-09 12:54:20 -04:00
2020-02-06 13:13:41 -05:00
MeshDrawCommand . ShaderBindings . SetOnCommandList ( RHICmdList , MeshPipelineState . BoundShaderState . AsBoundShaderState ( ) , StateCache . ShaderBindings ) ;
2020-12-10 14:32:50 -04:00
}
2018-12-11 22:25:04 -05:00
2021-01-19 08:25:03 -04:00
void FMeshDrawCommand : : SubmitDrawEnd ( const FMeshDrawCommand & MeshDrawCommand , uint32 InstanceFactor , FRHICommandList & RHICmdList ,
2021-01-20 06:49:41 -04:00
FRHIBuffer * IndirectArgsOverrideBuffer ,
2021-01-19 08:25:03 -04:00
uint32 IndirectArgsOverrideByteOffset )
2020-12-10 14:32:50 -04:00
{
2021-03-10 01:44:26 -04:00
const bool bDoOverrideArgs = IndirectArgsOverrideBuffer ! = nullptr & & MeshDrawCommand . PrimitiveIdStreamIndex > = 0 ;
2021-01-19 08:25:03 -04:00
2018-12-11 22:25:04 -05:00
if ( MeshDrawCommand . IndexBuffer )
{
2021-01-19 08:25:03 -04:00
if ( MeshDrawCommand . NumPrimitives > 0 & & ! bDoOverrideArgs )
2019-02-14 08:36:29 -05:00
{
RHICmdList . DrawIndexedPrimitive (
MeshDrawCommand . IndexBuffer ,
MeshDrawCommand . VertexParams . BaseVertexIndex ,
0 ,
MeshDrawCommand . VertexParams . NumVertices ,
MeshDrawCommand . FirstIndex ,
MeshDrawCommand . NumPrimitives ,
MeshDrawCommand . NumInstances * InstanceFactor
) ;
}
else
2019-01-16 14:28:24 -05:00
{
RHICmdList . DrawIndexedPrimitiveIndirect (
2020-12-10 14:32:50 -04:00
MeshDrawCommand . IndexBuffer ,
2021-01-19 08:25:03 -04:00
bDoOverrideArgs ? IndirectArgsOverrideBuffer : MeshDrawCommand . IndirectArgs . Buffer ,
bDoOverrideArgs ? IndirectArgsOverrideByteOffset : MeshDrawCommand . IndirectArgs . Offset
2020-12-10 14:32:50 -04:00
) ;
2019-01-16 14:28:24 -05:00
}
2018-12-11 22:25:04 -05:00
}
else
{
2021-01-19 08:25:03 -04:00
if ( MeshDrawCommand . NumPrimitives > 0 & & ! bDoOverrideArgs )
2020-01-15 16:28:04 -05:00
{
2020-12-10 14:32:50 -04:00
RHICmdList . DrawPrimitive (
MeshDrawCommand . VertexParams . BaseVertexIndex + MeshDrawCommand . FirstIndex ,
MeshDrawCommand . NumPrimitives ,
2020-01-15 16:28:04 -05:00
MeshDrawCommand . NumInstances * InstanceFactor ) ;
}
else
{
RHICmdList . DrawPrimitiveIndirect (
2021-01-19 08:25:03 -04:00
bDoOverrideArgs ? IndirectArgsOverrideBuffer : MeshDrawCommand . IndirectArgs . Buffer ,
bDoOverrideArgs ? IndirectArgsOverrideByteOffset : MeshDrawCommand . IndirectArgs . Offset
2020-12-10 14:32:50 -04:00
) ;
}
2018-12-11 22:25:04 -05:00
}
}
2020-12-10 14:32:50 -04:00
void FMeshDrawCommand : : SubmitDraw (
const FMeshDrawCommand & RESTRICT MeshDrawCommand ,
const FGraphicsMinimalPipelineStateSet & GraphicsMinimalPipelineStateSet ,
2021-01-20 06:49:41 -04:00
FRHIBuffer * ScenePrimitiveIdsBuffer ,
2020-12-10 14:32:50 -04:00
int32 PrimitiveIdOffset ,
uint32 InstanceFactor ,
FRHICommandList & RHICmdList ,
2021-01-19 08:25:03 -04:00
FMeshDrawCommandStateCache & RESTRICT StateCache ,
2021-01-20 06:49:41 -04:00
FRHIBuffer * IndirectArgsOverrideBuffer ,
2021-01-19 08:25:03 -04:00
uint32 IndirectArgsOverrideByteOffset )
2020-12-10 14:32:50 -04:00
{
2021-05-20 15:18:40 -04:00
# if MESH_DRAW_COMMAND_DEBUG_DATA
BREADCRUMB_EVENTF ( RHICmdList , MeshDrawCommand , TEXT ( " %s %s " ) ,
* MeshDrawCommand . DebugData . MaterialName ,
MeshDrawCommand . DebugData . ResourceName . IsValid ( ) ? * MeshDrawCommand . DebugData . ResourceName . ToString ( ) : TEXT ( " " ) ) ;
# endif
2021-04-30 14:04:55 -04:00
# if WANTS_DRAW_MESH_EVENTS
FMeshDrawEvent MeshEvent ( MeshDrawCommand , InstanceFactor , RHICmdList ) ;
# endif
2020-12-10 14:32:50 -04:00
SubmitDrawBegin ( MeshDrawCommand , GraphicsMinimalPipelineStateSet , ScenePrimitiveIdsBuffer , PrimitiveIdOffset , InstanceFactor , RHICmdList , StateCache ) ;
2021-01-19 08:25:03 -04:00
SubmitDrawEnd ( MeshDrawCommand , InstanceFactor , RHICmdList , IndirectArgsOverrideBuffer , IndirectArgsOverrideByteOffset ) ;
2020-09-24 00:43:27 -04:00
}
2020-12-10 14:32:50 -04:00
2019-05-10 06:56:22 -04:00
# if MESH_DRAW_COMMAND_DEBUG_DATA
2019-10-11 15:33:31 -04:00
void FMeshDrawCommand : : SetDebugData ( const FPrimitiveSceneProxy * PrimitiveSceneProxy , const FMaterial * Material , const FMaterialRenderProxy * MaterialRenderProxy , const FMeshProcessorShaders & UntypedShaders , const FVertexFactory * VertexFactory )
2019-05-10 06:56:22 -04:00
{
DebugData . PrimitiveSceneProxyIfNotUsingStateBuckets = PrimitiveSceneProxy ;
DebugData . MaterialRenderProxy = MaterialRenderProxy ;
DebugData . VertexShader = UntypedShaders . VertexShader ;
DebugData . PixelShader = UntypedShaders . PixelShader ;
2019-10-11 15:33:31 -04:00
DebugData . VertexFactory = VertexFactory ;
2019-05-10 06:56:22 -04:00
DebugData . ResourceName = PrimitiveSceneProxy ? PrimitiveSceneProxy - > GetResourceName ( ) : FName ( ) ;
2021-06-09 11:40:42 -04:00
DebugData . MaterialName = Material - > GetAssetName ( ) ;
2019-05-10 06:56:22 -04:00
}
# endif
2018-12-11 22:25:04 -05:00
2019-01-08 18:05:54 -05:00
void SubmitMeshDrawCommands (
const FMeshCommandOneFrameArray & VisibleMeshDrawCommands ,
2019-05-16 16:08:59 -04:00
const FGraphicsMinimalPipelineStateSet & GraphicsMinimalPipelineStateSet ,
2021-01-20 06:49:41 -04:00
FRHIBuffer * PrimitiveIdsBuffer ,
2019-01-08 18:05:54 -05:00
int32 BasePrimitiveIdsOffset ,
2019-01-29 11:23:59 -05:00
bool bDynamicInstancing ,
2019-02-01 16:42:04 -05:00
uint32 InstanceFactor ,
2019-01-08 18:05:54 -05:00
FRHICommandList & RHICmdList )
{
2019-05-16 16:08:59 -04:00
SubmitMeshDrawCommandsRange ( VisibleMeshDrawCommands , GraphicsMinimalPipelineStateSet , PrimitiveIdsBuffer , BasePrimitiveIdsOffset , bDynamicInstancing , 0 , VisibleMeshDrawCommands . Num ( ) , InstanceFactor , RHICmdList ) ;
2019-01-08 18:05:54 -05:00
}
2018-12-11 22:25:04 -05:00
void SubmitMeshDrawCommandsRange (
const FMeshCommandOneFrameArray & VisibleMeshDrawCommands ,
2019-05-16 16:08:59 -04:00
const FGraphicsMinimalPipelineStateSet & GraphicsMinimalPipelineStateSet ,
2021-01-20 06:49:41 -04:00
FRHIBuffer * PrimitiveIdsBuffer ,
2018-12-11 22:25:04 -05:00
int32 BasePrimitiveIdsOffset ,
bool bDynamicInstancing ,
int32 StartIndex ,
int32 NumMeshDrawCommands ,
2019-02-01 16:42:04 -05:00
uint32 InstanceFactor ,
2018-12-11 22:25:04 -05:00
FRHICommandList & RHICmdList )
{
2021-01-26 13:35:42 -04:00
// GPUCULL_TODO: workaround for the fact that DrawDynamicMeshPassPrivate et al. don't work with GPU-Scene instancing
// we don't support dynamic instancing for this path since we require one primitive per draw command
// This is because the stride on the instance data buffer is set to 0 so only the first will ever be fetched.
checkSlow ( ! bDynamicInstancing ) ;
bDynamicInstancing = false ;
2018-12-11 22:25:04 -05:00
FMeshDrawCommandStateCache StateCache ;
2019-01-16 14:28:24 -05:00
INC_DWORD_STAT_BY ( STAT_MeshDrawCalls , NumMeshDrawCommands ) ;
2018-12-11 22:25:04 -05:00
for ( int32 DrawCommandIndex = StartIndex ; DrawCommandIndex < StartIndex + NumMeshDrawCommands ; DrawCommandIndex + + )
{
2019-01-15 13:24:31 -05:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , MeshEvent , GEmitMeshDrawEvent ! = 0 , TEXT ( " Mesh Draw " ) ) ;
2018-12-11 22:25:04 -05:00
const FVisibleMeshDrawCommand & VisibleMeshDrawCommand = VisibleMeshDrawCommands [ DrawCommandIndex ] ;
const int32 PrimitiveIdBufferOffset = BasePrimitiveIdsOffset + ( bDynamicInstancing ? VisibleMeshDrawCommand . PrimitiveIdBufferOffset : DrawCommandIndex ) * sizeof ( int32 ) ;
checkSlow ( ! bDynamicInstancing | | VisibleMeshDrawCommand . PrimitiveIdBufferOffset > = 0 ) ;
2019-05-16 16:08:59 -04:00
FMeshDrawCommand : : SubmitDraw ( * VisibleMeshDrawCommand . MeshDrawCommand , GraphicsMinimalPipelineStateSet , PrimitiveIdsBuffer , PrimitiveIdBufferOffset , InstanceFactor , RHICmdList , StateCache ) ;
2018-12-11 22:25:04 -05:00
}
}
2020-02-06 13:13:41 -05:00
void ApplyViewOverridesToMeshDrawCommands ( const FSceneView & View , FMeshCommandOneFrameArray & VisibleMeshDrawCommands , FDynamicMeshDrawCommandStorage & DynamicMeshDrawCommandStorage , FGraphicsMinimalPipelineStateSet & GraphicsMinimalPipelineStateSet , bool & InNeedsShaderInitialisation )
2019-08-07 05:30:08 -04:00
{
if ( View . bReverseCulling | | View . bRenderSceneTwoSided )
{
const FMeshCommandOneFrameArray & PassVisibleMeshDrawCommands = VisibleMeshDrawCommands ;
FMeshCommandOneFrameArray ViewOverriddenMeshCommands ;
ViewOverriddenMeshCommands . Empty ( PassVisibleMeshDrawCommands . Num ( ) ) ;
for ( int32 MeshCommandIndex = 0 ; MeshCommandIndex < PassVisibleMeshDrawCommands . Num ( ) ; MeshCommandIndex + + )
{
DynamicMeshDrawCommandStorage . MeshDrawCommands . Add ( 1 ) ;
FMeshDrawCommand & NewMeshCommand = DynamicMeshDrawCommandStorage . MeshDrawCommands [ DynamicMeshDrawCommandStorage . MeshDrawCommands . Num ( ) - 1 ] ;
const FVisibleMeshDrawCommand & VisibleMeshDrawCommand = PassVisibleMeshDrawCommands [ MeshCommandIndex ] ;
const FMeshDrawCommand & MeshCommand = * VisibleMeshDrawCommand . MeshDrawCommand ;
NewMeshCommand = MeshCommand ;
const ERasterizerCullMode LocalCullMode = View . bRenderSceneTwoSided ? CM_None : View . bReverseCulling ? FMeshPassProcessor : : InverseCullMode ( VisibleMeshDrawCommand . MeshCullMode ) : VisibleMeshDrawCommand . MeshCullMode ;
FGraphicsMinimalPipelineStateInitializer PipelineState = MeshCommand . CachedPipelineId . GetPipelineState ( GraphicsMinimalPipelineStateSet ) ;
PipelineState . RasterizerState = GetStaticRasterizerState < true > ( VisibleMeshDrawCommand . MeshFillMode , LocalCullMode ) ;
2020-02-06 13:13:41 -05:00
const FGraphicsMinimalPipelineStateId PipelineId = FGraphicsMinimalPipelineStateId : : GetPipelineStateId ( PipelineState , GraphicsMinimalPipelineStateSet , InNeedsShaderInitialisation ) ;
2019-08-07 05:30:08 -04:00
NewMeshCommand . Finalize ( PipelineId , nullptr ) ;
FVisibleMeshDrawCommand NewVisibleMeshDrawCommand ;
NewVisibleMeshDrawCommand . Setup (
& NewMeshCommand ,
2021-06-21 12:25:46 -04:00
VisibleMeshDrawCommand . PrimitiveIdInfo ,
2019-08-07 05:30:08 -04:00
VisibleMeshDrawCommand . StateBucketId ,
VisibleMeshDrawCommand . MeshFillMode ,
VisibleMeshDrawCommand . MeshCullMode ,
2021-02-17 15:32:52 -04:00
VisibleMeshDrawCommand . Flags ,
2021-01-19 08:25:03 -04:00
VisibleMeshDrawCommand . SortKey ,
VisibleMeshDrawCommand . RunArray ,
VisibleMeshDrawCommand . NumRuns ) ;
2019-08-07 05:30:08 -04:00
ViewOverriddenMeshCommands . Add ( NewVisibleMeshDrawCommand ) ;
}
// Replace VisibleMeshDrawCommands
FMemory : : Memswap ( & VisibleMeshDrawCommands , & ViewOverriddenMeshCommands , sizeof ( ViewOverriddenMeshCommands ) ) ;
}
}
2018-12-11 22:25:04 -05:00
void DrawDynamicMeshPassPrivate (
const FSceneView & View ,
FRHICommandList & RHICmdList ,
FMeshCommandOneFrameArray & VisibleMeshDrawCommands ,
2019-02-01 16:42:04 -05:00
FDynamicMeshDrawCommandStorage & DynamicMeshDrawCommandStorage ,
2019-05-16 16:08:59 -04:00
FGraphicsMinimalPipelineStateSet & GraphicsMinimalPipelineStateSet ,
2020-02-06 13:13:41 -05:00
bool & InNeedsShaderInitialisation ,
2019-02-01 16:42:04 -05:00
uint32 InstanceFactor )
2018-12-11 22:25:04 -05:00
{
if ( VisibleMeshDrawCommands . Num ( ) > 0 )
{
2021-01-20 19:57:54 -04:00
// GPUCULL_TODO: workaround for the fact that DrawDynamicMeshPassPrivate et al. don't work with GPU-Scene instancing
// we don't support dynamic instancing for this path since we require one primitive per draw command
// This is because the stride on the instance data buffer is set to 0 so only the first will ever be fetched.
const bool bDynamicInstancing = false ;
2019-01-29 11:23:59 -05:00
2021-01-20 06:49:41 -04:00
FRHIBuffer * PrimitiveIdVertexBuffer = nullptr ;
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
ApplyViewOverridesToMeshDrawCommands ( View , VisibleMeshDrawCommands , DynamicMeshDrawCommandStorage , GraphicsMinimalPipelineStateSet , InNeedsShaderInitialisation ) ;
2021-02-17 15:31:33 -04:00
check ( View . bIsViewInfo ) ;
const FViewInfo * ViewInfo = static_cast < const FViewInfo * > ( & View ) ;
2021-02-20 08:07:57 -04:00
# if DO_GUARD_SLOW
2021-02-25 05:03:27 -04:00
if ( UseGPUScene ( View . GetShaderPlatform ( ) , View . GetFeatureLevel ( ) ) )
2021-02-20 08:07:57 -04:00
{
bool bNeedsGPUSceneData = false ;
for ( const auto & VisibleMeshDrawCommand : VisibleMeshDrawCommands )
{
bNeedsGPUSceneData = bNeedsGPUSceneData | | EnumHasAnyFlags ( VisibleMeshDrawCommand . Flags , EFVisibleMeshDrawCommandFlags : : HasPrimitiveIdStreamIndex ) ;
}
ensure ( ! bNeedsGPUSceneData | | ViewInfo - > CachedViewUniformShaderParameters - > PrimitiveSceneData ! = GIdentityPrimitiveBuffer . PrimitiveSceneDataBufferSRV ) ;
ensure ( ! bNeedsGPUSceneData | | ViewInfo - > CachedViewUniformShaderParameters - > InstanceSceneData ! = GIdentityPrimitiveBuffer . InstanceSceneDataBufferSRV ) ;
}
# endif // DO_GUARD_SLOW
2021-02-17 15:31:33 -04:00
SortAndMergeDynamicPassMeshDrawCommands ( View . GetFeatureLevel ( ) , VisibleMeshDrawCommands , DynamicMeshDrawCommandStorage , PrimitiveIdVertexBuffer , InstanceFactor , ViewInfo - > DynamicPrimitiveCollector . GetPrimitiveIdRange ( ) ) ;
2018-12-11 22:25:04 -05:00
2019-05-16 16:08:59 -04:00
SubmitMeshDrawCommandsRange ( VisibleMeshDrawCommands , GraphicsMinimalPipelineStateSet , PrimitiveIdVertexBuffer , 0 , bDynamicInstancing , 0 , VisibleMeshDrawCommands . Num ( ) , InstanceFactor , RHICmdList ) ;
2018-12-11 22:25:04 -05:00
}
}
2021-01-14 23:37:17 -04:00
2019-01-21 09:13:36 -05:00
FMeshDrawCommandSortKey CalculateMeshStaticSortKey ( const FMeshMaterialShader * VertexShader , const FMeshMaterialShader * PixelShader )
{
FMeshDrawCommandSortKey SortKey ;
2019-01-21 09:54:32 -05:00
SortKey . Generic . VertexShaderHash = PointerHash ( VertexShader ) ;
SortKey . Generic . PixelShaderHash = PointerHash ( PixelShader ) ;
2019-01-21 09:13:36 -05:00
return SortKey ;
}
2019-01-12 23:27:39 -05:00
FMeshPassProcessor : : FMeshPassProcessor ( const FScene * InScene , ERHIFeatureLevel : : Type InFeatureLevel , const FSceneView * InViewIfDynamicMeshCommand , FMeshPassDrawListContext * InDrawListContext )
2018-12-11 22:25:04 -05:00
: Scene ( InScene )
, FeatureLevel ( InFeatureLevel )
, ViewIfDynamicMeshCommand ( InViewIfDynamicMeshCommand )
, DrawListContext ( InDrawListContext )
2019-01-03 09:25:06 -05:00
{
}
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
FMeshPassProcessor : : FMeshDrawingPolicyOverrideSettings FMeshPassProcessor : : ComputeMeshOverrideSettings ( const FMeshBatch & Mesh )
2019-01-16 14:28:24 -05:00
{
FMeshDrawingPolicyOverrideSettings OverrideSettings ;
OverrideSettings . MeshPrimitiveType = ( EPrimitiveType ) Mesh . Type ;
OverrideSettings . MeshOverrideFlags | = Mesh . bDisableBackfaceCulling ? EDrawingPolicyOverrideFlags : : TwoSided : EDrawingPolicyOverrideFlags : : None ;
OverrideSettings . MeshOverrideFlags | = Mesh . bDitheredLODTransition ? EDrawingPolicyOverrideFlags : : DitheredLODTransition : EDrawingPolicyOverrideFlags : : None ;
OverrideSettings . MeshOverrideFlags | = Mesh . bWireframe ? EDrawingPolicyOverrideFlags : : Wireframe : EDrawingPolicyOverrideFlags : : None ;
OverrideSettings . MeshOverrideFlags | = Mesh . ReverseCulling ? EDrawingPolicyOverrideFlags : : ReverseCullMode : EDrawingPolicyOverrideFlags : : None ;
return OverrideSettings ;
}
2020-02-06 13:13:41 -05:00
ERasterizerFillMode FMeshPassProcessor : : ComputeMeshFillMode ( const FMeshBatch & Mesh , const FMaterial & InMaterialResource , const FMeshDrawingPolicyOverrideSettings & InOverrideSettings )
2018-12-11 22:25:04 -05:00
{
const bool bMaterialResourceIsTwoSided = InMaterialResource . IsTwoSided ( ) ;
const bool bIsWireframeMaterial = InMaterialResource . IsWireframe ( ) | | ! ! ( InOverrideSettings . MeshOverrideFlags & EDrawingPolicyOverrideFlags : : Wireframe ) ;
return bIsWireframeMaterial ? FM_Wireframe : FM_Solid ;
}
2020-02-06 13:13:41 -05:00
ERasterizerCullMode FMeshPassProcessor : : ComputeMeshCullMode ( const FMeshBatch & Mesh , const FMaterial & InMaterialResource , const FMeshDrawingPolicyOverrideSettings & InOverrideSettings )
2018-12-11 22:25:04 -05:00
{
const bool bMaterialResourceIsTwoSided = InMaterialResource . IsTwoSided ( ) ;
const bool bInTwoSidedOverride = ! ! ( InOverrideSettings . MeshOverrideFlags & EDrawingPolicyOverrideFlags : : TwoSided ) ;
const bool bInReverseCullModeOverride = ! ! ( InOverrideSettings . MeshOverrideFlags & EDrawingPolicyOverrideFlags : : ReverseCullMode ) ;
const bool bIsTwoSided = ( bMaterialResourceIsTwoSided | | bInTwoSidedOverride ) ;
2019-08-07 05:30:08 -04:00
const bool bMeshRenderTwoSided = bIsTwoSided | | bInTwoSidedOverride ;
return bMeshRenderTwoSided ? CM_None : ( bInReverseCullModeOverride ? CM_CCW : CM_CW ) ;
2018-12-11 22:25:04 -05:00
}
2019-06-11 18:27:07 -04:00
void FMeshPassProcessor : : GetDrawCommandPrimitiveId (
const FPrimitiveSceneInfo * RESTRICT PrimitiveSceneInfo ,
const FMeshBatchElement & BatchElement ,
int32 & DrawPrimitiveId ,
int32 & ScenePrimitiveId ) const
2018-12-11 22:25:04 -05:00
{
2021-06-21 12:25:46 -04:00
FMeshDrawCommandPrimitiveIdInfo PrimitiveIdInfo = GetDrawCommandPrimitiveId ( PrimitiveSceneInfo , BatchElement ) ;
DrawPrimitiveId = PrimitiveIdInfo . DrawPrimitiveId ;
ScenePrimitiveId = PrimitiveIdInfo . ScenePrimitiveId ;
}
FMeshDrawCommandPrimitiveIdInfo FMeshPassProcessor : : GetDrawCommandPrimitiveId (
const FPrimitiveSceneInfo * RESTRICT PrimitiveSceneInfo ,
const FMeshBatchElement & BatchElement ) const
{
FMeshDrawCommandPrimitiveIdInfo PrimitiveIdInfo = FMeshDrawCommandPrimitiveIdInfo ( 0 , - 1 ) ;
2018-12-11 22:25:04 -05:00
if ( UseGPUScene ( GMaxRHIShaderPlatform , FeatureLevel ) )
{
if ( BatchElement . PrimitiveIdMode = = PrimID_FromPrimitiveSceneInfo )
{
ensureMsgf ( BatchElement . PrimitiveUniformBufferResource = = nullptr , TEXT ( " PrimitiveUniformBufferResource should not be setup when PrimitiveIdMode == PrimID_FromPrimitiveSceneInfo " ) ) ;
2019-06-11 18:27:07 -04:00
check ( PrimitiveSceneInfo ) ;
2021-06-21 12:25:46 -04:00
PrimitiveIdInfo . DrawPrimitiveId = PrimitiveSceneInfo - > GetIndex ( ) ;
PrimitiveIdInfo . InstanceSceneDataOffset = PrimitiveSceneInfo - > GetInstanceSceneDataOffset ( ) ;
PrimitiveIdInfo . bIsDynamicPrimitive = 0U ;
2018-12-11 22:25:04 -05:00
}
2020-11-19 05:23:44 -04:00
else if ( BatchElement . PrimitiveIdMode = = PrimID_DynamicPrimitiveShaderData & & ViewIfDynamicMeshCommand ! = nullptr )
2018-12-11 22:25:04 -05:00
{
2021-02-17 15:31:33 -04:00
// Mark using GPrimIDDynamicFlag (top bit) as we defer this to later.
2021-06-21 12:25:46 -04:00
PrimitiveIdInfo . DrawPrimitiveId = BatchElement . DynamicPrimitiveShaderDataIndex | GPrimIDDynamicFlag ;
PrimitiveIdInfo . InstanceSceneDataOffset = BatchElement . DynamicPrimitiveShaderDataIndex ;
PrimitiveIdInfo . bIsDynamicPrimitive = 1U ;
2018-12-11 22:25:04 -05:00
}
else
{
check ( BatchElement . PrimitiveIdMode = = PrimID_ForceZero ) ;
}
}
2021-06-21 12:25:46 -04:00
PrimitiveIdInfo . ScenePrimitiveId = PrimitiveSceneInfo ? PrimitiveSceneInfo - > GetIndex ( ) : - 1 ;
return PrimitiveIdInfo ;
2018-12-11 22:25:04 -05:00
}
2021-04-27 23:50:55 -04:00
FCachedPassMeshDrawListContext : : FCachedPassMeshDrawListContext ( FCachedMeshDrawCommandInfo & InCommandInfo , FRWLock & InCachedMeshDrawCommandLock , FCachedPassMeshDrawList & InCachedDrawLists , FStateBucketMap & InCachedMeshDrawCommandStateBuckets , const FScene & InScene ) :
2018-12-17 17:12:31 -05:00
CommandInfo ( InCommandInfo ) ,
2020-02-06 13:13:41 -05:00
CachedMeshDrawCommandLock ( InCachedMeshDrawCommandLock ) ,
CachedDrawLists ( InCachedDrawLists ) ,
CachedMeshDrawCommandStateBuckets ( InCachedMeshDrawCommandStateBuckets ) ,
2018-12-11 22:25:04 -05:00
Scene ( InScene )
2019-02-14 08:36:29 -05:00
{
}
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
FMeshDrawCommand & FCachedPassMeshDrawListContext : : AddCommand ( FMeshDrawCommand & Initializer , uint32 NumElements )
2018-12-11 22:25:04 -05:00
{
2020-02-06 13:13:41 -05:00
if ( NumElements = = 1 )
2019-02-14 08:36:29 -05:00
{
2020-02-06 13:13:41 -05:00
return Initializer ;
2019-02-14 08:36:29 -05:00
}
else
{
2020-02-06 13:13:41 -05:00
MeshDrawCommandForStateBucketing = Initializer ;
return MeshDrawCommandForStateBucketing ;
2019-02-14 08:36:29 -05:00
}
2018-12-11 22:25:04 -05:00
}
void FCachedPassMeshDrawListContext : : FinalizeCommand (
const FMeshBatch & MeshBatch ,
2018-12-18 21:41:17 -05:00
int32 BatchElementIndex ,
2021-06-21 12:25:46 -04:00
const FMeshDrawCommandPrimitiveIdInfo & IdInfo ,
2018-12-11 22:25:04 -05:00
ERasterizerFillMode MeshFillMode ,
ERasterizerCullMode MeshCullMode ,
FMeshDrawCommandSortKey SortKey ,
2021-02-17 15:32:52 -04:00
EFVisibleMeshDrawCommandFlags Flags ,
2019-02-14 08:36:29 -05:00
const FGraphicsMinimalPipelineStateInitializer & PipelineState ,
const FMeshProcessorShaders * ShadersForDebugging ,
2019-03-07 11:25:32 -05:00
FMeshDrawCommand & MeshDrawCommand )
2018-12-11 22:25:04 -05:00
{
2019-04-16 15:23:01 -04:00
// disabling this by default as it incurs a high cost in perf captures due to sheer volume. Recommendation is to re-enable locally if you need to profile this particular code.
// QUICK_SCOPE_CYCLE_COUNTER(STAT_FinalizeCachedMeshDrawCommand);
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
FGraphicsMinimalPipelineStateId PipelineId = FGraphicsMinimalPipelineStateId : : GetPersistentId ( PipelineState ) ;
2019-02-18 13:18:45 -05:00
MeshDrawCommand . SetDrawParametersAndFinalize ( MeshBatch , BatchElementIndex , PipelineId , ShadersForDebugging ) ;
2018-12-11 22:25:04 -05:00
2020-02-06 13:13:41 -05:00
if ( UseGPUScene ( GMaxRHIShaderPlatform , GMaxRHIFeatureLevel ) )
2020-09-24 00:43:27 -04:00
{
2020-02-06 13:13:41 -05:00
Experimental : : FHashElementId SetId ;
auto hash = CachedMeshDrawCommandStateBuckets . ComputeHash ( MeshDrawCommand ) ;
2018-12-18 21:41:17 -05:00
{
2021-04-27 23:50:55 -04:00
FRWScopeLock Lock ( CachedMeshDrawCommandLock , SLT_ReadOnly ) ;
2020-02-06 13:13:41 -05:00
# if UE_BUILD_DEBUG
FMeshDrawCommand MeshDrawCommandDebug = FMeshDrawCommand ( MeshDrawCommand ) ;
check ( MeshDrawCommandDebug . ShaderBindings . GetDynamicInstancingHash ( ) = = MeshDrawCommand . ShaderBindings . GetDynamicInstancingHash ( ) ) ;
check ( MeshDrawCommandDebug . GetDynamicInstancingHash ( ) = = MeshDrawCommand . GetDynamicInstancingHash ( ) ) ;
# endif
2021-04-27 23:50:55 -04:00
SetId = CachedMeshDrawCommandStateBuckets . FindIdByHash ( hash , MeshDrawCommand ) ;
if ( ! SetId . IsValid ( ) )
{
Lock . ReleaseReadOnlyLockAndAcquireWriteLock_USE_WITH_CAUTION ( ) ;
SetId = CachedMeshDrawCommandStateBuckets . FindOrAddIdByHash ( hash , MeshDrawCommand , FMeshDrawCommandCount ( ) ) ;
}
FMeshDrawCommandCount & DrawCount = CachedMeshDrawCommandStateBuckets . GetByElementId ( SetId ) . Value ;
DrawCount . Num + + ;
2020-02-06 13:13:41 -05:00
# if MESH_DRAW_COMMAND_DEBUG_DATA
2021-04-27 23:50:55 -04:00
if ( DrawCount . Num = = 1 )
2020-02-06 13:13:41 -05:00
{
2020-09-24 14:30:14 -04:00
MeshDrawCommand . ClearDebugPrimitiveSceneProxy ( ) ; //When using State Buckets multiple PrimitiveSceneProxies use the same MeshDrawCommand, so The PrimitiveSceneProxy pointer can't be stored.
2020-02-06 13:13:41 -05:00
}
2019-05-10 06:56:22 -04:00
# endif
2018-12-18 21:41:17 -05:00
}
2019-02-14 08:36:29 -05:00
check ( CommandInfo . StateBucketId = = - 1 ) ;
2020-02-06 13:13:41 -05:00
CommandInfo . StateBucketId = SetId . GetIndex ( ) ;
2019-02-14 08:36:29 -05:00
check ( CommandInfo . CommandIndex = = - 1 ) ;
2018-12-18 21:41:17 -05:00
}
2019-02-14 08:36:29 -05:00
else
{
2020-02-06 13:13:41 -05:00
check ( CommandInfo . CommandIndex = = - 1 ) ;
2021-04-27 23:50:55 -04:00
FRWScopeLock Lock ( CachedMeshDrawCommandLock , SLT_Write ) ;
2020-02-06 13:13:41 -05:00
// Only one FMeshDrawCommand supported per FStaticMesh in a pass
// Allocate at lowest free index so that 'r.DoLazyStaticMeshUpdate' can shrink the TSparseArray more effectively
2020-08-11 01:36:57 -04:00
CommandInfo . CommandIndex = CachedDrawLists . MeshDrawCommands . EmplaceAtLowestFreeIndex ( CachedDrawLists . LowestFreeIndexSearchStart , MeshDrawCommand ) ;
2019-02-14 08:36:29 -05:00
}
2018-12-17 17:12:31 -05:00
CommandInfo . SortKey = SortKey ;
CommandInfo . MeshFillMode = MeshFillMode ;
CommandInfo . MeshCullMode = MeshCullMode ;
2021-02-17 15:32:52 -04:00
CommandInfo . Flags = Flags ;
2018-12-11 22:25:04 -05:00
}
PassProcessorCreateFunction FPassProcessorManager : : JumpTable [ ( int32 ) EShadingPath : : Num ] [ EMeshPass : : Num ] = { } ;
EMeshPassFlags FPassProcessorManager : : Flags [ ( int32 ) EShadingPath : : Num ] [ EMeshPass : : Num ] = { } ;
2021-01-15 06:16:40 -04:00
2021-04-30 14:04:55 -04:00
# if WANTS_DRAW_MESH_EVENTS
FMeshDrawCommand : : FMeshDrawEvent : : FMeshDrawEvent ( const FMeshDrawCommand & MeshDrawCommand , const uint32 InstanceFactor , FRHICommandList & RHICmdList )
{
if ( GShowMaterialDrawEvents )
{
const FString & MaterialName = MeshDrawCommand . DebugData . MaterialName ;
FName ResourceName = MeshDrawCommand . DebugData . ResourceName ;
FString DrawEventName = FString : : Printf (
TEXT ( " %s %s " ) ,
// Note: this is the parent's material name, not the material instance
* MaterialName ,
ResourceName . IsValid ( ) ? * ResourceName . ToString ( ) : TEXT ( " " ) ) ;
const uint32 Instances = MeshDrawCommand . NumInstances * InstanceFactor ;
if ( Instances > 1 )
{
BEGIN_DRAW_EVENTF (
RHICmdList ,
MaterialEvent ,
* this ,
TEXT ( " %s %u instances " ) ,
* DrawEventName ,
Instances ) ;
}
else
{
BEGIN_DRAW_EVENTF ( RHICmdList , MaterialEvent , * this , * DrawEventName ) ;
}
}
}
# endif