Files
UnrealEngineUWP/Engine/Source/Runtime/RenderCore/Public/RenderUtils.h
Sebastien Hillaire ab609c73b5 Add support for distance field shadow on water.
Storing water in gbuffer and runnign extra lighting pass would be too expenssiv. So instead, when in deferred, single layer water always output the main dir light luminance into a separate 111110 texture.
DF shadow is applied on that texture. DFShadow culling step is cached the first time for a given view in order to be able to reapply DFShadow later with a depth buffer containing water. This save 0.4ms on a base console.
DFShadow is naturaly skipped if the directional light does not have that feature enabled.
When DFShadow is executed, it is basically 0.24ms extra on a base console @ 1080p.
The separated light buffer is an extra 8MB allocated when in deferred.
This only works with deferred for now (forward does not run the reflection/composite pass).

Render target slot assignement is a bit fuzzy but this is a mostly static setup so should be fine. And could change with Strata down the line.

r.Water.SingleLayer.ShaderSupportDistanceFieldShadow is to enabled dfshadow on water for the shaders. Defaults to 1 and will only be enalbed when using deferred and when distance fields are enabled.
r.Water.SingleLayer.DistanceFieldShadow is a runtime toggle of the feature (if enabled the shaders still output to the separate light render target, but that is simply discarded).

Follow up: tile upsample, tile traceshadow, make it work with strata.

Tested shooter and console.

#rb Tiago.Costa, Kevin.Ortegren
#preflight https://horde.devtools.epicgames.com/job/62457ad79f404234145cd424

[CL 19613312 by Sebastien Hillaire in ue5-main branch]
2022-04-04 15:03:48 -04:00

800 lines
28 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "RHI.h"
#include "PackedNormal.h"
#include "RenderResource.h"
#include "RHIDefinitions.h"
class FBufferWithRDG;
class FRDGBuffer;
class FRDGPooledBuffer;
class FRDGTexture;
class FRDGBuilder;
struct IPooledRenderTarget;
class RENDERCORE_API FBufferWithRDG : public FRenderResource
{
public:
FBufferWithRDG();
FBufferWithRDG(const FBufferWithRDG& Other);
FBufferWithRDG& operator=(const FBufferWithRDG& Other);
~FBufferWithRDG() override;
void ReleaseRHI() override;
TRefCountPtr<FRDGPooledBuffer> Buffer;
};
extern RENDERCORE_API void RenderUtilsInit();
/**
* Constructs a basis matrix for the axis vectors and returns the sign of the determinant
*
* @param XAxis - x axis (tangent)
* @param YAxis - y axis (binormal)
* @param ZAxis - z axis (normal)
* @return sign of determinant either -1 or +1
*/
FORCEINLINE float GetBasisDeterminantSign( const FVector& XAxis, const FVector& YAxis, const FVector& ZAxis )
{
FMatrix Basis(
FPlane(XAxis,0),
FPlane(YAxis,0),
FPlane(ZAxis,0),
FPlane(0,0,0,1)
);
return (Basis.Determinant() < 0) ? -1.0f : +1.0f;
}
/**
* Constructs a basis matrix for the axis vectors and returns the sign of the determinant
*
* @param XAxis - x axis (tangent)
* @param YAxis - y axis (binormal)
* @param ZAxis - z axis (normal)
* @return sign of determinant either -127 (-1) or +1 (127)
*/
FORCEINLINE int8 GetBasisDeterminantSignByte( const FPackedNormal& XAxis, const FPackedNormal& YAxis, const FPackedNormal& ZAxis )
{
return GetBasisDeterminantSign(XAxis.ToFVector(),YAxis.ToFVector(),ZAxis.ToFVector()) < 0 ? -127 : 127;
}
/**
* Given 2 axes of a basis stored as a packed type, regenerates the y-axis tangent vector and scales by z.W
* @param XAxis - x axis (tangent)
* @param ZAxis - z axis (normal), the sign of the determinant is stored in ZAxis.W
* @return y axis (binormal)
*/
template<typename VectorType>
FORCEINLINE FVector GenerateYAxis(const VectorType& XAxis, const VectorType& ZAxis)
{
static_assert( ARE_TYPES_EQUAL(VectorType, FPackedNormal) ||
ARE_TYPES_EQUAL(VectorType, FPackedRGBA16N), "ERROR: Must be FPackedNormal or FPackedRGBA16N");
FVector x = XAxis.ToFVector();
FVector4 z = ZAxis.ToFVector4();
return (FVector(z) ^ x) * z.W;
}
#define NUM_DEBUG_UTIL_COLORS (32)
static const FColor DebugUtilColor[NUM_DEBUG_UTIL_COLORS] =
{
FColor(20,226,64),
FColor(210,21,0),
FColor(72,100,224),
FColor(14,153,0),
FColor(186,0,186),
FColor(54,0,175),
FColor(25,204,0),
FColor(15,189,147),
FColor(23,165,0),
FColor(26,206,120),
FColor(28,163,176),
FColor(29,0,188),
FColor(130,0,50),
FColor(31,0,163),
FColor(147,0,190),
FColor(1,0,109),
FColor(2,126,203),
FColor(3,0,58),
FColor(4,92,218),
FColor(5,151,0),
FColor(18,221,0),
FColor(6,0,131),
FColor(7,163,176),
FColor(8,0,151),
FColor(102,0,216),
FColor(10,0,171),
FColor(11,112,0),
FColor(12,167,172),
FColor(13,189,0),
FColor(16,155,0),
FColor(178,161,0),
FColor(19,25,126)
};
/** A global white texture. */
extern RENDERCORE_API class FTexture* GWhiteTexture;
extern RENDERCORE_API class FTextureWithSRV* GWhiteTextureWithSRV;
/** A global black texture. */
extern RENDERCORE_API class FTexture* GBlackTexture;
extern RENDERCORE_API class FTextureWithSRV* GBlackTextureWithSRV;
extern RENDERCORE_API class FTexture* GTransparentBlackTexture;
extern RENDERCORE_API class FTextureWithSRV* GTransparentBlackTextureWithSRV;
extern RENDERCORE_API class FVertexBufferWithSRV* GEmptyVertexBufferWithUAV;
extern RENDERCORE_API class FVertexBufferWithSRV* GWhiteVertexBufferWithSRV;
extern RENDERCORE_API class FBufferWithRDG* GWhiteVertexBufferWithRDG;
/** A global black array texture. */
extern RENDERCORE_API class FTexture* GBlackArrayTexture;
/** A global black volume texture. */
extern RENDERCORE_API class FTexture* GBlackVolumeTexture;
/** A global black volume texture, with alpha=1. */
extern RENDERCORE_API class FTexture* GBlackAlpha1VolumeTexture;
/** A global black texture<uint> */
extern RENDERCORE_API class FTexture* GBlackUintTexture;
/** A global black volume texture<uint> */
extern RENDERCORE_API class FTexture* GBlackUintVolumeTexture;
/** A global white cube texture. */
extern RENDERCORE_API class FTexture* GWhiteTextureCube;
/** A global black cube texture. */
extern RENDERCORE_API class FTexture* GBlackTextureCube;
/** A global black cube depth texture. */
extern RENDERCORE_API class FTexture* GBlackTextureDepthCube;
/** A global black cube array texture. */
extern RENDERCORE_API class FTexture* GBlackCubeArrayTexture;
/** A global texture that has a different solid color in each mip-level. */
extern RENDERCORE_API class FTexture* GMipColorTexture;
/** Number of mip-levels in 'GMipColorTexture' */
extern RENDERCORE_API int32 GMipColorTextureMipLevels;
// 4: 8x8 cubemap resolution, shader needs to use the same value as preprocessing
extern RENDERCORE_API const uint32 GDiffuseConvolveMipLevel;
#define NUM_CUBE_VERTICES 36
/** The indices for drawing a cube. */
extern RENDERCORE_API const uint16 GCubeIndices[36];
class FCubeIndexBuffer : public FIndexBuffer
{
public:
/**
* Initialize the RHI for this rendering resource
*/
virtual void InitRHI() override
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo(TEXT("FCubeIndexBuffer"));
IndexBufferRHI = RHICreateIndexBuffer(sizeof(uint16), sizeof(uint16) * NUM_CUBE_VERTICES, BUF_Static, CreateInfo);
void* VoidPtr = RHILockBuffer(IndexBufferRHI, 0, sizeof(uint16) * NUM_CUBE_VERTICES, RLM_WriteOnly);
FMemory::Memcpy(VoidPtr, GCubeIndices, NUM_CUBE_VERTICES * sizeof(uint16));
RHIUnlockBuffer(IndexBufferRHI);
}
};
extern RENDERCORE_API TGlobalResource<FCubeIndexBuffer> GCubeIndexBuffer;
class FTwoTrianglesIndexBuffer : public FIndexBuffer
{
public:
/**
* Initialize the RHI for this rendering resource
*/
virtual void InitRHI() override
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo(TEXT("FTwoTrianglesIndexBuffer"));
IndexBufferRHI = RHICreateIndexBuffer(sizeof(uint16), sizeof(uint16) * 6, BUF_Static, CreateInfo);
void* VoidPtr = RHILockBuffer(IndexBufferRHI, 0, sizeof(uint16) * 6, RLM_WriteOnly);
static const uint16 Indices[] = { 0, 1, 3, 0, 3, 2 };
FMemory::Memcpy(VoidPtr, Indices, 6 * sizeof(uint16));
RHIUnlockBuffer(IndexBufferRHI);
}
};
extern RENDERCORE_API TGlobalResource<FTwoTrianglesIndexBuffer> GTwoTrianglesIndexBuffer;
class FScreenSpaceVertexBuffer : public FVertexBuffer
{
public:
/**
* Initialize the RHI for this rendering resource
*/
virtual void InitRHI() override
{
// create a static vertex buffer
FRHIResourceCreateInfo CreateInfo(TEXT("FScreenSpaceVertexBuffer"));
VertexBufferRHI = RHICreateVertexBuffer(sizeof(FVector2f) * 4, BUF_Static, CreateInfo);
void* VoidPtr = RHILockBuffer(VertexBufferRHI, 0, sizeof(FVector2f) * 4, RLM_WriteOnly);
static const FVector2f Vertices[4] =
{
FVector2f(-1,-1),
FVector2f(-1,+1),
FVector2f(+1,-1),
FVector2f(+1,+1),
};
FMemory::Memcpy(VoidPtr, Vertices, sizeof(FVector2f) * 4);
RHIUnlockBuffer(VertexBufferRHI);
}
};
extern RENDERCORE_API TGlobalResource<FScreenSpaceVertexBuffer> GScreenSpaceVertexBuffer;
class FTileVertexDeclaration : public FRenderResource
{
public:
FVertexDeclarationRHIRef VertexDeclarationRHI;
/** Destructor. */
virtual ~FTileVertexDeclaration() {}
virtual void InitRHI()
{
FVertexDeclarationElementList Elements;
uint16 Stride = sizeof(FVector2f);
Elements.Add(FVertexElement(0, 0, VET_Float2, 0, Stride, false));
VertexDeclarationRHI = RHICreateVertexDeclaration(Elements);
}
virtual void ReleaseRHI()
{
VertexDeclarationRHI.SafeRelease();
}
};
extern RENDERCORE_API TGlobalResource<FTileVertexDeclaration> GTileVertexDeclaration;
/**
* Maps from an X,Y,Z cube vertex coordinate to the corresponding vertex index.
*/
inline uint16 GetCubeVertexIndex(uint32 X,uint32 Y,uint32 Z) { return (uint16)(X * 4 + Y * 2 + Z); }
/**
* A 3x1 of xyz(11:11:10) format.
*/
struct FPackedPosition
{
union
{
struct
{
#if PLATFORM_LITTLE_ENDIAN
int32 X : 11;
int32 Y : 11;
int32 Z : 10;
#else
int32 Z : 10;
int32 Y : 11;
int32 X : 11;
#endif
} Vector;
uint32 Packed;
};
// Constructors.
FPackedPosition() : Packed(0) {}
FPackedPosition(const FVector3f& Other) : Packed(0)
{
Set(Other);
}
FPackedPosition(const FVector3d& Other) : Packed(0)
{
Set(Other);
}
// Conversion operators.
FPackedPosition& operator=( FVector3f Other )
{
Set( Other );
return *this;
}
FPackedPosition& operator=( FVector3d Other )
{
Set( Other );
return *this;
}
operator FVector3f() const;
VectorRegister GetVectorRegister() const;
// Set functions.
void Set(const FVector3f& InVector);
void Set(const FVector3d& InVector);
// Serializer.
friend FArchive& operator<<(FArchive& Ar,FPackedPosition& N);
};
/** Flags that control ConstructTexture2D */
enum EConstructTextureFlags
{
/** Compress RGBA8 to DXT */
CTF_Compress = 0x01,
/** Don't actually compress until the pacakge is saved */
CTF_DeferCompression = 0x02,
/** Enable SRGB on the texture */
CTF_SRGB = 0x04,
/** Generate mipmaps for the texture */
CTF_AllowMips = 0x08,
/** Use DXT1a to get 1 bit alpha but only 4 bits per pixel (note: color of alpha'd out part will be black) */
CTF_ForceOneBitAlpha = 0x10,
/** When rendering a masked material, the depth is in the alpha, and anywhere not rendered will be full depth, which should actually be alpha of 0, and anything else is alpha of 255 */
CTF_RemapAlphaAsMasked = 0x20,
/** Ensure the alpha channel of the texture is opaque white (255). */
CTF_ForceOpaque = 0x40,
/** Default flags (maps to previous defaults to ConstructTexture2D) */
CTF_Default = CTF_Compress | CTF_SRGB,
};
/**
* Calculates the amount of memory used for a single mip-map of a texture 3D.
*
* @param TextureSizeX Number of horizontal texels (for the base mip-level)
* @param TextureSizeY Number of vertical texels (for the base mip-level)
* @param TextureSizeZ Number of slices (for the base mip-level)
* @param Format Texture format
* @param MipIndex The index of the mip-map to compute the size of.
*/
RENDERCORE_API SIZE_T CalcTextureMipMapSize3D( uint32 TextureSizeX, uint32 TextureSizeY, uint32 TextureSizeZ, EPixelFormat Format, uint32 MipIndex);
/**
* Calculates the extent of a mip.
*
* @param TextureSizeX Number of horizontal texels (for the base mip-level)
* @param TextureSizeY Number of vertical texels (for the base mip-level)
* @param TextureSizeZ Number of depth texels (for the base mip-level)
* @param Format Texture format
* @param MipIndex The index of the mip-map to compute the size of.
* @param OutXExtent The extent X of the mip
* @param OutYExtent The extent Y of the mip
* @param OutZExtent The extent Z of the mip
*/
RENDERCORE_API void CalcMipMapExtent3D( uint32 TextureSizeX, uint32 TextureSizeY, uint32 TextureSizeZ, EPixelFormat Format, uint32 MipIndex, uint32& OutXExtent, uint32& OutYExtent, uint32& OutZExtent );
/**
* Calculates the extent of a mip.
*
* @param TextureSizeX Number of horizontal texels (for the base mip-level)
* @param TextureSizeY Number of vertical texels (for the base mip-level)
* @param Format Texture format
* @param MipIndex The index of the mip-map to compute the size of.
*/
RENDERCORE_API FIntPoint CalcMipMapExtent( uint32 TextureSizeX, uint32 TextureSizeY, EPixelFormat Format, uint32 MipIndex );
/**
* Calculates the width of a mip, in blocks.
*
* @param TextureSizeX Number of horizontal texels (for the base mip-level)
* @param Format Texture format
* @param MipIndex The index of the mip-map to compute the size of.
*/
RENDERCORE_API SIZE_T CalcTextureMipWidthInBlocks(uint32 TextureSizeX, EPixelFormat Format, uint32 MipIndex);
/**
* Calculates the height of a mip, in blocks.
*
* @param TextureSizeY Number of vertical texels (for the base mip-level)
* @param Format Texture format
* @param MipIndex The index of the mip-map to compute the size of.
*/
RENDERCORE_API SIZE_T CalcTextureMipHeightInBlocks(uint32 TextureSizeY, EPixelFormat Format, uint32 MipIndex);
/**
* Calculates the amount of memory used for a single mip-map of a texture.
*
* @param TextureSizeX Number of horizontal texels (for the base mip-level)
* @param TextureSizeY Number of vertical texels (for the base mip-level)
* @param Format Texture format
* @param MipIndex The index of the mip-map to compute the size of.
*/
RENDERCORE_API SIZE_T CalcTextureMipMapSize( uint32 TextureSizeX, uint32 TextureSizeY, EPixelFormat Format, uint32 MipIndex );
/**
* Calculates the amount of memory used for a texture.
*
* @param SizeX Number of horizontal texels (for the base mip-level)
* @param SizeY Number of vertical texels (for the base mip-level)
* @param Format Texture format
* @param MipCount Number of mip-levels (including the base mip-level)
*/
RENDERCORE_API SIZE_T CalcTextureSize( uint32 SizeX, uint32 SizeY, EPixelFormat Format, uint32 MipCount );
/**
* Calculates the amount of memory used for a texture.
*
* @param SizeX Number of horizontal texels (for the base mip-level)
* @param SizeY Number of vertical texels (for the base mip-level)
* @param SizeY Number of depth texels (for the base mip-level)
* @param Format Texture format
* @param MipCount Number of mip-levels (including the base mip-level)
*/
RENDERCORE_API SIZE_T CalcTextureSize3D( uint32 SizeX, uint32 SizeY, uint32 SizeZ, EPixelFormat Format, uint32 MipCount );
/**
* Copies the data for a 2D texture between two buffers with potentially different strides.
* @param Source - The source buffer
* @param Dest - The destination buffer.
* @param SizeY - The height of the texture data to copy in pixels.
* @param Format - The format of the texture being copied.
* @param SourceStride - The stride of the source buffer.
* @param DestStride - The stride of the destination buffer.
*/
RENDERCORE_API void CopyTextureData2D(const void* Source,void* Dest,uint32 SizeY,EPixelFormat Format,uint32 SourceStride,uint32 DestStride);
/**
* enum to string
*
* @return e.g. "PF_B8G8R8A8"
*/
RENDERCORE_API const TCHAR* GetPixelFormatString(EPixelFormat InPixelFormat);
/**
* string to enum (not case sensitive)
*
* @param InPixelFormatStr e.g. "PF_B8G8R8A8", must not not be 0
*/
RENDERCORE_API EPixelFormat GetPixelFormatFromString(const TCHAR* InPixelFormatStr);
/**
* Returns the valid channels for this pixel format
*
* @return e.g. EPixelFormatChannelFlags::G for PF_G8
*/
RENDERCORE_API EPixelFormatChannelFlags GetPixelFormatValidChannels(EPixelFormat InPixelFormat);
/**
* Convert from ECubeFace to text string
* @param Face - ECubeFace type to convert
* @return text string for cube face enum value
*/
RENDERCORE_API const TCHAR* GetCubeFaceName(ECubeFace Face);
/**
* Convert from text string to ECubeFace
* @param Name e.g. RandomNamePosX
* @return CubeFace_MAX if not recognized
*/
RENDERCORE_API ECubeFace GetCubeFaceFromName(const FString& Name);
RENDERCORE_API FVertexDeclarationRHIRef& GetVertexDeclarationFVector4();
RENDERCORE_API FVertexDeclarationRHIRef& GetVertexDeclarationFVector3();
RENDERCORE_API FVertexDeclarationRHIRef& GetVertexDeclarationFVector2();
RENDERCORE_API bool PlatformSupportsSimpleForwardShading(const FStaticShaderPlatform Platform);
RENDERCORE_API bool IsSimpleForwardShadingEnabled(const FStaticShaderPlatform Platform);
RENDERCORE_API bool MobileSupportsGPUScene();
RENDERCORE_API bool IsMobileDeferredShadingEnabled(const FStaticShaderPlatform Platform);
RENDERCORE_API bool MobileRequiresSceneDepthAux(const FStaticShaderPlatform Platform);
RENDERCORE_API bool SupportsTextureCubeArray(ERHIFeatureLevel::Type FeatureLevel);
RENDERCORE_API bool MaskedInEarlyPass(const FStaticShaderPlatform Platform);
RENDERCORE_API bool AllowPixelDepthOffset(const FStaticShaderPlatform Platform);
RENDERCORE_API bool AllowPerPixelShadingModels(const FStaticShaderPlatform Platform);
RENDERCORE_API bool UseMobileAmbientOcclusion(const FStaticShaderPlatform Platform);
RENDERCORE_API bool IsMobileDistanceFieldEnabled(const FStaticShaderPlatform Platform);
RENDERCORE_API bool MobileBasePassAlwaysUsesCSM(const FStaticShaderPlatform Platform);
RENDERCORE_API bool SupportsGen4TAA(const FStaticShaderPlatform Platform);
RENDERCORE_API bool SupportsTSR(const FStaticShaderPlatform Platform);
RENDERCORE_API bool PlatformSupportsVelocityRendering(const FStaticShaderPlatform Platform);
RENDERCORE_API bool IsUsingDBuffers(const FStaticShaderPlatform Platform);
template<typename Type>
struct RENDERCORE_API FShaderPlatformCachedIniValue
{
FShaderPlatformCachedIniValue(const TCHAR* InCVarName)
: CVarName(InCVarName)
, CVar(nullptr)
{
}
FShaderPlatformCachedIniValue(IConsoleVariable* InCVar)
: CVar(InCVar)
{
}
Type Get(EShaderPlatform ShaderPlatform)
{
Type Value{};
FName IniPlatformName = ShaderPlatformToPlatformName(ShaderPlatform);
// find the cvar if needed
if (CVar == nullptr)
{
CVar = IConsoleManager::Get().FindConsoleVariable(*CVarName);
}
// if we are looking up our own platform, just use the current value
if (IniPlatformName == FPlatformProperties::IniPlatformName())
{
checkf(CVar != nullptr, TEXT("Failed to find CVar %s when getting current value for FShaderPlatformCachedIniValue"));
CVar->GetValue(Value);
return Value;
}
#if ALLOW_OTHER_PLATFORM_CONFIG
// create a dummy cvar if needed
if (CVar == nullptr)
{
// this could be a cvar that only exists on the target platform so create a dummy one
CVar = IConsoleManager::Get().RegisterConsoleVariable(*CVarName, Type(), TEXT(""), ECVF_ReadOnly);
}
// now get the value from the platform that makes sense for this shader platform
TSharedPtr<IConsoleVariable> OtherPlatformVar = CVar->GetPlatformValueVariable(IniPlatformName);
ensureMsgf(OtherPlatformVar.IsValid(), TEXT("Failed to get another platform's version of a cvar (possible name: '%s'). It is probably an esoteric subclass that needs to implement GetPlatformValueVariable."), *CVarName);
if (OtherPlatformVar.IsValid())
{
OtherPlatformVar->GetValue(Value);
}
else
{
// get this platform's value, even tho it could be wrong
CVar->GetValue(Value);
}
#else
checkf(IniPlatformName == FName(FPlatformProperties::IniPlatformName()), TEXT("FShaderPlatformCachedIniValue can only look up the current platform when ALLOW_OTHER_PLATFORM_CONFIG is false"));
#endif
return Value;
}
private:
FString CVarName;
IConsoleVariable* CVar;
};
/** Returns if ForwardShading is enabled. Only valid for the current platform (otherwise call ITargetPlatform::UsesForwardShading()). */
inline bool IsForwardShadingEnabled(const FStaticShaderPlatform Platform)
{
extern RENDERCORE_API uint64 GForwardShadingPlatformMask;
return !!(GForwardShadingPlatformMask & (1ull << Platform))
// Culling uses compute shader
&& GetMaxSupportedFeatureLevel(Platform) >= ERHIFeatureLevel::SM5;
}
/** Returns if ForwardShading or SimpleForwardShading is enabled. Only valid for the current platform. */
inline bool IsAnyForwardShadingEnabled(const FStaticShaderPlatform Platform)
{
return IsForwardShadingEnabled(Platform) || IsSimpleForwardShadingEnabled(Platform);
}
/** Returns if the GBuffer is used. Only valid for the current platform. */
inline bool IsUsingGBuffers(const FStaticShaderPlatform Platform)
{
if (IsMobilePlatform(Platform))
{
return IsMobileDeferredShadingEnabled(Platform);
}
else
{
return !IsAnyForwardShadingEnabled(Platform);
}
}
/** Returns whether the base pass should output to the velocity buffer is enabled for a given shader platform */
inline bool IsUsingBasePassVelocity(const FStaticShaderPlatform Platform)
{
extern RENDERCORE_API uint64 GBasePassVelocityPlatformMask;
return !!(GBasePassVelocityPlatformMask & (1ull << Platform));
}
/** Returns whether the base pass should use selective outputs for a given shader platform */
inline bool IsUsingSelectiveBasePassOutputs(const FStaticShaderPlatform Platform)
{
extern RENDERCORE_API uint64 GSelectiveBasePassOutputsPlatformMask;
return !!(GSelectiveBasePassOutputsPlatformMask & (1ull << Platform));
}
/** Returns whether distance fields are enabled for a given shader platform */
inline bool IsUsingDistanceFields(const FStaticShaderPlatform Platform)
{
extern RENDERCORE_API uint64 GDistanceFieldsPlatformMask;
return !!(GDistanceFieldsPlatformMask & (1ull << Platform));
}
/** Returns if water should render distance field shadow a second time for the water surface. This is for a platofrm so can be used at cook time. */
inline bool IsWaterDistanceFieldShadowEnabled(const FStaticShaderPlatform Platform)
{
// Only deferred support such a feature. It is not possible to do that for water without a water depth pre-pass.
static const auto CVarWaterSingleLayerShaderSupportDistanceFieldShadow = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Water.SingleLayer.ShadersSupportDistanceFieldShadow"));
const bool bWaterSingleLayerShaderSupportDistanceFieldShadow = CVarWaterSingleLayerShaderSupportDistanceFieldShadow && (CVarWaterSingleLayerShaderSupportDistanceFieldShadow->GetInt() > 0);
return !IsForwardShadingEnabled(Platform) && IsUsingDistanceFields(Platform) && bWaterSingleLayerShaderSupportDistanceFieldShadow;
}
inline bool UseGPUScene(const FStaticShaderPlatform Platform, const FStaticFeatureLevel FeatureLevel)
{
if (FeatureLevel == ERHIFeatureLevel::ES3_1)
{
return MobileSupportsGPUScene();
}
// GPU Scene management uses compute shaders
return FeatureLevel >= ERHIFeatureLevel::SM5
//@todo - support GPU Scene management compute shaders on these platforms to get dynamic instancing speedups on the Rendering Thread and RHI Thread
&& !IsOpenGLPlatform(Platform)
&& !IsVulkanMobileSM5Platform(Platform)
&& !IsMetalMobileSM5Platform(Platform)
// we only check DDSPI for platforms that have been read in - IsValid() can go away once ALL platforms are converted over to this system
&& (!FDataDrivenShaderPlatformInfo::IsValid(Platform) || FDataDrivenShaderPlatformInfo::GetSupportsGPUScene(Platform));
}
inline bool UseGPUScene(const FStaticShaderPlatform Platform)
{
return UseGPUScene(Platform, GetMaxSupportedFeatureLevel(Platform));
}
inline bool ForceSimpleSkyDiffuse(const FStaticShaderPlatform Platform)
{
extern RENDERCORE_API uint64 GSimpleSkyDiffusePlatformMask;
return !!(GSimpleSkyDiffusePlatformMask & (1ull << Platform));
}
inline bool VelocityEncodeDepth(const FStaticShaderPlatform Platform)
{
extern RENDERCORE_API uint64 GVelocityEncodeDepthPlatformMask;
return !!(GVelocityEncodeDepthPlatformMask & (1ull << Platform));
}
/** Unit cube vertex buffer (VertexDeclarationFVector4) */
RENDERCORE_API FBufferRHIRef& GetUnitCubeVertexBuffer();
/** Unit cube index buffer */
RENDERCORE_API FBufferRHIRef& GetUnitCubeIndexBuffer();
#if RHI_RAYTRACING
/** Unit cube AABB vertex buffer (useful to create procedural raytracing geometry) */
RENDERCORE_API FBufferRHIRef& GetUnitCubeAABBVertexBuffer();
#endif
/**
* Takes the requested buffer size and quantizes it to an appropriate size for the rest of the
* rendering pipeline. Currently ensures that sizes are multiples of 4 so that they can safely
* be halved in size several times.
*/
RENDERCORE_API void QuantizeSceneBufferSize(const FIntPoint& InBufferSize, FIntPoint& OutBufferSize);
/**
* Checks if virtual texturing enabled and supported
*/
RENDERCORE_API bool UseVirtualTexturing(const FStaticFeatureLevel InFeatureLevel, const class ITargetPlatform* TargetPlatform = nullptr);
RENDERCORE_API bool DoesPlatformSupportNanite(EShaderPlatform Platform, bool bCheckForProjectSetting = true);
inline bool NaniteAtomicsSupported()
{
// Are 64bit image atomics supported by the GPU/Driver/OS/API?
bool bAtomicsSupported = GRHISupportsAtomicUInt64;
#if PLATFORM_WINDOWS
const ERHIInterfaceType RHIInterface = RHIGetInterfaceType();
const bool bIsDx11 = RHIInterface == ERHIInterfaceType::D3D11;
const bool bIsDx12 = RHIInterface == ERHIInterfaceType::D3D12;
static const auto NaniteRequireDX12CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Nanite.RequireDX12"));
static const uint32 NaniteRequireDX12 = (NaniteRequireDX12CVar != nullptr) ? NaniteRequireDX12CVar->GetInt() : 1;
if (bAtomicsSupported && NaniteRequireDX12 != 0)
{
// Only allow Vulkan or D3D12
bAtomicsSupported = !bIsDx11;
// Disable DX12 vendor extensions unless DX12 SM6.6 is supported
if (NaniteRequireDX12 == 1 && bIsDx12 && !GRHISupportsDX12AtomicUInt64)
{
// Vendor extensions currently support atomic64, but SM 6.6 and the DX12 Agility SDK are reporting that atomics are not supported.
// Likely due to a pre-1909 Windows 10 version, or outdated drivers without SM 6.6 support.
// See: https://devblogs.microsoft.com/directx/gettingstarted-dx12agility/
bAtomicsSupported = false;
}
}
#endif
return bAtomicsSupported;
}
inline bool DoesRuntimeSupportNanite(EShaderPlatform ShaderPlatform, bool bCheckForAtomicSupport, bool bCheckForProjectSetting)
{
// Does the platform support Nanite?
const bool bSupportedPlatform = DoesPlatformSupportNanite(ShaderPlatform, bCheckForProjectSetting);
// Nanite is not supported with forward shading at this time.
const bool bForwardShadingEnabled = IsForwardShadingEnabled(ShaderPlatform);
return bSupportedPlatform && (!bCheckForAtomicSupport || NaniteAtomicsSupported()) && !bForwardShadingEnabled;
}
/**
* Returns true if Nanite rendering should be used for the given shader platform.
*/
inline bool UseNanite(EShaderPlatform ShaderPlatform, bool bCheckForAtomicSupport = true, bool bCheckForProjectSetting = true)
{
static const auto EnableNaniteCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Nanite"));
const bool bNaniteEnabled = (EnableNaniteCVar != nullptr) ? (EnableNaniteCVar->GetInt() != 0) : true;
return bNaniteEnabled && DoesRuntimeSupportNanite(ShaderPlatform, bCheckForAtomicSupport, bCheckForProjectSetting);
}
/**
* Returns true if Virtual Shadow Maps should be used for the given shader platform.
* Note: Virtual Shadow Maps require Nanite support.
*/
inline bool UseVirtualShadowMaps(EShaderPlatform ShaderPlatform, const FStaticFeatureLevel FeatureLevel)
{
static const auto EnableVirtualSMCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Shadow.Virtual.Enable"));
const bool bVirtualShadowMapsEnabled = EnableVirtualSMCVar ? (EnableVirtualSMCVar->GetInt() != 0) : false;
return bVirtualShadowMapsEnabled && DoesRuntimeSupportNanite(ShaderPlatform, true /* check for atomics */, true /* check project setting */);
}
/**
* Returns true if non-Nanite virtual shadow maps are enabled by CVar r.Shadow.Virtual.NonNaniteVSM
* and UseVirtualShadowMaps is true for the given platform and feature level.
*/
inline bool UseNonNaniteVirtualShadowMaps(EShaderPlatform ShaderPlatform, const FStaticFeatureLevel FeatureLevel)
{
static const auto EnableCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Shadow.Virtual.NonNaniteVSM"));
return EnableCVar->GetInt() != 0 && UseVirtualShadowMaps(ShaderPlatform, FeatureLevel);
}
/**
* Checks if virtual texturing lightmap enabled and supported
*/
RENDERCORE_API bool UseVirtualTextureLightmap(const FStaticFeatureLevel InFeatureLevel, const class ITargetPlatform* TargetPlatform = nullptr);
/**
* Checks if platform uses a baked landscape mesh (mobile)
*/
RENDERCORE_API bool UseMobileLandscapeMesh(EShaderPlatform ShaderPlatform);
/**
* Checks if the non-pipeline shaders will not be compild and ones from FShaderPipeline used instead.
*/
RENDERCORE_API bool ExcludeNonPipelinedShaderTypes(EShaderPlatform ShaderPlatform);
/**
* Checks if skin cache shaders are enabled for the platform (via r.SkinCache.CompileShaders)
*/
RENDERCORE_API bool AreSkinCacheShadersEnabled(EShaderPlatform Platform);
/*
* Detect (at runtime) if the runtime supports rendering one-pass point light shadows (i.e., cube maps)
*/
RENDERCORE_API bool DoesRuntimeSupportOnePassPointLightShadows(EShaderPlatform Platform);