2022-12-06 19:47:11 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "GlobalRenderResources.h"
# include "RenderGraphUtils.h"
2022-12-08 15:35:35 -05:00
# include "Containers/ResourceArray.h"
2023-01-13 17:25:01 -05:00
# include "RenderCore.h"
2023-01-27 14:54:10 -05:00
# include "RenderUtils.h"
2023-04-21 11:31:42 -04:00
# include "Algo/Reverse.h"
2023-08-25 12:14:13 -04:00
# include "Async/Mutex.h"
2022-12-06 19:47:11 -05:00
// The maximum number of transient vertex buffer bytes to allocate before we start panic logging who is doing the allocations
int32 GMaxVertexBytesAllocatedPerFrame = 32 * 1024 * 1024 ;
FAutoConsoleVariableRef CVarMaxVertexBytesAllocatedPerFrame (
TEXT ( " r.MaxVertexBytesAllocatedPerFrame " ) ,
GMaxVertexBytesAllocatedPerFrame ,
TEXT ( " The maximum number of transient vertex buffer bytes to allocate before we start panic logging who is doing the allocations " ) ) ;
2023-04-21 11:31:42 -04:00
int32 GGlobalBufferNumFramesUnusedThreshold = 30 ;
FAutoConsoleVariableRef CVarGlobalBufferNumFramesUnusedThreshold (
2022-12-06 19:47:11 -05:00
TEXT ( " r.NumFramesUnusedBeforeReleasingGlobalResourceBuffers " ) ,
2023-04-21 11:31:42 -04:00
GGlobalBufferNumFramesUnusedThreshold ,
2022-12-06 19:47:11 -05:00
TEXT ( " Number of frames after which unused global resource allocations will be discarded. Set 0 to ignore. (default=30) " ) ) ;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bulk data interface for providing a single color used to initialize a volume texture.
struct FColorBulkData : public FResourceBulkDataInterface
{
FColorBulkData ( uint8 Alpha ) : Color ( 0 , 0 , 0 , Alpha ) { }
FColorBulkData ( int32 R , int32 G , int32 B , int32 A ) : Color ( R , G , B , A ) { }
FColorBulkData ( FColor InColor ) : Color ( InColor ) { }
virtual const void * GetResourceBulkData ( ) const override { return & Color ; }
virtual uint32 GetResourceBulkDataSize ( ) const override { return sizeof ( Color ) ; }
virtual void Discard ( ) override { }
FColor Color ;
} ;
/**
* A solid - colored 1 x1 texture .
*/
template < int32 R , int32 G , int32 B , int32 A >
class FColoredTexture : public FTextureWithSRV
{
public :
// FResource interface.
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
// Create the texture RHI.
FColorBulkData BulkData ( R , G , B , A ) ;
// BGRA typed UAV is unsupported per D3D spec, use RGBA here.
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create2D ( TEXT ( " ColoredTexture " ) , 1 , 1 , PF_R8G8B8A8 )
. SetFlags ( ETextureCreateFlags : : ShaderResource )
2023-03-13 07:12:41 -04:00
. SetBulkData ( & BulkData )
. SetClassName ( TEXT ( " FColoredTexture " ) ) ;
2022-12-06 19:47:11 -05:00
TextureRHI = RHICreateTexture ( Desc ) ;
// Create the sampler state RHI resource.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
// Create a view of the texture
2023-06-19 13:56:56 -04:00
ShaderResourceViewRHI = RHICmdList . CreateShaderResourceView ( TextureRHI , 0u ) ;
2022-12-06 19:47:11 -05:00
}
virtual uint32 GetSizeX ( ) const override { return 1 ; }
virtual uint32 GetSizeY ( ) const override { return 1 ; }
} ;
class FEmptyVertexBuffer : public FVertexBufferWithSRV
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
// Create the texture RHI.
FRHIResourceCreateInfo CreateInfo ( TEXT ( " EmptyVertexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
VertexBufferRHI = RHICmdList . CreateVertexBuffer ( 16u , BUF_Static | BUF_ShaderResource | BUF_UnorderedAccess , CreateInfo ) ;
2022-12-06 19:47:11 -05:00
// Create a view of the buffer
2023-06-19 13:56:56 -04:00
ShaderResourceViewRHI = RHICmdList . CreateShaderResourceView ( VertexBufferRHI , 4u , PF_R32_UINT ) ;
UnorderedAccessViewRHI = RHICmdList . CreateUnorderedAccessView ( VertexBufferRHI , PF_R32_UINT ) ;
2022-12-06 19:47:11 -05:00
}
} ;
2023-02-08 09:27:57 -05:00
class FEmptyStructuredBuffer : public FVertexBufferWithSRV
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2023-02-08 09:27:57 -05:00
{
// Create the buffer RHI.
FRHIResourceCreateInfo CreateInfo ( TEXT ( " EmptyStructuredBuffer " ) ) ;
const uint32 BufferSize = sizeof ( uint32 ) * 4u ;
2023-06-22 11:08:27 -04:00
VertexBufferRHI = RHICmdList . CreateStructuredBuffer ( sizeof ( uint32 ) , BufferSize , BUF_Static | BUF_ShaderResource | BUF_UnorderedAccess , CreateInfo ) ;
2023-02-08 09:27:57 -05:00
// Create a view of the buffer
2023-06-19 13:56:56 -04:00
ShaderResourceViewRHI = RHICmdList . CreateShaderResourceView ( VertexBufferRHI ) ;
UnorderedAccessViewRHI = RHICmdList . CreateUnorderedAccessView ( VertexBufferRHI , false , false ) ;
2023-02-08 09:27:57 -05:00
}
} ;
2022-12-06 19:47:11 -05:00
class FBlackTextureWithSRV : public FColoredTexture < 0 , 0 , 0 , 255 >
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
2023-06-19 13:56:56 -04:00
FColoredTexture : : InitRHI ( RHICmdList ) ;
2022-12-06 19:47:11 -05:00
FRHITextureReference : : DefaultTexture = TextureRHI ;
}
virtual void ReleaseRHI ( ) override
{
FRHITextureReference : : DefaultTexture . SafeRelease ( ) ;
FColoredTexture : : ReleaseRHI ( ) ;
}
} ;
2023-06-12 17:54:08 -04:00
FTextureWithSRV * GWhiteTextureWithSRV = new TGlobalResource < FColoredTexture < 255 , 255 , 255 , 255 > , FRenderResource : : EInitPhase : : Pre > ;
FTextureWithSRV * GBlackTextureWithSRV = new TGlobalResource < FBlackTextureWithSRV , FRenderResource : : EInitPhase : : Pre > ( ) ;
FTextureWithSRV * GTransparentBlackTextureWithSRV = new TGlobalResource < FColoredTexture < 0 , 0 , 0 , 0 > , FRenderResource : : EInitPhase : : Pre > ;
2022-12-06 19:47:11 -05:00
FTexture * GWhiteTexture = GWhiteTextureWithSRV ;
FTexture * GBlackTexture = GBlackTextureWithSRV ;
FTexture * GTransparentBlackTexture = GTransparentBlackTextureWithSRV ;
2023-06-12 17:54:08 -04:00
FVertexBufferWithSRV * GEmptyVertexBufferWithUAV = new TGlobalResource < FEmptyVertexBuffer , FRenderResource : : EInitPhase : : Pre > ;
FVertexBufferWithSRV * GEmptyStructuredBufferWithUAV = new TGlobalResource < FEmptyStructuredBuffer , FRenderResource : : EInitPhase : : Pre > ;
2022-12-06 19:47:11 -05:00
class FWhiteVertexBuffer : public FVertexBufferWithSRV
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
// Create the texture RHI.
FRHIResourceCreateInfo CreateInfo ( TEXT ( " WhiteVertexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
VertexBufferRHI = RHICmdList . CreateVertexBuffer ( sizeof ( FVector4f ) , BUF_Static | BUF_ShaderResource , CreateInfo ) ;
2022-12-06 19:47:11 -05:00
2023-06-19 13:56:56 -04:00
FVector4f * BufferData = ( FVector4f * ) RHICmdList . LockBuffer ( VertexBufferRHI , 0 , sizeof ( FVector4f ) , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
* BufferData = FVector4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
2023-06-19 13:56:56 -04:00
RHICmdList . UnlockBuffer ( VertexBufferRHI ) ;
2022-12-06 19:47:11 -05:00
// Create a view of the buffer
2023-06-19 13:56:56 -04:00
ShaderResourceViewRHI = RHICmdList . CreateShaderResourceView ( VertexBufferRHI , sizeof ( FVector4f ) , PF_A32B32G32R32F ) ;
2022-12-06 19:47:11 -05:00
}
} ;
2023-06-12 17:54:08 -04:00
FVertexBufferWithSRV * GWhiteVertexBufferWithSRV = new TGlobalResource < FWhiteVertexBuffer , FRenderResource : : EInitPhase : : Pre > ;
2022-12-06 19:47:11 -05:00
class FWhiteVertexBufferWithRDG : public FBufferWithRDG
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
if ( ! Buffer . IsValid ( ) )
{
Buffer = AllocatePooledBuffer ( FRDGBufferDesc : : CreateBufferDesc ( sizeof ( FVector4f ) , 1 ) , TEXT ( " WhiteVertexBufferWithRDG " ) ) ;
FVector4f * BufferData = ( FVector4f * ) RHICmdList . LockBuffer ( Buffer - > GetRHI ( ) , 0 , sizeof ( FVector4f ) , RLM_WriteOnly ) ;
* BufferData = FVector4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
RHICmdList . UnlockBuffer ( Buffer - > GetRHI ( ) ) ;
}
}
} ;
2023-06-12 17:54:08 -04:00
FBufferWithRDG * GWhiteVertexBufferWithRDG = new TGlobalResource < FWhiteVertexBufferWithRDG , FRenderResource : : EInitPhase : : Pre > ( ) ;
2022-12-06 19:47:11 -05:00
/**
* A class representing a 1 x1x1 black volume texture .
*/
template < EPixelFormat PixelFormat , uint8 Alpha >
class FBlackVolumeTexture : public FTexture
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
if ( GSupportsTexture3D )
{
// Create the texture.
FColorBulkData BulkData ( Alpha ) ;
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create3D ( TEXT ( " BlackVolumeTexture3D " ) , 1 , 1 , 1 , PixelFormat )
. SetFlags ( ETextureCreateFlags : : ShaderResource )
2023-03-13 07:12:41 -04:00
. SetBulkData ( & BulkData )
. SetClassName ( TEXT ( " FBlackVolumeTexture " ) ) ;
2022-12-06 19:47:11 -05:00
TextureRHI = RHICreateTexture ( Desc ) ;
}
else
{
// Create a texture, even though it's not a volume texture
FColorBulkData BulkData ( Alpha ) ;
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create2D ( TEXT ( " BlackVolumeTexture2D " ) , 1 , 1 , PixelFormat )
. SetFlags ( ETextureCreateFlags : : ShaderResource )
. SetBulkData ( & BulkData ) ;
TextureRHI = RHICreateTexture ( Desc ) ;
}
// Create the sampler state.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
}
virtual uint32 GetSizeX ( ) const override { return 1 ; }
virtual uint32 GetSizeY ( ) const override { return 1 ; }
} ;
/** Global black volume texture resource. */
2023-06-12 17:54:08 -04:00
FTexture * GBlackVolumeTexture = new TGlobalResource < FBlackVolumeTexture < PF_B8G8R8A8 , 0 > , FRenderResource : : EInitPhase : : Pre > ( ) ;
FTexture * GBlackAlpha1VolumeTexture = new TGlobalResource < FBlackVolumeTexture < PF_B8G8R8A8 , 255 > , FRenderResource : : EInitPhase : : Pre > ( ) ;
2022-12-06 19:47:11 -05:00
/** Global black volume texture resource. */
2023-06-12 17:54:08 -04:00
FTexture * GBlackUintVolumeTexture = new TGlobalResource < FBlackVolumeTexture < PF_R8G8B8A8_UINT , 0 > , FRenderResource : : EInitPhase : : Pre > ( ) ;
2022-12-06 19:47:11 -05:00
class FBlackArrayTexture : public FTexture
{
public :
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
// Create the texture RHI.
FColorBulkData BulkData ( 0 ) ;
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create2DArray ( TEXT ( " BlackArrayTexture " ) , 1 , 1 , 1 , PF_B8G8R8A8 )
. SetFlags ( ETextureCreateFlags : : ShaderResource )
2023-03-13 07:12:41 -04:00
. SetBulkData ( & BulkData )
. SetClassName ( TEXT ( " FBlackArrayTexture " ) ) ;
2022-12-06 19:47:11 -05:00
TextureRHI = RHICreateTexture ( Desc ) ;
// Create the sampler state RHI resource.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
}
virtual uint32 GetSizeX ( ) const override { return 1 ; }
virtual uint32 GetSizeY ( ) const override { return 1 ; }
} ;
2023-06-12 17:54:08 -04:00
FTexture * GBlackArrayTexture = new TGlobalResource < FBlackArrayTexture , FRenderResource : : EInitPhase : : Pre > ;
2022-12-06 19:47:11 -05:00
//
// FMipColorTexture implementation
//
/**
* A texture that has a different solid color in each mip - level
*/
class FMipColorTexture : public FTexture
{
public :
enum
{
NumMips = 12
} ;
static const FColor MipColors [ NumMips ] ;
// FResource interface.
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
// Create the texture RHI.
int32 TextureSize = 1 < < ( NumMips - 1 ) ;
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create2D ( TEXT ( " FMipColorTexture " ) , TextureSize , TextureSize , PF_B8G8R8A8 )
. SetNumMips ( NumMips )
2023-03-13 07:12:41 -04:00
. SetFlags ( ETextureCreateFlags : : ShaderResource )
. SetClassName ( TEXT ( " FMipColorTexture " ) ) ;
2022-12-06 19:47:11 -05:00
TextureRHI = RHICreateTexture ( Desc ) ;
// Write the contents of the texture.
uint32 DestStride ;
int32 Size = TextureSize ;
for ( int32 MipIndex = 0 ; MipIndex < NumMips ; + + MipIndex )
{
FColor * DestBuffer = ( FColor * ) RHILockTexture2D ( TextureRHI , MipIndex , RLM_WriteOnly , DestStride , false ) ;
for ( int32 Y = 0 ; Y < Size ; + + Y )
{
for ( int32 X = 0 ; X < Size ; + + X )
{
DestBuffer [ X ] = MipColors [ NumMips - 1 - MipIndex ] ;
}
DestBuffer + = DestStride / sizeof ( FColor ) ;
}
RHIUnlockTexture2D ( TextureRHI , MipIndex , false ) ;
Size > > = 1 ;
}
// Create the sampler state RHI resource.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
}
/** Returns the width of the texture in pixels. */
virtual uint32 GetSizeX ( ) const override
{
int32 TextureSize = 1 < < ( NumMips - 1 ) ;
return TextureSize ;
}
/** Returns the height of the texture in pixels. */
// PVS-Studio notices that the implementation of GetSizeX is identical to this one
// and warns us. In this case, it is intentional, so we disable the warning:
virtual uint32 GetSizeY ( ) const override //-V524
{
int32 TextureSize = 1 < < ( NumMips - 1 ) ;
return TextureSize ;
}
} ;
const FColor FMipColorTexture : : MipColors [ NumMips ] =
{
FColor ( 80 , 80 , 80 , 0 ) , // Mip 0: 1x1 (dark grey)
FColor ( 200 , 200 , 200 , 0 ) , // Mip 1: 2x2 (light grey)
FColor ( 200 , 200 , 0 , 0 ) , // Mip 2: 4x4 (medium yellow)
FColor ( 255 , 255 , 0 , 0 ) , // Mip 3: 8x8 (yellow)
FColor ( 160 , 255 , 40 , 0 ) , // Mip 4: 16x16 (light green)
FColor ( 0 , 255 , 0 , 0 ) , // Mip 5: 32x32 (green)
FColor ( 0 , 255 , 200 , 0 ) , // Mip 6: 64x64 (cyan)
FColor ( 0 , 170 , 170 , 0 ) , // Mip 7: 128x128 (light blue)
FColor ( 60 , 60 , 255 , 0 ) , // Mip 8: 256x256 (dark blue)
FColor ( 255 , 0 , 255 , 0 ) , // Mip 9: 512x512 (pink)
FColor ( 255 , 0 , 0 , 0 ) , // Mip 10: 1024x1024 (red)
FColor ( 255 , 130 , 0 , 0 ) , // Mip 11: 2048x2048 (orange)
} ;
FTexture * GMipColorTexture = new FMipColorTexture ;
int32 GMipColorTextureMipLevels = FMipColorTexture : : NumMips ;
// 4: 8x8 cubemap resolution, shader needs to use the same value as preprocessing
const uint32 GDiffuseConvolveMipLevel = 4 ;
/** A solid color cube texture. */
class FSolidColorTextureCube : public FTexture
{
public :
FSolidColorTextureCube ( const FColor & InColor )
: bInitToZero ( false )
, PixelFormat ( PF_B8G8R8A8 )
, ColorData ( InColor . DWColor ( ) )
{ }
FSolidColorTextureCube ( EPixelFormat InPixelFormat )
: bInitToZero ( true )
, PixelFormat ( InPixelFormat )
, ColorData ( 0 )
{ }
// FRenderResource interface.
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
// Create the texture RHI.
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : CreateCube ( TEXT ( " SolidColorCube " ) , 1 , PixelFormat )
2023-03-13 07:12:41 -04:00
. SetFlags ( ETextureCreateFlags : : ShaderResource )
. SetClassName ( TEXT ( " FSolidColorTextureCube " ) ) ;
2022-12-06 19:47:11 -05:00
FTextureCubeRHIRef TextureCube = RHICreateTexture ( Desc ) ;
TextureRHI = TextureCube ;
// Write the contents of the texture.
for ( uint32 FaceIndex = 0 ; FaceIndex < 6 ; FaceIndex + + )
{
uint32 DestStride ;
void * DestBuffer = RHILockTextureCubeFace ( TextureCube , FaceIndex , 0 , 0 , RLM_WriteOnly , DestStride , false ) ;
if ( bInitToZero )
{
FMemory : : Memzero ( DestBuffer , GPixelFormats [ PixelFormat ] . BlockBytes ) ;
}
else
{
FMemory : : Memcpy ( DestBuffer , & ColorData , sizeof ( ColorData ) ) ;
}
RHIUnlockTextureCubeFace ( TextureCube , FaceIndex , 0 , 0 , false ) ;
}
// Create the sampler state RHI resource.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
}
virtual uint32 GetSizeX ( ) const override { return 1 ; }
virtual uint32 GetSizeY ( ) const override { return 1 ; }
private :
const bool bInitToZero ;
const EPixelFormat PixelFormat ;
const uint32 ColorData ;
} ;
/** A white cube texture. */
2023-06-12 17:54:08 -04:00
FTexture * GWhiteTextureCube = new TGlobalResource < FSolidColorTextureCube , FRenderResource : : EInitPhase : : Pre > ( FColor : : White ) ;
2022-12-06 19:47:11 -05:00
/** A black cube texture. */
2023-06-12 17:54:08 -04:00
FTexture * GBlackTextureCube = new TGlobalResource < FSolidColorTextureCube , FRenderResource : : EInitPhase : : Pre > ( FColor : : Black ) ;
2022-12-06 19:47:11 -05:00
/** A black cube texture. */
2023-06-12 17:54:08 -04:00
FTexture * GBlackTextureDepthCube = new TGlobalResource < FSolidColorTextureCube , FRenderResource : : EInitPhase : : Pre > ( PF_ShadowDepth ) ;
2022-12-06 19:47:11 -05:00
class FBlackCubeArrayTexture : public FTexture
{
public :
// FResource interface.
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
2023-11-16 22:11:48 -05:00
const TCHAR * Name = TEXT ( " BlackCubeArray " ) ;
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : CreateCubeArray ( TEXT ( " BlackCubeArray " ) , 1 , 1 , PF_B8G8R8A8 )
. SetFlags ( ETextureCreateFlags : : ShaderResource )
. SetClassName ( TEXT ( " FBlackCubeArrayTexture " ) ) ;
// Create the texture RHI.
TextureRHI = RHICreateTexture ( Desc ) ;
for ( uint32 FaceIndex = 0 ; FaceIndex < 6 ; FaceIndex + + )
2022-12-06 19:47:11 -05:00
{
2023-11-16 22:11:48 -05:00
uint32 DestStride ;
FColor * DestBuffer = ( FColor * ) RHILockTextureCubeFace ( TextureRHI , FaceIndex , 0 , 0 , RLM_WriteOnly , DestStride , false ) ;
// Note: alpha is used by reflection environment to say how much of the foreground texture is visible, so 0 says it is completely invisible
* DestBuffer = FColor ( 0 , 0 , 0 , 0 ) ;
RHIUnlockTextureCubeFace ( TextureRHI , FaceIndex , 0 , 0 , false ) ;
2022-12-06 19:47:11 -05:00
}
2023-11-16 22:11:48 -05:00
// Create the sampler state RHI resource.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
2022-12-06 19:47:11 -05:00
}
virtual uint32 GetSizeX ( ) const override { return 1 ; }
virtual uint32 GetSizeY ( ) const override { return 1 ; }
} ;
2023-06-12 17:54:08 -04:00
FTexture * GBlackCubeArrayTexture = new TGlobalResource < FBlackCubeArrayTexture , FRenderResource : : EInitPhase : : Pre > ;
2022-12-06 19:47:11 -05:00
/**
* A UINT 1 x1 texture .
*/
template < EPixelFormat Format , uint32 R = 0 , uint32 G = 0 , uint32 B = 0 , uint32 A = 0 >
class FUintTexture : public FTextureWithSRV
{
public :
// FResource interface.
2023-06-19 13:56:56 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
const FRHITextureCreateDesc Desc =
FRHITextureCreateDesc : : Create2D ( TEXT ( " UintTexture " ) , 1 , 1 , Format )
2023-03-13 07:12:41 -04:00
. SetFlags ( ETextureCreateFlags : : ShaderResource )
. SetClassName ( TEXT ( " FUintTexture " ) ) ;
2022-12-06 19:47:11 -05:00
TextureRHI = RHICreateTexture ( Desc ) ;
// Write the contents of the texture.
uint32 DestStride ;
void * DestBuffer = RHILockTexture2D ( TextureRHI , 0 , RLM_WriteOnly , DestStride , false ) ;
WriteData ( DestBuffer ) ;
RHIUnlockTexture2D ( TextureRHI , 0 , false ) ;
// Create the sampler state RHI resource.
FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Point , AM_Wrap , AM_Wrap , AM_Wrap ) ;
SamplerStateRHI = GetOrCreateSamplerState ( SamplerStateInitializer ) ;
// Create a view of the texture
2023-06-19 13:56:56 -04:00
ShaderResourceViewRHI = RHICmdList . CreateShaderResourceView ( TextureRHI , 0u ) ;
2022-12-06 19:47:11 -05:00
}
virtual uint32 GetSizeX ( ) const override { return 1 ; }
virtual uint32 GetSizeY ( ) const override { return 1 ; }
protected :
static int32 GetNumChannels ( )
{
return GPixelFormats [ Format ] . NumComponents ;
}
static int32 GetBytesPerChannel ( )
{
return GPixelFormats [ Format ] . BlockBytes / GPixelFormats [ Format ] . NumComponents ;
}
template < typename T >
static void DoWriteData ( T * DataPtr )
{
T Values [ ] = { R , G , B , A } ;
for ( int32 i = 0 ; i < GetNumChannels ( ) ; + + i )
{
DataPtr [ i ] = Values [ i ] ;
}
}
static void WriteData ( void * DataPtr )
{
switch ( GetBytesPerChannel ( ) )
{
case 1 :
DoWriteData ( ( uint8 * ) DataPtr ) ;
return ;
case 2 :
DoWriteData ( ( uint16 * ) DataPtr ) ;
return ;
case 4 :
DoWriteData ( ( uint32 * ) DataPtr ) ;
return ;
}
// Unsupported format
check ( 0 ) ;
}
} ;
2023-06-12 17:54:08 -04:00
FTexture * GBlackUintTexture = new TGlobalResource < FUintTexture < PF_R32G32B32A32_UINT > , FRenderResource : : EInitPhase : : Pre > ;
2022-12-06 19:47:11 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FNullColorVertexBuffer
FNullColorVertexBuffer : : FNullColorVertexBuffer ( ) = default ;
FNullColorVertexBuffer : : ~ FNullColorVertexBuffer ( ) = default ;
2023-06-19 13:56:56 -04:00
void FNullColorVertexBuffer : : InitRHI ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo ( TEXT ( " FNullColorVertexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
VertexBufferRHI = RHICmdList . CreateBuffer ( sizeof ( uint32 ) * 4 , BUF_Static | BUF_VertexBuffer | BUF_ShaderResource , 0 , ERHIAccess : : VertexOrIndexBuffer | ERHIAccess : : SRVMask , CreateInfo ) ;
uint32 * Vertices = ( uint32 * ) RHICmdList . LockBuffer ( VertexBufferRHI , 0 , sizeof ( uint32 ) * 4 , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
Vertices [ 0 ] = FColor ( 255 , 255 , 255 , 255 ) . DWColor ( ) ;
Vertices [ 1 ] = FColor ( 255 , 255 , 255 , 255 ) . DWColor ( ) ;
Vertices [ 2 ] = FColor ( 255 , 255 , 255 , 255 ) . DWColor ( ) ;
Vertices [ 3 ] = FColor ( 255 , 255 , 255 , 255 ) . DWColor ( ) ;
2023-06-19 13:56:56 -04:00
RHICmdList . UnlockBuffer ( VertexBufferRHI ) ;
VertexBufferSRV = RHICmdList . CreateShaderResourceView ( VertexBufferRHI , sizeof ( FColor ) , PF_R8G8B8A8 ) ;
2022-12-06 19:47:11 -05:00
}
void FNullColorVertexBuffer : : ReleaseRHI ( )
{
VertexBufferSRV . SafeRelease ( ) ;
FVertexBuffer : : ReleaseRHI ( ) ;
}
/** The global null color vertex buffer, which is set with a stride of 0 on meshes without a color component. */
2023-06-12 17:54:08 -04:00
TGlobalResource < FNullColorVertexBuffer , FRenderResource : : EInitPhase : : Pre > GNullColorVertexBuffer ;
2022-12-06 19:47:11 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FNullVertexBuffer
FNullVertexBuffer : : FNullVertexBuffer ( ) = default ;
FNullVertexBuffer : : ~ FNullVertexBuffer ( ) = default ;
2023-06-19 13:56:56 -04:00
void FNullVertexBuffer : : InitRHI ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo ( TEXT ( " FNullVertexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
VertexBufferRHI = RHICmdList . CreateBuffer ( sizeof ( FVector3f ) , BUF_Static | BUF_VertexBuffer | BUF_ShaderResource , 0 , ERHIAccess : : VertexOrIndexBuffer | ERHIAccess : : SRVMask , CreateInfo ) ;
FVector3f * LockedData = ( FVector3f * ) RHICmdList . LockBuffer ( VertexBufferRHI , 0 , sizeof ( FVector3f ) , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
* LockedData = FVector3f ( 0.0f ) ;
2023-06-19 13:56:56 -04:00
RHICmdList . UnlockBuffer ( VertexBufferRHI ) ;
2022-12-06 19:47:11 -05:00
2023-06-19 13:56:56 -04:00
VertexBufferSRV = RHICmdList . CreateShaderResourceView ( VertexBufferRHI , sizeof ( FColor ) , PF_R8G8B8A8 ) ;
2022-12-06 19:47:11 -05:00
}
void FNullVertexBuffer : : ReleaseRHI ( )
{
VertexBufferSRV . SafeRelease ( ) ;
FVertexBuffer : : ReleaseRHI ( ) ;
}
/** The global null vertex buffer, which is set with a stride of 0 on meshes */
2023-06-12 17:54:08 -04:00
TGlobalResource < FNullVertexBuffer , FRenderResource : : EInitPhase : : Pre > GNullVertexBuffer ;
2022-12-06 19:47:11 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FScreenSpaceVertexBuffer
2023-06-19 13:56:56 -04:00
void FScreenSpaceVertexBuffer : : InitRHI ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo ( TEXT ( " FScreenSpaceVertexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
VertexBufferRHI = RHICmdList . CreateVertexBuffer ( sizeof ( FVector2f ) * 4 , BUF_Static , CreateInfo ) ;
void * VoidPtr = RHICmdList . LockBuffer ( VertexBufferRHI , 0 , sizeof ( FVector2f ) * 4 , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
static const FVector2f Vertices [ 4 ] =
{
FVector2f ( - 1 , - 1 ) ,
FVector2f ( - 1 , + 1 ) ,
FVector2f ( + 1 , - 1 ) ,
FVector2f ( + 1 , + 1 ) ,
} ;
FMemory : : Memcpy ( VoidPtr , Vertices , sizeof ( FVector2f ) * 4 ) ;
2023-06-19 13:56:56 -04:00
RHICmdList . UnlockBuffer ( VertexBufferRHI ) ;
2022-12-06 19:47:11 -05:00
}
2023-06-12 17:54:08 -04:00
TGlobalResource < FScreenSpaceVertexBuffer , FRenderResource : : EInitPhase : : Pre > GScreenSpaceVertexBuffer ;
2022-12-06 19:47:11 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FTileVertexDeclaration
FTileVertexDeclaration : : FTileVertexDeclaration ( ) = default ;
FTileVertexDeclaration : : ~ FTileVertexDeclaration ( ) = default ;
2023-06-19 13:56:56 -04:00
void FTileVertexDeclaration : : InitRHI ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
FVertexDeclarationElementList Elements ;
uint16 Stride = sizeof ( FVector2f ) ;
Elements . Add ( FVertexElement ( 0 , 0 , VET_Float2 , 0 , Stride , false ) ) ;
VertexDeclarationRHI = RHICreateVertexDeclaration ( Elements ) ;
}
void FTileVertexDeclaration : : ReleaseRHI ( )
{
VertexDeclarationRHI . SafeRelease ( ) ;
}
2023-06-12 17:54:08 -04:00
TGlobalResource < FTileVertexDeclaration , FRenderResource : : EInitPhase : : Pre > GTileVertexDeclaration ;
2022-12-06 19:47:11 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FCubeIndexBuffer
2023-06-19 13:56:56 -04:00
void FCubeIndexBuffer : : InitRHI ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo ( TEXT ( " FCubeIndexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
IndexBufferRHI = RHICmdList . CreateIndexBuffer ( sizeof ( uint16 ) , sizeof ( uint16 ) * NUM_CUBE_VERTICES , BUF_Static , CreateInfo ) ;
void * VoidPtr = RHICmdList . LockBuffer ( IndexBufferRHI , 0 , sizeof ( uint16 ) * NUM_CUBE_VERTICES , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
FMemory : : Memcpy ( VoidPtr , GCubeIndices , NUM_CUBE_VERTICES * sizeof ( uint16 ) ) ;
2023-06-19 13:56:56 -04:00
RHICmdList . UnlockBuffer ( IndexBufferRHI ) ;
2022-12-06 19:47:11 -05:00
}
2023-06-12 17:54:08 -04:00
TGlobalResource < FCubeIndexBuffer , FRenderResource : : EInitPhase : : Pre > GCubeIndexBuffer ;
2022-12-06 19:47:11 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FTwoTrianglesIndexBuffer
2023-06-19 13:56:56 -04:00
void FTwoTrianglesIndexBuffer : : InitRHI ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo ( TEXT ( " FTwoTrianglesIndexBuffer " ) ) ;
2023-06-19 13:56:56 -04:00
IndexBufferRHI = RHICmdList . CreateIndexBuffer ( sizeof ( uint16 ) , sizeof ( uint16 ) * 6 , BUF_Static , CreateInfo ) ;
void * VoidPtr = RHICmdList . LockBuffer ( IndexBufferRHI , 0 , sizeof ( uint16 ) * 6 , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
static const uint16 Indices [ ] = { 0 , 1 , 3 , 0 , 3 , 2 } ;
FMemory : : Memcpy ( VoidPtr , Indices , 6 * sizeof ( uint16 ) ) ;
2023-06-19 13:56:56 -04:00
RHICmdList . UnlockBuffer ( IndexBufferRHI ) ;
2022-12-06 19:47:11 -05:00
}
2023-06-12 17:54:08 -04:00
TGlobalResource < FTwoTrianglesIndexBuffer , FRenderResource : : EInitPhase : : Pre > GTwoTrianglesIndexBuffer ;
2022-12-06 19:47:11 -05:00
/*------------------------------------------------------------------------------
FGlobalDynamicVertexBuffer implementation .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* An individual dynamic vertex buffer .
*/
2023-08-25 12:14:13 -04:00
template < typename BufferType >
class TDynamicBuffer final : public BufferType
2022-12-06 19:47:11 -05:00
{
public :
/** The aligned size of all dynamic vertex buffers. */
enum { ALIGNMENT = ( 1 < < 16 ) } ; // 64KB
/** Pointer to the vertex buffer mapped in main memory. */
uint8 * MappedBuffer ;
/** Size of the vertex buffer in bytes. */
uint32 BufferSize ;
/** Number of bytes currently allocated from the buffer. */
uint32 AllocatedByteCount ;
2023-08-25 12:14:13 -04:00
/** Stride of the buffer in bytes. */
uint32 Stride ;
2023-04-21 11:31:42 -04:00
/** Last render thread frame this resource was used in. */
uint64 LastUsedFrame = 0 ;
2022-12-06 19:47:11 -05:00
/** Default constructor. */
2023-08-25 12:14:13 -04:00
explicit TDynamicBuffer ( uint32 InMinBufferSize , uint32 InStride )
2022-12-06 19:47:11 -05:00
: MappedBuffer ( NULL )
, BufferSize ( FMath : : Max < uint32 > ( Align ( InMinBufferSize , ALIGNMENT ) , ALIGNMENT ) )
, AllocatedByteCount ( 0 )
2023-08-25 12:14:13 -04:00
, Stride ( InStride )
2022-12-06 19:47:11 -05:00
{
}
/**
* Locks the vertex buffer so it may be written to .
*/
2023-06-13 11:46:40 -04:00
void Lock ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
check ( MappedBuffer = = NULL ) ;
check ( AllocatedByteCount = = 0 ) ;
2023-08-25 12:14:13 -04:00
check ( IsValidRef ( BufferType : : GetRHI ( ) ) ) ;
MappedBuffer = ( uint8 * ) RHICmdList . LockBuffer ( BufferType : : GetRHI ( ) , 0 , BufferSize , RLM_WriteOnly ) ;
2022-12-06 19:47:11 -05:00
}
/**
* Unocks the buffer so the GPU may read from it .
*/
2023-06-13 11:46:40 -04:00
void Unlock ( FRHICommandListBase & RHICmdList )
2022-12-06 19:47:11 -05:00
{
check ( MappedBuffer ! = NULL ) ;
2023-08-25 12:14:13 -04:00
check ( IsValidRef ( BufferType : : GetRHI ( ) ) ) ;
RHICmdList . UnlockBuffer ( BufferType : : GetRHI ( ) ) ;
2022-12-06 19:47:11 -05:00
MappedBuffer = NULL ;
AllocatedByteCount = 0 ;
}
// FRenderResource interface.
2023-06-13 11:46:40 -04:00
virtual void InitRHI ( FRHICommandListBase & RHICmdList ) override
2022-12-06 19:47:11 -05:00
{
2023-08-25 12:14:13 -04:00
check ( ! IsValidRef ( BufferType : : GetRHI ( ) ) ) ;
FRHIResourceCreateInfo CreateInfo ( TEXT ( " FDynamicBuffer " ) ) ;
BufferType : : SetRHI ( RHICmdList . CreateBuffer ( BufferSize , Stride = = 0 ? EBufferUsageFlags : : VertexBuffer : EBufferUsageFlags : : IndexBuffer , Stride , ERHIAccess : : VertexOrIndexBuffer , CreateInfo ) ) ;
2022-12-06 19:47:11 -05:00
MappedBuffer = NULL ;
AllocatedByteCount = 0 ;
}
virtual void ReleaseRHI ( ) override
{
2023-08-25 12:14:13 -04:00
BufferType : : ReleaseRHI ( ) ;
2022-12-06 19:47:11 -05:00
MappedBuffer = NULL ;
AllocatedByteCount = 0 ;
}
} ;
/**
2023-08-25 12:14:13 -04:00
* A pool of dynamic buffers .
2022-12-06 19:47:11 -05:00
*/
2023-08-25 12:14:13 -04:00
template < typename DynamicBufferType >
struct TDynamicBufferPool : public FRenderResource
2022-12-06 19:47:11 -05:00
{
2023-08-25 12:14:13 -04:00
UE : : FMutex Mutex ;
TArray < DynamicBufferType * > LiveList ;
TArray < DynamicBufferType * > FreeList ;
TArray < DynamicBufferType * > LockList ;
TArray < DynamicBufferType * > ReclaimList ;
2023-04-21 11:31:42 -04:00
std : : atomic_uint32_t TotalAllocatedMemory { 0 } ;
uint32 CurrentCycle = 0 ;
2022-12-06 19:47:11 -05:00
2023-08-25 12:14:13 -04:00
DynamicBufferType * Acquire ( FRHICommandListBase & RHICmdList , uint32 SizeInBytes , uint32 Stride )
2022-12-06 19:47:11 -05:00
{
2023-04-21 11:31:42 -04:00
const uint32 MinimumBufferSize = 65536u ;
SizeInBytes = FMath : : Max ( SizeInBytes , MinimumBufferSize ) ;
2023-08-25 12:14:13 -04:00
DynamicBufferType * FoundBuffer = nullptr ;
2023-04-21 11:31:42 -04:00
bool bInitializeBuffer = false ;
{
2023-08-25 12:14:13 -04:00
UE : : TScopeLock Lock ( Mutex ) ;
2023-04-21 11:31:42 -04:00
// Traverse the free list like a stack, starting from the top, so recently reclaimed items are allocated first.
for ( int32 Index = FreeList . Num ( ) - 1 ; Index > = 0 ; - - Index )
{
2023-08-25 12:14:13 -04:00
DynamicBufferType * Buffer = FreeList [ Index ] ;
2023-04-21 11:31:42 -04:00
2023-08-25 12:14:13 -04:00
if ( SizeInBytes < = Buffer - > BufferSize & & Buffer - > Stride = = Stride )
2023-04-21 11:31:42 -04:00
{
FreeList . RemoveAt ( Index , 1 , false ) ;
FoundBuffer = Buffer ;
break ;
}
}
if ( ! FoundBuffer )
{
2023-08-25 12:14:13 -04:00
FoundBuffer = new DynamicBufferType ( SizeInBytes , Stride ) ;
2023-04-21 11:31:42 -04:00
LiveList . Emplace ( FoundBuffer ) ;
bInitializeBuffer = true ;
}
check ( FoundBuffer ) ;
}
if ( IsRenderAlarmLoggingEnabled ( ) )
{
UE_LOG ( LogRendererCore , Warning , TEXT ( " FGlobalDynamicVertexBuffer::Allocate(%u), will have allocated %u total this frame " ) , SizeInBytes , TotalAllocatedMemory . load ( ) ) ;
}
if ( bInitializeBuffer )
{
FoundBuffer - > InitResource ( RHICmdList ) ;
2023-06-08 12:25:41 -04:00
TotalAllocatedMemory + = FoundBuffer - > BufferSize ;
2023-04-21 11:31:42 -04:00
}
FoundBuffer - > Lock ( RHICmdList ) ;
FoundBuffer - > LastUsedFrame = GFrameCounterRenderThread ;
return FoundBuffer ;
2022-12-06 19:47:11 -05:00
}
2023-08-25 12:14:13 -04:00
void Forfeit ( FRHICommandListBase & RHICmdList , TConstArrayView < DynamicBufferType * > BuffersToForfeit )
2022-12-06 19:47:11 -05:00
{
2023-08-25 12:14:13 -04:00
if ( ! BuffersToForfeit . IsEmpty ( ) )
2022-12-06 19:47:11 -05:00
{
2023-08-25 12:14:13 -04:00
for ( DynamicBufferType * Buffer : BuffersToForfeit )
{
Buffer - > Unlock ( RHICmdList ) ;
}
2023-04-21 11:31:42 -04:00
2023-08-25 12:14:13 -04:00
UE : : TScopeLock Lock ( Mutex ) ;
ReclaimList . Append ( BuffersToForfeit ) ;
}
2023-04-21 11:31:42 -04:00
}
void GarbageCollect ( )
{
2023-08-25 12:14:13 -04:00
UE : : TScopeLock Lock ( Mutex ) ;
2023-04-21 11:31:42 -04:00
FreeList . Append ( ReclaimList ) ;
ReclaimList . Reset ( ) ;
for ( int32 Index = 0 ; Index < LiveList . Num ( ) ; + + Index )
{
2023-08-25 12:14:13 -04:00
DynamicBufferType * Buffer = LiveList [ Index ] ;
2023-04-21 11:31:42 -04:00
if ( GGlobalBufferNumFramesUnusedThreshold > 0 & & Buffer - > LastUsedFrame + GGlobalBufferNumFramesUnusedThreshold < = GFrameCounterRenderThread )
{
2023-06-02 11:56:01 -04:00
TotalAllocatedMemory - = Buffer - > BufferSize ;
2023-04-21 11:31:42 -04:00
Buffer - > ReleaseResource ( ) ;
LiveList . RemoveAt ( Index , 1 , false ) ;
FreeList . Remove ( Buffer ) ;
delete Buffer ;
}
}
}
bool IsRenderAlarmLoggingEnabled ( ) const
{
return GMaxVertexBytesAllocatedPerFrame > 0 & & TotalAllocatedMemory > = ( size_t ) GMaxVertexBytesAllocatedPerFrame ;
}
private :
2023-06-09 12:58:33 -04:00
void ReleaseRHI ( ) override
2023-04-21 11:31:42 -04:00
{
check ( LockList . IsEmpty ( ) ) ;
check ( FreeList . Num ( ) = = LiveList . Num ( ) ) ;
2023-08-25 12:14:13 -04:00
for ( DynamicBufferType * Buffer : LiveList )
2023-04-21 11:31:42 -04:00
{
2023-08-25 12:14:13 -04:00
TotalAllocatedMemory - = Buffer - > BufferSize ;
Buffer - > ReleaseResource ( ) ;
delete Buffer ;
2023-04-21 11:31:42 -04:00
}
LiveList . Empty ( ) ;
FreeList . Empty ( ) ;
2022-12-06 19:47:11 -05:00
}
} ;
2023-08-25 12:14:13 -04:00
static TGlobalResource < TDynamicBufferPool < FDynamicVertexBuffer > , FRenderResource : : EInitPhase : : Pre > GDynamicVertexBufferPool ;
2022-12-06 19:47:11 -05:00
FGlobalDynamicVertexBuffer : : FAllocation FGlobalDynamicVertexBuffer : : Allocate ( uint32 SizeInBytes )
2023-04-21 11:31:42 -04:00
{
2023-09-12 14:10:58 -04:00
checkf ( RHICmdList , TEXT ( " FGlobalDynamicVertexBuffer was not initialized prior to calling Allocate. " ) ) ;
2023-04-21 11:31:42 -04:00
2022-12-06 19:47:11 -05:00
FAllocation Allocation ;
2023-04-21 11:31:42 -04:00
if ( VertexBuffers . IsEmpty ( ) | | VertexBuffers . Last ( ) - > AllocatedByteCount + SizeInBytes > VertexBuffers . Last ( ) - > BufferSize )
2022-12-06 19:47:11 -05:00
{
2023-09-12 14:10:58 -04:00
VertexBuffers . Emplace ( GDynamicVertexBufferPool . Acquire ( * RHICmdList , SizeInBytes , 0 ) ) ;
2022-12-06 19:47:11 -05:00
}
2023-04-21 11:31:42 -04:00
FDynamicVertexBuffer * VertexBuffer = VertexBuffers . Last ( ) ;
2022-12-06 19:47:11 -05:00
checkf ( VertexBuffer - > AllocatedByteCount + SizeInBytes < = VertexBuffer - > BufferSize , TEXT ( " Global vertex buffer allocation failed: BufferSize=%d AllocatedByteCount=%d SizeInBytes=%d " ) , VertexBuffer - > BufferSize , VertexBuffer - > AllocatedByteCount , SizeInBytes ) ;
Allocation . Buffer = VertexBuffer - > MappedBuffer + VertexBuffer - > AllocatedByteCount ;
Allocation . VertexBuffer = VertexBuffer ;
Allocation . VertexOffset = VertexBuffer - > AllocatedByteCount ;
VertexBuffer - > AllocatedByteCount + = SizeInBytes ;
return Allocation ;
}
bool FGlobalDynamicVertexBuffer : : IsRenderAlarmLoggingEnabled ( ) const
{
2023-04-21 11:31:42 -04:00
return GDynamicVertexBufferPool . IsRenderAlarmLoggingEnabled ( ) ;
}
2022-12-06 19:47:11 -05:00
void FGlobalDynamicVertexBuffer : : Commit ( )
{
2023-09-12 14:10:58 -04:00
if ( RHICmdList )
{
GDynamicVertexBufferPool . Forfeit ( * RHICmdList , VertexBuffers ) ;
VertexBuffers . Reset ( ) ;
}
2023-04-21 11:31:42 -04:00
}
2022-12-06 19:47:11 -05:00
2023-08-25 12:14:13 -04:00
static TGlobalResource < TDynamicBufferPool < FDynamicIndexBuffer > , FRenderResource : : EInitPhase : : Pre > GDynamicIndexBufferPool ;
2022-12-06 19:47:11 -05:00
2023-09-12 14:10:58 -04:00
FGlobalDynamicIndexBuffer : : FAllocation FGlobalDynamicIndexBuffer : : Allocate ( uint32 NumIndices , uint32 IndexStride )
2022-12-06 19:47:11 -05:00
{
2023-09-12 14:10:58 -04:00
checkf ( RHICmdList , TEXT ( " FGlobalDynamicIndexBuffer was not initialized prior to calling Allocate. " ) ) ;
2022-12-06 19:47:11 -05:00
FAllocation Allocation ;
if ( IndexStride ! = 2 & & IndexStride ! = 4 )
{
return Allocation ;
}
2023-08-28 13:36:31 -04:00
const uint32 SizeInBytes = NumIndices * IndexStride ;
2023-08-25 12:14:13 -04:00
TArray < FDynamicIndexBuffer * > & IndexBuffers = ( IndexStride = = 2 )
? IndexBuffers16
: IndexBuffers32 ;
2022-12-06 19:47:11 -05:00
2023-08-25 12:14:13 -04:00
if ( IndexBuffers . IsEmpty ( ) | | IndexBuffers . Last ( ) - > AllocatedByteCount + SizeInBytes > IndexBuffers . Last ( ) - > BufferSize )
2022-12-06 19:47:11 -05:00
{
2023-09-12 14:10:58 -04:00
IndexBuffers . Emplace ( GDynamicIndexBufferPool . Acquire ( * RHICmdList , SizeInBytes , IndexStride ) ) ;
2022-12-06 19:47:11 -05:00
}
2023-08-25 12:14:13 -04:00
FDynamicIndexBuffer * IndexBuffer = IndexBuffers . Last ( ) ;
2022-12-06 19:47:11 -05:00
2023-08-25 12:14:13 -04:00
checkf ( IndexBuffer - > AllocatedByteCount + SizeInBytes < = IndexBuffer - > BufferSize , TEXT ( " Global index buffer allocation failed: BufferSize=%d BufferStride=%d AllocatedByteCount=%d SizeInBytes=%d " ) , IndexBuffer - > BufferSize , IndexBuffer - > Stride , IndexBuffer - > AllocatedByteCount , SizeInBytes ) ;
2022-12-06 19:47:11 -05:00
Allocation . Buffer = IndexBuffer - > MappedBuffer + IndexBuffer - > AllocatedByteCount ;
Allocation . IndexBuffer = IndexBuffer ;
Allocation . FirstIndex = IndexBuffer - > AllocatedByteCount / IndexStride ;
IndexBuffer - > AllocatedByteCount + = SizeInBytes ;
return Allocation ;
}
void FGlobalDynamicIndexBuffer : : Commit ( )
{
2023-09-12 14:10:58 -04:00
if ( RHICmdList )
{
GDynamicIndexBufferPool . Forfeit ( * RHICmdList , IndexBuffers16 ) ;
GDynamicIndexBufferPool . Forfeit ( * RHICmdList , IndexBuffers32 ) ;
IndexBuffers16 . Reset ( ) ;
IndexBuffers32 . Reset ( ) ;
}
2022-12-06 19:47:11 -05:00
}
2023-08-25 12:14:13 -04:00
namespace GlobalDynamicBuffer
{
void GarbageCollect ( )
{
GDynamicVertexBufferPool . GarbageCollect ( ) ;
GDynamicIndexBufferPool . GarbageCollect ( ) ;
}
}