// Copyright Epic Games, Inc. All Rights Reserved. /*============================================================================= SceneRendering.h: Scene rendering definitions. =============================================================================*/ #pragma once #include "SceneRendererInterface.h" #include "CoreMinimal.h" #include "Containers/IndirectArray.h" #include "Containers/ArrayView.h" #include "Stats/Stats.h" #include "RHI.h" #include "RenderResource.h" #include "UniformBuffer.h" #include "GlobalDistanceField.h" #include "GlobalDistanceFieldParameters.h" #include "SceneView.h" #include "RendererInterface.h" #include "BatchedElements.h" #include "MeshBatch.h" #include "ScenePrivateBase.h" #include "SceneVisibility.h" #include "PrimitiveSceneInfo.h" #include "PrimitiveViewRelevance.h" #include "LightShaftRendering.h" #include "StaticBoundShaderState.h" #include "Templates/UniquePtr.h" #include "MeshDrawCommands.h" #include "MeshPassProcessor.h" #include "RayTracingMeshDrawCommands.h" #include "ShaderPrintParameters.h" #include "PostProcess/PostProcessAmbientOcclusionMobile.h" #include "VirtualShadowMaps/VirtualShadowMapArray.h" #include "VirtualShadowMaps/VirtualShadowMapProjection.h" #include "Lumen/LumenTranslucencyVolumeLighting.h" #include "MegaLights/MegaLights.h" #include "HairStrands/HairStrandsData.h" #include "Substrate/Substrate.h" #include "TemporalUpscaler.h" #include "GPUScene.h" #include "RenderCore.h" #include "SceneTextures.h" #include "TranslucencyPass.h" #include "SceneTexturesConfig.h" #include "SceneUniformBuffer.h" #include "TextureFallbacks.h" #include "SceneInterface.h" #include "Async/Mutex.h" #include "LocalFogVolumeRendering.h" #include "Nanite/NaniteShared.h" #include "LightFunctionAtlas.h" #include "SceneExtensions.h" #include "PostProcess/LensDistortion.h" #if RHI_RAYTRACING #include "RayTracingInstanceBufferUtil.h" #endif // RHI_RAYTRACING // Forward declarations. class FScene; class FSceneViewState; class FViewInfo; struct FILCUpdatePrimTaskData; class FPostprocessContext; class FRayTracingLightGrid; class FRayTracingDecals; class FRayTracingLocalShaderBindingWriter; class FVirtualShadowMapClipmap; class FShadowProjectionPassParameters; class FSceneTextureShaderParameters; class FLumenSceneData; class FShadowSceneRenderer; class FGlobalShaderMap; class FVirtualTextureUpdater; class FExponentialHeightFogSceneInfo; struct FCloudRenderContext; struct FSceneWithoutWaterTextures; struct FHairStrandsVisibilityViews; struct FSortedLightSetSceneInfo; enum class EVelocityPass : uint32; enum class ERayTracingSceneLayer : uint8; class FTransientLightFunctionTextureAtlas; struct FSceneTexturesConfig; struct FMinimalSceneTextures; struct FSceneTextures; struct FCustomDepthTextures; struct FDynamicShadowsTaskData; class FAtmosphereUniformShaderParameters; struct FSkyAtmosphereRenderContext; class FTexture2DResource; class FSimpleLightArray; struct FScreenMessageWriter; struct FVolumetricFogIntegrationParameterData; class FLumenHardwareRayTracingUniformBufferParameters; struct FDBufferTextures; class FDistanceFieldCulledObjectBufferParameters; class FTileIntersectionParameters; class FDistanceFieldAOParameters; namespace Nanite { struct FInstanceDraw; } struct FPersistentViewId { bool IsValid() const { return Index != INDEX_NONE; } int32 Index = INDEX_NONE; }; DECLARE_LOG_CATEGORY_EXTERN(LogSceneCapture, Log, All); struct FSceneCaptureLogUtils { static bool bEnableSceneCaptureLogging; }; extern bool ShouldUseStereoLumenOptimizations(); DECLARE_GPU_STAT_NAMED_EXTERN(Postprocessing, TEXT("Postprocessing")); DECLARE_GPU_STAT_NAMED_EXTERN(CustomRenderPasses, TEXT("CustomRenderPasses")); /** Mobile only. Information used to determine whether static meshes will be rendered with CSM shaders or not. */ class FMobileCSMVisibilityInfo { public: /** true if there are any primitives affected by CSM subjects */ uint32 bMobileDynamicCSMInUse : 1; // true if all draws should be forced to use CSM shaders. uint32 bAlwaysUseCSM : 1; /** Visibility lists for static meshes that will use expensive CSM shaders. */ FSceneBitArray MobilePrimitiveCSMReceiverVisibilityMap; FSceneBitArray MobileCSMStaticMeshVisibilityMap; /** Visibility lists for static meshes that will use the non CSM shaders. */ FSceneBitArray MobileNonCSMStaticMeshVisibilityMap; /** Initialization constructor. */ FMobileCSMVisibilityInfo() : bMobileDynamicCSMInUse(false), bAlwaysUseCSM(false) {} }; /** Stores a list of CSM shadow casters. Used by mobile renderer for culling primitives receiving static + CSM shadows. */ class FMobileCSMSubjectPrimitives { public: /** Adds a subject primitive */ void AddSubjectPrimitive(const FPrimitiveSceneInfo* PrimitiveSceneInfo, int32 PrimitiveId) { checkSlow(PrimitiveSceneInfo->GetIndex() == PrimitiveId); const int32 PrimitiveIndex = PrimitiveSceneInfo->GetIndex(); if (!ShadowSubjectPrimitivesEncountered[PrimitiveId]) { ShadowSubjectPrimitives.Add(PrimitiveSceneInfo); ShadowSubjectPrimitivesEncountered[PrimitiveId] = true; } } /** Returns the list of subject primitives */ const TArray& GetShadowSubjectPrimitives() const { return ShadowSubjectPrimitives; } /** Used to initialize the ShadowSubjectPrimitivesEncountered bit array * to prevent shadow primitives being added more than once. */ void InitShadowSubjectPrimitives(int32 PrimitiveCount) { ShadowSubjectPrimitivesEncountered.Init(false, PrimitiveCount); } protected: /** List of this light's shadow subject primitives. */ FSceneBitArray ShadowSubjectPrimitivesEncountered; TArray ShadowSubjectPrimitives; }; /** Information about a visible light which is specific to the view it's visible in. */ class FVisibleLightViewInfo { public: /** Whether each shadow in the corresponding FVisibleLightInfo::AllProjectedShadows array is visible. */ FSceneBitArray ProjectedShadowVisibilityMap; /** The view relevance of each shadow in the corresponding FVisibleLightInfo::AllProjectedShadows array. */ TArray ProjectedShadowViewRelevanceMap; /** true if this light in the view frustum (dir/sky lights always are). */ uint32 bInViewFrustum : 1; /** true if the light didn't get distance culled. */ uint32 bInDrawRange : 1; /** List of CSM shadow casters. Used by mobile renderer for culling primitives receiving static + CSM shadows */ FMobileCSMSubjectPrimitives MobileCSMSubjectPrimitives; /** Initialization constructor. */ FVisibleLightViewInfo() : bInViewFrustum(false) , bInDrawRange(false) {} }; /** Information about a visible light which isn't view-specific. */ class FVisibleLightInfo { public: /** All visible projected shadows, output of shadow setup. Not all of these will be rendered. */ TArray AllProjectedShadows; /** Shadows to project for each feature that needs special handling. */ TArray ShadowsToProject; TArray CapsuleShadowsToProject; /** All visible projected preshdows. These are not allocated on the mem stack so they are refcounted. */ TArray,SceneRenderingAllocator> ProjectedPreShadows; /** A list of per-object shadows that were occluded. We need to track these so we can issue occlusion queries for them. */ TArray OccludedPerObjectShadows; TArray, SceneRenderingAllocator> VirtualShadowMapClipmaps; /** * Returns true if the light has only virtual shadow maps (or no shadows at all), i.e. no conventional shadow maps that are allocated */ bool ContainsOnlyVirtualShadowMaps() const; /** * Returns true if there are any virtual shadow maps for any views for this light. */ bool HasVirtualShadowMap() const { return VirtualShadowMapId != INDEX_NONE; } /** * Prefer this to direct access of the VirtualShadowMapId member when a view is known. * For directional lights this will attempt to find a clipmap associated with the given view, * while the VirtualShadowMapId variable will simply be an arbitrary one of them if multiple exist. */ int32 GetVirtualShadowMapId( const FViewInfo* View ) const; int32 VirtualShadowMapId = INDEX_NONE; }; // Stores the primitive count of each translucency pass (redundant, could be computed after sorting but this way we touch less memory) struct FTranslucenyPrimCount { private: uint32 Count[ETranslucencyPass::TPT_MAX]; bool UseSceneColorCopyPerPass[ETranslucencyPass::TPT_MAX]; public: // constructor FTranslucenyPrimCount() { for(uint32 i = 0; i < ETranslucencyPass::TPT_MAX; ++i) { Count[i] = 0; UseSceneColorCopyPerPass[i] = false; } } // interface similar to TArray but here we only store the count of Prims per pass void Append(const FTranslucenyPrimCount& InSrc) { for(uint32 i = 0; i < ETranslucencyPass::TPT_MAX; ++i) { Count[i] += InSrc.Count[i]; UseSceneColorCopyPerPass[i] |= InSrc.UseSceneColorCopyPerPass[i]; } } // interface similar to TArray but here we only store the count of Prims per pass void Add(ETranslucencyPass::Type InPass, bool bUseSceneColorCopy) { ++Count[InPass]; UseSceneColorCopyPerPass[InPass] |= bUseSceneColorCopy; } int32 Num(ETranslucencyPass::Type InPass) const { return Count[InPass]; } int32 NumPrims() const { int32 NumTotal = 0; for (uint32 PassIndex = 0; PassIndex < ETranslucencyPass::TPT_MAX; ++PassIndex) { NumTotal += Count[PassIndex]; } return NumTotal; } bool UseSceneColorCopy(ETranslucencyPass::Type InPass) const { return UseSceneColorCopyPerPass[InPass]; } }; /** A batched occlusion primitive. */ struct FOcclusionPrimitive { FVector Center; FVector Extent; }; // An occlusion query pool with frame based lifetime management class FFrameBasedOcclusionQueryPool { public: FFrameBasedOcclusionQueryPool() = default; FRHIRenderQuery* AllocateQuery(); // Recycle queries that are (OcclusionFrameCounter - NumBufferedFrames) old or older void AdvanceFrame(uint32 InOcclusionFrameCounter, uint32 InNumBufferedFrames, bool bStereoRoundRobin); private: struct FFrameOcclusionQueries { TArray Queries; int32 FirstFreeIndex; uint32 OcclusionFrameCounter; FFrameOcclusionQueries() : FirstFreeIndex(0) , OcclusionFrameCounter(0) {} }; FFrameOcclusionQueries FrameQueries[FOcclusionQueryHelpers::MaxBufferedOcclusionFrames * 2]; uint32 CurrentFrameIndex = 0; uint32 OcclusionFrameCounter = -1; uint32 NumBufferedFrames = 0; }; /** * Combines consecutive primitives which use the same occlusion query into a single DrawIndexedPrimitive call. */ class FOcclusionQueryBatcher { public: /** The maximum number of consecutive previously occluded primitives which will be combined into a single occlusion query. */ enum { OccludedPrimitiveQueryBatchSize = 16 }; /** Initialization constructor. */ FOcclusionQueryBatcher(class FSceneViewState* ViewState, uint32 InMaxBatchedPrimitives, uint32 InNumInstances); /** Destructor. */ ~FOcclusionQueryBatcher(); /** @returns True if the batcher has any outstanding batches, otherwise false. */ bool HasBatches(void) const { return (NumBatchedPrimitives > 0); } /** Renders the current batch and resets the batch state. */ void Flush(FRHICommandList& RHICmdList); /** * Batches a primitive's occlusion query for rendering. * @param Bounds - The primitive's bounds. */ FRHIRenderQuery* BatchPrimitive(const FVector& BoundsOrigin, const FVector& BoundsBoxExtent, FGlobalDynamicVertexBuffer& DynamicVertexBuffer); inline int32 GetNumBatchOcclusionQueries() const { return BatchOcclusionQueries.Num(); } private: struct FOcclusionBatch { FRHIRenderQuery* Query; FGlobalDynamicVertexBuffer::FAllocation VertexAllocation; }; /** The pending batches. */ TArray BatchOcclusionQueries; /** The batch new primitives are being added to. */ FOcclusionBatch* CurrentBatchOcclusionQuery; /** The maximum number of primitives in a batch. */ const uint32 MaxBatchedPrimitives; /** The number of primitives in the current batch. */ uint32 NumBatchedPrimitives; /** The pool to allocate occlusion queries from. */ FFrameBasedOcclusionQueryPool* OcclusionQueryPool; /** The number of instances for instanced stereo rendering */ uint32 NumInstances; }; class FHZBOcclusionTester : public FRenderResource { public: FHZBOcclusionTester(); ~FHZBOcclusionTester() {} // FRenderResource interface virtual void InitRHI(FRHICommandListBase& RHICmdList) override; virtual void ReleaseRHI() override; uint32 GetNum() const { return Primitives.Num(); } uint32 AddBounds( const FVector& BoundsOrigin, const FVector& BoundsExtent ); void Submit(FRDGBuilder& GraphBuilder, const FViewInfo& View); void MapResults(FRHICommandListImmediate& RHICmdList); void UnmapResults(FRHICommandListImmediate& RHICmdList); bool IsVisible( uint32 Index ) const; bool IsValidFrame(uint32 FrameNumber) const; void SetValidFrameNumber(uint32 FrameNumber); uint64 GetGPUSizeBytes(bool bLogSizes) const; private: enum { SizeX = 256 }; enum { SizeY = 256 }; enum { FrameNumberMask = 0x7fffffff }; enum { InvalidFrameNumber = 0xffffffff }; TArray< FOcclusionPrimitive, SceneRenderingAllocator > Primitives; const uint8* ResultsBuffer; int32 ResultsBufferRowPitch; TUniquePtr ResultsReadback; bool IsInvalidFrame() const; // set ValidFrameNumber to a number that cannot be set by SetValidFrameNumber so IsValidFrame will return false for any frame number void SetInvalidFrameNumber(); uint32 ValidFrameNumber; }; PRAGMA_DISABLE_DEPRECATION_WARNINGS /** Helper class to marshal data from your RDG pass into the parallel command list set. */ class UE_DEPRECATED(5.5, "Use GraphBuilder.AddDispatchPass instead") FParallelCommandListBindings { public: template FParallelCommandListBindings(ParameterStructType* ParameterStruct) : StaticUniformBuffers(GetStaticUniformBuffers(ParameterStruct)) , bHasRenderPassInfo(HasRenderPassInfo(ParameterStruct)) { if (bHasRenderPassInfo) { RenderPassInfo = GetRenderPassInfo(ParameterStruct); } } inline void SetOnCommandList(FRHICommandList& RHICmdList) const { if (bHasRenderPassInfo) { RHICmdList.BeginRenderPass(RenderPassInfo, TEXT("Parallel")); } RHICmdList.SetStaticUniformBuffers(StaticUniformBuffers); } FRHIRenderPassInfo RenderPassInfo; FUniformBufferStaticBindings StaticUniformBuffers; bool bHasRenderPassInfo; }; class UE_DEPRECATED(5.5, "Use GraphBuilder.AddDispatchPass instead") FParallelCommandListSet { public: const FRDGPass* Pass; const FViewInfo& View; FRHICommandListImmediate& ParentCmdList; int32 Width; int32 NumAlloc; int32 MinDrawsPerCommandList; private: TArray QueuedCommandLists; protected: //this must be called by deriving classes virtual destructor because it calls the virtual SetStateOnCommandList. //C++ will not do dynamic dispatch of virtual calls from destructors so we can't call it in the base class. void Dispatch(bool bHighPriority = false); FRHICommandList* AllocCommandList(); bool bHasRenderPasses; public: FParallelCommandListSet(const FRDGPass* InPass, const FViewInfo& InView, FRHICommandListImmediate& InParentCmdList, bool bHasRenderPasses = true); FParallelCommandListSet(const FRDGPass* InPass, TStatId InExecuteStat, const FViewInfo& InView, FRHICommandListImmediate& InParentCmdList, bool bHasRenderPasses = true) : FParallelCommandListSet(InPass, InView, InParentCmdList, bHasRenderPasses) {} virtual ~FParallelCommandListSet(); int32 NumParallelCommandLists() const { return QueuedCommandLists.Num(); } FRHICommandList* NewParallelCommandList(); FORCEINLINE FGraphEventArray* GetPrereqs() { return nullptr; } void AddParallelCommandList(FRHICommandList* CmdList); virtual void SetStateOnCommandList(FRHICommandList& CmdList) {} }; class UE_DEPRECATED(5.5, "Use GraphBuilder.AddDispatchPass instead") FRDGParallelCommandListSet final : public FParallelCommandListSet { public: FRDGParallelCommandListSet( const FRDGPass* InPass, FRHICommandListImmediate& InParentCmdList, const FViewInfo& InView, const FParallelCommandListBindings& InBindings, float InViewportScale = 1.0f) : FParallelCommandListSet(InPass, InView, InParentCmdList, InBindings.bHasRenderPassInfo) , Bindings(InBindings) , ViewportScale(InViewportScale) {} FRDGParallelCommandListSet(const FRDGPass* InPass, FRHICommandListImmediate& InParentCmdList, TStatId InStatId, const FViewInfo& InView, const FParallelCommandListBindings& InBindings, float InViewportScale = 1.0f) : FRDGParallelCommandListSet(InPass, InParentCmdList, InView, InBindings, InViewportScale) {} ~FRDGParallelCommandListSet() override { Dispatch(bHighPriority); } void SetStateOnCommandList(FRHICommandList& RHICmdList) override; void SetHighPriority() { bHighPriority = true; } private: FParallelCommandListBindings Bindings; float ViewportScale; bool bHighPriority = false; }; PRAGMA_ENABLE_DEPRECATION_WARNINGS enum EVolumeUpdateType { VUT_MeshDistanceFields = 1, VUT_Heightfields = 2, VUT_All = VUT_MeshDistanceFields | VUT_Heightfields }; class FVolumeUpdateRegion { public: FVolumeUpdateRegion() : UpdateType(VUT_All) {} /** World space bounds. */ FBox Bounds; /** Number of texels in each dimension to update. */ FIntVector CellsSize; EVolumeUpdateType UpdateType; }; class FClipmapUpdateBounds { public: FClipmapUpdateBounds() : Center(0.0f, 0.0f, 0.0f) , bExpandByInfluenceRadius(false) , Extent(0.0f, 0.0f, 0.0f) { } FClipmapUpdateBounds(const FVector& InCenter, const FVector& InExtent, bool bInExpandByInfluenceRadius) : Center(InCenter) , bExpandByInfluenceRadius(bInExpandByInfluenceRadius) , Extent(InExtent) { } FVector Center; bool bExpandByInfluenceRadius; FVector Extent; }; enum class EGlobalSDFFullRecaptureReason { None, TooManyUpdateBounds, HeightfieldStreaming, MeshSDFStreaming, NoViewState }; class FGlobalDistanceFieldClipmap { public: /** World space bounds. */ FBox Bounds; /** Offset applied to UVs so that only new or dirty areas of the volume texture have to be updated. */ FVector ScrollOffset; EGlobalSDFFullRecaptureReason FullRecaptureReason = EGlobalSDFFullRecaptureReason::None; // Bounds in the volume texture to update. TArray> UpdateBounds; }; class FGlobalDistanceFieldInfo { public: bool bInitialized = false; TArray MostlyStaticClipmaps; TArray Clipmaps; FGlobalDistanceFieldParameterData ParameterData; TRefCountPtr PageFreeListAllocatorBuffer; TRefCountPtr PageFreeListBuffer; TRefCountPtr PageAtlasTexture; TRefCountPtr CoverageAtlasTexture; TRefCountPtr PageObjectGridBuffer; TRefCountPtr PageTableCombinedTexture; TRefCountPtr PageTableLayerTextures[GDF_Num]; TRefCountPtr MipTexture; void UpdateParameterData(float MaxOcclusionDistance, bool bLumenEnabled, float LumenSceneViewDistance, FVector PreViewTranslation); }; const int32 GMaxForwardShadowCascades = 4; BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT_WITH_CONSTRUCTOR(FForwardLightUniformParameters, ) SHADER_PARAMETER(uint32, NumLocalLights) SHADER_PARAMETER(uint32, NumDirectionalLights) SHADER_PARAMETER(uint32, NumReflectionCaptures) SHADER_PARAMETER(uint32, HasDirectionalLight) SHADER_PARAMETER(uint32, NumGridCells) SHADER_PARAMETER(FIntVector, CulledGridSize) SHADER_PARAMETER(uint32, MaxCulledLightsPerCell) SHADER_PARAMETER(uint32, LightGridPixelSizeShift) SHADER_PARAMETER(FVector3f, LightGridZParams) SHADER_PARAMETER(FVector3f, DirectionalLightDirection) SHADER_PARAMETER(float, DirectionalLightSourceRadius) SHADER_PARAMETER(float, DirectionalLightSoftSourceRadius) SHADER_PARAMETER(FVector3f, DirectionalLightColor) SHADER_PARAMETER(float, DirectionalLightVolumetricScatteringIntensity) SHADER_PARAMETER(float, DirectionalLightSpecularScale) SHADER_PARAMETER(float, DirectionalLightDiffuseScale) SHADER_PARAMETER(uint32, DirectionalLightSceneInfoExtraDataPacked) SHADER_PARAMETER(FVector2f, DirectionalLightDistanceFadeMAD) SHADER_PARAMETER(uint32, NumDirectionalLightCascades) SHADER_PARAMETER(int32, DirectionalLightVSM) SHADER_PARAMETER(FVector4f, CascadeEndDepths) SHADER_PARAMETER_ARRAY(FMatrix44f, DirectionalLightTranslatedWorldToShadowMatrix, [GMaxForwardShadowCascades]) SHADER_PARAMETER_ARRAY(FVector4f, DirectionalLightShadowmapMinMax, [GMaxForwardShadowCascades]) SHADER_PARAMETER(FVector4f, DirectionalLightShadowmapAtlasBufferSize) SHADER_PARAMETER(float, DirectionalLightDepthBias) SHADER_PARAMETER(uint32, DirectionalLightUseStaticShadowing) SHADER_PARAMETER(uint32, DirectionalLightHandledByMegaLights) SHADER_PARAMETER(uint32, DirectionalMegaLightsSupportedStartIndex) SHADER_PARAMETER(FVector4f, DirectionalLightStaticShadowBufferSize) SHADER_PARAMETER(FMatrix44f, DirectionalLightTranslatedWorldToStaticShadow) SHADER_PARAMETER(uint32, DirectLightingShowFlag) SHADER_PARAMETER(uint32, CulledBufferOffsetISR) SHADER_PARAMETER(uint32, LightFunctionAtlasLightIndex) SHADER_PARAMETER(uint32, bAffectsTranslucentLighting) SHADER_PARAMETER(FVector4f, PreViewTranslationOffsetISR) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DirectionalLightShadowmapAtlas) SHADER_PARAMETER_SAMPLER(SamplerState, ShadowmapSampler) SHADER_PARAMETER_TEXTURE(Texture2D, DirectionalLightStaticShadowmap) SHADER_PARAMETER_SAMPLER(SamplerState, StaticShadowmapSampler) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ForwardLightBuffer) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, NumCulledLightsGrid) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, CulledLightDataGrid32Bit) SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, CulledLightDataGrid16Bit) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, DirectionalLightIndices) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, LightViewData) END_GLOBAL_SHADER_PARAMETER_STRUCT() extern TRDGUniformBufferRef CreateDummyForwardLightUniformBuffer(FRDGBuilder& GraphBuilder, EShaderPlatform ShaderPlatform); extern void SetDummyForwardLightUniformBufferOnViews(FRDGBuilder& GraphBuilder, EShaderPlatform ShaderPlatform, TArray& Views); class FForwardLightingViewResources { public: void SetUniformBuffer(TRDGUniformBufferRef UniformBuffer) { check(UniformBuffer); ForwardLightUniformBuffer = UniformBuffer; ForwardLightUniformParameters = UniformBuffer->GetContents(); } const FForwardLightUniformParameters* ForwardLightUniformParameters = nullptr; TRDGUniformBufferRef ForwardLightUniformBuffer = nullptr; const FLightSceneProxy* SelectedForwardDirectionalLightProxy = nullptr; // Buffers shared between primary and secondary view in single-pass stereo FRDGBufferSRVRef CulledLightDataGridSRV; FRDGBufferUAVRef CulledLightDataGridUAV; FRDGBufferSRVRef NumCulledLightsGridSRV; FRDGBufferUAVRef NumCulledLightsGridUAV; }; BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT_WITH_CONSTRUCTOR(FVolumetricFogGlobalData,) SHADER_PARAMETER(FIntVector,ViewGridSizeInt) SHADER_PARAMETER(FVector3f, ViewGridSize) SHADER_PARAMETER(FIntVector,ResourceGridSizeInt) SHADER_PARAMETER(FVector3f, ResourceGridSize) SHADER_PARAMETER(FVector3f, GridZParams) SHADER_PARAMETER(FVector2f, SVPosToVolumeUV) SHADER_PARAMETER(float, MaxDistance) SHADER_PARAMETER(float, LightSoftFading) SHADER_PARAMETER(FVector3f, HeightFogInscatteringColor) SHADER_PARAMETER(FVector3f, HeightFogDirectionalLightInscatteringColor) SHADER_PARAMETER(FIntPoint, FogGridToPixelXY) END_GLOBAL_SHADER_PARAMETER_STRUCT() extern void SetupVolumetricFogGlobalData(const FViewInfo& View, FVolumetricFogGlobalData& Parameters); struct FTransientLightFunctionTextureAtlasTile { bool bIsDefault; // If true, then the atlas item generation can be skipped FRDGTextureRef Texture; FIntRect RectBound; FVector4f MinMaxUvBound; }; struct FVolumetricFogLocalLightFunctionInfo { FTransientLightFunctionTextureAtlasTile AtlasTile; FMatrix44f LightFunctionTranslatedWorldToLightMatrix; }; class FVolumetricFogViewResources { public: TUniformBufferRef VolumetricFogGlobalData; FRDGTextureRef IntegratedLightScatteringTexture = nullptr; FVolumetricFogViewResources() {} void Release() { IntegratedLightScatteringTexture = nullptr; } }; struct FVolumetricMeshBatch { const FMeshBatch* Mesh; const FPrimitiveSceneProxy* Proxy; FVolumetricMeshBatch(const FMeshBatch* M, const FPrimitiveSceneProxy* P) : Mesh(M) , Proxy(P) {} FORCEINLINE bool operator==(const FVolumetricMeshBatch& rhs) const { return (Mesh->MeshIdInPrimitive == rhs.Mesh->MeshIdInPrimitive) && (Proxy == rhs.Proxy); } }; struct FSkyMeshBatch { const FMeshBatch* Mesh; const FPrimitiveSceneProxy* Proxy; bool bVisibleInMainPass : 1; bool bVisibleInRealTimeSkyCapture : 1; }; struct FSortedTrianglesMeshBatch { const FMeshBatch* Mesh = nullptr; const FPrimitiveSceneProxy* Proxy = nullptr; }; // DX11 maximum 2d texture array size is D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION = 2048, and 2048/6 = 341.33. UE_DEPRECATED(5.4, "Using GMaxNumReflectionCaptures directly is deprecated. Please use GetMaxNumReflectionCaptures(EShaderPlatform) instead") static const int32 GMaxNumReflectionCaptures = 341; /** Per-reflection capture data needed by the shader. */ PRAGMA_DISABLE_DEPRECATION_WARNINGS BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FReflectionCaptureShaderData,) SHADER_PARAMETER_ARRAY(FVector4f,PositionHighAndRadius,[GMaxNumReflectionCaptures]) // W is unused SHADER_PARAMETER_ARRAY(FVector4f,PositionLow,[GMaxNumReflectionCaptures]) // R is brightness, G is array index, B is shape SHADER_PARAMETER_ARRAY(FVector4f,CaptureProperties,[GMaxNumReflectionCaptures]) SHADER_PARAMETER_ARRAY(FVector4f,CaptureOffsetAndAverageBrightness,[GMaxNumReflectionCaptures]) // Stores the box transform for a box shape, other data is packed for other shapes SHADER_PARAMETER_ARRAY(FMatrix44f,BoxTransform,[GMaxNumReflectionCaptures]) SHADER_PARAMETER_ARRAY(FVector4f,BoxScales,[GMaxNumReflectionCaptures]) END_GLOBAL_SHADER_PARAMETER_STRUCT() PRAGMA_ENABLE_DEPRECATION_WARNINGS UE_DEPRECATED(5.4, "Using GMobileMaxNumReflectionCaptures directly is deprecated. Please use GetMaxNumReflectionCaptures(EShaderPlatform) instead") static const int32 GMobileMaxNumReflectionCaptures = 100; PRAGMA_DISABLE_DEPRECATION_WARNINGS BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FMobileReflectionCaptureShaderData, ) SHADER_PARAMETER_ARRAY(FVector4f,PositionHighAndRadius,[GMobileMaxNumReflectionCaptures]) // W is unused SHADER_PARAMETER_ARRAY(FVector4f,PositionLow,[GMobileMaxNumReflectionCaptures]) // R is brightness, G is array index, B is shape SHADER_PARAMETER_ARRAY(FVector4f,CaptureProperties,[GMobileMaxNumReflectionCaptures]) SHADER_PARAMETER_ARRAY(FVector4f,CaptureOffsetAndAverageBrightness,[GMobileMaxNumReflectionCaptures]) // Stores the box transform for a box shape, other data is packed for other shapes SHADER_PARAMETER_ARRAY(FMatrix44f,BoxTransform,[GMobileMaxNumReflectionCaptures]) SHADER_PARAMETER_ARRAY(FVector4f,BoxScales,[GMobileMaxNumReflectionCaptures]) END_GLOBAL_SHADER_PARAMETER_STRUCT() PRAGMA_ENABLE_DEPRECATION_WARNINGS extern int32 GetMaxNumReflectionCaptures(EShaderPlatform ShaderPlatform); // Structure in charge of storing all information about TAA's history. struct FTemporalAAHistory { // Number of render target in the history. static constexpr int32 kRenderTargetCount = 2; // Render targets holding's pixel history. // scene color's RGBA are in OutputRT[0]. TStaticArray, kRenderTargetCount> RT; // Reference size of RT. Might be different than RT's actual size to handle down res. FIntPoint ReferenceBufferSize; // Viewport coordinate of the history in RT according to ReferenceBufferSize. FIntRect ViewportRect; // Returns the slice index that contains the output in RT[0]. int32 OutputSliceIndex = 0; void SafeRelease() { *this = FTemporalAAHistory(); } bool IsValid() const { return RT[0].IsValid(); } uint64 GetGPUSizeBytes(bool bLogSizes) const; }; // Structure in charge of storing all information about TSR's history. struct FTSRHistory { // Output resolution. TRefCountPtr ColorArray; TRefCountPtr MetadataArray; // Input resolution representation of the output TRefCountPtr GuideArray; TRefCountPtr MoireArray; TRefCountPtr CoverageArray; // Frame's input and output resolution. FIntRect InputViewportRect; FIntRect OutputViewportRect; // Format of the history for auto camera cut when setting change. uint32 FormatBit = 0; // Number of frame in history. int32 FrameStorageCount = 1; int32 FrameStoragePeriod = 1; int32 AccumulatedFrameCount = 1; int32 LastFrameRollingIndex = 0; // All the information the previous frames for resurrection. TArray ViewMatrices; TArray SceneColorPreExposures; TArray InputViewportRects; TArray> DistortingDisplacementTextures; void SafeRelease() { *this = FTSRHistory(); } bool IsValid() const { return MetadataArray.IsValid(); } uint64 GetGPUSizeBytes(bool bLogSizes) const; }; /** Temporal history for a denoiser. */ struct FScreenSpaceDenoiserHistory { // Number of history render target to store. static constexpr int32 RTCount = 3; // Scissors of valid data in the render target (can be multiple if there are split screen views) TArray> Scissors; // Render target specific to the history. TStaticArray, RTCount> RT; // The texture for tile classification. TRefCountPtr TileClassification; void SafeRelease() { for (int32 i = 0; i < RTCount; i++) RT[i].SafeRelease(); TileClassification.SafeRelease(); } bool IsValid() const { return RT[0].IsValid(); } uint64 GetGPUSizeBytes(bool bLogSizes) const; }; // Structure for storing a frame of GTAO history. struct FGTAOTAAHistory { // Render targets holding a frame's pixel history. // scene color's RGBA are in RT[0]. TRefCountPtr RT; // Reference size of RT. Might be different than RT's actual size to handle down res. FIntPoint ReferenceBufferSize; // Viewport coordinate of the history in RT according to ReferenceBufferSize. FIntRect ViewportRect; void SafeRelease() { RT.SafeRelease(); } bool IsValid() const { return RT.IsValid(); } }; // Structure that hold all information related to previous frame. struct FPreviousViewInfo { // View rect FIntRect ViewRect; // View matrices. FViewMatrices ViewMatrices; // Scene color's PreExposure. float SceneColorPreExposure = 1.0f; bool bUsesGlobalDistanceField = false; // Depth buffer and Normals of the previous frame generating this history entry for bilateral kernel rejection. TRefCountPtr DepthBuffer; TRefCountPtr GBufferA; TRefCountPtr GBufferB; TRefCountPtr GBufferC; TRefCountPtr HZB; TRefCountPtr NaniteHZB; // Distorting displacement texture applied. TRefCountPtr DistortingDisplacementTexture; // Bit mask used to interpret per-instance occlusion query results for this view. // Expected to contain a single active bit or zero if instance occlusion query data is not available. // See FInstanceCullingOcclusionQueryRenderer. uint32 InstanceOcclusionQueryMask = 0; // Compressed scene textures for bandwidth efficient bilateral kernel rejection. // DeviceZ as float16, and normal in view space. TRefCountPtr CompressedDepthViewNormal; // 16bit compressed depth buffer with opaque only. TRefCountPtr CompressedOpaqueDepth; // R8_UINT Shading model ID with opaque only. TRefCountPtr CompressedOpaqueShadingModel; // Bleed free scene color to use for screen space ray tracing. TRefCountPtr ScreenSpaceRayTracingInput; // Temporal AA result of last frame FTemporalAAHistory TemporalAAHistory; // Temporal Super Resolution result of last frame FTSRHistory TSRHistory; // Custom Temporal AA result of last frame, used by plugins TRefCountPtr ThirdPartyTemporalUpscalerHistory; // Half resolution version temporal AA result of last frame TRefCountPtr HalfResTemporalAAHistory; // Temporal AA history for diaphragm DOF. FTemporalAAHistory DOFSetupHistory; // Temporal AA history for SSR FTemporalAAHistory SSRHistory; FTemporalAAHistory WaterSSRHistory; // Temporal AA history for Rough refraction FTemporalAAHistory RoughRefractionHistory; // Temporal AA history for Hair FTemporalAAHistory HairHistory; #if UE_ENABLE_DEBUG_DRAWING // Temporal AA history for the editor primitive depth upsampling FTemporalAAHistory CompositePrimitiveDepthHistory; #endif // Scene color input for SSR, that can be different from TemporalAAHistory.RT[0] if there is a SSR // input post process material. FTemporalAAHistory CustomSSRInput; // History for the reflections FScreenSpaceDenoiserHistory ReflectionsHistory; FScreenSpaceDenoiserHistory WaterReflectionsHistory; // History for the ambient occlusion FScreenSpaceDenoiserHistory AmbientOcclusionHistory; // History for GTAO FGTAOTAAHistory GTAOHistory; // History for global illumination FScreenSpaceDenoiserHistory DiffuseIndirectHistory; // History for sky light FScreenSpaceDenoiserHistory SkyLightHistory; // History for reflected sky light FScreenSpaceDenoiserHistory ReflectedSkyLightHistory; // History for shadow denoising. TMap> ShadowHistories; // History for denoising all lights penumbra at once. FScreenSpaceDenoiserHistory PolychromaticPenumbraHarmonicsHistory; // History for the final back buffer luminance TRefCountPtr LuminanceHistory; // History for the final back buffer luminance view rect FIntRect LuminanceViewRectHistory; // Mobile bloom setup eye adaptation surface. TRefCountPtr MobileBloomSetup_EyeAdaptation; // Mobile ambient occlusion texture used for next frame. TRefCountPtr MobileAmbientOcclusion = nullptr; // Scene color used for reprojecting next frame to verify the motion vector reprojects correctly. TRefCountPtr VisualizeMotionVectors; FIntRect VisualizeMotionVectorsRect; bool bIsVisualizeMotionVectorsDistorted = false; uint64 GetGPUSizeBytes(bool bLogSizes) const; }; #if RHI_RAYTRACING namespace RayTracing { enum class ECullingMode : uint8; }; struct FRayTracingCullingParameters { RayTracing::ECullingMode CullingMode; float CullingRadius; float FarFieldCullingRadius; float CullAngleThreshold; float AngleThresholdRatio; float AngleThresholdRatioSq; FVector ViewOrigin; FVector ViewDirection; FVector3f TranslatedViewOrigin; bool bCullAllObjects; bool bCullByRadiusOrDistance; bool bIsRayTracingFarField; bool bCullUsingGroupIds; bool bCullMinDrawDistance; bool bUseInstanceCulling; void Init(FViewInfo& View); }; #endif struct FPrimitiveInstanceRange { int32 PrimitiveIndex; int32 InstanceSceneDataOffset; int32 NumInstances; }; /** A FSceneView with additional state used by the scene renderer. */ class FViewInfo : public FSceneView { public: FSceneRenderingBulkObjectAllocator Allocator; /* Final position of the view in the final render target (in pixels), potentially scaled by ScreenPercentage */ FIntRect ViewRect; /** * The view's state, or NULL if no state exists. * This should be used internally to the renderer module to avoid having to cast View.State to an FSceneViewState* */ FSceneViewState* ViewState; /** Cached view uniform shader parameters, to allow recreating the view uniform buffer without having to fill out the entire struct. */ TUniquePtr CachedViewUniformShaderParameters; /** A map from primitive ID to a boolean visibility value. */ FSceneBitArray PrimitiveVisibilityMap; /** A map from primitive ID to a boolean ray tracing visibility value. */ FSceneBitArray PrimitiveRayTracingVisibilityMap; /** Bit set when a primitive is known to be un-occluded. */ FSceneBitArray PrimitiveDefinitelyUnoccludedMap; /** A map from primitive ID to a boolean is fading value. */ FSceneBitArray PotentiallyFadingPrimitiveMap; /** Primitive fade uniform buffers, indexed by packed primitive index. */ TArray PrimitiveFadeUniformBuffers; /** Bit set when a primitive has a valid fade uniform buffer. */ FSceneBitArray PrimitiveFadeUniformBufferMap; /** One frame dither fade in uniform buffer. */ FUniformBufferRHIRef DitherFadeInUniformBuffer; /** One frame dither fade out uniform buffer. */ FUniformBufferRHIRef DitherFadeOutUniformBuffer; /** A map from primitive ID to the primitive's view relevance. */ TArray PrimitiveViewRelevanceMap; /** A map from static mesh ID to a boolean visibility value. */ FSceneBitArray StaticMeshVisibilityMap; /** A map from static mesh ID to a boolean dithered LOD fade out value. */ FSceneBitArray StaticMeshFadeOutDitheredLODMap; /** A map from static mesh ID to a boolean dithered LOD fade in value. */ FSceneBitArray StaticMeshFadeInDitheredLODMap; /** Will only contain relevant primitives for view and/or shadow */ TArray PrimitivesLODMask; /** The dynamic primitives with simple lights visible in this view. */ TArray VisibleDynamicPrimitivesWithSimpleLights; /** Number of dynamic primitives visible in this view. */ int32 NumVisibleDynamicPrimitives; /** Number of dynamic editor primitives visible in this view. */ int32 NumVisibleDynamicEditorPrimitives; /** Number of dynamic mesh elements per mesh pass (inside FViewInfo::DynamicMeshElements). */ int32 NumVisibleDynamicMeshElements[EMeshPass::Num]; /** List of visible primitives with dirty indirect lighting cache buffers */ TArray DirtyIndirectLightingCacheBufferPrimitives; UE::FMutex DirtyIndirectLightingCacheBufferPrimitivesMutex; /** Maps a single primitive to it's per view translucent self shadow uniform buffer. */ FTranslucentSelfShadowUniformBufferMap TranslucentSelfShadowUniformBufferMap; /** View dependent global distance field clipmap info. */ FGlobalDistanceFieldInfo& GlobalDistanceFieldInfo = *Allocator.Create(); /** Count of translucent prims for this view. */ FTranslucenyPrimCount TranslucentPrimCount; bool bHasDistortionPrimitives; bool bHasCustomDepthPrimitives; /** Get all stencil values written into the custom depth pass */ TSet, SceneRenderingSetAllocator> CustomDepthStencilValues; /** Get the GPU Scene instance ranges of visible Nanite primitives writing custom depth. */ TArray NaniteCustomDepthInstances; /** Mesh batches with a volumetric material. */ TArray VolumetricMeshBatches; /** Mesh batches for heterogeneous volumes rendering. */ TArray HeterogeneousVolumesMeshBatches; /** Mesh batches with a sky material. */ TArray SkyMeshBatches; /** Mesh batches with a triangle sorting. */ TArray SortedTrianglesMeshBatches; /** A map from light ID to a boolean visibility value. */ TArray VisibleLightInfos; /** Tracks the list of visible reflection capture lights that need to add meshes to the view. */ TArray VisibleReflectionCaptureLights; /** The view's batched elements. */ FBatchedElements& BatchedViewElements = *Allocator.Create(); /** The view's batched elements, above all other elements, for gizmos that should never be occluded. */ FBatchedElements& TopBatchedViewElements = *Allocator.Create(); /** The view's mesh elements. */ TIndirectArray ViewMeshElements; /** The view's mesh elements for the foreground (editor gizmos and primitives )*/ TIndirectArray TopViewMeshElements; /** The dynamic resources used by the view elements. */ TArray DynamicResources; /** Gathered in initviews from all the primitives with dynamic view relevance, used in each mesh pass. */ TArray DynamicMeshElements; /* [PrimitiveIndex] = end index index in DynamicMeshElements[], to support GetDynamicMeshElementRange(). Contains valid values only for visible primitives with bDynamicRelevance. */ TArray DynamicMeshElementRanges; /** Hair strands & cards dynamic mesh element. */ TArray HairStrandsMeshElements; TArray HairCardsMeshElements; /* Mesh pass relevance for gathered dynamic mesh elements. */ TArray DynamicMeshElementsPassRelevance; /** Gathered in UpdateRayTracingWorld from all the primitives with dynamic view relevance, used in each mesh pass. */ TArray RayTracedDynamicMeshElements; TArray DynamicEditorMeshElements; FSimpleElementCollector& SimpleElementCollector = *Allocator.Create(); FSimpleElementCollector& EditorSimpleElementCollector = *Allocator.Create();; #if UE_ENABLE_DEBUG_DRAWING //Separate DebugSimpleElementCollector to not conflate any other simple element collector draws which may have been added from non-debug draw passes (e.g. non-opaque draws) FSimpleElementCollector& DebugSimpleElementCollector = *Allocator.Create();; #endif FParallelMeshDrawCommandPass* CreateMeshPass(EMeshPass::Type MeshPass); TStaticArray ParallelMeshDrawCommandPasses = TStaticArray(InPlace, nullptr); #if RHI_RAYTRACING FRayTracingShaderBindingDataOneFrameArray DirtyPersistentRayTracingShaderBindings; FRayTracingShaderBindingDataOneFrameArray VisibleRayTracingShaderBindings; FDynamicRayTracingMeshCommandStorage DynamicRayTracingMeshCommandStorage; TSet DynamicRayTracingRDGBuffers; FRayTracingCullingParameters RayTracingCullingParameters; UE::Tasks::FTask RayTracingSceneInitTask; // Task to asynchronously call RayTracingScene.BuildInitializationData() UE::Tasks::FTask VisibleRayTracingShaderBindingsFinalizeTask; TArray AddDynamicRayTracingMeshBatchTaskList; TArray DynamicRayTracingShaderBindingsPerTask; TArray DynamicRayTracingMeshCommandStoragePerTask; #endif // Used by mobile renderer to determine whether static meshes will be rendered with CSM shaders or not. FMobileCSMVisibilityInfo MobileCSMVisibilityInfo; FSubstrateViewData& SubstrateViewData = *Allocator.Create(); FLocalFogVolumeViewData& LocalFogVolumeViewData = *Allocator.Create(); FHairStrandsViewData& HairStrandsViewData = *Allocator.Create(); LightFunctionAtlas::FLightFunctionAtlasViewData LightFunctionAtlasViewData; /** Parameters for exponential height fog. */ FVector4f ExponentialFogParameters; FVector4f ExponentialFogParameters2; FVector3f ExponentialFogColor; float FogMaxOpacity; FVector4f ExponentialFogParameters3; FVector4f SkyAtmosphereAmbientContributionColorScale; float FogEndDistance; bool bEnableVolumetricFog; float VolumetricFogStartDistance; float VolumetricFogNearFadeInDistanceInv; FVector3f VolumetricFogAlbedo; float VolumetricFogPhaseG; FVector2f SinCosInscatteringColorCubemapRotation; UTexture* FogInscatteringColorCubemap; FVector FogInscatteringTextureParameters; /** Parameters for directional inscattering of exponential height fog. */ bool bUseDirectionalInscattering; float DirectionalInscatteringExponent; float DirectionalInscatteringStartDistance; FVector InscatteringLightDirection; FLinearColor DirectionalInscatteringColor; /** Translucency lighting volume properties. */ FVector TranslucencyLightingVolumeMin[TVC_MAX]; float TranslucencyVolumeVoxelSize[TVC_MAX]; FVector TranslucencyLightingVolumeSize[TVC_MAX]; /** Optional source view for temporal AA, to handle custom render passes and scene captures sharing the main view's camera (jitter needs to match) */ FViewInfo* TemporalSourceView; /** Number of samples in the temporal AA sequqnce */ int32 TemporalJitterSequenceLength; /** Index of the temporal AA jitter in the sequence. */ int32 TemporalJitterIndex; /** Temporal AA jitter at the pixel scale. */ FVector2D TemporalJitterPixels; /** Whether FSceneViewState::PrevFrameViewInfo can be updated with this view. */ uint32 bStatePrevViewInfoIsReadOnly : 1; /** true if all PrimitiveVisibilityMap's bits are set to false. */ uint32 bHasNoVisiblePrimitive : 1; /** true if the view has at least one mesh with a translucent material. */ uint32 bHasTranslucentViewMeshElements : 1; /** Indicates whether previous frame transforms were reset this frame for any reason. */ uint32 bPrevTransformsReset : 1; /** Whether we should ignore queries from last frame (useful to ignoring occlusions on the first frame after a large camera movement). */ uint32 bIgnoreExistingQueries : 1; /** Whether we should submit new queries this frame. (used to disable occlusion queries completely. */ uint32 bDisableQuerySubmissions : 1; /** Whether the view has any materials that use the global distance field. */ uint32 bUsesGlobalDistanceField : 1; uint32 bUsesLightingChannels : 1; uint32 bTranslucentSurfaceLighting : 1; uint32 bCustomDepthStencilValid : 1; uint32 bUsesCustomDepth : 1; uint32 bUsesCustomStencil : 1; /** Whether fog should only be computed on rendered opaque pixels or not. */ uint32 bFogOnlyOnRenderedOpaque : 1; /** * true if the scene has at least one mesh with a material tagged as sky. * This is used to skip the sky rendering part during the SkyAtmosphere pass on non mobile platforms. */ uint32 bSceneHasSkyMaterial : 1; /** * true if the scene has at least one mesh with a material tagged as water visible in a view. */ uint32 bHasSingleLayerWaterMaterial : 1; /** * True if the scene has at least one mesh that needs to sample form the first stage depth buffer. * And as such will need to render in the second stage depth buffer after the first stage depth buffer is copied. * The first stage depth buffer is usually used for depth buffer collision and projection of Niagara's particles. */ uint32 bUsesSecondStageDepthPass : 1; /** * Set to true if this is a scene capture sharing temporal AA jitter with the main view camera. Needed to force temporal jitter * logic to run when post processing is disabled for the scene capture, which otherwise disables jitter. */ uint32 bSceneCaptureMainViewJitter : 1; /** Whether post DOF translucency should be rendered before DOF if primitive bounds behind DOF's focus distance. */ float AutoBeforeDOFTranslucencyBoundary; /** Bitmask of all shading models used by primitives in this view */ uint16 ShadingModelMaskInView; /** Informations from the previous frame to use for this view. */ FPreviousViewInfo& PrevViewInfo = *Allocator.Create(); /** An intermediate number of visible static meshes. Doesn't account for occlusion until after FinishOcclusionQueries is called. */ int32 NumVisibleStaticMeshElements; /** Frame's exposure. Always > 0. */ float PreExposure; /** Precomputed visibility data, the bits are indexed by VisibilityId of a primitive component. */ const uint8* PrecomputedVisibilityData; FOcclusionQueryBatcher IndividualOcclusionQueries; FOcclusionQueryBatcher GroupedOcclusionQueries; // Furthest and closest Hierarchical Z Buffer FRDGTextureRef HZB = nullptr; FRDGTextureRef ClosestHZB = nullptr; struct FTranslucencyVolumeMarkData { FRDGTextureRef MarkTexture = nullptr; FRDGBufferRef VoxelAllocator = nullptr; FRDGBufferRef VoxelData = nullptr; FRDGBufferRef VoxelIndirectArgs = nullptr; }; TStaticArray TranslucencyVolumeMarkData = {}; int32 NumBoxReflectionCaptures; int32 NumSphereReflectionCaptures; float FurthestReflectionCaptureDistance; TUniformBufferRef ReflectionCaptureUniformBuffer; TUniformBufferRef MobileReflectionCaptureUniformBuffer; // Sky / Atmosphere textures (transient owned by this view info) and pointer to constants owned by SkyAtmosphere proxy. TRefCountPtr SkyAtmosphereCameraAerialPerspectiveVolume; TRefCountPtr SkyAtmosphereCameraAerialPerspectiveVolumeMieOnly; TRefCountPtr SkyAtmosphereCameraAerialPerspectiveVolumeRayOnly; TRefCountPtr SkyAtmosphereViewLutTexture; const FAtmosphereUniformShaderParameters* SkyAtmosphereUniformShaderParameters; FRDGTextureRef VolumetricCloudSkyAO = nullptr; TUniformBufferRef VolumetricRenderTargetViewUniformBuffer; // The effective cloud shadow target this frame independently of the fact that a view can have a state (primary view) or not (sky light reflection capture) FRDGTextureRef VolumetricCloudShadowRenderTarget[NUM_ATMOSPHERE_LIGHTS] = {}; // We need to extract that RDG resource because the RHI must be accessed to setup FTranslucentLightingInjectPS & TVolumetricFogLightScatteringCS TRefCountPtr VolumetricCloudShadowExtractedRenderTarget[NUM_ATMOSPHERE_LIGHTS] = {}; FForwardLightingViewResources ForwardLightingResources; FVolumetricFogViewResources VolumetricFogResources; bool bLightGridHasRectLights = false; bool bLightGridHasTexturedLights = false; FRDGTextureRef HeterogeneousVolumeRadiance = nullptr; FRDGTextureRef HeterogeneousVolumeHoldout = nullptr; FRDGTextureRef HeterogeneousVolumeBeerShadowMap = nullptr; // Size of the HZB's mipmap 0 // NOTE: the mipmap 0 is downsampled version of the depth buffer FIntPoint HZBMipmap0Size; /** Used by occlusion for percent unoccluded calculations. */ float OneOverNumPossiblePixels; TOptional MobileLightShaft; FGlobalShaderMap* ShaderMap; // Whether this view should use compute passes where appropriate. bool bUseComputePasses = false; // Optional stencil dithering optimization during prepasses bool bAllowStencilDither; // Max emissive luminance ouput by any material for this view. float MaterialMaxEmissiveValue; /** Custom visibility query for view */ ICustomVisibilityQuery* CustomVisibilityQuery; const FTexture2DResource* FFTBloomKernelTexture = nullptr; const FTexture2DResource* FilmGrainTexture = nullptr; TArray IndirectShadowPrimitives; /** Only one of the resources(TextureBuffer or Texture2D) will be used depending on the Mobile.UseGPUSceneTexture cvar */ FTextureRHIRef PrimitiveSceneDataTextureOverrideRHI; FLensDistortionLUT LensDistortionLUT; FShaderPrintData ShaderPrintData; private: FLumenTranslucencyGIVolume& LumenTranslucencyGIVolume = *Allocator.Create(); FMegaLightsVolume MegaLightsVolume; public: FLumenFrontLayerTranslucency LumenFrontLayerTranslucency; inline const FLumenTranslucencyGIVolume& GetLumenTranslucencyGIVolume() const { if (UNLIKELY(bIsInstancedStereoEnabled && ShouldUseStereoLumenOptimizations() && IStereoRendering::IsASecondaryPass(StereoPass))) { return GetPrimaryView()->LumenTranslucencyGIVolume; } return LumenTranslucencyGIVolume; } inline FLumenTranslucencyGIVolume& GetOwnLumenTranslucencyGIVolume() { return LumenTranslucencyGIVolume; } inline const FMegaLightsVolume& GetMegaLightsVolume() const { return MegaLightsVolume; } inline FMegaLightsVolume& GetOwnMegaLightsVolume() { return MegaLightsVolume; } FLumenSceneData* ViewLumenSceneData; #if RHI_RAYTRACING bool HasRayTracingScene() const; FRHIRayTracingScene* GetRayTracingSceneChecked(ERayTracingSceneLayer Layer) const; // Soft-deprecated method, use FScene.RayTracingScene instead. FRDGBufferSRVRef GetRayTracingSceneLayerViewChecked(ERayTracingSceneLayer Layer) const; // Soft-deprecated method, use FScene.RayTracingScene instead. FRDGBufferUAVRef GetRayTracingInstanceHitCountUAV(FRDGBuilder& GraphBuilder) const; struct FRayTracingData { FRayTracingPipelineState* PipelineState = nullptr; FShaderBindingTableRHIRef ShaderBindingTable; TArray MaterialBindings; // One per binding task TArray CallableBindings; // One per binding task FMemStackBase MaterialBindingsMemory; //< Optional stacked based alloc for binding data }; FRayTracingData MaterialRayTracingData; FRayTracingData LumenRayTracingData; FRayTracingData InlineRayTracingData; // Buffer to the shader binding data used for inline raytracing - only valid when inline raytracing is enabled FRDGBufferRef InlineRayTracingBindingDataBuffer = nullptr; // Buffer that stores the hit group data for Lumen passes that use MinimalPayload and inline ray tracing. FRDGBufferRef LumenHardwareRayTracingHitDataBuffer = nullptr; // Global Lumen parameters for CHS, AHS and inline TUniformBufferRef LumenHardwareRayTracingUniformBuffer; // Common resources used for lighting in ray tracing effects TRDGUniformBufferRef RayTracingLightGridUniformBuffer; TRDGUniformBufferRef RayTracingDecalUniformBuffer; bool bHasRayTracingDecals = false; int32 PathTracingVolumetricCloudCallableShaderIndex = -1; bool bHasAnyRayTracingPass = false; bool bHasRayTracingShadows = false; bool bRayTracingFeedbackEnabled = false; #endif // RHI_RAYTRACING /** * Index of the view in the AllViews array on the FSceneRenderer. This view ID is transient and only valid during this frame. * Identical to the ID of the view in the GPU instance culling manager. Among other things, used to fetch the culled draw commands. */ int32 SceneRendererPrimaryViewId; /** */ FPersistentViewId PersistentViewId; /* View rect for all instanced views laid out side-by-side. Only primary view will have it populated. * * This may be different than FamilySize if we're using adaptive resolution stereo rendering. In that case, FamilySize represents the maximum size of * the family to ensure the backing render targets don't change between frames as the view size varies. */ FIntRect ViewRectWithSecondaryViews; #if WITH_EDITOR TArray EditorVisualizeLevelInstancesNanite; TArray EditorSelectedInstancesNanite; TArray EditorSelectedNaniteHitProxyIds; #endif /** * Initialization constructor. Passes all parameters to FSceneView constructor */ RENDERER_API FViewInfo(const FSceneViewInitOptions& InitOptions); /** * Initialization constructor. * @param InView - copy to init with */ explicit FViewInfo(const FSceneView* InView); /** * Destructor. */ RENDERER_API virtual ~FViewInfo(); #if DO_CHECK || USING_CODE_ANALYSIS /** Verifies all the assertions made on members. */ bool VerifyMembersChecks() const; #endif /** Returns the size of view rect after primary upscale ( == only with secondary screen percentage). */ RENDERER_API FIntPoint GetSecondaryViewRectSize() const; /** Returns the rectangle to crop to during the secondary upscale */ RENDERER_API FIntRect GetSecondaryViewCropRect() const; /** Returns whether the view requires a secondary upscale. */ bool RequiresSecondaryUpscale() const { return UnscaledViewRect.Size() != GetSecondaryViewRectSize() || GetSecondaryViewCropRect().Size() != GetSecondaryViewRectSize(); } /** Compute the pre-exposure of internal renderer resources. */ void UpdatePreExposure(); /** Creates ViewUniformShaderParameters given a set of view transforms. */ RENDERER_API void SetupUniformBufferParameters( const FViewMatrices& InViewMatrices, const FViewMatrices& InPrevViewMatrices, FBox* OutTranslucentCascadeBoundsArray, int32 NumTranslucentCascades, FViewUniformShaderParameters& ViewUniformShaderParameters) const; /** Recreates ViewUniformShaderParameters, taking the view transform from the View Matrices */ inline void SetupUniformBufferParameters( FBox* OutTranslucentCascadeBoundsArray, int32 NumTranslucentCascades, FViewUniformShaderParameters& ViewUniformShaderParameters) const { SetupUniformBufferParameters( ViewMatrices, PrevViewInfo.ViewMatrices, OutTranslucentCascadeBoundsArray, NumTranslucentCascades, ViewUniformShaderParameters); } void SetupDefaultGlobalDistanceFieldUniformBufferParameters(FViewUniformShaderParameters& ViewUniformShaderParameters) const; void SetupGlobalDistanceFieldUniformBufferParameters(FViewUniformShaderParameters& ViewUniformShaderParameters) const; void SetupVolumetricFogUniformBufferParameters(FViewUniformShaderParameters& ViewUniformShaderParameters) const; /** Initializes the RHI resources used by this view. OverrideNumMSAASamples can optionally override NumSceneColorMSAASamples (needed for editor views) */ void InitRHIResources(uint32 OverrideNumMSAASamples = 0); /** Creates both ViewUniformBuffer and InstancedViewUniformBuffer (if needed). */ void CreateViewUniformBuffers(const FViewUniformShaderParameters& Params); /** Determines distance culling and fades if the state changes */ bool IsDistanceCulled(float DistanceSquared, float MinDrawDistance, float InMaxDrawDistance, const FPrimitiveSceneInfo* PrimitiveSceneInfo); bool IsDistanceCulled_AnyThread(float DistanceSquared, float MinDrawDistance, float InMaxDrawDistance, const FPrimitiveSceneInfo* PrimitiveSceneInfo, bool& bOutMayBeFading, bool& bOutFadingIn) const; /** @return - whether this primitive has completely faded out */ bool UpdatePrimitiveFadingState(const FPrimitiveSceneInfo* PrimitiveSceneInfo, bool bFadingIn); /** Allocates and returns the current eye adaptation texture. */ using FSceneView::GetEyeAdaptationTexture; IPooledRenderTarget* GetEyeAdaptationTexture(FRDGBuilder& GraphBuilder) const; /** Allocates and returns the current eye adaptation buffer. */ using FSceneView::GetEyeAdaptationBuffer; FRDGPooledBuffer* GetEyeAdaptationBuffer(FRDGBuilder& GraphBuilder) const; /** Get the last valid exposure value for eye adaptation. */ float GetLastEyeAdaptationExposure() const; /** Get the last valid average local exposure value. */ float GetLastAverageLocalExposure() const; /** Get the last valid average scene luminance for eye adaptation (exposure compensation curve). */ float GetLastAverageSceneLuminance() const; /**Swap the order of the two eye adaptation targets in the double buffer system */ void SwapEyeAdaptationBuffers() const; /** Update Last Exposure with the most recent available value */ void UpdateEyeAdaptationLastExposureFromBuffer() const; /** Enqueue a pass to readback current exposure */ void EnqueueEyeAdaptationExposureBufferReadback(FRDGBuilder& GraphBuilder) const; /** Returns whether the current view should update the eye adaptation state */ bool ShouldUpdateEyeAdaptationBuffer() const; /** Informs sceneinfo that tonemapping LUT has queued commands to compute it at least once */ void SetValidTonemappingLUT() const; /** Gets the tonemapping LUT texture, previously computed by the CombineLUTS post process, * for stereo rendering, this will force the post-processing to use the same texture for both eyes*/ IPooledRenderTarget* GetTonemappingLUT() const; /** Gets the rendertarget that will be populated by CombineLUTS post process * for stereo rendering, this will force the post-processing to use the same render target for both eyes*/ IPooledRenderTarget* GetTonemappingLUT(FRHICommandList& RHICmdList, const int32 LUTSize, const bool bUseVolumeLUT, const bool bNeedUAV, const bool bNeedFloatOutput) const; bool IsFirstInFamily() const { return Family->Views[0] == this; } bool IsLastInFamily() const { return Family->Views.Last() == this; } ERenderTargetLoadAction DecayLoadAction(ERenderTargetLoadAction RequestedLoadAction) const { return IsFirstInFamily() || Family->bMultiGPUForkAndJoin ? RequestedLoadAction : ERenderTargetLoadAction::ELoad; } /** Instanced stereo and multi-view only need to render the left eye. */ bool ShouldRenderView() const { if (bHasNoVisiblePrimitive) { return false; } else if (!bIsSinglePassStereo) { return true; } else if (bIsSinglePassStereo && !IStereoRendering::IsASecondaryPass(StereoPass)) { return true; } else { return false; } } /** Returns view rect for all views in the family (usable for atlased views only). Normally a union of their view rects */ FIntRect GetFamilyViewRect() const; /** Similar to above, but returns the unscaled rect, ignoring dynamic resolution scaling */ FIntRect GetUnscaledFamilyViewRect() const; /** Prepares the view shader parameters for rendering and calls the persistent uniform buffer hooks. */ void BeginRenderView() const; /** Returns the set of view uniform buffers representing this view. */ FViewShaderParameters GetShaderParameters() const; /** Returns the primary view associated with the input view, or null if none exists. */ const FViewInfo* GetPrimaryView() const; /** Returns the instanced view associated with the input view, or null if none exists. */ inline const FViewInfo* GetInstancedView() const { return static_cast(GetInstancedSceneView()); } /** Create a snapshot of this view info on the scene allocator. */ FViewInfo* CreateSnapshot() const; void WaitForTasks(); // Get the range in DynamicMeshElements[] for a given PrimitiveIndex // @return range (start is inclusive, end is exclusive) FInt32Range GetDynamicMeshElementRange(uint32 PrimitiveIndex) const; /** Get scene textures or config from the view family associated with this view */ const FSceneTexturesConfig& GetSceneTexturesConfig() const; const FSceneTextures& GetSceneTextures() const; const FSceneTextures* GetSceneTexturesChecked() const; FSceneUniformBuffer& GetSceneUniforms() const; RENDERER_API FRDGTextureRef GetVolumetricCloudTexture(FRDGBuilder& GraphBuilder) const; /** Return true if this view requires the use of debug material permutations. */ bool RequiresDebugMaterials() const; /** * Collector for view-dependent data. */ FGPUScenePrimitiveCollector DynamicPrimitiveCollector; FGPUScenePrimitiveCollector RayTracingDynamicPrimitiveCollector; private: // Cache of TEXTUREGROUP_World to create view's samplers on render thread. // may not have a valid value if FViewInfo is created on the render thread. ESamplerFilter WorldTextureGroupSamplerFilter; ESamplerFilter TerrainWeightmapTextureGroupSamplerFilter; int32 WorldTextureGroupMaxAnisotropy; bool bIsValidTextureGroupSamplerFilters; FSceneViewState* GetEyeAdaptationViewState() const; /** Initialization that is common to the constructors. */ void Init(); /** Calculates bounding boxes for the translucency lighting volume cascades. */ void CalcTranslucencyLightingVolumeBounds(FBox* InOutCascadeBoundsArray, int32 NumCascades) const; }; /** * Masks indicating for which views a primitive needs to have a certain operation on. * One entry per primitive in the scene. */ typedef TArray FPrimitiveViewMasks; class FShadowMapRenderTargetsRefCounted { public: // This structure gets included in FCachedShadowMapData, so avoid SceneRenderingAllocator use! TArray, TInlineAllocator<4>> ColorTargets; TRefCountPtr DepthTarget; bool IsValid() const { if (DepthTarget) { return true; } else { return ColorTargets.Num() > 0; } } FIntPoint GetSize() const { const FPooledRenderTargetDesc* Desc = NULL; if (DepthTarget) { Desc = &DepthTarget->GetDesc(); } else { check(ColorTargets.Num() > 0); Desc = &ColorTargets[0]->GetDesc(); } return Desc->Extent; } int64 ComputeMemorySize() const { int64 MemorySize = 0; for (int32 i = 0; i < ColorTargets.Num(); i++) { MemorySize += ColorTargets[i]->ComputeMemorySize(); } if (DepthTarget) { MemorySize += DepthTarget->ComputeMemorySize(); } return MemorySize; } void Release() { for (int32 i = 0; i < ColorTargets.Num(); i++) { ColorTargets[i] = NULL; } ColorTargets.Empty(); DepthTarget = NULL; } }; struct FSortedShadowMapAtlas { FShadowMapRenderTargetsRefCounted RenderTargets; TArray Shadows; }; struct FSortedShadowMaps { /** Visible shadows sorted by their shadow depth map render target. */ TArray ShadowMapAtlases; TArray ShadowMapCubemaps; FSortedShadowMapAtlas PreshadowCache; TArray TranslucencyShadowMapAtlases; TArray VirtualShadowMapShadows; TArray CompleteShadowMapAtlases; void Release(); int64 ComputeMemorySize() const { int64 MemorySize = 0; for (int i = 0; i < ShadowMapAtlases.Num(); i++) { MemorySize += ShadowMapAtlases[i].RenderTargets.ComputeMemorySize(); } for (int i = 0; i < ShadowMapCubemaps.Num(); i++) { MemorySize += ShadowMapCubemaps[i].RenderTargets.ComputeMemorySize(); } MemorySize += PreshadowCache.RenderTargets.ComputeMemorySize(); for (int i = 0; i < TranslucencyShadowMapAtlases.Num(); i++) { MemorySize += TranslucencyShadowMapAtlases[i].RenderTargets.ComputeMemorySize(); } return MemorySize; } bool IsEmpty() const { return ShadowMapAtlases.IsEmpty() && ShadowMapCubemaps.IsEmpty() && PreshadowCache.Shadows.IsEmpty() && TranslucencyShadowMapAtlases.IsEmpty() && VirtualShadowMapShadows.IsEmpty() && CompleteShadowMapAtlases.IsEmpty(); } }; struct FOcclusionSubmittedFenceState { FGraphEventRef Fence; uint32 ViewStateUniqueID; }; /** * View family plus associated transient scene textures. */ class FViewFamilyInfo : public FSceneViewFamily { public: explicit FViewFamilyInfo(const FSceneViewFamily& InViewFamily); explicit FViewFamilyInfo(const FSceneViewFamily::ConstructionValues& CVS, const FViewFamilyInfo& MainViewFamily); virtual ~FViewFamilyInfo(); FSceneTexturesConfig SceneTexturesConfig; /** Set to true if this is a scene capture sized to scene texture size */ bool bIsSceneTextureSizedCapture = false; /** Get scene textures associated with this view family -- asserts or checks that they have been initialized */ inline FSceneTextures& GetSceneTextures() { checkf(bIsViewFamilyInfo && SceneTextures->bIsSceneTexturesInitialized, TEXT("FSceneTextures was not initialized. Call FSceneTextures::InitializeViewFamily() first.")); return *SceneTextures; } inline const FSceneTextures& GetSceneTextures() const { checkf(bIsViewFamilyInfo && SceneTextures->bIsSceneTexturesInitialized, TEXT("FSceneTextures was not initialized. Call FSceneTextures::InitializeViewFamily() first.")); return *SceneTextures; } inline FSceneTextures* GetSceneTexturesChecked() { return bIsViewFamilyInfo && SceneTextures->bIsSceneTexturesInitialized ? SceneTextures : nullptr; } inline const FSceneTextures* GetSceneTexturesChecked() const { return bIsViewFamilyInfo && SceneTextures->bIsSceneTexturesInitialized ? SceneTextures : nullptr; } private: friend struct FMinimalSceneTextures; friend struct FSceneTextures; // Structure may be pointed to by multiple FViewFamilyInfo during scene rendering, through CustomRenderPasses. The Owner // (pointed to by FSceneTextures) handles deleting the structure when the scene renderer is destroyed. TRefCountPtr doesn't // work, because the structure is also copied by value, and the copy constructor is disabled for reference counted structures. FSceneTextures* SceneTextures; }; struct FComputeLightGridOutput { FRDGPassRef CompactLinksPass = {}; }; struct FSceneRenderUpdateInputs; class FDeferredShadingSceneRenderer; class FSceneRendererBase : public ISceneRenderer { public: /** The scene being rendered. */ FScene* Scene = nullptr; FSceneRendererBase() {} FSceneRendererBase(FScene& InScene) : Scene(&InScene) {} // Helper functions to retrieve the currently active scene renderer from the GraphBuilder instance. static void SetActiveInstance(FRDGBuilder& GraphBuilder, FSceneRendererBase* SceneRenderer); static FSceneRendererBase* GetActiveInstance(FRDGBuilder& GraphBuilder); // ISceneRenderer interface FScene* GetScene() final override { return Scene; } const FSceneUniformBuffer& GetSceneUniforms() const final override { return SceneUniforms; } FSceneUniformBuffer& GetSceneUniforms() final override { return SceneUniforms; } TRDGUniformBufferRef GetSceneUniformBufferRef(FRDGBuilder& GraphBuilder) override final { return GetSceneUniforms().GetBuffer(GraphBuilder); } void InitSceneExtensionsRenderers(const FEngineShowFlags& EngineShowFlags, bool bValidateCallbacks = false) { SceneExtensionsRenderers.Begin(*this, EngineShowFlags, bValidateCallbacks); } FSceneExtensionsRenderers& GetSceneExtensionsRenderers() { return SceneExtensionsRenderers; } const FSceneExtensionsRenderers& GetSceneExtensionsRenderers() const { return SceneExtensionsRenderers; } /** The views being rendered. */ TArray Views; /** * The view family being rendered. This references the Views array, if it exsists. * A view family is not always set up by all rendering paths, notably not the VT rendering path. */ virtual FViewFamilyInfo* GetViewFamily() { return nullptr; } /** * This is a workaround to allow initialization of scene extension (renderers) that depend on data not yet migrated to other extensions. * Be very careful to not build in new dependencies on this unless * 1. required to make something new better, * 2. you intend to fix this later, pinky promise! */ virtual FDeferredShadingSceneRenderer* GetDeferredShadingSceneRenderer() { return nullptr; } private: FSceneUniformBuffer SceneUniforms; FSceneExtensionsRenderers SceneExtensionsRenderers; }; /** * Used as the scope for scene rendering functions. * It is initialized in the game thread by FSceneViewFamily::BeginRender, and then passed to the rendering thread. * The rendering thread calls Render(), and deletes the scene renderer when it returns. */ class FSceneRenderer : public FSceneRendererBase { public: /** Linear bulk allocator with a lifetime tied to the scene renderer. */ FSceneRenderingBulkObjectAllocator Allocator; /** The view family being rendered. This references the Views array. */ FViewFamilyInfo ViewFamily; /** Information of a custom render pass that renders as part of the main renderer. */ struct FCustomRenderPassInfo { FCustomRenderPassInfo(const FSceneViewFamily::ConstructionValues& CVS); FCustomRenderPassInfo(const FSceneViewFamily::ConstructionValues& CVS, const FViewFamilyInfo& MainViewFamily); /** Custom render pass that render as part of the main renderer. */ FCustomRenderPassBase* CustomRenderPass; /** View family used by custom render pass. NOT treated as a linked view. Required to allow different EngineShowFlags from main renderer ViewFamily. */ FViewFamilyInfo ViewFamily; /** Views used to render the custom render pass. */ TArray Views; FNaniteShadingCommands NaniteBasePassShadingCommands; }; TArray CustomRenderPassInfos; /** All views include main camera views and custom render pass views. */ TArray AllViews; ////////////////////////////////////////////////////////////////////////// // Provides access to properties of linked scene renderers. struct { FSceneRenderer* Head = nullptr; FSceneRenderer* Next = nullptr; } Link; bool IsHeadLink() const { return Link.Head == this; } template void EnumerateLinkedViews(LambdaType&& Lambda, const FSceneView* ViewToSkip = nullptr) { for (FSceneRenderer* Renderer = Link.Head; Renderer; Renderer = Renderer->Link.Next) { for (FViewInfo& View : Renderer->Views) { if (ViewToSkip != &View) { if (!Lambda(View)) { return; } } } } } template void EnumerateLinkedViewFamilies(LambdaType&& Lambda, const FSceneViewFamily* ViewFamilyToSkip = nullptr) { for (FSceneRenderer* Renderer = Link.Head; Renderer; Renderer = Renderer->Link.Next) { if (ViewFamilyToSkip != &Renderer->ViewFamily) { if (!Lambda(Renderer->ViewFamily)) { return; } } } } ////////////////////////////////////////////////////////////////////////// /** All the dynamic scaling informations */ DynamicRenderScaling::TMap DynamicResolutionFractions; DynamicRenderScaling::TMap DynamicResolutionUpperBounds; /** Information about the visible lights. */ TArray VisibleLightInfos; /** Array of dispatched parallel shadow depth passes. */ UE::FMutex DispatchedShadowDepthPassesMutex; TArray DispatchedShadowDepthPasses; FSortedShadowMaps SortedShadowsForShadowDepthPass; FVirtualShadowMapArray VirtualShadowMapArray; LightFunctionAtlas::FLightFunctionAtlas LightFunctionAtlas; /** If a freeze request has been made */ bool bHasRequestedToggleFreeze; /** True if precomputed visibility was used when rendering the scene. */ bool bUsedPrecomputedVisibility; #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) /** Lights added if wholescenepointlight shadow would have been rendered (ignoring r.SupportPointLightWholeSceneShadows). Used for warning about unsupported features. */ TArray UsedWholeScenePointLightNames; #endif /** Feature level being rendered */ ERHIFeatureLevel::Type FeatureLevel; EShaderPlatform ShaderPlatform; bool bGPUMasksComputed; FRHIGPUMask RenderTargetGPUMask; public: FSceneRenderer(const FSceneViewFamily* InViewFamily, FHitProxyConsumer* HitProxyConsumer); virtual ~FSceneRenderer(); // ISceneRenderer interface virtual UE::Renderer::Private::IShadowInvalidatingInstances *GetShadowInvalidatingInstancesInterface(const FSceneView *SceneView) override; // FSceneRendererBase interface virtual FViewFamilyInfo* GetViewFamily() override { return &ViewFamily; } // FSceneRenderer interface virtual void Render(FRDGBuilder& GraphBuilder, const FSceneRenderUpdateInputs* SceneUpdateInputs) = 0; virtual void RenderHitProxies(FRDGBuilder& GraphBuilder, const FSceneRenderUpdateInputs* SceneUpdateInputs) {} virtual bool ShouldRenderVelocities() const { return false; } virtual bool ShouldRenderPrePass() const { return false; } virtual bool ShouldRenderNanite() const { return false; } virtual bool AllowSimpleLights() const; /** Setups FViewInfo::ViewRect according to ViewFamilly's ScreenPercentageInterface. */ void PrepareViewRectsForRendering(); #if WITH_MGPU /** * Assigns the view GPU masks and initializes RenderTargetGPUMask. RHICmdList is only required if alternate frame rendering * is active, and must be called in the render thread in that case, otherwise it can be called earlier. Computing the masks * early is used to optimize handling of cross GPU fences (see PreallocateCrossGPUFences). */ void ComputeGPUMasks(FRHICommandListImmediate* RHICmdList); #endif /** Logic to update render targets across all GPUs */ static void PreallocateCrossGPUFences(TConstArrayView SceneRenderers); void DoCrossGPUTransfers(FRDGBuilder& GraphBuilder, FRDGTextureRef ViewFamilyTexture, TArrayView InViews, bool bCrossGPUTransferFencesDefer, FRHIGPUMask RenderTargetGPUMask, class FCrossGPUTransfersDeferred* TransfersDeferred); void FlushCrossGPUTransfers(FRDGBuilder& GraphBuilder); void FlushCrossGPUFences(FRDGBuilder& GraphBuilder); bool DoOcclusionQueries() const; void FenceOcclusionTests(FRDGBuilder& GraphBuilder); void WaitOcclusionTests(FRHICommandListImmediate& RHICmdList); // fences to make sure the rhi thread has digested the occlusion query renders before we attempt to read them back async static FOcclusionSubmittedFenceState OcclusionSubmittedFence[FOcclusionQueryHelpers::MaxBufferedOcclusionFrames]; bool ShouldDumpMeshDrawCommandInstancingStats() const { return bDumpMeshDrawCommandInstancingStats; } /** bound shader state for occlusion test prims */ static FGlobalBoundShaderState OcclusionTestBoundShaderState; /** * Whether or not to composite editor objects onto the scene as a post processing step * * @param View The view to test against * * @return true if compositing is needed */ static bool ShouldCompositeEditorPrimitives(const FViewInfo& View); #if UE_ENABLE_DEBUG_DRAWING static bool ShouldCompositeDebugPrimitivesInPostProcess(const FViewInfo& View); #endif /** Apply the ResolutionFraction on ViewSize, taking into account renderer's requirements. */ static FIntPoint ApplyResolutionFraction( const FSceneViewFamily& ViewFamily, const FIntPoint& UnscaledViewSize, float ResolutionFraction); /** Quantize the ViewRect.Min according to various renderer's downscale requirements. */ static FIntPoint QuantizeViewRectMin(const FIntPoint& ViewRectMin); /** Get the desired buffer size from the view family's ResolutionFraction upperbound. * Can be called on game thread or render thread. */ static FIntPoint GetDesiredInternalBufferSize(const FSceneViewFamily& ViewFamily); /** Exposes renderer's privilege to fork view family's screen percentage interface. */ static ISceneViewFamilyScreenPercentage* ForkScreenPercentageInterface( const ISceneViewFamilyScreenPercentage* ScreenPercentageInterface, FSceneViewFamily& ForkedViewFamily) { return ScreenPercentageInterface->Fork_GameThread(ForkedViewFamily); } static int32 GetRefractionQuality(const FSceneViewFamily& ViewFamily); /** Common function to render a sky using shared LUT resources from any view point (if not using the SkyView and AerialPerspective textures). */ void RenderSkyAtmosphereInternal( FRDGBuilder& GraphBuilder, const FSceneTextureShaderParameters& SceneTextures, FSkyAtmosphereRenderContext& SkyRenderContext); /** Common function to render a cloud layer using shared LUT resources. */ void RenderVolumetricCloudsInternal(FRDGBuilder& GraphBuilder, FCloudRenderContext& CloudRC, FInstanceCullingManager& InstanceCullingManager, const FIntPoint& CloudViewportSize); /** Sets the stereo-compatible RHI viewport. If the view doesn't requires stereo rendering, the standard viewport is set. */ static void SetStereoViewport(FRHICommandList& RHICmdList, const FViewInfo& View, float ViewportScale = 1.0f); FGPUSceneDynamicContext& GetGPUSceneDynamicContext() { return GPUSceneDynamicContext; } void VoxelizeFogVolumePrimitives( FRDGBuilder& GraphBuilder, const FViewInfo& View, const FVolumetricFogIntegrationParameterData& IntegrationData, FIntVector VolumetricFogGridSize, FVector GridZParams, float VolumetricFogDistance, bool bVoxelizeEmissive); void RenderLightFunctionForVolumetricFog( FRDGBuilder& GraphBuilder, FViewInfo& View, const FSceneTextures& SceneTextures, FIntVector VolumetricFogGridSize, float VolumetricFogMaxDistance, FLightSceneInfo* DirectionalLightSceneInfo, FMatrix44f& OutLightFunctionTranslatedWorldToShadow, FRDGTexture*& OutLightFunctionTexture); void RenderLocalLightsForVolumetricFog( FRDGBuilder& GraphBuilder, FViewInfo& View, int32 ViewIndex, bool bUseTemporalReprojection, const struct FVolumetricFogIntegrationParameterData& IntegrationData, const FExponentialHeightFogSceneInfo& FogInfo, FIntVector VolumetricFogGridSize, FVector GridZParams, const FRDGTextureDesc& VolumeDesc, FRDGTextureRef ConservativeDepthTexture, TConstArrayView LightsToInject, TConstArrayView RayTracedLightsToInject, FRDGTexture*& OutLocalShadowedLightScattering); /** Renders capsule shadows for movable skylights, using the cone of visibility (bent normal) from DFAO. */ void RenderCapsuleShadowsForMovableSkylight( FRDGBuilder& GraphBuilder, const FViewInfo& View, FRDGTextureRef& BentNormalOutput) const; /** Render Ambient Occlusion using mesh distance fields on a screen based grid. */ void RenderDistanceFieldAOScreenGrid( FRDGBuilder& GraphBuilder, const FSceneTextures& SceneTextures, const FViewInfo& View, const FDistanceFieldCulledObjectBufferParameters& CulledObjectBufferParameters, FRDGBufferRef ObjectTilesIndirectArguments, const FTileIntersectionParameters& TileIntersectionParameters, const FDistanceFieldAOParameters& Parameters, FRDGTextureRef DistanceFieldNormal, FRDGTextureRef& OutDynamicBentNormalAO); /** Render Ambient Occlusion using mesh distance fields and the surface cache, which supports dynamic rigid meshes. */ void RenderDistanceFieldLighting( FRDGBuilder& GraphBuilder, const FSceneTextures& SceneTextures, const class FDistanceFieldAOParameters& Parameters, TArray& OutDynamicBentNormalAOTextures, bool bModulateToSceneColor, bool bVisualizeAmbientOcclusion, bool bModulateToScreenSpaceAO = false); void SetupVolumetricFog(); bool ShouldRenderVolumetricFog() const; void ComputeVolumetricFog(FRDGBuilder& GraphBuilder, const FSceneTextures& SceneTextures); virtual bool IsLumenEnabled(const FViewInfo& View) const { return false; } virtual bool IsLumenGIEnabled(const FViewInfo& View) const { return false; } virtual bool AnyViewHasGIMethodSupportingDFAO() const { return true; } /** Gets a readable light name for use with a draw event. */ static void GetLightNameForDrawEvent(const FLightSceneProxy* LightProxy, FString& LightNameWithLevel); FORCEINLINE FSceneTextures& GetActiveSceneTextures() { return ViewFamily.GetSceneTextures(); } FORCEINLINE FSceneTexturesConfig& GetActiveSceneTexturesConfig() { return ViewFamily.SceneTexturesConfig; } FORCEINLINE const FSceneTextures& GetActiveSceneTextures() const { return ViewFamily.GetSceneTextures(); } FORCEINLINE const FSceneTexturesConfig& GetActiveSceneTexturesConfig() const { return ViewFamily.SceneTexturesConfig; } DECLARE_MULTICAST_DELEGATE_OneParam(FSceneOnScreenMessagesDelegate, FScreenMessageWriter&); FSceneOnScreenMessagesDelegate OnGetOnScreenMessages; inline TConstStridedView GetSceneViews() const { return MakeStridedViewOfBase(MakeArrayView(Views)); } static TGlobalResource DynamicReadBufferForInitViews; static TGlobalResource DynamicReadBufferForRayTracing; static TGlobalResource DynamicReadBufferForShadows; bool IsRenderingStereo() const { return Views.Num() == 2 && IStereoRendering::IsASecondaryView(Views[1]); } protected: /** Size of the family. */ FIntPoint FamilySize; #if WITH_MGPU /** * Fences for cross GPU render target transfers. We defer the wait on cross GPU fences until the last scene renderer, * to avoid needless stalls in the middle of the frame, improving performance. The "Defer" array holds fences issued * by each prior scene renderer, while the "Wait" array holds fences to be waited on in the last scene renderer * (a collection of all the fences from prior scene renderers). The function "PreallocateCrossGPUFences" initializes * these arrays. */ TArray CrossGPUTransferFencesDefer; TArray CrossGPUTransferFencesWait; /** Deferred transfers to be executed in the last scene renderer */ TRefCountPtr CrossGPUTransferDeferred; FRHIGPUMask AllViewsGPUMask; bool IsShadowCached(FProjectedShadowInfo* ProjectedShadowInfo) const; FRHIGPUMask GetGPUMaskForShadow(FProjectedShadowInfo* ProjectedShadowInfo) const; #endif /** The cached FXSystem which could be released while we are rendering. */ class FFXSystemInterface* FXSystem = nullptr; bool bDumpMeshDrawCommandInstancingStats; // Shared functionality between all scene renderers enum class ERendererOutput { DepthPrepassOnly, // Only render depth prepass and its related code paths FinalSceneColor // Render the whole pipeline }; ERendererOutput GetRendererOutput() const; FDynamicShadowsTaskData* BeginInitDynamicShadows(FRDGBuilder& GraphBuilder, bool bRunningEarly, IVisibilityTaskData* VisibilityTaskData, FInstanceCullingManager& InstanceCullingManager); void FinishInitDynamicShadows(FRDGBuilder& GraphBuilder, FDynamicShadowsTaskData* TaskData); void FinishDynamicShadowMeshPassSetup(FRDGBuilder& GraphBuilder, FDynamicShadowsTaskData* TaskData); FDynamicShadowsTaskData* InitDynamicShadows(FRDGBuilder& GraphBuilder, FInstanceCullingManager& InstanceCullingManager); void CreateDynamicShadows(FDynamicShadowsTaskData& TaskData); void FilterDynamicShadows(FDynamicShadowsTaskData& TaskData); friend struct FGatherShadowPrimitivesPrepareTask; void SetupMeshPass(FViewInfo& View, FExclusiveDepthStencil::Type BasePassDepthStencilAccess, FViewCommands& ViewCommands, FInstanceCullingManager& InstanceCullingManager); void RenderShadowProjections( FRDGBuilder& GraphBuilder, FRDGTextureRef OutputTexture, const FMinimalSceneTextures& SceneTextures, const FLightSceneProxy* LightSceneProxy, TArrayView Shadows, bool bSubPixelShadow, bool bProjectingForForwardShading); void RenderShadowProjections( FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures, FRDGTextureRef ScreenShadowMaskTexture, FRDGTextureRef ScreenShadowMaskSubPixelTexture, const FLightSceneInfo* LightSceneInfo, bool bProjectingForForwardShading); void BeginAsyncDistanceFieldShadowProjections( FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures, const FDynamicShadowsTaskData* TaskData) const; /** Finds a matching cached preshadow, if one exists. */ TRefCountPtr GetCachedPreshadow( const FLightPrimitiveInteraction* InParentInteraction, const FProjectedShadowInitializer& Initializer, const FBoxSphereBounds& Bounds, uint32 InResolutionX); /** Creates a per object projected shadow for the given interaction. */ void CreatePerObjectProjectedShadow( FDynamicShadowsTaskData& TaskData, FLightPrimitiveInteraction* Interaction, bool bCreateTranslucentObjectShadow, bool bCreateInsetObjectShadow, const TArray& ViewDependentWholeSceneShadows, TArray& OutPreShadows); /** Creates shadows for the given interaction. */ void SetupInteractionShadows( FDynamicShadowsTaskData& TaskData, FLightPrimitiveInteraction* Interaction, FVisibleLightInfo& VisibleLightInfo, bool bStaticSceneOnly, const TArray& ViewDependentWholeSceneShadows, TArray& PreShadows); /** Generates FProjectedShadowInfos for all wholesceneshadows on the given light.*/ void AddViewDependentWholeSceneShadowsForView( TArray& ShadowInfos, TArray& ShadowInfosThatNeedCulling, FVisibleLightInfo& VisibleLightInfo, FLightSceneInfo& LightSceneInfo, int64 CachedShadowMapsSize, uint32& NumCSMCachesUpdatedThisFrame); void AllocateShadowDepthTargets(FDynamicShadowsTaskData& TaskData); void AllocateAtlasedShadowDepthTargets(FRHICommandListBase& RHICmdList, TConstArrayView Shadows, TArray& OutAtlases); void AllocateCachedShadowDepthTargets(FRHICommandListBase& RHICmdList, TConstArrayView CachedShadows); void AllocateCSMDepthTargets(FRHICommandListBase& RHICmdList, TConstArrayView WholeSceneDirectionalShadows, TArray& OutAtlases); void AllocateOnePassPointLightDepthTargets(FRHICommandListBase& RHICmdList, TConstArrayView WholeScenePointShadows); void AllocateTranslucentShadowDepthTargets(FRHICommandListBase& RHICmdList, TConstArrayView TranslucentShadows); void AllocateMobileCSMAndSpotLightShadowDepthTargets(FRHICommandListBase& RHICmdList, TConstArrayView MobileCSMAndSpotLightShadows); /** * Used by RenderLights to figure out if projected shadows need to be rendered to the attenuation buffer. * Or to render a given shadowdepth map for forward rendering. * * @param LightSceneInfo Represents the current light * @return true if anything needs to be rendered */ bool CheckForProjectedShadows(const FLightSceneInfo* LightSceneInfo) const; /** Gathers the list of primitives used to draw various shadow types */ void BeginGatherShadowPrimitives(FDynamicShadowsTaskData* TaskData, IVisibilityTaskData* VisibilityTaskData); void FinishGatherShadowPrimitives(FDynamicShadowsTaskData* TaskData); void RenderShadowDepthMaps(FRDGBuilder& GraphBuilder, FDynamicShadowsTaskData* DynamicShadowsTaskData, FInstanceCullingManager& InstanceCullingManager, FRDGExternalAccessQueue& ExternalAccessQueue); void RenderShadowDepthMaps(FRDGBuilder& GraphBuilder, FDynamicShadowsTaskData* DynamicShadowsTaskData, FInstanceCullingManager& InstanceCullingManager, FRDGExternalAccessQueue& ExternalAccessQueue, TFunctionRef RenderAdditionalShadowDepths); void RenderShadowDepthMapAtlases(FRDGBuilder& GraphBuilder); /** * Creates a projected shadow for all primitives affected by a light. * @param LightSceneInfo - The light to create a shadow for. */ void CreateWholeSceneProjectedShadow(FDynamicShadowsTaskData& TaskData, FLightSceneInfo* LightSceneInfo, int64 CachedShadowMapsSize, uint32& NumPointShadowCachesUpdatedThisFrame, uint32& NumSpotShadowCachesUpdatedThisFrame); /** Updates the preshadow cache, allocating new preshadows that can fit and evicting old ones. */ void UpdatePreshadowCache(); /** Gathers simple lights from visible primtives in the passed in views. */ static void GatherSimpleLights(const FSceneViewFamily& ViewFamily, const TArray& Views, FSimpleLightArray& SimpleLights); /** Calculates projected shadow visibility. */ void InitProjectedShadowVisibility(FDynamicShadowsTaskData& TaskData); /** Adds a debug shadow frustum to the views primitive draw interface. */ void DrawDebugShadowFrustum(FViewInfo& View, FProjectedShadowInfo& ProjectedShadowInfo); /** Gathers dynamic mesh elements for all shadows. */ void GatherShadowDynamicMeshElements(FDynamicShadowsTaskData& TaskData); /** Renders capsule shadows for all per-object shadows using it for the given light. */ bool RenderCapsuleDirectShadows( FRDGBuilder& GraphBuilder, const FLightSceneInfo& LightSceneInfo, FRDGTextureRef ScreenShadowMaskTexture, TArrayView CapsuleShadows, bool bProjectingForForwardShading) const; /** Performs once per frame setup prior to visibility determination. */ void PreVisibilityFrameSetup(FRDGBuilder& GraphBuilder); void GatherReflectionCaptureLightMeshElements(); /** Performs once per frame setup after to visibility determination. */ void PostVisibilityFrameSetup(FILCUpdatePrimTaskData*& OutILCTaskData); /** Initialized the fog constants for each view. */ void InitFogConstants(); /** Returns whether there are translucent primitives to be rendered. */ bool ShouldRenderTranslucency() const; static bool ShouldRenderTranslucency(ETranslucencyPass::Type TranslucencyPass, TArrayView InViews); /** Called at the begin / finish of the scene render. */ IVisibilityTaskData* OnRenderBegin(FRDGBuilder& GraphBuilder, const FSceneRenderUpdateInputs* SceneUpdateInputs); void OnRenderFinish(FRDGBuilder& GraphBuilder, FRDGTextureRef ViewFamilyTexture); bool RenderCustomDepthPass( FRDGBuilder& GraphBuilder, FCustomDepthTextures& CustomDepthTextures, const FSceneTextureShaderParameters& SceneTextures, TConstArrayView PrimaryNaniteRasterResults, TConstArrayView PrimaryNaniteViews); void UpdatePrimitiveIndirectLightingCacheBuffers(FRHICommandListBase& RHICmdList); void RenderPlanarReflection(class FPlanarReflectionSceneProxy* ReflectionSceneProxy); /** Initialise sky atmosphere resources.*/ void InitSkyAtmosphereForViews(FRHICommandListImmediate& RHICmdList, FRDGBuilder& GraphBuilder); /** Render the sky atmosphere look up table needed for this frame.*/ void RenderSkyAtmosphereLookUpTables(FRDGBuilder& GraphBuilder, class FSkyAtmospherePendingRDGResources& PendingRDGResources); /** Render the sky atmosphere over the scene.*/ void RenderSkyAtmosphere(FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures); /** Initialise volumetric cloud resources.*/ void InitVolumetricCloudsForViews(FRDGBuilder& GraphBuilder, bool bShouldRenderVolumetricCloud, FInstanceCullingManager& InstanceCullingManager); /** Render volumetric cloud. */ bool RenderVolumetricCloud( FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures, bool bSkipVolumetricRenderTarget, bool bSkipPerPixelTracing, FRDGTextureRef HalfResolutionDepthCheckerboardMinMaxTexture, FRDGTextureRef QuarterResolutionDepthMinMaxTexture, bool bAsyncCompute, FInstanceCullingManager& InstanceCullingManager); /** Render notification to artist when a sky material is used but it might comtains the camera (and then the sky/background would look black).*/ void RenderSkyAtmosphereEditorNotifications(FRDGBuilder& GraphBuilder, TArrayView InViews, FRDGTextureRef SceneColorTexture) const; /** We should render on screen notification only if any of the scene contains a mesh using a sky material.*/ static bool ShouldRenderSkyAtmosphereEditorNotifications(TArrayView Views); /** * Rounds up lights and sorts them according to what type of renderer supports them. The result is stored in OutSortedLights * NOTE: Also extracts the SimpleLights AND adds them to the sorted range (first sub-range). */ void GatherAndSortLights(FSortedLightSetSceneInfo& OutSortedLights, bool bShadowedLightsInClustered = false); /** * Register all lights with the light function atlas and updates it. */ void UpdateLightFunctionAtlasTaskFunction(); /** * Culls local lights and reflection probes to a grid in frustum space, builds one light list and grid per view in the current Views. * Needed for forward shading or translucency using the Surface lighting mode, and clustered deferred shading. */ FComputeLightGridOutput ComputeLightGrid(FRDGBuilder& GraphBuilder, bool bCullLightsToGrid, const FSortedLightSetSceneInfo& SortedLightSet, TArray>& PerViewForwardLightUniformParameters); /** * Prepare ForwardLightingResources for the Views (including building light grids) */ FComputeLightGridOutput PrepareForwardLightData(FRDGBuilder& GraphBuilder, bool bCullLightsToGrid, const FSortedLightSetSceneInfo& SortedLightSet); /** * Used by RenderLights to figure out if light functions need to be rendered to the attenuation buffer. * * @param LightSceneInfo Represents the current light * @return true if anything got rendered */ bool CheckForLightFunction(const FLightSceneInfo* LightSceneInfo) const; void SetupSceneReflectionCaptureBuffer(FRHICommandListImmediate& RHICmdList); void RenderVelocities( FRDGBuilder& GraphBuilder, TArrayView InViews, const FSceneTextures& SceneTextures, EVelocityPass VelocityPass, bool bForceVelocity, bool bBindRenderTarget = true); void RenderMeshDistanceFieldVisualization(FRDGBuilder& GraphBuilder, const FMinimalSceneTextures& SceneTextures); #if !UE_BUILD_SHIPPING static void CreateSplitScreenDebugViewFamilies(const FSceneViewFamily& InFamily, TArray& OutViewFamilies, TArray>& OutFamiliesStorage); static void DestroySplitScreenDebugViewFamilies(TConstArrayView ViewFamilies); #endif protected: FGPUSceneDynamicContext GPUSceneDynamicContext; void CheckShadowDepthRenderCompleted() const { checkf(bShadowDepthRenderCompleted, TEXT("Shadow depth rendering was not done before shadow projections, this will cause severe shadow artifacts and indicates an engine bug (pass ordering)")); } virtual void ComputeLightVisibility(); private: void ComputeFamilySize(); friend class FVisibilityTaskData; void SetupMeshPasses(IVisibilityTaskData& TaskData, FExclusiveDepthStencil::Type BasePassDepthStencilAccess, FInstanceCullingManager& InstanceCullingManager); void PrepareViewStateForVisibility(const FSceneTexturesConfig& SceneTexturesConfig); bool bShadowDepthRenderCompleted; #if RHI_RAYTRACING virtual void InitializeRayTracingFlags_RenderThread() {} #endif friend class FRendererModule; friend class FSceneRenderProcessor; }; /** A set of show flags thare are guaranteed to be common among all renderers in the set. */ enum class ESceneRenderCommonShowFlags { None = 0, HitProxies = 1 << 0, PathTracing = 1 << 1 }; ENUM_CLASS_FLAGS(ESceneRenderCommonShowFlags); /** An optional set of all renderers, view families, and views for operations that are performed once for a * batch of scene renderers. Only the first scene renderer will have this applied. */ struct FSceneRenderUpdateInputs { TConstArrayView GetAsSceneViews() const { return MakeArrayView(reinterpret_cast(Views.GetData()), Views.Num()); } TConstArrayView GetAsSceneViewFamilies() const { return MakeArrayView(reinterpret_cast(ViewFamilies.GetData()), ViewFamilies.Num()); } template bool HasAnyShowFlags(LambdaType&& Lambda) const { for (FViewFamilyInfo* Family : ViewFamilies) { if (Lambda(Family->EngineShowFlags)) { return true; } } return false; } template void ForEachView(LambdaType&& Lambda) const { for (FSceneRenderer* Renderer : Renderers) { for (FViewInfo& View : Renderer->Views) { if (!Lambda(Renderer, View)) { return; } } } } EShaderPlatform ShaderPlatform; ERHIFeatureLevel::Type FeatureLevel; FScene* Scene; FFXSystemInterface* FXSystem; FGlobalShaderMap* GlobalShaderMap; TConstArrayView Renderers; TConstArrayView ViewFamilies; TConstArrayView Views; ESceneRenderCommonShowFlags CommonShowFlags; }; template UE::Tasks::FTask LaunchSceneRenderTask(const TCHAR* DebugName, LambdaType&& Lambda, PrerequisiteTaskCollectionType&& Prerequisites, bool bExecuteInParallelCondition = true, UE::Tasks::ETaskPriority TaskPriority = UE::Tasks::ETaskPriority::High) { const bool bExecuteInParallel = bExecuteInParallelCondition && FApp::ShouldUseThreadingForPerformance() && GIsThreadedRendering; return UE::Tasks::Launch(DebugName, [Lambda = Forward(Lambda)] () mutable { FTaskTagScope Scope(ETaskTag::EParallelRenderingThread); Lambda(); }, Forward(Prerequisites), TaskPriority, bExecuteInParallel ? UE::Tasks::EExtendedTaskPriority::None : UE::Tasks::EExtendedTaskPriority::Inline ); } template UE::Tasks::FTask LaunchSceneRenderTask(const TCHAR* DebugName, LambdaType&& Lambda, bool bExecuteInParallelCondition = true, UE::Tasks::ETaskPriority TaskPriority = UE::Tasks::ETaskPriority::High) { const bool bExecuteInParallel = bExecuteInParallelCondition && FApp::ShouldUseThreadingForPerformance() && GIsThreadedRendering; return UE::Tasks::Launch(DebugName, [Lambda = Forward(Lambda)] () mutable { FTaskTagScope Scope(ETaskTag::EParallelRenderingThread); Lambda(); }, TaskPriority, bExecuteInParallel ? UE::Tasks::EExtendedTaskPriority::None : UE::Tasks::EExtendedTaskPriority::Inline ); } template UE::Tasks::TTask LaunchSceneRenderTask(const TCHAR* DebugName, LambdaType&& Lambda, PrerequisiteTaskCollectionType&& Prerequisites, bool bExecuteInParallelCondition = true, UE::Tasks::ETaskPriority TaskPriority = UE::Tasks::ETaskPriority::High) { const bool bExecuteInParallel = bExecuteInParallelCondition && FApp::ShouldUseThreadingForPerformance() && GIsThreadedRendering; return UE::Tasks::Launch(DebugName, [Lambda = Forward(Lambda)] () mutable { FTaskTagScope Scope(ETaskTag::EParallelRenderingThread); return Lambda(); }, Forward(Prerequisites), TaskPriority, bExecuteInParallel ? UE::Tasks::EExtendedTaskPriority::None : UE::Tasks::EExtendedTaskPriority::Inline ); } // Creates a FGraphEventRef from UE::Task::FTask prerequisites. template FGraphEventRef CreateCompatibilityGraphEvent(PrerequisiteTaskCollectionType&& Prerequisites) { FGraphEventRef GraphEvent = FGraphEvent::CreateGraphEvent(); UE::Tasks::Launch(UE_SOURCE_LOCATION, [GraphEvent] { GraphEvent->DispatchSubsequents(); }, Prerequisites, UE::Tasks::ETaskPriority::High, UE::Tasks::EExtendedTaskPriority::Inline); return GraphEvent; } struct FForwardScreenSpaceShadowMaskTextureMobileOutputs { TRefCountPtr ScreenSpaceShadowMaskTextureMobile; bool IsValid() { return ScreenSpaceShadowMaskTextureMobile.IsValid(); } void Release() { ScreenSpaceShadowMaskTextureMobile.SafeRelease(); } }; extern FForwardScreenSpaceShadowMaskTextureMobileOutputs GScreenSpaceShadowMaskTextureMobileOutputs; typedef TArray> FColorTargets; /** * Renderer that implements simple forward shading and associated features. */ class FMobileSceneRenderer : public FSceneRenderer { public: FMobileSceneRenderer(const FSceneViewFamily* InViewFamily, FHitProxyConsumer* HitProxyConsumer); // FSceneRenderer interface virtual void Render(FRDGBuilder& GraphBuilder, const FSceneRenderUpdateInputs* SceneUpdateInputs) override; virtual void RenderHitProxies(FRDGBuilder& GraphBuilder, const FSceneRenderUpdateInputs* SceneUpdateInputs) override; virtual bool ShouldRenderVelocities() const override; virtual bool ShouldRenderPrePass() const override; virtual bool AllowSimpleLights() const override; /** Whether platform requires multiple render-passes for SceneColor rendering */ static bool RequiresMultiPass(int32 NumMSAASamples, EShaderPlatform ShaderPlatform); protected: /** Finds the visible dynamic shadows for each view. */ FDynamicShadowsTaskData* InitDynamicShadows(FRDGBuilder& GraphBuilder, FInstanceCullingManager& FInstanceCullingManager); void PrepareViewVisibilityLists(); /** Build visibility lists on CSM receivers and non-csm receivers. */ void BuildCSMVisibilityState(FLightSceneInfo* LightSceneInfo); struct FInitViewTaskDatas { FInitViewTaskDatas(IVisibilityTaskData* InVisibilityTaskData) : VisibilityTaskData(InVisibilityTaskData) {} IVisibilityTaskData* VisibilityTaskData; FDynamicShadowsTaskData* DynamicShadows = nullptr; }; void InitViews( FRDGBuilder& GraphBuilder, FSceneTexturesConfig& SceneTexturesConfig, FInstanceCullingManager& InstanceCullingManager, FVirtualTextureUpdater* VirtualTextureUpdater, FInitViewTaskDatas& TaskDatas); void RenderPrePass(FRHICommandList& RHICmdList, const FViewInfo& View, const FInstanceCullingDrawParams* InstanceCullingDrawParams); void RenderMaskedPrePass(FRHICommandList& RHICmdList, const FViewInfo& View, const FInstanceCullingDrawParams* DepthPassInstanceCullingDrawParams); void RenderFullDepthPrepass(FRDGBuilder& GraphBuilder, TArrayView InViews, FSceneTextures& SceneTextures, FInstanceCullingManager& InstanceCullingManager, bool bIsSceneCaptureRenderPass=false); void RenderVelocityPass(FRHICommandList& RHICmdList, const FViewInfo& View, const FInstanceCullingDrawParams* InstanceCullingDrawParams); void RenderMobileLocalLightsBuffer(FRDGBuilder& GraphBuilder, FSceneTextures& SceneTextures, const FSortedLightSetSceneInfo& SortedLights); void RenderCustomRenderPassBasePass(FRDGBuilder& GraphBuilder, TArrayView InViews, FRDGTextureRef ViewFamilyTexture, FSceneTextures& SceneTextures, FInstanceCullingManager& InstanceCullingManager, bool bIncludeTranslucent); /** Renders the opaque base pass for mobile. */ void RenderMobileBasePass(FRHICommandList& RHICmdList, const FViewInfo& View, const FInstanceCullingDrawParams* InstanceCullingDrawParams, const FInstanceCullingDrawParams* SkyPassInstanceCullingDrawParams); void PostRenderBasePass(FRHICommandList& RHICmdList, FViewInfo& View); void RenderMobileEditorPrimitives(FRHICommandList& RHICmdList, const FViewInfo& View, const FMeshPassProcessorRenderState& DrawRenderState, const FInstanceCullingDrawParams* InstanceCullingDrawParams); #if UE_ENABLE_DEBUG_DRAWING /** Render debug primitives in the base pass, for MobileHDR=false */ void RenderMobileDebugPrimitives(FRHICommandList& RHICmdList, const FViewInfo& View); #endif /** Renders the debug view pass for mobile. */ void RenderMobileDebugView(FRHICommandList& RHICmdList, const FViewInfo& View, const FInstanceCullingDrawParams* DebugViewModeInstanceCullingDrawParams); /** Render modulated shadow projections in to the scene, loops over any unrendered shadows until all are processed.*/ void RenderModulatedShadowProjections(FRHICommandList& RHICmdList, int32 ViewIndex, const FViewInfo& View); /** Issues occlusion queries */ void RenderOcclusion(FRHICommandList& RHICmdList); bool ShouldRenderHZB(TArrayView InViews); /** Generate HZB */ void RenderHZB(FRHICommandListImmediate& RHICmdList, const TRefCountPtr& SceneDepthZ); void RenderHZB(FRDGBuilder& GraphBuilder, FRDGTextureRef SceneDepthTexture); /** Computes how many queries will be issued this frame */ int32 ComputeNumOcclusionQueriesToBatch() const; /** Renders decals. */ void RenderDecals(FRHICommandList& RHICmdList, FViewInfo& View, const FInstanceCullingDrawParams* InstanceCullingDrawParams); void RenderDBuffer(FRDGBuilder& GraphBuilder, FSceneTextures& SceneTextures, FDBufferTextures& DBufferTextures, FInstanceCullingManager& InstanceCullingManager); /** Renders the atmospheric and height fog */ void RenderFog(FRHICommandList& RHICmdList, const FViewInfo& View); /** Renders the base pass for translucency. */ static void RenderTranslucency(FRHICommandList& RHICmdList, const FViewInfo& View, TArrayView FamilyViewInfos, ETranslucencyPass::Type InStandardTranslucencyPass, EMeshPass::Type InStandardTranslucencyMeshPass, const FInstanceCullingDrawParams* InTranslucencyInstanceCullingDrawParams); /** On chip pre-tonemap before scene color MSAA resolve (iOS only) */ void PreTonemapMSAA(FRHICommandList& RHICmdList, const FMinimalSceneTextures& SceneTextures); void SetupMobileBasePassAfterShadowInit(FExclusiveDepthStencil::Type BasePassDepthStencilAccess, TArrayView ViewCommandsPerView, FInstanceCullingManager& InstanceCullingManager); void UpdateDirectionalLightUniformBuffers(FRDGBuilder& GraphBuilder, const FViewInfo& View); void UpdateSkyReflectionUniformBuffer(FRHICommandListBase& RHICmdList); void RenderForward(FRDGBuilder& GraphBuilder, FRDGTextureRef ViewFamilyTexture, FSceneTextures& SceneTextures, FDBufferTextures& DBufferTextures, FInstanceCullingManager& InstanceCullingManager); void RenderForwardSinglePass(FRDGBuilder& GraphBuilder, class FMobileRenderPassParameters* PassParameters, struct FRenderViewContext& ViewContext, FSceneTextures& SceneTextures, FInstanceCullingManager& InstanceCullingManager); void RenderForwardMultiPass(FRDGBuilder& GraphBuilder, class FMobileRenderPassParameters* PassParameters, struct FRenderViewContext& ViewContext, FSceneTextures& SceneTextures, FInstanceCullingManager& InstanceCullingManager); void RenderDeferredSinglePass(FRDGBuilder& GraphBuilder, FSceneTextures& SceneTextures, const FSortedLightSetSceneInfo& SortedLightSet, FDBufferTextures& DBufferTextures, FInstanceCullingManager& InstanceCullingManager); void RenderDeferredMultiPass(FRDGBuilder& GraphBuilder, FSceneTextures& SceneTextures, const FSortedLightSetSceneInfo& SortedLightSet, FDBufferTextures& DBufferTextures, FInstanceCullingManager& InstanceCullingManager); void RenderAmbientOcclusion(FRDGBuilder& GraphBuilder, FRDGTextureRef SceneDepthTexture, FRDGTextureRef AmbientOcclusionTexture); void RenderMobileShadowProjections(FRDGBuilder& GraphBuilder); FRenderTargetBindingSlots InitRenderTargetBindings_Deferred(FSceneTextures& SceneTextures, FColorTargets& ColorTargets); FRenderTargetBindingSlots InitRenderTargetBindings_Forward(FRDGTextureRef ViewFamilyTexture, FSceneTextures& SceneTextures); FColorTargets GetColorTargets_Deferred(FSceneTextures& SceneTextures); private: const bool bGammaSpace; const bool bDeferredShading; const bool bRequiresDBufferDecals; const bool bUseVirtualTexturing; const bool bSupportsSimpleLights; bool bTonemapSubpass; bool bTonemapSubpassInline; int32 NumMSAASamples; bool bRenderToSceneColor; bool bRequiresMultiPass; bool bKeepDepthContent; bool bModulatedShadowsInUse; bool bShouldRenderCustomDepth; bool bRequiresAmbientOcclusionPass; bool bShouldRenderVelocities; bool bShouldRenderHZB; bool bRequiresScreenSpaceReflections; bool bIsFullDepthPrepassEnabled; bool bIsMaskedOnlyDepthPrepassEnabled; bool bRequiresSceneDepthAux; bool bEnableClusteredLocalLights; bool bEnableClusteredReflections; bool bRequiresShadowProjections; bool bAdrenoOcclusionMode; bool bEnableDistanceFieldAO; ETranslucencyPass::Type StandardTranslucencyPass; EMeshPass::Type StandardTranslucencyMeshPass; const FViewInfo* CachedView = nullptr; }; // The noise textures need to be set in Slate too. RENDERER_API void UpdateNoiseTextureParameters(FViewUniformShaderParameters& ViewUniformShaderParameters); struct FFastVramConfig { FFastVramConfig(); void Update(); void OnCVarUpdated(); void OnSceneRenderTargetsAllocated(); ETextureCreateFlags GBufferA; ETextureCreateFlags GBufferB; ETextureCreateFlags GBufferC; ETextureCreateFlags GBufferD; ETextureCreateFlags GBufferE; ETextureCreateFlags GBufferF; ETextureCreateFlags GBufferVelocity; ETextureCreateFlags HZB; ETextureCreateFlags SceneDepth; ETextureCreateFlags SceneColor; ETextureCreateFlags Bloom; ETextureCreateFlags BokehDOF; ETextureCreateFlags CircleDOF; ETextureCreateFlags CombineLUTs; ETextureCreateFlags Downsample; ETextureCreateFlags EyeAdaptation; ETextureCreateFlags Histogram; ETextureCreateFlags HistogramReduce; ETextureCreateFlags VelocityFlat; ETextureCreateFlags VelocityMax; ETextureCreateFlags MotionBlur; ETextureCreateFlags Tonemap; ETextureCreateFlags Upscale; ETextureCreateFlags DistanceFieldNormal; ETextureCreateFlags DistanceFieldAOHistory; ETextureCreateFlags DistanceFieldAOBentNormal; ETextureCreateFlags DistanceFieldAODownsampledBentNormal; ETextureCreateFlags DistanceFieldShadows; ETextureCreateFlags DistanceFieldIrradiance; ETextureCreateFlags DistanceFieldAOConfidence; ETextureCreateFlags Distortion; ETextureCreateFlags ScreenSpaceShadowMask; ETextureCreateFlags VolumetricFog; ETextureCreateFlags SeparateTranslucency; ETextureCreateFlags SeparateTranslucencyModulate; ETextureCreateFlags ScreenSpaceAO; ETextureCreateFlags SSR; ETextureCreateFlags DBufferA; ETextureCreateFlags DBufferB; ETextureCreateFlags DBufferC; ETextureCreateFlags DBufferMask; ETextureCreateFlags DOFSetup; ETextureCreateFlags DOFReduce; ETextureCreateFlags DOFPostfilter; ETextureCreateFlags PostProcessMaterial; ETextureCreateFlags CustomDepth; ETextureCreateFlags ShadowPointLight; ETextureCreateFlags ShadowPerObject; ETextureCreateFlags ShadowCSM; // Buffers EBufferUsageFlags DistanceFieldCulledObjectBuffers; EBufferUsageFlags DistanceFieldTileIntersectionResources; EBufferUsageFlags DistanceFieldAOScreenGridResources; EBufferUsageFlags ForwardLightingCullingResources; EBufferUsageFlags GlobalDistanceFieldCullGridBuffers; bool bDirty; private: bool UpdateTextureFlagFromCVar(TAutoConsoleVariable& CVar, ETextureCreateFlags& InOutValue); bool UpdateBufferFlagFromCVar(TAutoConsoleVariable& CVar, EBufferUsageFlags& InOutValue); }; extern FFastVramConfig GFastVRamConfig; /** Returns the array of shadows with distance fields. Call only after finishing shadow initialization. */ extern TConstArrayView GetProjectedDistanceFieldShadows(const FDynamicShadowsTaskData* TaskData); /** Triggers shadow gather dynamic mesh elements task graph to start processing. */ extern void BeginShadowGatherDynamicMeshElements(FDynamicShadowsTaskData* TaskData); extern bool UseCachedMeshDrawCommands(); extern bool UseCachedMeshDrawCommands_AnyThread(); extern bool IsDynamicInstancingEnabled(ERHIFeatureLevel::Type FeatureLevel); enum class EGPUSkinCacheTransition { FrameSetup, Renderer, }; /** Resolves the view rect of scene color or depth using either a custom resolve or hardware resolve. */ void AddResolveSceneColorPass(FRDGBuilder& GraphBuilder, const FViewInfo& View, FRDGTextureMSAA SceneColor); void AddResolveSceneDepthPass(FRDGBuilder& GraphBuilder, const FViewInfo& View, FRDGTextureMSAA SceneDepth); /** Resolves all views for scene color / depth. */ void AddResolveSceneColorPass(FRDGBuilder& GraphBuilder, TArrayView Views, FRDGTextureMSAA SceneColor); void AddResolveSceneDepthPass(FRDGBuilder& GraphBuilder, TArrayView Views, FRDGTextureMSAA SceneDepth); /** Prepares virtual textures for feedback updates. */ void VirtualTextureFeedbackBegin(FRDGBuilder& GraphBuilder, TArrayView Views, FIntPoint SceneTextureExtent); /** Creates a half resolution checkerboard min / max depth buffer from the input full resolution depth buffer. */ FRDGTextureRef CreateHalfResolutionDepthCheckerboardMinMax(FRDGBuilder& GraphBuilder, TArrayView Views, FRDGTextureRef SceneDepth); /** Creates a half resolution depth buffer storing the min and max depth for each 2x2 pixel quad of a half resolution buffer. */ FRDGTextureRef CreateQuarterResolutionDepthMinAndMax(FRDGBuilder& GraphBuilder, TArrayView Views, FRDGTextureRef DepthTexture); /** Creates a quarter resolution depth buffer storing the min and max depth for each 4x4 pixel quad of the depth buffer. */ void CreateQuarterResolutionDepthMinAndMaxFromDepthTexture(FRDGBuilder& GraphBuilder, TArrayView Views, FRDGTextureRef DepthTexture, FRDGTextureRef& OutHalfResMinMax, FRDGTextureRef& OutQuarterResMinMax); inline const FSceneTexturesConfig& FViewInfo::GetSceneTexturesConfig() const { // TODO: We are refactoring away use of the FSceneTexturesConfig::Get() global singleton, but need this workaround for now to avoid crashes return Family->bIsViewFamilyInfo ? ((const FViewFamilyInfo*)Family)->SceneTexturesConfig : FSceneTexturesConfig::Get(); } inline const FSceneTextures& FViewInfo::GetSceneTextures() const { return ((FViewFamilyInfo*)Family)->GetSceneTextures(); } inline const FSceneTextures* FViewInfo::GetSceneTexturesChecked() const { return ((FViewFamilyInfo*)Family)->GetSceneTexturesChecked(); } inline FSceneUniformBuffer& FViewInfo::GetSceneUniforms() const { return Family->GetSceneRenderer()->GetSceneUniforms(); } /** * Returns a family from an array of views, with the assumption that all point to the same view family, which will be * true for the "Views" array in the scene renderer. There are some utility functions that receive the Views array, * rather than the renderer itself, and this avoids confusing code that accesses Views[0], in addition to validating * the assumption that all Views have the same Family. FViewFamilyInfo is used to access FSceneTextures|Config. */ inline FViewFamilyInfo& GetViewFamilyInfo(const TArray& Views) { check(Views.Num() == 1 || Views[0].Family == Views.Last().Family); return *(FViewFamilyInfo*)Views[0].Family; } inline const FViewFamilyInfo& GetViewFamilyInfo(const TArray& Views) { check(Views.Num() == 1 || Views[0].Family == Views.Last().Family); return *(const FViewFamilyInfo*)Views[0].Family; } inline FViewFamilyInfo& GetViewFamilyInfo(const TArrayView& Views) { check(Views.Num() == 1 || Views[0].Family == Views.Last().Family); return *(FViewFamilyInfo*)Views[0].Family; } inline const FViewFamilyInfo& GetViewFamilyInfo(const TArrayView& Views) { check(Views.Num() == 1 || Views[0].Family == Views.Last().Family); return *(const FViewFamilyInfo*)Views[0].Family; } /** Checks whether primitive alpha holdout is active.*/ bool IsPrimitiveAlphaHoldoutEnabled(const FViewInfo& View); /** Checks whether primitive alpha holdout is active for any view.*/ bool IsPrimitiveAlphaHoldoutEnabledForAnyView(TArrayView Views); bool SceneCaptureRequiresAlphaChannel(const FSceneView& View); /** Checks whether the material and scene proxy combination will modify the mesh position. Useful for determining whether the material can be substituted with a default material for depth rendering etc. */ bool DoMaterialAndPrimitiveModifyMeshPosition(const FMaterial& Material, const FPrimitiveSceneProxy* PrimitiveSceneProxy);