using UnityEngine.Rendering ;
using System ;
using System.Diagnostics ;
using System.Linq ;
using UnityEngine.Profiling ;
#if UNITY_EDITOR
using UnityEditor ;
#endif
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
RenderTargetIdentifier m_CameraDepthBufferCopyRT ;
RenderTargetIdentifier m_CameraStencilBufferCopyRT ;
static CustomSampler [ ] m_samplers = new CustomSampler [ ( int ) CustomSamplerId . Max ] ;
// The pass "SRPDefaultUnlit" is a fall back to legacy unlit rendering and is required to support unity 2d + unity UI that render in the scene.
ShaderPassName [ ] m_ForwardAndForwardOnlyPassNames = { new ShaderPassName ( ) , new ShaderPassName ( ) , HDShaderPassNames . s_SRPDefaultUnlitName } ;
ShaderPassName [ ] m_ForwardOnlyPassNames = { new ShaderPassName ( ) , HDShaderPassNames . s_SRPDefaultUnlitName } ;
int m_DebugFullScreenTempRT ;
bool m_FullScreenDebugPushed ;
static public CustomSampler GetSampler ( CustomSamplerId id )
{
return m_samplers [ ( int ) id ] ;
}
public HDRenderPipeline ( HDRenderPipelineAsset asset )
{
SetRenderingFeatures ( ) ;
FrameSettings . RegisterDebug ( "Default Camera" , m_Asset . GetFrameSettings ( ) ) ;
m_DebugFullScreenTempRT = HDShaderIDs . _DebugFullScreenTexture ;
// Init all samplers
for ( int i = 0 ; i < ( int ) CustomSamplerId . Max ; i + + )
{
CustomSamplerId id = ( CustomSamplerId ) i ;
m_samplers [ i ] = CustomSampler . Create ( "C#_" + id . ToString ( ) ) ;
}
InitializeRenderStateBlocks ( ) ;
}
public void PushGlobalParams ( HDCamera hdCamera , CommandBuffer cmd , DiffusionProfileSettings sssParameters )
{
using ( new ProfilingSample ( cmd , "Push Global Parameters" , GetSampler ( CustomSamplerId . PushGlobalParameters ) ) )
using ( new ProfilingSample ( cmd , "Push Global Parameters" , CustomSamplerId . PushGlobalParameters . GetSampler ( ) ) )
{
hdCamera . SetupGlobalParams ( cmd ) ;
void CopyDepthBufferIfNeeded ( CommandBuffer cmd )
{
using ( new ProfilingSample ( cmd , NeedDepthBufferCopy ( ) ? "Copy DepthBuffer" : "Set DepthBuffer" , GetSampler ( CustomSamplerId . CopySetDepthBuffer ) ) )
using ( new ProfilingSample ( cmd , NeedDepthBufferCopy ( ) ? "Copy DepthBuffer" : "Set DepthBuffer" , CustomSamplerId . CopySetDepthBuffer . GetSampler ( ) ) )
using ( new ProfilingSample ( cmd , "Copy depth-stencil buffer" , GetSampler ( CustomSamplerId . CopyDepthStencilbuffer ) ) )
using ( new ProfilingSample ( cmd , "Copy depth-stencil buffer" , CustomSamplerId . CopyDepthStencilbuffer . GetSampler ( ) ) )
{
cmd . CopyTexture ( m_CameraDepthStencilBufferRT , m_CameraDepthBufferCopyRT ) ;
}
foreach ( var material in m_MaterialList )
material . RenderInit ( cmd ) ;
using ( new ProfilingSample ( cmd , "HDRenderPipeline::Render" , GetSampler ( CustomSamplerId . HDRenderPipelineRender ) ) )
using ( new ProfilingSample ( cmd , "HDRenderPipeline::Render" , CustomSamplerId . HDRenderPipelineRender . GetSampler ( ) ) )
{
// Do anything we need to do upon a new frame.
m_LightLoop . NewFrame ( m_FrameSettings ) ;
{
m_CurrentDebugDisplaySettings = m_DebugDisplaySettings ;
using ( new ProfilingSample ( cmd , "Volume Update" , GetSampler ( CustomSamplerId . VolumeUpdate ) ) )
using ( new ProfilingSample ( cmd , "Volume Update" , CustomSamplerId . VolumeUpdate . GetSampler ( ) ) )
{
LayerMask layerMask = - 1 ;
if ( additionalCameraData ! = null )
if ( m_FrameSettings . enableDBuffer )
DecalSystem . instance . BeginCull ( camera ) ;
using ( new ProfilingSample ( cmd , "CullResults.Cull" , GetSampler ( CustomSamplerId . CullResultsCull ) ) )
using ( new ProfilingSample ( cmd , "CullResults.Cull" , CustomSamplerId . CullResultsCull . GetSampler ( ) ) )
{
CullResults . Cull ( ref cullingParams , renderContext , ref m_CullResults ) ;
}
// 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
using ( new ProfilingSample ( cmd , "Forward" , GetSampler ( CustomSamplerId . Forward ) ) )
using ( new ProfilingSample ( cmd , "Forward" , CustomSamplerId . Forward . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT , ClearFlag . Color | ClearFlag . Depth ) ;
RenderOpaqueRenderList ( m_CullResults , camera , renderContext , cmd , HDShaderPassNames . s_ForwardName ) ;
// 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 ) ) )
using ( new ProfilingSample ( cmd , "TP_PrepareLightsForGPU" , CustomSamplerId . TPPrepareLightsForGPU . GetSampler ( ) ) )
{
enableBakeShadowMask = m_LightLoop . PrepareLightsForGPU ( cmd , m_ShadowSettings , m_CullResults , camera ) & & m_FrameSettings . enableShadowMask ;
}
}
else
{
using ( new ProfilingSample ( cmd , "Render SSAO" , GetSampler ( CustomSamplerId . RenderSSAO ) ) )
using ( new ProfilingSample ( cmd , "Render SSAO" , CustomSamplerId . RenderSSAO . GetSampler ( ) ) )
{
// TODO: Everything here (SSAO, Shadow, Build light list, deferred shadow, material and light classification can be parallelize with Async compute)
RenderSSAO ( cmd , hdCamera , renderContext , postProcessLayer ) ;
buildGPULightListsCompleteFence = m_LightLoop . BuildGPULightListsAsyncBegin ( camera , renderContext , m_CameraDepthStencilBufferRT , m_CameraStencilBufferCopyRT , startFence , m_SkyManager . IsSkyValid ( ) ) ;
}
using ( new ProfilingSample ( cmd , "Render shadows" , GetSampler ( CustomSamplerId . RenderShadows ) ) )
using ( new ProfilingSample ( cmd , "Render shadows" , CustomSamplerId . RenderShadows . GetSampler ( ) ) )
{
m_LightLoop . RenderShadows ( renderContext , cmd , m_CullResults ) ;
// TODO: check if statement below still apply
using ( new ProfilingSample ( cmd , "Deferred directional shadows" , GetSampler ( CustomSamplerId . RenderDeferredDirectionalShadow ) ) )
using ( new ProfilingSample ( cmd , "Deferred directional shadows" , CustomSamplerId . RenderDeferredDirectionalShadow . GetSampler ( ) ) )
{
cmd . ReleaseTemporaryRT ( m_DeferredShadowBuffer ) ;
CoreUtils . CreateCmdTemporaryRT ( cmd , m_DeferredShadowBuffer , hdCamera . renderTextureDesc , 0 , FilterMode . Point , RenderTextureFormat . ARGB32 , RenderTextureReadWrite . Linear , 1 , true ) ;
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 ) ) )
using ( new ProfilingSample ( cmd , "Clear and copy stencil texture" , CustomSamplerId . ClearAndCopyStencilTexture . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraStencilBufferCopyRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
}
else
{
using ( new ProfilingSample ( cmd , "Build Light list" , GetSampler ( CustomSamplerId . BuildLightList ) ) )
using ( new ProfilingSample ( cmd , "Build Light list" , CustomSamplerId . BuildLightList . GetSampler ( ) ) )
{
m_LightLoop . BuildGPULightLists ( camera , cmd , m_CameraDepthStencilBufferRT , m_CameraStencilBufferCopyRT , m_SkyManager . IsSkyValid ( ) ) ;
}
}
else
{
using ( new ProfilingSample ( cmd , "Blit to final RT" , GetSampler ( CustomSamplerId . BlitToFinalRT ) ) )
using ( new ProfilingSample ( cmd , "Blit to final RT" , CustomSamplerId . BlitToFinalRT . GetSampler ( ) ) )
{
// Simple blit
cmd . Blit ( m_CameraColorBufferRT , BuiltinRenderTextureType . CameraTarget ) ;
if ( ! m_FrameSettings . enableDistortion )
return ;
using ( new ProfilingSample ( cmd , "Distortion" , GetSampler ( CustomSamplerId . Distortion ) ) )
using ( new ProfilingSample ( cmd , "Distortion" , CustomSamplerId . Distortion . GetSampler ( ) ) )
{
cmd . ReleaseTemporaryRT ( m_DistortionBuffer ) ;
CoreUtils . CreateCmdTemporaryRT ( cmd , m_DistortionBuffer , hdCamera . renderTextureDesc , 0 , FilterMode . Point , Builtin . GetDistortionBufferFormat ( ) , Builtin . GetDistortionBufferReadWrite ( ) ) ;
if ( ! m_FrameSettings . enableDistortion )
return ;
using ( new ProfilingSample ( cmd , "ApplyDistortion" , GetSampler ( CustomSamplerId . ApplyDistortion ) ) )
using ( new ProfilingSample ( cmd , "ApplyDistortion" , CustomSamplerId . ApplyDistortion . GetSampler ( ) ) )
{
var size = new Vector4 ( hdCamera . screenSize . x , hdCamera . screenSize . y , 1f / hdCamera . screenSize . x , 1f / hdCamera . screenSize . y ) ;
uint x , y , z ;
var camera = hdCamera . camera ;
using ( new ProfilingSample ( cmd , addAlphaTestedOnly ? "Depth Prepass alpha test" : "Depth Prepass" , GetSampler ( CustomSamplerId . DepthPrepass ) ) )
using ( new ProfilingSample ( cmd , addAlphaTestedOnly ? "Depth Prepass alpha test" : "Depth Prepass" , CustomSamplerId . DepthPrepass . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraDepthStencilBufferRT ) ;
if ( forcePrepass | | ( addFullDepthPrepass & & ! addAlphaTestedOnly ) ) // Always true in case of forward rendering, use in case of deferred rendering if requesting a full depth prepass
if ( m_FrameSettings . enableTransparentPrepass )
{
// Render transparent depth prepass after opaque one
using ( new ProfilingSample ( cmd , "Transparent Depth Prepass" , GetSampler ( CustomSamplerId . TransparentDepthPrepass ) ) )
using ( new ProfilingSample ( cmd , "Transparent Depth Prepass" , CustomSamplerId . TransparentDepthPrepass . GetSampler ( ) ) )
{
RenderTransparentRenderList ( cull , camera , renderContext , cmd , m_TransparentDepthPrepassNames ) ;
}
var camera = hdCamera . camera ;
using ( new ProfilingSample ( cmd , m_CurrentDebugDisplaySettings . IsDebugDisplayEnabled ( ) ? "GBufferDebugDisplay" : "GBuffer" , GetSampler ( CustomSamplerId . GBuffer ) ) )
using ( new ProfilingSample ( cmd , m_CurrentDebugDisplaySettings . IsDebugDisplayEnabled ( ) ? "GBufferDebugDisplay" : "GBuffer" , CustomSamplerId . GBuffer . GetSampler ( ) ) )
{
// setup GBuffer for rendering
CoreUtils . SetRenderTarget ( cmd , m_GbufferManager . GetGBuffers ( ) , m_CameraDepthStencilBufferRT ) ;
if ( ! m_FrameSettings . enableDBuffer )
return ;
using ( new ProfilingSample ( cmd , "DBuffer" , GetSampler ( CustomSamplerId . DBuffer ) ) )
using ( new ProfilingSample ( cmd , "DBuffer" , CustomSamplerId . DBuffer . GetSampler ( ) ) )
{
// We need to copy depth buffer texture if we want to bind it at this stage
CopyDepthBufferIfNeeded ( cmd ) ;
void RenderDebugViewMaterial ( CullResults cull , HDCamera hdCamera , ScriptableRenderContext renderContext , CommandBuffer cmd )
{
using ( new ProfilingSample ( cmd , "DisplayDebug ViewMaterial" , GetSampler ( CustomSamplerId . DisplayDebugViewMaterial ) ) )
using ( new ProfilingSample ( cmd , "DisplayDebug ViewMaterial" , CustomSamplerId . DisplayDebugViewMaterial . GetSampler ( ) ) )
using ( new ProfilingSample ( cmd , "DebugViewMaterialGBuffer" , GetSampler ( CustomSamplerId . DebugViewMaterialGBuffer ) ) )
using ( new ProfilingSample ( cmd , "DebugViewMaterialGBuffer" , CustomSamplerId . DebugViewMaterialGBuffer . GetSampler ( ) ) )
{
CoreUtils . DrawFullScreen ( cmd , m_currentDebugViewMaterialGBuffer , m_CameraColorBufferRT ) ;
}
// Last blit
{
using ( new ProfilingSample ( cmd , "Blit DebugView Material Debug" , GetSampler ( CustomSamplerId . BlitDebugViewMaterialDebug ) ) )
using ( new ProfilingSample ( cmd , "Blit DebugView Material Debug" , CustomSamplerId . BlitDebugViewMaterialDebug . GetSampler ( ) ) )
{
cmd . Blit ( m_CameraColorBufferRT , BuiltinRenderTextureType . CameraTarget ) ;
}
profileName = k_ForwardPassName [ ( int ) pass ] ;
}
using ( new ProfilingSample ( cmd , profileName , GetSampler ( CustomSamplerId . ForwardPassName ) ) )
using ( new ProfilingSample ( cmd , profileName , CustomSamplerId . ForwardPassName . GetSampler ( ) ) )
{
var camera = hdCamera . camera ;
[Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
void RenderForwardError ( CullResults cullResults , Camera camera , ScriptableRenderContext renderContext , CommandBuffer cmd , ForwardPass pass )
{
using ( new ProfilingSample ( cmd , "Render Forward Error" , GetSampler ( CustomSamplerId . RenderForwardError ) ) )
using ( new ProfilingSample ( cmd , "Render Forward Error" , CustomSamplerId . RenderForwardError . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT ) ;
if ( ! m_FrameSettings . enableTransparentPostpass )
return ;
using ( new ProfilingSample ( cmd , "Render Transparent Depth Post " , GetSampler ( CustomSamplerId . TransparentDepthPostpass ) ) )
using ( new ProfilingSample ( cmd , "Render Transparent Depth Post " , CustomSamplerId . TransparentDepthPostpass . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraDepthStencilBufferRT ) ;
RenderTransparentRenderList ( cullResults , camera , renderContext , cmd , m_TransparentDepthPostpassNames ) ;
if ( ! m_FrameSettings . enableMotionVectors | | ! m_FrameSettings . enableObjectMotionVectors )
return ;
using ( new ProfilingSample ( cmd , "Objects Velocity" , GetSampler ( CustomSamplerId . ObjectsVelocity ) ) )
using ( new ProfilingSample ( cmd , "Objects Velocity" , CustomSamplerId . ObjectsVelocity . GetSampler ( ) ) )
{
// These flags are still required in SRP or the engine won't compute previous model matrices...
// If the flag hasn't been set yet on this camera, motion vectors will skip a frame.
if ( ! m_FrameSettings . enableMotionVectors )
return ;
using ( new ProfilingSample ( cmd , "Camera Velocity" , GetSampler ( CustomSamplerId . CameraVelocity ) ) )
using ( new ProfilingSample ( cmd , "Camera Velocity" , CustomSamplerId . CameraVelocity . GetSampler ( ) ) )
{
// These flags are still required in SRP or the engine won't compute previous model matrices...
// If the flag hasn't been set yet on this camera, motion vectors will skip a frame.
return ;
}
using ( new ProfilingSample ( cmd , "Gaussian Pyramid Color" , GetSampler ( CustomSamplerId . GaussianPyramidColor ) ) )
using ( new ProfilingSample ( cmd , "Gaussian Pyramid Color" , CustomSamplerId . GaussianPyramidColor . GetSampler ( ) ) )
{
var colorPyramidDesc = m_GaussianPyramidColorBufferDesc ;
var pyramidSideSize = GetPyramidSize ( colorPyramidDesc ) ;
void RenderPyramidDepth ( Camera camera , CommandBuffer cmd , ScriptableRenderContext renderContext , FullScreenDebugMode debugMode )
{
using ( new ProfilingSample ( cmd , "Pyramid Depth" , GetSampler ( CustomSamplerId . PyramidDepth ) ) )
using ( new ProfilingSample ( cmd , "Pyramid Depth" , CustomSamplerId . PyramidDepth . GetSampler ( ) ) )
{
var depthPyramidDesc = m_DepthPyramidBufferDesc ;
var pyramidSideSize = GetPyramidSize ( depthPyramidDesc ) ;
void RenderPostProcess ( HDCamera hdcamera , CommandBuffer cmd , PostProcessLayer layer )
{
using ( new ProfilingSample ( cmd , "Post-processing" , GetSampler ( CustomSamplerId . PostProcessing ) ) )
using ( new ProfilingSample ( cmd , "Post-processing" , CustomSamplerId . PostProcessing . GetSampler ( ) ) )
{
// Note: Here we don't use GetDepthTexture() to get the depth texture but m_CameraDepthStencilBuffer as the Forward transparent pass can
// write extra data to deal with DOF/MB
if ( camera . camera . cameraType = = CameraType . Reflection | | camera . camera . cameraType = = CameraType . Preview )
return ;
using ( new ProfilingSample ( cmd , "Render Debug" , GetSampler ( CustomSamplerId . RenderDebug ) ) )
using ( new ProfilingSample ( cmd , "Render Debug" , CustomSamplerId . RenderDebug . GetSampler ( ) ) )
{
// We make sure the depth buffer is bound because we need it to write depth at near plane for overlays otherwise the editor grid end up visible in them.
CoreUtils . SetRenderTarget ( cmd , BuiltinRenderTextureType . CameraTarget , m_CameraDepthStencilBufferRT ) ;
void InitAndClearBuffer ( HDCamera hdCamera , bool enableBakeShadowMask , CommandBuffer cmd )
{
using ( new ProfilingSample ( cmd , "InitAndClearBuffer" , GetSampler ( CustomSamplerId . InitAndClearBuffer ) ) )
using ( new ProfilingSample ( cmd , "InitAndClearBuffer" , CustomSamplerId . InitAndClearBuffer . GetSampler ( ) ) )
using ( new ProfilingSample ( cmd , "InitGBuffers and clear Depth/Stencil" , GetSampler ( CustomSamplerId . InitGBuffersAndClearDepthStencil ) ) )
using ( new ProfilingSample ( cmd , "InitGBuffers and clear Depth/Stencil" , CustomSamplerId . InitGBuffersAndClearDepthStencil . GetSampler ( ) ) )
{
// Init buffer
// With scriptable render loop we must allocate ourself depth and color buffer (We must be independent of backbuffer for now, hope to fix that later).
}
// Clear the diffuse SSS lighting target
using ( new ProfilingSample ( cmd , "Clear SSS diffuse target" , GetSampler ( CustomSamplerId . ClearSSSDiffuseTarget ) ) )
using ( new ProfilingSample ( cmd , "Clear SSS diffuse target" , CustomSamplerId . ClearSSSDiffuseTarget . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_CameraSssDiffuseLightingBufferRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
}
// Clear the HDR target
using ( new ProfilingSample ( cmd , "Clear HDR target" , GetSampler ( CustomSamplerId . ClearHDRTarget ) ) )
using ( new ProfilingSample ( cmd , "Clear HDR target" , CustomSamplerId . ClearHDRTarget . GetSampler ( ) ) )
{
Color clearColor = hdCamera . camera . backgroundColor . linear ; // Need it in linear because we clear a linear fp16 texture.
CoreUtils . SetRenderTarget ( cmd , m_CameraColorBufferRT , m_CameraDepthStencilBufferRT , ClearFlag . Color , clearColor ) ;
if ( ! m_FrameSettings . enableForwardRenderingOnly )
{
using ( new ProfilingSample ( cmd , "Clear GBuffer" , GetSampler ( CustomSamplerId . ClearGBuffer ) ) )
using ( new ProfilingSample ( cmd , "Clear GBuffer" , CustomSamplerId . ClearGBuffer . GetSampler ( ) ) )
{
CoreUtils . SetRenderTarget ( cmd , m_GbufferManager . GetGBuffers ( ) , m_CameraDepthStencilBufferRT , ClearFlag . Color , CoreUtils . clearColorAllBlack ) ;
}