Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/DistanceFieldLightingPost.cpp
mickael gilabert d8e082633e Added Distance field shadow / AO support on Switch
Don't compile distance field shader permutations if bUseDistanceFields is unset or false
Added UAV output to pixel shader
Clear Tiny UAV uses command buffer ClearBuffer command instead of allocating a temp buffer and copying it to UAV

anthony.bills
#rnx

#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: mickael.gilabert
#ROBOMERGE-SOURCE: CL 6077502 via CL 6077551 via CL 6080478 via CL 6080627
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)

[CL 6084211 by mickael gilabert in Dev-VR branch]
2019-04-24 17:06:06 -04:00

823 lines
35 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
DistanceFieldLightingPost.cpp
=============================================================================*/
#include "DistanceFieldLightingPost.h"
#include "PostProcess/PostProcessing.h"
#include "PostProcess/SceneFilterRendering.h"
#include "DistanceFieldLightingShared.h"
#include "DistanceFieldAmbientOcclusion.h"
#include "CompositionLighting/PostProcessAmbientOcclusion.h"
#include "PipelineStateCache.h"
int32 GAOUseHistory = 1;
FAutoConsoleVariableRef CVarAOUseHistory(
TEXT("r.AOUseHistory"),
GAOUseHistory,
TEXT("Whether to apply a temporal filter to the distance field AO, which reduces flickering but also adds trails when occluders are moving."),
ECVF_RenderThreadSafe
);
int32 GAOClearHistory = 0;
FAutoConsoleVariableRef CVarAOClearHistory(
TEXT("r.AOClearHistory"),
GAOClearHistory,
TEXT(""),
ECVF_RenderThreadSafe
);
int32 GAOHistoryStabilityPass = 1;
FAutoConsoleVariableRef CVarAOHistoryStabilityPass(
TEXT("r.AOHistoryStabilityPass"),
GAOHistoryStabilityPass,
TEXT("Whether to gather stable results to fill in holes in the temporal reprojection. Adds some GPU cost but improves temporal stability with foliage."),
ECVF_RenderThreadSafe
);
float GAOHistoryWeight = .85f;
FAutoConsoleVariableRef CVarAOHistoryWeight(
TEXT("r.AOHistoryWeight"),
GAOHistoryWeight,
TEXT("Amount of last frame's AO to lerp into the final result. Higher values increase stability, lower values have less streaking under occluder movement."),
ECVF_RenderThreadSafe
);
float GAOHistoryDistanceThreshold = 30;
FAutoConsoleVariableRef CVarAOHistoryDistanceThreshold(
TEXT("r.AOHistoryDistanceThreshold"),
GAOHistoryDistanceThreshold,
TEXT("World space distance threshold needed to discard last frame's DFAO results. Lower values reduce ghosting from characters when near a wall but increase flickering artifacts."),
ECVF_RenderThreadSafe
);
float GAOViewFadeDistanceScale = .7f;
FAutoConsoleVariableRef CVarAOViewFadeDistanceScale(
TEXT("r.AOViewFadeDistanceScale"),
GAOViewFadeDistanceScale,
TEXT("Distance over which AO will fade out as it approaches r.AOMaxViewDistance, as a fraction of r.AOMaxViewDistance."),
ECVF_RenderThreadSafe
);
bool UseAOHistoryStabilityPass()
{
extern int32 GDistanceFieldAOQuality;
return GAOHistoryStabilityPass && GDistanceFieldAOQuality >= 2;
}
class FGeometryAwareUpsampleParameters
{
public:
void Bind(const FShaderParameterMap& ParameterMap)
{
DistanceFieldNormalTexture.Bind(ParameterMap, TEXT("DistanceFieldNormalTexture"));
DistanceFieldNormalSampler.Bind(ParameterMap, TEXT("DistanceFieldNormalSampler"));
BentNormalAOTexture.Bind(ParameterMap, TEXT("BentNormalAOTexture"));
BentNormalAOSampler.Bind(ParameterMap, TEXT("BentNormalAOSampler"));
DistanceFieldGBufferTexelSize.Bind(ParameterMap, TEXT("DistanceFieldGBufferTexelSize"));
DistanceFieldGBufferJitterOffset.Bind(ParameterMap, TEXT("DistanceFieldGBufferJitterOffset"));
BentNormalBufferAndTexelSize.Bind(ParameterMap, TEXT("BentNormalBufferAndTexelSize"));
MinDownsampleFactorToBaseLevel.Bind(ParameterMap, TEXT("MinDownsampleFactorToBaseLevel"));
DistanceFadeScale.Bind(ParameterMap, TEXT("DistanceFadeScale"));
JitterOffset.Bind(ParameterMap, TEXT("JitterOffset"));
}
void Set(FRHICommandList& RHICmdList, const FPixelShaderRHIParamRef& ShaderRHI, const FViewInfo& View, FSceneRenderTargetItem& DistanceFieldNormal, FSceneRenderTargetItem& DistanceFieldAOBentNormal)
{
SetTextureParameter(
RHICmdList,
ShaderRHI,
DistanceFieldNormalTexture,
DistanceFieldNormalSampler,
TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI(),
DistanceFieldNormal.ShaderResourceTexture
);
SetTextureParameter(
RHICmdList,
ShaderRHI,
BentNormalAOTexture,
BentNormalAOSampler,
TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI(),
DistanceFieldAOBentNormal.ShaderResourceTexture
);
extern FVector2D GetJitterOffset(int32 SampleIndex);
FVector2D const JitterOffsetValue = GetJitterOffset(View.ViewState->GetDistanceFieldTemporalSampleIndex());
const FIntPoint DownsampledBufferSize = GetBufferSizeForAO();
const FVector2D BaseLevelTexelSizeValue(1.0f / DownsampledBufferSize.X, 1.0f / DownsampledBufferSize.Y);
SetShaderValue(RHICmdList, ShaderRHI, DistanceFieldGBufferTexelSize, BaseLevelTexelSizeValue);
SetShaderValue(RHICmdList, ShaderRHI, DistanceFieldGBufferJitterOffset, BaseLevelTexelSizeValue * JitterOffsetValue);
extern FIntPoint GetBufferSizeForConeTracing();
const FIntPoint ConeTracingBufferSize = GetBufferSizeForConeTracing();
const FVector4 BentNormalBufferAndTexelSizeValue(ConeTracingBufferSize.X, ConeTracingBufferSize.Y, 1.0f / ConeTracingBufferSize.X, 1.0f / ConeTracingBufferSize.Y);
SetShaderValue(RHICmdList, ShaderRHI, BentNormalBufferAndTexelSize, BentNormalBufferAndTexelSizeValue);
extern int32 GConeTraceDownsampleFactor;
const float MinDownsampleFactor = GConeTraceDownsampleFactor;
SetShaderValue(RHICmdList, ShaderRHI, MinDownsampleFactorToBaseLevel, MinDownsampleFactor);
extern float GAOViewFadeDistanceScale;
const float DistanceFadeScaleValue = 1.0f / ((1.0f - GAOViewFadeDistanceScale) * GetMaxAOViewDistance());
SetShaderValue(RHICmdList, ShaderRHI, DistanceFadeScale, DistanceFadeScaleValue);
SetShaderValue(RHICmdList, ShaderRHI, JitterOffset, JitterOffsetValue);
}
/** Serializer. */
friend FArchive& operator<<(FArchive& Ar, FGeometryAwareUpsampleParameters& P)
{
Ar << P.DistanceFieldNormalTexture;
Ar << P.DistanceFieldNormalSampler;
Ar << P.BentNormalAOTexture;
Ar << P.BentNormalAOSampler;
Ar << P.DistanceFieldGBufferTexelSize;
Ar << P.DistanceFieldGBufferJitterOffset;
Ar << P.BentNormalBufferAndTexelSize;
Ar << P.MinDownsampleFactorToBaseLevel;
Ar << P.DistanceFadeScale;
Ar << P.JitterOffset;
return Ar;
}
private:
FShaderResourceParameter DistanceFieldNormalTexture;
FShaderResourceParameter DistanceFieldNormalSampler;
FShaderResourceParameter BentNormalAOTexture;
FShaderResourceParameter BentNormalAOSampler;
FShaderParameter DistanceFieldGBufferTexelSize;
FShaderParameter DistanceFieldGBufferJitterOffset;
FShaderParameter BentNormalBufferAndTexelSize;
FShaderParameter MinDownsampleFactorToBaseLevel;
FShaderParameter DistanceFadeScale;
FShaderParameter JitterOffset;
};
class FUpdateHistoryDepthRejectionPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FUpdateHistoryDepthRejectionPS, Global);
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldAO(Parameters.Platform) && IsUsingDistanceFields(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("DOWNSAMPLE_FACTOR"), GAODownsampleFactor);
}
/** Default constructor. */
FUpdateHistoryDepthRejectionPS() {}
/** Initialization constructor. */
FUpdateHistoryDepthRejectionPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
SceneTextureParameters.Bind(Initializer);
AOParameters.Bind(Initializer.ParameterMap);
GeometryAwareUpsampleParameters.Bind(Initializer.ParameterMap);
BentNormalHistoryTexture.Bind(Initializer.ParameterMap, TEXT("BentNormalHistoryTexture"));
BentNormalHistorySampler.Bind(Initializer.ParameterMap, TEXT("BentNormalHistorySampler"));
HistoryWeight.Bind(Initializer.ParameterMap, TEXT("HistoryWeight"));
HistoryDistanceThreshold.Bind(Initializer.ParameterMap, TEXT("HistoryDistanceThreshold"));
UseHistoryFilter.Bind(Initializer.ParameterMap, TEXT("UseHistoryFilter"));
VelocityTexture.Bind(Initializer.ParameterMap, TEXT("VelocityTexture"));
VelocityTextureSampler.Bind(Initializer.ParameterMap, TEXT("VelocityTextureSampler"));
HistoryScreenPositionScaleBias.Bind(Initializer.ParameterMap, TEXT("HistoryScreenPositionScaleBias"));
HistoryUVMinMax.Bind(Initializer.ParameterMap, TEXT("HistoryUVMinMax"));
}
void SetParameters(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const FIntRect& HistoryViewRect,
FSceneRenderTargetItem& DistanceFieldNormal,
FSceneRenderTargetItem& DistanceFieldAOBentNormal,
FSceneRenderTargetItem& BentNormalHistoryTextureValue,
IPooledRenderTarget* VelocityTextureValue,
const FDistanceFieldAOParameters& Parameters)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, ShaderRHI, View.ViewUniformBuffer);
SceneTextureParameters.Set(RHICmdList, ShaderRHI, View.FeatureLevel, ESceneTextureSetupMode::All);
AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
GeometryAwareUpsampleParameters.Set(RHICmdList, ShaderRHI, View, DistanceFieldNormal, DistanceFieldAOBentNormal);
SetTextureParameter(
RHICmdList,
ShaderRHI,
BentNormalHistoryTexture,
BentNormalHistorySampler,
TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
BentNormalHistoryTextureValue.ShaderResourceTexture
);
SetShaderValue(RHICmdList, ShaderRHI, HistoryWeight, GAOHistoryWeight);
SetShaderValue(RHICmdList, ShaderRHI, HistoryDistanceThreshold, GAOHistoryDistanceThreshold);
SetShaderValue(RHICmdList, ShaderRHI, UseHistoryFilter, UseAOHistoryStabilityPass() ? 1.0f : 0.0f);
SetTextureParameter(
RHICmdList,
ShaderRHI,
VelocityTexture,
VelocityTextureSampler,
TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
VelocityTextureValue ? VelocityTextureValue->GetRenderTargetItem().ShaderResourceTexture : GBlackTexture->TextureRHI
);
{
FIntPoint HistoryBufferSize = FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY() / FIntPoint(GAODownsampleFactor, GAODownsampleFactor);
const float InvBufferSizeX = 1.0f / HistoryBufferSize.X;
const float InvBufferSizeY = 1.0f / HistoryBufferSize.Y;
const FVector4 HistoryScreenPositionScaleBiasValue(
HistoryViewRect.Width() * InvBufferSizeX / +2.0f,
HistoryViewRect.Height() * InvBufferSizeY / (-2.0f * GProjectionSignY),
(HistoryViewRect.Height() / 2.0f + HistoryViewRect.Min.Y) * InvBufferSizeY,
(HistoryViewRect.Width() / 2.0f + HistoryViewRect.Min.X) * InvBufferSizeX);
// Pull in the max UV to exclude the region which will read outside the viewport due to bilinear filtering
const FVector4 HistoryUVMinMaxValue(
(HistoryViewRect.Min.X + 0.5f) * InvBufferSizeX,
(HistoryViewRect.Min.Y + 0.5f) * InvBufferSizeY,
(HistoryViewRect.Max.X - 0.5f) * InvBufferSizeX,
(HistoryViewRect.Max.Y - 0.5f) * InvBufferSizeY);
SetShaderValue(RHICmdList, ShaderRHI, HistoryScreenPositionScaleBias, HistoryScreenPositionScaleBiasValue);
SetShaderValue(RHICmdList, ShaderRHI, HistoryUVMinMax, HistoryUVMinMaxValue);
}
}
// FShader interface.
virtual bool Serialize(FArchive& Ar)
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << SceneTextureParameters;
Ar << AOParameters;
Ar << GeometryAwareUpsampleParameters;
Ar << BentNormalHistoryTexture;
Ar << BentNormalHistorySampler;
Ar << HistoryWeight;
Ar << HistoryDistanceThreshold;
Ar << UseHistoryFilter;
Ar << VelocityTexture;
Ar << VelocityTextureSampler;
Ar << HistoryScreenPositionScaleBias;
Ar << HistoryUVMinMax;
return bShaderHasOutdatedParameters;
}
private:
FSceneTextureShaderParameters SceneTextureParameters;
FAOParameters AOParameters;
FGeometryAwareUpsampleParameters GeometryAwareUpsampleParameters;
FShaderResourceParameter BentNormalHistoryTexture;
FShaderResourceParameter BentNormalHistorySampler;
FShaderParameter HistoryWeight;
FShaderParameter HistoryDistanceThreshold;
FShaderParameter UseHistoryFilter;
FShaderResourceParameter VelocityTexture;
FShaderResourceParameter VelocityTextureSampler;
FShaderParameter HistoryScreenPositionScaleBias;
FShaderParameter HistoryUVMinMax;
};
IMPLEMENT_SHADER_TYPE(, FUpdateHistoryDepthRejectionPS,TEXT("/Engine/Private/DistanceFieldLightingPost.usf"),TEXT("UpdateHistoryDepthRejectionPS"),SF_Pixel);
template<bool bManuallyClampUV>
class TFilterHistoryPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(TFilterHistoryPS, Global);
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldAO(Parameters.Platform) && IsUsingDistanceFields(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("DOWNSAMPLE_FACTOR"), GAODownsampleFactor);
OutEnvironment.SetDefine(TEXT("MANUALLY_CLAMP_UV"), bManuallyClampUV);
}
/** Default constructor. */
TFilterHistoryPS() {}
/** Initialization constructor. */
TFilterHistoryPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
BentNormalAOTexture.Bind(Initializer.ParameterMap, TEXT("BentNormalAOTexture"));
BentNormalAOSampler.Bind(Initializer.ParameterMap, TEXT("BentNormalAOSampler"));
HistoryWeight.Bind(Initializer.ParameterMap, TEXT("HistoryWeight"));
BentNormalAOTexelSize.Bind(Initializer.ParameterMap, TEXT("BentNormalAOTexelSize"));
MaxSampleBufferUV.Bind(Initializer.ParameterMap, TEXT("MaxSampleBufferUV"));
DistanceFieldNormalTexture.Bind(Initializer.ParameterMap, TEXT("DistanceFieldNormalTexture"));
DistanceFieldNormalSampler.Bind(Initializer.ParameterMap, TEXT("DistanceFieldNormalSampler"));
}
void SetParameters(
FRHICommandList& RHICmdList,
const FViewInfo& View,
FSceneRenderTargetItem& DistanceFieldNormal,
FSceneRenderTargetItem& BentNormalHistoryTextureValue)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, ShaderRHI, View.ViewUniformBuffer);
SetTextureParameter(
RHICmdList,
ShaderRHI,
BentNormalAOTexture,
BentNormalAOSampler,
TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
BentNormalHistoryTextureValue.ShaderResourceTexture
);
SetTextureParameter(
RHICmdList,
ShaderRHI,
DistanceFieldNormalTexture,
DistanceFieldNormalSampler,
TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(),
DistanceFieldNormal.ShaderResourceTexture
);
SetShaderValue(RHICmdList, ShaderRHI, HistoryWeight, GAOHistoryWeight);
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
const FIntPoint DownsampledBufferSize(SceneContext.GetBufferSizeXY() / FIntPoint(GAODownsampleFactor, GAODownsampleFactor));
const FVector2D BaseLevelTexelSizeValue(1.0f / DownsampledBufferSize.X, 1.0f / DownsampledBufferSize.Y);
SetShaderValue(RHICmdList, ShaderRHI, BentNormalAOTexelSize, BaseLevelTexelSizeValue);
if (bManuallyClampUV)
{
FVector2D MaxSampleBufferUVValue(
(View.ViewRect.Width() / GAODownsampleFactor - 0.5f - GAODownsampleFactor) / DownsampledBufferSize.X,
(View.ViewRect.Height() / GAODownsampleFactor - 0.5f - GAODownsampleFactor) / DownsampledBufferSize.Y);
SetShaderValue(RHICmdList, ShaderRHI, MaxSampleBufferUV, MaxSampleBufferUVValue);
}
}
// FShader interface.
virtual bool Serialize(FArchive& Ar)
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << BentNormalAOTexture;
Ar << BentNormalAOSampler;
Ar << HistoryWeight;
Ar << BentNormalAOTexelSize;
Ar << MaxSampleBufferUV;
Ar << DistanceFieldNormalTexture;
Ar << DistanceFieldNormalSampler;
return bShaderHasOutdatedParameters;
}
private:
FShaderResourceParameter BentNormalAOTexture;
FShaderResourceParameter BentNormalAOSampler;
FShaderParameter HistoryWeight;
FShaderParameter BentNormalAOTexelSize;
FShaderParameter MaxSampleBufferUV;
FShaderResourceParameter DistanceFieldNormalTexture;
FShaderResourceParameter DistanceFieldNormalSampler;
};
#define VARIATION1(A) \
typedef TFilterHistoryPS<A> TFilterHistoryPS##A; \
IMPLEMENT_SHADER_TYPE(template<>,TFilterHistoryPS##A,TEXT("/Engine/Private/DistanceFieldLightingPost.usf"),TEXT("FilterHistoryPS"),SF_Pixel);
VARIATION1(false)
VARIATION1(true)
#undef VARIATION1
class FGeometryAwareUpsamplePS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FGeometryAwareUpsamplePS, Global);
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldAO(Parameters.Platform) && IsUsingDistanceFields(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("DOWNSAMPLE_FACTOR"), GAODownsampleFactor);
}
/** Default constructor. */
FGeometryAwareUpsamplePS() {}
/** Initialization constructor. */
FGeometryAwareUpsamplePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
AOParameters.Bind(Initializer.ParameterMap);
GeometryAwareUpsampleParameters.Bind(Initializer.ParameterMap);
}
void SetParameters(
FRHICommandList& RHICmdList,
const FViewInfo& View,
FSceneRenderTargetItem& DistanceFieldNormal,
FSceneRenderTargetItem& DistanceFieldAOBentNormal,
const FDistanceFieldAOParameters& Parameters)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, ShaderRHI, View.ViewUniformBuffer);
AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
GeometryAwareUpsampleParameters.Set(RHICmdList, ShaderRHI, View, DistanceFieldNormal, DistanceFieldAOBentNormal);
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << AOParameters;
Ar << GeometryAwareUpsampleParameters;
return bShaderHasOutdatedParameters;
}
private:
FAOParameters AOParameters;
FGeometryAwareUpsampleParameters GeometryAwareUpsampleParameters;
};
IMPLEMENT_SHADER_TYPE(,FGeometryAwareUpsamplePS, TEXT("/Engine/Private/DistanceFieldLightingPost.usf"), TEXT("GeometryAwareUpsamplePS"), SF_Pixel);
void AllocateOrReuseAORenderTarget(FRHICommandList& RHICmdList, TRefCountPtr<IPooledRenderTarget>& Target, const TCHAR* Name, EPixelFormat Format, uint32 Flags)
{
if (!Target)
{
FIntPoint BufferSize = GetBufferSizeForAO();
FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(BufferSize, Format, FClearValueBinding::None, Flags, TexCreate_RenderTargetable | TexCreate_UAV, false));
Desc.AutoWritable = false;
GRenderTargetPool.FindFreeElement(RHICmdList, Desc, Target, Name, true, ERenderTargetTransience::NonTransient);
}
}
void GeometryAwareUpsample(FRHICommandList& RHICmdList, const FViewInfo& View, TRefCountPtr<IPooledRenderTarget>& DistanceFieldAOBentNormal, FSceneRenderTargetItem& DistanceFieldNormal, FSceneRenderTargetItem& BentNormalInterpolation, const FDistanceFieldAOParameters& Parameters)
{
SCOPED_DRAW_EVENT(RHICmdList, GeometryAwareUpsample);
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
FRHIRenderPassInfo RPInfo(DistanceFieldAOBentNormal->GetRenderTargetItem().TargetableTexture, ERenderTargetActions::Load_Store);
RHICmdList.BeginRenderPass(RPInfo, TEXT("GeometryAwareUpsample"));
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
{
RHICmdList.SetViewport(0, 0, 0.0f, View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor, 1.0f);
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
TShaderMapRef<FPostProcessVS> VertexShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
TShaderMapRef<FGeometryAwareUpsamplePS> PixelShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
PixelShader->SetParameters(RHICmdList, View, DistanceFieldNormal, BentNormalInterpolation, Parameters);
VertexShader->SetParameters(RHICmdList, View.ViewUniformBuffer);
DrawRectangle(
RHICmdList,
0, 0,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
0, 0,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
FIntPoint(View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor),
SceneContext.GetBufferSizeXY() / FIntPoint(GAODownsampleFactor, GAODownsampleFactor),
*VertexShader);
}
RHICmdList.EndRenderPass();
RHICmdList.CopyToResolveTarget(DistanceFieldAOBentNormal->GetRenderTargetItem().TargetableTexture, DistanceFieldAOBentNormal->GetRenderTargetItem().ShaderResourceTexture, FResolveParams());
}
void UpdateHistory(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const TCHAR* BentNormalHistoryRTName,
IPooledRenderTarget* VelocityTexture,
FSceneRenderTargetItem& DistanceFieldNormal,
FSceneRenderTargetItem& BentNormalInterpolation,
/** Contains last frame's history, if non-NULL. This will be updated with the new frame's history. */
FIntRect* DistanceFieldAOHistoryViewRect,
TRefCountPtr<IPooledRenderTarget>* BentNormalHistoryState,
/** Output of Temporal Reprojection for the next step in the pipeline. */
TRefCountPtr<IPooledRenderTarget>& BentNormalHistoryOutput,
const FDistanceFieldAOParameters& Parameters)
{
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
if (BentNormalHistoryState && GAOUseHistory)
{
FIntPoint BufferSize = GetBufferSizeForAO();
if (*BentNormalHistoryState
&& !View.bCameraCut
&& !View.bPrevTransformsReset
&& !GAOClearHistory
// If the scene render targets reallocate, toss the history so we don't read uninitialized data
&& (*BentNormalHistoryState)->GetDesc().Extent == BufferSize)
{
uint32 HistoryPassOutputFlags = UseAOHistoryStabilityPass() ? GFastVRamConfig.DistanceFieldAOHistory : 0;
// Reuse a render target from the pool with a consistent name, for vis purposes
TRefCountPtr<IPooledRenderTarget> NewBentNormalHistory;
AllocateOrReuseAORenderTarget(RHICmdList, NewBentNormalHistory, BentNormalHistoryRTName, PF_FloatRGBA, HistoryPassOutputFlags);
SCOPED_DRAW_EVENT(RHICmdList, UpdateHistory);
{
FRHIRenderPassInfo RPInfo(NewBentNormalHistory->GetRenderTargetItem().TargetableTexture, ERenderTargetActions::Load_Store);
RHICmdList.BeginRenderPass(RPInfo, TEXT("UpdateHistory"));
{
RHICmdList.SetViewport(0, 0, 0.0f, View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor, 1.0f);
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
TShaderMapRef<FPostProcessVS> VertexShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
TShaderMapRef<FUpdateHistoryDepthRejectionPS> PixelShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
PixelShader->SetParameters(RHICmdList, View, *DistanceFieldAOHistoryViewRect, DistanceFieldNormal, BentNormalInterpolation, (*BentNormalHistoryState)->GetRenderTargetItem(), VelocityTexture, Parameters);
VertexShader->SetParameters(RHICmdList, View.ViewUniformBuffer);
DrawRectangle(
RHICmdList,
0, 0,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
View.ViewRect.Min.X / GAODownsampleFactor, View.ViewRect.Min.Y / GAODownsampleFactor,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
FIntPoint(View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor),
SceneContext.GetBufferSizeXY() / FIntPoint(GAODownsampleFactor, GAODownsampleFactor),
*VertexShader);
}
RHICmdList.EndRenderPass();
RHICmdList.CopyToResolveTarget(NewBentNormalHistory->GetRenderTargetItem().TargetableTexture, NewBentNormalHistory->GetRenderTargetItem().ShaderResourceTexture, FResolveParams());
}
if (UseAOHistoryStabilityPass())
{
const FPooledRenderTargetDesc& HistoryDesc = (*BentNormalHistoryState)->GetDesc();
// Reallocate history if buffer sizes have changed
if (HistoryDesc.Extent != SceneContext.GetBufferSizeXY() / FIntPoint(GAODownsampleFactor, GAODownsampleFactor))
{
GRenderTargetPool.FreeUnusedResource(*BentNormalHistoryState);
*BentNormalHistoryState = NULL;
// Update the view state's render target reference with the new history
AllocateOrReuseAORenderTarget(RHICmdList, *BentNormalHistoryState, BentNormalHistoryRTName, PF_FloatRGBA);
}
FRHIRenderPassInfo RPInfo((*BentNormalHistoryState)->GetRenderTargetItem().TargetableTexture, ERenderTargetActions::Load_Store);
RHICmdList.BeginRenderPass(RPInfo, TEXT("UpdateHistoryStability"));
{
RHICmdList.SetViewport(0, 0, 0.0f, View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor, 1.0f);
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
TShaderMapRef<FPostProcessVS> VertexShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
if (View.ViewRect.Min == FIntPoint::ZeroValue && View.ViewRect.Max == SceneContext.GetBufferSizeXY())
{
TShaderMapRef<TFilterHistoryPS<false> > PixelShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
PixelShader->SetParameters(RHICmdList, View, DistanceFieldNormal, NewBentNormalHistory->GetRenderTargetItem());
}
else
{
TShaderMapRef<TFilterHistoryPS<true> > PixelShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
PixelShader->SetParameters(RHICmdList, View, DistanceFieldNormal, NewBentNormalHistory->GetRenderTargetItem());
}
VertexShader->SetParameters(RHICmdList, View.ViewUniformBuffer);
DrawRectangle(
RHICmdList,
0, 0,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
0, 0,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
FIntPoint(View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor),
SceneContext.GetBufferSizeXY() / FIntPoint(GAODownsampleFactor, GAODownsampleFactor),
*VertexShader);
}
RHICmdList.EndRenderPass();
RHICmdList.CopyToResolveTarget((*BentNormalHistoryState)->GetRenderTargetItem().TargetableTexture, (*BentNormalHistoryState)->GetRenderTargetItem().ShaderResourceTexture, FResolveParams());
BentNormalHistoryOutput = *BentNormalHistoryState;
}
else
{
// Update the view state's render target reference with the new history
*BentNormalHistoryState = NewBentNormalHistory;
BentNormalHistoryOutput = NewBentNormalHistory;
}
}
else
{
// Use the current frame's upscaled mask for next frame's history
TRefCountPtr<IPooledRenderTarget> DistanceFieldAOBentNormal;
AllocateOrReuseAORenderTarget(RHICmdList, DistanceFieldAOBentNormal, TEXT("DistanceFieldBentNormalAO"), PF_FloatRGBA, GFastVRamConfig.DistanceFieldAOBentNormal);
GeometryAwareUpsample(RHICmdList, View, DistanceFieldAOBentNormal, DistanceFieldNormal, BentNormalInterpolation, Parameters);
RHICmdList.CopyToResolveTarget(DistanceFieldAOBentNormal->GetRenderTargetItem().TargetableTexture, DistanceFieldAOBentNormal->GetRenderTargetItem().ShaderResourceTexture, FResolveParams());
*BentNormalHistoryState = DistanceFieldAOBentNormal;
BentNormalHistoryOutput = DistanceFieldAOBentNormal;
}
DistanceFieldAOHistoryViewRect->Min = FIntPoint::ZeroValue;
DistanceFieldAOHistoryViewRect->Max.X = View.ViewRect.Size().X / GAODownsampleFactor;
DistanceFieldAOHistoryViewRect->Max.Y = View.ViewRect.Size().Y / GAODownsampleFactor;
}
else
{
// Temporal reprojection is disabled or there is no view state - just upscale
TRefCountPtr<IPooledRenderTarget> DistanceFieldAOBentNormal;
AllocateOrReuseAORenderTarget(RHICmdList, DistanceFieldAOBentNormal, TEXT("DistanceFieldBentNormalAO"), PF_FloatRGBA, GFastVRamConfig.DistanceFieldAOBentNormal);
GeometryAwareUpsample(RHICmdList, View, DistanceFieldAOBentNormal, DistanceFieldNormal, BentNormalInterpolation, Parameters);
RHICmdList.CopyToResolveTarget(DistanceFieldAOBentNormal->GetRenderTargetItem().TargetableTexture, DistanceFieldAOBentNormal->GetRenderTargetItem().ShaderResourceTexture, FResolveParams());
BentNormalHistoryOutput = DistanceFieldAOBentNormal;
}
}
template<bool bModulateToSceneColor>
class TDistanceFieldAOUpsamplePS : public FGlobalShader
{
DECLARE_SHADER_TYPE(TDistanceFieldAOUpsamplePS, Global);
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldAO(Parameters.Platform) && IsUsingDistanceFields(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("MODULATE_SCENE_COLOR"), bModulateToSceneColor);
}
/** Default constructor. */
TDistanceFieldAOUpsamplePS() {}
/** Initialization constructor. */
TDistanceFieldAOUpsamplePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
SceneTextureParameters.Bind(Initializer);
DFAOUpsampleParameters.Bind(Initializer.ParameterMap);
MinIndirectDiffuseOcclusion.Bind(Initializer.ParameterMap,TEXT("MinIndirectDiffuseOcclusion"));
}
void SetParameters(FRHICommandList& RHICmdList, const FViewInfo& View, TRefCountPtr<IPooledRenderTarget>& DistanceFieldAOBentNormal)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, ShaderRHI, View.ViewUniformBuffer);
SceneTextureParameters.Set(RHICmdList, ShaderRHI, View.FeatureLevel, ESceneTextureSetupMode::All);
DFAOUpsampleParameters.Set(RHICmdList, ShaderRHI, View, DistanceFieldAOBentNormal);
FScene* Scene = (FScene*)View.Family->Scene;
const float MinOcclusion = Scene->SkyLight ? Scene->SkyLight->MinOcclusion : 0;
SetShaderValue(RHICmdList, ShaderRHI, MinIndirectDiffuseOcclusion, MinOcclusion);
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << SceneTextureParameters;
Ar << DFAOUpsampleParameters;
Ar << MinIndirectDiffuseOcclusion;
return bShaderHasOutdatedParameters;
}
private:
FSceneTextureShaderParameters SceneTextureParameters;
FDFAOUpsampleParameters DFAOUpsampleParameters;
FShaderParameter MinIndirectDiffuseOcclusion;
};
#define IMPLEMENT_UPSAMPLE_PS_TYPE(bModulateToSceneColor) \
typedef TDistanceFieldAOUpsamplePS<bModulateToSceneColor> TDistanceFieldAOUpsamplePS##bModulateToSceneColor; \
IMPLEMENT_SHADER_TYPE(template<>,TDistanceFieldAOUpsamplePS##bModulateToSceneColor,TEXT("/Engine/Private/DistanceFieldLightingPost.usf"),TEXT("AOUpsamplePS"),SF_Pixel);
IMPLEMENT_UPSAMPLE_PS_TYPE(false)
IMPLEMENT_UPSAMPLE_PS_TYPE(true)
void UpsampleBentNormalAO(
FRHICommandList& RHICmdList,
const TArray<FViewInfo>& Views,
TRefCountPtr<IPooledRenderTarget>& DistanceFieldAOBentNormal,
bool bModulateSceneColor)
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
const FViewInfo& View = Views[ViewIndex];
SCOPED_DRAW_EVENT(RHICmdList, UpsampleAO);
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
if (bModulateSceneColor)
{
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGB, BO_Add, BF_DestColor, BF_Zero, BO_Add, BF_Zero, BF_One>::GetRHI();
}
else
{
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
}
TShaderMapRef<FPostProcessVS> VertexShader(View.ShaderMap);
if (bModulateSceneColor)
{
TShaderMapRef<TDistanceFieldAOUpsamplePS<true> > PixelShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
PixelShader->SetParameters(RHICmdList, View, DistanceFieldAOBentNormal);
}
else
{
TShaderMapRef<TDistanceFieldAOUpsamplePS<false> > PixelShader(View.ShaderMap);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
PixelShader->SetParameters(RHICmdList, View, DistanceFieldAOBentNormal);
}
DrawRectangle(
RHICmdList,
0, 0,
View.ViewRect.Width(), View.ViewRect.Height(),
View.ViewRect.Min.X / GAODownsampleFactor, View.ViewRect.Min.Y / GAODownsampleFactor,
View.ViewRect.Width() / GAODownsampleFactor, View.ViewRect.Height() / GAODownsampleFactor,
FIntPoint(View.ViewRect.Width(), View.ViewRect.Height()),
GetBufferSizeForAO(),
*VertexShader);
}
}