vault backup: 2024-09-27 19:44:52
This commit is contained in:
parent
083d49a79c
commit
4ba40d3c18
@ -22,7 +22,7 @@ FDeferredShadingSceneRenderer::RenderBasePassInternal() =>
|
||||
FBasePassMeshProcessor::TryAddMeshBatch =>
|
||||
|
||||
## 大致流程
|
||||
1. 绑定GBuffer与Depth。
|
||||
1. 创建MRT并绑定、取得深度缓存。
|
||||
```c++
|
||||
const FExclusiveDepthStencil ExclusiveDepthStencil(BasePassDepthStencilAccess);
|
||||
|
||||
@ -58,10 +58,173 @@ GraphBuilder.AddPass(RDG_EVENT_NAME("GBufferClear"), PassParameters, ERDGPassFla
|
||||
}
|
||||
});
|
||||
```
|
||||
3.
|
||||
3. RenderTargetBindingSlots
|
||||
```c++
|
||||
// Render targets bindings should remain constant at this point.
|
||||
FRenderTargetBindingSlots BasePassRenderTargets = GetRenderTargetBindings(ERenderTargetLoadAction::ELoad, BasePassTexturesView);
|
||||
BasePassRenderTargets.DepthStencil = FDepthStencilBinding(BasePassDepthTexture, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, ExclusiveDepthStencil);
|
||||
```
|
||||
4. RenderBasePassInternal()
|
||||
5. RenderAnisotropyPass()
|
||||
|
||||
# MeshDraw
|
||||
## RenderBasePassInternal()
|
||||
RenderNaniteBasePass()为一个Lambda,最终调用**Nanite::DrawBasePass()** 渲染Nanite物体的BasePass。其他相关渲染代码如下:
|
||||
```c++
|
||||
SCOPE_CYCLE_COUNTER(STAT_BasePassDrawTime);
|
||||
RDG_EVENT_SCOPE(GraphBuilder, "BasePass");
|
||||
RDG_GPU_STAT_SCOPE(GraphBuilder, Basepass);
|
||||
|
||||
# SetDepthStencilStateForBasePass()
|
||||
const bool bDrawSceneViewsInOneNanitePass = Views.Num() > 1 && Nanite::ShouldDrawSceneViewsInOneNanitePass(Views[0]);
|
||||
if (bParallelBasePass)//并行渲染模式
|
||||
{
|
||||
RDG_WAIT_FOR_TASKS_CONDITIONAL(GraphBuilder, IsBasePassWaitForTasksEnabled());
|
||||
|
||||
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
|
||||
{
|
||||
FViewInfo& View = Views[ViewIndex];
|
||||
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
|
||||
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
|
||||
View.BeginRenderView();
|
||||
|
||||
const bool bLumenGIEnabled = GetViewPipelineState(View).DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen;
|
||||
|
||||
FMeshPassProcessorRenderState DrawRenderState;
|
||||
SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);
|
||||
|
||||
FOpaqueBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
|
||||
PassParameters->View = View.GetShaderParameters();
|
||||
PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
|
||||
PassParameters->BasePass = CreateOpaqueBasePassUniformBuffer(GraphBuilder, View, ViewIndex, ForwardBasePassTextures, DBufferTextures, bLumenGIEnabled);
|
||||
PassParameters->RenderTargets = BasePassRenderTargets;
|
||||
PassParameters->RenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, View, FVariableRateShadingImageManager::EVRSPassType::BasePass);
|
||||
|
||||
const bool bShouldRenderView = View.ShouldRenderView();
|
||||
if (bShouldRenderView)
|
||||
{
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, PassParameters->InstanceCullingDrawParams);
|
||||
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("BasePassParallel"),
|
||||
PassParameters,
|
||||
ERDGPassFlags::Raster | ERDGPassFlags::SkipRenderPass,
|
||||
[this, &View, PassParameters](const FRDGPass* InPass, FRHICommandListImmediate& RHICmdList)
|
||||
{
|
||||
FRDGParallelCommandListSet ParallelCommandListSet(InPass, RHICmdList, GET_STATID(STAT_CLP_BasePass), View, FParallelCommandListBindings(PassParameters));
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].DispatchDraw(&ParallelCommandListSet, RHICmdList, &PassParameters->InstanceCullingDrawParams);
|
||||
});
|
||||
}
|
||||
|
||||
const bool bShouldRenderViewForNanite = bNaniteEnabled && (!bDrawSceneViewsInOneNanitePass || ViewIndex == 0); // when bDrawSceneViewsInOneNanitePass, the first view should cover all the other atlased ones
|
||||
if (bShouldRenderViewForNanite)
|
||||
{
|
||||
// Should always have a full Z prepass with Nanite
|
||||
check(ShouldRenderPrePass());
|
||||
//渲染Nanite物体BasePass
|
||||
RenderNaniteBasePass(View, ViewIndex);
|
||||
}
|
||||
|
||||
//渲染编辑器相关的图元物体
|
||||
RenderEditorPrimitives(GraphBuilder, PassParameters, View, DrawRenderState, InstanceCullingManager);
|
||||
|
||||
//渲染大气
|
||||
if (bShouldRenderView && View.Family->EngineShowFlags.Atmosphere)
|
||||
{
|
||||
FOpaqueBasePassParameters* SkyPassPassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
|
||||
SkyPassPassParameters->BasePass = PassParameters->BasePass;
|
||||
SkyPassPassParameters->RenderTargets = BasePassRenderTargets;
|
||||
SkyPassPassParameters->View = View.GetShaderParameters();
|
||||
SkyPassPassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
|
||||
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, SkyPassPassParameters->InstanceCullingDrawParams);
|
||||
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("SkyPassParallel"),
|
||||
SkyPassPassParameters,
|
||||
ERDGPassFlags::Raster | ERDGPassFlags::SkipRenderPass,
|
||||
[this, &View, SkyPassPassParameters](const FRDGPass* InPass, FRHICommandListImmediate& RHICmdList)
|
||||
{
|
||||
FRDGParallelCommandListSet ParallelCommandListSet(InPass, RHICmdList, GET_STATID(STAT_CLP_BasePass), View, FParallelCommandListBindings(SkyPassPassParameters));
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].DispatchDraw(&ParallelCommandListSet, RHICmdList, &SkyPassPassParameters->InstanceCullingDrawParams);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
|
||||
{
|
||||
FViewInfo& View = Views[ViewIndex];
|
||||
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
|
||||
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
|
||||
View.BeginRenderView();
|
||||
|
||||
const bool bLumenGIEnabled = GetViewPipelineState(View).DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen;
|
||||
|
||||
FMeshPassProcessorRenderState DrawRenderState;
|
||||
SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);
|
||||
|
||||
FOpaqueBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
|
||||
PassParameters->View = View.GetShaderParameters();
|
||||
PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
|
||||
PassParameters->BasePass = CreateOpaqueBasePassUniformBuffer(GraphBuilder, View, ViewIndex, ForwardBasePassTextures, DBufferTextures, bLumenGIEnabled);
|
||||
PassParameters->RenderTargets = BasePassRenderTargets;
|
||||
PassParameters->RenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, View, FVariableRateShadingImageManager::EVRSPassType::BasePass);
|
||||
|
||||
const bool bShouldRenderView = View.ShouldRenderView();
|
||||
if (bShouldRenderView)
|
||||
{
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, PassParameters->InstanceCullingDrawParams);
|
||||
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("BasePass"),
|
||||
PassParameters,
|
||||
ERDGPassFlags::Raster,
|
||||
[this, &View, PassParameters](FRHICommandList& RHICmdList)
|
||||
{
|
||||
SetStereoViewport(RHICmdList, View, 1.0f);
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].DispatchDraw(nullptr, RHICmdList, &PassParameters->InstanceCullingDrawParams);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const bool bShouldRenderViewForNanite = bNaniteEnabled && (!bDrawSceneViewsInOneNanitePass || ViewIndex == 0); // when bDrawSceneViewsInOneNanitePass, the first view should cover all the other atlased ones
|
||||
if (bShouldRenderViewForNanite)
|
||||
{
|
||||
// Should always have a full Z prepass with Nanite
|
||||
check(ShouldRenderPrePass());
|
||||
|
||||
RenderNaniteBasePass(View, ViewIndex);
|
||||
}
|
||||
|
||||
RenderEditorPrimitives(GraphBuilder, PassParameters, View, DrawRenderState, InstanceCullingManager);
|
||||
|
||||
if (bShouldRenderView && View.Family->EngineShowFlags.Atmosphere)
|
||||
{
|
||||
FOpaqueBasePassParameters* SkyPassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
|
||||
SkyPassParameters->BasePass = PassParameters->BasePass;
|
||||
SkyPassParameters->RenderTargets = BasePassRenderTargets;
|
||||
SkyPassParameters->View = View.GetShaderParameters();
|
||||
SkyPassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
|
||||
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, SkyPassParameters->InstanceCullingDrawParams);
|
||||
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("SkyPass"),
|
||||
SkyPassParameters,
|
||||
ERDGPassFlags::Raster,
|
||||
[this, &View, SkyPassParameters](FRHICommandList& RHICmdList)
|
||||
{
|
||||
SetStereoViewport(RHICmdList, View, 1.0f);
|
||||
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].DispatchDraw(nullptr, RHICmdList, &SkyPassParameters->InstanceCullingDrawParams);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### SetDepthStencilStateForBasePass()
|
||||
```c++
|
||||
void SetDepthStencilStateForBasePass(
|
||||
FMeshPassProcessorRenderState& DrawRenderState,
|
||||
@ -98,4 +261,118 @@ void SetDepthStencilStateForBasePass(
|
||||
}
|
||||
}
|
||||
```
|
||||
#
|
||||
## AnisotropyPass
|
||||
Anisotropy的RT设置:
|
||||
- RenderTarget:SceneTextures.GBufferF。
|
||||
- DepthStencil:SceneTextures.Depth.Target。**ERenderTargetLoadAction::ELoad**、**FExclusiveDepthStencil::DepthRead_StencilNop**
|
||||
|
||||
### 管线状态
|
||||
在FAnisotropyMeshProcessor::CollectPSOInitializers()中:
|
||||
```c++
|
||||
ETextureCreateFlags GBufferFCreateFlags;
|
||||
EPixelFormat GBufferFPixelFormat = FSceneTextures::GetGBufferFFormatAndCreateFlags(GBufferFCreateFlags);
|
||||
AddRenderTargetInfo(GBufferFPixelFormat, GBufferFCreateFlags, RenderTargetsInfo);
|
||||
SetupDepthStencilInfo(PF_DepthStencil, SceneTexturesConfig.DepthCreateFlags, ERenderTargetLoadAction::ELoad,
|
||||
ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilNop, RenderTargetsInfo);
|
||||
```
|
||||
|
||||
```c++
|
||||
void SetupDepthStencilInfo(
|
||||
EPixelFormat DepthStencilFormat,
|
||||
ETextureCreateFlags DepthStencilCreateFlags,
|
||||
ERenderTargetLoadAction DepthTargetLoadAction,
|
||||
ERenderTargetLoadAction StencilTargetLoadAction,
|
||||
FExclusiveDepthStencil DepthStencilAccess,
|
||||
FGraphicsPipelineRenderTargetsInfo& RenderTargetsInfo)
|
||||
{
|
||||
// Setup depth stencil state
|
||||
RenderTargetsInfo.DepthStencilTargetFormat = DepthStencilFormat;
|
||||
RenderTargetsInfo.DepthStencilTargetFlag = DepthStencilCreateFlags;
|
||||
|
||||
RenderTargetsInfo.DepthTargetLoadAction = DepthTargetLoadAction;
|
||||
RenderTargetsInfo.StencilTargetLoadAction = StencilTargetLoadAction;
|
||||
RenderTargetsInfo.DepthStencilAccess = DepthStencilAccess;
|
||||
|
||||
const ERenderTargetStoreAction StoreAction = EnumHasAnyFlags(RenderTargetsInfo.DepthStencilTargetFlag, TexCreate_Memoryless) ? ERenderTargetStoreAction::ENoAction : ERenderTargetStoreAction::EStore;
|
||||
RenderTargetsInfo.DepthTargetStoreAction = RenderTargetsInfo.DepthStencilAccess.IsUsingDepth() ? StoreAction : ERenderTargetStoreAction::ENoAction;
|
||||
RenderTargetsInfo.StencilTargetStoreAction = RenderTargetsInfo.DepthStencilAccess.IsUsingStencil() ? StoreAction : ERenderTargetStoreAction::ENoAction;
|
||||
}
|
||||
```
|
||||
|
||||
### ParallelRendering
|
||||
AnisotropyPass支持并行渲染,并行渲染的判断逻辑为
|
||||
```c++
|
||||
const bool bEnableParallelBasePasses = GRHICommandList.UseParallelAlgorithms() && CVarParallelBasePass.GetValueOnRenderThread();
|
||||
```
|
||||
看得出判断条件是:
|
||||
1. 显卡是否支持并行渲染。
|
||||
2. CVar(r.ParallelBasePass)是否开启并行渲染。
|
||||
|
||||
从AnisotropyPass可以看得出并行渲染与一般渲染的差别在于:
|
||||
1. FRenderTargetBinding绑定时的ERenderTargetLoadAction不同,**并行为ELoad**;**普通渲染为EClear**。
|
||||
2. 调用AddPass添加了**ERDGPassFlags::SkipRenderPass**标记。
|
||||
3. 并行渲染会在AddPass中构建**FRDGParallelCommandListSet ParallelCommandListSet**,并作为传入**DispatchDraw**;普通渲染传递nullptr。
|
||||
4. 普通渲染会额外调用**SetStereoViewport(RHICmdList, View);**,本质是调用RHICmdList.SetViewport来设置View。
|
||||
|
||||
### Code
|
||||
```c++
|
||||
RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, RenderAnisotropyPass);
|
||||
SCOPED_NAMED_EVENT(FDeferredShadingSceneRenderer_RenderAnisotropyPass, FColor::Emerald);
|
||||
SCOPE_CYCLE_COUNTER(STAT_AnisotropyPassDrawTime);
|
||||
RDG_GPU_STAT_SCOPE(GraphBuilder, RenderAnisotropyPass);
|
||||
|
||||
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
||||
{
|
||||
FViewInfo& View = Views[ViewIndex];
|
||||
|
||||
if (View.ShouldRenderView())
|
||||
{
|
||||
FParallelMeshDrawCommandPass& ParallelMeshPass = View.ParallelMeshDrawCommandPasses[EMeshPass::AnisotropyPass];
|
||||
|
||||
if (!ParallelMeshPass.HasAnyDraw())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
View.BeginRenderView();
|
||||
|
||||
auto* PassParameters = GraphBuilder.AllocParameters<FAnisotropyPassParameters>();
|
||||
PassParameters->View = View.GetShaderParameters();
|
||||
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(SceneTextures.Depth.Target, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilNop);
|
||||
|
||||
ParallelMeshPass.BuildRenderingCommands(GraphBuilder, Scene->GPUScene, PassParameters->InstanceCullingDrawParams);
|
||||
if (bDoParallelPass)
|
||||
{
|
||||
AddClearRenderTargetPass(GraphBuilder, SceneTextures.GBufferF);
|
||||
|
||||
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextures.GBufferF, ERenderTargetLoadAction::ELoad);
|
||||
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("AnisotropyPassParallel"),
|
||||
PassParameters,
|
||||
ERDGPassFlags::Raster | ERDGPassFlags::SkipRenderPass,
|
||||
[this, &View, &ParallelMeshPass, PassParameters](const FRDGPass* InPass, FRHICommandListImmediate& RHICmdList)
|
||||
{
|
||||
FRDGParallelCommandListSet ParallelCommandListSet(InPass, RHICmdList, GET_STATID(STAT_CLP_AnisotropyPass), View, FParallelCommandListBindings(PassParameters));
|
||||
|
||||
ParallelMeshPass.DispatchDraw(&ParallelCommandListSet, RHICmdList, &PassParameters->InstanceCullingDrawParams);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextures.GBufferF, ERenderTargetLoadAction::EClear);
|
||||
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("AnisotropyPass"),
|
||||
PassParameters,
|
||||
ERDGPassFlags::Raster,
|
||||
[this, &View, &ParallelMeshPass, PassParameters](FRHICommandList& RHICmdList)
|
||||
{
|
||||
SetStereoViewport(RHICmdList, View);
|
||||
|
||||
ParallelMeshPass.DispatchDraw(nullptr, RHICmdList, &PassParameters->InstanceCullingDrawParams);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -32,6 +32,7 @@ OutGBufferD = GBuffer.CustomData
|
||||
OutGBufferE = GBuffer.PrecomputedShadowFactors (GBT_Unorm_8_8_8_8)
|
||||
TargetVelocity / OutGBufferF = velocity / tangent (默认不开启 带有深度<开启Lumen与距离场 或者 开启光线追踪> GBC_Raw_Float_16_16_16_16 不带深度 GBC_Raw_Float_16_16)
|
||||
TargetSeparatedMainDirLight = SingleLayerWater相关 (有SingleLayerWater才会开启 GBC_Raw_Float_11_11_10)
|
||||
OutGBufferF = Anisotropy
|
||||
|
||||
// 0..1, 2 bits, use CastContactShadow(GBuffer) or HasDynamicIndirectShadowCasterRepresentation(GBuffer) to extract
|
||||
half PerObjectGBufferData;
|
||||
|
Loading…
x
Reference in New Issue
Block a user