Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/Strata/Strata.cpp

1148 lines
56 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Strata.h"
#include "HAL/IConsoleManager.h"
#include "PixelShaderUtils.h"
#include "SceneView.h"
#include "ScenePrivate.h"
#include "SceneRendering.h"
#include "RendererInterface.h"
#include "UniformBuffer.h"
#include "SceneTextureParameters.h"
#include "ShaderCompiler.h"
#include "Lumen/Lumen.h"
//PRAGMA_DISABLE_OPTIMIZATION
// The project setting for Strata
static TAutoConsoleVariable<int32> CVarStrata(
TEXT("r.Strata"),
0,
TEXT("Enable Strata materials (Beta)."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarStrataBackCompatibility(
TEXT("r.StrataBackCompatibility"),
0,
TEXT("Disables Strata multiple scattering and replaces Chan diffuse by Lambert."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarStrataBytePerPixel(
TEXT("r.Strata.BytesPerPixel"),
80,
TEXT("Strata allocated byte per pixel to store materials data. Higher value means more complex material can be represented."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarStrataRoughDiffuse(
TEXT("r.Strata.RoughDiffuse"),
1,
TEXT("Enable Strata rough diffuse model (works only if r.Material.RoughDiffuse is enabled in the project settings). Togglable at runtime"),
ECVF_RenderThreadSafe);
// Transition render settings that will disapear when strata gets enabled
static TAutoConsoleVariable<int32> CVarMaterialRoughDiffuse(
TEXT("r.Material.RoughDiffuse"),
0,
TEXT("Enable rough diffuse material."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
// STRATA_TODO we keep this for now and can remove it once battletested.
static TAutoConsoleVariable<int32> CVarClearDuringCategorization(
TEXT("r.Strata.ClearDuringCategorization"),
1,
TEXT("TEST."),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<float> CVarStrataTileOverflow(
TEXT("r.Strata.TileOverflow"),
1.f,
TEXT("Scale the number of Strata tile for overflowing tiles containing multi-BSDFs pixels. (0: 0%, 1: 100%. Default 1.0f)."),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarStrataDebugPeelLayersAboveDepth(
TEXT("r.Strata.Debug.PeelLayersAboveDepth"),
0,
TEXT("Strata debug control to progressively peel off materials layer by layer."),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarStrataAsyncClassification(
TEXT("r.Strata.AsyncClassification"),
1,
TEXT("Run Strata material classification in async (with shadow)."),
ECVF_RenderThreadSafe);
IMPLEMENT_GLOBAL_SHADER_PARAMETER_STRUCT(FStrataGlobalUniformParameters, "Strata");
void FStrataViewData::Reset()
{
*this = FStrataViewData();
for (uint32 i = 0; i < EStrataTileType::ECount; ++i)
{
ClassificationTileListBuffer[i] = nullptr;
ClassificationTileListBufferUAV[i] = nullptr;
ClassificationTileListBufferSRV[i] = nullptr;
}
}
const TCHAR* ToString(EStrataTileType Type)
{
switch (Type)
{
case EStrataTileType::ESimple: return TEXT("Simple");
case EStrataTileType::ESingle: return TEXT("Single");
case EStrataTileType::EComplex: return TEXT("Complex");
case EStrataTileType::EOpaqueRoughRefraction: return TEXT("OpaqueRoughRefraction");
case EStrataTileType::ESSSWithoutOpaqueRoughRefraction: return TEXT("SSSWithoutOpaqueRoughRefraction");
}
return TEXT("Unknown");
}
FORCEINLINE bool ClearDuringCategorization()
{
return CVarClearDuringCategorization.GetValueOnRenderThread() > 0;
}
namespace Strata
{
// Forward declaration
static void AddStrataClearMaterialBufferPass(
FRDGBuilder& GraphBuilder,
FRDGTextureUAVRef MaterialTextureArrayUAV,
FRDGTextureUAVRef SSSTextureUAV,
uint32 MaxBytesPerPixel,
FIntPoint TiledViewBufferResolution);
bool IsStrataEnabled()
{
return CVarStrata.GetValueOnAnyThread() > 0;
}
enum EStrataTileSpace
{
StrataTileSpace_Primary = 1u,
StrataTileSpace_Overflow = 2u
};
static FIntPoint GetStrataTextureTileResolution(const FIntPoint& InResolution, uint32 InSpace)
{
FIntPoint Out = InResolution;
Out.X = FMath::DivideAndRoundUp(Out.X, STRATA_TILE_SIZE);
Out.Y = 0;
if (InSpace & EStrataTileSpace::StrataTileSpace_Primary)
{
Out.Y += FMath::DivideAndRoundUp(InResolution.Y, STRATA_TILE_SIZE);
}
if (InSpace & EStrataTileSpace::StrataTileSpace_Overflow)
{
const float OverflowRatio = FMath::Clamp(CVarStrataTileOverflow.GetValueOnRenderThread(), 0.f, 4.0f);
Out.Y += FMath::DivideAndRoundUp(FMath::CeilToInt(InResolution.Y * OverflowRatio), STRATA_TILE_SIZE);
}
return Out;
}
FIntPoint GetStrataTextureResolution(const FIntPoint& InResolution)
{
if (Strata::IsStrataEnabled())
{
return GetStrataTextureTileResolution(InResolution, EStrataTileSpace::StrataTileSpace_Primary | EStrataTileSpace::StrataTileSpace_Overflow) * STRATA_TILE_SIZE;
}
{
return InResolution;
}
}
static void BindStrataGlobalUniformParameters(FRDGBuilder& GraphBuilder, FStrataViewData* StrataViewData, FStrataGlobalUniformParameters& OutStrataUniformParameters);
static void InitialiseStrataViewData(FRDGBuilder& GraphBuilder, FViewInfo& View, const FSceneTexturesConfig& SceneTexturesConfig, bool bNeedBSDFOffets, FStrataSceneData& SceneData)
{
// Sanity check: the scene data should already exist
check(SceneData.MaterialTextureArray != nullptr);
FStrataViewData& Out = View.StrataViewData;
Out.Reset();
Out.SceneData = &SceneData;
const FIntPoint ViewResolution(View.ViewRect.Width(), View.ViewRect.Height());
if (IsStrataEnabled())
{
const FIntPoint TileResolution(FMath::DivideAndRoundUp(ViewResolution.X, STRATA_TILE_SIZE), FMath::DivideAndRoundUp(ViewResolution.Y, STRATA_TILE_SIZE));
const TCHAR* StrataTileListBufferNames[EStrataTileType::ECount] =
{
TEXT("Strata.StrataTileListBuffer(Simple)"),
TEXT("Strata.StrataTileListBuffer(Single)"),
TEXT("Strata.StrataTileListBuffer(Complex)"),
TEXT("Strata.StrataTileListBuffer(OpaqueRoughRefraction)"),
TEXT("Strata.StrataTileListBuffer(SSSWithoutOpaqueRoughRefraction)")
};
// Tile classification buffers
{
// Indirect draw
Out.ClassificationTileDrawIndirectBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDrawIndirectParameters>(EStrataTileType::ECount), TEXT("Strata.StrataTileDrawIndirectBuffer"));
Out.ClassificationTileDrawIndirectBufferUAV = GraphBuilder.CreateUAV(Out.ClassificationTileDrawIndirectBuffer, PF_R32_UINT);
AddClearUAVPass(GraphBuilder, Out.ClassificationTileDrawIndirectBufferUAV, 0);
// Indirect dispatch
Out.ClassificationTileDispatchIndirectBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(EStrataTileType::ECount), TEXT("Strata.StrataTileDispatchIndirectBuffer"));
Out.ClassificationTileDispatchIndirectBufferUAV = GraphBuilder.CreateUAV(Out.ClassificationTileDispatchIndirectBuffer, PF_R32_UINT);
AddClearUAVPass(GraphBuilder, Out.ClassificationTileDispatchIndirectBufferUAV, 0);
for (uint32 i = 0; i <= EStrataTileType::EComplex; ++i)
{
Out.ClassificationTileListBuffer[i] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), TileResolution.X * TileResolution.Y), StrataTileListBufferNames[i]);
Out.ClassificationTileListBufferSRV[i] = GraphBuilder.CreateSRV(Out.ClassificationTileListBuffer[i], PF_R32_UINT);
Out.ClassificationTileListBufferUAV[i] = GraphBuilder.CreateUAV(Out.ClassificationTileListBuffer[i], PF_R32_UINT);
}
}
// Separated subsurface & rough refraction textures (tile data)
{
const bool bIsStrataOpaqueMaterialRoughRefractionEnabled= IsStrataOpaqueMaterialRoughRefractionEnabled();
const int32 TileListBufferElementCount = bIsStrataOpaqueMaterialRoughRefractionEnabled ? TileResolution.X * TileResolution.Y : 4;
Out.ClassificationTileListBuffer[EStrataTileType::EOpaqueRoughRefraction] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), TileListBufferElementCount), StrataTileListBufferNames[EStrataTileType::EOpaqueRoughRefraction]);
Out.ClassificationTileListBufferSRV[EStrataTileType::EOpaqueRoughRefraction] = GraphBuilder.CreateSRV(Out.ClassificationTileListBuffer[EStrataTileType::EOpaqueRoughRefraction], PF_R32_UINT);
Out.ClassificationTileListBufferUAV[EStrataTileType::EOpaqueRoughRefraction] = GraphBuilder.CreateUAV(Out.ClassificationTileListBuffer[EStrataTileType::EOpaqueRoughRefraction], PF_R32_UINT);
Out.ClassificationTileListBuffer[EStrataTileType::ESSSWithoutOpaqueRoughRefraction] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), TileListBufferElementCount), StrataTileListBufferNames[EStrataTileType::ESSSWithoutOpaqueRoughRefraction]);
Out.ClassificationTileListBufferSRV[EStrataTileType::ESSSWithoutOpaqueRoughRefraction] = GraphBuilder.CreateSRV(Out.ClassificationTileListBuffer[EStrataTileType::ESSSWithoutOpaqueRoughRefraction], PF_R32_UINT);
Out.ClassificationTileListBufferUAV[EStrataTileType::ESSSWithoutOpaqueRoughRefraction] = GraphBuilder.CreateUAV(Out.ClassificationTileListBuffer[EStrataTileType::ESSSWithoutOpaqueRoughRefraction], PF_R32_UINT);
}
// BSDF tiles
if (bNeedBSDFOffets)
{
const FIntPoint BufferSize = SceneTexturesConfig.Extent;
const FIntPoint BufferSize_Extended = GetStrataTextureTileResolution(SceneTexturesConfig.Extent, EStrataTileSpace::StrataTileSpace_Primary | EStrataTileSpace::StrataTileSpace_Overflow);
const FIntPoint BaseOverflowTileOffset = FIntPoint(0, FMath::DivideAndRoundUp(BufferSize.Y, STRATA_TILE_SIZE));
Out.TileCount = GetStrataTextureTileResolution(ViewResolution, EStrataTileSpace::StrataTileSpace_Primary);
Out.TileOffset = FIntPoint(FMath::DivideAndRoundUp(View.ViewRect.Min.X, STRATA_TILE_SIZE), FMath::DivideAndRoundUp(View.ViewRect.Min.Y, STRATA_TILE_SIZE));
Out.OverflowTileCount = GetStrataTextureTileResolution(ViewResolution, EStrataTileSpace::StrataTileSpace_Overflow);
Out.OverflowTileOffset = GetStrataTextureTileResolution(Out.TileOffset * STRATA_TILE_SIZE, EStrataTileSpace::StrataTileSpace_Overflow) + BaseOverflowTileOffset;
Out.BSDFTileTexture = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(BufferSize_Extended, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource), TEXT("Strata.BSDFTiles"));
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Out.BSDFTileTexture), 0u);
Out.BSDFTilePerThreadDispatchIndirectBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(1), TEXT("Strata.StrataBSDFTilePerThreadDispatchIndirectBuffer"));
Out.BSDFTileDispatchIndirectBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(1), TEXT("Strata.StrataBSDFTileDispatchIndirectBuffer"));
Out.BSDFTileCountBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(4, 1), TEXT("Strata.BSDFTileCount"));
}
else
{
Out.TileCount = GetStrataTextureTileResolution(ViewResolution, EStrataTileSpace::StrataTileSpace_Primary);
Out.TileOffset = FIntPoint(0,0);
Out.OverflowTileCount = FIntPoint(0, 0);
Out.OverflowTileOffset = FIntPoint(0, 0);
Out.BSDFTileTexture = nullptr;
Out.BSDFTilePerThreadDispatchIndirectBuffer = nullptr;
Out.BSDFTileDispatchIndirectBuffer = nullptr;
Out.BSDFTileCountBuffer = nullptr;
}
}
// Create the readable uniform buffers
if (IsStrataEnabled())
{
FStrataGlobalUniformParameters* StrataUniformParameters = GraphBuilder.AllocParameters<FStrataGlobalUniformParameters>();
BindStrataGlobalUniformParameters(GraphBuilder, &Out, *StrataUniformParameters);
Out.StrataGlobalUniformParameters = GraphBuilder.CreateUniformBuffer(StrataUniformParameters);
}
}
static bool NeedBSDFOffsets(const FScene* Scene, const FViewInfo& View)
{
return ShouldRenderLumenDiffuseGI(Scene, View) || ShouldRenderLumenReflections(View) || Strata::ShouldRenderStrataDebugPasses(View);
}
void InitialiseStrataFrameSceneData(FRDGBuilder& GraphBuilder, FSceneRenderer& SceneRenderer)
{
FStrataSceneData& Out = SceneRenderer.Scene->StrataSceneData;
Out = FStrataSceneData();
auto UpdateMaterialBufferToTiledResolution = [](FIntPoint InBufferSizeXY, FIntPoint& OutMaterialBufferSizeXY)
{
// We need to allocate enough for the tiled memory addressing to always work
OutMaterialBufferSizeXY.X = FMath::DivideAndRoundUp(InBufferSizeXY.X, STRATA_TILE_SIZE) * STRATA_TILE_SIZE;
OutMaterialBufferSizeXY.Y = FMath::DivideAndRoundUp(InBufferSizeXY.Y, STRATA_TILE_SIZE) * STRATA_TILE_SIZE;
};
bool bNeedBSDFOffsets = false;
for (const FViewInfo& View : SceneRenderer.Views)
{
bNeedBSDFOffsets = bNeedBSDFOffsets || NeedBSDFOffsets(SceneRenderer.Scene, View);
}
FIntPoint MaterialBufferSizeXY;
UpdateMaterialBufferToTiledResolution(FIntPoint(1, 1), MaterialBufferSizeXY);
if (IsStrataEnabled())
{
UE5_MAIN: Multi-view-family scene renderer refactor, part 2. Move FSceneTextures singleton out of RDG blackboard and FSceneTexturesConfig global variable singleton, into FViewFamilyInfo. This is necessary to allow multiple view families to render in a single render graph and a single scene renderer call. * Existing calls to CreateSceneTextureShaderParameters and similar functions use "GetSceneTexturesChecked", which allows for the possibility that they are reached in a code path where scene textures haven't been initialized, and nullptr is returned instead of asserting. The shader parameter setup functions then fill in dummy defaults for that case. The goal was to precisely match the original behavior, which queried the RDG blackboard, and gracefully handled null if scene textures weren't there. This definitely appears to occur in FNiagaraGpuComputeDispatch::ProcessPendingTicksFlush, which can be called with a dummy scene with no scene textures. In the future, I may change this so dummy defaults are filled in for FSceneTextures at construction time, so the structure is never in an uninitialized state, but I would like to set up a test case for the Niagara code path before doing that, and the checks aren't harmful in the meantime. * I marked as deprecated global functions which query values from FSceneTexturesConfig, but they'll still work with the caveat that if you use multi-view-family rendering, the results will be indeterminate (whatever view family rendered last). There was only one case outside the scene renderer that accessed the globals (depth clear value), which I removed, noting that there is nowhere in the code where we modify the depth clear value from its global default. I would like to permanently deprecate or remove these at some point. Display Cluster is the only code that's currently using the multi-view-family code path, and as a new (still incomplete) feature, third party code can't be using it, and won't be affected. #jira NONE #rb chris.kulla zach.bethel mihnea.balta #preflight 6261aca76119a1a496bd2644 [CL 19873983 by jason hoerner in ue5-main branch]
2022-04-22 17:33:02 -04:00
FIntPoint SceneTextureExtent = SceneRenderer.GetActiveSceneTexturesConfig().Extent;
// We need to allocate enough for the tiled memory addressing of material data to always work
UpdateMaterialBufferToTiledResolution(SceneTextureExtent, MaterialBufferSizeXY);
const uint32 MaterialConservativeByteCountPerPixel = CVarStrataBytePerPixel.GetValueOnAnyThread();
const uint32 RoundToValue = 4u;
Out.MaxBytesPerPixel = FMath::DivideAndRoundUp(MaterialConservativeByteCountPerPixel, RoundToValue) * RoundToValue;
// Top layer texture
{
Out.TopLayerTexture = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(SceneTextureExtent, PF_R32_UINT, FClearValueBinding::Black, TexCreate_RenderTargetable | TexCreate_ShaderResource), TEXT("Strata.TopLayerTexture"));
}
// SSS texture
{
const uint32 SSSDataUintCount = 2;
const FRDGTextureDesc SSSTextureDesc = FRDGTextureDesc::Create2DArray(SceneTextureExtent, PF_R32_UINT, FClearValueBinding::Black,
TexCreate_TargetArraySlicesIndependently | TexCreate_DisableDCC | TexCreate_NoFastClear | TexCreate_ShaderResource | TexCreate_UAV, SSSDataUintCount, 1, 1);
Out.SSSTexture = GraphBuilder.CreateTexture(SSSTextureDesc, TEXT("Strata.SSSTexture"));
Out.SSSTextureUAV = GraphBuilder.CreateUAV(Out.SSSTexture);
}
// Separated subsurface and rough refraction textures
{
const bool bIsStrataOpaqueMaterialRoughRefractionEnabled = IsStrataOpaqueMaterialRoughRefractionEnabled();
const FIntPoint OpaqueRoughRefractionSceneExtent = bIsStrataOpaqueMaterialRoughRefractionEnabled ? SceneTextureExtent : FIntPoint(4, 4);
Out.OpaqueRoughRefractionTexture = GraphBuilder.CreateTexture(
FRDGTextureDesc::Create2D(OpaqueRoughRefractionSceneExtent, PF_FloatR11G11B10, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_RenderTargetable), TEXT("Strata.OpaqueRoughRefractionTexture"));
Out.OpaqueRoughRefractionTextureUAV = GraphBuilder.CreateUAV(Out.OpaqueRoughRefractionTexture);
Out.SeparatedSubSurfaceSceneColor = GraphBuilder.CreateTexture(
FRDGTextureDesc::Create2D(OpaqueRoughRefractionSceneExtent, PF_FloatR11G11B10, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_RenderTargetable), TEXT("Strata.SeparatedSubSurfaceSceneColor"));
Out.SeparatedOpaqueRoughRefractionSceneColor= GraphBuilder.CreateTexture(
FRDGTextureDesc::Create2D(OpaqueRoughRefractionSceneExtent, PF_FloatR11G11B10, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV | TexCreate_RenderTargetable), TEXT("Strata.SeparatedOpaqueRoughRefractionSceneColor"));
if (bIsStrataOpaqueMaterialRoughRefractionEnabled)
{
// Fast clears
AddClearRenderTargetPass(GraphBuilder, Out.OpaqueRoughRefractionTexture, Out.OpaqueRoughRefractionTexture->Desc.ClearValue.GetClearColor());
AddClearRenderTargetPass(GraphBuilder, Out.SeparatedSubSurfaceSceneColor, Out.SeparatedSubSurfaceSceneColor->Desc.ClearValue.GetClearColor());
AddClearRenderTargetPass(GraphBuilder, Out.SeparatedOpaqueRoughRefractionSceneColor, Out.SeparatedOpaqueRoughRefractionSceneColor->Desc.ClearValue.GetClearColor());
}
}
// BSDF offsets
if (bNeedBSDFOffsets)
{
Out.BSDFOffsetTexture = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(SceneTextureExtent, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource), TEXT("Strata.BSDFOffsets"));
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Out.BSDFOffsetTexture), 0u);
}
}
else
{
Out.MaxBytesPerPixel = 4u * STRATA_BASE_PASS_MRT_OUTPUT_COUNT;
}
// Create the material data container
UE5_MAIN: Multi-view-family scene renderer refactor, part 2. Move FSceneTextures singleton out of RDG blackboard and FSceneTexturesConfig global variable singleton, into FViewFamilyInfo. This is necessary to allow multiple view families to render in a single render graph and a single scene renderer call. * Existing calls to CreateSceneTextureShaderParameters and similar functions use "GetSceneTexturesChecked", which allows for the possibility that they are reached in a code path where scene textures haven't been initialized, and nullptr is returned instead of asserting. The shader parameter setup functions then fill in dummy defaults for that case. The goal was to precisely match the original behavior, which queried the RDG blackboard, and gracefully handled null if scene textures weren't there. This definitely appears to occur in FNiagaraGpuComputeDispatch::ProcessPendingTicksFlush, which can be called with a dummy scene with no scene textures. In the future, I may change this so dummy defaults are filled in for FSceneTextures at construction time, so the structure is never in an uninitialized state, but I would like to set up a test case for the Niagara code path before doing that, and the checks aren't harmful in the meantime. * I marked as deprecated global functions which query values from FSceneTexturesConfig, but they'll still work with the caveat that if you use multi-view-family rendering, the results will be indeterminate (whatever view family rendered last). There was only one case outside the scene renderer that accessed the globals (depth clear value), which I removed, noting that there is nowhere in the code where we modify the depth clear value from its global default. I would like to permanently deprecate or remove these at some point. Display Cluster is the only code that's currently using the multi-view-family code path, and as a new (still incomplete) feature, third party code can't be using it, and won't be affected. #jira NONE #rb chris.kulla zach.bethel mihnea.balta #preflight 6261aca76119a1a496bd2644 [CL 19873983 by jason hoerner in ue5-main branch]
2022-04-22 17:33:02 -04:00
FIntPoint SceneTextureExtent = IsStrataEnabled() ? SceneRenderer.GetActiveSceneTexturesConfig().Extent : FIntPoint(2, 2);
const uint32 SliceCount = FMath::DivideAndRoundUp(Out.MaxBytesPerPixel, 4u);
const FRDGTextureDesc MaterialTextureDesc = FRDGTextureDesc::Create2DArray(SceneTextureExtent, PF_R32_UINT, FClearValueBinding::Transparent,
TexCreate_TargetArraySlicesIndependently | TexCreate_DisableDCC | TexCreate_NoFastClear | TexCreate_RenderTargetable | TexCreate_ShaderResource | TexCreate_UAV, SliceCount, 1, 1);
Out.MaterialTextureArray = GraphBuilder.CreateTexture(MaterialTextureDesc, TEXT("Strata.Material"));
Out.MaterialTextureArraySRV = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::Create(Out.MaterialTextureArray));
Out.MaterialTextureArrayUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Out.MaterialTextureArray, 0));
// See AppendStrataMRTs
check(STRATA_BASE_PASS_MRT_OUTPUT_COUNT <= SliceCount);
Out.MaterialTextureArrayUAVWithoutRTs = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Out.MaterialTextureArray, 0, PF_Unknown, STRATA_BASE_PASS_MRT_OUTPUT_COUNT, SliceCount - STRATA_BASE_PASS_MRT_OUTPUT_COUNT));
// Rough diffuse model
Out.bRoughDiffuse = CVarStrataRoughDiffuse.GetValueOnRenderThread() > 0 ? 1u : 0u;
Out.PeelLayersAboveDepth = FMath::Max(CVarStrataDebugPeelLayersAboveDepth.GetValueOnRenderThread(), 0);
Out.SliceStoringDebugStrataTree = SliceCount - 1 - STRATA_BASE_PASS_MRT_OUTPUT_COUNT; // The UAV skips the first slices set as render target
if (IsStrataEnabled())
{
AddStrataClearMaterialBufferPass(
GraphBuilder,
GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Out.MaterialTextureArray, 0)),
Out.SSSTextureUAV,
Out.MaxBytesPerPixel,
MaterialBufferSizeXY);
}
// Initialized view data
for (int32 ViewIndex = 0; ViewIndex < SceneRenderer.Views.Num(); ViewIndex++)
{
Strata::InitialiseStrataViewData(GraphBuilder, SceneRenderer.Views[ViewIndex], SceneRenderer.GetActiveSceneTexturesConfig(), bNeedBSDFOffsets, Out);
}
}
void BindStrataBasePassUniformParameters(FRDGBuilder& GraphBuilder, const FViewInfo& View, FStrataBasePassUniformParameters& OutStrataUniformParameters)
{
const FStrataSceneData* StrataSceneData = View.StrataViewData.SceneData;
if (IsStrataEnabled() && StrataSceneData)
{
OutStrataUniformParameters.bRoughDiffuse = StrataSceneData->bRoughDiffuse ? 1u : 0u;
OutStrataUniformParameters.MaxBytesPerPixel = StrataSceneData->MaxBytesPerPixel;
OutStrataUniformParameters.PeelLayersAboveDepth = StrataSceneData->PeelLayersAboveDepth;
OutStrataUniformParameters.SliceStoringDebugStrataTree = StrataSceneData->SliceStoringDebugStrataTree;
OutStrataUniformParameters.MaterialTextureArrayUAVWithoutRTs = StrataSceneData->MaterialTextureArrayUAVWithoutRTs;
OutStrataUniformParameters.SSSTextureUAV = StrataSceneData->SSSTextureUAV;
OutStrataUniformParameters.OpaqueRoughRefractionTextureUAV = StrataSceneData->OpaqueRoughRefractionTextureUAV;
}
else
{
FRDGTextureRef DummyWritableSSSTexture = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(FIntPoint(1, 1), PF_R32_UINT, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV), TEXT("Strata.DummyWritableTexture"));
FRDGTextureUAVRef DummyWritableSSSTextureUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(DummyWritableSSSTexture));
FRDGTextureRef DummyWritableRefracTexture = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(FIntPoint(1, 1), PF_R8, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV), TEXT("Strata.DummyWritableTexture"));
FRDGTextureUAVRef DummyWritableRefracTextureUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(DummyWritableRefracTexture));
FRDGTextureRef DummyWritableTextureArray = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2DArray(FIntPoint(1, 1), PF_R32_UINT, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV, 1), TEXT("Strata.DummyWritableTexture"));
FRDGTextureUAVRef DummyWritableTextureArrayUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(DummyWritableTextureArray));
const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);
OutStrataUniformParameters.bRoughDiffuse = 0u;
OutStrataUniformParameters.MaxBytesPerPixel = 0;
OutStrataUniformParameters.PeelLayersAboveDepth = 0;
OutStrataUniformParameters.SliceStoringDebugStrataTree = -1;
OutStrataUniformParameters.MaterialTextureArrayUAVWithoutRTs = DummyWritableTextureArrayUAV;
OutStrataUniformParameters.SSSTextureUAV = DummyWritableSSSTextureUAV;
OutStrataUniformParameters.OpaqueRoughRefractionTextureUAV = DummyWritableRefracTextureUAV;
}
}
static void BindStrataGlobalUniformParameters(FRDGBuilder& GraphBuilder, FStrataViewData* StrataViewData, FStrataGlobalUniformParameters& OutStrataUniformParameters)
{
FStrataSceneData* StrataSceneData = StrataViewData->SceneData;
if (IsStrataEnabled() && StrataSceneData)
{
OutStrataUniformParameters.bRoughDiffuse = StrataSceneData->bRoughDiffuse ? 1u : 0u;
OutStrataUniformParameters.MaxBytesPerPixel = StrataSceneData->MaxBytesPerPixel;
OutStrataUniformParameters.PeelLayersAboveDepth = StrataSceneData->PeelLayersAboveDepth;
OutStrataUniformParameters.SliceStoringDebugStrataTree = StrataSceneData->SliceStoringDebugStrataTree;
OutStrataUniformParameters.TileSize = STRATA_TILE_SIZE;
OutStrataUniformParameters.TileSizeLog2 = STRATA_TILE_SIZE_DIV_AS_SHIFT;
OutStrataUniformParameters.TileCount = StrataViewData->TileCount;
OutStrataUniformParameters.TileOffset = StrataViewData->TileOffset;
OutStrataUniformParameters.OverflowTileCount = StrataViewData->OverflowTileCount;
OutStrataUniformParameters.OverflowTileOffset = StrataViewData->OverflowTileOffset;
OutStrataUniformParameters.MaterialTextureArray = StrataSceneData->MaterialTextureArray;
OutStrataUniformParameters.TopLayerTexture = StrataSceneData->TopLayerTexture;
OutStrataUniformParameters.SSSTexture = StrataSceneData->SSSTexture;
OutStrataUniformParameters.OpaqueRoughRefractionTexture = StrataSceneData->OpaqueRoughRefractionTexture;
OutStrataUniformParameters.BSDFTileTexture = StrataViewData->BSDFTileTexture;
OutStrataUniformParameters.BSDFOffsetTexture = StrataSceneData->BSDFOffsetTexture;
OutStrataUniformParameters.BSDFTileCountBuffer = StrataViewData->BSDFTileCountBuffer ? GraphBuilder.CreateSRV(StrataViewData->BSDFTileCountBuffer, PF_R32_UINT) : nullptr;
if (OutStrataUniformParameters.BSDFOffsetTexture == nullptr)
{
const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);
FRDGBufferSRVRef DefaultBuffer = GraphBuilder.CreateSRV(GSystemTextures.GetDefaultBuffer(GraphBuilder, 4, 0u), PF_R32_UINT);
OutStrataUniformParameters.BSDFOffsetTexture = SystemTextures.Black;
OutStrataUniformParameters.BSDFTileTexture = SystemTextures.Black;
OutStrataUniformParameters.BSDFTileCountBuffer = DefaultBuffer;
}
}
else
{
const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);
FRDGTextureRef DefaultTextureArray = GSystemTextures.GetDefaultTexture(GraphBuilder, ETextureDimension::Texture2DArray, EPixelFormat::PF_R32_UINT, FClearValueBinding::Transparent);
FRDGBufferSRVRef DefaultBuffer = GraphBuilder.CreateSRV(GSystemTextures.GetDefaultBuffer(GraphBuilder, 4, 0u), PF_R32_UINT);
OutStrataUniformParameters.bRoughDiffuse = 0;
OutStrataUniformParameters.MaxBytesPerPixel = 0;
OutStrataUniformParameters.PeelLayersAboveDepth = 0;
OutStrataUniformParameters.SliceStoringDebugStrataTree = -1;
OutStrataUniformParameters.TileSize = 0;
OutStrataUniformParameters.TileSizeLog2 = 0;
OutStrataUniformParameters.TileCount = 0;
OutStrataUniformParameters.TileOffset = 0;
OutStrataUniformParameters.OverflowTileCount = 0;
OutStrataUniformParameters.OverflowTileOffset = 0;
OutStrataUniformParameters.MaterialTextureArray = DefaultTextureArray;
OutStrataUniformParameters.TopLayerTexture = SystemTextures.DefaultNormal8Bit;
OutStrataUniformParameters.SSSTexture = SystemTextures.Black;
OutStrataUniformParameters.OpaqueRoughRefractionTexture = SystemTextures.Black;
OutStrataUniformParameters.BSDFTileTexture = SystemTextures.Black;
OutStrataUniformParameters.BSDFOffsetTexture = SystemTextures.Black;
OutStrataUniformParameters.BSDFTileCountBuffer = DefaultBuffer;
}
}
void BindStrataForwardPasslUniformParameters(FRDGBuilder& GraphBuilder, const FViewInfo& View, FStrataForwardPassUniformParameters& OutStrataUniformParameters)
{
FStrataSceneData* StrataSceneData = View.StrataViewData.SceneData;
if (IsStrataEnabled() && StrataSceneData)
{
OutStrataUniformParameters.bRoughDiffuse = StrataSceneData->bRoughDiffuse ? 1u : 0u;
OutStrataUniformParameters.PeelLayersAboveDepth = StrataSceneData->PeelLayersAboveDepth;
}
else
{
OutStrataUniformParameters.bRoughDiffuse = 0;
OutStrataUniformParameters.PeelLayersAboveDepth = 0;
}
}
TRDGUniformBufferRef<FStrataGlobalUniformParameters> BindStrataGlobalUniformParameters(const FViewInfo& View)
{
check(View.StrataViewData.StrataGlobalUniformParameters != nullptr || !IsStrataEnabled());
return View.StrataViewData.StrataGlobalUniformParameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FStrataClearMaterialBufferCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FStrataClearMaterialBufferCS);
SHADER_USE_PARAMETER_STRUCT(FStrataClearMaterialBufferCS, FGlobalShader);
using FPermutationDomain = TShaderPermutationDomain<>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray<uint>, MaterialTextureArrayUAV)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray<uint>, SSSTextureUAV)
SHADER_PARAMETER(uint32, MaxBytesPerPixel)
SHADER_PARAMETER(FIntPoint, TiledViewBufferResolution)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5 && Strata::IsStrataEnabled();
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_CLEAR_MATERIAL_BUFFER"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FStrataClearMaterialBufferCS, "/Engine/Private/Strata/StrataMaterialClassification.usf", "ClearMaterialBufferMainCS", SF_Compute);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FStrataBSDFTilePassCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FStrataBSDFTilePassCS);
SHADER_USE_PARAMETER_STRUCT(FStrataBSDFTilePassCS, FGlobalShader);
class FWaveOps : SHADER_PERMUTATION_BOOL("PERMUTATION_WAVE_OPS");
using FPermutationDomain = TShaderPermutationDomain<FWaveOps>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER(int32, bRectPrimitive)
SHADER_PARAMETER(int32, TileSizeLog2)
SHADER_PARAMETER(FIntPoint, TileCount_Primary)
SHADER_PARAMETER(FIntPoint, TileOffset_Primary)
SHADER_PARAMETER(FIntPoint, OverflowTileCount)
SHADER_PARAMETER(FIntPoint, OverflowTileOffset)
SHADER_PARAMETER(FIntPoint, ViewResolution)
SHADER_PARAMETER(uint32, MaxBytesPerPixel)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TopLayerTexture)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2DArray<uint>, MaterialTextureArray)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, RWBSDFTileTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, RWBSDFOffsetTexture)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWBSDFTileCountBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, TileListBuffer)
RDG_BUFFER_ACCESS(TileIndirectBuffer, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
const bool bUseWaveIntrinsics = FDataDrivenShaderPlatformInfo::GetSupportsWaveOperations(Parameters.Platform);
FPermutationDomain PermutationVector(Parameters.PermutationId);
if (PermutationVector.Get<FWaveOps>() && !bUseWaveIntrinsics)
{
return false;
}
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5 && Strata::IsStrataEnabled();
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_BSDF_TILE"), 1);
FPermutationDomain PermutationVector(Parameters.PermutationId);
if (PermutationVector.Get<FWaveOps>())
{
OutEnvironment.CompilerFlags.Add(CFLAG_WaveOperations);
}
}
};
IMPLEMENT_GLOBAL_SHADER(FStrataBSDFTilePassCS, "/Engine/Private/Strata/StrataMaterialClassification.usf", "BSDFTileMainCS", SF_Compute);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FStrataMaterialTileClassificationPassCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FStrataMaterialTileClassificationPassCS);
SHADER_USE_PARAMETER_STRUCT(FStrataMaterialTileClassificationPassCS, FGlobalShader);
class FStrataClearDuringCategorization : SHADER_PERMUTATION_BOOL("PERMUTATION_STRATA_CLEAR_DURING_CATEGORIZATION");
class FWaveOps : SHADER_PERMUTATION_BOOL("PERMUTATION_WAVE_OPS");
using FPermutationDomain = TShaderPermutationDomain<FWaveOps, FStrataClearDuringCategorization>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER(int32, bRectPrimitive)
SHADER_PARAMETER(FIntPoint, ViewResolution)
SHADER_PARAMETER(uint32, MaxBytesPerPixel)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TopLayerTexture)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2DArray<uint>, MaterialTextureArray)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, TileDrawIndirectDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, SimpleTileListDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, SingleTileListDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, ComplexTileListDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OpaqueRoughRefractionTileListDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, SSSWithoutOpaqueRoughRefractionTileListDataBuffer)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray<uint>, SSSTextureUAV)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<float3>, OpaqueRoughRefractionTexture)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
const bool bUseWaveIntrinsics = FDataDrivenShaderPlatformInfo::GetSupportsWaveOperations(Parameters.Platform);
FPermutationDomain PermutationVector(Parameters.PermutationId);
if (PermutationVector.Get<FWaveOps>() && !bUseWaveIntrinsics)
{
return false;
}
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5 && Strata::IsStrataEnabled();
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_TILE_CATEGORIZATION"), 1);
FPermutationDomain PermutationVector(Parameters.PermutationId);
if (PermutationVector.Get<FWaveOps>())
{
OutEnvironment.CompilerFlags.Add(CFLAG_WaveOperations);
}
}
};
IMPLEMENT_GLOBAL_SHADER(FStrataMaterialTileClassificationPassCS, "/Engine/Private/Strata/StrataMaterialClassification.usf", "TileMainCS", SF_Compute);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FStrataMaterialTilePrepareArgsPassCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FStrataMaterialTilePrepareArgsPassCS);
SHADER_USE_PARAMETER_STRUCT(FStrataMaterialTilePrepareArgsPassCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, TileDrawIndirectDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, TileDispatchIndirectDataBuffer)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5 && Strata::IsStrataEnabled();
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_MATERIAL_TILE_PREPARE_ARGS"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FStrataMaterialTilePrepareArgsPassCS, "/Engine/Private/Strata/StrataMaterialClassification.usf", "ArgsMainCS", SF_Compute);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FStrataBSDFTilePrepareArgsPassCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FStrataBSDFTilePrepareArgsPassCS);
SHADER_USE_PARAMETER_STRUCT(FStrataBSDFTilePrepareArgsPassCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FIntPoint, TileCount_Primary)
SHADER_PARAMETER(FIntPoint, TileOffset_Primary)
SHADER_PARAMETER(FIntPoint, OverflowTileCount)
SHADER_PARAMETER(FIntPoint, OverflowTileOffset)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, TileDrawIndirectDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, TileDispatchIndirectDataBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, TileDispatchPerThreadIndirectDataBuffer)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5 && Strata::IsStrataEnabled();
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_BSDF_TILE_PREPARE_ARGS"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FStrataBSDFTilePrepareArgsPassCS, "/Engine/Private/Strata/StrataMaterialClassification.usf", "ArgsMainCS", SF_Compute);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FStrataMaterialStencilTaggingPassPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FStrataMaterialStencilTaggingPassPS);
SHADER_USE_PARAMETER_STRUCT(FStrataMaterialStencilTaggingPassPS, FGlobalShader);
using FPermutationDomain = TShaderPermutationDomain<>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(Strata::FStrataTilePassVS::FParameters, VS)
SHADER_PARAMETER(FVector4f, DebugTileColor)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
static FPermutationDomain RemapPermutation(FPermutationDomain PermutationVector)
{
return PermutationVector;
}
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5 && Strata::IsStrataEnabled();
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SHADER_STENCIL_TAGGING_PS"), 1);
}
};
IMPLEMENT_GLOBAL_SHADER(FStrataTilePassVS, "/Engine/Private/Strata/StrataTile.usf", "StrataTilePassVS", SF_Vertex);
IMPLEMENT_GLOBAL_SHADER(FStrataMaterialStencilTaggingPassPS, "/Engine/Private/Strata/StrataTile.usf", "StencilTaggingMainPS", SF_Pixel);
static FStrataTileParameter InternalSetTileParameters(FRDGBuilder* GraphBuilder, const FViewInfo& View, const EStrataTileType TileType)
{
FStrataTileParameter Out;
if (TileType != EStrataTileType::ECount)
{
Out.TileListBuffer = View.StrataViewData.ClassificationTileListBufferSRV[TileType];
Out.TileIndirectBuffer = View.StrataViewData.ClassificationTileDrawIndirectBuffer;
}
else if (GraphBuilder)
{
FRDGBufferRef BufferDummy = GSystemTextures.GetDefaultBuffer(*GraphBuilder, 4, 0u);
FRDGBufferSRVRef BufferDummySRV = GraphBuilder->CreateSRV(BufferDummy, PF_R32_UINT);
Out.TileListBuffer = BufferDummySRV;
Out.TileIndirectBuffer = BufferDummy;
}
return Out;
}
FStrataTilePassVS::FParameters SetTileParameters(
const FViewInfo& View,
const EStrataTileType TileType,
EPrimitiveType& PrimitiveType)
{
FStrataTileParameter Temp = InternalSetTileParameters(nullptr, View, TileType);
PrimitiveType = GRHISupportsRectTopology ? PT_RectList : PT_TriangleList;
FStrataTilePassVS::FParameters Out;
Out.OutputViewMinRect = FVector2f(View.CachedViewUniformShaderParameters->ViewRectMin.X, View.CachedViewUniformShaderParameters->ViewRectMin.Y);
Out.OutputViewSizeAndInvSize = View.CachedViewUniformShaderParameters->ViewSizeAndInvSize;
Out.OutputBufferSizeAndInvSize = View.CachedViewUniformShaderParameters->BufferSizeAndInvSize;
Out.ViewScreenToTranslatedWorld = View.CachedViewUniformShaderParameters->ScreenToTranslatedWorld;
Out.TileListBuffer = Temp.TileListBuffer;
Out.TileIndirectBuffer = Temp.TileIndirectBuffer;
return Out;
}
FStrataTilePassVS::FParameters SetTileParameters(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const EStrataTileType TileType,
EPrimitiveType& PrimitiveType)
{
FStrataTileParameter Temp = InternalSetTileParameters(&GraphBuilder, View, TileType);
PrimitiveType = GRHISupportsRectTopology ? PT_RectList : PT_TriangleList;
FStrataTilePassVS::FParameters Out;
Out.OutputViewMinRect = FVector2f(View.CachedViewUniformShaderParameters->ViewRectMin.X, View.CachedViewUniformShaderParameters->ViewRectMin.Y);
Out.OutputViewSizeAndInvSize = View.CachedViewUniformShaderParameters->ViewSizeAndInvSize;
Out.OutputBufferSizeAndInvSize = View.CachedViewUniformShaderParameters->BufferSizeAndInvSize;
Out.ViewScreenToTranslatedWorld = View.CachedViewUniformShaderParameters->ScreenToTranslatedWorld;
Out.TileListBuffer = Temp.TileListBuffer;
Out.TileIndirectBuffer = Temp.TileIndirectBuffer;
return Out;
}
FStrataTileParameter SetTileParameters(FRDGBuilder& GraphBuilder, const FViewInfo& View, const EStrataTileType TileType)
{
return InternalSetTileParameters(&GraphBuilder, View, TileType);
}
uint32 TileTypeDrawIndirectArgOffset(const EStrataTileType Type)
{
check(Type >= 0 && Type < EStrataTileType::ECount);
return GetStrataTileTypeDrawIndirectArgOffset_Byte(Type);
}
uint32 TileTypeDispatchIndirectArgOffset(const EStrataTileType Type)
{
check(Type >= 0 && Type < EStrataTileType::ECount);
return GetStrataTileTypeDispatchIndirectArgOffset_Byte(Type);
}
// Add additionnaly bits for filling/clearing stencil to ensure that the 'Strata' bits are not corrupted by the stencil shadows
// when generating shadow mask. Withouth these 'trailing' bits, the incr./decr. operation would change/corrupt the 'Strata' bits
constexpr uint32 StencilBit_Fast_1 = StencilBit_Fast;
constexpr uint32 StencilBit_Single_1 = StencilBit_Single;
constexpr uint32 StencilBit_Complex_1 = StencilBit_Complex;
void AddStrataInternalClassificationTilePass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FRDGTextureRef* DepthTexture,
const FRDGTextureRef* ColorTexture,
EStrataTileType TileMaterialType,
const bool bDebug = false)
{
EPrimitiveType StrataTilePrimitiveType = PT_TriangleList;
const FIntPoint OutputResolution = View.ViewRect.Size();
const FIntRect ViewRect = View.ViewRect;
FStrataMaterialStencilTaggingPassPS::FParameters* ParametersPS = GraphBuilder.AllocParameters<FStrataMaterialStencilTaggingPassPS::FParameters>();
ParametersPS->VS = Strata::SetTileParameters(GraphBuilder, View, TileMaterialType, StrataTilePrimitiveType);
FStrataTilePassVS::FPermutationDomain VSPermutationVector;
VSPermutationVector.Set< FStrataTilePassVS::FEnableDebug >(bDebug);
VSPermutationVector.Set< FStrataTilePassVS::FEnableTexCoordScreenVector >(false);
TShaderMapRef<FStrataTilePassVS> VertexShader(View.ShaderMap, VSPermutationVector);
TShaderMapRef<FStrataMaterialStencilTaggingPassPS> PixelShader(View.ShaderMap);
// For debug purpose
if (bDebug)
{
check(ColorTexture);
ParametersPS->RenderTargets[0] = FRenderTargetBinding(*ColorTexture, ERenderTargetLoadAction::ELoad);
switch (TileMaterialType)
{
case EStrataTileType::ESimple: ParametersPS->DebugTileColor = FVector4f(0.0f, 1.0f, 0.0f, 1.0); break;
case EStrataTileType::ESingle: ParametersPS->DebugTileColor = FVector4f(1.0f, 1.0f, 0.0f, 1.0); break;
case EStrataTileType::EComplex: ParametersPS->DebugTileColor = FVector4f(1.0f, 0.0f, 0.0f, 1.0); break;
case EStrataTileType::EOpaqueRoughRefraction: ParametersPS->DebugTileColor = FVector4f(0.0f, 1.0f, 1.0f, 1.0); break;
case EStrataTileType::ESSSWithoutOpaqueRoughRefraction: ParametersPS->DebugTileColor = FVector4f(0.0f, 0.0f, 1.0f, 1.0); break;
default: check(false);
}
}
else
{
check(DepthTexture);
ParametersPS->RenderTargets.DepthStencil = FDepthStencilBinding(
*DepthTexture,
ERenderTargetLoadAction::ELoad,
ERenderTargetLoadAction::ELoad,
FExclusiveDepthStencil::DepthNop_StencilWrite);
ParametersPS->DebugTileColor = FVector4f(ForceInitToZero);
}
GraphBuilder.AddPass(
RDG_EVENT_NAME("Strata::%sClassificationPass(%s)", bDebug ? TEXT("Debug") : TEXT("Stencil"), ToString(TileMaterialType)),
ParametersPS,
ERDGPassFlags::Raster,
[ParametersPS, VertexShader, PixelShader, ViewRect, OutputResolution, StrataTilePrimitiveType, TileMaterialType, bDebug](FRHICommandList& RHICmdList)
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
uint32 StencilRef = 0xFF;
if (bDebug)
{
// Use premultiplied alpha blending, pixel shader and depth/stencil is off
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_InverseSourceAlpha, BO_Add, BF_Zero, BF_One>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
}
else
{
check(TileMaterialType != EStrataTileType::ECount && TileMaterialType != EStrataTileType::EOpaqueRoughRefraction && TileMaterialType != EStrataTileType::ESSSWithoutOpaqueRoughRefraction);
// No blending and no pixel shader required. Stencil will be written to.
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = nullptr;
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
switch (TileMaterialType)
{
case EStrataTileType::ESimple:
{
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<
false, CF_Always,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, StencilBit_Fast_1>::GetRHI();
StencilRef = StencilBit_Fast_1;
}
break;
case EStrataTileType::ESingle:
{
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<
false, CF_Always,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, StencilBit_Single_1>::GetRHI();
StencilRef = StencilBit_Single_1;
}
break;
case EStrataTileType::EComplex:
{
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<
false, CF_Always,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, StencilBit_Complex_1>::GetRHI();
StencilRef = StencilBit_Complex_1;
}
break;
}
}
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.PrimitiveType = StrataTilePrimitiveType;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, StencilRef);
SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), ParametersPS->VS);
if (bDebug)
{
// Debug rendering is aways done during the post-processing stage, which has an ViewMinRect set to (0,0)
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *ParametersPS);
RHICmdList.SetViewport(0, 0, 0.0f, OutputResolution.X, OutputResolution.Y, 1.0f);
}
else
{
RHICmdList.SetViewport(ViewRect.Min.X, ViewRect.Min.Y, 0.0f, ViewRect.Max.X, ViewRect.Max.Y, 1.0f);
}
RHICmdList.SetStreamSource(0, nullptr, 0);
RHICmdList.DrawPrimitiveIndirect(ParametersPS->VS.TileIndirectBuffer->GetIndirectRHICallBuffer(), TileTypeDrawIndirectArgOffset(TileMaterialType));
});
}
void AddStrataStencilPass(
FRDGBuilder& GraphBuilder,
const TArrayView<FViewInfo>& Views,
const FMinimalSceneTextures& SceneTextures)
{
for (int32 i = 0; i < Views.Num(); ++i)
{
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", i);
const FViewInfo& View = Views[i];
AddStrataInternalClassificationTilePass(GraphBuilder, View, &SceneTextures.Depth.Target, nullptr, EStrataTileType::EComplex);
AddStrataInternalClassificationTilePass(GraphBuilder, View, &SceneTextures.Depth.Target, nullptr, EStrataTileType::ESingle);
AddStrataInternalClassificationTilePass(GraphBuilder, View, &SceneTextures.Depth.Target, nullptr, EStrataTileType::ESimple);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void AppendStrataMRTs(const FSceneRenderer& SceneRenderer, uint32& RenderTargetCount, TStaticArray<FTextureRenderTargetBinding, MaxSimultaneousRenderTargets>& RenderTargets)
{
if (Strata::IsStrataEnabled() && SceneRenderer.Scene)
{
// If this function changes, update Strata::SetBasePassRenderTargetOutputFormat()
// Add 2 uint for Strata fast path.
// - We must clear the first uint to 0 to identify pixels that have not been written to.
// - We must never clear the second uint, it will only be written/read if needed.
auto AddStrataOutputTarget = [&](int16 StrataMaterialArraySlice, bool bNeverClear = false)
{
RenderTargets[RenderTargetCount] = FTextureRenderTargetBinding(SceneRenderer.Scene->StrataSceneData.MaterialTextureArray, StrataMaterialArraySlice, bNeverClear);
RenderTargetCount++;
};
for (int i = 0; i < STRATA_BASE_PASS_MRT_OUTPUT_COUNT; ++i)
{
const bool bNeverClear = i != 0; // Only allow clearing the first slice containing the header
AddStrataOutputTarget(i, bNeverClear);
}
// Add another MRT for Strata top layer information. We want to follow the usual clear process which can leverage fast clear.
{
RenderTargets[RenderTargetCount] = FTextureRenderTargetBinding(SceneRenderer.Scene->StrataSceneData.TopLayerTexture);
RenderTargetCount++;
};
}
}
void SetBasePassRenderTargetOutputFormat(const EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
if (Strata::IsStrataEnabled())
{
const FGBufferParams GBufferParams = FShaderCompileUtilities::FetchGBufferParamsRuntime(Platform);
const FGBufferInfo BufferInfo = FetchFullGBufferInfo(GBufferParams);
// Add 2 uint for Strata fast path
OutEnvironment.SetRenderTargetOutputFormat(BufferInfo.NumTargets + 0, PF_R32_UINT);
OutEnvironment.SetRenderTargetOutputFormat(BufferInfo.NumTargets + 1, PF_R32_UINT);
// Add another MRT for Strata top layer information
OutEnvironment.SetRenderTargetOutputFormat(BufferInfo.NumTargets + 2, PF_R32_UINT);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void AddStrataMaterialClassificationPass(FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures, const TArrayView<FViewInfo>& Views)
{
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, IsStrataEnabled() && Views.Num() > 0, "Strata::MaterialClassification");
if (!IsStrataEnabled())
{
return;
}
// Optionally run tile classification in async compute
const ERDGPassFlags PassFlags = CVarStrataAsyncClassification.GetValueOnRenderThread() > 0 ? ERDGPassFlags::AsyncCompute : ERDGPassFlags::Compute;
for (int32 i = 0; i < Views.Num(); ++i)
{
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", i);
const FViewInfo& View = Views[i];
bool bWaveOps = GRHISupportsWaveOperations && GRHIMaximumWaveSize >= 64 && FDataDrivenShaderPlatformInfo::GetSupportsWaveOperations(View.GetShaderPlatform());
const FStrataViewData* StrataViewData = &View.StrataViewData;
const FStrataSceneData* StrataSceneData = View.StrataViewData.SceneData;
// Tile reduction
{
const bool bClear = ClearDuringCategorization();
FStrataMaterialTileClassificationPassCS::FPermutationDomain PermutationVector;
PermutationVector.Set< FStrataMaterialTileClassificationPassCS::FStrataClearDuringCategorization >(bClear);
PermutationVector.Set< FStrataMaterialTileClassificationPassCS::FWaveOps >(bWaveOps);
TShaderMapRef<FStrataMaterialTileClassificationPassCS> ComputeShader(View.ShaderMap, PermutationVector);
FStrataMaterialTileClassificationPassCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FStrataMaterialTileClassificationPassCS::FParameters>();
PassParameters->ViewUniformBuffer = View.ViewUniformBuffer;
PassParameters->bRectPrimitive = GRHISupportsRectTopology ? 1 : 0;
PassParameters->ViewResolution = View.ViewRect.Size();
PassParameters->MaxBytesPerPixel = StrataSceneData->MaxBytesPerPixel;
PassParameters->TopLayerTexture = StrataSceneData->TopLayerTexture;
PassParameters->MaterialTextureArray = StrataSceneData->MaterialTextureArraySRV;
PassParameters->SSSTextureUAV = StrataSceneData->SSSTextureUAV;
PassParameters->OpaqueRoughRefractionTexture = StrataSceneData->OpaqueRoughRefractionTexture;
PassParameters->TileDrawIndirectDataBuffer = StrataViewData->ClassificationTileDrawIndirectBufferUAV;
PassParameters->SimpleTileListDataBuffer = StrataViewData->ClassificationTileListBufferUAV[EStrataTileType::ESimple];
PassParameters->SingleTileListDataBuffer = StrataViewData->ClassificationTileListBufferUAV[EStrataTileType::ESingle];
PassParameters->ComplexTileListDataBuffer = StrataViewData->ClassificationTileListBufferUAV[EStrataTileType::EComplex];
PassParameters->OpaqueRoughRefractionTileListDataBuffer = StrataViewData->ClassificationTileListBufferUAV[EStrataTileType::EOpaqueRoughRefraction];
PassParameters->SSSWithoutOpaqueRoughRefractionTileListDataBuffer = StrataViewData->ClassificationTileListBufferUAV[EStrataTileType::ESSSWithoutOpaqueRoughRefraction];
const uint32 GroupSize = 8;
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Strata::MaterialTileClassification(%s%s)", bWaveOps ? TEXT("Wave") : TEXT("SharedMemory"), bClear ? TEXT(", Clear") : TEXT("")),
PassFlags,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(PassParameters->ViewResolution, GroupSize));
}
// Tile indirect dispatch args conversion
{
TShaderMapRef<FStrataMaterialTilePrepareArgsPassCS> ComputeShader(View.ShaderMap);
FStrataMaterialTilePrepareArgsPassCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FStrataMaterialTilePrepareArgsPassCS::FParameters>();
PassParameters->TileDrawIndirectDataBuffer = GraphBuilder.CreateSRV(StrataViewData->ClassificationTileDrawIndirectBuffer, PF_R32_UINT);
PassParameters->TileDispatchIndirectDataBuffer = StrataViewData->ClassificationTileDispatchIndirectBufferUAV;
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Strata::MaterialTilePrepareArgs"),
PassFlags,
ComputeShader,
PassParameters,
FIntVector(1,1,1));
}
// Compute BSDF tile index and material read offset
if (StrataSceneData->BSDFOffsetTexture)
{
FRDGBufferUAVRef RWBSDFTileCountBuffer = GraphBuilder.CreateUAV(StrataViewData->BSDFTileCountBuffer, PF_R32_UINT);
AddClearUAVPass(GraphBuilder, RWBSDFTileCountBuffer, 0u);
FStrataBSDFTilePassCS::FPermutationDomain PermutationVector;
PermutationVector.Set< FStrataBSDFTilePassCS::FWaveOps >(bWaveOps);
TShaderMapRef<FStrataBSDFTilePassCS> ComputeShader(View.ShaderMap, PermutationVector);
FStrataBSDFTilePassCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FStrataBSDFTilePassCS::FParameters>();
PassParameters->ViewUniformBuffer = View.ViewUniformBuffer;
PassParameters->TileSizeLog2 = STRATA_TILE_SIZE_DIV_AS_SHIFT;
PassParameters->TileCount_Primary = StrataViewData->TileCount;
PassParameters->TileOffset_Primary = StrataViewData->TileOffset;
PassParameters->OverflowTileCount = StrataViewData->OverflowTileCount;
PassParameters->OverflowTileOffset = StrataViewData->OverflowTileOffset;
PassParameters->ViewResolution = View.ViewRect.Size();
PassParameters->MaxBytesPerPixel = StrataSceneData->MaxBytesPerPixel;
PassParameters->TopLayerTexture = StrataSceneData->TopLayerTexture;
PassParameters->MaterialTextureArray = StrataSceneData->MaterialTextureArraySRV;
PassParameters->TileListBuffer = StrataViewData->ClassificationTileListBufferSRV[EStrataTileType::EComplex];
PassParameters->TileIndirectBuffer = StrataViewData->ClassificationTileDispatchIndirectBuffer;
PassParameters->RWBSDFOffsetTexture = GraphBuilder.CreateUAV(StrataSceneData->BSDFOffsetTexture);
PassParameters->RWBSDFTileTexture = GraphBuilder.CreateUAV(StrataViewData->BSDFTileTexture);
PassParameters->RWBSDFTileCountBuffer = RWBSDFTileCountBuffer;
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Strata::BSDFTileAndOffsets(%s)", bWaveOps ? TEXT("Wave") : TEXT("SharedMemory")),
PassFlags,
ComputeShader,
PassParameters,
PassParameters->TileIndirectBuffer,
TileTypeDispatchIndirectArgOffset(EStrataTileType::EComplex));
}
// Tile indirect dispatch args conversion
if (StrataSceneData->BSDFOffsetTexture)
{
TShaderMapRef<FStrataBSDFTilePrepareArgsPassCS> ComputeShader(View.ShaderMap);
FStrataBSDFTilePrepareArgsPassCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FStrataBSDFTilePrepareArgsPassCS::FParameters>();
PassParameters->TileCount_Primary = StrataViewData->TileCount;
PassParameters->TileOffset_Primary = StrataViewData->TileOffset;
PassParameters->OverflowTileCount = StrataViewData->OverflowTileCount;
PassParameters->OverflowTileOffset = StrataViewData->OverflowTileOffset;
PassParameters->TileDrawIndirectDataBuffer = GraphBuilder.CreateSRV(StrataViewData->BSDFTileCountBuffer, PF_R32_UINT);
PassParameters->TileDispatchIndirectDataBuffer = GraphBuilder.CreateUAV(StrataViewData->BSDFTileDispatchIndirectBuffer, PF_R32_UINT);
PassParameters->TileDispatchPerThreadIndirectDataBuffer = GraphBuilder.CreateUAV(StrataViewData->BSDFTilePerThreadDispatchIndirectBuffer, PF_R32_UINT);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Strata::BSDFTilePrepareArgs"),
PassFlags,
ComputeShader,
PassParameters,
FIntVector(1, 1, 1));
}
}
}
static void AddStrataClearMaterialBufferPass(
FRDGBuilder& GraphBuilder,
FRDGTextureUAVRef MaterialTextureArrayUAV,
FRDGTextureUAVRef SSSTextureUAV,
uint32 MaxBytesPerPixel,
FIntPoint TiledViewBufferResolution)
{
if (ClearDuringCategorization())
{
return;
}
TShaderMapRef<FStrataClearMaterialBufferCS> ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel));
FStrataClearMaterialBufferCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FStrataClearMaterialBufferCS::FParameters>();
PassParameters->MaterialTextureArrayUAV = MaterialTextureArrayUAV;
PassParameters->SSSTextureUAV = SSSTextureUAV;
PassParameters->MaxBytesPerPixel = MaxBytesPerPixel;
PassParameters->TiledViewBufferResolution = TiledViewBufferResolution;
const uint32 GroupSize = 8;
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Strata::ClearMaterialBuffer"),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(TiledViewBufferResolution, GroupSize));
}
} // namespace Strata