2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
/*=============================================================================
DeferredShadingRenderer . cpp : Top level rendering loop for deferred shading
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "RendererPrivate.h"
2014-05-20 07:27:59 -04:00
# include "Engine.h"
2014-03-14 14:13:41 -04:00
# include "ScenePrivate.h"
# include "ScreenRendering.h"
# include "SceneFilterRendering.h"
2015-04-09 19:14:28 -04:00
# include "ScreenSpaceReflections.h"
2014-03-14 14:13:41 -04:00
# include "VisualizeTexture.h"
# include "CompositionLighting.h"
# include "FXSystem.h"
# include "OneColorShader.h"
# include "CompositionLighting/PostProcessDeferredDecals.h"
# include "LightPropagationVolume.h"
2014-08-21 06:03:00 -04:00
# include "DeferredShadingRenderer.h"
# include "SceneUtils.h"
2014-09-18 15:13:07 -04:00
# include "DistanceFieldSurfaceCacheLighting.h"
2014-09-03 07:26:17 -04:00
# include "PostProcess/PostProcessing.h"
2014-11-21 22:32:16 -05:00
# include "DistanceFieldAtlas.h"
2015-01-20 20:14:07 -05:00
# include "../../Engine/Private/SkeletalRenderGPUSkin.h" // GPrevPerBoneMotionBlur
2014-03-14 14:13:41 -04:00
TAutoConsoleVariable < int32 > CVarEarlyZPass (
TEXT ( " r.EarlyZPass " ) ,
3 ,
TEXT ( " Whether to use a depth only pass to initialize Z culling for the base pass. Cannot be changed at runtime. \n " )
TEXT ( " Note: also look at r.EarlyZPassMovable \n " )
TEXT ( " 0: off \n " )
TEXT ( " 1: only if not masked, and only if large on the screen \n " )
TEXT ( " 2: all opaque (including masked) \n " )
2014-11-20 12:36:32 -05:00
TEXT ( " x: use built in heuristic (default is 3) " ) ,
2014-03-14 14:13:41 -04:00
ECVF_Default ) ;
2014-06-25 05:47:33 -04:00
2014-03-14 14:13:41 -04:00
int32 GEarlyZPassMovable = 0 ;
/** Affects static draw lists so must reload level to propagate. */
static FAutoConsoleVariableRef CVarEarlyZPassMovable (
TEXT ( " r.EarlyZPassMovable " ) ,
GEarlyZPassMovable ,
TEXT ( " Whether to render movable objects into the depth only pass. Movable objects are typically not good occluders so this defaults to off. \n " )
TEXT ( " Note: also look at r.EarlyZPass " ) ,
ECVF_RenderThreadSafe | ECVF_ReadOnly
) ;
# if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
2014-06-25 05:47:33 -04:00
static TAutoConsoleVariable < int32 > CVarVisualizeTexturePool (
TEXT ( " r.VisualizeTexturePool " ) ,
0 ,
TEXT ( " Allows to enable the visualize the texture pool (currently only on console). \n " )
TEXT ( " 0: off \n " )
TEXT ( " 1: on " ) ,
ECVF_Cheat | ECVF_RenderThreadSafe ) ;
2014-03-14 14:13:41 -04:00
# endif
/*-----------------------------------------------------------------------------
FDeferredShadingSceneRenderer
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
FDeferredShadingSceneRenderer : : FDeferredShadingSceneRenderer ( const FSceneViewFamily * InViewFamily , FHitProxyConsumer * HitProxyConsumer )
: FSceneRenderer ( InViewFamily , HitProxyConsumer )
, EarlyZPassMode ( DDM_NonMaskedOnly )
, TranslucentSelfShadowLayout ( 0 , 0 , 0 , 0 )
, CachedTranslucentSelfShadowLightId ( INDEX_NONE )
{
if ( FPlatformProperties : : SupportsWindowedMode ( ) )
{
// Use a depth only pass if we are using full blown HQ lightmaps
// Otherwise base pass pixel shaders will be cheap and there will be little benefit to rendering a depth only pass
2014-07-24 05:23:50 -04:00
if ( AllowHighQualityLightmaps ( FeatureLevel ) | | ! ViewFamily . EngineShowFlags . Lighting )
2014-03-14 14:13:41 -04:00
{
EarlyZPassMode = DDM_None ;
}
}
// developer override, good for profiling, can be useful as project setting
{
static const auto ICVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.EarlyZPass " ) ) ;
const int32 CVarValue = ICVar - > GetValueOnGameThread ( ) ;
switch ( CVarValue )
{
case 0 : EarlyZPassMode = DDM_None ; break ;
case 1 : EarlyZPassMode = DDM_NonMaskedOnly ; break ;
case 2 : EarlyZPassMode = DDM_AllOccluders ; break ;
2014-12-18 01:27:13 -05:00
case 3 : break ; // Note: 3 indicates "default behavior" and does not specify an override
2014-03-14 14:13:41 -04:00
}
}
2015-03-12 11:26:29 -04:00
// Shader complexity requires depth only pass to display masked material cost correctly
if ( ViewFamily . EngineShowFlags . ShaderComplexity )
{
EarlyZPassMode = DDM_AllOpaque ;
}
2014-03-14 14:13:41 -04:00
}
extern FGlobalBoundShaderState GClearMRTBoundShaderState [ 8 ] ;
/**
* Clears view where Z is still at the maximum value ( ie no geometry rendered )
*/
2014-07-08 10:43:52 -04:00
void FDeferredShadingSceneRenderer : : ClearGBufferAtMaxZ ( FRHICommandList & RHICmdList )
2014-03-14 14:13:41 -04:00
{
// Assumes BeginRenderingSceneColor() has been called before this function
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , ClearGBufferAtMaxZ ) ;
2014-03-14 14:13:41 -04:00
// Clear the G Buffer render targets
const bool bClearBlack = Views [ 0 ] . Family - > EngineShowFlags . ShaderComplexity | | Views [ 0 ] . Family - > EngineShowFlags . StationaryLightOverlap ;
// Same clear color from RHIClearMRT
FLinearColor ClearColors [ 6 ] =
{ bClearBlack ? FLinearColor ( 0 , 0 , 0 , 0 ) : Views [ 0 ] . BackgroundColor , FLinearColor ( 0.5f , 0.5f , 0.5f , 0 ) , FLinearColor ( 0 , 0 , 0 , 1 ) , FLinearColor ( 0 , 0 , 0 , 0 ) , FLinearColor ( 0 , 1 , 1 , 1 ) , FLinearColor ( 1 , 1 , 1 , 1 ) } ;
uint32 NumActiveRenderTargets = GSceneRenderTargets . GetNumGBufferTargets ( ) ;
2014-08-28 06:22:54 -04:00
auto ShaderMap = GetGlobalShaderMap ( FeatureLevel ) ;
TShaderMapRef < TOneColorVS < true > > VertexShader ( ShaderMap ) ;
2014-03-14 14:13:41 -04:00
FOneColorPS * PixelShader = NULL ;
// Assume for now all code path supports SM4, otherwise render target numbers are changed
switch ( NumActiveRenderTargets )
{
case 5 :
{
2014-08-28 06:22:54 -04:00
TShaderMapRef < TOneColorPixelShaderMRT < 5 > > MRTPixelShader ( ShaderMap ) ;
2014-03-14 14:13:41 -04:00
PixelShader = * MRTPixelShader ;
}
break ;
case 6 :
{
2014-08-28 06:22:54 -04:00
TShaderMapRef < TOneColorPixelShaderMRT < 6 > > MRTPixelShader ( ShaderMap ) ;
2014-03-14 14:13:41 -04:00
PixelShader = * MRTPixelShader ;
}
break ;
default :
case 1 :
{
2014-08-28 06:22:54 -04:00
TShaderMapRef < TOneColorPixelShaderMRT < 1 > > MRTPixelShader ( ShaderMap ) ;
2014-03-14 14:13:41 -04:00
PixelShader = * MRTPixelShader ;
}
break ;
}
2014-08-19 10:41:34 -04:00
SetGlobalBoundShaderState ( RHICmdList , FeatureLevel , GClearMRTBoundShaderState [ NumActiveRenderTargets - 1 ] , GetVertexDeclarationFVector4 ( ) , * VertexShader , PixelShader ) ;
2014-03-14 14:13:41 -04:00
// Opaque rendering, depth test but no depth writes
2014-06-12 07:13:34 -04:00
RHICmdList . SetRasterizerState ( TStaticRasterizerState < FM_Solid , CM_None > : : GetRHI ( ) ) ;
RHICmdList . SetBlendState ( TStaticBlendStateWriteMask < > : : GetRHI ( ) ) ;
2015-04-01 10:53:07 -04:00
RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < false , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
// Clear each viewport by drawing background color at MaxZ depth
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " ClearView%d " ) , ViewIndex ) ;
2014-03-14 14:13:41 -04:00
FViewInfo & View = Views [ ViewIndex ] ;
// Set viewport for this view
2014-06-12 07:13:34 -04:00
RHICmdList . SetViewport ( View . ViewRect . Min . X , View . ViewRect . Min . Y , 0 , View . ViewRect . Max . X , View . ViewRect . Max . Y , 1 ) ;
2014-03-14 14:13:41 -04:00
// Setup PS
2014-06-05 16:38:54 -04:00
SetShaderValueArray ( RHICmdList , PixelShader - > GetPixelShader ( ) , PixelShader - > ColorParameter , ClearColors , NumActiveRenderTargets ) ;
2014-03-14 14:13:41 -04:00
// Render quad
2015-03-06 15:13:38 -05:00
static const FVector4 ClearQuadVertices [ 4 ] =
{
2015-03-31 14:02:45 -04:00
FVector4 ( - 1.0f , 1.0f , ( float ) ERHIZBuffer : : FarPlane , 1.0f ) ,
FVector4 ( 1.0f , 1.0f , ( float ) ERHIZBuffer : : FarPlane , 1.0f ) ,
FVector4 ( - 1.0f , - 1.0f , ( float ) ERHIZBuffer : : FarPlane , 1.0f ) ,
FVector4 ( 1.0f , - 1.0f , ( float ) ERHIZBuffer : : FarPlane , 1.0f )
2015-03-06 15:13:38 -05:00
} ;
2014-06-12 07:13:34 -04:00
DrawPrimitiveUP ( RHICmdList , PT_TriangleStrip , 2 , ClearQuadVertices , sizeof ( ClearQuadVertices [ 0 ] ) ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-06-10 07:29:49 -04:00
bool FDeferredShadingSceneRenderer : : RenderBasePassStaticDataMasked ( FRHICommandList & RHICmdList , FViewInfo & View )
2014-03-14 14:13:41 -04:00
{
bool bDirty = false ;
{
// Draw the scene's base pass draw lists.
FScene : : EBasePassDrawListType MaskedDrawType = FScene : : EBasePass_Masked ;
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , StaticMaskedNoLightmap ) ;
2014-06-05 16:38:54 -04:00
bDirty | = Scene - > BasePassNoLightMapDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassSimpleDynamicLightingDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassCachedVolumeIndirectLightingDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassCachedPointIndirectLightingDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
2014-03-14 14:13:41 -04:00
}
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , StaticMaskedLightmapped ) ;
2014-06-05 16:38:54 -04:00
bDirty | = Scene - > BasePassHighQualityLightMapDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassDistanceFieldShadowMapLightMapDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassLowQualityLightMapDrawList [ MaskedDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
2014-03-14 14:13:41 -04:00
}
}
return bDirty ;
}
2014-10-02 11:20:07 -04:00
void FDeferredShadingSceneRenderer : : RenderBasePassStaticDataMaskedParallel ( FParallelCommandListSet & ParallelCommandListSet )
2014-07-17 08:14:11 -04:00
{
// Draw the scene's base pass draw lists.
FScene : : EBasePassDrawListType MaskedDrawType = FScene : : EBasePass_Masked ;
2014-09-11 09:38:38 -04:00
{
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, StaticMaskedNoLightmap);
2014-10-02 11:20:07 -04:00
Scene - > BasePassNoLightMapDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassSimpleDynamicLightingDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassCachedVolumeIndirectLightingDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassCachedPointIndirectLightingDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-09-11 09:38:38 -04:00
}
2014-07-17 08:14:11 -04:00
2014-09-11 09:38:38 -04:00
{
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, StaticMaskedLightmapped);
2014-10-02 11:20:07 -04:00
Scene - > BasePassHighQualityLightMapDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassDistanceFieldShadowMapLightMapDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassLowQualityLightMapDrawList [ MaskedDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-09-11 09:38:38 -04:00
}
2014-07-17 08:14:11 -04:00
}
2014-07-15 07:34:34 -04:00
2014-06-10 07:29:49 -04:00
bool FDeferredShadingSceneRenderer : : RenderBasePassStaticDataDefault ( FRHICommandList & RHICmdList , FViewInfo & View )
2014-03-14 14:13:41 -04:00
{
bool bDirty = false ;
{
FScene : : EBasePassDrawListType OpaqueDrawType = FScene : : EBasePass_Default ;
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , StaticOpaqueNoLightmap ) ;
2014-06-05 16:38:54 -04:00
bDirty | = Scene - > BasePassNoLightMapDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassSimpleDynamicLightingDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassCachedVolumeIndirectLightingDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassCachedPointIndirectLightingDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
2014-03-14 14:13:41 -04:00
}
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , StaticOpaqueLightmapped ) ;
2014-06-05 16:38:54 -04:00
bDirty | = Scene - > BasePassHighQualityLightMapDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassDistanceFieldShadowMapLightMapDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
bDirty | = Scene - > BasePassLowQualityLightMapDrawList [ OpaqueDrawType ] . DrawVisible ( RHICmdList , View , View . StaticMeshVisibilityMap , View . StaticMeshBatchVisibility ) ;
2014-03-14 14:13:41 -04:00
}
}
return bDirty ;
}
2014-10-02 11:20:07 -04:00
void FDeferredShadingSceneRenderer : : RenderBasePassStaticDataDefaultParallel ( FParallelCommandListSet & ParallelCommandListSet )
2014-07-17 08:14:11 -04:00
{
FScene : : EBasePassDrawListType OpaqueDrawType = FScene : : EBasePass_Default ;
2014-09-11 09:38:38 -04:00
{
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, StaticOpaqueNoLightmap);
2014-10-02 11:20:07 -04:00
Scene - > BasePassNoLightMapDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassSimpleDynamicLightingDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassCachedVolumeIndirectLightingDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassCachedPointIndirectLightingDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-09-11 09:38:38 -04:00
}
2014-07-17 08:14:11 -04:00
2014-09-11 09:38:38 -04:00
{
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, StaticOpaqueLightmapped);
2014-10-02 11:20:07 -04:00
Scene - > BasePassHighQualityLightMapDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassDistanceFieldShadowMapLightMapDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
Scene - > BasePassLowQualityLightMapDrawList [ OpaqueDrawType ] . DrawVisibleParallel ( ParallelCommandListSet . View . StaticMeshVisibilityMap , ParallelCommandListSet . View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-09-11 09:38:38 -04:00
}
2014-07-17 08:14:11 -04:00
}
2014-03-14 14:13:41 -04:00
void FDeferredShadingSceneRenderer : : SortBasePassStaticData ( FVector ViewPosition )
{
// If we're not using a depth only pass, sort the static draw list buckets roughly front to back, to maximize HiZ culling
// Note that this is only a very rough sort, since it does not interfere with state sorting, and each list is sorted separately
if ( EarlyZPassMode = = DDM_None )
{
SCOPE_CYCLE_COUNTER ( STAT_SortStaticDrawLists ) ;
for ( int32 DrawType = 0 ; DrawType < FScene : : EBasePass_MAX ; DrawType + + )
{
Scene - > BasePassNoLightMapDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
Scene - > BasePassSimpleDynamicLightingDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
Scene - > BasePassCachedVolumeIndirectLightingDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
Scene - > BasePassCachedPointIndirectLightingDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
Scene - > BasePassHighQualityLightMapDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
Scene - > BasePassDistanceFieldShadowMapLightMapDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
Scene - > BasePassLowQualityLightMapDrawList [ DrawType ] . SortFrontToBack ( ViewPosition ) ;
}
}
}
/**
* Renders the basepass for the static data of a given View .
*
* @ return true if anything was rendered to scene color
*/
2014-06-10 07:29:49 -04:00
bool FDeferredShadingSceneRenderer : : RenderBasePassStaticData ( FRHICommandList & RHICmdList , FViewInfo & View )
2014-03-14 14:13:41 -04:00
{
bool bDirty = false ;
SCOPE_CYCLE_COUNTER ( STAT_StaticDrawListDrawTime ) ;
// When using a depth-only pass, the default opaque geometry's depths are already
// in the depth buffer at this point, so rendering masked next will already cull
// as efficiently as it can, while also increasing the ZCull efficiency when
// rendering the default opaque geometry afterward.
if ( EarlyZPassMode ! = DDM_None )
{
2014-06-05 16:38:54 -04:00
bDirty | = RenderBasePassStaticDataMasked ( RHICmdList , View ) ;
bDirty | = RenderBasePassStaticDataDefault ( RHICmdList , View ) ;
2014-03-14 14:13:41 -04:00
}
else
{
// Otherwise, in the case where we're not using a depth-only pre-pass, there
// is an advantage to rendering default opaque first to help cull the more
// expensive masked geometry.
2014-06-05 16:38:54 -04:00
bDirty | = RenderBasePassStaticDataDefault ( RHICmdList , View ) ;
bDirty | = RenderBasePassStaticDataMasked ( RHICmdList , View ) ;
2014-03-14 14:13:41 -04:00
}
return bDirty ;
}
2014-10-02 11:20:07 -04:00
void FDeferredShadingSceneRenderer : : RenderBasePassStaticDataParallel ( FParallelCommandListSet & ParallelCommandListSet )
2014-07-17 08:14:11 -04:00
{
SCOPE_CYCLE_COUNTER ( STAT_StaticDrawListDrawTime ) ;
// When using a depth-only pass, the default opaque geometry's depths are already
// in the depth buffer at this point, so rendering masked next will already cull
// as efficiently as it can, while also increasing the ZCull efficiency when
// rendering the default opaque geometry afterward.
if ( EarlyZPassMode ! = DDM_None )
{
2014-10-02 11:20:07 -04:00
RenderBasePassStaticDataMaskedParallel ( ParallelCommandListSet ) ;
RenderBasePassStaticDataDefaultParallel ( ParallelCommandListSet ) ;
2014-07-17 08:14:11 -04:00
}
else
{
// Otherwise, in the case where we're not using a depth-only pre-pass, there
// is an advantage to rendering default opaque first to help cull the more
// expensive masked geometry.
2014-10-02 11:20:07 -04:00
RenderBasePassStaticDataDefaultParallel ( ParallelCommandListSet ) ;
RenderBasePassStaticDataMaskedParallel ( ParallelCommandListSet ) ;
2014-07-17 08:14:11 -04:00
}
}
2014-03-14 14:13:41 -04:00
/**
* Renders the basepass for the dynamic data of a given DPG and View .
*
* @ return true if anything was rendered to scene color
*/
2014-07-23 10:50:15 -04:00
void FDeferredShadingSceneRenderer : : RenderBasePassDynamicData ( FRHICommandList & RHICmdList , const FViewInfo & View , bool & bOutDirty )
2014-03-14 14:13:41 -04:00
{
2014-07-23 10:50:15 -04:00
bool bDirty = false ;
SCOPE_CYCLE_COUNTER ( STAT_DynamicPrimitiveDrawTime ) ;
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , Dynamic ) ;
2014-07-23 10:50:15 -04:00
2014-11-25 17:56:43 -05:00
FBasePassOpaqueDrawingPolicyFactory : : ContextType Context ( false , ESceneRenderTargetsMode : : DontSet ) ;
2014-08-12 18:24:52 -04:00
2014-11-25 17:56:43 -05:00
for ( int32 MeshBatchIndex = 0 ; MeshBatchIndex < View . DynamicMeshElements . Num ( ) ; MeshBatchIndex + + )
2014-08-12 18:24:52 -04:00
{
2014-11-25 17:56:43 -05:00
const FMeshBatchAndRelevance & MeshBatchAndRelevance = View . DynamicMeshElements [ MeshBatchIndex ] ;
2014-08-12 18:24:52 -04:00
2014-11-25 17:56:43 -05:00
if ( ( MeshBatchAndRelevance . bHasOpaqueOrMaskedMaterial | | ViewFamily . EngineShowFlags . Wireframe )
& & MeshBatchAndRelevance . bRenderInMainPass )
2014-08-12 18:24:52 -04:00
{
2014-11-25 17:56:43 -05:00
const FMeshBatch & MeshBatch = * MeshBatchAndRelevance . Mesh ;
FBasePassOpaqueDrawingPolicyFactory : : DrawDynamicMesh ( RHICmdList , View , Context , MeshBatch , false , true , MeshBatchAndRelevance . PrimitiveSceneProxy , MeshBatch . BatchHitProxyId ) ;
2014-08-12 18:24:52 -04:00
}
}
2014-07-23 10:50:15 -04:00
2014-11-25 17:56:43 -05:00
View . SimpleElementCollector . DrawBatchedElements ( RHICmdList , View , FTexture2DRHIRef ( ) , EBlendModeFilter : : OpaqueAndMasked ) ;
2014-03-14 14:13:41 -04:00
if ( ! View . Family - > EngineShowFlags . CompositeEditorPrimitives )
{
2014-08-19 10:41:34 -04:00
const auto ShaderPlatform = View . GetShaderPlatform ( ) ;
const bool bNeedToSwitchVerticalAxis = RHINeedsToSwitchVerticalAxis ( ShaderPlatform ) ;
2014-03-14 14:13:41 -04:00
// Draw the base pass for the view's batched mesh elements.
2014-07-02 12:18:30 -04:00
bDirty = DrawViewElements < FBasePassOpaqueDrawingPolicyFactory > ( RHICmdList , View , FBasePassOpaqueDrawingPolicyFactory : : ContextType ( false , ESceneRenderTargetsMode : : DontSet ) , SDPG_World , true ) | | bDirty ;
2014-03-14 14:13:41 -04:00
// Draw the view's batched simple elements(lines, sprites, etc).
2014-08-19 10:41:34 -04:00
bDirty = View . BatchedViewElements . Draw ( RHICmdList , FeatureLevel , bNeedToSwitchVerticalAxis , View . ViewProjectionMatrix , View . ViewRect . Width ( ) , View . ViewRect . Height ( ) , false ) | | bDirty ;
2014-03-14 14:13:41 -04:00
// Draw foreground objects last
2014-07-02 12:18:30 -04:00
bDirty = DrawViewElements < FBasePassOpaqueDrawingPolicyFactory > ( RHICmdList , View , FBasePassOpaqueDrawingPolicyFactory : : ContextType ( false , ESceneRenderTargetsMode : : DontSet ) , SDPG_Foreground , true ) | | bDirty ;
2014-03-14 14:13:41 -04:00
// Draw the view's batched simple elements(lines, sprites, etc).
2014-08-19 10:41:34 -04:00
bDirty = View . TopBatchedViewElements . Draw ( RHICmdList , FeatureLevel , bNeedToSwitchVerticalAxis , View . ViewProjectionMatrix , View . ViewRect . Width ( ) , View . ViewRect . Height ( ) , false ) | | bDirty ;
2014-03-14 14:13:41 -04:00
}
2014-07-23 10:50:15 -04:00
// this little bit of code is required because multiple threads might be writing bOutDirty...this you cannot use || bDirty - type things.
if ( bDirty )
{
bOutDirty = true ;
}
}
class FRenderBasePassDynamicDataThreadTask
{
FDeferredShadingSceneRenderer & ThisRenderer ;
FRHICommandList & RHICmdList ;
const FViewInfo & View ;
bool & OutDirty ;
public :
FRenderBasePassDynamicDataThreadTask (
2014-10-06 10:05:28 -04:00
FDeferredShadingSceneRenderer & InThisRenderer ,
FRHICommandList & InRHICmdList ,
const FViewInfo & InView ,
bool & InOutDirty
2014-07-23 10:50:15 -04:00
)
2014-10-06 10:05:28 -04:00
: ThisRenderer ( InThisRenderer )
, RHICmdList ( InRHICmdList )
, View ( InView )
, OutDirty ( InOutDirty )
2014-07-23 10:50:15 -04:00
{
}
FORCEINLINE TStatId GetStatId ( ) const
{
RETURN_QUICK_DECLARE_CYCLE_STAT ( FRenderBasePassDynamicDataThreadTask , STATGROUP_TaskGraphTasks ) ;
}
ENamedThreads : : Type GetDesiredThread ( )
{
return ENamedThreads : : AnyThread ;
}
static ESubsequentsMode : : Type GetSubsequentsMode ( ) { return ESubsequentsMode : : TrackSubsequents ; }
void DoTask ( ENamedThreads : : Type CurrentThread , const FGraphEventRef & MyCompletionGraphEvent )
{
ThisRenderer . RenderBasePassDynamicData ( RHICmdList , View , OutDirty ) ;
2014-09-03 10:52:00 -04:00
RHICmdList . HandleRTThreadTaskCompletion ( MyCompletionGraphEvent ) ;
2014-07-23 10:50:15 -04:00
}
} ;
2014-10-02 11:20:07 -04:00
void FDeferredShadingSceneRenderer : : RenderBasePassDynamicDataParallel ( FParallelCommandListSet & ParallelCommandListSet )
2014-07-23 10:50:15 -04:00
{
2014-10-02 11:20:07 -04:00
FRHICommandList * CmdList = ParallelCommandListSet . NewParallelCommandList ( ) ;
2014-07-23 10:50:15 -04:00
FGraphEventRef AnyThreadCompletionEvent = TGraphTask < FRenderBasePassDynamicDataThreadTask > : : CreateTask ( nullptr , ENamedThreads : : RenderThread )
2014-10-06 10:05:28 -04:00
. ConstructAndDispatchWhenReady ( * this , * CmdList , ParallelCommandListSet . View , ParallelCommandListSet . OutDirty ) ;
2014-07-23 10:50:15 -04:00
2014-10-02 11:20:07 -04:00
ParallelCommandListSet . AddParallelCommandList ( CmdList , AnyThreadCompletionEvent ) ;
2014-03-14 14:13:41 -04:00
}
2014-08-12 08:46:25 -04:00
static void SetupBasePassView ( FRHICommandList & RHICmdList , const FIntRect & ViewRect , bool bShaderComplexity )
2014-07-24 09:29:37 -04:00
{
if ( bShaderComplexity )
{
// Additive blending when shader complexity viewmode is enabled.
RHICmdList . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_One , BF_One , BO_Add , BF_Zero , BF_One > : : GetRHI ( ) ) ;
// Disable depth writes as we have a full depth prepass.
2015-04-01 10:53:07 -04:00
RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < false , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
2014-07-24 09:29:37 -04:00
}
else
{
// Opaque blending for all G buffer targets, depth tests and writes.
2015-02-02 18:00:05 -05:00
static const auto CVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.BasePassOutputsVelocityDebug " ) ) ;
if ( CVar & & CVar - > GetValueOnRenderThread ( ) = = 2 )
{
RHICmdList . SetBlendState ( TStaticBlendStateWriteMask < CW_RGBA , CW_RGBA , CW_RGBA , CW_RGBA , CW_RGBA , CW_RGBA , CW_NONE > : : GetRHI ( ) ) ;
}
else
{
RHICmdList . SetBlendState ( TStaticBlendStateWriteMask < CW_RGBA , CW_RGBA , CW_RGBA , CW_RGBA > : : GetRHI ( ) ) ;
}
2015-04-01 10:53:07 -04:00
RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < true , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
2014-07-24 09:29:37 -04:00
}
2015-02-05 16:35:00 -05:00
RHICmdList . SetScissorRect ( false , 0 , 0 , 0 , 0 ) ;
2014-08-12 08:46:25 -04:00
RHICmdList . SetViewport ( ViewRect . Min . X , ViewRect . Min . Y , 0 , ViewRect . Max . X , ViewRect . Max . Y , 1 ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetRasterizerState ( TStaticRasterizerState < FM_Solid , CM_None > : : GetRHI ( ) ) ;
2014-07-24 09:29:37 -04:00
}
2014-10-02 11:20:07 -04:00
class FBasePassParallelCommandListSet : public FParallelCommandListSet
2014-07-24 09:29:37 -04:00
{
2014-10-02 11:20:07 -04:00
public :
const FSceneViewFamily & ViewFamily ;
2014-07-24 09:29:37 -04:00
2014-10-02 11:20:07 -04:00
FBasePassParallelCommandListSet ( const FViewInfo & InView , FRHICommandList & InParentCmdList , bool * InOutDirty , bool bInParallelExecute , const FSceneViewFamily & InViewFamily )
: FParallelCommandListSet ( InView , InParentCmdList , InOutDirty , bInParallelExecute )
, ViewFamily ( InViewFamily )
{
SetStateOnCommandList ( ParentCmdList ) ;
}
2015-01-27 16:14:50 -05:00
virtual ~ FBasePassParallelCommandListSet ( )
{
Dispatch ( ) ;
}
2014-10-02 11:20:07 -04:00
virtual void SetStateOnCommandList ( FRHICommandList & CmdList ) override
{
2014-10-23 16:31:43 -04:00
GSceneRenderTargets . BeginRenderingGBuffer ( CmdList , ERenderTargetLoadAction : : ELoad , ERenderTargetLoadAction : : ELoad ) ;
2014-10-02 11:20:07 -04:00
SetupBasePassView ( CmdList , View . ViewRect , ! ! ViewFamily . EngineShowFlags . ShaderComplexity ) ;
}
} ;
static TAutoConsoleVariable < int32 > CVarRHICmdBasePassDeferredContexts (
TEXT ( " r.RHICmdBasePassDeferredContexts " ) ,
1 ,
2014-11-20 12:36:32 -05:00
TEXT ( " True to use deferred contexts to parallelize base pass command list execution. " ) ) ;
2014-10-02 11:20:07 -04:00
void FDeferredShadingSceneRenderer : : RenderBasePassViewParallel ( FViewInfo & View , FRHICommandList & ParentCmdList , bool & OutDirty )
{
FBasePassParallelCommandListSet ParallelSet ( View , ParentCmdList , & OutDirty , CVarRHICmdBasePassDeferredContexts . GetValueOnRenderThread ( ) > 0 , ViewFamily ) ;
RenderBasePassStaticDataParallel ( ParallelSet ) ;
RenderBasePassDynamicDataParallel ( ParallelSet ) ;
2014-07-24 09:29:37 -04:00
}
bool FDeferredShadingSceneRenderer : : RenderBasePassView ( FRHICommandListImmediate & RHICmdList , FViewInfo & View )
2014-03-14 14:13:41 -04:00
{
2014-07-23 10:50:15 -04:00
bool bDirty = false ;
2014-08-12 08:46:25 -04:00
SetupBasePassView ( RHICmdList , View . ViewRect , ViewFamily . EngineShowFlags . ShaderComplexity ) ;
2014-07-24 09:29:37 -04:00
bDirty | = RenderBasePassStaticData ( RHICmdList , View ) ;
RenderBasePassDynamicData ( RHICmdList , View , bDirty ) ;
2014-03-14 14:13:41 -04:00
2014-07-23 10:50:15 -04:00
return bDirty ;
2014-03-14 14:13:41 -04:00
}
/** Render the TexturePool texture */
# if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
2014-06-27 11:07:13 -04:00
void FDeferredShadingSceneRenderer : : RenderVisualizeTexturePool ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
TRefCountPtr < IPooledRenderTarget > VisualizeTexturePool ;
/** Resolution for the texture pool visualizer texture. */
enum
{
TexturePoolVisualizerSizeX = 280 ,
TexturePoolVisualizerSizeY = 140 ,
} ;
FPooledRenderTargetDesc Desc ( FPooledRenderTargetDesc : : Create2DDesc ( FIntPoint ( TexturePoolVisualizerSizeX , TexturePoolVisualizerSizeY ) , PF_B8G8R8A8 , TexCreate_None , TexCreate_None , false ) ) ;
GRenderTargetPool . FindFreeElement ( Desc , VisualizeTexturePool , TEXT ( " VisualizeTexturePool " ) ) ;
uint32 Pitch ;
2014-06-27 11:07:13 -04:00
FColor * TextureData = ( FColor * ) RHICmdList . LockTexture2D ( ( FTexture2DRHIRef & ) VisualizeTexturePool - > GetRenderTargetItem ( ) . ShaderResourceTexture , 0 , RLM_WriteOnly , Pitch , false ) ;
2014-03-14 14:13:41 -04:00
if ( TextureData )
{
// clear with grey to get reliable background color
FMemory : : Memset ( TextureData , 0x88 , TexturePoolVisualizerSizeX * TexturePoolVisualizerSizeY * 4 ) ;
2014-06-27 11:07:13 -04:00
RHICmdList . GetTextureMemoryVisualizeData ( TextureData , TexturePoolVisualizerSizeX , TexturePoolVisualizerSizeY , Pitch , 4096 ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-27 11:07:13 -04:00
RHICmdList . UnlockTexture2D ( ( FTexture2DRHIRef & ) VisualizeTexturePool - > GetRenderTargetItem ( ) . ShaderResourceTexture , 0 , false ) ;
2014-03-14 14:13:41 -04:00
FIntPoint RTExtent = GSceneRenderTargets . GetBufferSizeXY ( ) ;
FVector2D Tex00 = FVector2D ( 0 , 0 ) ;
FVector2D Tex11 = FVector2D ( 1 , 1 ) ;
//todo VisualizeTexture(*VisualizeTexturePool, ViewFamily.RenderTarget, FIntRect(0, 0, RTExtent.X, RTExtent.Y), RTExtent, 1.0f, 0.0f, 0.0f, Tex00, Tex11, 1.0f, false);
}
# endif
/**
* Finishes the view family rendering .
*/
2014-06-27 11:07:13 -04:00
void FDeferredShadingSceneRenderer : : RenderFinish ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
# if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
{
2014-06-25 05:47:33 -04:00
if ( CVarVisualizeTexturePool . GetValueOnRenderThread ( ) )
2014-03-14 14:13:41 -04:00
{
2014-06-27 11:07:13 -04:00
RenderVisualizeTexturePool ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
}
# endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
2014-06-27 11:07:13 -04:00
FSceneRenderer : : RenderFinish ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
2014-05-06 17:24:57 -04:00
// Some RT should be released as early as possible to allow sharing of that memory for other purposes.
// SceneColor is be released in tone mapping, if not we want to get access to the HDR scene color after this pass so we keep it.
2014-05-06 11:27:50 -04:00
// This becomes even more important with some limited VRam (XBoxOne).
GSceneRenderTargets . SetLightAttenuation ( 0 ) ;
2014-03-14 14:13:41 -04:00
}
2015-01-09 20:56:36 -05:00
void BuildHZB ( FRHICommandListImmediate & RHICmdList , FViewInfo & View ) ;
2014-03-14 14:13:41 -04:00
/**
* Renders the view family .
*/
2014-09-03 10:52:00 -04:00
2014-10-02 11:20:07 -04:00
DECLARE_STATS_GROUP ( TEXT ( " Command List Markers " ) , STATGROUP_CommandListMarkers , STATCAT_Advanced ) ;
DECLARE_CYCLE_STAT ( TEXT ( " PrePass " ) , STAT_CLM_PrePass , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " AfterPrePass " ) , STAT_CLM_AfterPrePass , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " BasePass " ) , STAT_CLM_BasePass , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " AfterBasePass " ) , STAT_CLM_AfterBasePass , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " Lighting " ) , STAT_CLM_Lighting , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " AfterLighting " ) , STAT_CLM_AfterLighting , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " Translucency " ) , STAT_CLM_Translucency , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " AfterTranslucency " ) , STAT_CLM_AfterTranslucency , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " Velocity " ) , STAT_CLM_Velocity , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " AfterVelocity " ) , STAT_CLM_AfterVelocity , STATGROUP_CommandListMarkers ) ;
DECLARE_CYCLE_STAT ( TEXT ( " AfterFrame " ) , STAT_CLM_AfterFrame , STATGROUP_CommandListMarkers ) ;
2015-03-26 18:31:22 -04:00
FGraphEventRef FDeferredShadingSceneRenderer : : OcclusionSubmittedFence ;
2014-10-23 16:31:43 -04:00
/**
* Returns true if the depth Prepass needs to run
*/
static FORCEINLINE bool NeedsPrePass ( const FDeferredShadingSceneRenderer * Renderer )
{
return ( RHIHasTiledGPU ( Renderer - > ViewFamily . GetShaderPlatform ( ) ) = = false ) & &
( Renderer - > EarlyZPassMode ! = DDM_None | | GEarlyZPassMovable ! = 0 ) ;
}
2014-10-02 11:20:07 -04:00
2014-10-27 20:23:51 -04:00
static void SetAndClearViewGBuffer ( FRHICommandListImmediate & RHICmdList , FViewInfo & View , bool bClearDepth )
{
// if we didn't to the prepass above, then we will need to clear now, otherwise, it's already been cleared and rendered to
ERenderTargetLoadAction DepthLoadAction = bClearDepth ? ERenderTargetLoadAction : : EClear : ERenderTargetLoadAction : : ELoad ;
const bool bClearBlack = View . Family - > EngineShowFlags . ShaderComplexity | | View . Family - > EngineShowFlags . StationaryLightOverlap ;
const FLinearColor ClearColor = ( bClearBlack ? FLinearColor ( 0 , 0 , 0 , 0 ) : View . BackgroundColor ) ;
// clearing the GBuffer
GSceneRenderTargets . BeginRenderingGBuffer ( RHICmdList , ERenderTargetLoadAction : : EClear , DepthLoadAction , ClearColor ) ;
}
2015-03-26 18:31:22 -04:00
static TAutoConsoleVariable < int32 > CVarOcclusionQueryLocation (
TEXT ( " r.OcclusionQueryLocation " ) ,
0 ,
TEXT ( " Controls when occlusion queries are rendered. Rendering before the base pass may give worse occlusion (because not all occluders generally render in the earlyzpass). " )
TEXT ( " However, it may reduce CPU waiting for query result stalls on some platforms and increase overall performance. " )
TEXT ( " 0: After BasePass. " )
TEXT ( " 1: After EarlyZPass, but before BasePass. " ) ) ;
void FDeferredShadingSceneRenderer : : RenderOcclusion ( FRHICommandListImmediate & RHICmdList , bool bRenderQueries , bool bRenderHZB )
{
if ( bRenderQueries | | bRenderHZB )
{
{
// Update the quarter-sized depth buffer with the current contents of the scene depth texture.
// This needs to happen before occlusion tests, which makes use of the small depth buffer.
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_UpdateDownsampledDepthSurface ) ;
UpdateDownsampledDepthSurface ( RHICmdList ) ;
}
2015-04-09 19:14:28 -04:00
2015-03-26 18:31:22 -04:00
if ( bRenderHZB )
2015-04-09 19:14:28 -04:00
{
static const auto ICVarAO = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.AmbientOcclusionLevels " ) ) ;
static const auto ICVarHZBOcc = IConsoleManager : : Get ( ) . FindConsoleVariable ( TEXT ( " r.HZBOcclusion " ) ) ;
bool bSSAO = ICVarAO - > GetValueOnRenderThread ( ) ! = 0 ;
bool bHzbOcclusion = ICVarHZBOcc - > GetInt ( ) ! = 0 ;
2015-03-26 18:31:22 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
2015-04-09 19:14:28 -04:00
const uint32 bSSR = DoScreenSpaceReflections ( Views [ ViewIndex ] ) ;
if ( bSSAO | | bHzbOcclusion | | bSSR )
{
BuildHZB ( RHICmdList , Views [ ViewIndex ] ) ;
}
2015-03-26 18:31:22 -04:00
}
}
// Issue occlusion queries
// This is done after the downsampled depth buffer is created so that it can be used for issuing queries
BeginOcclusionTests ( RHICmdList , bRenderQueries , bRenderHZB ) ;
2015-04-22 14:16:01 -04:00
// Hint to the RHI to submit commands up to this point to the GPU if possible. Can help avoid CPU stalls next frame waiting
// for these query results on some platforms.
RHICmdList . SubmitCommandsHint ( ) ;
2015-03-26 18:31:22 -04:00
if ( bRenderQueries & & GRHIThread )
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_OcclusionSubmittedFence_Dispatch ) ;
OcclusionSubmittedFence = FRHICommandListExecutor : : RHIThreadFence ( ) ;
}
}
}
2014-06-27 11:07:13 -04:00
void FDeferredShadingSceneRenderer : : Render ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
2015-03-26 18:31:22 -04:00
bool bDBuffer = IsDBufferEnabled ( ) ;
2014-09-03 10:52:00 -04:00
if ( GRHIThread )
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_OcclusionSubmittedFence_Wait ) ;
FRHICommandListExecutor : : WaitOnRHIThreadFence ( OcclusionSubmittedFence ) ;
}
2014-03-14 14:13:41 -04:00
if ( ! ViewFamily . EngineShowFlags . Rendering )
{
return ;
}
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , Scene ) ;
2014-09-03 10:52:00 -04:00
2015-03-04 08:31:40 -05:00
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_Render_Init ) ;
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
// Initialize global system textures (pass-through if already initialized).
GSystemTextures . InitializeTextures ( RHICmdList , FeatureLevel ) ;
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
// Allocate the maximum scene render target space for the current view family.
GSceneRenderTargets . Allocate ( ViewFamily ) ;
}
2014-03-14 14:13:41 -04:00
// Find the visible primitives.
2014-06-27 11:07:13 -04:00
InitViews ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
2014-09-03 10:52:00 -04:00
if ( GRHIThread )
{
// we will probably stall on occlusion queries, so might as well have the RHI thread and GPU work while we wait.
QUICK_SCOPE_CYCLE_COUNTER ( STAT_PostInitViews_FlushDel ) ;
FRHICommandListExecutor : : GetImmediateCommandList ( ) . ImmediateFlush ( EImmediateFlushType : : FlushRHIThreadFlushResources ) ;
}
2014-11-21 22:32:16 -05:00
if ( ShouldPrepareForDistanceFieldAO ( ) | | ShouldPrepareForDistanceFieldShadows ( ) )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_DistanceFieldAO_Init ) ;
2014-12-10 11:54:51 -05:00
GDistanceFieldVolumeTextureAtlas . UpdateAllocations ( ) ;
UpdateGlobalDistanceFieldObjectBuffers ( RHICmdList ) ;
2015-02-06 23:31:19 -05:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
Views [ ViewIndex ] . HeightfieldLightingViewInfo . SetupVisibleHeightfields ( Views [ ViewIndex ] , RHICmdList ) ;
}
2014-11-21 22:32:16 -05:00
}
2014-09-03 10:52:00 -04:00
2014-03-14 14:13:41 -04:00
const bool bIsWireframe = ViewFamily . EngineShowFlags . Wireframe ;
static const auto ClearMethodCVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.ClearSceneMethod " ) ) ;
bool bRequiresRHIClear = true ;
bool bRequiresFarZQuadClear = false ;
2014-07-29 17:32:52 -04:00
static const auto GBufferCVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.GBuffer " ) ) ;
bool bGBuffer = GBufferCVar ? ( GBufferCVar - > GetValueOnRenderThread ( ) ! = 0 ) : true ;
if ( ViewFamily . EngineShowFlags . ForceGBuffer )
{
bGBuffer = true ;
}
2014-03-14 14:13:41 -04:00
if ( ClearMethodCVar )
{
2015-04-17 11:11:12 -04:00
int32 clearMethod = ClearMethodCVar - > GetValueOnRenderThread ( ) ;
if ( clearMethod = = 0 & & ! ViewFamily . EngineShowFlags . Game )
{
// Do not clear the scene only if the view family is in game mode.
clearMethod = 1 ;
}
switch ( clearMethod )
2014-03-14 14:13:41 -04:00
{
case 0 : // No clear
{
bRequiresRHIClear = false ;
bRequiresFarZQuadClear = false ;
break ;
}
2014-06-27 11:07:13 -04:00
case 1 : // RHICmdList.Clear
2014-03-14 14:13:41 -04:00
{
bRequiresRHIClear = true ;
bRequiresFarZQuadClear = false ;
break ;
}
case 2 : // Clear using far-z quad
{
bRequiresFarZQuadClear = true ;
bRequiresRHIClear = false ;
break ;
}
}
}
// Always perform a full buffer clear for wireframe, shader complexity view mode, and stationary light overlap viewmode.
if ( bIsWireframe | | ViewFamily . EngineShowFlags . ShaderComplexity | | ViewFamily . EngineShowFlags . StationaryLightOverlap )
{
bRequiresRHIClear = true ;
}
// force using occ queries for wireframe if rendering is parented or frozen in the first view
check ( Views . Num ( ) ) ;
# if (UE_BUILD_SHIPPING || UE_BUILD_TEST)
const bool bIsViewFrozen = false ;
const bool bHasViewParent = false ;
# else
const bool bIsViewFrozen = Views [ 0 ] . State & & ( ( FSceneViewState * ) Views [ 0 ] . State ) - > bIsFrozen ;
const bool bHasViewParent = Views [ 0 ] . State & & ( ( FSceneViewState * ) Views [ 0 ] . State ) - > HasViewParent ( ) ;
# endif
2014-06-05 16:38:54 -04:00
2014-06-27 11:07:13 -04:00
2014-08-19 10:41:34 -04:00
const bool bIsOcclusionTesting = DoOcclusionQueries ( FeatureLevel ) & & ( ! bIsWireframe | | bIsViewFrozen | | bHasViewParent ) ;
2014-03-14 14:13:41 -04:00
// Dynamic vertex and index buffers need to be committed before rendering.
2015-03-04 08:31:40 -05:00
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_FGlobalDynamicVertexBuffer_Commit ) ;
FGlobalDynamicVertexBuffer : : Get ( ) . Commit ( ) ;
FGlobalDynamicIndexBuffer : : Get ( ) . Commit ( ) ;
}
2014-03-14 14:13:41 -04:00
2015-04-27 14:32:32 -04:00
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_MotionBlurStartFrame ) ;
Scene - > MotionBlurInfoData . StartFrame ( ViewFamily . bWorldIsPaused ) ;
}
2014-03-14 14:13:41 -04:00
// Notify the FX system that the scene is about to be rendered.
if ( Scene - > FXSystem )
{
2014-06-27 11:07:13 -04:00
Scene - > FXSystem - > PreRender ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:52:11 -04:00
GRenderTargetPool . AddPhaseEvent ( TEXT ( " EarlyZPass " ) ) ;
2014-03-14 14:13:41 -04:00
// Draw the scene pre-pass / early z pass, populating the scene depth buffer and HiZ
2014-10-23 16:31:43 -04:00
bool bDepthWasCleared = false ;
2015-03-26 18:31:22 -04:00
const bool bNeedsPrePass = NeedsPrePass ( this ) ;
if ( bNeedsPrePass )
2014-10-23 16:31:43 -04:00
{
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_PrePass ) ) ;
RenderPrePass ( RHICmdList ) ;
// at this point, the depth was cleared
bDepthWasCleared = true ;
}
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_AfterPrePass ) ) ;
2015-03-26 18:31:22 -04:00
//occlusion can't run before basepass if there's no prepass to fill in some depth to occlude against.
bool bOcclusionBeforeBasePass = ( CVarOcclusionQueryLocation . GetValueOnRenderThread ( ) = = 1 ) & & bNeedsPrePass ;
bool bHZBBeforeBasePass = false ;
RenderOcclusion ( RHICmdList , bOcclusionBeforeBasePass , bHZBBeforeBasePass ) ;
2014-06-05 16:38:54 -04:00
2015-02-02 18:00:05 -05:00
const bool bShouldRenderVelocities = ShouldRenderVelocities ( ) ;
const bool bUseVelocityGBuffer = FVelocityRendering : : OutputsToGBuffer ( ) ;
2015-03-04 08:31:40 -05:00
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_AllocGBufferTargets ) ;
GSceneRenderTargets . PreallocGBufferTargets ( bShouldRenderVelocities & & bUseVelocityGBuffer ) ;
GSceneRenderTargets . AllocGBufferTargets ( ) ;
}
2014-03-14 14:13:41 -04:00
// Clear LPVs for all views
2014-08-19 10:41:34 -04:00
if ( FeatureLevel > = ERHIFeatureLevel : : SM5 )
2014-03-14 14:13:41 -04:00
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_ClearLPVs ) ;
2014-06-05 16:38:54 -04:00
ClearLPVs ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
// only temporarily available after early z pass and until base pass
check ( ! GSceneRenderTargets . DBufferA ) ;
check ( ! GSceneRenderTargets . DBufferB ) ;
check ( ! GSceneRenderTargets . DBufferC ) ;
2014-09-15 11:46:14 -04:00
if ( bDBuffer )
2014-03-14 14:13:41 -04:00
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_DBuffer ) ;
2014-06-27 11:07:13 -04:00
GSceneRenderTargets . ResolveSceneDepthTexture ( RHICmdList ) ;
GSceneRenderTargets . ResolveSceneDepthToAuxiliaryTexture ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
2015-04-23 13:22:07 -04:00
// e.g. DBuffer deferred decals
2014-03-14 14:13:41 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2015-04-23 13:22:07 -04:00
2014-06-27 11:07:13 -04:00
GCompositionLighting . ProcessBeforeBasePass ( RHICmdList , Views [ ViewIndex ] ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-10-27 20:23:51 -04:00
// Clear the G Buffer render targets
bool bIsGBufferCurrent = false ;
if ( bRequiresRHIClear )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_SetAndClearViewGBuffer ) ;
2014-10-27 20:23:51 -04:00
// set GBuffer to be current, and clear it
SetAndClearViewGBuffer ( RHICmdList , Views [ 0 ] , ! bDepthWasCleared ) ;
// depth was cleared now no matter what
bDepthWasCleared = true ;
bIsGBufferCurrent = true ;
}
2015-01-13 10:44:59 -05:00
if ( bIsWireframe & & FSceneRenderer : : ShouldCompositeEditorPrimitives ( Views [ 0 ] ) )
2014-03-14 14:13:41 -04:00
{
// In Editor we want wire frame view modes to be MSAA for better quality. Resolve will be done with EditorPrimitives
2014-06-27 11:07:13 -04:00
SetRenderTarget ( RHICmdList , GSceneRenderTargets . GetEditorPrimitivesColor ( ) , GSceneRenderTargets . GetEditorPrimitivesDepth ( ) ) ;
2015-03-31 14:02:45 -04:00
RHICmdList . Clear ( true , FLinearColor ( 0 , 0 , 0 , 0 ) , true , ( float ) ERHIZBuffer : : FarPlane , false , 0 , FIntRect ( ) ) ;
2014-03-14 14:13:41 -04:00
}
2014-10-27 20:23:51 -04:00
else if ( ! bIsGBufferCurrent )
2014-03-14 14:13:41 -04:00
{
2014-10-27 20:23:51 -04:00
// make sure the GBuffer is set, in case we didn't need to clear above
2014-10-23 16:31:43 -04:00
ERenderTargetLoadAction DepthLoadAction = bDepthWasCleared ? ERenderTargetLoadAction : : ELoad : ERenderTargetLoadAction : : EClear ;
2014-10-27 20:23:51 -04:00
GSceneRenderTargets . BeginRenderingGBuffer ( RHICmdList , ERenderTargetLoadAction : : ENoAction , DepthLoadAction ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:52:11 -04:00
GRenderTargetPool . AddPhaseEvent ( TEXT ( " BasePass " ) ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_BasePass ) ) ;
2014-06-27 11:07:13 -04:00
RenderBasePass ( RHICmdList ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_AfterBasePass ) ) ;
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
if ( ViewFamily . EngineShowFlags . VisualizeLightCulling )
{
// clear out emissive and baked lighting (not too efficient but simple and only needed for this debug view)
GSceneRenderTargets . BeginRenderingSceneColor ( RHICmdList ) ;
2015-03-31 14:02:45 -04:00
RHICmdList . Clear ( true , FLinearColor ( 0 , 0 , 0 , 0 ) , false , ( float ) ERHIZBuffer : : FarPlane , false , 0 , FIntRect ( ) ) ;
2015-03-04 08:31:40 -05:00
}
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
GSceneRenderTargets . DBufferA . SafeRelease ( ) ;
GSceneRenderTargets . DBufferB . SafeRelease ( ) ;
GSceneRenderTargets . DBufferC . SafeRelease ( ) ;
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
// only temporarily available after early z pass and until base pass
check ( ! GSceneRenderTargets . DBufferA ) ;
check ( ! GSceneRenderTargets . DBufferB ) ;
check ( ! GSceneRenderTargets . DBufferC ) ;
2014-03-14 14:13:41 -04:00
if ( bRequiresFarZQuadClear )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_ClearGBufferAtMaxZ ) ;
2014-03-14 14:13:41 -04:00
// Clears view by drawing quad at maximum Z
2014-06-27 11:07:13 -04:00
// TODO: if all the platforms have fast color clears, we can replace this with an RHICmdList.Clear.
2014-06-12 07:13:34 -04:00
ClearGBufferAtMaxZ ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
bRequiresFarZQuadClear = false ;
}
2015-03-04 08:31:40 -05:00
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_Resolve_After_Basepass ) ;
2015-01-27 16:14:50 -05:00
2015-03-04 08:31:40 -05:00
GSceneRenderTargets . ResolveSceneColor ( RHICmdList , FResolveRect ( 0 , 0 , ViewFamily . FamilySizeX , ViewFamily . FamilySizeY ) ) ;
GSceneRenderTargets . ResolveSceneDepthTexture ( RHICmdList ) ;
GSceneRenderTargets . ResolveSceneDepthToAuxiliaryTexture ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
2015-03-04 08:31:40 -05:00
GSceneRenderTargets . FinishRenderingGBuffer ( RHICmdList ) ;
RenderCustomDepthPass ( RHICmdList ) ;
}
2014-03-14 14:13:41 -04:00
// Notify the FX system that opaque primitives have been rendered and we now have a valid depth buffer.
if ( Scene - > FXSystem & & Views . IsValidIndex ( 0 ) )
{
Scene - > FXSystem - > PostRenderOpaque (
2014-06-27 11:07:13 -04:00
RHICmdList ,
2014-09-29 04:23:44 -04:00
Views . GetData ( ) ,
2014-03-14 14:13:41 -04:00
GSceneRenderTargets . GetSceneDepthTexture ( ) ,
GSceneRenderTargets . GetGBufferATexture ( )
) ;
}
2015-03-26 18:31:22 -04:00
bool bOcclusionAfterBasePass = bIsOcclusionTesting & & ! bOcclusionBeforeBasePass ;
bool bHZBAfterBasePass = true ;
RenderOcclusion ( RHICmdList , bOcclusionAfterBasePass , bHZBAfterBasePass ) ;
2014-10-07 07:21:22 -04:00
2015-02-19 16:09:15 -05:00
TRefCountPtr < IPooledRenderTarget > VelocityRT ;
if ( bUseVelocityGBuffer )
{
VelocityRT = GSceneRenderTargets . GetGBufferVelocityRT ( ) ;
}
else if ( bShouldRenderVelocities )
{
// Render the velocities of movable objects
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_Velocity ) ) ;
RenderVelocities ( RHICmdList , VelocityRT ) ;
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_AfterVelocity ) ) ;
}
2015-04-13 15:39:50 -04:00
// Pre-lighting composition lighting stage
// e.g. deferred decals
if ( FeatureLevel > = ERHIFeatureLevel : : SM4
& & bGBuffer )
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_AfterBasePass ) ;
GRenderTargetPool . AddPhaseEvent ( TEXT ( " AfterBasePass " ) ) ;
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
GCompositionLighting . ProcessAfterBasePass ( RHICmdList , Views [ ViewIndex ] ) ;
}
}
2014-03-14 14:13:41 -04:00
// Render lighting.
if ( ViewFamily . EngineShowFlags . Lighting
2014-05-08 09:05:50 -04:00
& & FeatureLevel > = ERHIFeatureLevel : : SM4
2014-03-14 14:13:41 -04:00
& & ViewFamily . EngineShowFlags . DeferredLighting
2014-07-29 17:32:52 -04:00
& & bGBuffer
2014-03-14 14:13:41 -04:00
)
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_Lighting ) ;
2014-04-23 19:52:11 -04:00
GRenderTargetPool . AddPhaseEvent ( TEXT ( " Lighting " ) ) ;
2014-03-14 14:13:41 -04:00
// Clear the translucent lighting volumes before we accumulate
2014-06-05 16:38:54 -04:00
ClearTranslucentVolumeLighting ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_Lighting ) ) ;
2014-06-05 16:38:54 -04:00
RenderLights ( RHICmdList ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_AfterLighting ) ) ;
2014-03-14 14:13:41 -04:00
2014-06-30 16:04:34 -04:00
GRenderTargetPool . AddPhaseEvent ( TEXT ( " AfterRenderLights " ) ) ;
2014-06-05 16:38:54 -04:00
InjectAmbientCubemapTranslucentVolumeLighting ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
// Filter the translucency lighting volume now that it is complete
2014-06-12 07:13:34 -04:00
FilterTranslucentVolumeLighting ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
// Clear LPVs for all views
2014-08-19 10:41:34 -04:00
if ( FeatureLevel > = ERHIFeatureLevel : : SM5 )
2014-03-14 14:13:41 -04:00
{
2014-06-27 11:07:13 -04:00
PropagateLPVs ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
2014-08-28 13:54:31 -04:00
TRefCountPtr < IPooledRenderTarget > DynamicBentNormalAO ;
2015-02-19 16:09:15 -05:00
RenderDynamicSkyLighting ( RHICmdList , VelocityRT , DynamicBentNormalAO ) ;
2014-08-28 13:54:31 -04:00
2015-01-27 16:14:50 -05:00
//SSR and SSS need the SceneColor finalized as an SRV.
GSceneRenderTargets . FinishRenderingSceneColor ( RHICmdList , true ) ;
2014-03-14 14:13:41 -04:00
// Render reflections that only operate on opaque pixels
2014-08-28 13:54:31 -04:00
RenderDeferredReflections ( RHICmdList , DynamicBentNormalAO ) ;
2014-03-14 14:13:41 -04:00
// Post-lighting composition lighting stage
// e.g. ambient cubemaps, ambient occlusion, LPV indirect
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; + + ViewIndex )
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2014-06-27 11:07:13 -04:00
GCompositionLighting . ProcessLighting ( RHICmdList , Views [ ViewIndex ] ) ;
2014-03-14 14:13:41 -04:00
}
}
if ( ViewFamily . EngineShowFlags . StationaryLightOverlap & &
2014-05-08 09:05:50 -04:00
FeatureLevel > = ERHIFeatureLevel : : SM4 )
2014-03-14 14:13:41 -04:00
{
2014-06-12 07:13:34 -04:00
RenderStationaryLightOverlap ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
FLightShaftsOutput LightShaftOutput ;
// Draw Lightshafts
if ( ViewFamily . EngineShowFlags . LightShafts )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderLightShaftOcclusion ) ;
2014-06-12 07:13:34 -04:00
LightShaftOutput = RenderLightShaftOcclusion ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
// Draw atmosphere
if ( ShouldRenderAtmosphere ( ViewFamily ) )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderAtmosphere ) ;
2014-03-14 14:13:41 -04:00
if ( Scene - > AtmosphericFog )
{
// Update RenderFlag based on LightShaftTexture is valid or not
if ( LightShaftOutput . bRendered )
{
Scene - > AtmosphericFog - > RenderFlag & = EAtmosphereRenderFlag : : E_LightShaftMask ;
}
else
{
Scene - > AtmosphericFog - > RenderFlag | = EAtmosphereRenderFlag : : E_DisableLightShaft ;
}
# if WITH_EDITOR
if ( Scene - > bIsEditorScene )
{
// Precompute Atmospheric Textures
2014-09-29 04:23:44 -04:00
Scene - > AtmosphericFog - > PrecomputeTextures ( RHICmdList , Views . GetData ( ) , & ViewFamily ) ;
2014-03-14 14:13:41 -04:00
}
# endif
2014-06-27 11:07:13 -04:00
RenderAtmosphere ( RHICmdList , LightShaftOutput ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-04-23 19:52:11 -04:00
GRenderTargetPool . AddPhaseEvent ( TEXT ( " Fog " ) ) ;
2014-03-14 14:13:41 -04:00
// Draw fog.
if ( ShouldRenderFog ( ViewFamily ) )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderFog ) ;
2014-06-12 07:13:34 -04:00
RenderFog ( RHICmdList , LightShaftOutput ) ;
2014-03-14 14:13:41 -04:00
}
// No longer needed, release
LightShaftOutput . LightShaftOcclusion = NULL ;
2014-04-23 19:52:11 -04:00
GRenderTargetPool . AddPhaseEvent ( TEXT ( " Translucency " ) ) ;
2014-03-14 14:13:41 -04:00
// Draw translucency.
if ( ViewFamily . EngineShowFlags . Translucency )
{
SCOPE_CYCLE_COUNTER ( STAT_TranslucencyDrawTime ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_Translucency ) ) ;
2014-06-27 11:07:13 -04:00
RenderTranslucency ( RHICmdList ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_AfterTranslucency ) ) ;
2014-06-24 20:14:10 -04:00
if ( ViewFamily . EngineShowFlags . Refraction )
2014-03-14 14:13:41 -04:00
{
2014-06-24 20:14:10 -04:00
// To apply refraction effect by distorting the scene color.
// After non separate translucency as that is considered at scene depth anyway
// It allows skybox translucency (set to non separate translucency) to be refracted.
2014-06-05 16:38:54 -04:00
RenderDistortion ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
}
if ( ViewFamily . EngineShowFlags . LightShafts )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderLightShaftBloom ) ;
2014-06-12 07:13:34 -04:00
RenderLightShaftBloom ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
2014-12-16 20:00:22 -05:00
if ( ViewFamily . EngineShowFlags . VisualizeDistanceFieldAO | | ViewFamily . EngineShowFlags . VisualizeDistanceFieldGI )
2014-06-03 15:53:13 -04:00
{
2014-12-16 20:00:22 -05:00
// Use the skylight's max distance if there is one, to be consistent with DFAO shadowing on the skylight
const float OcclusionMaxDistance = Scene - > SkyLight & & ! Scene - > SkyLight - > bWantsStaticShadowing ? Scene - > SkyLight - > OcclusionMaxDistance : 600 ;
2014-08-28 13:54:31 -04:00
TRefCountPtr < IPooledRenderTarget > DummyOutput ;
2015-02-19 16:09:15 -05:00
RenderDistanceFieldAOSurfaceCache ( RHICmdList , FDistanceFieldAOParameters ( OcclusionMaxDistance ) , VelocityRT , DummyOutput , DummyOutput , ViewFamily . EngineShowFlags . VisualizeDistanceFieldAO , ViewFamily . EngineShowFlags . VisualizeDistanceFieldGI ) ;
2014-08-28 13:54:31 -04:00
}
if ( ViewFamily . EngineShowFlags . VisualizeMeshDistanceFields )
{
2014-12-16 20:00:22 -05:00
RenderMeshDistanceFieldVisualization ( RHICmdList , FDistanceFieldAOParameters ( 600 ) ) ;
2014-06-03 15:53:13 -04:00
}
2014-03-14 14:13:41 -04:00
// Resolve the scene color for post processing.
2014-06-27 11:07:13 -04:00
GSceneRenderTargets . ResolveSceneColor ( RHICmdList , FResolveRect ( 0 , 0 , ViewFamily . FamilySizeX , ViewFamily . FamilySizeY ) ) ;
2014-03-14 14:13:41 -04:00
// Finish rendering for each view.
if ( ViewFamily . bResolveScene )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , PostProcessing ) ;
2014-03-14 14:13:41 -04:00
SCOPE_CYCLE_COUNTER ( STAT_FinishRenderViewTargetTime ) ;
2014-09-02 16:37:25 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2014-09-02 16:37:25 -04:00
GPostProcessing . Process ( RHICmdList , Views [ ViewIndex ] , VelocityRT ) ;
// we rendered to it during the frame, seems we haven't made use of it, because it should be released
FSceneViewState * ViewState = ( FSceneViewState * ) Views [ ViewIndex ] . State ;
check ( ! ViewState | | ! ViewState - > SeparateTranslucencyRT ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-05-19 09:42:34 -04:00
else
{
// Release the original reference on the scene render targets
GSceneRenderTargets . AdjustGBufferRefCount ( - 1 ) ;
}
2014-03-14 14:13:41 -04:00
2014-12-18 17:17:28 -05:00
//grab the new transform out of the proxies for next frame
2015-01-20 20:14:07 -05:00
if ( VelocityRT )
2014-12-18 17:17:28 -05:00
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_UpdateMotionBlurCache ) ;
2014-12-18 17:17:28 -05:00
Scene - > MotionBlurInfoData . UpdateMotionBlurCache ( Scene ) ;
}
2014-09-02 16:37:25 -04:00
VelocityRT . SafeRelease ( ) ;
2015-03-04 08:31:40 -05:00
{
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderFinish ) ;
RenderFinish ( RHICmdList ) ;
RHICmdList . SetCurrentStat ( GET_STATID ( STAT_CLM_AfterFrame ) ) ;
}
2014-03-14 14:13:41 -04:00
}
2014-07-24 08:54:31 -04:00
bool FDeferredShadingSceneRenderer : : RenderPrePassViewDynamic ( FRHICommandList & RHICmdList , const FViewInfo & View )
{
2014-11-25 17:56:43 -05:00
FDepthDrawingPolicyFactory : : ContextType Context ( EarlyZPassMode ) ;
2014-08-12 18:24:52 -04:00
2014-11-25 17:56:43 -05:00
for ( int32 MeshBatchIndex = 0 ; MeshBatchIndex < View . DynamicMeshElements . Num ( ) ; MeshBatchIndex + + )
2014-07-24 08:54:31 -04:00
{
2014-11-25 17:56:43 -05:00
const FMeshBatchAndRelevance & MeshBatchAndRelevance = View . DynamicMeshElements [ MeshBatchIndex ] ;
2014-08-12 18:24:52 -04:00
2014-11-25 17:56:43 -05:00
if ( MeshBatchAndRelevance . bHasOpaqueOrMaskedMaterial & & MeshBatchAndRelevance . bRenderInMainPass )
2014-07-24 08:54:31 -04:00
{
2014-11-25 17:56:43 -05:00
const FMeshBatch & MeshBatch = * MeshBatchAndRelevance . Mesh ;
const FPrimitiveSceneProxy * PrimitiveSceneProxy = MeshBatchAndRelevance . PrimitiveSceneProxy ;
bool bShouldUseAsOccluder = true ;
2014-07-24 08:54:31 -04:00
2014-12-17 01:30:20 -05:00
if ( EarlyZPassMode < DDM_AllOccluders )
2014-07-24 08:54:31 -04:00
{
2014-11-25 17:56:43 -05:00
extern float GMinScreenRadiusForDepthPrepass ;
//@todo - move these proxy properties into FMeshBatchAndRelevance so we don't have to dereference the proxy in order to reject a mesh
const float LODFactorDistanceSquared = ( PrimitiveSceneProxy - > GetBounds ( ) . Origin - View . ViewMatrices . ViewOrigin ) . SizeSquared ( ) * FMath : : Square ( View . LODDistanceFactor ) ;
2014-07-24 08:54:31 -04:00
2014-11-25 17:56:43 -05:00
// Only render primitives marked as occluders
bShouldUseAsOccluder = PrimitiveSceneProxy - > ShouldUseAsOccluder ( )
// Only render static objects unless movable are requested
& & ( ! PrimitiveSceneProxy - > IsMovable ( ) | | GEarlyZPassMovable )
& & ( FMath : : Square ( PrimitiveSceneProxy - > GetBounds ( ) . SphereRadius ) > GMinScreenRadiusForDepthPrepass * GMinScreenRadiusForDepthPrepass * LODFactorDistanceSquared ) ;
2014-07-24 08:54:31 -04:00
}
2014-11-25 17:56:43 -05:00
if ( bShouldUseAsOccluder )
2014-08-12 18:24:52 -04:00
{
2014-11-25 17:56:43 -05:00
FDepthDrawingPolicyFactory : : DrawDynamicMesh ( RHICmdList , View , Context , MeshBatch , false , true , PrimitiveSceneProxy , MeshBatch . BatchHitProxyId ) ;
2014-08-12 18:24:52 -04:00
}
}
}
return true ;
2014-07-24 08:54:31 -04:00
}
2014-08-12 08:46:25 -04:00
static void SetupPrePassView ( FRHICommandList & RHICmdList , const FIntRect & ViewRect )
2014-07-24 08:54:31 -04:00
{
// Disable color writes, enable depth tests and writes.
RHICmdList . SetBlendState ( TStaticBlendState < CW_NONE > : : GetRHI ( ) ) ;
2015-04-01 10:53:07 -04:00
RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < true , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
2014-08-12 08:46:25 -04:00
RHICmdList . SetViewport ( ViewRect . Min . X , ViewRect . Min . Y , 0 , ViewRect . Max . X , ViewRect . Max . Y , 1 ) ;
2014-10-02 11:20:07 -04:00
RHICmdList . SetRasterizerState ( TStaticRasterizerState < FM_Solid , CM_None > : : GetRHI ( ) ) ;
2015-04-23 13:22:07 -04:00
RHICmdList . SetScissorRect ( false , 0 , 0 , 0 , 0 ) ;
2014-07-24 09:29:37 -04:00
}
bool FDeferredShadingSceneRenderer : : RenderPrePassView ( FRHICommandList & RHICmdList , const FViewInfo & View )
{
bool bDirty = false ;
2014-08-12 08:46:25 -04:00
SetupPrePassView ( RHICmdList , View . ViewRect ) ;
2014-07-24 08:54:31 -04:00
// Draw the static occluder primitives using a depth drawing policy.
{
// Draw opaque occluders which support a separate position-only
// vertex buffer to minimize vertex fetch bandwidth, which is
// often the bottleneck during the depth only pass.
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , PosOnlyOpaque ) ;
2014-07-24 08:54:31 -04:00
bDirty | = Scene - > PositionOnlyDepthDrawList . DrawVisible ( RHICmdList , View , View . StaticMeshOccluderMap , View . StaticMeshBatchVisibility ) ;
}
{
// Draw opaque occluders, using double speed z where supported.
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , Opaque ) ;
2014-07-24 08:54:31 -04:00
bDirty | = Scene - > DepthDrawList . DrawVisible ( RHICmdList , View , View . StaticMeshOccluderMap , View . StaticMeshBatchVisibility ) ;
}
if ( EarlyZPassMode > = DDM_AllOccluders )
{
// Draw opaque occluders with masked materials
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , Opaque ) ;
2014-07-24 08:54:31 -04:00
bDirty | = Scene - > MaskedDepthDrawList . DrawVisible ( RHICmdList , View , View . StaticMeshOccluderMap , View . StaticMeshBatchVisibility ) ;
}
bDirty | = RenderPrePassViewDynamic ( RHICmdList , View ) ;
return bDirty ;
}
class FRenderPrepassDynamicDataThreadTask
{
FDeferredShadingSceneRenderer & ThisRenderer ;
FRHICommandList & RHICmdList ;
const FViewInfo & View ;
bool & OutDirty ;
public :
FRenderPrepassDynamicDataThreadTask (
2014-10-06 10:05:28 -04:00
FDeferredShadingSceneRenderer & InThisRenderer ,
FRHICommandList & InRHICmdList ,
const FViewInfo & InView ,
bool & InOutDirty
2014-07-24 08:54:31 -04:00
)
2014-10-06 10:05:28 -04:00
: ThisRenderer ( InThisRenderer )
, RHICmdList ( InRHICmdList )
, View ( InView )
, OutDirty ( InOutDirty )
2014-07-24 08:54:31 -04:00
{
}
FORCEINLINE TStatId GetStatId ( ) const
{
RETURN_QUICK_DECLARE_CYCLE_STAT ( FRenderPrepassDynamicDataThreadTask , STATGROUP_TaskGraphTasks ) ;
}
ENamedThreads : : Type GetDesiredThread ( )
{
return ENamedThreads : : AnyThread ;
}
static ESubsequentsMode : : Type GetSubsequentsMode ( ) { return ESubsequentsMode : : TrackSubsequents ; }
void DoTask ( ENamedThreads : : Type CurrentThread , const FGraphEventRef & MyCompletionGraphEvent )
{
if ( ThisRenderer . RenderPrePassViewDynamic ( RHICmdList , View ) )
{
OutDirty = true ;
}
2014-09-03 10:52:00 -04:00
RHICmdList . HandleRTThreadTaskCompletion ( MyCompletionGraphEvent ) ;
2014-07-24 08:54:31 -04:00
}
} ;
2014-10-02 11:20:07 -04:00
class FPrePassParallelCommandListSet : public FParallelCommandListSet
2014-07-24 08:54:31 -04:00
{
2014-10-02 11:20:07 -04:00
public :
FPrePassParallelCommandListSet ( const FViewInfo & InView , FRHICommandList & InParentCmdList , bool * InOutDirty , bool bInParallelExecute )
: FParallelCommandListSet ( InView , InParentCmdList , InOutDirty , bInParallelExecute )
{
SetStateOnCommandList ( ParentCmdList ) ;
}
2015-01-27 16:14:50 -05:00
virtual ~ FPrePassParallelCommandListSet ( )
{
Dispatch ( ) ;
}
2014-10-02 11:20:07 -04:00
virtual void SetStateOnCommandList ( FRHICommandList & CmdList ) override
{
2015-01-27 16:14:50 -05:00
GSceneRenderTargets . BeginRenderingPrePass ( CmdList , false ) ;
2014-10-02 11:20:07 -04:00
SetupPrePassView ( CmdList , View . ViewRect ) ;
}
} ;
static TAutoConsoleVariable < int32 > CVarRHICmdPrePassDeferredContexts (
TEXT ( " r.RHICmdPrePassDeferredContexts " ) ,
1 ,
2014-11-20 12:36:32 -05:00
TEXT ( " True to use deferred contexts to parallelize prepass command list execution. " ) ) ;
2014-10-02 11:20:07 -04:00
void FDeferredShadingSceneRenderer : : RenderPrePassViewParallel ( const FViewInfo & View , FRHICommandList & ParentCmdList , bool & OutDirty )
{
FPrePassParallelCommandListSet ParallelCommandListSet ( View , ParentCmdList , & OutDirty , CVarRHICmdPrePassDeferredContexts . GetValueOnRenderThread ( ) > 0 ) ;
2014-07-24 08:54:31 -04:00
// Draw the static occluder primitives using a depth drawing policy.
{
// Draw opaque occluders which support a separate position-only
// vertex buffer to minimize vertex fetch bandwidth, which is
// often the bottleneck during the depth only pass.
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, PosOnlyOpaque);
2014-10-02 11:20:07 -04:00
Scene - > PositionOnlyDepthDrawList . DrawVisibleParallel ( View . StaticMeshOccluderMap , View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-07-24 08:54:31 -04:00
}
{
// Draw opaque occluders, using double speed z where supported.
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, Opaque);
2014-10-02 11:20:07 -04:00
Scene - > DepthDrawList . DrawVisibleParallel ( View . StaticMeshOccluderMap , View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-07-24 08:54:31 -04:00
}
if ( EarlyZPassMode > = DDM_AllOccluders )
{
// Draw opaque occluders with masked materials
2014-10-02 11:20:07 -04:00
// we can't insert this event on the parent command list; need to pass it along to the ParallelCommandListSet
2014-10-20 10:43:43 -04:00
//SCOPED_DRAW_EVENT(ParentCmdList, Opaque);
2014-10-02 11:20:07 -04:00
Scene - > MaskedDepthDrawList . DrawVisibleParallel ( View . StaticMeshOccluderMap , View . StaticMeshBatchVisibility , ParallelCommandListSet ) ;
2014-07-24 08:54:31 -04:00
}
{
2014-10-02 11:20:07 -04:00
FRHICommandList * CmdList = ParallelCommandListSet . NewParallelCommandList ( ) ;
2014-07-24 08:54:31 -04:00
FGraphEventRef AnyThreadCompletionEvent = TGraphTask < FRenderPrepassDynamicDataThreadTask > : : CreateTask ( nullptr , ENamedThreads : : RenderThread )
2014-10-06 10:05:28 -04:00
. ConstructAndDispatchWhenReady ( * this , * CmdList , View , OutDirty ) ;
2014-07-24 08:54:31 -04:00
2014-10-02 11:20:07 -04:00
ParallelCommandListSet . AddParallelCommandList ( CmdList , AnyThreadCompletionEvent ) ;
2014-07-24 08:54:31 -04:00
}
}
2015-01-27 16:14:50 -05:00
static TAutoConsoleVariable < int32 > CVarParallelPrePass (
TEXT ( " r.ParallelPrePass " ) ,
1 ,
TEXT ( " Toggles parallel zprepass rendering. Parallel rendering must be enabled for this to have an effect. " ) ,
ECVF_RenderThreadSafe
) ;
2014-03-14 14:13:41 -04:00
/** Renders the scene's prepass and occlusion queries */
2014-06-27 11:07:13 -04:00
bool FDeferredShadingSceneRenderer : : RenderPrePass ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , PrePass ) ;
2014-03-14 14:13:41 -04:00
SCOPE_CYCLE_COUNTER ( STAT_DepthDrawTime ) ;
bool bDirty = false ;
2015-01-27 16:14:50 -05:00
GSceneRenderTargets . BeginRenderingPrePass ( RHICmdList , true ) ;
2014-03-14 14:13:41 -04:00
// Draw a depth pass to avoid overdraw in the other passes.
if ( EarlyZPassMode ! = DDM_None )
{
2015-01-27 16:14:50 -05:00
if ( GRHICommandList . UseParallelAlgorithms ( ) & & CVarParallelPrePass . GetValueOnRenderThread ( ) )
2014-03-14 14:13:41 -04:00
{
2014-09-03 10:52:00 -04:00
FScopedCommandListWaitForTasks Flusher ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
2014-07-24 08:54:31 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
2014-03-14 14:13:41 -04:00
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2014-07-24 08:54:31 -04:00
const FViewInfo & View = Views [ ViewIndex ] ;
2014-10-02 11:20:07 -04:00
RenderPrePassViewParallel ( View , RHICmdList , bDirty ) ;
2014-03-14 14:13:41 -04:00
}
2014-07-24 08:54:31 -04:00
}
else
{
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
2014-03-14 14:13:41 -04:00
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2014-07-24 08:54:31 -04:00
const FViewInfo & View = Views [ ViewIndex ] ;
bDirty | = RenderPrePassView ( RHICmdList , View ) ;
2014-03-14 14:13:41 -04:00
}
}
}
2014-06-27 11:07:13 -04:00
GSceneRenderTargets . FinishRenderingPrePass ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
return bDirty ;
}
2015-01-27 16:14:50 -05:00
static TAutoConsoleVariable < int32 > CVarParallelBasePass (
TEXT ( " r.ParallelBasePass " ) ,
1 ,
TEXT ( " Toggles parallel base pass rendering. Parallel rendering must be enabled for this to have an effect. " ) ,
ECVF_RenderThreadSafe
) ;
2014-03-14 14:13:41 -04:00
/**
* Renders the scene ' s base pass
* @ return true if anything was rendered
*/
2014-06-27 11:07:13 -04:00
bool FDeferredShadingSceneRenderer : : RenderBasePass ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
bool bDirty = false ;
2015-01-20 20:14:07 -05:00
if ( FVelocityRendering : : OutputsToGBuffer ( ) )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderBasePass_GPrevPerBoneMotionBlur_LockData ) ;
2015-04-21 13:44:06 -04:00
GPrevPerBoneMotionBlur . StartAppend ( ViewFamily . bWorldIsPaused ) ;
2015-01-20 20:14:07 -05:00
}
2014-03-14 14:13:41 -04:00
if ( ViewFamily . EngineShowFlags . LightMapDensity & & AllowDebugViewmodes ( ) )
{
// Override the base pass with the lightmap density pass if the viewmode is enabled.
2014-06-27 11:07:13 -04:00
bDirty = RenderLightMapDensities ( RHICmdList ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , BasePass ) ;
2014-03-14 14:13:41 -04:00
SCOPE_CYCLE_COUNTER ( STAT_BasePassDrawTime ) ;
2015-01-27 16:14:50 -05:00
if ( GRHICommandList . UseParallelAlgorithms ( ) & & CVarParallelBasePass . GetValueOnRenderThread ( ) )
2014-03-14 14:13:41 -04:00
{
2014-09-03 10:52:00 -04:00
FScopedCommandListWaitForTasks Flusher ( RHICmdList ) ;
2014-07-24 09:29:37 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
2014-03-14 14:13:41 -04:00
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2014-07-24 09:29:37 -04:00
FViewInfo & View = Views [ ViewIndex ] ;
2014-10-02 11:20:07 -04:00
RenderBasePassViewParallel ( View , RHICmdList , bDirty ) ;
2014-07-24 09:29:37 -04:00
}
2014-03-14 14:13:41 -04:00
}
2014-07-24 09:29:37 -04:00
else
{
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
2014-10-20 10:43:43 -04:00
SCOPED_CONDITIONAL_DRAW_EVENTF ( RHICmdList , EventView , Views . Num ( ) > 1 , TEXT ( " View%d " ) , ViewIndex ) ;
2014-07-24 09:29:37 -04:00
FViewInfo & View = Views [ ViewIndex ] ;
bDirty | = RenderBasePassView ( RHICmdList , View ) ;
}
}
2014-03-14 14:13:41 -04:00
}
2015-01-20 20:14:07 -05:00
if ( FVelocityRendering : : OutputsToGBuffer ( ) )
{
2015-03-04 08:31:40 -05:00
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FDeferredShadingSceneRenderer_RenderBasePass_GPrevPerBoneMotionBlur_UnlockData ) ;
2015-04-17 17:13:30 -04:00
GPrevPerBoneMotionBlur . EndAppend ( ) ;
2015-01-20 20:14:07 -05:00
}
2014-03-14 14:13:41 -04:00
return bDirty ;
}
2014-06-27 11:07:13 -04:00
void FDeferredShadingSceneRenderer : : ClearLPVs ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
// clear light propagation volumes
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & View = Views [ ViewIndex ] ;
FSceneViewState * ViewState = ( FSceneViewState * ) Views [ ViewIndex ] . State ;
if ( ViewState )
{
FLightPropagationVolume * LightPropagationVolume = ViewState - > GetLightPropagationVolume ( ) ;
if ( LightPropagationVolume )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , ClearLPVs ) ;
2014-03-14 14:13:41 -04:00
SCOPE_CYCLE_COUNTER ( STAT_UpdateLPVs ) ;
2014-07-09 11:02:23 -04:00
LightPropagationVolume - > InitSettings ( RHICmdList , Views [ ViewIndex ] ) ;
2014-08-28 06:22:54 -04:00
LightPropagationVolume - > Clear ( RHICmdList , View ) ;
2014-03-14 14:13:41 -04:00
}
}
}
}
2014-06-27 11:07:13 -04:00
void FDeferredShadingSceneRenderer : : PropagateLPVs ( FRHICommandListImmediate & RHICmdList )
2014-03-14 14:13:41 -04:00
{
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & View = Views [ ViewIndex ] ;
FSceneViewState * ViewState = ( FSceneViewState * ) Views [ ViewIndex ] . State ;
if ( ViewState )
{
FLightPropagationVolume * LightPropagationVolume = ViewState - > GetLightPropagationVolume ( ) ;
if ( LightPropagationVolume )
{
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , UpdateLPVs ) ;
2014-03-14 14:13:41 -04:00
SCOPE_CYCLE_COUNTER ( STAT_UpdateLPVs ) ;
2014-06-27 11:07:13 -04:00
2014-08-28 06:22:54 -04:00
LightPropagationVolume - > Propagate ( RHICmdList , View ) ;
2014-03-14 14:13:41 -04:00
}
}
}
}
/** A simple pixel shader used on PC to read scene depth from scene color alpha and write it to a downsized depth buffer. */
class FDownsampleSceneDepthPS : public FGlobalShader
{
DECLARE_SHADER_TYPE ( FDownsampleSceneDepthPS , Global ) ;
public :
static bool ShouldCache ( EShaderPlatform Platform )
{
2014-08-25 14:41:54 -04:00
return IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM4 ) ;
2014-03-14 14:13:41 -04:00
}
FDownsampleSceneDepthPS ( const ShaderMetaType : : CompiledShaderInitializerType & Initializer ) :
FGlobalShader ( Initializer )
{
SceneTextureParameters . Bind ( Initializer . ParameterMap ) ;
ProjectionScaleBias . Bind ( Initializer . ParameterMap , TEXT ( " ProjectionScaleBias " ) ) ;
SourceTexelOffsets01 . Bind ( Initializer . ParameterMap , TEXT ( " SourceTexelOffsets01 " ) ) ;
SourceTexelOffsets23 . Bind ( Initializer . ParameterMap , TEXT ( " SourceTexelOffsets23 " ) ) ;
}
FDownsampleSceneDepthPS ( ) { }
2014-06-10 07:29:49 -04:00
void SetParameters ( FRHICommandList & RHICmdList , const FSceneView & View )
2014-03-14 14:13:41 -04:00
{
2014-06-05 16:38:54 -04:00
FGlobalShader : : SetParameters ( RHICmdList , GetPixelShader ( ) , View ) ;
2014-03-14 14:13:41 -04:00
// Used to remap view space Z (which is stored in scene color alpha) into post projection z and w so we can write z/w into the downsized depth buffer
const FVector2D ProjectionScaleBiasValue ( View . ViewMatrices . ProjMatrix . M [ 2 ] [ 2 ] , View . ViewMatrices . ProjMatrix . M [ 3 ] [ 2 ] ) ;
2014-06-05 16:38:54 -04:00
SetShaderValue ( RHICmdList , GetPixelShader ( ) , ProjectionScaleBias , ProjectionScaleBiasValue ) ;
2014-03-14 14:13:41 -04:00
FIntPoint BufferSize = GSceneRenderTargets . GetBufferSizeXY ( ) ;
const uint32 DownsampledBufferSizeX = BufferSize . X / GSceneRenderTargets . GetSmallColorDepthDownsampleFactor ( ) ;
const uint32 DownsampledBufferSizeY = BufferSize . Y / GSceneRenderTargets . GetSmallColorDepthDownsampleFactor ( ) ;
// Offsets of the four full resolution pixels corresponding with a low resolution pixel
const FVector4 Offsets01 ( 0.0f , 0.0f , 1.0f / DownsampledBufferSizeX , 0.0f ) ;
2014-06-05 16:38:54 -04:00
SetShaderValue ( RHICmdList , GetPixelShader ( ) , SourceTexelOffsets01 , Offsets01 ) ;
2014-03-14 14:13:41 -04:00
const FVector4 Offsets23 ( 0.0f , 1.0f / DownsampledBufferSizeY , 1.0f / DownsampledBufferSizeX , 1.0f / DownsampledBufferSizeY ) ;
2014-06-05 16:38:54 -04:00
SetShaderValue ( RHICmdList , GetPixelShader ( ) , SourceTexelOffsets23 , Offsets23 ) ;
SceneTextureParameters . Set ( RHICmdList , GetPixelShader ( ) , View ) ;
2014-03-14 14:13:41 -04:00
}
2015-04-01 07:20:55 -04:00
virtual bool Serialize ( FArchive & Ar ) override
2014-03-14 14:13:41 -04:00
{
bool bShaderHasOutdatedParameters = FGlobalShader : : Serialize ( Ar ) ;
Ar < < ProjectionScaleBias ;
Ar < < SourceTexelOffsets01 ;
Ar < < SourceTexelOffsets23 ;
Ar < < SceneTextureParameters ;
return bShaderHasOutdatedParameters ;
}
FShaderParameter ProjectionScaleBias ;
FShaderParameter SourceTexelOffsets01 ;
FShaderParameter SourceTexelOffsets23 ;
FSceneTextureShaderParameters SceneTextureParameters ;
} ;
IMPLEMENT_SHADER_TYPE ( , FDownsampleSceneDepthPS , TEXT ( " DownsampleDepthPixelShader " ) , TEXT ( " Main " ) , SF_Pixel ) ;
FGlobalBoundShaderState DownsampleDepthBoundShaderState ;
/** Updates the downsized depth buffer with the current full resolution depth buffer. */
2014-07-08 10:43:52 -04:00
void FDeferredShadingSceneRenderer : : UpdateDownsampledDepthSurface ( FRHICommandList & RHICmdList )
2014-03-14 14:13:41 -04:00
{
2014-10-07 08:46:39 -04:00
if ( GSceneRenderTargets . UseDownsizedOcclusionQueries ( ) & & ( FeatureLevel > = ERHIFeatureLevel : : SM4 ) )
2014-03-14 14:13:41 -04:00
{
2014-06-12 07:13:34 -04:00
SetRenderTarget ( RHICmdList , NULL , GSceneRenderTargets . GetSmallDepthSurface ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-10-20 10:43:43 -04:00
SCOPED_DRAW_EVENT ( RHICmdList , DownsampleDepth ) ;
2014-03-14 14:13:41 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
const FViewInfo & View = Views [ ViewIndex ] ;
// Set shaders and texture
2014-08-28 06:22:54 -04:00
TShaderMapRef < FScreenVS > ScreenVertexShader ( View . ShaderMap ) ;
TShaderMapRef < FDownsampleSceneDepthPS > PixelShader ( View . ShaderMap ) ;
2014-03-14 14:13:41 -04:00
extern TGlobalResource < FFilterVertexDeclaration > GFilterVertexDeclaration ;
2014-08-19 10:41:34 -04:00
SetGlobalBoundShaderState ( RHICmdList , FeatureLevel , DownsampleDepthBoundShaderState , GFilterVertexDeclaration . VertexDeclarationRHI , * ScreenVertexShader , * PixelShader ) ;
2014-03-14 14:13:41 -04:00
2014-06-12 07:13:34 -04:00
RHICmdList . SetBlendState ( TStaticBlendState < CW_NONE > : : GetRHI ( ) ) ;
RHICmdList . SetRasterizerState ( TStaticRasterizerState < FM_Solid , CM_None > : : GetRHI ( ) ) ;
RHICmdList . SetDepthStencilState ( TStaticDepthStencilState < true , CF_Always > : : GetRHI ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-06-05 16:38:54 -04:00
PixelShader - > SetParameters ( RHICmdList , View ) ;
2014-03-14 14:13:41 -04:00
2014-05-06 06:26:25 -04:00
const uint32 DownsampledX = FMath : : TruncToInt ( View . ViewRect . Min . X / GSceneRenderTargets . GetSmallColorDepthDownsampleFactor ( ) ) ;
const uint32 DownsampledY = FMath : : TruncToInt ( View . ViewRect . Min . Y / GSceneRenderTargets . GetSmallColorDepthDownsampleFactor ( ) ) ;
const uint32 DownsampledSizeX = FMath : : TruncToInt ( View . ViewRect . Width ( ) / GSceneRenderTargets . GetSmallColorDepthDownsampleFactor ( ) ) ;
const uint32 DownsampledSizeY = FMath : : TruncToInt ( View . ViewRect . Height ( ) / GSceneRenderTargets . GetSmallColorDepthDownsampleFactor ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-06-12 07:13:34 -04:00
RHICmdList . SetViewport ( DownsampledX , DownsampledY , 0.0f , DownsampledX + DownsampledSizeX , DownsampledY + DownsampledSizeY , 1.0f ) ;
2014-03-14 14:13:41 -04:00
DrawRectangle (
2014-06-12 07:13:34 -04:00
RHICmdList ,
2014-03-14 14:13:41 -04:00
0 , 0 ,
DownsampledSizeX , DownsampledSizeY ,
View . ViewRect . Min . X , View . ViewRect . Min . Y ,
View . ViewRect . Width ( ) , View . ViewRect . Height ( ) ,
FIntPoint ( DownsampledSizeX , DownsampledSizeY ) ,
GSceneRenderTargets . GetBufferSizeXY ( ) ,
2014-04-23 17:26:59 -04:00
* ScreenVertexShader ,
2014-03-14 14:13:41 -04:00
EDRF_UseTriangleOptimization ) ;
}
}
}