353 lines
14 KiB
C++
353 lines
14 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "PostProcess/TemporalAA.h"
|
|
#include "PostProcess/PostProcessing.h"
|
|
#include "ScenePrivate.h"
|
|
#include "ScreenPass.h"
|
|
#include "PixelShaderUtils.h"
|
|
#include "UnrealEngine.h"
|
|
#include "PostProcess/PostProcessMotionBlur.h"
|
|
#include "PostProcess/PostProcessVisualizeBuffer.h"
|
|
#include "PostProcess/VisualizeMotionVectors.h"
|
|
#include "VisualizeTexture.h"
|
|
|
|
|
|
FScreenPassTexture AddVisualizeTemporalUpscalerPass(FRDGBuilder& GraphBuilder, const FViewInfo& View, const FVisualizeTemporalUpscalerInputs& Inputs)
|
|
{
|
|
check(Inputs.SceneColor.IsValid());
|
|
|
|
RDG_EVENT_SCOPE(GraphBuilder, "VisualizeTemporalUpscaler %dx%d", Inputs.SceneColor.ViewRect.Width(), Inputs.SceneColor.ViewRect.Height());
|
|
|
|
const bool bSupportsAlpha = IsPostProcessingWithAlphaChannelSupported();
|
|
|
|
// Allocate output and copy
|
|
FScreenPassRenderTarget Output = Inputs.OverrideOutput;
|
|
if (!Output.IsValid())
|
|
{
|
|
Output = FScreenPassRenderTarget::CreateFromInput(GraphBuilder, Inputs.SceneColor, View.GetOverwriteLoadAction(), TEXT("MotionVectors.Visualize"));
|
|
}
|
|
|
|
// Populate all the tiles
|
|
TArray<FVisualizeBufferTile> Tiles;
|
|
Tiles.SetNum(16);
|
|
|
|
if (Inputs.TAAConfig != EMainTAAPassConfig::Disabled)
|
|
{
|
|
FScreenPassTexture OutputTexture;
|
|
if (Inputs.Outputs.FullRes.TextureSRV->Desc.Texture->Desc.IsTextureArray())
|
|
{
|
|
FRDGTextureDesc Desc = Inputs.Outputs.FullRes.TextureSRV->Desc.Texture->Desc;
|
|
Desc.Dimension = ETextureDimension::Texture2D;
|
|
Desc.ArraySize = 1;
|
|
Desc.NumMips = 1;
|
|
|
|
FRDGTextureRef NewTexture = GraphBuilder.CreateTexture(Desc, Inputs.Outputs.FullRes.TextureSRV->Desc.Texture->Name);
|
|
|
|
FRHICopyTextureInfo CopyInfo;
|
|
CopyInfo.SourceSliceIndex = Inputs.Outputs.FullRes.TextureSRV->Desc.FirstArraySlice;
|
|
|
|
AddCopyTexturePass(
|
|
GraphBuilder,
|
|
Inputs.Outputs.FullRes.TextureSRV->Desc.Texture,
|
|
NewTexture,
|
|
CopyInfo);
|
|
|
|
OutputTexture = FScreenPassTexture(NewTexture, Inputs.Outputs.FullRes.ViewRect);
|
|
}
|
|
else
|
|
{
|
|
OutputTexture = FScreenPassTexture(Inputs.Outputs.FullRes.TextureSRV->Desc.Texture, Inputs.Outputs.FullRes.ViewRect);
|
|
}
|
|
|
|
auto VisualizeTextureLabel = [](FRDGTextureRef Texture, const TCHAR* Suffix = TEXT(""))
|
|
{
|
|
return FString::Printf(TEXT("vis %s%s"), Texture->Name, Suffix);
|
|
};
|
|
|
|
auto CropViewRectToCenter = [](FIntRect ViewRect)
|
|
{
|
|
return FIntRect(ViewRect.Min + ViewRect.Size() / 4, ViewRect.Min + (ViewRect.Size() * 3) / 4);
|
|
};
|
|
|
|
// Depth buffer
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 0 + 0];
|
|
Tile.Input.Texture = FVisualizeTexture::AddVisualizeTexturePass(GraphBuilder, View.ShaderMap, Inputs.Inputs.SceneDepth.Texture);
|
|
Tile.Input.ViewRect = CropViewRectToCenter(View.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(Inputs.Inputs.SceneDepth.Texture);
|
|
}
|
|
|
|
// Scene Color
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 0 + 1];
|
|
Tile.Input = FScreenPassTexture(Inputs.Inputs.SceneColor.Texture, CropViewRectToCenter(View.ViewRect));
|
|
Tile.Label = VisualizeTextureLabel(Inputs.Inputs.SceneColor.Texture);
|
|
}
|
|
|
|
// Scene Color alpha
|
|
if (bSupportsAlpha)
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 3 + 1];
|
|
//Tile.Input = FScreenPassTexture(Inputs.Inputs.SceneColorTexture, CropViewRectToCenter(View.ViewRect));
|
|
Tile.Input.Texture = FVisualizeTexture::AddVisualizeTextureAlphaPass(GraphBuilder, View.ShaderMap, Inputs.Inputs.SceneColor.Texture);
|
|
Tile.Input.ViewRect = CropViewRectToCenter(View.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(Inputs.Inputs.SceneColor.Texture, TEXT(" A"));
|
|
}
|
|
|
|
// Translucency
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::TSR)
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 0 + 2];
|
|
if (Inputs.Inputs.PostDOFTranslucencyResources.IsValid())
|
|
{
|
|
Tile.Input.Texture = Inputs.Inputs.PostDOFTranslucencyResources.ColorTexture.Resolve;
|
|
Tile.Input.ViewRect = CropViewRectToCenter(Inputs.Inputs.PostDOFTranslucencyResources.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(Inputs.Inputs.PostDOFTranslucencyResources.ColorTexture.Resolve);
|
|
}
|
|
else
|
|
{
|
|
Tile.Input = FScreenPassTexture(GSystemTextures.GetBlackDummy(GraphBuilder));
|
|
Tile.Label = TEXT("No PostDOF Translucency!");
|
|
}
|
|
}
|
|
|
|
// Translucency alpha
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::TSR)
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 0 + 3];
|
|
if (Inputs.Inputs.PostDOFTranslucencyResources.IsValid())
|
|
{
|
|
Tile.Input.Texture = FVisualizeTexture::AddVisualizeTextureAlphaPass(GraphBuilder, View.ShaderMap, Inputs.Inputs.PostDOFTranslucencyResources.ColorTexture.Resolve);
|
|
Tile.Input.ViewRect = CropViewRectToCenter(Inputs.Inputs.PostDOFTranslucencyResources.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(Inputs.Inputs.PostDOFTranslucencyResources.ColorTexture.Resolve, TEXT(" A"));
|
|
}
|
|
else
|
|
{
|
|
Tile.Input = FScreenPassTexture(GSystemTextures.GetBlackDummy(GraphBuilder));
|
|
Tile.Label = TEXT("No PostDOF Translucency!");
|
|
}
|
|
}
|
|
|
|
// Motion blur
|
|
{
|
|
FMotionBlurInputs PassInputs;
|
|
PassInputs.SceneColor = Inputs.Outputs.FullRes;
|
|
PassInputs.SceneDepth = Inputs.Inputs.SceneDepth;
|
|
PassInputs.SceneVelocity = Inputs.Inputs.SceneVelocity;
|
|
PassInputs.LensDistortionLUT = Inputs.Inputs.LensDistortionLUT;
|
|
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 1 + 0];
|
|
Tile.Input = FScreenPassTexture(AddVisualizeMotionBlurPass(GraphBuilder, View, PassInputs));
|
|
Tile.Input.ViewRect = CropViewRectToCenter(Tile.Input.ViewRect);
|
|
Tile.Label = TEXT("show VisualizeMotionBlur");
|
|
}
|
|
|
|
// Reprojection
|
|
{
|
|
FVisualizeMotionVectorsInputs PassInputs;
|
|
PassInputs.SceneColor = Inputs.SceneColor;
|
|
PassInputs.SceneDepth = Inputs.Inputs.SceneDepth;
|
|
PassInputs.SceneVelocity = Inputs.Inputs.SceneVelocity;
|
|
PassInputs.LensDistortionLUT = Inputs.Inputs.LensDistortionLUT;
|
|
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 2 + 0];
|
|
Tile.Input = AddVisualizeMotionVectorsPass(GraphBuilder, View, PassInputs, EVisualizeMotionVectors::ReprojectionAlignment);
|
|
Tile.Input.ViewRect = CropViewRectToCenter(Tile.Input.ViewRect);
|
|
Tile.Label = TEXT("show VisualizeReprojection");
|
|
}
|
|
|
|
// Display TSR's luminance used for stability.
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::TSR)
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 1 + 3];
|
|
if (Inputs.Inputs.FlickeringInputTexture.IsValid())
|
|
{
|
|
Tile.Input = Inputs.Inputs.FlickeringInputTexture;
|
|
Tile.Input.ViewRect = CropViewRectToCenter(View.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(Inputs.Inputs.FlickeringInputTexture.Texture);
|
|
}
|
|
else
|
|
{
|
|
Tile.Input = FScreenPassTexture(GSystemTextures.GetBlackDummy(GraphBuilder));
|
|
Tile.Label = TEXT("No Moire Luma!");
|
|
}
|
|
}
|
|
|
|
// Display UMaterial::bHasPixelAnimation used to disable TSR's anti-flickering heuristic (r.TSR.ShadingRejection.Flickering) on per pixel basis
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::TSR)
|
|
{
|
|
FVisualizeMotionVectorsInputs PassInputs;
|
|
PassInputs.SceneColor = Inputs.SceneColor;
|
|
PassInputs.SceneDepth = Inputs.Inputs.SceneDepth;
|
|
PassInputs.SceneVelocity = Inputs.Inputs.SceneVelocity;
|
|
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 2 + 3];
|
|
Tile.Input = AddVisualizeMotionVectorsPass(GraphBuilder, View, PassInputs, EVisualizeMotionVectors::HasPixelAnimationFlag);
|
|
Tile.Input.ViewRect = CropViewRectToCenter(Tile.Input.ViewRect);
|
|
Tile.Label = TEXT("UMaterial::bHasPixelAnimation");
|
|
}
|
|
|
|
// Output
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 3 + 3];
|
|
Tile.Input.Texture = OutputTexture.Texture;
|
|
Tile.Input.ViewRect = CropViewRectToCenter(OutputTexture.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(OutputTexture.Texture);
|
|
}
|
|
|
|
// Output alpha
|
|
if (bSupportsAlpha)
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 3 + 2];
|
|
Tile.Input.Texture = FVisualizeTexture::AddVisualizeTextureAlphaPass(GraphBuilder, View.ShaderMap, OutputTexture.Texture);
|
|
Tile.Input.ViewRect = CropViewRectToCenter(OutputTexture.ViewRect);
|
|
Tile.Label = VisualizeTextureLabel(OutputTexture.Texture, TEXT(" A"));
|
|
}
|
|
|
|
// Black bottom left corner
|
|
{
|
|
FVisualizeBufferTile& Tile = Tiles[4 * 3 + 0];
|
|
Tile.Input = FScreenPassTexture(GSystemTextures.GetBlackDummy(GraphBuilder));
|
|
Tile.Label = TEXT("Summary");
|
|
}
|
|
}
|
|
|
|
// Draws all overview tiles
|
|
{
|
|
FVisualizeBufferInputs PassInputs;
|
|
PassInputs.OverrideOutput = Output;
|
|
PassInputs.SceneColor = Inputs.SceneColor;
|
|
PassInputs.Tiles = Tiles;
|
|
|
|
AddVisualizeBufferPass(GraphBuilder, View, PassInputs);
|
|
}
|
|
|
|
// Draw additional text
|
|
// Early return if not using a temporal upscaler.
|
|
if (Inputs.TAAConfig != EMainTAAPassConfig::Disabled)
|
|
{
|
|
AddDrawCanvasPass(GraphBuilder, RDG_EVENT_NAME("VisualizeTemporalUpscaler Text"), View, FScreenPassRenderTarget(Output, ERenderTargetLoadAction::ELoad),
|
|
[&View, &ViewRect = Output.ViewRect, &Inputs, bSupportsAlpha](FCanvas& Canvas)
|
|
{
|
|
const float DPIScale = Canvas.GetDPIScale();
|
|
Canvas.SetBaseTransform(FMatrix(FScaleMatrix(DPIScale) * Canvas.CalcBaseTransform2D(Canvas.GetViewRect().Width(), Canvas.GetViewRect().Height())));
|
|
|
|
auto QuickDrawSummary = [&](int32 Location, const FString& Text)
|
|
{
|
|
FIntPoint LabelLocation(20, 20 + 22 * Location + (ViewRect.Height() * 3) / 4);
|
|
Canvas.DrawShadowedString(LabelLocation.X / DPIScale, LabelLocation.Y / DPIScale, *Text, GetStatsFont(), FLinearColor::White);
|
|
};
|
|
|
|
// Display which temporal upscaler is being used.
|
|
{
|
|
static auto CVarAntiAliasingQuality = IConsoleManager::Get().FindConsoleVariable(TEXT("sg.AntiAliasingQuality"));
|
|
check(CVarAntiAliasingQuality);
|
|
|
|
FString Text;
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::TAA)
|
|
{
|
|
Text = FString::Printf(TEXT("TemporalUpscaler: TAA (sg.AntiAliasingQuality=%d)"), CVarAntiAliasingQuality->GetInt());
|
|
}
|
|
else if (Inputs.TAAConfig == EMainTAAPassConfig::TSR)
|
|
{
|
|
Text = FString::Printf(TEXT("TemporalUpscaler: TSR (sg.AntiAliasingQuality=%d)"), CVarAntiAliasingQuality->GetInt());
|
|
}
|
|
else
|
|
{
|
|
Text = FString::Printf(TEXT("ThirdParty TemporalUpscaler: %s"), Inputs.UpscalerUsed->GetDebugName());
|
|
}
|
|
QuickDrawSummary(/* Location = */ 0, Text);
|
|
}
|
|
|
|
// Display the input/output resolutions
|
|
{
|
|
QuickDrawSummary(/* Location = */ 1, FString::Printf(TEXT("Input: %dx%d %s"), View.ViewRect.Width(), View.ViewRect.Height(), GPixelFormats[Inputs.Inputs.SceneColor.Texture->Desc.Format].Name));
|
|
QuickDrawSummary(/* Location = */ 2, FString::Printf(TEXT("Output: %dx%d %s"), Inputs.Outputs.FullRes.ViewRect.Width(), Inputs.Outputs.FullRes.ViewRect.Height(), GPixelFormats[Inputs.Outputs.FullRes.TextureSRV->Desc.Texture->Desc.Format].Name));
|
|
}
|
|
|
|
// Display the pre-exposure being used
|
|
{
|
|
static auto CVarPreExposureOverride = IConsoleManager::Get().FindConsoleVariable(TEXT("r.EyeAdaptation.PreExposureOverride"));
|
|
check(CVarPreExposureOverride);
|
|
|
|
FString Text = FString::Printf(TEXT("PreExposure: %f"), View.PreExposure);
|
|
if (CVarPreExposureOverride->GetFloat() > 0.0f)
|
|
{
|
|
Text += TEXT(" (r.EyeAdaptation.PreExposureOverride)");
|
|
}
|
|
|
|
QuickDrawSummary(/* Location = */ 3, Text);
|
|
}
|
|
|
|
// Display alpha support
|
|
{
|
|
FString Text = bSupportsAlpha ? TEXT("r.PostProcessing.PropagateAlpha=true") : TEXT("r.PostProcessing.PropagateAlpha=false");
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::ThirdParty)
|
|
{
|
|
Text = TEXT("Unknown");
|
|
}
|
|
QuickDrawSummary(/* Location = */ 4, TEXT("Support Alpha: ") + Text);
|
|
}
|
|
|
|
// Display memory size of the history.
|
|
{
|
|
static auto CVarAntiAliasingQuality = IConsoleManager::Get().FindConsoleVariable(TEXT("sg.AntiAliasingQuality"));
|
|
check(CVarAntiAliasingQuality);
|
|
|
|
const uint64 PingPongHistorySizeMultiplier = 2;
|
|
uint64 HistorySize = 0;
|
|
if (Inputs.TAAConfig == EMainTAAPassConfig::TAA)
|
|
{
|
|
HistorySize = View.PrevViewInfo.TemporalAAHistory.GetGPUSizeBytes(/* bLogSizes = */ false) * PingPongHistorySizeMultiplier;
|
|
}
|
|
else if (Inputs.TAAConfig == EMainTAAPassConfig::TSR && View.PrevViewInfo.TSRHistory.IsValid())
|
|
{
|
|
HistorySize = View.PrevViewInfo.TSRHistory.GetGPUSizeBytes(/* bLogSizes = */ false);
|
|
|
|
bool bHasTSRHistoryResurrection = View.PrevViewInfo.TSRHistory.MetadataArray->GetDesc().ArraySize > 1;
|
|
bool bHasTSRPingPongHistory = !bHasTSRHistoryResurrection;
|
|
if (bHasTSRPingPongHistory)
|
|
{
|
|
HistorySize *= PingPongHistorySizeMultiplier;
|
|
}
|
|
}
|
|
else if (Inputs.TAAConfig == EMainTAAPassConfig::ThirdParty && View.PrevViewInfo.ThirdPartyTemporalUpscalerHistory.IsValid())
|
|
{
|
|
HistorySize = View.PrevViewInfo.ThirdPartyTemporalUpscalerHistory->GetGPUSizeBytes();
|
|
}
|
|
QuickDrawSummary(/* Location = */ 5, FString::Printf(TEXT("History VRAM footprint: %.1f MB"), float(HistorySize) / float(1024 * 1024)));
|
|
}
|
|
|
|
// Display if any additional sharpening is happening
|
|
{
|
|
static auto CVarSharpen = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Tonemapper.Sharpen"));
|
|
check(CVarSharpen);
|
|
float Sharpen = CVarSharpen->GetFloat();
|
|
Sharpen = (Sharpen < 0) ? View.FinalPostProcessSettings.Sharpen : Sharpen;
|
|
QuickDrawSummary(/* Location = */ 6, Sharpen > 0 ? FString::Printf(TEXT("Tonemapper Sharpen: %f"), Sharpen) : TEXT("Tonemapper Sharpen: Off"));
|
|
}
|
|
|
|
// Display if doing any lens distortion
|
|
{
|
|
QuickDrawSummary(/* Location = */ 7, View.LensDistortionLUT.IsEnabled() ? FString::Printf(TEXT("Lens Distortion: Enabled (%3.1f%% Additional Upscale)"), View.LensDistortionLUT.ResolutionFraction * 100.0f) : TEXT("Lens Distortion: Disabled"));
|
|
}
|
|
});
|
|
|
|
}
|
|
else
|
|
{
|
|
check(Inputs.TAAConfig == EMainTAAPassConfig::Disabled);
|
|
AddDrawCanvasPass(GraphBuilder, RDG_EVENT_NAME("VisualizeTemporalUpscaler Text"), View, FScreenPassRenderTarget(Output, ERenderTargetLoadAction::ELoad),
|
|
[&ViewRect = Output.ViewRect](FCanvas& Canvas)
|
|
{
|
|
const float DPIScale = Canvas.GetDPIScale();
|
|
Canvas.SetBaseTransform(FMatrix(FScaleMatrix(DPIScale) * Canvas.CalcBaseTransform2D(Canvas.GetViewRect().Width(), Canvas.GetViewRect().Height())));
|
|
|
|
FIntPoint LabelLocation(60, 60);
|
|
Canvas.DrawShadowedString(LabelLocation.X / DPIScale, LabelLocation.Y / DPIScale, TEXT("No temporal upscaler used"), GetStatsFont(), FLinearColor::Red);
|
|
});
|
|
}
|
|
|
|
return MoveTemp(Output);
|
|
}
|