当前位置:   article > 正文

UE4阴影渲染【2】

UE4阴影渲染【2】

处理ShadowMapAtlases

FSceneRenderer::RenderShadowDepthMapAtlases(RHICmdList);

  1. void FSceneRenderer::RenderShadowDepthMapAtlases(FRHICommandListImmediate& RHICmdList)
  2. {
  3. check(RHICmdList.IsOutsideRenderPass());
  4. // Perform setup work on all GPUs in case any cached shadows are being updated this
  5. // frame. We revert to the AllViewsGPUMask for uncached shadows.
  6. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  7. FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
  8. bool bCanUseParallelDispatch = RHICmdList.IsImmediate() && // translucent shadows are draw on the render thread, using a recursive cmdlist (which is not immediate)
  9. GRHICommandList.UseParallelAlgorithms() && CVarParallelShadows.GetValueOnRenderThread();
  10. for (int32 AtlasIndex = 0; AtlasIndex < SortedShadowsForShadowDepthPass.ShadowMapAtlases.Num(); AtlasIndex++)
  11. {
  12. const FSortedShadowMapAtlas& ShadowMapAtlas = SortedShadowsForShadowDepthPass.ShadowMapAtlases[AtlasIndex];
  13. FSceneRenderTargetItem& RenderTarget = ShadowMapAtlas.RenderTargets.DepthTarget->GetRenderTargetItem();
  14. FIntPoint AtlasSize = ShadowMapAtlas.RenderTargets.DepthTarget->GetDesc().Extent;
  15. GVisualizeTexture.SetCheckPoint(RHICmdList, ShadowMapAtlas.RenderTargets.DepthTarget.GetReference());
  16. SCOPED_DRAW_EVENTF(RHICmdList, EventShadowDepths, TEXT("Atlas%u %ux%u"), AtlasIndex, AtlasSize.X, AtlasSize.Y);
  17. auto BeginShadowRenderPass = [this, &RenderTarget, &SceneContext](FRHICommandList& InRHICmdList, bool bPerformClear)
  18. {
  19. check(RenderTarget.TargetableTexture->GetDepthClearValue() == 1.0f);
  20. ERenderTargetLoadAction DepthLoadAction = bPerformClear ? ERenderTargetLoadAction::EClear : ERenderTargetLoadAction::ELoad;
  21. FRHIRenderPassInfo RPInfo(RenderTarget.TargetableTexture, MakeDepthStencilTargetActions(MakeRenderTargetActions(DepthLoadAction, ERenderTargetStoreAction::EStore), ERenderTargetActions::DontLoad_DontStore), nullptr, FExclusiveDepthStencil::DepthWrite_StencilNop);
  22. if (!GSupportsDepthRenderTargetWithoutColorRenderTarget)
  23. {
  24. RPInfo.ColorRenderTargets[0].Action = ERenderTargetActions::DontLoad_DontStore;
  25. RPInfo.ColorRenderTargets[0].RenderTarget = SceneContext.GetOptionalShadowDepthColorSurface(InRHICmdList, RPInfo.DepthStencilRenderTarget.DepthStencilTarget->GetTexture2D()->GetSizeX(), RPInfo.DepthStencilRenderTarget.DepthStencilTarget->GetTexture2D()->GetSizeY());
  26. InRHICmdList.Transition(FRHITransitionInfo(RPInfo.ColorRenderTargets[0].RenderTarget, ERHIAccess::Unknown, ERHIAccess::RTV));
  27. }
  28. InRHICmdList.Transition(FRHITransitionInfo(RPInfo.DepthStencilRenderTarget.DepthStencilTarget, ERHIAccess::Unknown, ERHIAccess::DSVWrite));
  29. InRHICmdList.BeginRenderPass(RPInfo, TEXT("ShadowMapAtlases"));
  30. };
  31. TArray<FProjectedShadowInfo*, SceneRenderingAllocator> ParallelShadowPasses;
  32. TArray<FProjectedShadowInfo*, SceneRenderingAllocator> SerialShadowPasses;
  33. // Gather our passes here to minimize switching renderpasses
  34. for (int32 ShadowIndex = 0; ShadowIndex < ShadowMapAtlas.Shadows.Num(); ShadowIndex++)
  35. {
  36. FProjectedShadowInfo* ProjectedShadowInfo = ShadowMapAtlas.Shadows[ShadowIndex];
  37. const bool bDoParallelDispatch = bCanUseParallelDispatch &&
  38. (ProjectedShadowInfo->IsWholeSceneDirectionalShadow() || CVarParallelShadowsNonWholeScene.GetValueOnRenderThread());
  39. if (bDoParallelDispatch)
  40. {
  41. ParallelShadowPasses.Add(ProjectedShadowInfo);
  42. }
  43. else
  44. {
  45. SerialShadowPasses.Add(ProjectedShadowInfo);
  46. }
  47. }
  48. FLightSceneProxy* CurrentLightForDrawEvent = NULL;
  49. #if WANTS_DRAW_MESH_EVENTS
  50. FDrawEvent LightEvent;
  51. #endif
  52. if (ParallelShadowPasses.Num() > 0)
  53. {
  54. {
  55. // Clear before going wide.
  56. SCOPED_DRAW_EVENT(RHICmdList, SetShadowRTsAndClear);
  57. BeginShadowRenderPass(RHICmdList, true);
  58. RHICmdList.EndRenderPass();
  59. }
  60. for (int32 ShadowIndex = 0; ShadowIndex < ParallelShadowPasses.Num(); ShadowIndex++)
  61. {
  62. FProjectedShadowInfo* ProjectedShadowInfo = ParallelShadowPasses[ShadowIndex];
  63. SCOPED_GPU_MASK(RHICmdList, GetGPUMaskForShadow(ProjectedShadowInfo));
  64. if (!CurrentLightForDrawEvent || ProjectedShadowInfo->GetLightSceneInfo().Proxy != CurrentLightForDrawEvent)
  65. {
  66. if (CurrentLightForDrawEvent)
  67. {
  68. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  69. STOP_DRAW_EVENT(LightEvent);
  70. }
  71. CurrentLightForDrawEvent = ProjectedShadowInfo->GetLightSceneInfo().Proxy;
  72. FString LightNameWithLevel;
  73. GetLightNameForDrawEvent(CurrentLightForDrawEvent, LightNameWithLevel);
  74. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  75. BEGIN_DRAW_EVENTF(
  76. RHICmdList,
  77. LightNameEvent,
  78. LightEvent,
  79. *LightNameWithLevel);
  80. }
  81. ProjectedShadowInfo->SetupShadowUniformBuffers(RHICmdList, Scene);
  82. ProjectedShadowInfo->TransitionCachedShadowmap(RHICmdList, Scene);
  83. ProjectedShadowInfo->RenderDepth(RHICmdList, this, BeginShadowRenderPass, true);
  84. }
  85. }
  86. if (CurrentLightForDrawEvent)
  87. {
  88. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  89. STOP_DRAW_EVENT(LightEvent);
  90. }
  91. CurrentLightForDrawEvent = nullptr;
  92. if (SerialShadowPasses.Num() > 0)
  93. {
  94. bool bShadowDepthCleared = ParallelShadowPasses.Num() > 0;
  95. bool bForceSingleRenderPass = CVarShadowForceSerialSingleRenderPass.GetValueOnAnyThread() != 0;
  96. if (bForceSingleRenderPass)
  97. {
  98. SCOPED_GPU_MASK(RHICmdList, AllViewsGPUMask);
  99. BeginShadowRenderPass(RHICmdList, !bShadowDepthCleared);
  100. }
  101. for (int32 ShadowIndex = 0; ShadowIndex < SerialShadowPasses.Num(); ShadowIndex++)
  102. {
  103. FProjectedShadowInfo* ProjectedShadowInfo = SerialShadowPasses[ShadowIndex];
  104. SCOPED_GPU_MASK(RHICmdList, GetGPUMaskForShadow(ProjectedShadowInfo));
  105. if (!CurrentLightForDrawEvent || ProjectedShadowInfo->GetLightSceneInfo().Proxy != CurrentLightForDrawEvent)
  106. {
  107. if (CurrentLightForDrawEvent)
  108. {
  109. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  110. STOP_DRAW_EVENT(LightEvent);
  111. }
  112. CurrentLightForDrawEvent = ProjectedShadowInfo->GetLightSceneInfo().Proxy;
  113. FString LightNameWithLevel;
  114. GetLightNameForDrawEvent(CurrentLightForDrawEvent, LightNameWithLevel);
  115. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  116. BEGIN_DRAW_EVENTF(
  117. RHICmdList,
  118. LightNameEvent,
  119. LightEvent,
  120. *LightNameWithLevel);
  121. }
  122. ProjectedShadowInfo->SetupShadowUniformBuffers(RHICmdList, Scene);
  123. ProjectedShadowInfo->TransitionCachedShadowmap(RHICmdList, Scene);
  124. #if WITH_MGPU
  125. // In case the first shadow is view-dependent, ensure we do the clear on all GPUs.
  126. FRHIGPUMask GPUMaskForRenderPass = RHICmdList.GetGPUMask();
  127. if (ShadowIndex == 0)
  128. {
  129. // This ensures that we don't downgrade the GPU mask if the first shadow is a
  130. // cached whole scene shadow.
  131. GPUMaskForRenderPass |= AllViewsGPUMask;
  132. }
  133. #endif
  134. if (!bForceSingleRenderPass)
  135. {
  136. SCOPED_GPU_MASK(RHICmdList, GPUMaskForRenderPass);
  137. BeginShadowRenderPass(RHICmdList, ShadowIndex == 0 && !bShadowDepthCleared);
  138. }
  139. ProjectedShadowInfo->RenderDepth(RHICmdList, this, BeginShadowRenderPass, false);
  140. if (!bForceSingleRenderPass)
  141. {
  142. RHICmdList.EndRenderPass();
  143. }
  144. }
  145. if (bForceSingleRenderPass)
  146. {
  147. SCOPED_GPU_MASK(RHICmdList, AllViewsGPUMask);
  148. RHICmdList.EndRenderPass();
  149. }
  150. }
  151. if (CurrentLightForDrawEvent)
  152. {
  153. SCOPED_GPU_MASK(RHICmdList, FRHIGPUMask::All());
  154. STOP_DRAW_EVENT(LightEvent);
  155. CurrentLightForDrawEvent = NULL;
  156. }
  157. RHICmdList.Transition(FRHITransitionInfo(RenderTarget.TargetableTexture, ERHIAccess::Unknown, ERHIAccess::SRVMask));
  158. }
  159. }
  1. void FProjectedShadowInfo::SetupShadowUniformBuffers(FRHICommandListImmediate& RHICmdList, FScene* Scene, FLightPropagationVolume* LPV)
  2. {
  3. const ERHIFeatureLevel::Type FeatureLevel = ShadowDepthView->FeatureLevel;
  4. if (FSceneInterface::GetShadingPath(FeatureLevel) == EShadingPath::Deferred)
  5. {
  6. FShadowDepthPassUniformParameters ShadowDepthPassParameters;
  7. SetupShadowDepthPassUniformBuffer(this, RHICmdList, *ShadowDepthView, ShadowDepthPassParameters, LPV);
  8. if (IsWholeSceneDirectionalShadow() && !bReflectiveShadowmap)
  9. {
  10. check(GetShadowDepthType() == CSMShadowDepthType);
  11. Scene->UniformBuffers.CSMShadowDepthPassUniformBuffer.UpdateUniformBufferImmediate(ShadowDepthPassParameters);
  12. }
  13. ShadowDepthPassUniformBuffer.UpdateUniformBufferImmediate(ShadowDepthPassParameters);
  14. if (DependentView)
  15. {
  16. extern TSet<IPersistentViewUniformBufferExtension*> PersistentViewUniformBufferExtensions;
  17. for (IPersistentViewUniformBufferExtension* Extension : PersistentViewUniformBufferExtensions)
  18. {
  19. Extension->BeginRenderView(DependentView);
  20. }
  21. }
  22. }
  23. // This needs to be done for both mobile and deferred
  24. UploadDynamicPrimitiveShaderDataForView(RHICmdList, *Scene, *ShadowDepthView);
  25. }
  26. void FProjectedShadowInfo::TransitionCachedShadowmap(FRHICommandListImmediate& RHICmdList, FScene* Scene)
  27. {
  28. if (CacheMode == SDCM_MovablePrimitivesOnly)
  29. {
  30. const FCachedShadowMapData& CachedShadowMapData = Scene->CachedShadowMaps.FindChecked(GetLightSceneInfo().Id);
  31. if (CachedShadowMapData.bCachedShadowMapHasPrimitives && CachedShadowMapData.ShadowMap.IsValid())
  32. {
  33. RHICmdList.Transition(FRHITransitionInfo(CachedShadowMapData.ShadowMap.DepthTarget->GetRenderTargetItem().ShaderResourceTexture, ERHIAccess::Unknown, ERHIAccess::SRVGraphics));
  34. }
  35. }
  36. }
  1. void FProjectedShadowInfo::RenderDepth(FRHICommandListImmediate& RHICmdList, FSceneRenderer* SceneRenderer, FBeginShadowRenderPassFunction BeginShadowRenderPass, bool bDoParallelDispatch)
  2. {
  3. #if WANTS_DRAW_MESH_EVENTS
  4. FString EventName;
  5. if (GetEmitDrawEvents())
  6. {
  7. GetShadowTypeNameForDrawEvent(EventName);
  8. EventName += FString(TEXT(" ")) + FString::FromInt(ResolutionX) + TEXT("x") + FString::FromInt(ResolutionY);
  9. }
  10. SCOPED_DRAW_EVENTF(RHICmdList, EventShadowDepthActor, *EventName);
  11. #endif
  12. CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_RenderWholeSceneShadowDepthsTime, bWholeSceneShadow);
  13. CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_RenderPerObjectShadowDepthsTime, !bWholeSceneShadow);
  14. QUICK_SCOPE_CYCLE_COUNTER(STAT_RenderShadowDepth);
  15. RenderDepthInner(RHICmdList, SceneRenderer, BeginShadowRenderPass, bDoParallelDispatch);
  16. }
  17. void FProjectedShadowInfo::RenderDepthInner(FRHICommandListImmediate& RHICmdList, FSceneRenderer* SceneRenderer, FBeginShadowRenderPassFunction BeginShadowRenderPass, bool bDoParallelDispatch)
  18. {
  19. const ERHIFeatureLevel::Type FeatureLevel = ShadowDepthView->FeatureLevel;
  20. FRHIUniformBuffer* PassUniformBuffer = ShadowDepthPassUniformBuffer;
  21. const bool bIsWholeSceneDirectionalShadow = IsWholeSceneDirectionalShadow();
  22. if (bIsWholeSceneDirectionalShadow)
  23. {
  24. // CSM shadow depth cached mesh draw commands are all referencing the same view uniform buffer. We need to update it before rendering each cascade.
  25. ShadowDepthView->ViewUniformBuffer.UpdateUniformBufferImmediate(*ShadowDepthView->CachedViewUniformShaderParameters);
  26. if (DependentView)
  27. {
  28. extern TSet<IPersistentViewUniformBufferExtension*> PersistentViewUniformBufferExtensions;
  29. for (IPersistentViewUniformBufferExtension* Extension : PersistentViewUniformBufferExtensions)
  30. {
  31. Extension->BeginRenderView(DependentView);
  32. }
  33. }
  34. }
  35. if (FSceneInterface::GetShadingPath(FeatureLevel) == EShadingPath::Mobile)
  36. {
  37. FMobileShadowDepthPassUniformParameters ShadowDepthPassParameters;
  38. SetupShadowDepthPassUniformBuffer(this, RHICmdList, *ShadowDepthView, ShadowDepthPassParameters);
  39. SceneRenderer->Scene->UniformBuffers.MobileCSMShadowDepthPassUniformBuffer.UpdateUniformBufferImmediate(ShadowDepthPassParameters);
  40. MobileShadowDepthPassUniformBuffer.UpdateUniformBufferImmediate(ShadowDepthPassParameters);
  41. PassUniformBuffer = SceneRenderer->Scene->UniformBuffers.MobileCSMShadowDepthPassUniformBuffer;
  42. }
  43. FMeshPassProcessorRenderState DrawRenderState(*ShadowDepthView, PassUniformBuffer);
  44. SetStateForShadowDepth(bReflectiveShadowmap, bOnePassPointLightShadow, DrawRenderState);
  45. SetStateForView(RHICmdList);
  46. if (CacheMode == SDCM_MovablePrimitivesOnly)
  47. {
  48. // In parallel mode we will not have a renderpass active at this point.
  49. if (bDoParallelDispatch)
  50. {
  51. BeginShadowRenderPass(RHICmdList, false);
  52. }
  53. // Copy in depths of static primitives before we render movable primitives
  54. CopyCachedShadowMap(RHICmdList, DrawRenderState, SceneRenderer, *ShadowDepthView);
  55. if (bDoParallelDispatch)
  56. {
  57. RHICmdList.EndRenderPass();
  58. }
  59. }
  60. if (bDoParallelDispatch)
  61. {
  62. check(IsInRenderingThread());
  63. // Parallel encoding requires its own renderpass.
  64. check(RHICmdList.IsOutsideRenderPass());
  65. // parallel version
  66. bool bFlush = CVarRHICmdFlushRenderThreadTasksShadowPass.GetValueOnRenderThread() > 0
  67. || CVarRHICmdFlushRenderThreadTasks.GetValueOnRenderThread() > 0;
  68. FScopedCommandListWaitForTasks Flusher(bFlush);
  69. // Dispatch commands
  70. {
  71. FShadowParallelCommandListSet ParallelCommandListSet(RHICmdList, *ShadowDepthView, !bFlush, *this, BeginShadowRenderPass);
  72. ShadowDepthPass.DispatchDraw(&ParallelCommandListSet, RHICmdList);
  73. }
  74. // Renderpass must be closed once we get here.
  75. check(RHICmdList.IsOutsideRenderPass());
  76. }
  77. else
  78. {
  79. // We must have already opened the renderpass by the time we get here.
  80. check(RHICmdList.IsInsideRenderPass());
  81. ShadowDepthPass.DispatchDraw(nullptr, RHICmdList);
  82. // Renderpass must still be open when we reach here
  83. check(RHICmdList.IsInsideRenderPass());
  84. }
  85. }
  86. void FParallelMeshDrawCommandPass::DispatchDraw(FParallelCommandListSet* ParallelCommandListSet, FRHICommandList& RHICmdList) const
  87. {
  88. TRACE_CPUPROFILER_EVENT_SCOPE(ParallelMdcDispatchDraw);
  89. if (MaxNumDraws <= 0)
  90. {
  91. return;
  92. }
  93. FRHIVertexBuffer* PrimitiveIdsBuffer = PrimitiveIdVertexBufferPoolEntry.BufferRHI;
  94. const int32 BasePrimitiveIdsOffset = 0;
  95. if (ParallelCommandListSet)
  96. {
  97. if (TaskContext.bUseGPUScene)
  98. {
  99. // Queue a command on the RHI thread which will upload PrimitiveIdVertexBuffer after finishing FMeshDrawCommandPassSetupTask.
  100. FRHICommandListImmediate &RHICommandList = GetImmediateCommandList_ForRenderCommand();
  101. if (TaskEventRef.IsValid())
  102. {
  103. RHICommandList.AddDispatchPrerequisite(TaskEventRef);
  104. }
  105. RHICommandList.EnqueueLambda([
  106. VertexBuffer = PrimitiveIdsBuffer,
  107. VertexBufferData = TaskContext.PrimitiveIdBufferData,
  108. VertexBufferDataSize = TaskContext.PrimitiveIdBufferDataSize,
  109. PrimitiveIdVertexBufferPoolEntry = PrimitiveIdVertexBufferPoolEntry](FRHICommandListImmediate& CmdList)
  110. {
  111. // Upload vertex buffer data.
  112. void* RESTRICT Data = (void* RESTRICT)CmdList.LockVertexBuffer(VertexBuffer, 0, VertexBufferDataSize, RLM_WriteOnly);
  113. FMemory::Memcpy(Data, VertexBufferData, VertexBufferDataSize);
  114. CmdList.UnlockVertexBuffer(VertexBuffer);
  115. FMemory::Free(VertexBufferData);
  116. });
  117. RHICommandList.RHIThreadFence(true);
  118. bPrimitiveIdBufferDataOwnedByRHIThread = true;
  119. }
  120. const ENamedThreads::Type RenderThread = ENamedThreads::GetRenderThread();
  121. FGraphEventArray Prereqs;
  122. if (ParallelCommandListSet->GetPrereqs())
  123. {
  124. Prereqs.Append(*ParallelCommandListSet->GetPrereqs());
  125. }
  126. if (TaskEventRef.IsValid())
  127. {
  128. Prereqs.Add(TaskEventRef);
  129. }
  130. // Distribute work evenly to the available task graph workers based on NumEstimatedDraws.
  131. // Every task will then adjust it's working range based on FVisibleMeshDrawCommandProcessTask results.
  132. const int32 NumThreads = FMath::Min<int32>(FTaskGraphInterface::Get().GetNumWorkerThreads(), ParallelCommandListSet->Width);
  133. const int32 NumTasks = FMath::Min<int32>(NumThreads, FMath::DivideAndRoundUp(MaxNumDraws, ParallelCommandListSet->MinDrawsPerCommandList));
  134. const int32 NumDrawsPerTask = FMath::DivideAndRoundUp(MaxNumDraws, NumTasks);
  135. for (int32 TaskIndex = 0; TaskIndex < NumTasks; TaskIndex++)
  136. {
  137. const int32 StartIndex = TaskIndex * NumDrawsPerTask;
  138. const int32 NumDraws = FMath::Min(NumDrawsPerTask, MaxNumDraws - StartIndex);
  139. checkSlow(NumDraws > 0);
  140. FRHICommandList* CmdList = ParallelCommandListSet->NewParallelCommandList();
  141. FGraphEventRef AnyThreadCompletionEvent = TGraphTask<FDrawVisibleMeshCommandsAnyThreadTask>::CreateTask(&Prereqs, RenderThread)
  142. .ConstructAndDispatchWhenReady(*CmdList, TaskContext.MeshDrawCommands, TaskContext.MinimalPipelineStatePassSet, PrimitiveIdsBuffer, BasePrimitiveIdsOffset, TaskContext.bDynamicInstancing, TaskContext.InstanceFactor, TaskIndex, NumTasks);
  143. ParallelCommandListSet->AddParallelCommandList(CmdList, AnyThreadCompletionEvent, NumDraws);
  144. }
  145. }
  146. else
  147. {
  148. QUICK_SCOPE_CYCLE_COUNTER(STAT_MeshPassDrawImmediate);
  149. WaitForMeshPassSetupTask();
  150. if (TaskContext.bUseGPUScene)
  151. {
  152. // Can immediately upload vertex buffer data, as there is no parallel draw task.
  153. void* RESTRICT Data = RHILockVertexBuffer(PrimitiveIdVertexBufferPoolEntry.BufferRHI, 0, TaskContext.PrimitiveIdBufferDataSize, RLM_WriteOnly);
  154. FMemory::Memcpy(Data, TaskContext.PrimitiveIdBufferData, TaskContext.PrimitiveIdBufferDataSize);
  155. RHIUnlockVertexBuffer(PrimitiveIdVertexBufferPoolEntry.BufferRHI);
  156. }
  157. SubmitMeshDrawCommandsRange(TaskContext.MeshDrawCommands, TaskContext.MinimalPipelineStatePassSet, PrimitiveIdsBuffer, BasePrimitiveIdsOffset, TaskContext.bDynamicInstancing, 0, TaskContext.MeshDrawCommands.Num(), TaskContext.InstanceFactor, RHICmdList);
  158. }
  159. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/91475
推荐阅读
相关标签
  

闽ICP备14008679号