You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change3244756on 2017/01/03 by Marcus.Wassmer Copying //Tasks/UE4/Dev-Niagara@3244743 to Dev-Rendering (//UE4/Dev-Rendering) Change 3248667 on 2017/01/05 by Olaf.Piesche Resaving default asset because of engine verison issue; maybe unnecessary, but resaving niagara engine content to be sure #jira UE-40160 Change 3249324 on 2017/01/06 by Marcus.Wassmer Resave with an actual version to stop cook warning Change 3249611 on 2017/01/06 by Marcus.Wassmer Just remove warning-causing niagara data for now. Change 3308052 on 2017/02/16 by Rolando.Caloca DR - Check for Vulkan SDK, and only use it if it's newer or the same as the headers we distribute Change 3308109 on 2017/02/16 by Rolando.Caloca DR - Upgrade glslang to 1.0.39.1 Change 3308111 on 2017/02/16 by Rolando.Caloca DR - Update Vulkan distribution to 1.0.39.1 Change 3308153 on 2017/02/16 by Rolando.Caloca DR - Updated glslang libs Change 3308842 on 2017/02/17 by Rolando.Caloca DR - Fixed copy/paste Change 3310007 on 2017/02/17 by Chris.Bunner Back out CL 3221219 - causing MIC generation issues and superseded by CL 3273971. #jira UE-37792 Change 3310154 on 2017/02/17 by Chris.Bunner Assert when attempting to add a custom material attribute already in the base attributes list. Change 3310155 on 2017/02/17 by Chris.Bunner PR #3231: Validate material index before accessing (Contributed by projectgheist) #jira UE-41774, UE-41788 Change 3310162 on 2017/02/17 by Chris.Bunner PR #3252: Added MobileMaterialInterface to UsedMaterials (Contributed by projectgheist) #jira UE-41823, UE-41950 Change 3310176 on 2017/02/17 by Chris.Bunner Merging CL 3233886: AMD HDR support (requires r.AMDSupportsHDRDisplayOutput=1 in ini). Update to AGS 5.0.5. Partial code tidy up. Change 3310187 on 2017/02/17 by Chris.Bunner Preserve constant expressions rather than always casting after translating a material attribute. Losing the notion of constant means we can't correctly detect used properties and falsely enable e.g. PDO. Happened because of the incorrect component masks in BreakMaterialNodes which then had to be downcast to the correct type which is done as an inline fragment rather than swizzle expression. #jira UE-41594 Change 3310215 on 2017/02/17 by Chris.Bunner Prevent SpeedTree node compiling for skeletal meshes (not supported as uses more UV sets than available). More descriptive error for missing Cubemap UV input on TextureSample material node . #jira UE-33098 Change 3310838 on 2017/02/18 by Joe.Graf Moved some private functions to public for a licensee #CodeReview: matt.kuhlenschmidt #rb: n/a Change 3311876 on 2017/02/20 by Rolando.Caloca DR - Expose skin cache cvar r.SkinCache.AccumulationBufferSizeInKB #jira UE-42014 Change 3314139 on 2017/02/21 by Rolando.Caloca DR - Minor cleanup pass - Remove FVulkanPendingState - Renamed some classes for clarity - Hoist pending UAVs for flush out to pending compute state Change 3314642 on 2017/02/21 by Rolando.Caloca DR - Some more renaming Change3315431on 2017/02/21 by Ben.Salem Properly set default values for test time out and tick. We now will default to ticking once per second, and tracking the macro stats of GPU/Render/Game thread time. #tests Ran showdown demo several times Change 3316710 on 2017/02/22 by Rolando.Caloca DR - hlslcc - Fix refract intrinsic Change 3316718 on 2017/02/22 by Rolando.Caloca DR - hlslcc - Built libs to pick up change from 3316710 - refract fix Change 3316820 on 2017/02/22 by Benjamin.Hyder updating Tm-TrigNodes map Change 3317192 on 2017/02/22 by Benjamin.Hyder Updating QA-Decals map Change 3317528 on 2017/02/22 by Benjamin.Hyder Updating QA-Decals map Change 3317639 on 2017/02/22 by Benjamin.Hyder Updating Decal on Complex Mesh example in QA-Decals Change 3317764 on 2017/02/22 by Benjamin.Hyder Final updates to QA-Decals Change 3318319 on 2017/02/22 by Rolando.Caloca DR - minor reorg/rename Change 3318379 on 2017/02/22 by Rolando.Caloca DR - more cleanup Change 3321181 on 2017/02/24 by Rolando.Caloca DR - Fix GL bug Change 3321247 on 2017/02/24 by Rolando.Caloca DR - Fix misc bugs Change 3321898 on 2017/02/24 by Chris.Bunner Only issue clear TLV dispatch if required. #jira UERNDR-193 Change 3321904 on 2017/02/24 by Chris.Bunner Added comment for potential future optimization. Change 3322013 on 2017/02/24 by Uriel.Doyon Fixed separate translucency being affected by Gaussian DOF #jira UE-40489 Change 3322517 on 2017/02/24 by Uriel.Doyon Fixed issue with InvestigateTexture command removing budget limit. Fixed StreamingBounds show flag not working. It nows shows the streaming bound for the currently selected textures. #jira UE-40485 Change 3323470 on 2017/02/27 by Chad.Garyet Removing DDC job from dev-rendering Change 3323479 on 2017/02/27 by Chad.Garyet Removing RDU agent type Change 3323519 on 2017/02/27 by Chad.Garyet removing NCL/LHR/SEA agent types to clean up space Change 3323639 on 2017/02/27 by Benjamin.Hyder More updates to QA-Decals Change 3324207 on 2017/02/27 by Uriel.Doyon Fixed typo ScaleTexturesByGlobalMyBias -> ScaleTexturesByGlobalMipBias Removed bad merge in FStreamingTextureLevelContext::GetBuildDataIndexRef Change 3324396 on 2017/02/27 by Uriel.Doyon Fixed an issue with the Streaming Bounds show flag interferring with the static level data initialization #jira UE-40485 Change 3325227 on 2017/02/28 by Chris.Bunner Fix-up AMD AGS libs. Change 3325566 on 2017/02/28 by Uriel.Doyon Fixed possible out-of-bound access in GetUsedTexture() when passing ERHIFeatureLevel::Num Change 3326009 on 2017/02/28 by Uriel.Doyon Better fix for 3325566, as the previous fix would ignore the material instance overrides. Change 3327058 on 2017/03/01 by Benjamin.Hyder Preparing TM_Shadermodels map for automation Change 3328222 on 2017/03/01 by Chris.Bunner Prevent decals from drawing in separate translucency pass. Whilst user control and material relevance were already removed, if the flag was checked before being disabled (by swapping to decal domain) this was still being read in the render loop, now explicitly ignores decals. #jira UE-42449, UE-42446 Change 3329848 on 2017/03/02 by Uriel.Doyon Added some extra logs to help track UE-42168 Change 3329977 on 2017/03/02 by Rolando.Caloca DR - Fix bad clear value Change 3330008 on 2017/03/02 by Benjamin.Hyder More preparations for QA-Decals automation Change 3330754 on 2017/03/02 by Daniel.Wright Prominent comment explaining reflection env async compute usage and why it's not overlapped with anything Change 3331451 on 2017/03/03 by Marc.Olano Manually unroll simplex noise loop to avoid PSO bug on AMD/Metal Change 3331839 on 2017/03/03 by Rolando.Caloca DR - hlslcc - add missing file to project Change 3332247 on 2017/03/03 by Rolando.Caloca DR - Fix for integrated intel PR #3305 #jira UE-42393 Change 3332259 on 2017/03/03 by Rolando.Caloca DR - Fix bad index into pixel formats PR #3237 #jira UE-41855 Change 3332305 on 2017/03/03 by Rolando.Caloca DR - OpenGL SRV for index buffers PR #3271 #jira UE-32618 Change 3332313 on 2017/03/03 by Rolando.Caloca DR - Fix for integrated intel (properly) PR #3305 #jira UE-42393 Change 3332317 on 2017/03/03 by Rolando.Caloca DR - OpenGL SRV for index buffers (properly) PR #3271 #jira UE-32618 Change 3332368 on 2017/03/03 by Rolando.Caloca DR - Minor fixes so -sm4 and -sm5 can be used on windows with OpenGL/Vulkan Change 3333690 on 2017/03/06 by Daniel.Wright [Copy] Changing movable skylight properties no longer affects static draw lists Change 3333693 on 2017/03/06 by Daniel.Wright [Copy] Added 'r.AOListMeshDistanceFields' which dumps out mesh distance fields sorted by memory size, useful for directing content optimizations Change3333705on 2017/03/06 by Daniel.Wright [Copy] Mesh distance fields are now 8 bit fixed point by default, but can be changed back to 16 bit floating piont with a project setting. * 8 bit uses half memory but introduces error for thin surfaces or large meshes. Change 3333721 on 2017/03/06 by David.Hill DecalProxy: Copy float FadeScreenSize to FDeferredDecalProxy for use in the render thread. This avoids pointer chasing to the UDecalComponent (game thread component). Change 3333772 on 2017/03/06 by Daniel.Wright [Copy] Scene motion blur data is only updated for the main renderer frames. Fixes scene captures and planar reflections breaking object motion blur. Change 3333790 on 2017/03/06 by Daniel.Wright [Copy] Mesh distance field generation uses Embree, for a 2.5x speedup * Can switch back to old kDOP generation with 'r.DistanceFieldBuild.UseEmbree 0' for debugging Change 3333822 on 2017/03/06 by Daniel.Wright [Copy] Moved mesh distance field code into MeshDistanceFieldUtilities.cpp * Moved FMeshUtilities to its own header so the 8k line MeshUtilites.cpp file can be further split up Change 3333827 on 2017/03/06 by Daniel.Wright [Copy] Range compress 8bit distance fields - gets one extra bit of precision on average Change 3333828 on 2017/03/06 by Daniel.Wright [Copy] Raised High ShadowQuality to 2048 as 1024 for CSM is way too low Change 3333831 on 2017/03/06 by Daniel.Wright Non-editor compile fix Change 3333836 on 2017/03/06 by Daniel.Wright [Copy] Workaround for gobal distance field volume textures being bloated by 4x on PS4 due to the recommended tiling modes. They now use a 2d tiling mode which avoids the bloat, saving 96Mb. Change 3333843 on 2017/03/06 by Daniel.Wright [Copy] Added OcclusionExponent to skylight component * Useful for brightening up indoors without losing contact shadows as MinOcclusion does Change 3333845 on 2017/03/06 by Daniel.Wright [Copy] Capsule shadow BP functions Change 3333850 on 2017/03/06 by Daniel.Wright [Copy] Added OcclusionCombineMode to skylight component Change 3333854 on 2017/03/06 by Daniel.Wright [Copy] Gnm properly registers clears as GPU work so those events show up in profilegpu Change 3333857 on 2017/03/06 by Daniel.Wright [Copy] Clear light attenuation for local lights with a quad covering their screen extents * Clearing the entire light attenuation buffer costs .1ms on PS4. This optimization lowers the minimum cost of a shadow casting light from .15ms -> .03ms. * Shadowed lights in Fortnite with 25 lights 3.7ms -> 1.42ms on PS4 Change 3333860 on 2017/03/06 by Daniel.Wright [Copy] Flush deferred deletes when reallocating distance field atlas to reduce peak memory Change 3333861 on 2017/03/06 by Daniel.Wright [Copy] Disable all distance field features on Intel cards as HD 4000 hangs in the RHICreateTexture3D call to allocate the large atlas Change 3333869 on 2017/03/06 by Daniel.Wright [Copy] Volumetric Fog using a volume texture mapped to the camera frustum * Volumetric fog can be enabled on an Exponential Height Fog component with additional controls * Lights have a VolumetricScatteringIntensity * New cvars r.VolumetricFog, r.VolumetricFog.GridPixelSize, r.VolumetricFog.GridSizeZ, r.VolumetricFog.DepthDistributionScale * Lighting features supported: * Directional light with CSM and a light function * Point / spot lights without shadows / light functions / IES profiles * Skylight with occlusion from distance fields * Analytical height fog covers the view range past where the volumetric fog ends * Temporal reprojection is used on the volumetric fog scattering and extinction to achieve stability * Translucency integrates properly into volumetric fog * Height fog StartDistance is not supported by volumetric fog and should be set to 0. Change 3333894 on 2017/03/06 by Daniel.Wright [Copy] Initialize GDummyVolumetricFogGlobalDataUniformBuffer outside of parallel rendering Change 3333902 on 2017/03/06 by Daniel.Wright [Copy] Better handling of volumetric fog enabled with distance of 0 Change 3333903 on 2017/03/06 by Daniel.Wright [Copy] Fixed volumetric fog trying to render light functions for a point light Change 3333908 on 2017/03/06 by Daniel.Wright [Copy] Volumetric materials * Added new material domain Volume, which can output Scattering, Absorption and Emissive. All properties are in world space densities. * Particle systems using the Volume domain are voxelized based on their ParticlePosition and ParticleRadius * Volumetric fog integration is now energy conservative - scattering is integrated against transmission over the depth of each slice. * Added bOverrideLightColorsWithFogInscatteringColors to exponential height fog, which can be enabled to make Volumetric Fog match Height fog more closely Change 3334134 on 2017/03/06 by Daniel.Wright [Copy from Michael Trepka] Added Embree 2.14.0 and changed MeshUtilities to use it as this solves issues with Embree leaking TLS keys. UnrealLightmass is still using older Embree 2.7.0 until we can find time to properly test it with the new version. Also, invalidated distance field DDC to force it to rebuild with updated Embree. Change 3334420 on 2017/03/06 by Daniel.Wright Fixed RTDF shadows Change 3335467 on 2017/03/07 by Benjamin.Hyder Initial submission of QA-Decals map to EngineTest Change 3335556 on 2017/03/07 by Daniel.Wright Changed mesh distance field default format back to R16f Change 3338020 on 2017/03/08 by Daniel.Wright Disable volumetric fog in vertex shaders for feature levels which don't support it Change 3339394 on 2017/03/09 by Chris.Bunner Correctly handle material texture translation error edge case. #jira UE-42579, UE-42670 Change 3339992 on 2017/03/09 by Daniel.Wright Only compile volumetric fog shaders on supporting platforms Change 3341858 on 2017/03/10 by Arne.Schober Copying //UE4/Dev-Rendering-PSO to Dev-Rendering (//UE4/Dev-Rendering) #RB Rolando.Caloca, Marcus.Wassmer, Daniel.Wright, Nick.Penwarden, Mark.Satterthwaite Change 3342004 on 2017/03/10 by Arne.Schober Copying //UE4/Dev-Rendering-PSO to Dev-Rendering (//UE4/Dev-Rendering) Fix unity build #RB Marcus.Wassmer Change 3343307 on 2017/03/13 by Marcus.Wassmer Update showflags when we are guaranteed it will happen in all possible ways to spawn the scenecapture. (drag into editor, PIE, -game, etc) Change 3343732 on 2017/03/13 by Rolando.Caloca DR - Vulkan compute pipeline & refactor Change 3344846 on 2017/03/14 by Rolando.Caloca DR - Android compile fixes Change 3344883 on 2017/03/14 by Rolando.Caloca DR - Add missing stencil load/store to PSO initializer Change 3344985 on 2017/03/14 by Rolando.Caloca DR - Made load/store actions uint8 Change 3345141 on 2017/03/14 by Rolando.Caloca DR - vk - Rework render pass hash Change 3345304 on 2017/03/14 by Benjamin.Hyder Updating TM-Distancefields map to include TemplateFloor mesh Change 3345387 on 2017/03/14 by Rolando.Caloca DR - Add _RenderThread calls for Create*Shader so RHIs can choose not to stall when creating Change 3345388 on 2017/03/14 by Rolando.Caloca DR - Do not stall when creating shaders on Vulkan Change 3345722 on 2017/03/14 by Chris.Bunner PR #3357: MinimalAPI add to many material expressions (Contributed by DeanoC) #jira UE-42752 Change 3345723 on 2017/03/14 by Chris.Bunner Reduce log verbosity causing spamming during landscape editing. #jira UE-42714 Change 3345725 on 2017/03/14 by Chris.Bunner [Duplicate 3341860] Fixed material translation error with multiple connections from custom interpolator nodes. Change 3345726 on 2017/03/14 by Chris.Bunner Typo fixes. Change 3345732 on 2017/03/14 by Rolando.Caloca DR - Decouple vertex declaration off BSS Change 3345746 on 2017/03/14 by Chris.Bunner Added sign() intrinsic material graph node and delisted material function workaround. Change 3346042 on 2017/03/14 by Chris.Bunner Implement missing size query interface for FRenderTargetResources. #jira UE-41672 Change 3346387 on 2017/03/14 by Daniel.Wright [Copy] Added VolumetricScatteringIntensity to particle lights Change 3346389 on 2017/03/14 by Daniel.Wright [Copy] Clamp Volumetric material attributes to fp16 range to avoid INFs Disable volumetric fog when the fog show flag is disabled Change 3346392 on 2017/03/14 by Daniel.Wright [Copy] Fixed skylight being much too bright on volumetric fog Change 3346406 on 2017/03/14 by Daniel.Wright [Copy] CSM resolution is now controlled by r.Shadow.MaxCSMResolution. * Changed HighPC to use 1024 MaxShadowResolution (max for all non-CSM shadows), saves 60Mb in Fortnite Change 3346412 on 2017/03/14 by Daniel.Wright [Copy] TexCreate_ReduceMemoryWithTilingMode for translucency lighting 3d textures, saves 13Mb Change3346414on 2017/03/14 by Daniel.Wright [Copy] TexCreate_ReduceMemoryWithTilingMode for volumetric fog 3d textures, saves 13Mb Change 3346415 on 2017/03/14 by Daniel.Wright [Copy] Missing file from cl 3338451 Change 3346421 on 2017/03/14 by Daniel.Wright [Copy] Fixed NaNs in volumetric fog due to rendering when height fog is disabled * Volumetric fog converts NaNs to black now so they don't spread Change 3346422 on 2017/03/14 by Daniel.Wright [Copy] Fixed NaN in volumetric fog with low density values Change 3346423 on 2017/03/14 by Daniel.Wright [Copy] Changed default VolumetricFogScatteringDistribution to .2 Change 3346430 on 2017/03/14 by Daniel.Wright [Copy] New translucent material option to compute fog per pixel instead of the default per vertex Change 3346432 on 2017/03/14 by Daniel.Wright [Copy] Moved Volumetric Fog parameters to view uniform buffer for translucency pass Fixed lifetimes of temporary Volumetric Fog render targets Change 3346526 on 2017/03/14 by Daniel.Wright [Copy] Volumetric Fog supports point and spot light shadows * These lights are injected separately so that per-light resources can be bound (shadow depth map, static shadow depth map) * Forward lighting of local lights can be forced with 'r.VolumetricFog.InjectShadowedLightsSeparately 0' * Shadowed lights come at a cost: 2.9ms for volumetric fog on 970 -> 4.2ms with shadowing Change 3347053 on 2017/03/15 by Rolando.Caloca DR - android compile fix Change 3347384 on 2017/03/15 by Rolando.Caloca DR - Fix merge issue Change 3347643 on 2017/03/15 by Marcus.Wassmer Fix some bugs with the 'disable stationary skylight ffor the project' feature. Fixes lighting in Persona on Paragon. Change 3347979 on 2017/03/15 by Rolando.Caloca DR - Allow to automatically apply cached rendertargets to PSO initializer Change 3348024 on 2017/03/15 by Rolando.Caloca DR - Remove NullPS on Vulkan to avoid deadlock Change 3348303 on 2017/03/15 by Rolando.Caloca DR - Fix for debugging SCW with material SRT Change 3348357 on 2017/03/15 by Marcus.Wassmer Fix stencildither and a stencilref bug that was probably breaking decals sometimes. Change 3348549 on 2017/03/15 by Marcus.Wassmer Hopefully fix static analysis for potential nullptr access. Change 3348614 on 2017/03/15 by Marcus.Wassmer Duplicate some switch changes to fix crash on launch. Change 3349369 on 2017/03/16 by Gil.Gribb Fixed botched merge Change 3349947 on 2017/03/16 by Rolando.Caloca DR - Fix for mismatched primitive type Change 3349956 on 2017/03/16 by Benjamin.Hyder initial updates to TM-DistanceFields map Change 3350151 on 2017/03/16 by Rolando.Caloca DR - Fix UT compile issue Change 3350155 on 2017/03/16 by Rolando.Caloca DR - Catch mismatched primitive type on PSOs on D3D11 Change 3350192 on 2017/03/16 by Daniel.Wright Fix for point light shadow depths rendering with wrong cull mode due to PSO refactor Change 3350736 on 2017/03/16 by Daniel.Wright Fixed formatting from merge Change 3350881 on 2017/03/16 by Rolando.Caloca DR - Fix texture arrays as UAVs on Metal Change 3350927 on 2017/03/16 by Rolando.Caloca DR - Fix warning Change 3350935 on 2017/03/16 by Daniel.Wright Fix for materials with non-Surface domains being skipped in mesh passes Change 3351583 on 2017/03/17 by Marcus.Wassmer Fix clang platforms Change 3351917 on 2017/03/17 by Marcus.Wassmer Fix linux compile Change 3351973 on 2017/03/17 by Marcus.Wassmer Fix mismatched rendertargetformat Change 3352038 on 2017/03/17 by Daniel.Wright Enabled GetAndOrCreateGraphicsPipelineState ensures in Development for testing Change 3352110 on 2017/03/17 by Marcus.Wassmer Fix missing RT PSO apply Change 3352695 on 2017/03/17 by Arne.Schober DR - Remove PSO Rendertarget check in DX12 Resolve with Shader. #RB Rolando.Caloca Change 3352960 on 2017/03/17 by Arne.Schober DR - Fix some things that slipped trough the PSO merge #RB none Change 3353150 on 2017/03/18 by Rolando.Caloca DR - compile fix Change 3353205 on 2017/03/18 by Arne.Schober DR - Fix Incremental Compile and PS4 runtime error where CMASK is not allowed for ThickTile Mode #RB none Change 3353207 on 2017/03/18 by Arne.Schober DR - Fix Confusion #RB none Change 3355183 on 2017/03/20 by Nick.Bullard Fixed up Content orginzation for Decals automation tests in EngineTest Change 3355627 on 2017/03/20 by Arne.Schober DR - [UE-43094] - removed ensure in comporiton graph as control of the clear color cannot be gurantueed. Change 3356342 on 2017/03/21 by Marcus.Wassmer Fix clang errors Change 3356591 on 2017/03/21 by Arne.Schober DR - Fix ensure message #RB none Change 3356873 on 2017/03/21 by Arne.Schober DR - Fix comparission of undefined values in RendertargetApply Check Change 3357261 on 2017/03/21 by Marcus.Wassmer Fix LinuxEditor compile Change 3357294 on 2017/03/21 by Marcus.Wassmer Add missing SSE functions Change 3357351 on 2017/03/21 by Frank.Fella Fix win32 and linux compiler errors Change 3357370 on 2017/03/21 by Arne.Schober DR - disable ensure in test builds #RB Marcus.Wassmer [CL 3357449 by Marcus Wassmer in Main branch]
1552 lines
63 KiB
C++
1552 lines
63 KiB
C++
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
DeferredShadingRenderer.cpp: Top level rendering loop for deferred shading
|
|
=============================================================================*/
|
|
|
|
#include "DeferredShadingRenderer.h"
|
|
#include "VelocityRendering.h"
|
|
#include "AtmosphereRendering.h"
|
|
#include "ScenePrivate.h"
|
|
#include "ScreenRendering.h"
|
|
#include "PostProcess/SceneFilterRendering.h"
|
|
#include "PostProcess/ScreenSpaceReflections.h"
|
|
#include "CompositionLighting/CompositionLighting.h"
|
|
#include "FXSystem.h"
|
|
#include "OneColorShader.h"
|
|
#include "CompositionLighting/PostProcessDeferredDecals.h"
|
|
#include "DistanceFieldAmbientOcclusion.h"
|
|
#include "GlobalDistanceField.h"
|
|
#include "PostProcess/PostProcessing.h"
|
|
#include "DistanceFieldAtlas.h"
|
|
#include "EngineModule.h"
|
|
#include "SceneViewExtension.h"
|
|
#include "GPUSkinCache.h"
|
|
#include "PipelineStateCache.h"
|
|
#include "ClearQuad.h"
|
|
|
|
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: good occluders only: not masked, and large on screen\n")
|
|
TEXT(" 2: all opaque (including masked)\n")
|
|
TEXT(" x: use built in heuristic (default is 3)"),
|
|
ECVF_Scalability);
|
|
|
|
int32 GEarlyZPassMovable = 1;
|
|
|
|
/** 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. Defaults to on.\n")
|
|
TEXT("Note: also look at r.EarlyZPass"),
|
|
ECVF_RenderThreadSafe | ECVF_Scalability
|
|
);
|
|
|
|
/** Affects BasePassPixelShader.usf so must relaunch editor to recompile shaders. */
|
|
static TAutoConsoleVariable<int32> CVarEarlyZPassOnlyMaterialMasking(
|
|
TEXT("r.EarlyZPassOnlyMaterialMasking"),
|
|
0,
|
|
TEXT("Whether to compute materials' mask opacity only in early Z pass. Changing this setting requires restarting the editor.\n")
|
|
TEXT("Note: Needs r.EarlyZPass == 2 && r.EarlyZPassMovable == 1"),
|
|
ECVF_RenderThreadSafe | ECVF_ReadOnly
|
|
);
|
|
|
|
static TAutoConsoleVariable<int32> CVarStencilForLODDither(
|
|
TEXT("r.StencilForLODDither"),
|
|
0,
|
|
TEXT("Whether to use stencil tests in the prepass, and depth-equal tests in the base pass to implement LOD dithering.\n")
|
|
TEXT("If disabled, LOD dithering will be done through clip() instructions in the prepass and base pass, which disables EarlyZ.\n")
|
|
TEXT("Forces a full prepass when enabled."),
|
|
ECVF_RenderThreadSafe | ECVF_ReadOnly);
|
|
|
|
TAutoConsoleVariable<int32> CVarCustomDepthOrder(
|
|
TEXT("r.CustomDepth.Order"),
|
|
1,
|
|
TEXT("When CustomDepth (and CustomStencil) is getting rendered\n")
|
|
TEXT(" 0: Before GBuffer (can be more efficient with AsyncCompute, allows using it in DBuffer pass, no GBuffer blending decals allow GBuffer compression)\n")
|
|
TEXT(" 1: After Base Pass (default)"),
|
|
ECVF_RenderThreadSafe);
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
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 (default)\n")
|
|
TEXT(" 1: on"),
|
|
ECVF_Cheat | ECVF_RenderThreadSafe);
|
|
#endif
|
|
|
|
static TAutoConsoleVariable<int32> CVarClearCoatNormal(
|
|
TEXT("r.ClearCoatNormal"),
|
|
0,
|
|
TEXT("0 to disable clear coat normal.\n")
|
|
TEXT(" 0: off\n")
|
|
TEXT(" 1: on"),
|
|
ECVF_ReadOnly);
|
|
|
|
static TAutoConsoleVariable<int32> CVarFXSystemPreRenderAfterPrepass(
|
|
TEXT("r.FXSystemPreRenderAfterPrepass"),
|
|
0,
|
|
TEXT("If > 0, then do the FX prerender after the prepass. This improves pipelining for greater performance. Experiemental option."),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GbEnableAsyncComputeTranslucencyLightingVolumeClear = 1;
|
|
static FAutoConsoleVariableRef CVarEnableAsyncComputeTranslucencyLightingVolumeClear(
|
|
TEXT("r.EnableAsyncComputeTranslucencyLightingVolumeClear"),
|
|
GbEnableAsyncComputeTranslucencyLightingVolumeClear,
|
|
TEXT("Whether to clear the translucency lighting volume using async compute.\n"),
|
|
ECVF_RenderThreadSafe | ECVF_Scalability
|
|
);
|
|
|
|
static TAutoConsoleVariable<int32> CVarAlphaChannel(
|
|
TEXT("r.SceneAlpha"),
|
|
0,
|
|
TEXT("0 to disable scene alpha channel support.\n")
|
|
TEXT(" 0: disabled (default)\n")
|
|
TEXT(" 1: enabled"),
|
|
ECVF_ReadOnly);
|
|
|
|
static TAutoConsoleVariable<int32> CVarBasePassWriteDepthEvenWithFullPrepass(
|
|
TEXT("r.BasePassWriteDepthEvenWithFullPrepass"),
|
|
0,
|
|
TEXT("0 to allow a readonly base pass, which skips an MSAA depth resolve, and allows masked materials to get EarlyZ (writing to depth while doing clip() disables EarlyZ) (default)\n")
|
|
TEXT("1 to force depth writes in the base pass. Useful for debugging when the prepass and base pass don't match what they render."));
|
|
|
|
DECLARE_CYCLE_STAT(TEXT("PostInitViews FlushDel"), STAT_PostInitViews_FlushDel, STATGROUP_InitViews);
|
|
DECLARE_CYCLE_STAT(TEXT("InitViews Intentional Stall"), STAT_InitViews_Intentional_Stall, STATGROUP_InitViews);
|
|
|
|
DEFINE_STAT(STAT_FDeferredShadingSceneRenderer_AsyncSortBasePassStaticData);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer UpdateDownsampledDepthSurface"), STAT_FDeferredShadingSceneRenderer_UpdateDownsampledDepthSurface, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer Render Init"), STAT_FDeferredShadingSceneRenderer_Render_Init, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer Render ServiceLocalQueue"), STAT_FDeferredShadingSceneRenderer_Render_ServiceLocalQueue, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer DistanceFieldAO Init"), STAT_FDeferredShadingSceneRenderer_DistanceFieldAO_Init, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer FGlobalDynamicVertexBuffer Commit"), STAT_FDeferredShadingSceneRenderer_FGlobalDynamicVertexBuffer_Commit, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer FXSystem PreRender"), STAT_FDeferredShadingSceneRenderer_FXSystem_PreRender, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer AllocGBufferTargets"), STAT_FDeferredShadingSceneRenderer_AllocGBufferTargets, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer ClearLPVs"), STAT_FDeferredShadingSceneRenderer_ClearLPVs, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer DBuffer"), STAT_FDeferredShadingSceneRenderer_DBuffer, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer SetAndClearViewGBuffer"), STAT_FDeferredShadingSceneRenderer_SetAndClearViewGBuffer, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer ClearGBufferAtMaxZ"), STAT_FDeferredShadingSceneRenderer_ClearGBufferAtMaxZ, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer ResolveDepth After Basepass"), STAT_FDeferredShadingSceneRenderer_ResolveDepth_After_Basepass, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer Resolve After Basepass"), STAT_FDeferredShadingSceneRenderer_Resolve_After_Basepass, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer FXSystem PostRenderOpaque"), STAT_FDeferredShadingSceneRenderer_FXSystem_PostRenderOpaque, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer AfterBasePass"), STAT_FDeferredShadingSceneRenderer_AfterBasePass, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer Lighting"), STAT_FDeferredShadingSceneRenderer_Lighting, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer RenderLightShaftOcclusion"), STAT_FDeferredShadingSceneRenderer_RenderLightShaftOcclusion, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer RenderAtmosphere"), STAT_FDeferredShadingSceneRenderer_RenderAtmosphere, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer RenderFog"), STAT_FDeferredShadingSceneRenderer_RenderFog, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer RenderLightShaftBloom"), STAT_FDeferredShadingSceneRenderer_RenderLightShaftBloom, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer RenderFinish"), STAT_FDeferredShadingSceneRenderer_RenderFinish, STATGROUP_SceneRendering);
|
|
|
|
DECLARE_CYCLE_STAT(TEXT("OcclusionSubmittedFence Dispatch"), STAT_OcclusionSubmittedFence_Dispatch, STATGROUP_SceneRendering);
|
|
DECLARE_CYCLE_STAT(TEXT("OcclusionSubmittedFence Wait"), STAT_OcclusionSubmittedFence_Wait, STATGROUP_SceneRendering);
|
|
|
|
DECLARE_FLOAT_COUNTER_STAT(TEXT("Postprocessing"), Stat_GPU_Postprocessing, STATGROUP_GPU);
|
|
DECLARE_FLOAT_COUNTER_STAT(TEXT("HZB"), Stat_GPU_HZB, STATGROUP_GPU);
|
|
DECLARE_FLOAT_COUNTER_STAT(TEXT("[unaccounted]"), Stat_GPU_Unaccounted, STATGROUP_GPU);
|
|
|
|
bool ShouldForceFullDepthPass(ERHIFeatureLevel::Type FeatureLevel)
|
|
{
|
|
static IConsoleVariable* CDBufferVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.DBuffer"));
|
|
bool bDBufferAllowed = CDBufferVar ? CDBufferVar->GetInt() != 0 : false;
|
|
|
|
static const auto StencilLODDitherCVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.StencilForLODDither"));
|
|
bool bStencilLODDither = StencilLODDitherCVar->GetValueOnAnyThread() != 0;
|
|
|
|
// Note: ShouldForceFullDepthPass affects which static draw lists meshes go into, so nothing it depends on can change at runtime, unless you do a FGlobalComponentRecreateRenderStateContext to propagate the cvar change
|
|
return bDBufferAllowed || bStencilLODDither || IsForwardShadingEnabled(FeatureLevel) || UseSelectiveBasePassOutputs();
|
|
}
|
|
|
|
void GetEarlyZPassMode(ERHIFeatureLevel::Type FeatureLevel, EDepthDrawingMode& EarlyZPassMode, bool& bEarlyZPassMovable)
|
|
{
|
|
EarlyZPassMode = DDM_NonMaskedOnly;
|
|
bEarlyZPassMovable = false;
|
|
|
|
// developer override, good for profiling, can be useful as project setting
|
|
{
|
|
const int32 CVarValue = CVarEarlyZPass.GetValueOnAnyThread();
|
|
|
|
switch(CVarValue)
|
|
{
|
|
case 0: EarlyZPassMode = DDM_None; break;
|
|
case 1: EarlyZPassMode = DDM_NonMaskedOnly; break;
|
|
case 2: EarlyZPassMode = DDM_AllOccluders; break;
|
|
case 3: break; // Note: 3 indicates "default behavior" and does not specify an override
|
|
}
|
|
}
|
|
|
|
if (ShouldForceFullDepthPass(FeatureLevel))
|
|
{
|
|
// DBuffer decals and stencil LOD dithering force a full prepass
|
|
EarlyZPassMode = DDM_AllOpaque;
|
|
bEarlyZPassMovable = true;
|
|
}
|
|
}
|
|
|
|
bool SupportSceneAlpha()
|
|
{
|
|
return CVarAlphaChannel.GetValueOnRenderThread() != 0;
|
|
}
|
|
|
|
const TCHAR* GetDepthPassReason(bool bDitheredLODTransitionsUseStencil, ERHIFeatureLevel::Type FeatureLevel)
|
|
{
|
|
if (IsForwardShadingEnabled(FeatureLevel))
|
|
{
|
|
return TEXT("(Forced by ForwardShading)");
|
|
}
|
|
|
|
static IConsoleVariable* CDBufferVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.DBuffer"));
|
|
bool bDBufferAllowed = CDBufferVar ? CDBufferVar->GetInt() != 0 : false;
|
|
|
|
if (bDBufferAllowed)
|
|
{
|
|
return TEXT("(Forced by DBuffer)");
|
|
}
|
|
|
|
if (bDitheredLODTransitionsUseStencil)
|
|
{
|
|
return TEXT("(Forced by StencilLODDither)");
|
|
}
|
|
|
|
return TEXT("");
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FDeferredShadingSceneRenderer
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
FDeferredShadingSceneRenderer::FDeferredShadingSceneRenderer(const FSceneViewFamily* InViewFamily,FHitProxyConsumer* HitProxyConsumer)
|
|
: FSceneRenderer(InViewFamily, HitProxyConsumer)
|
|
{
|
|
static const auto StencilLODDitherCVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.StencilForLODDither"));
|
|
bDitheredLODTransitionsUseStencil = StencilLODDitherCVar->GetValueOnAnyThread() != 0;
|
|
|
|
GetEarlyZPassMode(FeatureLevel, EarlyZPassMode, bEarlyZPassMovable);
|
|
|
|
// Shader complexity requires depth only pass to display masked material cost correctly
|
|
if (ViewFamily.UseDebugViewPS() && ViewFamily.GetDebugViewShaderMode() != DVSM_OutputMaterialTextureScales)
|
|
{
|
|
EarlyZPassMode = DDM_AllOpaque;
|
|
bEarlyZPassMovable = true;
|
|
}
|
|
}
|
|
|
|
float GetSceneColorClearAlpha()
|
|
{
|
|
// Scene color alpha is used during scene captures and planar reflections. 1 indicates background should be shown, 0 indicates foreground is fully present.
|
|
return 1.0f;
|
|
}
|
|
|
|
/**
|
|
* Clears view where Z is still at the maximum value (ie no geometry rendered)
|
|
*/
|
|
void FDeferredShadingSceneRenderer::ClearGBufferAtMaxZ(FRHICommandList& RHICmdList)
|
|
{
|
|
// Assumes BeginRenderingSceneColor() has been called before this function
|
|
SCOPED_DRAW_EVENT(RHICmdList, ClearGBufferAtMaxZ);
|
|
|
|
// Clear the G Buffer render targets
|
|
const bool bClearBlack = Views[0].Family->EngineShowFlags.ShaderComplexity || Views[0].Family->EngineShowFlags.StationaryLightOverlap;
|
|
const float ClearAlpha = GetSceneColorClearAlpha();
|
|
const FLinearColor ClearColor = bClearBlack ? FLinearColor(0, 0, 0, ClearAlpha) : FLinearColor(Views[0].BackgroundColor.R, Views[0].BackgroundColor.G, Views[0].BackgroundColor.B, ClearAlpha);
|
|
// Same clear color from RHIClearMRT
|
|
FLinearColor ClearColors[MaxSimultaneousRenderTargets] =
|
|
{ClearColor, 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), FLinearColor::Transparent, FLinearColor::Transparent};
|
|
|
|
uint32 NumActiveRenderTargets = FSceneRenderTargets::Get(RHICmdList).GetNumGBufferTargets();
|
|
|
|
auto ShaderMap = GetGlobalShaderMap(FeatureLevel);
|
|
|
|
TShaderMapRef<TOneColorVS<true> > VertexShader(ShaderMap);
|
|
FOneColorPS* PixelShader = NULL;
|
|
|
|
// Assume for now all code path supports SM4, otherwise render target numbers are changed
|
|
switch(NumActiveRenderTargets)
|
|
{
|
|
case 5:
|
|
{
|
|
TShaderMapRef<TOneColorPixelShaderMRT<5> > MRTPixelShader(ShaderMap);
|
|
PixelShader = *MRTPixelShader;
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
TShaderMapRef<TOneColorPixelShaderMRT<6> > MRTPixelShader(ShaderMap);
|
|
PixelShader = *MRTPixelShader;
|
|
}
|
|
break;
|
|
default:
|
|
case 1:
|
|
{
|
|
TShaderMapRef<TOneColorPixelShaderMRT<1> > MRTPixelShader(ShaderMap);
|
|
PixelShader = *MRTPixelShader;
|
|
}
|
|
break;
|
|
}
|
|
|
|
FGraphicsPipelineStateInitializer GraphicsPSOInit;
|
|
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
|
|
|
|
// Opaque rendering, depth test but no depth writes
|
|
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
|
|
GraphicsPSOInit.BlendState = TStaticBlendStateWriteMask<>::GetRHI();
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI();
|
|
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GetVertexDeclarationFVector4();
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader);
|
|
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(PixelShader);
|
|
GraphicsPSOInit.PrimitiveType = PT_TriangleStrip;
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
|
|
|
|
// Clear each viewport by drawing background color at MaxZ depth
|
|
for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++)
|
|
{
|
|
SCOPED_CONDITIONAL_DRAW_EVENTF(RHICmdList, EventView, Views.Num() > 1, TEXT("ClearView%d"), ViewIndex);
|
|
|
|
FViewInfo& View = Views[ViewIndex];
|
|
|
|
// Set viewport for this view
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1);
|
|
|
|
// Setup PS
|
|
PixelShader->SetColors(RHICmdList, ClearColors, NumActiveRenderTargets);
|
|
|
|
// Render quad
|
|
static const FVector4 ClearQuadVertices[4] =
|
|
{
|
|
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 )
|
|
};
|
|
DrawPrimitiveUP(RHICmdList, PT_TriangleStrip, 2, ClearQuadVertices, sizeof(ClearQuadVertices[0]));
|
|
}
|
|
}
|
|
|
|
/** Render the TexturePool texture */
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
void FDeferredShadingSceneRenderer::RenderVisualizeTexturePool(FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
TRefCountPtr<IPooledRenderTarget> VisualizeTexturePool;
|
|
|
|
/** Resolution for the texture pool visualizer texture. */
|
|
enum
|
|
{
|
|
TexturePoolVisualizerSizeX = 280,
|
|
TexturePoolVisualizerSizeY = 140,
|
|
};
|
|
|
|
FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(FIntPoint(TexturePoolVisualizerSizeX, TexturePoolVisualizerSizeY), PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_None, false));
|
|
GRenderTargetPool.FindFreeElement(RHICmdList, Desc, VisualizeTexturePool, TEXT("VisualizeTexturePool"));
|
|
|
|
uint32 Pitch;
|
|
FColor* TextureData = (FColor*)RHICmdList.LockTexture2D((FTexture2DRHIRef&)VisualizeTexturePool->GetRenderTargetItem().ShaderResourceTexture, 0, RLM_WriteOnly, Pitch, false);
|
|
if(TextureData)
|
|
{
|
|
// clear with grey to get reliable background color
|
|
FMemory::Memset(TextureData, 0x88, TexturePoolVisualizerSizeX * TexturePoolVisualizerSizeY * 4);
|
|
RHICmdList.GetTextureMemoryVisualizeData(TextureData, TexturePoolVisualizerSizeX, TexturePoolVisualizerSizeY, Pitch, 4096);
|
|
}
|
|
|
|
RHICmdList.UnlockTexture2D((FTexture2DRHIRef&)VisualizeTexturePool->GetRenderTargetItem().ShaderResourceTexture, 0, false);
|
|
|
|
FIntPoint RTExtent = FSceneRenderTargets::Get(RHICmdList).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.
|
|
*/
|
|
void FDeferredShadingSceneRenderer::RenderFinish(FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
{
|
|
if(CVarVisualizeTexturePool.GetValueOnRenderThread())
|
|
{
|
|
RenderVisualizeTexturePool(RHICmdList);
|
|
}
|
|
}
|
|
|
|
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
|
|
if (GEnableGPUSkinCache)
|
|
{
|
|
GGPUSkinCache.TransitionToWriteable(RHICmdList);
|
|
}
|
|
|
|
FSceneRenderer::RenderFinish(RHICmdList);
|
|
|
|
// 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.
|
|
// This becomes even more important with some limited VRam (XBoxOne).
|
|
FSceneRenderTargets::Get(RHICmdList).SetLightAttenuation(0);
|
|
}
|
|
|
|
void BuildHZB( FRHICommandListImmediate& RHICmdList, FViewInfo& View );
|
|
|
|
/**
|
|
* Renders the view family.
|
|
*/
|
|
|
|
DEFINE_STAT(STAT_CLM_PrePass);
|
|
DECLARE_CYCLE_STAT(TEXT("FXPreRender"), STAT_CLM_FXPreRender, 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("RenderDistortion"), STAT_CLM_RenderDistortion, STATGROUP_CommandListMarkers);
|
|
DECLARE_CYCLE_STAT(TEXT("AfterTranslucency"), STAT_CLM_AfterTranslucency, STATGROUP_CommandListMarkers);
|
|
DECLARE_CYCLE_STAT(TEXT("RenderDistanceFieldLighting"), STAT_CLM_RenderDistanceFieldLighting, STATGROUP_CommandListMarkers);
|
|
DECLARE_CYCLE_STAT(TEXT("LightShaftBloom"), STAT_CLM_LightShaftBloom, STATGROUP_CommandListMarkers);
|
|
DECLARE_CYCLE_STAT(TEXT("PostProcessing"), STAT_CLM_PostProcessing, 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("RenderFinish"), STAT_CLM_RenderFinish, STATGROUP_CommandListMarkers);
|
|
DECLARE_CYCLE_STAT(TEXT("AfterFrame"), STAT_CLM_AfterFrame, STATGROUP_CommandListMarkers);
|
|
|
|
FGraphEventRef FDeferredShadingSceneRenderer::OcclusionSubmittedFence[FOcclusionQueryHelpers::MaxBufferedOcclusionFrames];
|
|
FGraphEventRef FDeferredShadingSceneRenderer::TranslucencyTimestampQuerySubmittedFence[FOcclusionQueryHelpers::MaxBufferedOcclusionFrames + 1];
|
|
|
|
/**
|
|
* 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 || Renderer->bEarlyZPassMovable != 0);
|
|
}
|
|
|
|
static void SetAndClearViewGBuffer(FRHICommandListImmediate& RHICmdList, FViewInfo& View, FExclusiveDepthStencil::Type DepthStencilAccess, 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 float ClearAlpha = GetSceneColorClearAlpha();
|
|
const FLinearColor ClearColor = bClearBlack ? FLinearColor(0, 0, 0, ClearAlpha) : FLinearColor(View.BackgroundColor.R, View.BackgroundColor.G, View.BackgroundColor.B, ClearAlpha);
|
|
|
|
// clearing the GBuffer
|
|
FSceneRenderTargets::Get(RHICmdList).BeginRenderingGBuffer(RHICmdList, ERenderTargetLoadAction::EClear, DepthLoadAction, DepthStencilAccess, View.Family->EngineShowFlags.ShaderComplexity, ClearColor);
|
|
}
|
|
|
|
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)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
SCOPED_GPU_STAT(RHICmdList, Stat_GPU_HZB);
|
|
|
|
{
|
|
// 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.
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_UpdateDownsampledDepthSurface);
|
|
UpdateDownsampledDepthSurface(RHICmdList);
|
|
}
|
|
|
|
// 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);
|
|
|
|
if (bRenderHZB)
|
|
{
|
|
RHICmdList.TransitionResource( EResourceTransitionAccess::EReadable, SceneContext.GetSceneDepthSurface() );
|
|
|
|
static const auto ICVarHZBOcc = IConsoleManager::Get().FindConsoleVariable(TEXT("r.HZBOcclusion"));
|
|
bool bHZBOcclusion = ICVarHZBOcc->GetInt() != 0;
|
|
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
FViewInfo& View = Views[ViewIndex];
|
|
FSceneViewState* ViewState = (FSceneViewState*)View.State;
|
|
|
|
const uint32 bSSR = ShouldRenderScreenSpaceReflections(View);
|
|
const bool bSSAO = ShouldRenderScreenSpaceAmbientOcclusion(View);
|
|
|
|
if (bSSAO || bHZBOcclusion || bSSR)
|
|
{
|
|
BuildHZB(RHICmdList, Views[ViewIndex]);
|
|
}
|
|
|
|
if (bHZBOcclusion && ViewState && ViewState->HZBOcclusionTests.GetNum() != 0)
|
|
{
|
|
check(ViewState->HZBOcclusionTests.IsValidFrame(ViewState->OcclusionFrameCounter));
|
|
|
|
SCOPED_DRAW_EVENT(RHICmdList, HZB);
|
|
ViewState->HZBOcclusionTests.Submit(RHICmdList, View);
|
|
}
|
|
}
|
|
|
|
//async ssao only requires HZB and depth as inputs so get started ASAP
|
|
if (GCompositionLighting.CanProcessAsyncSSAO(Views))
|
|
{
|
|
GCompositionLighting.ProcessAsyncSSAO(RHICmdList, Views);
|
|
}
|
|
}
|
|
|
|
// 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();
|
|
|
|
if (bRenderQueries && GRHIThread)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_OcclusionSubmittedFence_Dispatch);
|
|
int32 NumFrames = FOcclusionQueryHelpers::GetNumBufferedFrames();
|
|
for (int32 Dest = 1; Dest < NumFrames; Dest++)
|
|
{
|
|
CA_SUPPRESS(6385);
|
|
OcclusionSubmittedFence[Dest] = OcclusionSubmittedFence[Dest - 1];
|
|
}
|
|
OcclusionSubmittedFence[0] = RHICmdList.RHIThreadFence();
|
|
RHICmdList.ImmediateFlush(EImmediateFlushType::DispatchToRHIThread);
|
|
}
|
|
}
|
|
}
|
|
|
|
// The render thread is involved in sending stuff to the RHI, so we will periodically service that queue
|
|
void ServiceLocalQueue()
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_Render_ServiceLocalQueue);
|
|
FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::RenderThread_Local);
|
|
}
|
|
|
|
// @return 0/1
|
|
static int32 GetCustomDepthPassLocation()
|
|
{
|
|
return FMath::Clamp(CVarCustomDepthOrder.GetValueOnRenderThread(), 0, 1);
|
|
}
|
|
|
|
extern bool IsLpvIndirectPassRequired(const FViewInfo& View);
|
|
|
|
static TAutoConsoleVariable<float> CVarStallInitViews(
|
|
TEXT("CriticalPathStall.AfterInitViews"),
|
|
0.0f,
|
|
TEXT("Sleep for the given time after InitViews. Time is given in ms. This is a debug option used for critical path analysis and forcing a change in the critical path."));
|
|
|
|
void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
//make sure all the targets we're going to use will be safely writable.
|
|
GRenderTargetPool.TransitionTargetsWritable(RHICmdList);
|
|
|
|
// this way we make sure the SceneColor format is the correct one and not the one from the end of frame before
|
|
SceneContext.ReleaseSceneColor();
|
|
|
|
bool bDBuffer = IsDBufferEnabled();
|
|
|
|
if (GRHIThread)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_OcclusionSubmittedFence_Wait);
|
|
int32 BlockFrame = FOcclusionQueryHelpers::GetNumBufferedFrames() - 1;
|
|
FRHICommandListExecutor::WaitOnRHIThreadFence(OcclusionSubmittedFence[BlockFrame]);
|
|
OcclusionSubmittedFence[BlockFrame] = nullptr;
|
|
}
|
|
|
|
if (!ViewFamily.EngineShowFlags.Rendering)
|
|
{
|
|
return;
|
|
}
|
|
SCOPED_DRAW_EVENT(RHICmdList, Scene);
|
|
|
|
// Anything rendered inside Render() which isn't accounted for will fall into this stat
|
|
// This works because child stat events do not contribute to their parents' times (see GPU_STATS_CHILD_TIMES_INCLUDED)
|
|
SCOPED_GPU_STAT(RHICmdList, Stat_GPU_Unaccounted);
|
|
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_Render_Init);
|
|
|
|
// Initialize global system textures (pass-through if already initialized).
|
|
GSystemTextures.InitializeTextures(RHICmdList, FeatureLevel);
|
|
|
|
// Allocate the maximum scene render target space for the current view family.
|
|
SceneContext.Allocate(RHICmdList, ViewFamily);
|
|
}
|
|
|
|
FGraphEventArray SortEvents;
|
|
FILCUpdatePrimTaskData ILCTaskData;
|
|
|
|
// Find the visible primitives.
|
|
bool bDoInitViewAftersPrepass = InitViews(RHICmdList, ILCTaskData, SortEvents);
|
|
|
|
for (int32 ViewExt = 0; ViewExt < ViewFamily.ViewExtensions.Num(); ++ViewExt)
|
|
{
|
|
ViewFamily.ViewExtensions[ViewExt]->PostInitViewFamily_RenderThread(RHICmdList, ViewFamily);
|
|
for (int32 ViewIndex = 0; ViewIndex < ViewFamily.Views.Num(); ++ViewIndex)
|
|
{
|
|
ViewFamily.ViewExtensions[ViewExt]->PostInitView_RenderThread(RHICmdList, Views[ViewIndex]);
|
|
}
|
|
}
|
|
|
|
TGuardValue<bool> LockDrawLists(GDrawListsLocked, true);
|
|
#if !UE_BUILD_SHIPPING
|
|
if (CVarStallInitViews.GetValueOnRenderThread() > 0.0f)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_InitViews_Intentional_Stall);
|
|
FPlatformProcess::Sleep(CVarStallInitViews.GetValueOnRenderThread() / 1000.0f);
|
|
}
|
|
#endif
|
|
|
|
if (GRHICommandList.UseParallelAlgorithms())
|
|
{
|
|
// there are dynamic attempts to get this target during parallel rendering
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
Views[ViewIndex].GetEyeAdaptation(RHICmdList);
|
|
}
|
|
}
|
|
|
|
if (ShouldPrepareDistanceFieldScene())
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_DistanceFieldAO_Init);
|
|
GDistanceFieldVolumeTextureAtlas.UpdateAllocations();
|
|
UpdateGlobalDistanceFieldObjectBuffers(RHICmdList);
|
|
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
Views[ViewIndex].HeightfieldLightingViewInfo.SetupVisibleHeightfields(Views[ViewIndex], RHICmdList);
|
|
|
|
if (ShouldPrepareGlobalDistanceField())
|
|
{
|
|
// Use the skylight's max distance if there is one
|
|
const float OcclusionMaxDistance = Scene->SkyLight && !Scene->SkyLight->bWantsStaticShadowing ? Scene->SkyLight->OcclusionMaxDistance : Scene->DefaultMaxDistanceFieldOcclusionDistance;
|
|
UpdateGlobalDistanceFieldVolume(RHICmdList, Views[ViewIndex], Scene, OcclusionMaxDistance, Views[ViewIndex].GlobalDistanceFieldInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GRHIThread)
|
|
{
|
|
// we will probably stall on occlusion queries, so might as well have the RHI thread and GPU work while we wait.
|
|
SCOPE_CYCLE_COUNTER(STAT_PostInitViews_FlushDel);
|
|
FRHICommandListExecutor::GetImmediateCommandList().ImmediateFlush(EImmediateFlushType::FlushRHIThreadFlushResources);
|
|
}
|
|
|
|
const bool bIsWireframe = ViewFamily.EngineShowFlags.Wireframe;
|
|
static const auto ClearMethodCVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ClearSceneMethod"));
|
|
bool bRequiresRHIClear = true;
|
|
bool bRequiresFarZQuadClear = false;
|
|
|
|
const bool bUseGBuffer = IsUsingGBuffers(GetFeatureLevelShaderPlatform(FeatureLevel));
|
|
const bool bRenderDeferredLighting = ViewFamily.EngineShowFlags.Lighting
|
|
&& FeatureLevel >= ERHIFeatureLevel::SM4
|
|
&& ViewFamily.EngineShowFlags.DeferredLighting
|
|
&& bUseGBuffer;
|
|
|
|
if (ClearMethodCVar)
|
|
{
|
|
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)
|
|
{
|
|
case 0: // No clear
|
|
{
|
|
bRequiresRHIClear = false;
|
|
bRequiresFarZQuadClear = false;
|
|
break;
|
|
}
|
|
|
|
case 1: // RHICmdList.Clear
|
|
{
|
|
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
|
|
|
|
|
|
const bool bIsOcclusionTesting = DoOcclusionQueries(FeatureLevel) && (!bIsWireframe || bIsViewFrozen || bHasViewParent);
|
|
|
|
// Dynamic vertex and index buffers need to be committed before rendering.
|
|
if (!bDoInitViewAftersPrepass)
|
|
{
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_FGlobalDynamicVertexBuffer_Commit);
|
|
FGlobalDynamicVertexBuffer::Get().Commit();
|
|
FGlobalDynamicIndexBuffer::Get().Commit();
|
|
}
|
|
}
|
|
|
|
// Notify the FX system that the scene is about to be rendered.
|
|
bool bLateFXPrerender = CVarFXSystemPreRenderAfterPrepass.GetValueOnRenderThread() > 0;
|
|
bool bDoFXPrerender = Scene->FXSystem && Views.IsValidIndex(0) && !Views[0].bIsPlanarReflection;
|
|
if (!bLateFXPrerender && bDoFXPrerender)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_FXSystem_PreRender);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_FXPreRender));
|
|
Scene->FXSystem->PreRender(RHICmdList, &Views[0].GlobalDistanceFieldInfo.ParameterData);
|
|
}
|
|
|
|
if (GEnableGPUSkinCache)
|
|
{
|
|
GGPUSkinCache.TransitionToReadable(RHICmdList);
|
|
}
|
|
|
|
bool bDidAfterTaskWork = false;
|
|
auto AfterTasksAreStarted = [&bDidAfterTaskWork, bDoInitViewAftersPrepass, this, &RHICmdList, &ILCTaskData, &SortEvents, bLateFXPrerender, bDoFXPrerender]()
|
|
{
|
|
if (!bDidAfterTaskWork)
|
|
{
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_AfterPrepassTasksWork);
|
|
bDidAfterTaskWork = true; // only do this once
|
|
if (bDoInitViewAftersPrepass)
|
|
{
|
|
InitViewsPossiblyAfterPrepass(RHICmdList, ILCTaskData, SortEvents);
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_FGlobalDynamicVertexBuffer_Commit);
|
|
FGlobalDynamicVertexBuffer::Get().Commit();
|
|
FGlobalDynamicIndexBuffer::Get().Commit();
|
|
}
|
|
ServiceLocalQueue();
|
|
}
|
|
if (bLateFXPrerender && bDoFXPrerender)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_FXSystem_PreRender);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_FXPreRender));
|
|
Scene->FXSystem->PreRender(RHICmdList, &Views[0].GlobalDistanceFieldInfo.ParameterData);
|
|
ServiceLocalQueue();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Draw the scene pre-pass / early z pass, populating the scene depth buffer and HiZ
|
|
GRenderTargetPool.AddPhaseEvent(TEXT("EarlyZPass"));
|
|
const bool bNeedsPrePass = NeedsPrePass(this);
|
|
bool bDepthWasCleared;
|
|
if (bNeedsPrePass)
|
|
{
|
|
bDepthWasCleared = RenderPrePass(RHICmdList, AfterTasksAreStarted);
|
|
}
|
|
else
|
|
{
|
|
// we didn't do the prepass, but we still want the HMD mask if there is one
|
|
AfterTasksAreStarted();
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_PrePass));
|
|
bDepthWasCleared = RenderPrePassHMD(RHICmdList);
|
|
}
|
|
check(bDidAfterTaskWork);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_AfterPrePass));
|
|
ServiceLocalQueue();
|
|
|
|
const bool bShouldRenderVelocities = ShouldRenderVelocities();
|
|
const bool bUseVelocityGBuffer = FVelocityRendering::OutputsToGBuffer();
|
|
const bool bUseSelectiveBasePassOutputs = UseSelectiveBasePassOutputs();
|
|
|
|
// Use readonly depth in the base pass if we have a full depth prepass
|
|
const bool bAllowReadonlyDepthBasePass = EarlyZPassMode == DDM_AllOpaque
|
|
&& CVarBasePassWriteDepthEvenWithFullPrepass.GetValueOnRenderThread() == 0
|
|
&& !ViewFamily.EngineShowFlags.ShaderComplexity
|
|
&& !ViewFamily.UseDebugViewPS()
|
|
&& !bIsWireframe
|
|
&& !ViewFamily.EngineShowFlags.LightMapDensity;
|
|
|
|
const FExclusiveDepthStencil::Type BasePassDepthStencilAccess =
|
|
bAllowReadonlyDepthBasePass
|
|
? FExclusiveDepthStencil::DepthRead_StencilWrite
|
|
: FExclusiveDepthStencil::DepthWrite_StencilWrite;
|
|
|
|
SceneContext.ResolveSceneDepthTexture(RHICmdList, FResolveRect(0, 0, ViewFamily.FamilySizeX, ViewFamily.FamilySizeY));
|
|
|
|
if (bUseGBuffer || IsSimpleForwardShadingEnabled(GetFeatureLevelShaderPlatform(FeatureLevel)))
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_AllocGBufferTargets);
|
|
SceneContext.PreallocGBufferTargets(); // Even if !bShouldRenderVelocities, the velocity buffer must be bound because it's a compile time option for the shader.
|
|
SceneContext.AllocGBufferTargets(RHICmdList);
|
|
}
|
|
|
|
//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) || IsForwardShadingEnabled(FeatureLevel);
|
|
bool bHZBBeforeBasePass = bOcclusionBeforeBasePass && (EarlyZPassMode == EDepthDrawingMode::DDM_AllOccluders);
|
|
|
|
RenderOcclusion(RHICmdList, bOcclusionBeforeBasePass, bHZBBeforeBasePass);
|
|
ServiceLocalQueue();
|
|
|
|
if (bOcclusionBeforeBasePass)
|
|
{
|
|
RenderShadowDepthMaps(RHICmdList);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// Clear LPVs for all views
|
|
if (FeatureLevel >= ERHIFeatureLevel::SM5)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_ClearLPVs);
|
|
ClearLPVs(RHICmdList);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
if(GetCustomDepthPassLocation() == 0)
|
|
{
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_CustomDepthPass0);
|
|
RenderCustomDepthPassAtLocation(RHICmdList, 0);
|
|
}
|
|
|
|
ComputeLightGrid(RHICmdList);
|
|
|
|
if (bOcclusionBeforeBasePass)
|
|
{
|
|
ComputeVolumetricFog(RHICmdList);
|
|
}
|
|
|
|
if (IsForwardShadingEnabled(FeatureLevel))
|
|
{
|
|
RenderForwardShadingShadowProjections(RHICmdList);
|
|
|
|
RenderIndirectCapsuleShadows(
|
|
RHICmdList,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
|
|
// only temporarily available after early z pass and until base pass
|
|
check(!SceneContext.DBufferA);
|
|
check(!SceneContext.DBufferB);
|
|
check(!SceneContext.DBufferC);
|
|
|
|
if (bDBuffer)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_DBuffer);
|
|
SceneContext.ResolveSceneDepthToAuxiliaryTexture(RHICmdList);
|
|
|
|
// e.g. DBuffer deferred decals
|
|
for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++)
|
|
{
|
|
SCOPED_CONDITIONAL_DRAW_EVENTF(RHICmdList, EventView,Views.Num() > 1, TEXT("View%d"), ViewIndex);
|
|
|
|
GCompositionLighting.ProcessBeforeBasePass(RHICmdList, Views[ViewIndex]);
|
|
}
|
|
//GBuffer pass will want to write to SceneDepthZ
|
|
RHICmdList.TransitionResource(EResourceTransitionAccess::EWritable, SceneContext.GetSceneDepthTexture());
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// Clear the GBuffer render targets
|
|
bool bIsGBufferCurrent = false;
|
|
if (bRequiresRHIClear)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_SetAndClearViewGBuffer);
|
|
// set GBuffer to be current, and clear it
|
|
SetAndClearViewGBuffer(RHICmdList, Views[0], BasePassDepthStencilAccess, !bDepthWasCleared);
|
|
|
|
// depth was cleared now no matter what
|
|
bDepthWasCleared = true;
|
|
bIsGBufferCurrent = true;
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
if (bIsWireframe && FSceneRenderer::ShouldCompositeEditorPrimitives(Views[0]))
|
|
{
|
|
// In Editor we want wire frame view modes to be MSAA for better quality. Resolve will be done with EditorPrimitives
|
|
SetRenderTarget(RHICmdList, SceneContext.GetEditorPrimitivesColor(RHICmdList), SceneContext.GetEditorPrimitivesDepth(RHICmdList), ESimpleRenderTargetMode::EClearColorAndDepth);
|
|
}
|
|
else if (!bIsGBufferCurrent)
|
|
{
|
|
// make sure the GBuffer is set, in case we didn't need to clear above
|
|
ERenderTargetLoadAction DepthLoadAction = bDepthWasCleared ? ERenderTargetLoadAction::ELoad : ERenderTargetLoadAction::EClear;
|
|
SceneContext.BeginRenderingGBuffer(RHICmdList, ERenderTargetLoadAction::ENoAction, DepthLoadAction, BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity);
|
|
}
|
|
|
|
if (bRenderDeferredLighting)
|
|
{
|
|
//Single point to catch UE-31578, UE-32536 and UE-22073 and attempt to recover by reallocating Deferred Render Targets
|
|
if (!SceneContext.TranslucencyLightingVolumeAmbient[0] || !SceneContext.TranslucencyLightingVolumeDirectional[0] ||
|
|
!SceneContext.TranslucencyLightingVolumeAmbient[1] || !SceneContext.TranslucencyLightingVolumeDirectional[1])
|
|
{
|
|
const char* str = SceneContext.ScreenSpaceAO ? "Allocated" : "Unallocated"; //ScreenSpaceAO is determining factor of detecting render target allocation
|
|
ensureMsgf(SceneContext.TranslucencyLightingVolumeAmbient[0], TEXT("%s is unallocated, Deferred Render Targets would be detected as: %s"), "TranslucencyLightingVolumeAmbient0", str);
|
|
ensureMsgf(SceneContext.TranslucencyLightingVolumeDirectional[0], TEXT("%s is unallocated, Deferred Render Targets would be detected as: %s"), "TranslucencyLightingVolumeDirectional0", str);
|
|
ensureMsgf(SceneContext.TranslucencyLightingVolumeAmbient[1], TEXT("%s is unallocated, Deferred Render Targets would be detected as: %s"), "TranslucencyLightingVolumeAmbient1", str);
|
|
ensureMsgf(SceneContext.TranslucencyLightingVolumeDirectional[1], TEXT("%s is unallocated, Deferred Render Targets would be detected as: %s"), "TranslucencyLightingVolumeDirectional1", str);
|
|
SceneContext.AllocateDeferredShadingPathRenderTargets(RHICmdList);
|
|
}
|
|
|
|
if (GbEnableAsyncComputeTranslucencyLightingVolumeClear && GSupportsEfficientAsyncCompute)
|
|
{
|
|
ClearTranslucentVolumeLightingAsyncCompute(RHICmdList);
|
|
}
|
|
}
|
|
|
|
GRenderTargetPool.AddPhaseEvent(TEXT("BasePass"));
|
|
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_BasePass));
|
|
RenderBasePass(RHICmdList, BasePassDepthStencilAccess);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_AfterBasePass));
|
|
ServiceLocalQueue();
|
|
|
|
if (!bAllowReadonlyDepthBasePass)
|
|
{
|
|
SceneContext.ResolveSceneDepthTexture(RHICmdList, FResolveRect(0, 0, ViewFamily.FamilySizeX, ViewFamily.FamilySizeY));
|
|
}
|
|
|
|
if (ViewFamily.EngineShowFlags.VisualizeLightCulling)
|
|
{
|
|
// clear out emissive and baked lighting (not too efficient but simple and only needed for this debug view)
|
|
SceneContext.BeginRenderingSceneColor(RHICmdList);
|
|
DrawClearQuad(RHICmdList, GMaxRHIFeatureLevel, FLinearColor(0, 0, 0, 0));
|
|
}
|
|
|
|
SceneContext.DBufferA.SafeRelease();
|
|
SceneContext.DBufferB.SafeRelease();
|
|
SceneContext.DBufferC.SafeRelease();
|
|
|
|
// only temporarily available after early z pass and until base pass
|
|
check(!SceneContext.DBufferA);
|
|
check(!SceneContext.DBufferB);
|
|
check(!SceneContext.DBufferC);
|
|
|
|
if (bRequiresFarZQuadClear)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_ClearGBufferAtMaxZ);
|
|
// Clears view by drawing quad at maximum Z
|
|
// TODO: if all the platforms have fast color clears, we can replace this with an RHICmdList.Clear.
|
|
ClearGBufferAtMaxZ(RHICmdList);
|
|
ServiceLocalQueue();
|
|
|
|
bRequiresFarZQuadClear = false;
|
|
}
|
|
|
|
SceneContext.ResolveSceneDepthToAuxiliaryTexture(RHICmdList);
|
|
|
|
bool bOcclusionAfterBasePass = bIsOcclusionTesting && !bOcclusionBeforeBasePass;
|
|
bool bHZBAfterBasePass = !bHZBBeforeBasePass;
|
|
RenderOcclusion(RHICmdList, bOcclusionAfterBasePass, bHZBAfterBasePass);
|
|
ServiceLocalQueue();
|
|
|
|
if (!bOcclusionBeforeBasePass)
|
|
{
|
|
RenderShadowDepthMaps(RHICmdList);
|
|
ComputeVolumetricFog(RHICmdList);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
if (bUseGBuffer)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_Resolve_After_Basepass);
|
|
SceneContext.FinishRenderingGBuffer(RHICmdList);
|
|
}
|
|
|
|
if(GetCustomDepthPassLocation() == 1)
|
|
{
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_CustomDepthPass1);
|
|
RenderCustomDepthPassAtLocation(RHICmdList, 1);
|
|
}
|
|
|
|
ServiceLocalQueue();
|
|
|
|
// Notify the FX system that opaque primitives have been rendered and we now have a valid depth buffer.
|
|
if (Scene->FXSystem && Views.IsValidIndex(0) && !Views[0].bIsPlanarReflection)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_FXSystem_PostRenderOpaque);
|
|
Scene->FXSystem->PostRenderOpaque(
|
|
RHICmdList,
|
|
Views[0].ViewUniformBuffer,
|
|
SceneContext.GetSceneDepthTexture(),
|
|
SceneContext.GBufferA ? SceneContext.GetGBufferATexture() : NULL
|
|
);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
TRefCountPtr<IPooledRenderTarget> VelocityRT;
|
|
|
|
if (bUseVelocityGBuffer)
|
|
{
|
|
VelocityRT = SceneContext.GetGBufferVelocityRT();
|
|
}
|
|
|
|
if (bShouldRenderVelocities && (!bUseVelocityGBuffer || bUseSelectiveBasePassOutputs))
|
|
{
|
|
// Render the velocities of movable objects
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_Velocity));
|
|
RenderVelocities(RHICmdList, VelocityRT);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_AfterVelocity));
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// Copy lighting channels out of stencil before deferred decals which overwrite those values
|
|
CopyStencilToLightingChannelTexture(RHICmdList);
|
|
|
|
{
|
|
GCompositionLighting.GfxWaitForAsyncSSAO(RHICmdList);
|
|
}
|
|
|
|
// Pre-lighting composition lighting stage
|
|
// e.g. deferred decals, SSAO
|
|
if (FeatureLevel >= ERHIFeatureLevel::SM4)
|
|
{
|
|
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]);
|
|
}
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// TODO: Could entirely remove this by using STENCIL_SANDBOX_BIT in ShadowRendering.cpp and DistanceFieldSurfaceCacheLighting.cpp
|
|
if (!IsForwardShadingEnabled(FeatureLevel))
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, ClearStencilFromBasePass);
|
|
|
|
FRHISetRenderTargetsInfo Info(0, NULL, FRHIDepthRenderTargetView(
|
|
SceneContext.GetSceneDepthSurface(),
|
|
ERenderTargetLoadAction::ENoAction,
|
|
ERenderTargetStoreAction::ENoAction,
|
|
ERenderTargetLoadAction::EClear,
|
|
ERenderTargetStoreAction::EStore,
|
|
FExclusiveDepthStencil::DepthNop_StencilWrite));
|
|
|
|
// Clear stencil to 0 now that deferred decals are done using what was setup in the base pass
|
|
// Shadow passes and other users of stencil assume it is cleared to 0 going in
|
|
RHICmdList.SetRenderTargetsAndClear(Info);
|
|
|
|
RHICmdList.TransitionResource(EResourceTransitionAccess::EReadable, SceneContext.GetSceneDepthSurface());
|
|
}
|
|
|
|
// Render lighting.
|
|
if (bRenderDeferredLighting)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_Lighting);
|
|
|
|
GRenderTargetPool.AddPhaseEvent(TEXT("Lighting"));
|
|
|
|
// These modulate the scenecolor output from the basepass, which is assumed to be indirect lighting
|
|
RenderIndirectCapsuleShadows(
|
|
RHICmdList,
|
|
SceneContext.GetSceneColorSurface(),
|
|
SceneContext.bScreenSpaceAOIsValid ? SceneContext.ScreenSpaceAO->GetRenderTargetItem().TargetableTexture : NULL);
|
|
|
|
TRefCountPtr<IPooledRenderTarget> DynamicBentNormalAO;
|
|
// These modulate the scenecolor output from the basepass, which is assumed to be indirect lighting
|
|
RenderDFAOAsIndirectShadowing(RHICmdList, VelocityRT, DynamicBentNormalAO);
|
|
|
|
// Clear the translucent lighting volumes before we accumulate
|
|
if ((GbEnableAsyncComputeTranslucencyLightingVolumeClear && GSupportsEfficientAsyncCompute) == false)
|
|
{
|
|
ClearTranslucentVolumeLighting(RHICmdList);
|
|
}
|
|
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_Lighting));
|
|
RenderLights(RHICmdList);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_AfterLighting));
|
|
ServiceLocalQueue();
|
|
|
|
GRenderTargetPool.AddPhaseEvent(TEXT("AfterRenderLights"));
|
|
|
|
InjectAmbientCubemapTranslucentVolumeLighting(RHICmdList);
|
|
ServiceLocalQueue();
|
|
|
|
// Filter the translucency lighting volume now that it is complete
|
|
FilterTranslucentVolumeLighting(RHICmdList);
|
|
ServiceLocalQueue();
|
|
|
|
// Pre-lighting composition lighting stage
|
|
// e.g. LPV indirect
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
|
|
{
|
|
FViewInfo& View = Views[ViewIndex];
|
|
|
|
if(IsLpvIndirectPassRequired(View))
|
|
{
|
|
SCOPED_CONDITIONAL_DRAW_EVENTF(RHICmdList, EventView,Views.Num() > 1, TEXT("View%d"), ViewIndex);
|
|
|
|
GCompositionLighting.ProcessLpvIndirect(RHICmdList, View);
|
|
ServiceLocalQueue();
|
|
}
|
|
}
|
|
|
|
RenderDynamicSkyLighting(RHICmdList, VelocityRT, DynamicBentNormalAO);
|
|
ServiceLocalQueue();
|
|
|
|
// SSS need the SceneColor finalized as an SRV.
|
|
ResolveSceneColor(RHICmdList);
|
|
|
|
// Render reflections that only operate on opaque pixels
|
|
RenderDeferredReflections(RHICmdList, DynamicBentNormalAO, VelocityRT);
|
|
ServiceLocalQueue();
|
|
|
|
// Post-lighting composition lighting stage
|
|
// e.g. ScreenSpaceSubsurfaceScattering
|
|
for(int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
|
|
{
|
|
SCOPED_CONDITIONAL_DRAW_EVENTF(RHICmdList, EventView,Views.Num() > 1, TEXT("View%d"), ViewIndex);
|
|
GCompositionLighting.ProcessAfterLighting(RHICmdList, Views[ViewIndex]);
|
|
}
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
FLightShaftsOutput LightShaftOutput;
|
|
|
|
// Draw Lightshafts
|
|
if (ViewFamily.EngineShowFlags.LightShafts)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderLightShaftOcclusion);
|
|
RenderLightShaftOcclusion(RHICmdList, LightShaftOutput);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// Draw atmosphere
|
|
if (ShouldRenderAtmosphere(ViewFamily))
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderAtmosphere);
|
|
if (Scene->AtmosphericFog)
|
|
{
|
|
// Update RenderFlag based on LightShaftTexture is valid or not
|
|
if (LightShaftOutput.LightShaftOcclusion)
|
|
{
|
|
Scene->AtmosphericFog->RenderFlag &= EAtmosphereRenderFlag::E_LightShaftMask;
|
|
}
|
|
else
|
|
{
|
|
Scene->AtmosphericFog->RenderFlag |= EAtmosphereRenderFlag::E_DisableLightShaft;
|
|
}
|
|
#if WITH_EDITOR
|
|
if (Scene->bIsEditorScene)
|
|
{
|
|
// Precompute Atmospheric Textures
|
|
Scene->AtmosphericFog->PrecomputeTextures(RHICmdList, Views.GetData(), &ViewFamily);
|
|
}
|
|
#endif
|
|
RenderAtmosphere(RHICmdList, LightShaftOutput);
|
|
ServiceLocalQueue();
|
|
}
|
|
}
|
|
|
|
GRenderTargetPool.AddPhaseEvent(TEXT("Fog"));
|
|
|
|
// Draw fog.
|
|
if (ShouldRenderFog(ViewFamily))
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderFog);
|
|
RenderFog(RHICmdList, LightShaftOutput);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
IRendererModule& RendererModule = GetRendererModule();
|
|
if (RendererModule.HasPostOpaqueExtentions())
|
|
{
|
|
SceneContext.BeginRenderingSceneColor(RHICmdList);
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
|
|
RendererModule.RenderPostOpaqueExtensions(View, RHICmdList, SceneContext);
|
|
}
|
|
}
|
|
|
|
// No longer needed, release
|
|
LightShaftOutput.LightShaftOcclusion = NULL;
|
|
|
|
GRenderTargetPool.AddPhaseEvent(TEXT("Translucency"));
|
|
|
|
// Draw translucency.
|
|
if (ViewFamily.EngineShowFlags.Translucency)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_TranslucencyDrawTime);
|
|
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_Translucency));
|
|
RenderTranslucency(RHICmdList);
|
|
ServiceLocalQueue();
|
|
|
|
if(GetRefractionQuality(ViewFamily) > 0)
|
|
{
|
|
// 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.
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_RenderDistortion));
|
|
RenderDistortion(RHICmdList);
|
|
ServiceLocalQueue();
|
|
}
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_AfterTranslucency));
|
|
}
|
|
|
|
if (ViewFamily.EngineShowFlags.LightShafts)
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderLightShaftBloom);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_LightShaftBloom));
|
|
RenderLightShaftBloom(RHICmdList);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
|
|
RendererModule.RenderOverlayExtensions(View, RHICmdList, SceneContext);
|
|
}
|
|
|
|
if (ViewFamily.EngineShowFlags.VisualizeDistanceFieldAO || ViewFamily.EngineShowFlags.VisualizeDistanceFieldGI)
|
|
{
|
|
// 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 : Scene->DefaultMaxDistanceFieldOcclusionDistance;
|
|
TRefCountPtr<IPooledRenderTarget> DummyOutput;
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_RenderDistanceFieldLighting));
|
|
RenderDistanceFieldLighting(RHICmdList, FDistanceFieldAOParameters(OcclusionMaxDistance), VelocityRT, DummyOutput, DummyOutput, false, ViewFamily.EngineShowFlags.VisualizeDistanceFieldAO, ViewFamily.EngineShowFlags.VisualizeDistanceFieldGI);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// Draw visualizations just before use to avoid target contamination
|
|
if (ViewFamily.EngineShowFlags.VisualizeMeshDistanceFields || ViewFamily.EngineShowFlags.VisualizeGlobalDistanceField)
|
|
{
|
|
RenderMeshDistanceFieldVisualization(RHICmdList, FDistanceFieldAOParameters(Scene->DefaultMaxDistanceFieldOcclusionDistance));
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
if (ViewFamily.EngineShowFlags.StationaryLightOverlap &&
|
|
FeatureLevel >= ERHIFeatureLevel::SM4 &&
|
|
bUseGBuffer)
|
|
{
|
|
RenderStationaryLightOverlap(RHICmdList);
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
// Resolve the scene color for post processing.
|
|
ResolveSceneColor(RHICmdList);
|
|
|
|
GetRendererModule().RenderPostResolvedSceneColorExtension(RHICmdList, SceneContext);
|
|
|
|
CopySceneCaptureComponentToTarget(RHICmdList);
|
|
|
|
// Finish rendering for each view.
|
|
if (ViewFamily.bResolveScene)
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, PostProcessing);
|
|
SCOPED_GPU_STAT(RHICmdList, Stat_GPU_Postprocessing);
|
|
|
|
SCOPE_CYCLE_COUNTER(STAT_FinishRenderViewTargetTime);
|
|
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_PostProcessing));
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
SCOPED_CONDITIONAL_DRAW_EVENTF(RHICmdList, EventView, Views.Num() > 1, TEXT("View%d"), ViewIndex);
|
|
|
|
GPostProcessing.Process(RHICmdList, Views[ ViewIndex ], VelocityRT);
|
|
}
|
|
|
|
// End of frame, we don't need it anymore
|
|
FSceneRenderTargets::Get(RHICmdList).FreeSeparateTranslucencyDepth();
|
|
|
|
// we rendered to it during the frame, seems we haven't made use of it, because it should be released
|
|
check(!FSceneRenderTargets::Get(RHICmdList).SeparateTranslucencyRT);
|
|
}
|
|
else
|
|
{
|
|
// Release the original reference on the scene render targets
|
|
SceneContext.AdjustGBufferRefCount(RHICmdList, -1);
|
|
}
|
|
|
|
//grab the new transform out of the proxies for next frame
|
|
if (VelocityRT)
|
|
{
|
|
VelocityRT.SafeRelease();
|
|
}
|
|
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_RenderFinish);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_RenderFinish));
|
|
RenderFinish(RHICmdList);
|
|
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_AfterFrame));
|
|
}
|
|
ServiceLocalQueue();
|
|
}
|
|
|
|
/** 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)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
|
|
}
|
|
|
|
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"));
|
|
UseMaxDepth.Bind(Initializer.ParameterMap, TEXT("UseMaxDepth"));
|
|
}
|
|
FDownsampleSceneDepthPS() {}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, bool bUseMaxDepth)
|
|
{
|
|
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, GetPixelShader(), View.ViewUniformBuffer);
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
// 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.GetProjectionMatrix().M[2][2], View.ViewMatrices.GetProjectionMatrix().M[3][2]);
|
|
SetShaderValue(RHICmdList, GetPixelShader(), ProjectionScaleBias, ProjectionScaleBiasValue);
|
|
SetShaderValue(RHICmdList, GetPixelShader(), UseMaxDepth, (bUseMaxDepth ? 1.0f : 0.0f));
|
|
|
|
FIntPoint BufferSize = SceneContext.GetBufferSizeXY();
|
|
|
|
const uint32 DownsampledBufferSizeX = BufferSize.X / SceneContext.GetSmallColorDepthDownsampleFactor();
|
|
const uint32 DownsampledBufferSizeY = BufferSize.Y / SceneContext.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);
|
|
SetShaderValue(RHICmdList, GetPixelShader(), SourceTexelOffsets01, Offsets01);
|
|
const FVector4 Offsets23(0.0f, 1.0f / DownsampledBufferSizeY, 1.0f / DownsampledBufferSizeX, 1.0f / DownsampledBufferSizeY);
|
|
SetShaderValue(RHICmdList, GetPixelShader(), SourceTexelOffsets23, Offsets23);
|
|
SceneTextureParameters.Set(RHICmdList, GetPixelShader(), View);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << ProjectionScaleBias;
|
|
Ar << SourceTexelOffsets01;
|
|
Ar << SourceTexelOffsets23;
|
|
Ar << SceneTextureParameters;
|
|
Ar << UseMaxDepth;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
FShaderParameter ProjectionScaleBias;
|
|
FShaderParameter SourceTexelOffsets01;
|
|
FShaderParameter SourceTexelOffsets23;
|
|
FSceneTextureShaderParameters SceneTextureParameters;
|
|
FShaderParameter UseMaxDepth;
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FDownsampleSceneDepthPS,TEXT("DownsampleDepthPixelShader"),TEXT("Main"),SF_Pixel);
|
|
|
|
/** Updates the downsized depth buffer with the current full resolution depth buffer. */
|
|
void FDeferredShadingSceneRenderer::UpdateDownsampledDepthSurface(FRHICommandList& RHICmdList)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
if (SceneContext.UseDownsizedOcclusionQueries() && (FeatureLevel >= ERHIFeatureLevel::SM4))
|
|
{
|
|
RHICmdList.TransitionResource( EResourceTransitionAccess::EReadable, SceneContext.GetSceneDepthSurface() );
|
|
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
DownsampleDepthSurface(RHICmdList, SceneContext.GetSmallDepthSurface(), View, 1.0f / SceneContext.GetSmallColorDepthDownsampleFactor(), true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Downsample the scene depth with a specified scale factor to a specified render target
|
|
*/
|
|
void FDeferredShadingSceneRenderer::DownsampleDepthSurface(FRHICommandList& RHICmdList, const FTexture2DRHIRef& RenderTarget, const FViewInfo& View, float ScaleFactor, bool bUseMaxDepth)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
SetRenderTarget(RHICmdList, NULL, RenderTarget);
|
|
SCOPED_DRAW_EVENT(RHICmdList, DownsampleDepth);
|
|
|
|
// Set shaders and texture
|
|
TShaderMapRef<FScreenVS> ScreenVertexShader(View.ShaderMap);
|
|
TShaderMapRef<FDownsampleSceneDepthPS> PixelShader(View.ShaderMap);
|
|
|
|
extern TGlobalResource<FFilterVertexDeclaration> GFilterVertexDeclaration;
|
|
|
|
FGraphicsPipelineStateInitializer GraphicsPSOInit;
|
|
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
|
|
|
|
GraphicsPSOInit.BlendState = TStaticBlendState<CW_NONE>::GetRHI();
|
|
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<true, CF_Always>::GetRHI();
|
|
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*ScreenVertexShader);
|
|
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
|
|
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
|
|
|
|
PixelShader->SetParameters(RHICmdList, View, bUseMaxDepth);
|
|
const uint32 DownsampledX = FMath::TruncToInt(View.ViewRect.Min.X * ScaleFactor);
|
|
const uint32 DownsampledY = FMath::TruncToInt(View.ViewRect.Min.Y * ScaleFactor);
|
|
const uint32 DownsampledSizeX = FMath::TruncToInt(View.ViewRect.Width() * ScaleFactor);
|
|
const uint32 DownsampledSizeY = FMath::TruncToInt(View.ViewRect.Height() * ScaleFactor);
|
|
|
|
RHICmdList.SetViewport(DownsampledX, DownsampledY, 0.0f, DownsampledX + DownsampledSizeX, DownsampledY + DownsampledSizeY, 1.0f);
|
|
|
|
DrawRectangle(
|
|
RHICmdList,
|
|
0, 0,
|
|
DownsampledSizeX, DownsampledSizeY,
|
|
View.ViewRect.Min.X, View.ViewRect.Min.Y,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
FIntPoint(DownsampledSizeX, DownsampledSizeY),
|
|
SceneContext.GetBufferSizeXY(),
|
|
*ScreenVertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
RHICmdList.TransitionResource(EResourceTransitionAccess::EReadable, RenderTarget);
|
|
}
|
|
|
|
/** */
|
|
class FCopyStencilToLightingChannelsPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FCopyStencilToLightingChannelsPS,Global);
|
|
public:
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("STENCIL_LIGHTING_CHANNELS_SHIFT"), STENCIL_LIGHTING_CHANNELS_BIT_ID);
|
|
OutEnvironment.SetRenderTargetOutputFormat(0, PF_R16_UINT);
|
|
}
|
|
|
|
FCopyStencilToLightingChannelsPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer):
|
|
FGlobalShader(Initializer)
|
|
{
|
|
SceneStencilTexture.Bind(Initializer.ParameterMap,TEXT("SceneStencilTexture"));
|
|
}
|
|
FCopyStencilToLightingChannelsPS() {}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View)
|
|
{
|
|
FGlobalShader::SetParameters<FViewUniformShaderParameters>(RHICmdList, GetPixelShader(), View.ViewUniformBuffer);
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
SetSRVParameter(RHICmdList, GetPixelShader(), SceneStencilTexture, SceneContext.SceneStencilSRV);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << SceneStencilTexture;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
FShaderResourceParameter SceneStencilTexture;
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FCopyStencilToLightingChannelsPS,TEXT("DownsampleDepthPixelShader"),TEXT("CopyStencilToLightingChannelsPS"),SF_Pixel);
|
|
|
|
void FDeferredShadingSceneRenderer::CopyStencilToLightingChannelTexture(FRHICommandList& RHICmdList)
|
|
{
|
|
bool bAnyViewUsesLightingChannels = false;
|
|
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
bAnyViewUsesLightingChannels = bAnyViewUsesLightingChannels || View.bUsesLightingChannels;
|
|
}
|
|
|
|
if (bAnyViewUsesLightingChannels)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
SCOPED_DRAW_EVENT(RHICmdList, CopyStencilToLightingChannels);
|
|
RHICmdList.TransitionResource(EResourceTransitionAccess::EReadable, SceneContext.GetSceneDepthTexture());
|
|
|
|
SceneContext.AllocateLightingChannelTexture(RHICmdList);
|
|
|
|
// Set the light attenuation surface as the render target, and the scene depth buffer as the depth-stencil surface.
|
|
SetRenderTarget(RHICmdList, SceneContext.LightingChannels->GetRenderTargetItem().TargetableTexture, nullptr, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthNop_StencilNop, true);
|
|
|
|
FGraphicsPipelineStateInitializer GraphicsPSOInit;
|
|
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
|
|
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA>::GetRHI();
|
|
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
|
|
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
|
|
|
|
extern TGlobalResource<FFilterVertexDeclaration> GFilterVertexDeclaration;
|
|
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
|
|
|
|
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
// Set shaders and texture
|
|
TShaderMapRef<FScreenVS> ScreenVertexShader(View.ShaderMap);
|
|
TShaderMapRef<FCopyStencilToLightingChannelsPS> PixelShader(View.ShaderMap);
|
|
|
|
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*ScreenVertexShader);
|
|
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader);
|
|
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
|
|
PixelShader->SetParameters(RHICmdList, View);
|
|
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Min.X + View.ViewRect.Width(), View.ViewRect.Min.Y + View.ViewRect.Height(), 1.0f);
|
|
|
|
DrawRectangle(
|
|
RHICmdList,
|
|
0, 0,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
View.ViewRect.Min.X, View.ViewRect.Min.Y,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
FIntPoint(View.ViewRect.Width(), View.ViewRect.Height()),
|
|
SceneContext.GetBufferSizeXY(),
|
|
*ScreenVertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
}
|
|
|
|
FResolveParams ResolveParams;
|
|
|
|
RHICmdList.CopyToResolveTarget(
|
|
SceneContext.LightingChannels->GetRenderTargetItem().TargetableTexture,
|
|
SceneContext.LightingChannels->GetRenderTargetItem().TargetableTexture,
|
|
true,
|
|
ResolveParams);
|
|
}
|
|
}
|