597 lines
20 KiB
C++
597 lines
20 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Nanite.h"
|
|
#include "RHI.h"
|
|
#include "SceneUtils.h"
|
|
#include "ScenePrivate.h"
|
|
#include "PixelShaderUtils.h"
|
|
#include "ShaderPrintParameters.h"
|
|
#include "ShadowRendering.h"
|
|
#include "Rendering/NaniteStreamingManager.h"
|
|
#include "NaniteVisualizationData.h"
|
|
#include "NaniteShading.h"
|
|
#include "VirtualShadowMaps/VirtualShadowMapCacheManager.h"
|
|
|
|
#define NUM_PRINT_STATS_PASSES 6
|
|
|
|
int32 GNaniteShowStats = 0;
|
|
FAutoConsoleVariableRef CVarNaniteShowStats(
|
|
TEXT("r.Nanite.ShowStats"),
|
|
GNaniteShowStats,
|
|
TEXT("")
|
|
);
|
|
|
|
FString GNaniteStatsFilter;
|
|
FAutoConsoleVariableRef CVarNaniteStatsFilter(
|
|
TEXT("r.Nanite.StatsFilter"),
|
|
GNaniteStatsFilter,
|
|
TEXT("Sets the name of a specific Nanite raster pass to capture stats from - enumerate available filters with `NaniteStats List` cmd."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
extern TAutoConsoleVariable<int32> CVarNaniteShadows;
|
|
|
|
bool bNaniteListStatFilters = false;
|
|
|
|
void NaniteStatsFilterExec(const TCHAR* Cmd, FOutputDevice& Ar)
|
|
{
|
|
check(IsInGameThread());
|
|
|
|
FlushRenderingCommands();
|
|
|
|
uint32 ParameterCount = 0;
|
|
|
|
// Convenience, force on Nanite debug/stats and also shader printing.
|
|
GNaniteShowStats = 1;
|
|
ShaderPrint::SetEnabled(true);
|
|
|
|
// parse parameters
|
|
for (;;)
|
|
{
|
|
FString Parameter = FParse::Token(Cmd, 0);
|
|
|
|
if (Parameter.IsEmpty())
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (Parameter == TEXT("list"))
|
|
{
|
|
// We don't have access to all the scene data here, so we'll set a flag
|
|
// to print out every filter comparison for the next frame.
|
|
bNaniteListStatFilters = true;
|
|
}
|
|
else if (Parameter == TEXT("primary"))
|
|
{
|
|
// Empty filter name denotes the primary raster view.
|
|
ParameterCount = 0;
|
|
break;
|
|
}
|
|
else if (Parameter == TEXT("off"))
|
|
{
|
|
// disable stats
|
|
GNaniteShowStats = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
GNaniteStatsFilter = Parameter;
|
|
}
|
|
|
|
++ParameterCount;
|
|
}
|
|
|
|
if (!ParameterCount)
|
|
{
|
|
// Default to showing stats for the primary view
|
|
GNaniteStatsFilter.Empty();
|
|
}
|
|
}
|
|
|
|
class FEmitShadowMapPS : public FNaniteGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FEmitShadowMapPS);
|
|
SHADER_USE_PARAMETER_STRUCT(FEmitShadowMapPS, FNaniteGlobalShader);
|
|
|
|
class FDepthOutputTypeDim : SHADER_PERMUTATION_INT("DEPTH_OUTPUT_TYPE", 3);
|
|
using FPermutationDomain = TShaderPermutationDomain< FDepthOutputTypeDim >;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportNanite(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment( const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment )
|
|
{
|
|
FNaniteGlobalShader::ModifyCompilationEnvironment( Parameters, OutEnvironment );
|
|
FVirtualShadowMapArray::SetShaderDefines( OutEnvironment );
|
|
}
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER( FIntPoint, SourceOffset )
|
|
SHADER_PARAMETER( float, ViewToClip22 )
|
|
SHADER_PARAMETER( float, DepthBias )
|
|
SHADER_PARAMETER( uint32, ShadowMapID )
|
|
SHADER_PARAMETER_RDG_TEXTURE( Texture2D<uint>, DepthBuffer )
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
};
|
|
IMPLEMENT_GLOBAL_SHADER(FEmitShadowMapPS, "/Engine/Private/Nanite/NaniteEmitShadow.usf", "EmitShadowMapPS", SF_Pixel);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FEmitCubemapShadowParameters, )
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<uint>, DepthBuffer)
|
|
SHADER_PARAMETER( uint32, CubemapFaceIndex )
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FEmitCubemapShadowVS : public FNaniteGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FEmitCubemapShadowVS);
|
|
SHADER_USE_PARAMETER_STRUCT(FEmitCubemapShadowVS, FNaniteGlobalShader);
|
|
|
|
class FUseGeometryShader : SHADER_PERMUTATION_BOOL("USE_GEOMETRY_SHADER");
|
|
using FPermutationDomain = TShaderPermutationDomain<FUseGeometryShader>;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
if (DoesPlatformSupportNanite(Parameters.Platform))
|
|
{
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
|
|
const bool bSupportsVertexShaderLayer = FDataDrivenShaderPlatformInfo::GetSupportsVertexShaderLayer(Parameters.Platform);
|
|
return (PermutationVector.Get<FUseGeometryShader>() || bSupportsVertexShaderLayer);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment( const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment )
|
|
{
|
|
FNaniteGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
FVirtualShadowMapArray::SetShaderDefines(OutEnvironment);
|
|
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
|
|
if (PermutationVector.Get<FUseGeometryShader>())
|
|
{
|
|
OutEnvironment.CompilerFlags.Add(CFLAG_VertexToGeometryShader);
|
|
}
|
|
}
|
|
|
|
using FParameters = FEmitCubemapShadowParameters;
|
|
};
|
|
IMPLEMENT_GLOBAL_SHADER(FEmitCubemapShadowVS, "/Engine/Private/Nanite/NaniteEmitShadow.usf", "EmitCubemapShadowVS", SF_Vertex);
|
|
|
|
class FEmitCubemapShadowGS : public FNaniteGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FEmitCubemapShadowGS);
|
|
SHADER_USE_PARAMETER_STRUCT(FEmitCubemapShadowGS, FNaniteGlobalShader);
|
|
|
|
using FParameters = FEmitCubemapShadowParameters;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return RHISupportsGeometryShaders(Parameters.Platform) && DoesPlatformSupportNanite(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment( const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment )
|
|
{
|
|
FNaniteGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
FVirtualShadowMapArray::SetShaderDefines(OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("USE_GEOMETRY_SHADER"), 1);
|
|
}
|
|
};
|
|
IMPLEMENT_GLOBAL_SHADER(FEmitCubemapShadowGS, "/Engine/Private/Nanite/NaniteEmitShadow.usf", "EmitCubemapShadowGS", SF_Geometry);
|
|
|
|
class FEmitCubemapShadowPS : public FNaniteGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FEmitCubemapShadowPS);
|
|
SHADER_USE_PARAMETER_STRUCT(FEmitCubemapShadowPS, FNaniteGlobalShader);
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportNanite(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FNaniteGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
FVirtualShadowMapArray::SetShaderDefines(OutEnvironment);
|
|
}
|
|
|
|
using FParameters = FEmitCubemapShadowParameters;
|
|
};
|
|
IMPLEMENT_GLOBAL_SHADER(FEmitCubemapShadowPS, "/Engine/Private/Nanite/NaniteEmitShadow.usf", "EmitCubemapShadowPS", SF_Pixel);
|
|
|
|
// Gather shading stats
|
|
class FCalculateShadingStatsCS : public FNaniteGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FCalculateShadingStatsCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FCalculateShadingStatsCS, FNaniteGlobalShader);
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportNanite(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FNaniteGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_CALCULATE_STATS"), 1);
|
|
}
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER(uint32, RenderFlags)
|
|
SHADER_PARAMETER(uint32, NumShadingBins)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<FNaniteStats>, OutStatsBuffer)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, ShadingBinData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<FNaniteShadingBinStats>, ShadingBinStats)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, ShadingBinArgs)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
};
|
|
IMPLEMENT_GLOBAL_SHADER(FCalculateShadingStatsCS, "/Engine/Private/Nanite/NanitePrintStats.usf", "CalculateShadingStats", SF_Compute);
|
|
|
|
class FPrintStatsCS : public FNaniteGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER( FPrintStatsCS );
|
|
SHADER_USE_PARAMETER_STRUCT( FPrintStatsCS, FNaniteGlobalShader);
|
|
|
|
class FTwoPassCullingDim : SHADER_PERMUTATION_BOOL( "TWO_PASS_CULLING" );
|
|
class FPassDim : SHADER_PERMUTATION_INT("PRINT_PASS", NUM_PRINT_STATS_PASSES);
|
|
using FPermutationDomain = TShaderPermutationDomain<FTwoPassCullingDim, FPassDim>;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportNanite(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FNaniteGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_PRINT_STATS"), 1);
|
|
}
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT( FParameters, )
|
|
SHADER_PARAMETER(uint32, PackedClusterSize)
|
|
SHADER_PARAMETER(uint32, RenderFlags)
|
|
SHADER_PARAMETER(uint32, DebugFlags)
|
|
|
|
SHADER_PARAMETER_STRUCT_INCLUDE( ShaderPrint::FShaderParameters, ShaderPrintStruct )
|
|
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer<FNaniteStats>, InStatsBuffer )
|
|
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV( Buffer< uint >, MainPassRasterizeArgsSWHW )
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV( Buffer< uint >, PostPassRasterizeArgsSWHW )
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
};
|
|
IMPLEMENT_GLOBAL_SHADER(FPrintStatsCS, "/Engine/Private/Nanite/NanitePrintStats.usf", "PrintStats", SF_Compute);
|
|
|
|
namespace Nanite
|
|
{
|
|
|
|
FString GetFilterNameForLight(const FLightSceneProxy* LightProxy)
|
|
{
|
|
FString LightFilterName;
|
|
{
|
|
FString FullLevelName = LightProxy->GetLevelName().ToString();
|
|
const int32 LastSlashIndex = FullLevelName.Find(TEXT("/"), ESearchCase::CaseSensitive, ESearchDir::FromEnd);
|
|
|
|
if (LastSlashIndex != INDEX_NONE)
|
|
{
|
|
FullLevelName.MidInline(LastSlashIndex + 1, FullLevelName.Len() - (LastSlashIndex + 1), EAllowShrinking::No);
|
|
}
|
|
|
|
LightFilterName = FullLevelName + TEXT(".") + LightProxy->GetOwnerNameOrLabel();
|
|
}
|
|
|
|
return LightFilterName;
|
|
}
|
|
|
|
bool IsStatFilterActive(const FString& FilterName)
|
|
{
|
|
if (GNaniteShowStats == 0)
|
|
{
|
|
// Stats are disabled, do nothing.
|
|
return false;
|
|
}
|
|
|
|
return (GNaniteStatsFilter == FilterName);
|
|
}
|
|
|
|
bool IsStatFilterActiveForLight(const FLightSceneProxy* LightProxy)
|
|
{
|
|
if (GNaniteShowStats == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const FString LightFilterName = Nanite::GetFilterNameForLight(LightProxy);
|
|
return IsStatFilterActive(LightFilterName);
|
|
}
|
|
|
|
void ListStatFilters(FSceneRenderer* SceneRenderer)
|
|
{
|
|
if (bNaniteListStatFilters && SceneRenderer)
|
|
{
|
|
UE_LOG(LogNanite, Warning, TEXT("** Available Filters **"));
|
|
|
|
// Primary view is always available.
|
|
UE_LOG(LogNanite, Warning, TEXT("Primary"));
|
|
|
|
const bool bListShadows = CVarNaniteShadows.GetValueOnRenderThread() != 0;
|
|
|
|
// Virtual shadow maps
|
|
if (bListShadows)
|
|
{
|
|
if (SceneRenderer->VirtualShadowMapArray.GetNumShadowMaps() > 0)
|
|
{
|
|
UE_LOG(LogNanite, Warning, TEXT("VirtualShadowMaps"));
|
|
}
|
|
}
|
|
|
|
// Shadow map atlases
|
|
if (bListShadows)
|
|
{
|
|
const auto& ShadowMapAtlases = SceneRenderer->SortedShadowsForShadowDepthPass.ShadowMapAtlases;
|
|
for (int32 AtlasIndex = 0; AtlasIndex < ShadowMapAtlases.Num(); AtlasIndex++)
|
|
{
|
|
UE_LOG(LogNanite, Warning, TEXT("ShadowAtlas%d"), AtlasIndex);
|
|
}
|
|
}
|
|
|
|
// Shadow cube maps
|
|
if (bListShadows)
|
|
{
|
|
const auto& ShadowCubeMaps = SceneRenderer->SortedShadowsForShadowDepthPass.ShadowMapCubemaps;
|
|
for (int32 CubemapIndex = 0; CubemapIndex < ShadowCubeMaps.Num(); CubemapIndex++)
|
|
{
|
|
const FSortedShadowMapAtlas& ShadowMap = ShadowCubeMaps[CubemapIndex];
|
|
check(ShadowMap.Shadows.Num() == 1);
|
|
FProjectedShadowInfo* ProjectedShadowInfo = ShadowMap.Shadows[0];
|
|
|
|
if (ProjectedShadowInfo->bNaniteGeometry && ProjectedShadowInfo->CacheMode != SDCM_MovablePrimitivesOnly)
|
|
{
|
|
// Get the base light filter name.
|
|
FString CubeFilterName = GetFilterNameForLight(ProjectedShadowInfo->GetLightSceneInfo().Proxy);
|
|
CubeFilterName.Append(TEXT("_Face_"));
|
|
|
|
for (int32 CubemapFaceIndex = 0; CubemapFaceIndex < 6; CubemapFaceIndex++)
|
|
{
|
|
FString CubeFaceFilterName = CubeFilterName;
|
|
CubeFaceFilterName.AppendInt(CubemapFaceIndex);
|
|
UE_LOG(LogNanite, Warning, TEXT("Shadow Cube Map: %s"), *CubeFaceFilterName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bNaniteListStatFilters = false;
|
|
}
|
|
|
|
void ExtractShadingDebug(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& View,
|
|
const FShadeBinning& ShadeBinning,
|
|
uint32 NumShadingBins
|
|
)
|
|
{
|
|
LLM_SCOPE_BYTAG(Nanite);
|
|
|
|
const FNaniteVisualizationData& VisualizationData = GetNaniteVisualizationData();
|
|
if (VisualizationData.IsActive())
|
|
{
|
|
FRDGBufferRef ShadingBinData = nullptr;
|
|
if (ShadeBinning.ShadingBinData)
|
|
{
|
|
ShadingBinData = ShadeBinning.ShadingBinData;
|
|
}
|
|
else
|
|
{
|
|
ShadingBinData = GSystemTextures.GetDefaultByteAddressBuffer(GraphBuilder, 4u);
|
|
}
|
|
|
|
FRDGTextureRef FastTileVis = nullptr;
|
|
if (ShadeBinning.FastClearVisualize)
|
|
{
|
|
FastTileVis = ShadeBinning.FastClearVisualize;
|
|
}
|
|
else
|
|
{
|
|
FastTileVis = GSystemTextures.GetZeroUIntDummy(GraphBuilder);
|
|
}
|
|
|
|
Nanite::GGlobalResources.GetShadingBinDataBufferRef() = GraphBuilder.ConvertToExternalBuffer(ShadingBinData);
|
|
Nanite::GGlobalResources.GetFastClearTileVisRef() = GraphBuilder.ConvertToExternalTexture(FastTileVis);
|
|
}
|
|
|
|
if (GNaniteShowStats != 0 && Nanite::GGlobalResources.GetStatsBufferRef())
|
|
{
|
|
FCalculateShadingStatsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FCalculateShadingStatsCS::FParameters>();
|
|
|
|
PassParameters->RenderFlags = Nanite::GGlobalResources.StatsRenderFlags;
|
|
|
|
PassParameters->OutStatsBuffer = GraphBuilder.CreateUAV(GraphBuilder.RegisterExternalBuffer(Nanite::GGlobalResources.GetStatsBufferRef()));
|
|
|
|
PassParameters->NumShadingBins = NumShadingBins;
|
|
|
|
PassParameters->ShadingBinData = GraphBuilder.CreateSRV(ShadeBinning.ShadingBinData);
|
|
PassParameters->ShadingBinStats = GraphBuilder.CreateSRV(ShadeBinning.ShadingBinStats);
|
|
PassParameters->ShadingBinArgs = GraphBuilder.CreateSRV(ShadeBinning.ShadingBinArgs);
|
|
|
|
auto ComputeShader = View.ShaderMap->GetShader<FCalculateShadingStatsCS>();
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("CalculateShadingStatsArgs"),
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(1, 1, 1)
|
|
);
|
|
}
|
|
}
|
|
|
|
void PrintStats(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& View)
|
|
{
|
|
LLM_SCOPE_BYTAG(Nanite);
|
|
|
|
// Print stats
|
|
if (GNaniteShowStats != 0 && Nanite::GGlobalResources.GetStatsBufferRef())
|
|
{
|
|
auto& MainPassBuffers = Nanite::GGlobalResources.GetMainPassBuffers();
|
|
auto& PostPassBuffers = Nanite::GGlobalResources.GetPostPassBuffers();
|
|
|
|
// Shader compilers have a hard time handling the size of the full PrintStats shader, so we split it into multiple passes.
|
|
// This reduces the FXC compilation time from 2-3 minutes to just a few seconds.
|
|
for (uint32 Pass = 0; Pass < NUM_PRINT_STATS_PASSES; Pass++)
|
|
{
|
|
FPrintStatsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FPrintStatsCS::FParameters>();
|
|
|
|
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, PassParameters->ShaderPrintStruct);
|
|
PassParameters->PackedClusterSize = sizeof(Nanite::FPackedCluster);
|
|
|
|
PassParameters->RenderFlags = Nanite::GGlobalResources.StatsRenderFlags;
|
|
PassParameters->DebugFlags = Nanite::GGlobalResources.StatsDebugFlags;
|
|
|
|
PassParameters->InStatsBuffer = GraphBuilder.CreateSRV(GraphBuilder.RegisterExternalBuffer(Nanite::GGlobalResources.GetStatsBufferRef()));
|
|
|
|
PassParameters->MainPassRasterizeArgsSWHW = GraphBuilder.CreateSRV(GraphBuilder.RegisterExternalBuffer(MainPassBuffers.StatsRasterizeArgsSWHWBuffer));
|
|
|
|
const bool bTwoPass = (PostPassBuffers.StatsRasterizeArgsSWHWBuffer != nullptr);
|
|
if( bTwoPass )
|
|
{
|
|
PassParameters->PostPassRasterizeArgsSWHW = GraphBuilder.CreateSRV( GraphBuilder.RegisterExternalBuffer( PostPassBuffers.StatsRasterizeArgsSWHWBuffer ) );
|
|
}
|
|
|
|
FPrintStatsCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FPrintStatsCS::FTwoPassCullingDim>(bTwoPass);
|
|
PermutationVector.Set<FPrintStatsCS::FPassDim>(Pass);
|
|
auto ComputeShader = View.ShaderMap->GetShader<FPrintStatsCS>(PermutationVector);
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("Print Stats"),
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(1, 1, 1)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EmitShadowMap(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FSharedContext& SharedContext,
|
|
const FRasterContext& RasterContext,
|
|
const FRDGTextureRef DepthBuffer,
|
|
const FIntRect& SourceRect,
|
|
const FIntPoint DestOrigin,
|
|
const FMatrix& ProjectionMatrix,
|
|
float DepthBias,
|
|
bool bOrtho
|
|
)
|
|
{
|
|
LLM_SCOPE_BYTAG(Nanite);
|
|
|
|
auto* PassParameters = GraphBuilder.AllocParameters< FEmitShadowMapPS::FParameters >();
|
|
|
|
PassParameters->SourceOffset = SourceRect.Min - DestOrigin;
|
|
PassParameters->ViewToClip22 = ProjectionMatrix.M[2][2];
|
|
PassParameters->DepthBias = DepthBias;
|
|
|
|
PassParameters->DepthBuffer = RasterContext.DepthBuffer;
|
|
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding( DepthBuffer, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthWrite_StencilNop );
|
|
|
|
FEmitShadowMapPS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set< FEmitShadowMapPS::FDepthOutputTypeDim >( bOrtho ? 1 : 2 );
|
|
|
|
auto PixelShader = SharedContext.ShaderMap->GetShader< FEmitShadowMapPS >( PermutationVector );
|
|
|
|
FIntRect DestRect;
|
|
DestRect.Min = DestOrigin;
|
|
DestRect.Max = DestRect.Min + SourceRect.Max - SourceRect.Min;
|
|
|
|
FPixelShaderUtils::AddFullscreenPass(
|
|
GraphBuilder,
|
|
SharedContext.ShaderMap,
|
|
RDG_EVENT_NAME("EmitShadowMap"),
|
|
PixelShader,
|
|
PassParameters,
|
|
DestRect,
|
|
nullptr,
|
|
nullptr,
|
|
TStaticDepthStencilState<true, CF_LessEqual>::GetRHI()
|
|
);
|
|
}
|
|
|
|
void EmitCubemapShadow(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FSharedContext& SharedContext,
|
|
const FRasterContext& RasterContext,
|
|
const FRDGTextureRef CubemapDepthBuffer,
|
|
const FIntRect& ViewRect,
|
|
uint32 CubemapFaceIndex,
|
|
bool bUseGeometryShader
|
|
)
|
|
{
|
|
LLM_SCOPE_BYTAG(Nanite);
|
|
|
|
FEmitCubemapShadowVS::FPermutationDomain VertexPermutationVector;
|
|
VertexPermutationVector.Set<FEmitCubemapShadowVS::FUseGeometryShader>(bUseGeometryShader);
|
|
TShaderMapRef<FEmitCubemapShadowVS> VertexShader(SharedContext.ShaderMap, VertexPermutationVector);
|
|
TShaderRef<FEmitCubemapShadowGS> GeometryShader;
|
|
TShaderMapRef<FEmitCubemapShadowPS> PixelShader(SharedContext.ShaderMap);
|
|
|
|
// VS output of RT array index on D3D11 requires a caps bit. Use GS fallback if set.
|
|
if (bUseGeometryShader)
|
|
{
|
|
GeometryShader = TShaderMapRef<FEmitCubemapShadowGS>(SharedContext.ShaderMap);
|
|
}
|
|
|
|
FEmitCubemapShadowParameters* PassParameters = GraphBuilder.AllocParameters<FEmitCubemapShadowParameters>();
|
|
PassParameters->CubemapFaceIndex = CubemapFaceIndex;
|
|
PassParameters->DepthBuffer = RasterContext.DepthBuffer;
|
|
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(CubemapDepthBuffer, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthWrite_StencilNop);
|
|
|
|
GraphBuilder.AddPass(
|
|
RDG_EVENT_NAME("Emit Cubemap Shadow"),
|
|
PassParameters,
|
|
ERDGPassFlags::Raster,
|
|
[PassParameters, VertexShader, GeometryShader, PixelShader, ViewRect, CubemapFaceIndex](FRDGAsyncTask, FRHICommandList& RHICmdList)
|
|
{
|
|
RHICmdList.SetViewport(ViewRect.Min.X, ViewRect.Min.Y, 0.0f, ViewRect.Max.X, ViewRect.Max.Y, 1.0f);
|
|
|
|
FGraphicsPipelineStateInitializer GraphicsPSOInit;
|
|
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
|
|
|
|
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
|
|
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
|
|
// NOTE: Shadow cubemaps are reverse Z
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<true, CF_DepthNear>::GetRHI();
|
|
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GEmptyVertexDeclaration.VertexDeclarationRHI;
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
|
|
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
|
|
if (GeometryShader.GetGeometryShader())
|
|
{
|
|
GraphicsPSOInit.BoundShaderState.SetGeometryShader(GeometryShader.GetGeometryShader());
|
|
}
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
|
|
|
|
SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), *PassParameters);
|
|
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
|
|
if (GeometryShader.GetGeometryShader())
|
|
{
|
|
SetShaderParameters(RHICmdList, GeometryShader, GeometryShader.GetGeometryShader(), *PassParameters);
|
|
}
|
|
|
|
RHICmdList.SetStreamSource(0, nullptr, 0);
|
|
RHICmdList.DrawPrimitive(0, 1, 1);
|
|
}
|
|
);
|
|
}
|
|
|
|
} // namespace Nanite
|