Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessDownsample.cpp
guillaume abadie cffaa1fe82 Replaces r.Bloom.HalfResConvolution with r.Bloom.ScreenPercentage
#rb none
#jira none
#preflight 61ae42868358693a22c276d0

#ROBOMERGE-AUTHOR: guillaume.abadie
#ROBOMERGE-SOURCE: CL 18385314 in //UE5/Release-5.0/... via CL 18385332
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469)

[CL 18385358 by guillaume abadie in ue5-release-engine-test branch]
2021-12-06 13:45:02 -05:00

238 lines
8.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PostProcess/PostProcessDownsample.h"
#include "PostProcess/PostProcessEyeAdaptation.h"
#include "PixelShaderUtils.h"
namespace
{
const int32 GDownsampleTileSizeX = 8;
const int32 GDownsampleTileSizeY = 8;
BEGIN_SHADER_PARAMETER_STRUCT(FDownsampleParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, Input)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, Output)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, InputSampler)
END_SHADER_PARAMETER_STRUCT()
FDownsampleParameters GetDownsampleParameters(const FViewInfo& View, FScreenPassTexture Output, FScreenPassTexture Input, EDownsampleQuality DownsampleMethod)
{
check(Output.IsValid());
check(Input.IsValid());
const FScreenPassTextureViewportParameters InputParameters = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(Input));
const FScreenPassTextureViewportParameters OutputParameters = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(Output));
FDownsampleParameters Parameters;
Parameters.ViewUniformBuffer = View.ViewUniformBuffer;
Parameters.Input = InputParameters;
Parameters.Output = OutputParameters;
Parameters.InputTexture = Input.Texture;
Parameters.InputSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
return Parameters;
}
class FDownsampleQualityDimension : SHADER_PERMUTATION_ENUM_CLASS("DOWNSAMPLE_QUALITY", EDownsampleQuality);
using FDownsamplePermutationDomain = TShaderPermutationDomain<FDownsampleQualityDimension>;
class FDownsamplePS : public FGlobalShader
{
public:
DECLARE_GLOBAL_SHADER(FDownsamplePS);
SHADER_USE_PARAMETER_STRUCT(FDownsamplePS, FGlobalShader);
using FPermutationDomain = FDownsamplePermutationDomain;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FDownsampleParameters, Common)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return true;
}
};
IMPLEMENT_GLOBAL_SHADER(FDownsamplePS, "/Engine/Private/PostProcessDownsample.usf", "MainPS", SF_Pixel);
class FDownsampleCS : public FGlobalShader
{
public:
DECLARE_GLOBAL_SHADER(FDownsampleCS);
SHADER_USE_PARAMETER_STRUCT(FDownsampleCS, FGlobalShader);
using FPermutationDomain = FDownsamplePermutationDomain;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FDownsampleParameters, Common)
SHADER_PARAMETER(FScreenTransform, DispatchThreadIdToInputUV)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, OutComputeTexture)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters,OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEX"), GDownsampleTileSizeX);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GDownsampleTileSizeY);
}
};
IMPLEMENT_GLOBAL_SHADER(FDownsampleCS, "/Engine/Private/PostProcessDownsample.usf", "MainCS", SF_Compute);
} //! namespace
FScreenPassTexture AddDownsamplePass(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FDownsamplePassInputs& Inputs)
{
check(Inputs.SceneColor.IsValid());
bool bIsComputePass = View.bUseComputePasses;
if ((Inputs.Flags & EDownsampleFlags::ForceRaster) == EDownsampleFlags::ForceRaster)
{
bIsComputePass = false;
}
FScreenPassRenderTarget Output;
// Construct the output texture to be half resolution (rounded up to even) with an optional format override.
{
FRDGTextureDesc Desc = Inputs.SceneColor.Texture->Desc;
Desc.Reset();
Desc.Extent = FIntPoint::DivideAndRoundUp(Desc.Extent, 2);
Desc.Extent.X = FMath::Max(1, Desc.Extent.X);
Desc.Extent.Y = FMath::Max(1, Desc.Extent.Y);
Desc.Flags &= ~(TexCreate_RenderTargetable | TexCreate_UAV | TexCreate_Presentable);
Desc.Flags |= bIsComputePass ? TexCreate_UAV : TexCreate_RenderTargetable;
Desc.Flags |= GFastVRamConfig.Downsample;
Desc.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 0));
if (Inputs.FormatOverride != PF_Unknown)
{
Desc.Format = Inputs.FormatOverride;
}
if (Inputs.UserSuppliedOutput && Translate(Inputs.UserSuppliedOutput->GetDesc()) == Desc)
{
Output.Texture = GraphBuilder.RegisterExternalTexture(Inputs.UserSuppliedOutput, Inputs.Name);
}
else
{
Output.Texture = GraphBuilder.CreateTexture(Desc, Inputs.Name);
}
Output.ViewRect = FIntRect::DivideAndRoundUp(Inputs.SceneColor.ViewRect, 2);
Output.LoadAction = ERenderTargetLoadAction::ENoAction;
}
if (bIsComputePass)
{
AddDownsampleComputePass(GraphBuilder, View, Inputs.SceneColor, Output, Inputs.Quality, bIsComputePass ? ERDGPassFlags::Compute : ERDGPassFlags::Raster);
}
else
{
FDownsamplePermutationDomain PermutationVector;
PermutationVector.Set<FDownsampleQualityDimension>(Inputs.Quality);
FDownsamplePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FDownsamplePS::FParameters>();
PassParameters->Common = GetDownsampleParameters(View, Output, Inputs.SceneColor, Inputs.Quality);
PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();
TShaderMapRef<FDownsamplePS> PixelShader(View.ShaderMap, PermutationVector);
FPixelShaderUtils::AddFullscreenPass(
GraphBuilder,
View.ShaderMap,
RDG_EVENT_NAME("Downsample(%s Quality=%s PS) %dx%d -> %dx%d",
Output.Texture->Name,
Inputs.Quality == EDownsampleQuality::High ? TEXT("High") : TEXT("Bilinear"),
Inputs.SceneColor.ViewRect.Width(), Inputs.SceneColor.ViewRect.Height(),
Output.ViewRect.Width(), Output.ViewRect.Height()),
PixelShader,
PassParameters,
Output.ViewRect);
}
return MoveTemp(Output);
}
void AddDownsampleComputePass(FRDGBuilder& GraphBuilder, const FViewInfo& View, FScreenPassTexture Input, FScreenPassTexture Output, EDownsampleQuality Quality, ERDGPassFlags PassFlags)
{
check(PassFlags == ERDGPassFlags::Compute || PassFlags == ERDGPassFlags::AsyncCompute);
FDownsampleCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FDownsampleCS::FParameters>();
PassParameters->Common = GetDownsampleParameters(View, Output, Input, Quality);
PassParameters->DispatchThreadIdToInputUV = ((FScreenTransform::Identity + 0.5f) / Output.ViewRect.Size()) * FScreenTransform::ChangeTextureBasisFromTo(FScreenPassTextureViewport(Input), FScreenTransform::ETextureBasis::ViewportUV, FScreenTransform::ETextureBasis::TextureUV);
PassParameters->OutComputeTexture = GraphBuilder.CreateUAV(Output.Texture);
FDownsamplePermutationDomain PermutationVector;
PermutationVector.Set<FDownsampleQualityDimension>(Quality);
TShaderMapRef<FDownsampleCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Downsample(%s Quality=%s CS) %dx%d -> %dx%d",
Output.Texture->Name,
Quality == EDownsampleQuality::High ? TEXT("High") : TEXT("Bilinear"),
Input.ViewRect.Width(), Input.ViewRect.Height(),
Output.ViewRect.Width(), Output.ViewRect.Height()),
PassFlags,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(Output.ViewRect.Size(), FIntPoint(GDownsampleTileSizeX, GDownsampleTileSizeY)));
}
void FSceneDownsampleChain::Init(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FEyeAdaptationParameters& EyeAdaptationParameters,
FScreenPassTexture HalfResolutionSceneColor,
EDownsampleQuality DownsampleQuality,
bool bLogLumaInAlpha)
{
check(HalfResolutionSceneColor.IsValid());
RDG_EVENT_SCOPE(GraphBuilder, "SceneDownsample");
static const TCHAR* PassNames[StageCount] =
{
nullptr,
TEXT("Scene(1/4)"),
TEXT("Scene(1/8)"),
TEXT("Scene(1/16)"),
TEXT("Scene(1/32)"),
TEXT("Scene(1/64)")
};
static_assert(UE_ARRAY_COUNT(PassNames) == StageCount, "PassNames size must equal StageCount");
// The first stage is the input.
Textures[0] = HalfResolutionSceneColor;
for (uint32 StageIndex = 1; StageIndex < StageCount; StageIndex++)
{
const uint32 PreviousStageIndex = StageIndex - 1;
FDownsamplePassInputs PassInputs;
PassInputs.Name = PassNames[StageIndex];
PassInputs.SceneColor = Textures[PreviousStageIndex];
PassInputs.Quality = DownsampleQuality;
Textures[StageIndex] = AddDownsamplePass(GraphBuilder, View, PassInputs);
if (bLogLumaInAlpha)
{
bLogLumaInAlpha = false;
Textures[StageIndex] = AddBasicEyeAdaptationSetupPass(GraphBuilder, View, EyeAdaptationParameters, Textures[StageIndex]);
}
}
bInitialized = true;
}