Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/DistanceFieldVisualization.cpp
tiago costa 7503b52da0 Updated most of distance field ambient occlusion codepath to use RDG.
- Resource state transitions handled by RDG.
- FDistanceFieldObjectBufferResource replaced by FDistanceFieldCulledObjectBufferParameters to use RDG.
- FTileIntersectionResources replaced by FTileIntersectionParameters to use RDG.
- FAOScreenGridResources replaced by FAOScreenGridParameters to use RDG.
- Don't store DFAO resources in View.State.
- Split FDeferredShadingSceneRenderer::RenderDistanceFieldAOScreenGrid() into multiple passes.
- Split BuildTileObjectLists() into multiple passes.

#rb daniel.wright

[CL 16660080 by tiago costa in ue5-main branch]
2021-06-14 12:45:34 -04:00

210 lines
9.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
DistanceFieldVisualization.cpp
=============================================================================*/
#include "DistanceFieldAmbientOcclusion.h"
#include "DeferredShadingRenderer.h"
#include "PostProcess/PostProcessing.h"
#include "PostProcess/SceneFilterRendering.h"
#include "DistanceFieldLightingShared.h"
#include "ScreenRendering.h"
#include "DistanceFieldLightingPost.h"
#include "OneColorShader.h"
#include "GlobalDistanceField.h"
#include "FXSystem.h"
#include "PostProcess/PostProcessSubsurface.h"
#include "PipelineStateCache.h"
class FVisualizeMeshDistanceFieldCS : public FGlobalShader
{
public:
DECLARE_GLOBAL_SHADER(FVisualizeMeshDistanceFieldCS);
class FUseGlobalDistanceFieldDim : SHADER_PERMUTATION_BOOL("USE_GLOBAL_DISTANCE_FIELD");
using FPermutationDomain = TShaderPermutationDomain<FUseGlobalDistanceFieldDim>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_REF(FForwardLightData, ForwardLightData)
SHADER_PARAMETER_STRUCT_REF(FReflectionUniformParameters, ReflectionStruct)
SHADER_PARAMETER_STRUCT_INCLUDE(FDistanceFieldCulledObjectBufferParameters, DistanceFieldCulledObjectBuffers)
SHADER_PARAMETER_STRUCT_INCLUDE(FDistanceFieldAtlasParameters, DistanceFieldAtlas)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTextures)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, RWVisualizeMeshDistanceFields)
SHADER_PARAMETER(FVector2D, NumGroups)
END_SHADER_PARAMETER_STRUCT()
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("THREADGROUP_SIZEX"), GDistanceFieldAOTileSizeX);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GDistanceFieldAOTileSizeY);
}
FVisualizeMeshDistanceFieldCS() = default;
FVisualizeMeshDistanceFieldCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
BindForLegacyShaderParameters<FParameters>(this, Initializer.PermutationId, Initializer.ParameterMap);
AOParameters.Bind(Initializer.ParameterMap);
GlobalDistanceFieldParameters.Bind(Initializer.ParameterMap);
}
void SetParameters(
FRHICommandList& RHICmdList,
const FDistanceFieldAOParameters& Parameters,
const FGlobalDistanceFieldInfo& GlobalDistanceFieldInfo)
{
FRHIComputeShader* ShaderRHI = RHICmdList.GetBoundComputeShader();
AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
if (GlobalDistanceFieldParameters.IsBound())
{
GlobalDistanceFieldParameters.Set(RHICmdList, ShaderRHI, GlobalDistanceFieldInfo.ParameterData);
}
}
private:
LAYOUT_FIELD(FAOParameters, AOParameters);
LAYOUT_FIELD(FGlobalDistanceFieldParameters, GlobalDistanceFieldParameters);
};
IMPLEMENT_GLOBAL_SHADER(FVisualizeMeshDistanceFieldCS, "/Engine/Private/DistanceFieldVisualization.usf", "VisualizeMeshDistanceFieldCS", SF_Compute);
class FVisualizeDistanceFieldUpsamplePS : public FGlobalShader
{
public:
DECLARE_GLOBAL_SHADER(FVisualizeDistanceFieldUpsamplePS);
SHADER_USE_PARAMETER_STRUCT(FVisualizeDistanceFieldUpsamplePS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTextures)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, VisualizeDistanceFieldTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, VisualizeDistanceFieldSampler)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
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);
}
};
IMPLEMENT_GLOBAL_SHADER(FVisualizeDistanceFieldUpsamplePS, "/Engine/Private/DistanceFieldVisualization.usf", "VisualizeDistanceFieldUpsamplePS", SF_Pixel);
void FDeferredShadingSceneRenderer::RenderMeshDistanceFieldVisualization(
FRDGBuilder& GraphBuilder,
const FMinimalSceneTextures& SceneTextures,
const FDistanceFieldAOParameters& Parameters)
{
const FViewInfo& FirstView = Views[0];
if (!UseDistanceFieldAO()
|| FeatureLevel < ERHIFeatureLevel::SM5
|| !DoesPlatformSupportDistanceFieldAO(FirstView.GetShaderPlatform())
|| Scene->DistanceFieldSceneData.NumObjectsInBuffer == 0)
{
return;
}
check(!Scene->DistanceFieldSceneData.HasPendingOperations());
QUICK_SCOPE_CYCLE_COUNTER(STAT_AOIssueGPUWork);
const bool bUseGlobalDistanceField = UseGlobalDistanceField(Parameters) && FirstView.Family->EngineShowFlags.VisualizeGlobalDistanceField;
RDG_EVENT_SCOPE(GraphBuilder, "VisualizeMeshDistanceFields");
FRDGTextureRef VisualizeResultTexture = nullptr;
{
const FIntPoint BufferSize = GetBufferSizeForAO();
const FRDGTextureDesc Desc(FRDGTextureDesc::Create2D(BufferSize, PF_FloatRGBA, FClearValueBinding::None, TexCreate_RenderTargetable | TexCreate_UAV));
VisualizeResultTexture = GraphBuilder.CreateTexture(Desc, TEXT("VisualizeDistanceField"));
}
FVisualizeMeshDistanceFieldCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FVisualizeMeshDistanceFieldCS::FUseGlobalDistanceFieldDim>(bUseGlobalDistanceField);
TShaderMapRef<FVisualizeMeshDistanceFieldCS> ComputeShader(FirstView.ShaderMap, PermutationVector);
for (const FViewInfo& View : Views)
{
check(!bUseGlobalDistanceField || View.GlobalDistanceFieldInfo.Clipmaps.Num() > 0);
FRDGBufferRef ObjectIndirectArguments = nullptr;
FDistanceFieldCulledObjectBufferParameters CulledObjectBufferParameters;
AllocateDistanceFieldCulledObjectBuffers(
GraphBuilder,
false,
FMath::DivideAndRoundUp(Scene->DistanceFieldSceneData.NumObjectsInBuffer, 256) * 256,
DFPT_SignedDistanceField,
ObjectIndirectArguments,
CulledObjectBufferParameters);
CullObjectsToView(GraphBuilder, Scene, View, Parameters, CulledObjectBufferParameters);
uint32 GroupSizeX = FMath::DivideAndRoundUp(View.ViewRect.Size().X / GAODownsampleFactor, GDistanceFieldAOTileSizeX);
uint32 GroupSizeY = FMath::DivideAndRoundUp(View.ViewRect.Size().Y / GAODownsampleFactor, GDistanceFieldAOTileSizeY);
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
auto* PassParameters = GraphBuilder.AllocParameters<FVisualizeMeshDistanceFieldCS::FParameters>();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ForwardLightData = View.ForwardLightingResources->ForwardLightDataUniformBuffer;
PassParameters->ReflectionStruct = CreateReflectionUniformBuffer(View, UniformBuffer_MultiFrame);
PassParameters->DistanceFieldCulledObjectBuffers = CulledObjectBufferParameters;
PassParameters->DistanceFieldAtlas = DistanceField::SetupAtlasParameters(Scene->DistanceFieldSceneData);
PassParameters->NumGroups = FVector2D(GroupSizeX, GroupSizeY);
PassParameters->SceneTextures = SceneTextures.UniformBuffer;
PassParameters->RWVisualizeMeshDistanceFields = GraphBuilder.CreateUAV(VisualizeResultTexture);
ClearUnusedGraphResources(ComputeShader, PassParameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("VisualizeMeshDistanceFieldCS"),
PassParameters,
ERDGPassFlags::Compute,
[&View, Parameters, ComputeShader, PassParameters, GroupSizeX, GroupSizeY](FRHICommandList& RHICmdList)
{
FRHIComputeShader* ShaderRHI = ComputeShader.GetComputeShader();
RHICmdList.SetComputeShader(ComputeShader.GetComputeShader());
SetShaderParameters(RHICmdList, ComputeShader, ShaderRHI, *PassParameters);
ComputeShader->SetParameters(RHICmdList, Parameters, View.GlobalDistanceFieldInfo);
DispatchComputeShader(RHICmdList, ComputeShader.GetShader(), GroupSizeX, GroupSizeY, 1);
UnsetShaderUAVs(RHICmdList, ComputeShader, ShaderRHI);
});
}
TShaderMapRef<FVisualizeDistanceFieldUpsamplePS> PixelShader(FirstView.ShaderMap);
for (const FViewInfo& View : Views)
{
auto* PassParameters = GraphBuilder.AllocParameters<FVisualizeDistanceFieldUpsamplePS::FParameters>();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTextures = SceneTextures.UniformBuffer;
PassParameters->VisualizeDistanceFieldTexture = VisualizeResultTexture;
PassParameters->VisualizeDistanceFieldSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextures.Color.Target, ERenderTargetLoadAction::ELoad);
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(SceneTextures.Depth.Target, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilRead);
const FScreenPassTextureViewport InputViewport(VisualizeResultTexture, GetDownscaledRect(View.ViewRect, GAODownsampleFactor));
const FScreenPassTextureViewport OutputViewport(SceneTextures.Color.Target, View.ViewRect);
AddDrawScreenPass(GraphBuilder, {}, View, OutputViewport, InputViewport, PixelShader, PassParameters);
}
}