[UE4]Deferred Shading Renderer Notes
Keywords: UE4, Deferred Shading Renderer, Multipass
Shading Model
Documents
Real Shading in Unreal Engine 4 (BRDF)
Multipass
Documents
Content-Driven Multipass Rendering in UE4 | GDC 2017 | Unreal Engine
https://www.youtube.com/watch?v=QGIKrD7uHu8
Render Thread
Callstack in engine source
Entrance of tick function on Deffered Shading Rendering: void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)
.
Engine\Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp
UE4Editor-Renderer.dll!FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate & RHICmdList) Line 1263 C++
UE4Editor-Renderer.dll!RenderViewFamily_RenderThread(FRHICommandListImmediate & RHICmdList, FSceneRenderer * SceneRenderer) Line 3581 C++
[Inline Frame] UE4Editor-Renderer.dll!FRendererModule::BeginRenderingViewFamily::__l35::<lambda_759d0c4589f205101b108f5da3fb1556>::operator()(FRHICommandListImmediate &) Line 3820 C++
UE4Editor-Renderer.dll!TEnqueueUniqueRenderCommandType<`FRendererModule::BeginRenderingViewFamily'::`35'::FDrawSceneCommandName,<lambda_759d0c4589f205101b108f5da3fb1556>>::DoTask(ENamedThreads::Type CurrentThread, const TRefCountPtr<FGraphEvent> & MyCompletionGraphEvent) Line 195 C++
UE4Editor-Renderer.dll!TGraphTask<TEnqueueUniqueRenderCommandType<`FRendererModule::BeginRenderingViewFamily'::`35'::FDrawSceneCommandName,<lambda_759d0c4589f205101b108f5da3fb1556>>>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & NewTasks, ENamedThreads::Type CurrentThread) Line 849 C++
[Inline Frame] UE4Editor-Core.dll!FBaseGraphTask::Execute(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & CurrentThread, ENamedThreads::Type) Line 516 C++
UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksNamedThread(int QueueIndex, bool bAllowStall) Line 692 C++
UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksUntilQuit(int QueueIndex) Line 587 C++
UE4Editor-RenderCore.dll!RenderingThreadMain(FEvent * TaskGraphBoundSyncEvent) Line 341 C++
UE4Editor-RenderCore.dll!FRenderingThread::Run() Line 492 C++
UE4Editor-Core.dll!FRunnableThreadWin::Run() Line 86 C++
UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun() Line 27 C++
Downsampling
Callstack in engine source
UE4Editor-Renderer.dll!AddDownsamplePass(FRDGBuilder & GraphBuilder, const FViewInfo & View, const FDownsamplePassInputs & Inputs) Line 173 C++
UE4Editor-Renderer.dll!AddPostProcessingPasses(FRDGBuilder & GraphBuilder, const FViewInfo & View, const FPostProcessingInputs & Inputs) Line 503 C++
UE4Editor-Renderer.dll!FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate & RHICmdList) Line 2794 C++
UE4Editor-Renderer.dll!RenderViewFamily_RenderThread(FRHICommandListImmediate & RHICmdList, FSceneRenderer * SceneRenderer) Line 3581 C++
[Inline Frame] UE4Editor-Renderer.dll!FRendererModule::BeginRenderingViewFamily::__l35::<lambda_759d0c4589f205101b108f5da3fb1556>::operator()(FRHICommandListImmediate &) Line 3820 C++
UE4Editor-Renderer.dll!TEnqueueUniqueRenderCommandType<`FRendererModule::BeginRenderingViewFamily'::`35'::FDrawSceneCommandName,<lambda_759d0c4589f205101b108f5da3fb1556>>::DoTask(ENamedThreads::Type CurrentThread, const TRefCountPtr<FGraphEvent> & MyCompletionGraphEvent) Line 195 C++
UE4Editor-Renderer.dll!TGraphTask<TEnqueueUniqueRenderCommandType<`FRendererModule::BeginRenderingViewFamily'::`35'::FDrawSceneCommandName,<lambda_759d0c4589f205101b108f5da3fb1556>>>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & NewTasks, ENamedThreads::Type CurrentThread) Line 849 C++
[Inline Frame] UE4Editor-Core.dll!FBaseGraphTask::Execute(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & CurrentThread, ENamedThreads::Type) Line 516 C++
UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksNamedThread(int QueueIndex, bool bAllowStall) Line 692 C++
UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksUntilQuit(int QueueIndex) Line 587 C++
UE4Editor-RenderCore.dll!RenderingThreadMain(FEvent * TaskGraphBoundSyncEvent) Line 341 C++
UE4Editor-RenderCore.dll!FRenderingThread::Run() Line 492 C++
UE4Editor-Core.dll!FRunnableThreadWin::Run() Line 86 C++
UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun() Line 27 C++
[External Code]
Critical Code
Quoted from void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)
\Engine\Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp
FRDGBuilder GraphBuilder(RHICmdList);
FSceneTextureParameters SceneTextures;
SetupSceneTextureParameters(GraphBuilder, &SceneTextures);
// Fallback to a black texture if no velocity.
if (!SceneTextures.SceneVelocityBuffer)
{
SceneTextures.SceneVelocityBuffer = GSystemTextures.GetBlackDummy(GraphBuilder);
}
FPostProcessingInputs PostProcessingInputs;
PostProcessingInputs.SceneTextures = &SceneTextures;
PostProcessingInputs.ViewFamilyTexture = CreateViewFamilyTexture(GraphBuilder, ViewFamily);
PostProcessingInputs.SceneColor = GraphBuilder.RegisterExternalTexture(SceneContext.GetSceneColor(), TEXT("SceneColor"));
PostProcessingInputs.CustomDepth = GraphBuilder.TryRegisterExternalTexture(SceneContext.CustomDepth, TEXT("CustomDepth"));
PostProcessingInputs.SeparateTranslucency = RegisterExternalTextureWithFallback(GraphBuilder, SceneContext.SeparateTranslucencyRT, SceneContext.GetSeparateTranslucencyDummy(), TEXT("SeparateTranslucency"));
PostProcessingInputs.SeparateModulation = RegisterExternalTextureWithFallback(GraphBuilder, SceneContext.SeparateTranslucencyModulateRT, SceneContext.GetSeparateTranslucencyModulateDummy(), TEXT("SeparateModulate"));
if (ViewFamily.UseDebugViewPS())
{
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
FViewInfo& View = Views[ViewIndex];
SCOPED_GPU_MASK(RHICmdList, View.GPUMask);
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
AddDebugPostProcessingPasses(GraphBuilder, View, PostProcessingInputs);
}
}
else
{
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
FViewInfo& View = Views[ViewIndex];
SCOPED_GPU_MASK(RHICmdList, View.GPUMask);
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
AddPostProcessingPasses(GraphBuilder, View, PostProcessingInputs);
}
}
Quoted from void AddPostProcessingPasses(FRDGBuilder& GraphBuilder, const FViewInfo& View, const FPostProcessingInputs& Inputs)
\Engine\Source\Runtime\Renderer\Private\PostProcess\PostProcessing.cpp
// If TAA didn't do it, downsample the scene color texture by half.
if (!HalfResolutionSceneColor.Texture)
{
FDownsamplePassInputs PassInputs;
PassInputs.Name = TEXT("HalfResolutionSceneColor");
PassInputs.SceneColor = SceneColor;
PassInputs.Quality = DownsampleQuality;
PassInputs.FormatOverride = DownsampleOverrideFormat;
HalfResolutionSceneColor = AddDownsamplePass(GraphBuilder, View, PassInputs);
}
Quoted from FScreenPassTexture AddDownsamplePass(FRDGBuilder& GraphBuilder, const FViewInfo& View, const FDownsamplePassInputs& Inputs)
\Engine\Source\Runtime\Renderer\Private\PostProcess\PostProcessDownsample.cpp
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.TargetableFlags &= ~(TexCreate_RenderTargetable | TexCreate_UAV);
Desc.TargetableFlags |= bIsComputePass ? TexCreate_UAV : TexCreate_RenderTargetable;
Desc.Flags |= GFastVRamConfig.Downsample;
Desc.DebugName = Inputs.Name;
Desc.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 0));
if (Inputs.FormatOverride != PF_Unknown)
{
Desc.Format = Inputs.FormatOverride;
}
Output.Texture = GraphBuilder.CreateTexture(Desc, Inputs.Name);
Output.ViewRect = FIntRect::DivideAndRoundUp(Inputs.SceneColor.ViewRect, 2);
Output.LoadAction = ERenderTargetLoadAction::ENoAction;
}
FDownsamplePermutationDomain PermutationVector;
PermutationVector.Set<FDownsampleQualityDimension>(Inputs.Quality);
const FScreenPassTextureViewport SceneColorViewport(Inputs.SceneColor);
const FScreenPassTextureViewport OutputViewport(Output);
if (bIsComputePass)
{
FDownsampleCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FDownsampleCS::FParameters>();
PassParameters->Common = GetDownsampleParameters(View, Output, Inputs.SceneColor, Inputs.Quality);
PassParameters->OutComputeTexture = GraphBuilder.CreateUAV(Output.Texture);
TShaderMapRef<FDownsampleCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Downsample.%s %dx%d (CS)", Inputs.Name, Inputs.SceneColor.ViewRect.Width(), Inputs.SceneColor.ViewRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(OutputViewport.Rect.Size(), FIntPoint(GDownsampleTileSizeX, GDownsampleTileSizeY)));
}
else
{
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 %dx%d (PS)", Inputs.Name, Inputs.SceneColor.ViewRect.Width(), Inputs.SceneColor.ViewRect.Height()),
PixelShader,
PassParameters,
OutputViewport.Rect);
}
return MoveTemp(Output);
}
There is nothing quite so useless, as doing with great efficiency, something that should not be done at all. ― Peter Drucker