using System.Collections.Generic ;
using System.Collections.Generic ;
using UnityEngine.Rendering ;
using System ;
using System.Diagnostics ;
readonly List < RenderPipelineMaterial > m_MaterialList = new List < RenderPipelineMaterial > ( ) ;
readonly GBufferManager m_GbufferManager = new GBufferManager ( ) ;
readonly SubsurfaceScatteringManager m_SSSBufferManager = new SubsurfaceScatteringManager ( ) ;
Material m_CopyStencilForRegularLighting ;
Material m_CopyStencilForNoLighting ;
GPUCopy m_GPUCopy ;
IBLFilterGGX m_IBLFilterGGX = null ;
m_applyDistortionKernel = m_applyDistortionCS . FindKernel ( "KMain" ) ;
m_CopyStencilForSplitLighting = CoreUtils . CreateEngineMaterial ( "Hidden/HDRenderPipeline/CopyStencilBuffer" ) ;
m_CopyStencilForSplitLighting . EnableKeyword ( "EXPORT_HTILE" ) ;
m_CopyStencilForRegularLighting = CoreUtils . CreateEngineMaterial ( "Hidden/HDRenderPipeline/CopyStencilBuffer" ) ;
m_CopyStencilForRegularLighting . DisableKeyword ( "EXPORT_HTILE" ) ;
m_CopyStencilForRegularLighting . SetInt ( HDShaderIDs . _StencilRef , ( int ) StencilLightingUsage . RegularLighting ) ;
m_CopyStencilForNoLighting = CoreUtils . CreateEngineMaterial ( "Hidden/HDRenderPipeline/CopyStencilBuffer" ) ;
m_CopyStencilForNoLighting . SetInt ( HDShaderIDs . _StencilRef , ( int ) StencilLightingUsage . NoLighting ) ;
m_CameraMotionVectorsMaterial = CoreUtils . CreateEngineMaterial ( "Hidden/HDRenderPipeline/CameraMotionVectors" ) ;
InitializeDebugMaterials ( ) ;
m_IBLFilterGGX = new IBLFilterGGX ( asset . renderPipelineResources ) ;
m_LightLoop . Build ( asset . renderPipelineResources , asset . globalRenderingSettings , asset . tile Settings, asset . globalTextureSettings , asset . shadowInitParams , m_ShadowSettings , m_IBLFilterGGX ) ;
m_LightLoop . Build ( asset . renderPipelineResources , asset . lightLoop Settings, asset . globalTextureSettings , asset . shadowInitParams , m_ShadowSettings , m_IBLFilterGGX ) ;
m_SkyManager . Build ( asset . renderPipelineResources , m_IBLFilterGGX ) ;
m_SkyManager . skySettings = skySettingsToUse ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Deferred Depth Prepass" , ( ) = > m_Asset . globalRenderingSettings . useDepthPrepassWithDeferredRendering , ( value ) = > m_Asset . globalRenderingSettings . useDepthPrepassWithDeferredRendering = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Deferred Depth Prepass ATest Only" , ( ) = > m_Asset . globalRenderingSettings . renderAlphaTestOnlyInDeferredPrepass , ( value ) = > m_Asset . globalRenderingSettings . renderAlphaTestOnlyInDeferredPrepass = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Tile/Cluster" , ( ) = > m_Asset . tileSettings . enableTileAndCluster , ( value ) = > m_Asset . tileSettings . enableTileAndCluster = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Big Tile" , ( ) = > m_Asset . tileSettings . enableBigTilePrepass , ( value ) = > m_Asset . tileSettings . enableBigTilePrepass = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Compute Lighting" , ( ) = > m_Asset . tileSettings . enableComputeLightEvaluation , ( value ) = > m_Asset . tileSettings . enableComputeLightEvaluation = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Light Classification" , ( ) = > m_Asset . tileSettings . enableComputeLightVariants , ( value ) = > m_Asset . tileSettings . enableComputeLightVariants = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Material Classification" , ( ) = > m_Asset . tileSettings . enableComputeMaterialVariants , ( value ) = > m_Asset . tileSettings . enableComputeMaterialVariants = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Tile/Cluster" , ( ) = > m_Asset . lightLoopSettings . enableTileAndCluster , ( value ) = > m_Asset . lightLoopSettings . enableTileAndCluster = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Big Tile" , ( ) = > m_Asset . lightLoopSettings . enableBigTilePrepass , ( value ) = > m_Asset . lightLoopSettings . enableBigTilePrepass = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Compute Lighting" , ( ) = > m_Asset . lightLoopSettings . enableComputeLightEvaluation , ( value ) = > m_Asset . lightLoopSettings . enableComputeLightEvaluation = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Light Classification" , ( ) = > m_Asset . lightLoopSettings . enableComputeLightVariants , ( value ) = > m_Asset . lightLoopSettings . enableComputeLightVariants = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Material Classification" , ( ) = > m_Asset . lightLoopSettings . enableComputeMaterialVariants , ( value ) = > m_Asset . lightLoopSettings . enableComputeMaterialVariants = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
DebugMenuManager . instance . AddDebugItem < bool > ( "HDRP" , "Enable Async Compute" , ( ) = > m_Asset . lightLoopSettings . enableAsyncCompute , ( value ) = > m_Asset . lightLoopSettings . enableAsyncCompute = ( bool ) value , DebugItemFlag . RuntimeOnly ) ;
}
void InitializeDebugMaterials ( )
return NeedDepthBufferCopy ( ) ? m_CameraDepthBufferCopy : m_CameraDepthStencilBuffer ;
}
RenderTargetIdentifier GetStencilTexture ( )
{
return NeedStencilBufferCopy ( ) ? m_CameraStencilBufferCopyRT : m_CameraDepthStencilBufferRT ;
}
RenderTargetIdentifier GetHTile ( )
{
// Currently, Unity does not offer a way to access the GCN HTile.
}
}
void PrepareAndBindStencilTexture ( CommandBuffer cmd )
{
if ( NeedStencilBufferCopy ( ) )
{
using ( new ProfilingSample ( cmd , "Copy StencilBuffer" , GetSampler ( CustomSamplerId . CopyStencilBuffer ) ) )
{
cmd . SetRandomWriteTarget ( 1 , GetHTile ( ) ) ;
// Our method of exporting the stencil requires one pass per unique stencil value.
CoreUtils . DrawFullScreen ( cmd , m_CopyStencilForSplitLighting , m_CameraStencilBufferCopyRT , m_CameraDepthStencilBufferRT ) ;
CoreUtils . DrawFullScreen ( cmd , m_CopyStencilForRegularLighting , m_CameraStencilBufferCopyRT , m_CameraDepthStencilBufferRT ) ;
cmd . ClearRandomWriteTargets ( ) ;
}
}
cmd . SetGlobalTexture ( HDShaderIDs . _HTile , GetHTile ( ) ) ;
cmd . SetGlobalTexture ( HDShaderIDs . _StencilTexture , GetStencilTexture ( ) ) ;
}
public void UpdateCommonSettings ( )
{
var commonSettings = commonSettingsToUse ;
m_FrameCount = Time . frameCount ;
}
foreach ( var camera in cameras )
{
// This is the main command buffer used for the frame.
var cmd = CommandBufferPool . Get ( "" ) ;
var stereoActive = UnityEngine . XR . XRSettings . isDeviceActive & & m_DebugDisplaySettings . renderingDebugSettings . allowStereo ;
using ( new ProfilingSample ( cmd , "HDRenderPipeline::Render" , GetSampler ( CustomSamplerId . HDRenderPipelineRender ) ) )
foreach ( var camera in cameras )
// This is the main command buffer used for the frame.
var cmd = CommandBufferPool . Get ( "" ) ;
foreach ( var material in m_MaterialList )
material . RenderInit ( cmd ) ;
using ( new ProfilingSample ( cmd , "HDRenderPipeline::Render" , GetSampler ( CustomSamplerId . HDRenderPipelineRender ) ) )
{
foreach ( var material in m_MaterialList )
material . RenderInit ( cmd ) ;
// Do anything we need to do upon a new frame.
m_LightLoop . NewFrame ( ) ;
// Do anything we need to do upon a new frame.
m_LightLoop . NewFrame ( ) ;
if ( camera = = null )
{
renderContext . Submit ( ) ;
continue ;
}
if ( camera = = null )
{
renderContext . Submit ( ) ;
continue ;
}
// If we render a reflection view or a preview we should not display any debug information
// This need to be call before ApplyDebugDisplaySettings()
if ( camera . cameraType = = CameraType . Reflection | | camera . cameraType = = CameraType . Preview )
{
// Neutral allow to disable all debug settings
m_CurrentDebugDisplaySettings = s_NeutralDebugDisplaySettings ;
}
else
{
m_CurrentDebugDisplaySettings = m_DebugDisplaySettings ;
// If we render a reflection view or a preview we should not display any debug information
// This need to be call before ApplyDebugDisplaySettings()
if ( camera . cameraType = = CameraType . Reflection | | camera . cameraType = = CameraType . Preview )
{
// Neutral allow to disable all debug settings
m_CurrentDebugDisplaySettings = s_NeutralDebugDisplaySettings ;
}
else
{
m_CurrentDebugDisplaySettings = m_DebugDisplaySettings ;
using ( new ProfilingSample ( cmd , "Volume Update" , GetSampler ( CustomSamplerId . VolumeUpdate ) ) )
{
// TODO: Transform & layer should be configurable per camera
VolumeManager . instance . Update ( camera . transform , - 1 ) ;
}
}
using ( new ProfilingSample ( cmd , "Volume Update" , GetSampler ( CustomSamplerId . VolumeUpdate ) ) )
{
// TODO: Transform & layer should be configurable per camera
VolumeManager . instance . Update ( camera . transform , - 1 ) ;
}
}
ApplyDebugDisplaySettings ( cmd ) ;
UpdateCommonSettings ( ) ;
ApplyDebugDisplaySettings ( cmd ) ;
UpdateCommonSettings ( ) ;
if ( ! m_IBLFilterGGX . IsInitialized ( ) )
m_IBLFilterGGX . Initialize ( cmd ) ;
if ( ! m_IBLFilterGGX . IsInitialized ( ) )
m_IBLFilterGGX . Initialize ( cmd ) ;
ScriptableCullingParameters cullingParams ;
if ( ! CullResults . GetCullingParameters ( camera , out cullingParams ) )
{
renderContext . Submit ( ) ;
continue ;
}
ScriptableCullingParameters cullingParams ;
if ( ! CullResults . GetCullingParameters ( camera , out cullingParams ) )
{
renderContext . Submit ( ) ;
continue ;
}
m_LightLoop . UpdateCullingParameters ( ref cullingParams ) ;
m_LightLoop . UpdateCullingParameters ( ref cullingParams ) ;
// emit scene view UI
if ( camera . cameraType = = CameraType . SceneView )
{
ScriptableRenderContext . EmitWorldGeometryForSceneView ( camera ) ;
}
// emit scene view UI
if ( camera . cameraType = = CameraType . SceneView )
{
ScriptableRenderContext . EmitWorldGeometryForSceneView ( camera ) ;
}
using ( new ProfilingSample ( cmd , "CullResults.Cull" , GetSampler ( CustomSamplerId . CullResultsCull ) ) )
{
CullResults . Cull ( ref cullingParams , renderContext , ref m_CullResults ) ;
}
using ( new ProfilingSample ( cmd , "CullResults.Cull" , GetSampler ( CustomSamplerId . CullResultsCull ) ) )
{
CullResults . Cull ( ref cullingParams , renderContext , ref m_CullResults ) ;
}
Resize ( camera ) ;
var postProcessLayer = camera . GetComponent < PostProcessLayer > ( ) ;
var hdCamera = HDCamera . Get ( camera , postProcessLayer , m_Asset . globalRenderingSettings , stereoActive ) ;
m_LightLoop . UpdateRenderingPathState ( hdCamera . useForwardOnly ) ;
renderContext . SetupCameraProperties ( camera ) ;
Resize ( camera ) ;
var postProcessLayer = camera . GetComponent < PostProcessLayer > ( ) ;
var hdCamera = HDCamera . Get ( camera , postProcessLayer ) ;
PushGlobalParams ( hdCamera , cmd , sssSettings ) ;
renderContext . SetupCameraProperties ( camera ) ;
// TODO: Find a correct place to bind these material textures
// We have to bind the material specific global parameters in this mode
m_MaterialList . ForEach ( material = > material . Bind ( ) ) ;
PushGlobalParams ( hdCamera , cmd , sssSettings ) ;
var additionalCameraData = camera . GetComponent < HDAdditionalCameraData > ( ) ;
if ( additionalCameraData & & additionalCameraData . renderingPath = = RenderingPathHDRP . Unlit )
{
// TODO: Add another path dedicated to planar reflection / real time cubemap that implement simpler lighting
// It is up to the users to only send unlit object for this camera path
// TODO: Find a correct place to bind these material textures
// We have to bind the material specific global parameters in this mode
m_MaterialList . ForEach ( material = > material . Bind ( ) ) ;
using ( new ProfilingSample ( cmd , "Forward" , GetSampler ( CustomSamplerId . Forward ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT , ClearFlag . Color | ClearFlag . Depth ) ;
RenderOpaqueRenderList ( m_CullResults , camera , renderContext , cmd , HDShaderPassNames . s_ForwardName ) ;
RenderTransparentRenderList ( m_CullResults , camera , renderContext , cmd , HDShaderPassNames . s_ForwardName , false ) ;
}
var additionalCameraData = camera . GetComponent < HDAdditionalCameraData > ( ) ;
if ( additionalCameraData & & additionalCameraData . renderingPath = = RenderingPathHDRP . Unlit )
{
// TODO: Add another path dedicated to planar reflection / real time cubemap that implement simpler lighting
// It is up to the users to only send unlit object for this camera path
renderContext . ExecuteCommandBuffer ( cmd ) ;
CommandBufferPool . Release ( cmd ) ;
renderContext . Submit ( ) ;
continue ;
}
using ( new ProfilingSample ( cmd , "Forward" , GetSampler ( CustomSamplerId . Forward ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT , ClearFlag . Color | ClearFlag . Depth ) ;
RenderOpaqueRenderList ( m_CullResults , camera , renderContext , cmd , HDShaderPassNames . s_ForwardName ) ;
RenderTransparentRenderList ( m_CullResults , camera , renderContext , cmd , HDShaderPassNames . s_ForwardName , false ) ;
}
// Note: Legacy Unity behave like this for ShadowMask
// When you select ShadowMask in Lighting panel it recompile shaders on the fly with the SHADOW_MASK keyword.
// However there is no C# function that we can query to know what mode have been select in Lighting Panel and it will be wrong anyway. Lighting Panel setup what will be the next bake mode. But until light is bake, it is wrong.
// Currently to know if you need shadow mask you need to go through all visible lights (of CullResult), check the LightBakingOutput struct and look at lightmapBakeType/mixedLightingMode. If one light have shadow mask bake mode, then you need shadow mask features (i.e extra Gbuffer).
// It mean that when we build a standalone player, if we detect a light with bake shadow mask, we generate all shader variant (with and without shadow mask) and at runtime, when a bake shadow mask light is visible, we dynamically allocate an extra GBuffer and switch the shader.
// So the first thing to do is to go through all the light: PrepareLightsForGPU
bool enableBakeShadowMask ;
using ( new ProfilingSample ( cmd , "TP_PrepareLightsForGPU" , GetSampler ( CustomSamplerId . TPPrepareLightsForGPU ) ) )
{
enableBakeShadowMask = m_LightLoop . PrepareLightsForGPU ( cmd , m_ShadowSettings , m_CullResults , camera ) ;
}
ConfigureForShadowMask ( enableBakeShadowMask , cmd ) ;
renderContext . ExecuteCommandBuffer ( cmd ) ;
CommandBufferPool . Release ( cmd ) ;
renderContext . Submit ( ) ;
continue ;
}
InitAndClearBuffer ( hdCamera , enableBakeShadowMask , cmd ) ;
RenderDepthPrepass ( m_CullResults , camera , renderContext , cmd ) ;
// Note: Legacy Unity behave like this for ShadowMask
// When you select ShadowMask in Lighting panel it recompile shaders on the fly with the SHADOW_MASK keyword.
// However there is no C# function that we can query to know what mode have been select in Lighting Panel and it will be wrong anyway. Lighting Panel setup what will be the next bake mode. But until light is bake, it is wrong.
// Currently to know if you need shadow mask you need to go through all visible lights (of CullResult), check the LightBakingOutput struct and look at lightmapBakeType/mixedLightingMode. If one light have shadow mask bake mode, then you need shadow mask features (i.e extra Gbuffer).
// It mean that when we build a standalone player, if we detect a light with bake shadow mask, we generate all shader variant (with and without shadow mask) and at runtime, when a bake shadow mask light is visible, we dynamically allocate an extra GBuffer and switch the shader.
// So the first thing to do is to go through all the light: PrepareLightsForGPU
bool enableBakeShadowMask ;
using ( new ProfilingSample ( cmd , "TP_PrepareLightsForGPU" , GetSampler ( CustomSamplerId . TPPrepareLightsForGPU ) ) )
{
enableBakeShadowMask = m_LightLoop . PrepareLightsForGPU ( cmd , m_ShadowSettings , m_CullResults , camera ) ;
}
ConfigureForShadowMask ( enableBakeShadowMask , cmd ) ;
RenderGBuffer ( m_CullResults , camera , renderContext , cmd ) ;
InitAndClearBuffer ( hdCamera , enableBakeShadowMask , cmd ) ;
// In both forward and deferred, everything opaque should have been rendered at this point so we can safely copy the depth buffer for later processing.
CopyDepthBufferIfNeeded ( cmd ) ;
RenderDepthPrepass ( m_CullResults , hdCamera , renderContext , cmd ) ;
RenderPyramidDepth ( camera , cmd , renderContext , FullScreenDebugMode . DepthPyramid ) ;
RenderGBuffer ( m_CullResults , hdCamera , renderContext , cmd ) ;
// Required for the SSS and the shader feature classification pass.
PrepareAndBindStencilTexture ( cmd ) ;
// In both forward and deferred, everything opaque should have been rendered at this point so we can safely copy the depth buffer for later processing.
CopyDepthBufferIfNeeded ( cmd ) ;
if ( m_CurrentDebugDisplaySettings . IsDebugMaterialDisplayEnabled ( ) )
{
RenderDebugViewMaterial ( m_CullResults , hdCamera , renderContext , cmd ) ;
}
else
{
using ( new ProfilingSample ( cmd , "Render SSAO" , GetSampler ( CustomSamplerId . RenderSSAO ) ) )
{
// TODO: Everything here (SSAO, Shadow, Build light list, deferred shadow, material and light classification can be parallelize with Async compute)
RenderSSAO ( cmd , camera , renderContext , postProcessLayer ) ;
}
RenderPyramidDepth ( camera , cmd , renderContext , FullScreenDebugMode . DepthPyramid ) ;
using ( new ProfilingSample ( cmd , "Render shadows" , GetSampler ( CustomSamplerId . RenderShadows ) ) )
if ( m_CurrentDebugDisplaySettings . IsDebugMaterialDisplayEnabled ( ) )
{
RenderDebugViewMaterial ( m_CullResults , hdCamera , renderContext , cmd ) ;
}
else
m_LightLoop . RenderShadows ( renderContext , cmd , m_CullResults ) ;
// TODO: check if statement below still apply
renderContext . SetupCameraProperties ( camera ) ; // Need to recall SetupCameraProperties after RenderShadows as it modify our view/proj matrix
}
using ( new ProfilingSample ( cmd , "Render SSAO" , GetSampler ( CustomSamplerId . RenderSSAO ) ) )
{
// TODO: Everything here (SSAO, Shadow, Build light list, deferred shadow, material and light classification can be parallelize with Async compute)
RenderSSAO ( cmd , camera , renderContext , postProcessLayer ) ;
}
using ( new ProfilingSample ( cmd , "Deferred directional shadows" , GetSampler ( CustomSamplerId . RenderDeferredDirectionalShadow ) ) )
{
cmd . ReleaseTemporaryRT ( m_DeferredShadowBuffer ) ;
cmd . GetTemporaryRT ( m_DeferredShadowBuffer , camera . pixelWidth , camera . pixelHeight , 0 , FilterMode . Point , RenderTextureFormat . ARGB32 , RenderTextureReadWrite . Linear , 1 , true ) ;
m_LightLoop . RenderDeferredDirectionalShadow ( hdCamera , m_DeferredShadowBufferRT , GetDepthTexture ( ) , cmd ) ;
PushFullScreenDebugTexture ( cmd , m_DeferredShadowBuffer , hdCamera . camera , renderContext , FullScreenDebugMode . DeferredShadows ) ;
}
bool enableAsyncCompute = m_LightLoop . IsAsyncEnabled ( ) ;
GPUFence buildGPULightListsCompleteFence = new GPUFence ( ) ;
if ( enableAsyncCompute )
{
GPUFence startFence = cmd . CreateGPUFence ( ) ;
renderContext . ExecuteCommandBuffer ( cmd ) ;
CommandBufferPool . Release ( cmd ) ;
cmd = CommandBufferPool . Get ( "" ) ;
using ( new ProfilingSample ( cmd , "Build Light list" , GetSampler ( CustomSamplerId . BuildLightList ) ) )
{
m_LightLoop . BuildGPULightLists ( camera , cmd , m_CameraDepthStencilBufferRT , GetStencilTexture ( ) ) ;
}
buildGPULightListsCompleteFence = m_LightLoop . BuildGPULightListsAsyncBegin ( camera , renderContext , m_CameraDepthStencilBufferRT , m_CameraStencilBufferCopyRT , startFence ) ;
}
// Caution: We require sun light here as some sky use the sun light to render, mean UpdateSkyEnvironment
// must be call after BuildGPULightLists.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
UpdateSkyEnvironment ( hdCamera , cmd ) ;
using ( new ProfilingSample ( cmd , "Render shadows" , GetSampler ( CustomSamplerId . RenderShadows ) ) )
{
m_LightLoop . RenderShadows ( renderContext , cmd , m_CullResults ) ;
// TODO: check if statement below still apply
renderContext . SetupCameraProperties ( camera ) ; // Need to recall SetupCameraProperties after RenderShadows as it modify our view/proj matrix
}
RenderDeferredLighting ( hdCamera , cmd ) ;
using ( new ProfilingSample ( cmd , "Deferred directional shadows" , GetSampler ( CustomSamplerId . RenderDeferredDirectionalShadow ) ) )
{
cmd . ReleaseTemporaryRT ( m_DeferredShadowBuffer ) ;
cmd . GetTemporaryRT ( m_DeferredShadowBuffer , camera . pixelWidth , camera . pixelHeight , 0 , FilterMode . Point , RenderTextureFormat . ARGB32 , RenderTextureReadWrite . Linear , 1 , true ) ;
m_LightLoop . RenderDeferredDirectionalShadow ( hdCamera , m_DeferredShadowBufferRT , GetDepthTexture ( ) , cmd ) ;
PushFullScreenDebugTexture ( cmd , m_DeferredShadowBuffer , hdCamera . camera , renderContext , FullScreenDebugMode . DeferredShadows ) ;
}
// We compute subsurface scattering here. Therefore, no objects rendered afterwards will exhibit SSS.
// Currently, there is no efficient way to switch between SRT and MRT for the forward pass;
// therefore, forward-rendered objects do not output split lighting required for the SSS pass.
SubsurfaceScatteringPass ( hdCamera , cmd , sssSettings ) ;
// TODO: Move this code inside LightLoop
if ( m_LightLoop . GetFeatureVariantsEnabled ( ) )
{
// For material classification we use compute shader and so can't read into the stencil, so prepare it.
using ( new ProfilingSample ( cmd , "Clear and copy stencil texture" , GetSampler ( CustomSamplerId . ClearAndCopyStencilTexture ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraStencilBufferCopyRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
RenderForward ( m_CullResults , camera , renderContext , cmd , ForwardPass . Opaque ) ;
RenderForwardError ( m_CullResults , camera , renderContext , cmd , ForwardPass . Opaque ) ;
cmd . SetRandomWriteTarget ( 1 , GetHTile ( ) ) ;
// In the material classification shader we will simply test is we are no lighting
// Use ShaderPassID 1 => "Pass 1 - Write 1 if value different from stencilRef to output"
CoreUtils . DrawFullScreen ( cmd , m_CopyStencilForNoLighting , m_CameraStencilBufferCopyRT , m_CameraDepthStencilBufferRT , null , 1 ) ;
cmd . ClearRandomWriteTargets ( ) ;
}
}
RenderSky ( hdCamera , cmd ) ;
if ( enableAsyncCompute )
{
m_LightLoop . BuildGPULightListAsyncEnd ( camera , cmd , buildGPULightListsCompleteFence ) ;
}
else
{
using ( new ProfilingSample ( cmd , "Build Light list" , GetSampler ( CustomSamplerId . BuildLightList ) ) )
{
m_LightLoop . BuildGPULightLists ( camera , cmd , m_CameraDepthStencilBufferRT , m_CameraStencilBufferCopyRT ) ;
}
}
// Render pre refraction objects
RenderForward ( m_CullResults , camera , renderContext , cmd , ForwardPass . PreRefraction ) ;
RenderForwardError ( m_CullResults , camera , renderContext , cmd , ForwardPass . PreRefraction ) ;
// Caution: We require sun light here as some sky use the sun light to render, mean UpdateSkyEnvironment
// must be call after BuildGPULightLists.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
UpdateSkyEnvironment ( hdCamera , cmd ) ;
RenderGaussianPyramidColor ( camera , cmd , renderContext , FullScreenDebugMode . PreRefractionColorPyramid ) ;
RenderDeferredLighting ( hdCamera , cmd ) ;
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward ( m_CullResults , camera , renderContext , cmd , ForwardPass . Transparent ) ;
RenderForwardError ( m_CullResults , camera , renderContext , cmd , ForwardPass . Transparent ) ;
RenderForward ( m_CullResults , hdCamera , renderContext , cmd , ForwardPass . Opaque ) ;
RenderForwardError ( m_CullResults , camera , renderContext , cmd , ForwardPass . Opaque ) ;
PushFullScreenDebugTexture ( cmd , m_CameraColorBuffer , camera , renderContext , FullScreenDebugMode . NanTracker ) ;
// SSS pass here handle both SSS material from deferred and forward
SubsurfaceScatteringPass ( hdCamera , cmd , sssSettings ) ;
// Planar and real time cubemap doesn't need post process and render in FP16
if ( camera . cameraType = = CameraType . Reflection )
{
using ( new ProfilingSample ( cmd , "Blit to final RT" , GetSampler ( CustomSamplerId . BlitToFinalRT ) ) )
{
// Simple blit
cmd . Blit ( m_CameraColorBufferRT , BuiltinRenderTextureType . CameraTarget ) ;
}
}
else
{
RenderVelocity ( m_CullResults , hdCamera , renderContext , cmd ) ; // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?
RenderSky ( hdCamera , cmd ) ;
// Render pre refraction objects
RenderForward ( m_CullResults , hdCamera , renderContext , cmd , ForwardPass . PreRefraction ) ;
RenderForwardError ( m_CullResults , camera , renderContext , cmd , ForwardPass . PreRefraction ) ;
RenderGaussianPyramidColor ( camera , cmd , renderContext , FullScreenDebugMode . PreRefractionColorPyramid ) ;
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward ( m_CullResults , hdCamera , renderContext , cmd , ForwardPass . Transparent ) ;
RenderForwardError ( m_CullResults , camera , renderContext , cmd , ForwardPass . Transparent ) ;
PushFullScreenDebugTexture ( cmd , m_CameraColorBuffer , camera , renderContext , FullScreenDebugMode . NanTracker ) ;
// Planar and real time cubemap doesn't need post process and render in FP16
if ( camera . cameraType = = CameraType . Reflection )
{
using ( new ProfilingSample ( cmd , "Blit to final RT" , GetSampler ( CustomSamplerId . BlitToFinalRT ) ) )
{
// Simple blit
cmd . Blit ( m_CameraColorBufferRT , BuiltinRenderTextureType . CameraTarget ) ;
}
}
else
{
RenderVelocity ( m_CullResults , hdCamera , renderContext , cmd ) ; // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?
RenderGaussianPyramidColor ( camera , cmd , renderContext , FullScreenDebugMode . FinalColorPyramid ) ;
RenderGaussianPyramidColor ( camera , cmd , renderContext , FullScreenDebugMode . FinalColorPyramid ) ;
// TODO: Check with VFX team.
// Rendering distortion here have off course lot of artifact.
// But resolving at each objects that write in distortion is not possible (need to sort transparent, render those that do not distort, then resolve, then etc...)
// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness.
AccumulateDistortion ( m_CullResults , camera , renderContext , cmd ) ;
RenderDistortion ( cmd , m_Asset . renderPipelineResources ) ;
// TODO: Check with VFX team.
// Rendering distortion here have off course lot of artifact.
// But resolving at each objects that write in distortion is not possible (need to sort transparent, render those that do not distort, then resolve, then etc...)
// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness.
AccumulateDistortion ( m_CullResults , camera , renderContext , cmd ) ;
RenderDistortion ( cmd , m_Asset . renderPipelineResources ) ;
RenderPostProcesses ( hdCamera , cmd , postProcessLayer ) ;
}
}
RenderPostProcesses ( hdCamera , cmd , postProcessLayer ) ;
}
}
RenderDebug ( hdCamera , cmd ) ;
RenderDebug ( hdCamera , cmd ) ;
// Make sure to unbind every render texture here because in the next iteration of the loop we might have to reallocate render texture (if the camera size is different)
cmd . SetRenderTarget ( new RenderTargetIdentifier ( - 1 ) , new RenderTargetIdentifier ( - 1 ) ) ;
// Make sure to unbind every render texture here because in the next iteration of the loop we might have to reallocate render texture (if the camera size is different)
cmd . SetRenderTarget ( new RenderTargetIdentifier ( - 1 ) , new RenderTargetIdentifier ( - 1 ) ) ;
// We still need to bind correctly default camera target with our depth buffer in case we are currently rendering scene view. It should be the last camera here
// We still need to bind correctly default camera target with our depth buffer in case we are currently rendering scene view. It should be the last camera here
// bind depth surface for editor grid/gizmo/selection rendering
if ( camera . cameraType = = CameraType . SceneView )
cmd . SetRenderTarget ( BuiltinRenderTextureType . CameraTarget , m_CameraDepthStencilBufferRT ) ;
// bind depth surface for editor grid/gizmo/selection rendering
if ( camera . cameraType = = CameraType . SceneView )
cmd . SetRenderTarget ( BuiltinRenderTextureType . CameraTarget , m_CameraDepthStencilBufferRT ) ;
}
renderContext . ExecuteCommandBuffer ( cmd ) ;
}
// Caution: ExecuteCommandBuffer must be outside of the profiling bracket
renderContext . ExecuteCommandBuffer ( cmd ) ;
CommandBufferPool . Release ( cmd ) ;
renderContext . Submit ( ) ;
CommandBufferPool . Release ( cmd ) ;
renderContext . Submit ( ) ;
} // For each camera
}
// Forward only renderer: We always render everything
// Deferred renderer: We render a depth prepass only if engine request it. We can decide if we render everything or only opaque alpha tested object.
// Forward opaque with deferred renderer (DepthForwardOnly pass): We always render everything
void RenderDepthPrepass ( CullResults cull , Camera c amera, ScriptableRenderContext renderContext , CommandBuffer cmd )
void RenderDepthPrepass ( CullResults cull , HDCamera hdC amera, ScriptableRenderContext renderContext , CommandBuffer cmd )
{
// In case of deferred renderer, we can have forward opaque material. These materials need to be render in the depth buffer to correctly build the light list.
// And they will tag the stencil to not be lit during the deferred lighting pass.
// It must also have a "DepthForwardOnly" and no "DepthOnly" pass as forward material (either deferred or forward only rendering) have always a depth pass.
// In case of forward only rendering we have a depth prepass. In case of deferred renderer, it is optional
bool addFullDepthPrepass = m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) | | m_Asset . globalRenderingSettings . useDepthPrepassWithDeferredRendering ;
bool addAlphaTestedOnly = ! m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) & & m_Asset . globalRenderingSettings . useDepthPrepassWithDeferredRendering & & m_Asset . globalRenderingSettings . renderAlphaTestOnlyInDeferredPrepass ;
bool addFullDepthPrepass = hdCamera . useForwardOnly | | m_Asset . globalRenderingSettings . useDepthPrepassWithDeferredRendering ;
bool addAlphaTestedOnly = ! hdCamera . useForwardOnly & & m_Asset . globalRenderingSettings . useDepthPrepassWithDeferredRendering & & m_Asset . globalRenderingSettings . renderAlphaTestOnlyInDeferredPrepass ;
var camera = hdCamera . camera ;
using ( new ProfilingSample ( cmd , addAlphaTestedOnly ? "Depth Prepass alpha test" : "Depth Prepass" , GetSampler ( CustomSamplerId . DepthPrepass ) ) )
{
// RenderGBuffer do the gbuffer pass. This is solely call with deferred. If we use a depth prepass, then the depth prepass will perform the alpha testing for opaque apha tested and we don't need to do it anymore
// during Gbuffer pass. This is handled in the shader and the depth test (equal and no depth write) is done here.
void RenderGBuffer ( CullResults cull , Camera camera , ScriptableRenderContext renderContext , CommandBuffer cmd )
void RenderGBuffer ( CullResults cull , HDCamera hdCamera , ScriptableRenderContext renderContext , CommandBuffer cmd )
if ( m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) )
if ( hdCamera . useForwardOnly )
var camera = hdCamera . camera ;
using ( new ProfilingSample ( cmd , m_CurrentDebugDisplaySettings . IsDebugDisplayEnabled ( ) ? "GBufferDebugDisplay" : "GBuffer" , GetSampler ( CustomSamplerId . GBuffer ) ) )
{
void RenderDeferredLighting ( HDCamera hdCamera , CommandBuffer cmd )
{
if ( m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) )
if ( hdCamera . useForwardOnly )
return ;
m_MRTCache2 [ 0 ] = m_CameraColorBufferRT ;
// Combines specular lighting and diffuse lighting with subsurface scattering.
void SubsurfaceScatteringPass ( HDCamera hdCamera , CommandBuffer cmd , SubsurfaceScatteringSettings sssParameters )
{
// Currently, forward-rendered objects do not output split lighting required for the SSS pass.
if ( ! m_CurrentDebugDisplaySettings . renderingDebugSettings . enableSSSAndTransmission | | m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) )
if ( ! m_CurrentDebugDisplaySettings . renderingDebugSettings . enableSSSAndTransmission )
return ;
using ( new ProfilingSample ( cmd , "Subsurface Scattering" , GetSampler ( CustomSamplerId . SubsurfaceScattering ) ) )
using ( new ProfilingSample ( cmd , "HTile for SSS" , GetSampler ( CustomSamplerId . HTileForSSS ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_HTileRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
cmd . SetRandomWriteTarget ( 1 , GetHTile ( ) ) ;
// Generate HTile for the split lighting stencil usage. Don't write into stencil texture (shaderPassId = 2)
// Use ShaderPassID 1 => "Pass 2 - Export HTILE for stencilRef to output"
CoreUtils . DrawFullScreen ( cmd , m_CopyStencilForSplitLighting , m_CameraStencilBufferCopyRT , m_CameraDepthStencilBufferRT , null , 2 ) ;
cmd . ClearRandomWriteTargets ( ) ;
}
// TODO: Remove this once fix, see comment inside the function
hdCamera . SetupComputeShader ( m_SubsurfaceScatteringCS , cmd ) ;
cmd . SetComputeFloatParam ( m_SubsurfaceScatteringCS , HDShaderIDs . _TexturingModeFlags , * ( float * ) & texturingModeFlags ) ;
}
cmd . SetComputeVectorArrayParam ( m_SubsurfaceScatteringCS , HDShaderIDs . _FilterKernels , sssParameters . filterKernels ) ;
cmd . SetComputeVectorArrayParam ( m_SubsurfaceScatteringCS , HDShaderIDs . _WorldScales , sssParameters . worldScales ) ;
cmd . SetComputeVectorArrayParam ( m_SubsurfaceScatteringCS , HDShaderIDs . _FilterKernels , sssParameters . filterKernels ) ;
cmd . SetComputeVectorArrayParam ( m_SubsurfaceScatteringCS , HDShaderIDs . _ShapeParams , sssParameters . shapeParams ) ;
cmd . SetComputeTextureParam ( m_SubsurfaceScatteringCS , m_SubsurfaceScatteringKernel , HDShaderIDs . _GBufferTexture0 , m_GbufferManager . GetGBuffers ( ) [ 0 ] ) ;
cmd . SetComputeTextureParam ( m_SubsurfaceScatteringCS , m_SubsurfaceScatteringKernel , HDShaderIDs . _GBufferTexture1 , m_GbufferManager . GetGBuffers ( ) [ 1 ] ) ;
cmd . SetComputeTextureParam ( m_SubsurfaceScatteringCS , m_SubsurfaceScatteringKernel , HDShaderIDs . _GBufferTexture2 , m_GbufferManager . GetGBuffers ( ) [ 2 ] ) ;
cmd . SetComputeTextureParam ( m_SubsurfaceScatteringCS , m_SubsurfaceScatteringKernel , HDShaderIDs . _GBufferTexture3 , m_GbufferManager . GetGBuffers ( ) [ 3 ] ) ;
for ( int i = 0 ; i < m_SSSBufferManager . sssBufferCount ; + + i )
{
cmd . SetComputeTextureParam ( m_SubsurfaceScatteringCS , m_SubsurfaceScatteringKernel , HDShaderIDs . _SSSBufferTexture [ i ] , m_SSSBufferManager . GetSSSBuffers ( i ) ) ;
}
if ( NeedTemporarySubsurfaceBuffer ( ) )
{
}
else
{
for ( int i = 0 ; i < m_SSSBufferManager . sssBufferCount ; + + i )
{
cmd . SetGlobalTexture ( HDShaderIDs . _SSSBufferTexture [ i ] , m_SSSBufferManager . GetSSSBuffers ( i ) ) ;
}
cmd . SetGlobalTexture ( HDShaderIDs . _IrradianceSource , m_CameraSssDiffuseLightingBufferRT ) ; // Cannot set a RT on a material
m_SssVerticalFilterPass . SetVectorArray ( HDShaderIDs . _FilterKernelsBasic , sssParameters . filterKernelsBasic ) ;
m_SssVerticalFilterPass . SetVectorArray ( HDShaderIDs . _HalfRcpWeightedVariances , sssParameters . halfRcpWeightedVariances ) ;
}
// Render forward is use for both transparent and opaque objects. In case of deferred we can still render opaque object in forward.
void RenderForward ( CullResults cullResults , Camera c amera, ScriptableRenderContext renderContext , CommandBuffer cmd , ForwardPass pass )
void RenderForward ( CullResults cullResults , HDCamera hdC amera, ScriptableRenderContext renderContext , CommandBuffer cmd , ForwardPass pass )
{
// Guidelines: In deferred by default there is no opaque in forward. However it is possible to force an opaque material to render in forward
// by using the pass "ForwardOnly". In this case the .shader should not have "Forward" but only a "ForwardOnly" pass.
using ( new ProfilingSample ( cmd , profileName , GetSampler ( CustomSamplerId . ForwardPassName ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT ) ;
var camera = hdCamera . camera ;
// In case of forward SSS we will bind all the required target. It is up to the shader to write into it or not.
if ( m_CurrentDebugDisplaySettings . renderingDebugSettings . enableSSSAndTransmission )
{
RenderTargetIdentifier [ ] m_MRTWithSSS = new RenderTargetIdentifier [ 2 + m_SSSBufferManager . sssBufferCount ] ;
m_MRTWithSSS [ 0 ] = m_CameraColorBufferRT ; // Store the specular color
m_MRTWithSSS [ 1 ] = m_CameraSssDiffuseLightingBufferRT ;
for ( int i = 0 ; i < m_SSSBufferManager . sssBufferCount ; + + i )
{
m_MRTWithSSS [ i + 2 ] = m_SSSBufferManager . GetSSSBuffers ( i ) ;
}
CoreUtils . SetRenderTarget ( cmd , m_MRTWithSSS , m_CameraDepthStencilBufferRT ) ;
}
else
{
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT ) ;
}
if ( m_CurrentDebugDisplaySettings . IsDebugDisplayEnabled ( ) )
{
m_ForwardAndForwardOnlyPassNames [ 0 ] = m_ForwardOnlyPassNames [ 0 ] = HDShaderPassNames . s_ForwardOnlyDebugDisplayName ;
m_ForwardAndForwardOnlyPassNames [ 1 ] = HDShaderPassNames . s_ForwardName ;
}
var passNames = m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) ? m_ForwardAndForwardOnlyPassNames : m_ForwardOnlyPassNames ;
var passNames = hdCamera . useForwardOnly ? m_ForwardAndForwardOnlyPassNames : m_ForwardOnlyPassNames ;
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT ) ;
var passNames = m_CurrentDebugDisplaySettings . IsDebugDisplayEnabled ( ) ? m_AllTransparentDebugDisplayPassNames : m_AllTransparentPassNames ;
RenderTransparentRenderList ( cullResults , camera , renderContext , cmd , passNames , pass = = ForwardPass . PreRefraction , m_currentRendererConfigurationBakedLighting ) ;
}
cmd . GetTemporaryRT ( m_DepthPyramidBuffer , m_DepthPyramidBufferDesc , FilterMode . Trilinear ) ;
// End
if ( ! m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) )
if ( ! camera . useForwardOnly )
{
m_SSSBufferManager . InitGBuffers ( w , h , m_GbufferManager , cmd ) ;
}
else
{
// We need to allocate target for SSS
m_SSSBufferManager . InitGBuffers ( w , h , cmd ) ;
}
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT , ClearFlag . Depth ) ;
}
}
// <<< Old SSS Model
if ( NeedStencilBufferCopy ( ) )
{
using ( new ProfilingSample ( cmd , "Clear stencil texture" , GetSampler ( CustomSamplerId . ClearStencilTexture ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraStencilBufferCopyRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
}
}
if ( NeedHTileCopy ( ) )
{
using ( new ProfilingSample ( cmd , "Clear HTile" , GetSampler ( CustomSamplerId . ClearHTile ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_HTileRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
}
}
// TODO: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.
// Clear the HDR target
}
// Clear GBuffers
if ( ! m_Asset . globalRenderingSettings . ShouldUseForwardRenderingOnly ( ) )
if ( ! camera . useForwardOnly )
{
using ( new ProfilingSample ( cmd , "Clear GBuffer" , GetSampler ( CustomSamplerId . ClearGBuffer ) ) )
{