159 lines
7.0 KiB
C++
159 lines
7.0 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "DBufferTextures.h"
|
|
|
|
#include "DataDrivenShaderPlatformInfo.h"
|
|
#include "RendererUtils.h"
|
|
#include "RenderGraphUtils.h"
|
|
#include "SceneUtils.h"
|
|
#include "ScenePrivate.h"
|
|
#include "SystemTextures.h"
|
|
|
|
bool FDBufferTextures::IsValid() const
|
|
{
|
|
check((!DBufferA || (DBufferB && DBufferC)) || (!DBufferATexArray || (DBufferBTexArray && DBufferCTexArray)));
|
|
return HasBeenProduced(DBufferA) || HasBeenProduced(DBufferATexArray);
|
|
}
|
|
|
|
EDecalDBufferMaskTechnique GetDBufferMaskTechnique(EShaderPlatform ShaderPlatform)
|
|
{
|
|
const bool bWriteMaskDBufferMask = RHISupportsRenderTargetWriteMask(ShaderPlatform);
|
|
const bool bPerPixelDBufferMask = FDataDrivenShaderPlatformInfo::GetSupportsPerPixelDBufferMask(ShaderPlatform);
|
|
checkf(!bWriteMaskDBufferMask || !bPerPixelDBufferMask, TEXT("The WriteMask and PerPixel DBufferMask approaches cannot be enabled at the same time. They are mutually exclusive."));
|
|
|
|
if (bWriteMaskDBufferMask)
|
|
{
|
|
return EDecalDBufferMaskTechnique::WriteMask;
|
|
}
|
|
else if (bPerPixelDBufferMask)
|
|
{
|
|
return EDecalDBufferMaskTechnique::PerPixel;
|
|
}
|
|
return EDecalDBufferMaskTechnique::Disabled;
|
|
}
|
|
|
|
FDBufferTexturesDesc GetDBufferTexturesDesc(FIntPoint Extent, EShaderPlatform ShaderPlatform)
|
|
{
|
|
FDBufferTexturesDesc DBufferTexturesDesc;
|
|
|
|
if (IsUsingDBuffers(ShaderPlatform))
|
|
{
|
|
const EDecalDBufferMaskTechnique DBufferMaskTechnique = GetDBufferMaskTechnique(ShaderPlatform);
|
|
const ETextureCreateFlags WriteMaskFlags = DBufferMaskTechnique == EDecalDBufferMaskTechnique::WriteMask ? TexCreate_NoFastClearFinalize | TexCreate_DisableDCC : TexCreate_None;
|
|
const ETextureCreateFlags BaseFlags = WriteMaskFlags | TexCreate_ShaderResource | TexCreate_RenderTargetable;
|
|
|
|
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(Extent, PF_B8G8R8A8, FClearValueBinding::None, BaseFlags);
|
|
FRDGTextureDesc ArrayDesc = FRDGTextureDesc::Create2DArray(Extent, PF_B8G8R8A8, FClearValueBinding::None, BaseFlags, 2);
|
|
|
|
Desc.Flags = ArrayDesc.Flags = BaseFlags | GFastVRamConfig.DBufferA;
|
|
Desc.ClearValue = ArrayDesc.ClearValue = FClearValueBinding::Black;
|
|
DBufferTexturesDesc.DBufferADesc = Desc;
|
|
DBufferTexturesDesc.DBufferATexArrayDesc = ArrayDesc;
|
|
DBufferTexturesDesc.DBufferADesc.Flags |= TexCreate_SRGB;
|
|
DBufferTexturesDesc.DBufferATexArrayDesc.Flags |= TexCreate_SRGB;
|
|
|
|
Desc.Flags = ArrayDesc.Flags = BaseFlags | GFastVRamConfig.DBufferB;
|
|
Desc.ClearValue = ArrayDesc.ClearValue = FClearValueBinding(FLinearColor(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1));
|
|
DBufferTexturesDesc.DBufferBDesc = Desc;
|
|
DBufferTexturesDesc.DBufferBTexArrayDesc = ArrayDesc;
|
|
|
|
Desc.Flags = ArrayDesc.Flags = BaseFlags | GFastVRamConfig.DBufferC;
|
|
Desc.ClearValue = ArrayDesc.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 1));
|
|
DBufferTexturesDesc.DBufferCDesc = Desc;
|
|
DBufferTexturesDesc.DBufferCTexArrayDesc = ArrayDesc;
|
|
|
|
if (DBufferMaskTechnique == EDecalDBufferMaskTechnique::PerPixel)
|
|
{
|
|
// Note: 32bpp format is used here to utilize color compression hardware (same as other DBuffer targets).
|
|
// This significantly reduces bandwidth for clearing, writing and reading on some GPUs.
|
|
// While a smaller format, such as R8_UINT, will use less video memory, it will result in slower clears and higher bandwidth requirements.
|
|
check(Desc.Format == PF_B8G8R8A8);
|
|
// On mobile platforms using PF_B8G8R8A8 has no benefits over R8.
|
|
if (IsMobilePlatform(ShaderPlatform))
|
|
{
|
|
Desc.Format = PF_R8;
|
|
}
|
|
Desc.Flags = TexCreate_ShaderResource | TexCreate_RenderTargetable;
|
|
Desc.ClearValue = FClearValueBinding::Transparent;
|
|
DBufferTexturesDesc.DBufferMaskDesc = Desc;
|
|
}
|
|
}
|
|
|
|
return DBufferTexturesDesc;
|
|
}
|
|
|
|
FDBufferTextures CreateDBufferTextures(FRDGBuilder& GraphBuilder, FIntPoint Extent, EShaderPlatform ShaderPlatform, const bool bIsMobileMultiView)
|
|
{
|
|
FDBufferTextures DBufferTextures;
|
|
|
|
if (IsUsingDBuffers(ShaderPlatform))
|
|
{
|
|
FDBufferTexturesDesc TexturesDesc = GetDBufferTexturesDesc(Extent, ShaderPlatform);
|
|
|
|
const EDecalDBufferMaskTechnique DBufferMaskTechnique = GetDBufferMaskTechnique(ShaderPlatform);
|
|
const ERDGTextureFlags TextureFlags = DBufferMaskTechnique != EDecalDBufferMaskTechnique::Disabled
|
|
? ERDGTextureFlags::MaintainCompression
|
|
: ERDGTextureFlags::None;
|
|
if (!bIsMobileMultiView)
|
|
{
|
|
DBufferTextures.DBufferA = GraphBuilder.CreateTexture(TexturesDesc.DBufferADesc, TEXT("DBufferA"), TextureFlags);
|
|
DBufferTextures.DBufferB = GraphBuilder.CreateTexture(TexturesDesc.DBufferBDesc, TEXT("DBufferB"), TextureFlags);
|
|
DBufferTextures.DBufferC = GraphBuilder.CreateTexture(TexturesDesc.DBufferCDesc, TEXT("DBufferC"), TextureFlags);
|
|
}
|
|
else
|
|
{
|
|
DBufferTextures.DBufferATexArray = GraphBuilder.CreateTexture(TexturesDesc.DBufferATexArrayDesc, TEXT("DBufferATexArray"), TextureFlags);
|
|
DBufferTextures.DBufferBTexArray = GraphBuilder.CreateTexture(TexturesDesc.DBufferBTexArrayDesc, TEXT("DBufferBTexArray"), TextureFlags);
|
|
DBufferTextures.DBufferCTexArray = GraphBuilder.CreateTexture(TexturesDesc.DBufferCTexArrayDesc, TEXT("DBufferCTexArray"), TextureFlags);
|
|
}
|
|
|
|
if (DBufferMaskTechnique == EDecalDBufferMaskTechnique::PerPixel)
|
|
{
|
|
DBufferTextures.DBufferMask = GraphBuilder.CreateTexture(TexturesDesc.DBufferMaskDesc, TEXT("DBufferMask"));
|
|
}
|
|
}
|
|
|
|
return DBufferTextures;
|
|
}
|
|
|
|
FDBufferParameters GetDBufferParameters(FRDGBuilder& GraphBuilder, const FDBufferTextures& DBufferTextures, EShaderPlatform ShaderPlatform, const bool bIsMobileMultiView)
|
|
{
|
|
const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);
|
|
|
|
FDBufferParameters Parameters;
|
|
Parameters.DBufferATextureSampler = TStaticSamplerState<>::GetRHI();
|
|
Parameters.DBufferBTextureSampler = TStaticSamplerState<>::GetRHI();
|
|
Parameters.DBufferCTextureSampler = TStaticSamplerState<>::GetRHI();
|
|
Parameters.DBufferATexture = SystemTextures.BlackAlphaOne;
|
|
Parameters.DBufferBTexture = SystemTextures.DefaultNormal8Bit;
|
|
Parameters.DBufferCTexture = SystemTextures.BlackAlphaOne;
|
|
Parameters.DBufferATextureArray = GSystemTextures.GetDefaultTexture(GraphBuilder, ETextureDimension::Texture2DArray, EPixelFormat::PF_B8G8R8A8, FClearValueBinding::Black);
|
|
Parameters.DBufferBTextureArray = GSystemTextures.GetDefaultTexture(GraphBuilder, ETextureDimension::Texture2DArray, EPixelFormat::PF_B8G8R8A8, FClearValueBinding::Black);
|
|
Parameters.DBufferCTextureArray = GSystemTextures.GetDefaultTexture(GraphBuilder, ETextureDimension::Texture2DArray, EPixelFormat::PF_B8G8R8A8, FClearValueBinding::Black);
|
|
|
|
Parameters.DBufferRenderMask = SystemTextures.White;
|
|
|
|
if (DBufferTextures.IsValid())
|
|
{
|
|
if (bIsMobileMultiView)
|
|
{
|
|
Parameters.DBufferATextureArray = DBufferTextures.DBufferATexArray;
|
|
Parameters.DBufferBTextureArray = DBufferTextures.DBufferBTexArray;
|
|
Parameters.DBufferCTextureArray = DBufferTextures.DBufferCTexArray;
|
|
}
|
|
else
|
|
{
|
|
Parameters.DBufferATexture = DBufferTextures.DBufferA;
|
|
Parameters.DBufferBTexture = DBufferTextures.DBufferB;
|
|
Parameters.DBufferCTexture = DBufferTextures.DBufferC;
|
|
}
|
|
|
|
if (DBufferTextures.DBufferMask)
|
|
{
|
|
Parameters.DBufferRenderMask = DBufferTextures.DBufferMask;
|
|
}
|
|
}
|
|
|
|
return Parameters;
|
|
}
|