From 2403c553991e181fa42bb40c92b9e1a6d1aa753e Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Wed, 22 Apr 2020 16:41:09 +0200 Subject: [PATCH 01/19] Handle deallocation/reallocation of resources when switching rendergraph on/off (WIP) --- .../Runtime/RenderGraph/RenderGraph.cs | 30 +++--- .../RenderGraphDefaultResources.cs | 71 ++++++++++++++ .../RenderGraphDefaultResources.cs.meta | 11 +++ .../Runtime/Debug/DebugDisplay.cs | 2 + .../Runtime/Lighting/LightLoop/HDShadow.hlsl | 6 +- .../Runtime/Lighting/LightLoop/LightLoop.cs | 29 +----- .../Runtime/Lighting/Shadow/HDShadowAtlas.cs | 10 +- .../Lighting/Shadow/HDShadowContext.hlsl | 3 +- .../Shadow/HDShadowManager.RenderGraph.cs | 56 ++++++++--- .../Lighting/Shadow/HDShadowManager.cs | 40 +++++--- .../Runtime/Material/Decal/DBufferManager.cs | 5 +- .../Runtime/Material/SharedRTManager.cs | 3 - .../SubsurfaceScatteringManager.cs | 10 +- .../PostProcessSystem.RenderGraph.cs | 2 +- .../Runtime/RenderPipeline/HDProfileId.cs | 1 - .../HDRenderPipeline.LightLoop.cs | 6 -- .../HDRenderPipeline.PostProcess.cs | 2 +- .../HDRenderPipeline.Prepass.cs | 2 +- .../HDRenderPipeline.RenderGraph.cs | 2 +- .../RenderPipeline/HDRenderPipeline.cs | 98 +++++++++++++++---- .../RenderPipeline/HDStringConstants.cs | 5 +- 21 files changed, 279 insertions(+), 115 deletions(-) create mode 100644 com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs create mode 100644 com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs.meta diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 34f7b894800..b6758e37ad1 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -33,6 +33,8 @@ public ref struct RenderGraphContext public RenderGraphObjectPool renderGraphPool; ///Render Graph Resource Registry used for accessing resources. public RenderGraphResourceRegistry resources; + ///Render Graph default resources. + public RenderGraphDefaultResources defaultResources; } /// @@ -50,7 +52,6 @@ public struct RenderGraphExecuteParams class RenderGraphDebugParams { - public bool enableRenderGraph = false; // TODO: TEMP TO REMOVE public bool tagResourceNamesWithRG; public bool clearRenderTargetsAtCreation; public bool clearRenderTargetsAtRelease; @@ -61,7 +62,6 @@ class RenderGraphDebugParams public void RegisterDebug() { var list = new List(); - list.Add(new DebugUI.BoolField { displayName = "Enable Render Graph", getter = () => enableRenderGraph, setter = value => enableRenderGraph = value }); list.Add(new DebugUI.BoolField { displayName = "Tag Resources with RG", getter = () => tagResourceNamesWithRG, setter = value => tagResourceNamesWithRG = value }); list.Add(new DebugUI.BoolField { displayName = "Clear Render Targets at creation", getter = () => clearRenderTargetsAtCreation, setter = value => clearRenderTargetsAtCreation = value }); list.Add(new DebugUI.BoolField { displayName = "Clear Render Targets at release", getter = () => clearRenderTargetsAtRelease, setter = value => clearRenderTargetsAtRelease = value }); @@ -69,8 +69,8 @@ public void RegisterDebug() list.Add(new DebugUI.Button { displayName = "Log Frame Information", action = () => logFrameInformation = true }); list.Add(new DebugUI.Button { displayName = "Log Resources", action = () => logResources = true }); - var testPanel = DebugManager.instance.GetPanel("Render Graph", true); - testPanel.children.Add(list.ToArray()); + var panel = DebugManager.instance.GetPanel("Render Graph", true); + panel.children.Add(list.ToArray()); } public void UnRegisterDebug() @@ -194,20 +194,25 @@ internal override bool HasRenderFunc() List m_RendererLists = new List(); RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams(); RenderGraphLogger m_Logger = new RenderGraphLogger(); + RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources(); #region Public Interface - /// - /// Returns true if rendering with Render Graph is enabled. - /// - public bool enabled { get { return m_DebugParameters.enableRenderGraph; } } - // TODO: Currently only needed by SSAO to sample correctly depth texture mips. Need to figure out a way to hide this behind a proper formalization. /// /// Gets the RTHandleProperties structure associated with the Render Graph's RTHandle System. /// public RTHandleProperties rtHandleProperties { get { return m_Resources.GetRTHandleProperties(); } } + public RenderGraphDefaultResources defaultResources + { + get + { + m_DefaultResources.InitializeForRendering(this); + return m_DefaultResources; + } + } + /// /// Render Graph constructor. /// @@ -224,6 +229,7 @@ public RenderGraph(bool supportMSAA, MSAASamples initialSampleCount) public void Cleanup() { m_Resources.Cleanup(); + m_DefaultResources.Cleanup(); } /// @@ -231,7 +237,7 @@ public void Cleanup() /// public void RegisterDebug() { - //m_DebugParameters.RegisterDebug(); + m_DebugParameters.RegisterDebug(); } /// @@ -239,7 +245,7 @@ public void RegisterDebug() /// public void UnRegisterDebug() { - //m_DebugParameters.UnRegisterDebug(); + m_DebugParameters.UnRegisterDebug(); } /// @@ -380,6 +386,7 @@ public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in rgContext.renderContext = renderContext; rgContext.renderGraphPool = m_RenderGraphPool; rgContext.resources = m_Resources; + rgContext.defaultResources = m_DefaultResources; try { @@ -413,6 +420,7 @@ public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in { ClearRenderPasses(); m_Resources.Clear(); + m_DefaultResources.Clear(); m_RendererLists.Clear(); if (m_DebugParameters.logFrameInformation || m_DebugParameters.logResources) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs new file mode 100644 index 00000000000..87a8bb68e30 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs @@ -0,0 +1,71 @@ +using UnityEngine.Rendering; + +namespace UnityEngine.Experimental.Rendering.RenderGraphModule +{ + /// + /// Helper class allowing access to default resources (black or white texture, etc.) during render passes. + /// + public class RenderGraphDefaultResources + { + bool m_IsValid; + + // We need to keep around a RTHandle version of default regular 2D textures since RenderGraph API is all RTHandle. + RTHandle m_BlackTexture2D; + RTHandle m_WhiteTexture2D; + + /// Default black 2D texture. + public TextureHandle blackTexture { get; private set; } + /// Default white 2D texture. + public TextureHandle whiteTexture { get; private set; } + /// Default clear color XR 2D texture. + public TextureHandle clearTextureXR { get; private set; } + /// Default magenta XR 2D texture. + public TextureHandle magentaTextureXR { get; private set; } + /// Default black XR 2D texture. + public TextureHandle blackTextureXR { get; private set; } + /// Default black (UInt) XR 2D texture. + public TextureHandle blackUIntTextureXR { get; private set; } + /// Default blac XR 3D texture. + public TextureHandle blackTexture3DXR { get; private set; } + /// Default white XR 2D texture. + public TextureHandle whiteTextureXR { get; private set; } + + internal RenderGraphDefaultResources() + { + m_BlackTexture2D = RTHandles.Alloc(Texture2D.blackTexture); + m_WhiteTexture2D = RTHandles.Alloc(Texture2D.whiteTexture); + } + + internal void Cleanup() + { + m_BlackTexture2D.Release(); + m_WhiteTexture2D.Release(); + } + + internal void InitializeForRendering(RenderGraph renderGraph) + { + if (!m_IsValid) + { + blackTexture = renderGraph.ImportTexture(m_BlackTexture2D); + whiteTexture = renderGraph.ImportTexture(m_WhiteTexture2D); + + clearTextureXR = renderGraph.ImportTexture(TextureXR.GetClearTexture()); + magentaTextureXR = renderGraph.ImportTexture(TextureXR.GetMagentaTexture()); + blackTextureXR = renderGraph.ImportTexture(TextureXR.GetBlackTexture()); + blackUIntTextureXR = renderGraph.ImportTexture(TextureXR.GetBlackUIntTexture()); + blackTexture3DXR = renderGraph.ImportTexture(TextureXR.GetBlackTexture3D()); + whiteTextureXR = renderGraph.ImportTexture(TextureXR.GetWhiteTexture()); + + m_IsValid = true; + } + } + + // Imported resources are cleared everytime the Render Graph is executed, so we need to know if that happens + // so that we can re-import all default resources if needed. + internal void Clear() + { + m_IsValid = false; + } + } +} + diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs.meta b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs.meta new file mode 100644 index 00000000000..16bf971686f --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9929b63696b16c4ca41927306959897 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs index 34bc9598dba..f756ad3bf89 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs @@ -1436,6 +1436,8 @@ void RegisterRenderingDebug() widgetList.Add(new DebugUI.BoolField { displayName = "XR single-pass test mode", getter = () => data.xrSinglePassTestMode, setter = value => data.xrSinglePassTestMode = value }); } + //widgetList.Add(new DebugUI.BoolField { displayName = "Enable Render Graph", getter = () => HDRenderPipeline.currentPipeline.IsRenderGraphEnabled(), setter = value => HDRenderPipeline.currentPipeline.EnableRenderGraph(value) }); + m_DebugRenderingItems = widgetList.ToArray(); var panel = DebugManager.instance.GetPanel(k_PanelRendering, true); panel.children.Add(m_DebugRenderingItems); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl index 17e092d4f3f..8d916005488 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl @@ -57,7 +57,7 @@ float GetPunctualShadowClosestDistance(HDShadowContext shadowContext, SamplerSta // Note: Here we assume that all the shadow map cube faces have been added contiguously in the buffer to retreive the shadow information // TODO: if on the light type to retrieve the good shadow data HDShadowData sd = shadowContext.shadowDatas[shadowDataIndex]; - + if (pointLight) { sd.shadowToWorld = shadowContext.shadowDatas[shadowDataIndex + CubeMapFaceID(-L)].shadowToWorld; @@ -66,14 +66,14 @@ float GetPunctualShadowClosestDistance(HDShadowContext shadowContext, SamplerSta sd.rot1 = shadowContext.shadowDatas[shadowDataIndex + CubeMapFaceID(-L)].rot1; sd.rot2 = shadowContext.shadowDatas[shadowDataIndex + CubeMapFaceID(-L)].rot2; } - + return EvalShadow_SampleClosestDistance_Punctual(sd, _ShadowmapAtlas, sampl, positionWS, L, lightPositionWS); } float GetAreaLightAttenuation(HDShadowContext shadowContext, float2 positionSS, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist) { HDShadowData sd = shadowContext.shadowDatas[shadowDataIndex]; - return EvalShadow_AreaDepth(sd, _AreaShadowmapMomentAtlas, positionSS, positionWS, normalWS, L, L_dist, true); + return EvalShadow_AreaDepth(sd, _ShadowmapAreaAtlas, positionSS, positionWS, normalWS, L, L_dist, true); } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs index 390ab604361..fafd2de06dd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs @@ -2703,6 +2703,7 @@ bool PrepareLightsForGPU(CommandBuffer cmd, HDCamera hdCamera, CullingResults cu } PushLightDataGlobalParams(cmd); + PushShadowGlobalParams(cmd); } m_EnableBakeShadowMask = m_EnableBakeShadowMask && hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask); @@ -3387,20 +3388,6 @@ HDAdditionalLightData GetHDAdditionalLightData(Light light) return add; } - struct ShadowGlobalParameters - { - public HDCamera hdCamera; - public HDShadowManager shadowManager; - } - - ShadowGlobalParameters PrepareShadowGlobalParameters(HDCamera hdCamera) - { - ShadowGlobalParameters parameters = new ShadowGlobalParameters(); - parameters.hdCamera = hdCamera; - parameters.shadowManager = m_ShadowManager; - return parameters; - } - struct LightLoopGlobalParameters { public HDCamera hdCamera; @@ -3495,16 +3482,9 @@ void PushLightDataGlobalParams(CommandBuffer cmd) cmd.SetGlobalBuffer(HDShaderIDs._DirectionalLightDatas, m_LightLoopLightData.directionalLightData); } - static void PushShadowGlobalParams(in ShadowGlobalParameters param, CommandBuffer cmd) + void PushShadowGlobalParams(CommandBuffer cmd) { - using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.PushShadowGlobalParameters))) - { - Camera camera = param.hdCamera.camera; - - // Shadows - param.shadowManager.SyncData(); - param.shadowManager.BindResources(cmd); - } + m_ShadowManager.PushGlobalParameters(cmd); } static void PushLightLoopGlobalParams(in LightLoopGlobalParameters param, CommandBuffer cmd) @@ -3535,8 +3515,7 @@ void RenderShadowMaps(ScriptableRenderContext renderContext, CommandBuffer cmd, m_ShadowManager.RenderShadows(renderContext, cmd, globalCB, cullResults, hdCamera); // Bind the shadow data - var globalParams = PrepareShadowGlobalParameters(hdCamera); - PushShadowGlobalParams(globalParams, cmd); + m_ShadowManager.BindResources(cmd); } bool WillRenderContactShadow() diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs index f83708478b2..2a747077acd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs @@ -31,7 +31,6 @@ public enum BlurAlgorithm RenderTextureFormat m_Format; string m_Name; int m_AtlasShaderID; - int m_MomentAtlasShaderID; RenderPipelineResources m_RenderPipelineResources; // Moment shadow data @@ -52,7 +51,7 @@ public enum BlurAlgorithm bool m_HasResizedAtlas = false; int frameCounter = 0; - public HDShadowAtlas(RenderPipelineResources renderPipelineResources, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "", int momentAtlasShaderID = 0) + public HDShadowAtlas(RenderPipelineResources renderPipelineResources, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") { this.width = width; this.height = height; @@ -61,7 +60,6 @@ public HDShadowAtlas(RenderPipelineResources renderPipelineResources, int width, m_Format = format; m_Name = name; m_AtlasShaderID = atlasShaderID; - m_MomentAtlasShaderID = momentAtlasShaderID; m_ClearMaterial = clearMaterial; m_BlurAlgorithm = blurAlgorithm; m_RenderPipelineResources = renderPipelineResources; @@ -76,7 +74,7 @@ public HDShadowAtlas(RenderPipelineResources renderPipelineResources, int width, AllocateRenderTexture(); } - void AllocateRenderTexture() + public void AllocateRenderTexture() { if (m_Atlas != null) m_Atlas.Release(); @@ -109,7 +107,7 @@ public void BindResources(CommandBuffer cmd) cmd.SetGlobalTexture(m_AtlasShaderID, m_Atlas); if (m_BlurAlgorithm == BlurAlgorithm.EVSM) { - cmd.SetGlobalTexture(m_MomentAtlasShaderID, m_AtlasMoments[0]); + cmd.SetGlobalTexture(m_AtlasShaderID, m_AtlasMoments[0]); } } @@ -471,7 +469,6 @@ struct RenderShadowsParameters // EVSM public ComputeShader evsmShadowBlurMomentsCS; - public int momentAtlasShaderID; // IM public ComputeShader imShadowBlurMomentsCS; @@ -489,7 +486,6 @@ RenderShadowsParameters PrepareRenderShadowsParameters(in ShaderVariablesGlobal // EVSM parameters.evsmShadowBlurMomentsCS = m_RenderPipelineResources.shaders.evsmBlurCS; - parameters.momentAtlasShaderID = m_MomentAtlasShaderID; // IM parameters.imShadowBlurMomentsCS = m_RenderPipelineResources.shaders.momentShadowsCS; diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowContext.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowContext.hlsl index dfee6ffa597..3dfe1536d2a 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowContext.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowContext.hlsl @@ -19,8 +19,7 @@ struct HDShadowContext TEXTURE2D(_ShadowmapAtlas); TEXTURE2D(_ShadowmapCascadeAtlas); -TEXTURE2D(_AreaShadowmapAtlas); -TEXTURE2D(_AreaShadowmapMomentAtlas); +TEXTURE2D(_ShadowmapAreaAtlas); StructuredBuffer _HDShadowDatas; // Only the first element is used since we only support one directional light diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.RenderGraph.cs index f3bf3abfe3b..52738760492 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.RenderGraph.cs @@ -12,7 +12,7 @@ internal struct ShadowResult partial class HDShadowManager { - internal static ShadowResult ReadShadowResult(ShadowResult shadowResult, RenderGraphBuilder builder) + internal static ShadowResult ReadShadowResult(in ShadowResult shadowResult, RenderGraphBuilder builder) { var result = new ShadowResult(); @@ -30,15 +30,49 @@ internal ShadowResult RenderShadows(RenderGraph renderGraph, in ShaderVariablesG { var result = new ShadowResult(); // Avoid to do any commands if there is no shadow to draw - if (m_ShadowRequestCount == 0) - return result; + if (m_ShadowRequestCount != 0) + { + result.punctualShadowResult = m_Atlas.RenderShadows(renderGraph, cullResults, globalCB, hdCamera.frameSettings, "Punctual Lights Shadows rendering"); + result.directionalShadowResult = m_CascadeAtlas.RenderShadows(renderGraph, cullResults, globalCB, hdCamera.frameSettings, "Directional Light Shadows rendering"); + result.areaShadowResult = m_AreaLightShadowAtlas.RenderShadows(renderGraph, cullResults, globalCB, hdCamera.frameSettings, "Area Light Shadows rendering"); + } - result.punctualShadowResult = m_Atlas.RenderShadows(renderGraph, cullResults, globalCB, hdCamera.frameSettings, "Punctual Lights Shadows rendering"); - result.directionalShadowResult = m_CascadeAtlas.RenderShadows(renderGraph, cullResults, globalCB, hdCamera.frameSettings, "Directional Light Shadows rendering"); - result.areaShadowResult = m_AreaLightShadowAtlas.RenderShadows(renderGraph, cullResults, globalCB, hdCamera.frameSettings, "Area Light Shadows rendering"); + // TODO RENDERGRAPH + // Not really good to bind things globally here (makes lifecycle of the textures fuzzy) + // Probably better to bind it explicitly where needed (deferred lighting and forward/debug passes) + BindShadowGlobalResources(renderGraph, result); return result; } + + class BindShadowGlobalResourcesPassData + { + public ShadowResult shadowResult; + } + + + static void BindAtlasTexture(RenderGraphContext ctx, TextureHandle texture, int shaderId) + { + if (texture.IsValid()) + ctx.cmd.SetGlobalTexture(shaderId, ctx.resources.GetTexture(texture)); + else + ctx.cmd.SetGlobalTexture(shaderId, ctx.resources.GetTexture(ctx.defaultResources.blackTexture)); + } + + void BindShadowGlobalResources(RenderGraph renderGraph, in ShadowResult shadowResult) + { + using (var builder = renderGraph.AddRenderPass("BindShadowGlobalResources", out var passData)) + { + passData.shadowResult = ReadShadowResult(shadowResult, builder); + builder.SetRenderFunc( + (BindShadowGlobalResourcesPassData data, RenderGraphContext ctx) => + { + BindAtlasTexture(ctx, data.shadowResult.punctualShadowResult, HDShaderIDs._ShadowmapAtlas); + BindAtlasTexture(ctx, data.shadowResult.directionalShadowResult, HDShaderIDs._ShadowmapCascadeAtlas); + BindAtlasTexture(ctx, data.shadowResult.areaShadowResult, HDShaderIDs._ShadowmapAreaAtlas); + }); + } + } } partial class HDShadowAtlas @@ -76,13 +110,13 @@ internal TextureHandle RenderShadows(RenderGraph renderGraph, CullingResults cul passData.shadowDrawSettings.useRenderingLayerMaskTest = frameSettings.IsEnabled(FrameSettingsField.LightLayers); passData.atlasTexture = builder.WriteTexture( renderGraph.CreateTexture( new TextureDesc(width, height) - { filterMode = m_FilterMode, depthBufferBits = m_DepthBufferBits, isShadowMap = true, name = m_Name, clearBuffer = passData.parameters.debugClearAtlas }, passData.parameters.atlasShaderID)); + { filterMode = m_FilterMode, depthBufferBits = m_DepthBufferBits, isShadowMap = true, name = m_Name, clearBuffer = passData.parameters.debugClearAtlas })); result = passData.atlasTexture; if (passData.parameters.blurAlgorithm == BlurAlgorithm.EVSM) { - passData.momentAtlasTexture1 = builder.WriteTexture(AllocateMomentAtlas(renderGraph, string.Format("{0}Moment", m_Name), passData.parameters.momentAtlasShaderID)); + passData.momentAtlasTexture1 = builder.WriteTexture(AllocateMomentAtlas(renderGraph, string.Format("{0}Moment", m_Name))); passData.momentAtlasTexture2 = builder.WriteTexture(AllocateMomentAtlas(renderGraph, string.Format("{0}MomentCopy", m_Name))); result = passData.momentAtlasTexture1; @@ -90,11 +124,11 @@ internal TextureHandle RenderShadows(RenderGraph renderGraph, CullingResults cul else if (passData.parameters.blurAlgorithm == BlurAlgorithm.IM) { passData.momentAtlasTexture1 = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(width, height) - { colorFormat = GraphicsFormat.R32G32B32A32_SFloat, name = string.Format("{0}Moment", m_Name), enableRandomWrite = true }, passData.parameters.momentAtlasShaderID)); + { colorFormat = GraphicsFormat.R32G32B32A32_SFloat, name = string.Format("{0}Moment", m_Name), enableRandomWrite = true })); passData.intermediateSummedAreaTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(width, height) - { colorFormat = GraphicsFormat.R32G32B32A32_SInt, name = string.Format("{0}IntermediateSummedArea", m_Name), enableRandomWrite = true }, passData.parameters.momentAtlasShaderID)); + { colorFormat = GraphicsFormat.R32G32B32A32_SInt, name = string.Format("{0}IntermediateSummedArea", m_Name), enableRandomWrite = true })); passData.summedAreaTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(width, height) - { colorFormat = GraphicsFormat.R32G32B32A32_SInt, name = string.Format("{0}SummedArea", m_Name), enableRandomWrite = true }, passData.parameters.momentAtlasShaderID)); + { colorFormat = GraphicsFormat.R32G32B32A32_SInt, name = string.Format("{0}SummedArea", m_Name), enableRandomWrite = true })); result = passData.momentAtlasTexture1; } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs index baca84547a9..ef50ee78de8 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs @@ -290,7 +290,7 @@ public void InitShadowManager(RenderPipelineResources renderPipelineResources, D m_CascadeAtlas = new HDShadowAtlas(renderPipelineResources, 1, 1, HDShaderIDs._ShadowmapCascadeAtlas, m_ClearShadowMaterial, maxShadowRequests, cascadeBlur, depthBufferBits: directionalShadowDepthBits, name: "Cascade Shadow Map Atlas"); if (ShaderConfig.s_AreaLights == 1) - m_AreaLightShadowAtlas = new HDShadowAtlas(renderPipelineResources, areaLightAtlasInfo.shadowAtlasResolution, areaLightAtlasInfo.shadowAtlasResolution, HDShaderIDs._AreaLightShadowmapAtlas, m_ClearShadowMaterial, maxShadowRequests, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: areaLightAtlasInfo.shadowAtlasDepthBits, name: "Area Light Shadow Map Atlas", momentAtlasShaderID: HDShaderIDs._AreaShadowmapMomentAtlas); + m_AreaLightShadowAtlas = new HDShadowAtlas(renderPipelineResources, areaLightAtlasInfo.shadowAtlasResolution, areaLightAtlasInfo.shadowAtlasResolution, HDShaderIDs._ShadowmapAreaAtlas, m_ClearShadowMaterial, maxShadowRequests, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: areaLightAtlasInfo.shadowAtlasDepthBits, name: "Area Light Shadow Map Atlas"); m_ShadowDataBuffer = new ComputeBuffer(maxShadowRequests, System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDShadowData))); m_DirectionalShadowDataBuffer = new ComputeBuffer(1, System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDDirectionalShadowData))); @@ -298,6 +298,22 @@ public void InitShadowManager(RenderPipelineResources renderPipelineResources, D m_MaxShadowRequests = maxShadowRequests; } + public void InitializeNonRenderGraphResources() + { + m_Atlas.AllocateRenderTexture(); + m_CascadeAtlas.AllocateRenderTexture(); + if (ShaderConfig.s_AreaLights == 1) + m_AreaLightShadowAtlas.AllocateRenderTexture(); + } + + public void CleanupNonRenderGraphResources() + { + m_Atlas.Release(); + m_CascadeAtlas.Release(); + if (ShaderConfig.s_AreaLights == 1) + m_AreaLightShadowAtlas.Release(); + } + // Keep in sync with both HDShadowSampling.hlsl public static DirectionalShadowAlgorithm GetDirectionalShadowAlgorithm() { @@ -686,6 +702,14 @@ unsafe public void PrepareGPUShadowDatas(CullingResults cullResults, HDCamera ca m_DirectionalShadowData.cascadeDirection = Vector4.zero; m_DirectionalShadowData.cascadeDirection.w = camera.volumeStack.GetComponent().cascadeShadowSplitCount.value; + + if (m_ShadowRequestCount > 0) + { + // Upload the shadow buffers to GPU + m_ShadowDataBuffer.SetData(m_ShadowDatas); + m_CachedDirectionalShadowData[0] = m_DirectionalShadowData; + m_DirectionalShadowDataBuffer.SetData(m_CachedDirectionalShadowData); + } } public void RenderShadows(ScriptableRenderContext renderContext, CommandBuffer cmd, in ShaderVariablesGlobal globalCB, CullingResults cullResults, HDCamera hdCamera) @@ -712,18 +736,6 @@ public void RenderShadows(ScriptableRenderContext renderContext, CommandBuffer c } } - public void SyncData() - { - // Avoid to upload datas which will not be used - if (m_ShadowRequestCount == 0) - return; - - // Upload the shadow buffers to GPU - m_ShadowDataBuffer.SetData(m_ShadowDatas); - m_CachedDirectionalShadowData[0] = m_DirectionalShadowData; - m_DirectionalShadowDataBuffer.SetData(m_CachedDirectionalShadowData); - } - public void PushGlobalParameters(CommandBuffer cmd) { // This code must be in sync with HDShadowContext.hlsl @@ -733,8 +745,6 @@ public void PushGlobalParameters(CommandBuffer cmd) public void BindResources(CommandBuffer cmd) { - PushGlobalParameters(cmd); - m_Atlas.BindResources(cmd); m_CascadeAtlas.BindResources(cmd); if (ShaderConfig.s_AreaLights == 1) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DBufferManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DBufferManager.cs index 5a30edd2afe..e9bcf7e2ea9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DBufferManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DBufferManager.cs @@ -3,7 +3,7 @@ namespace UnityEngine.Rendering.HighDefinition { class DBufferManager : MRTBufferManager - { + { ComputeBuffer m_PropertyMaskBuffer; int m_PropertyMaskBufferSize; ComputeShader m_ClearPropertyMaskBufferShader; @@ -79,7 +79,7 @@ public void ReleaseResolutionDependentBuffers() } public void AllocResolutionDependentBuffers(HDCamera hdCamera, int width, int height) - { + { m_PropertyMaskBufferSize = ((width + 7) / 8) * ((height + 7) / 8); m_PropertyMaskBufferSize = ((m_PropertyMaskBufferSize + 63) / 64) * 64; // round off to nearest multiple of 64 for ease of use in CS m_PropertyMaskBuffer = new ComputeBuffer(m_PropertyMaskBufferSize, 4); @@ -88,7 +88,6 @@ public void AllocResolutionDependentBuffers(HDCamera hdCamera, int width, int he override public void DestroyBuffers() { base.DestroyBuffers(); - ReleaseResolutionDependentBuffers(); } public void BindBlackTextures(CommandBuffer cmd) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/SharedRTManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Material/SharedRTManager.cs index 42b8fd65502..1a6a3136f9f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/SharedRTManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/SharedRTManager.cs @@ -98,8 +98,6 @@ public void InitSharedBuffers(GBufferManager gbufferManager, RenderPipelineSetti CoreUtils.SetKeyword(m_DepthResolveMaterial, "_HAS_MOTION_VECTORS", m_MotionVectorsSupport); } - AllocateCoarseStencilBuffer(RTHandles.maxWidth, RTHandles.maxHeight, TextureXR.slices); - // If we are in the forward only mode if (!m_ReuseGBufferMemory) { @@ -296,7 +294,6 @@ public void Cleanup() RTHandles.Release(m_CameraDepthStencilBuffer); RTHandles.Release(m_CameraDepthBufferMipChain); RTHandles.Release(m_CameraHalfResDepthBuffer); - DisposeCoarseStencilBuffer(); if (m_MSAASupported) { diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs index 1d0c61a2653..705aa120dab 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs @@ -80,6 +80,12 @@ void InitSSSBuffers() m_SSSSetDiffusionProfiles = new DiffusionProfileSettings[DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT]; } + void DestroySSSBuffers() + { + RTHandles.Release(m_SSSColorMSAA); + RTHandles.Release(m_SSSCameraFilteringBuffer); + } + RTHandle GetSSSBuffer() { return m_SSSColor; @@ -115,8 +121,8 @@ void CleanupSubsurfaceScattering() { RTHandles.Release(m_SSSColor); } - RTHandles.Release(m_SSSColorMSAA); - RTHandles.Release(m_SSSCameraFilteringBuffer); + + DestroySSSBuffers(); } void UpdateCurrentDiffusionProfileSettings(HDCamera hdCamera) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index 498cd19d8fb..5b55edea50a 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -237,7 +237,7 @@ public void Render( RenderGraph renderGraph, passData.parameters = PrepareFinalPass(hdCamera, blueNoise, flipY); passData.source = builder.ReadTexture(source); passData.afterPostProcessTexture = builder.ReadTexture(afterPostProcessTexture); - passData.alphaTexture = builder.ReadTexture(m_KeepAlpha ? alphaTexture : renderGraph.ImportTexture(TextureXR.GetWhiteTexture())); + passData.alphaTexture = builder.ReadTexture(m_KeepAlpha ? alphaTexture : renderGraph.defaultResources.whiteTextureXR); passData.destination = builder.WriteTexture(finalRT); builder.SetRenderFunc( diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs index 8d369531b2a..0c7ed7c7bfc 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs @@ -119,7 +119,6 @@ internal enum HDProfileId PrepareLightsForGPU, // Profile sampler for shadow - PushShadowGlobalParameters, RenderShadowMaps, RenderMomentShadowMaps, RenderPunctualShadowMaps, diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs index 695f1f899a7..81211667b5d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs @@ -27,7 +27,6 @@ static void ReadLightingBuffers(LightingBuffers buffers, RenderGraphBuilder buil class BuildGPULightListPassData { - public ShadowGlobalParameters shadowGlobalParameters; public LightLoopGlobalParameters lightLoopGlobalParameters; public BuildGPULightListParameters buildGPULightListParameters; @@ -93,7 +92,6 @@ BuildGPULightListOutput BuildGPULightList(RenderGraph renderGraph, HDCamera hdCa { builder.EnableAsyncCompute(hdCamera.frameSettings.BuildLightListRunsAsync()); - passData.shadowGlobalParameters = PrepareShadowGlobalParameters(hdCamera); passData.lightLoopGlobalParameters = PrepareLightLoopGlobalParameters(hdCamera, m_TileAndClusterData); passData.buildGPULightListParameters = PrepareBuildGPULightListParameters(hdCamera, m_TileAndClusterData, ref m_ShaderVariablesLightListCB, m_TotalLightCount); passData.depthBuffer = builder.ReadTexture(depthStencilBuffer); @@ -135,7 +133,6 @@ BuildGPULightListOutput BuildGPULightList(RenderGraph renderGraph, HDCamera hdCa BuildDispatchIndirectArguments(data.buildGPULightListParameters, buildLightListResources, tileFlagsWritten, context.cmd); // TODO RENDERGRAPH WARNING: Note that the three sets of variables are bound here, but it should be handled differently. - PushShadowGlobalParams(data.shadowGlobalParameters, context.cmd); PushLightLoopGlobalParams(data.lightLoopGlobalParameters, context.cmd); }); @@ -431,7 +428,6 @@ TextureHandle RenderContactShadows(RenderGraph renderGraph, HDCamera hdCamera, T passData.lightLoopLightData = m_LightLoopLightData; passData.lightList = builder.ReadComputeBuffer(lightLists.lightList); passData.depthTexture = builder.ReadTexture(depthTexture); - passData.shadowManager = m_ShadowManager; passData.contactShadowsTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R32_UInt, enableRandomWrite = true, clearBuffer = clearBuffer, clearColor = Color.clear, name = "ContactShadowsBuffer" }, HDShaderIDs._ContactShadowTexture)); @@ -441,8 +437,6 @@ TextureHandle RenderContactShadows(RenderGraph renderGraph, HDCamera hdCamera, T (RenderContactShadowPassData data, RenderGraphContext context) => { var res = context.resources; - data.shadowManager.PushGlobalParameters(context.cmd); - RenderContactShadows(data.parameters, res.GetTexture(data.contactShadowsTexture), res.GetTexture(data.depthTexture), data.lightLoopLightData, res.GetComputeBuffer(data.lightList), context.cmd); }); } diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs index 0198ccdcf73..2c6aac34fb9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs @@ -23,7 +23,7 @@ TextureHandle RenderPostProcess( RenderGraph renderGraph, { PostProcessParameters parameters = PreparePostProcess(cullResults, hdCamera); - TextureHandle afterPostProcessBuffer = renderGraph.ImportTexture(TextureXR.GetBlackTexture()); + TextureHandle afterPostProcessBuffer = renderGraph.defaultResources.blackTextureXR; TextureHandle dest = HDUtils.PostProcessIsFinalPass(parameters.hdCamera) ? backBuffer : renderGraph.CreateTexture( new TextureDesc(Vector2.one, true, true) { colorFormat = GetColorBufferFormat(), name = "Intermediate Postprocess buffer" }); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs index a2ce07399c5..ffb4c42da01 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs @@ -584,7 +584,7 @@ void RenderDBuffer(RenderGraph renderGraph, HDCamera hdCamera, ref PrepassOutput if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.Decals)) { // Return all black textures for default values. - var blackTexture = renderGraph.ImportTexture(TextureXR.GetBlackTexture()); + var blackTexture = renderGraph.defaultResources.blackTextureXR; output.dbuffer.dBufferCount = use4RTs ? 4 : 3; for (int i = 0; i < output.dbuffer.dBufferCount; ++i) output.dbuffer.mrt[i] = blackTexture; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs index 497c5984b3a..1e40fb46dbe 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs @@ -70,7 +70,7 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, PushFullScreenDebugTexture(m_RenderGraph, lightingBuffers.ambientOcclusionBuffer, FullScreenDebugMode.SSAO); // Evaluate the clear coat mask texture based on the lit shader mode - var clearCoatMask = hdCamera.frameSettings.litShaderMode == LitShaderMode.Deferred ? prepassOutput.gbuffer.mrt[2] : m_RenderGraph.ImportTexture(TextureXR.GetBlackTexture()); + var clearCoatMask = hdCamera.frameSettings.litShaderMode == LitShaderMode.Deferred ? prepassOutput.gbuffer.mrt[2] : m_RenderGraph.defaultResources.blackTextureXR; lightingBuffers.ssrLightingBuffer = RenderSSR(m_RenderGraph, hdCamera, prepassOutput.resolvedNormalBuffer, diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index ba05ca5c744..13e5f18a922 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -319,7 +319,8 @@ internal bool showCascade } // RENDER GRAPH - RenderGraph m_RenderGraph; + RenderGraph m_RenderGraph; + bool m_EnableRenderGraph; // MSAA resolve materials Material m_ColorResolveMaterial = null; @@ -506,10 +507,6 @@ public HDRenderPipeline(HDRenderPipelineAsset asset, HDRenderPipelineAsset defau CameraCaptureBridge.enabled = true; - // Render Graph - m_RenderGraph = new RenderGraph(m_Asset.currentPlatformRenderPipelineSettings.supportMSAA, m_MSAASamples); - m_RenderGraph.RegisterDebug(); - InitializePrepass(m_Asset); m_ColorResolveMaterial = CoreUtils.CreateEngineMaterial(asset.renderPipelineResources.shaders.colorResolvePS); @@ -625,6 +622,9 @@ void InitializeRenderTextures() void GetOrCreateDebugTextures() { + if (m_EnableRenderGraph) + return; + //Debug.isDebugBuild can be changed during DoBuildPlayer, these allocation has to be check on every frames //TODO : Clean this with the RenderGraph system if (Debug.isDebugBuild && m_DebugColorPickerBuffer == null && m_DebugFullScreenTempBuffer == null) @@ -645,15 +645,18 @@ void DestroyRenderTextures() { m_GbufferManager.DestroyBuffers(); m_DbufferManager.DestroyBuffers(); - m_MipGenerator.Release(); + + DestroySSSBuffers(); + m_SharedRTManager.Cleanup(); RTHandles.Release(m_CameraColorBuffer); + RTHandles.Release(m_OpaqueAtmosphericScatteringBuffer); + RTHandles.Release(m_CameraSssDiffuseLightingBuffer); + if (m_CustomPassColorBuffer.IsValueCreated) RTHandles.Release(m_CustomPassColorBuffer.Value); if (m_CustomPassDepthBuffer.IsValueCreated) RTHandles.Release(m_CustomPassDepthBuffer.Value); - RTHandles.Release(m_OpaqueAtmosphericScatteringBuffer); - RTHandles.Release(m_CameraSssDiffuseLightingBuffer); RTHandles.Release(m_DistortionBuffer); RTHandles.Release(m_ContactShadowBuffer); @@ -664,13 +667,17 @@ void DestroyRenderTextures() RTHandles.Release(m_SsrHitPointTexture); RTHandles.Release(m_SsrLightingTexture); - RTHandles.Release(m_DebugColorPickerBuffer); - RTHandles.Release(m_DebugFullScreenTempBuffer); - RTHandles.Release(m_IntermediateAfterPostProcessBuffer); - RTHandles.Release(m_CameraColorMSAABuffer); RTHandles.Release(m_OpaqueAtmosphericScatteringMSAABuffer); RTHandles.Release(m_CameraSssDiffuseLightingMSAABuffer); + + // Those buffer are initialized lazily so we need to null them for this to work after deallocation. + RTHandles.Release(m_DebugColorPickerBuffer); + RTHandles.Release(m_DebugFullScreenTempBuffer); + RTHandles.Release(m_IntermediateAfterPostProcessBuffer); + m_DebugColorPickerBuffer = null; + m_DebugFullScreenTempBuffer = null; + m_IntermediateAfterPostProcessBuffer = null; } void SetRenderingFeatures() @@ -828,6 +835,59 @@ void UnsetRenderingFeatures() #endif } + void InitializeRenderGraph() + { + m_RenderGraph = new RenderGraph(m_Asset.currentPlatformRenderPipelineSettings.supportMSAA, m_MSAASamples); + m_RenderGraph.RegisterDebug(); + } + + void CleanupRenderGraph() + { + if (m_EnableRenderGraph) + { + m_RenderGraph.Cleanup(); + m_RenderGraph.UnRegisterDebug(); + m_RenderGraph = null; + } + } + + internal bool IsRenderGraphEnabled() + { + return m_EnableRenderGraph; + } + + internal void EnableRenderGraph(bool value) + { + bool changed = value != m_EnableRenderGraph; + if (changed) + { + if (value) + { + CleanupNonRenderGraphResources(); + InitializeRenderGraph(); + m_EnableRenderGraph = true; + } + else + { + CleanupRenderGraph(); + InitializeNonRenderGraphResources(); + m_EnableRenderGraph = false; + } + } + } + + void InitializeNonRenderGraphResources() + { + InitializeRenderTextures(); + m_ShadowManager.InitializeNonRenderGraphResources(); + } + + void CleanupNonRenderGraphResources() + { + DestroyRenderTextures(); + m_ShadowManager.CleanupNonRenderGraphResources(); + } + void InitializeDebugMaterials() { m_DebugViewMaterialGBuffer = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugViewMaterialGBufferPS); @@ -930,8 +990,6 @@ protected override void Dispose(bool disposing) CoreUtils.Destroy(m_ApplyDistortionMaterial); CoreUtils.Destroy(m_ClearStencilBufferMaterial); - CleanupSubsurfaceScattering(); - m_SharedRTManager.Cleanup(); m_XRSystem.Cleanup(); m_SkyManager.Cleanup(); CleanupVolumetricLighting(); @@ -948,16 +1006,18 @@ protected override void Dispose(bool disposing) HDCamera.ClearAll(); + m_MipGenerator.Release(); + DestroyRenderTextures(); CullingGroupManager.instance.Cleanup(); + m_DbufferManager.ReleaseResolutionDependentBuffers(); + m_SharedRTManager.DisposeCoarseStencilBuffer(); + CoreUtils.SafeRelease(m_DepthPyramidMipLevelOffsetsBuffer); CustomPassVolume.Cleanup(); - // RenderGraph - m_RenderGraph.Cleanup(); - m_RenderGraph.UnRegisterDebug(); CleanupPrepass(); CoreUtils.Destroy(m_ColorResolveMaterial); @@ -2069,7 +2129,7 @@ AOVRequestData aovRequest return; } - if (m_RenderGraph.enabled) + if (m_EnableRenderGraph) { ExecuteWithRenderGraph(renderRequest, aovRequest, aovBuffers, renderContext, cmd); return; @@ -3215,7 +3275,7 @@ void RenderDBuffer(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext { // We still bind black textures to make sure that something is bound (can be a problem on some platforms) m_DbufferManager.BindBlackTextures(cmd); - + // Bind buffer to make sure that something is bound . cmd.SetGlobalBuffer(HDShaderIDs._DecalPropertyMaskBufferSRV, m_DbufferManager.propertyMaskBuffer); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs index 28dc5a92ebe..ff18a2f1d54 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs @@ -80,8 +80,7 @@ static class HDShaderIDs public static readonly int _HDShadowDatas = Shader.PropertyToID("_HDShadowDatas"); public static readonly int _HDDirectionalShadowData = Shader.PropertyToID("_HDDirectionalShadowData"); public static readonly int _ShadowmapAtlas = Shader.PropertyToID("_ShadowmapAtlas"); - public static readonly int _AreaLightShadowmapAtlas = Shader.PropertyToID("_AreaShadowmapAtlas"); - public static readonly int _AreaShadowmapMomentAtlas = Shader.PropertyToID("_AreaShadowmapMomentAtlas"); + public static readonly int _ShadowmapAreaAtlas = Shader.PropertyToID("_ShadowmapAreaAtlas"); public static readonly int _ShadowmapCascadeAtlas = Shader.PropertyToID("_ShadowmapCascadeAtlas"); // Moment shadow map data @@ -343,7 +342,7 @@ static class HDShaderIDs public static readonly int _InputCubemap = Shader.PropertyToID("_InputCubemap"); public static readonly int _Mipmap = Shader.PropertyToID("_Mipmap"); - public static readonly int _ApplyExposure = Shader.PropertyToID("_ApplyExposure"); + public static readonly int _ApplyExposure = Shader.PropertyToID("_ApplyExposure"); public static readonly int _DiffusionProfileHash = Shader.PropertyToID("_DiffusionProfileHash"); public static readonly int _MaxRadius = Shader.PropertyToID("_MaxRadius"); From c7756896312a19d03d59c4a91f6de69055ab18e4 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Fri, 24 Apr 2020 16:40:27 +0200 Subject: [PATCH 02/19] AO and Post Processes. --- .../ScreenSpaceLighting/AmbientOcclusion.cs | 11 ++ .../PostProcessing/PostProcessSystem.cs | 141 +++++++++++------- .../RenderPipeline/HDRenderPipeline.cs | 4 + 3 files changed, 98 insertions(+), 58 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs index a5f2607b370..40bf78c2e80 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs @@ -234,6 +234,17 @@ internal void Cleanup() ReleaseRT(); } + internal void InitializeNonRenderGraphResources() + { + float scaleFactor = m_RunningFullRes ? 1.0f : 0.5f; + AllocRT(scaleFactor); + } + + internal void CleanupNonRenderGraphResources() + { + ReleaseRT(); + } + internal void InitRaytracing(HDRenderPipeline renderPipeline) { m_RaytracingAmbientOcclusion.Init(renderPipeline); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 53acbb6240e..d5dffe9bc43 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -126,6 +126,8 @@ private enum SMAAStage bool m_MotionBlurSupportsScattering; + bool m_NonRenderGraphResourcesAvailable; + // Max guard band size is assumed to be 8 pixels const int k_RTGuardBandSize = 4; @@ -155,36 +157,13 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources m_UseSafePath = SystemInfo.graphicsDeviceVendor .ToLowerInvariant().Contains("intel"); - // Project-wise LUT size for all grading operations - meaning that internal LUTs and - // user-provided LUTs will have to be this size var settings = hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings; m_LutSize = settings.lutSize; - var lutFormat = (GraphicsFormat)settings.lutFormat; + + InitializeNonRenderGraphResources(hdAsset); // Grading specific m_HableCurve = new HableCurve(); - m_InternalLogLut = RTHandles.Alloc( - name: "Color Grading Log Lut", - dimension: TextureDimension.Tex3D, - width: m_LutSize, - height: m_LutSize, - slices: m_LutSize, - depthBufferBits: DepthBits.None, - colorFormat: lutFormat, - filterMode: FilterMode.Bilinear, - wrapMode: TextureWrapMode.Clamp, - anisoLevel: 0, - useMipMap: false, - enableRandomWrite: true - ); - - // Setup a default exposure textures and clear it to neutral values so that the exposure - // multiplier is 1 and thus has no effect - // Beware that 0 in EV100 maps to a multiplier of 0.833 so the EV100 value in this - // neutral exposure texture isn't 0 - m_EmptyExposureTexture = RTHandles.Alloc(1, 1, colorFormat: k_ExposureFormat, - enableRandomWrite: true, name: "Empty EV100 Exposure" - ); m_MotionBlurSupportsScattering = SystemInfo.IsFormatSupported(GraphicsFormat.R32_UInt, FormatUsage.LoadStore) && SystemInfo.IsFormatSupported(GraphicsFormat.R16_UInt, FormatUsage.LoadStore); // TODO: Remove this line when atomic bug in HLSLcc is fixed. @@ -201,49 +180,25 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources // relying on (breaks determinism in their code) m_Random = new System.Random(); - // Misc targets - m_TempTexture1024 = RTHandles.Alloc( - 1024, 1024, colorFormat: GraphicsFormat.R16G16_SFloat, - enableRandomWrite: true, name: "Average Luminance Temp 1024" - ); - - m_TempTexture32 = RTHandles.Alloc( - 32, 32, colorFormat: GraphicsFormat.R16G16_SFloat, - enableRandomWrite: true, name: "Average Luminance Temp 32" - ); - - m_ColorFormat = (GraphicsFormat)hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings.bufferFormat; + m_ColorFormat = (GraphicsFormat)settings.bufferFormat; m_KeepAlpha = false; // if both rendering and post-processing support an alpha channel, then post-processing will process (or copy) the alpha - m_EnableAlpha = hdAsset.currentPlatformRenderPipelineSettings.supportsAlpha && hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings.supportsAlpha; + m_EnableAlpha = settings.supportsAlpha && settings.supportsAlpha; if (m_EnableAlpha == false) { // if only rendering has an alpha channel (and not post-processing), then we just copy the alpha to the output (but we don't process it). - m_KeepAlpha = hdAsset.currentPlatformRenderPipelineSettings.supportsAlpha; - } - - if (m_KeepAlpha) - { - m_AlphaTexture = RTHandles.Alloc( - Vector2.one, slices: TextureXR.slices, dimension: TextureXR.dimension, - colorFormat: GraphicsFormat.R16_SFloat, enableRandomWrite: true, name: "Alpha Channel Copy" - ); + m_KeepAlpha = settings.supportsAlpha; } } public void Cleanup() { - m_Pool.Cleanup(); + CleanupNonRenderGraphResources(); - RTHandles.Release(m_EmptyExposureTexture); - RTHandles.Release(m_TempTexture1024); - RTHandles.Release(m_TempTexture32); - RTHandles.Release(m_AlphaTexture); CoreUtils.Destroy(m_ExposureCurveTexture); CoreUtils.Destroy(m_InternalSpectralLut); - RTHandles.Release(m_InternalLogLut); CoreUtils.Destroy(m_FinalPassMaterial); CoreUtils.Destroy(m_ClearBlackMaterial); CoreUtils.Destroy(m_SMAAMaterial); @@ -255,13 +210,8 @@ public void Cleanup() CoreUtils.SafeRelease(m_FarBokehTileList); CoreUtils.SafeRelease(m_ContrastAdaptiveSharpen); - m_EmptyExposureTexture = null; - m_TempTexture1024 = null; - m_TempTexture32 = null; - m_AlphaTexture = null; m_ExposureCurveTexture = null; m_InternalSpectralLut = null; - m_InternalLogLut = null; m_FinalPassMaterial = null; m_ClearBlackMaterial = null; m_SMAAMaterial = null; @@ -273,11 +223,86 @@ public void Cleanup() m_FarBokehTileList = null; } + public void InitializeNonRenderGraphResources(HDRenderPipelineAsset hdAsset) + { + m_NonRenderGraphResourcesAvailable = true; + + var settings = hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings; + + // Project-wide LUT size for all grading operations - meaning that internal LUTs and + // user-provided LUTs will have to be this size + var lutFormat = (GraphicsFormat)settings.lutFormat; + + m_InternalLogLut = RTHandles.Alloc( + name: "Color Grading Log Lut", + dimension: TextureDimension.Tex3D, + width: m_LutSize, + height: m_LutSize, + slices: m_LutSize, + depthBufferBits: DepthBits.None, + colorFormat: lutFormat, + filterMode: FilterMode.Bilinear, + wrapMode: TextureWrapMode.Clamp, + anisoLevel: 0, + useMipMap: false, + enableRandomWrite: true + ); + + // Setup a default exposure textures and clear it to neutral values so that the exposure + // multiplier is 1 and thus has no effect + // Beware that 0 in EV100 maps to a multiplier of 0.833 so the EV100 value in this + // neutral exposure texture isn't 0 + m_EmptyExposureTexture = RTHandles.Alloc(1, 1, colorFormat: k_ExposureFormat, + enableRandomWrite: true, name: "Empty EV100 Exposure" + ); + + // Misc targets + m_TempTexture1024 = RTHandles.Alloc( + 1024, 1024, colorFormat: GraphicsFormat.R16G16_SFloat, + enableRandomWrite: true, name: "Average Luminance Temp 1024" + ); + + m_TempTexture32 = RTHandles.Alloc( + 32, 32, colorFormat: GraphicsFormat.R16G16_SFloat, + enableRandomWrite: true, name: "Average Luminance Temp 32" + ); + + if (m_KeepAlpha) + { + m_AlphaTexture = RTHandles.Alloc( + Vector2.one, slices: TextureXR.slices, dimension: TextureXR.dimension, + colorFormat: GraphicsFormat.R16_SFloat, enableRandomWrite: true, name: "Alpha Channel Copy" + ); + } + } + + public void CleanupNonRenderGraphResources() + { + m_NonRenderGraphResourcesAvailable = false; + + m_Pool.Cleanup(); + + RTHandles.Release(m_EmptyExposureTexture); + RTHandles.Release(m_TempTexture1024); + RTHandles.Release(m_TempTexture32); + RTHandles.Release(m_AlphaTexture); + RTHandles.Release(m_InternalLogLut); + + m_EmptyExposureTexture = null; + m_TempTexture1024 = null; + m_TempTexture32 = null; + m_AlphaTexture = null; + m_InternalLogLut = null; + } + // In some cases, the internal buffer of render textures might be invalid. // Usually when using these textures with API such as SetRenderTarget, they are recreated internally. // This is not the case when these textures are used exclusively with Compute Shaders. So to make sure they work in this case, we recreate them here. void CheckRenderTexturesValidity() { + if (!m_NonRenderGraphResourcesAvailable) + return; + if (!m_EmptyExposureTexture.rt.IsCreated()) FillEmptyExposureTexture(); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 13e5f18a922..924831a7303 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -880,12 +880,16 @@ void InitializeNonRenderGraphResources() { InitializeRenderTextures(); m_ShadowManager.InitializeNonRenderGraphResources(); + m_AmbientOcclusionSystem.InitializeNonRenderGraphResources(); + m_PostProcessSystem.InitializeNonRenderGraphResources(asset); } void CleanupNonRenderGraphResources() { DestroyRenderTextures(); m_ShadowManager.CleanupNonRenderGraphResources(); + m_AmbientOcclusionSystem.CleanupNonRenderGraphResources(); + m_PostProcessSystem.CleanupNonRenderGraphResources(); } void InitializeDebugMaterials() From a14733010d862f5c5d92f031241bea4cfc115d48 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Fri, 24 Apr 2020 17:04:56 +0200 Subject: [PATCH 03/19] Prefixed all history buffers with camera name for readability in the memory profiler. --- .../Runtime/Lighting/Shadow/ScreenSpaceShadowManager.cs | 6 +++--- .../SubsurfaceScattering/SubsurfaceScatteringManager.cs | 2 +- .../Runtime/PostProcessing/PostProcessSystem.cs | 8 ++++---- .../Runtime/RenderPipeline/Camera/HDCamera.cs | 4 ++-- .../Runtime/RenderPipeline/HDRenderPipeline.cs | 6 +++--- .../Runtime/RenderPipeline/PathTracing/PathTracing.cs | 2 +- .../Raytracing/HDRaytracingAmbientOcclusion.cs | 2 +- .../Raytracing/HDRaytracingIndirectDiffuse.cs | 2 +- .../RenderPipeline/Raytracing/HDRaytracingReflection.cs | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ScreenSpaceShadowManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ScreenSpaceShadowManager.cs index 6d46c1fbad4..bff48aaeab9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ScreenSpaceShadowManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ScreenSpaceShadowManager.cs @@ -63,7 +63,7 @@ static RTHandle ShadowHistoryBufferAllocatorFunction(string viewName, int frameI HDRenderPipeline hdrp = (RenderPipelineManager.currentPipeline as HDRenderPipeline); int numShadowSlices = Math.Max((int)Math.Ceiling(hdrp.m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: graphicsFormat, - enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("ScreenSpaceShadowHistoryBuffer{0}", frameIndex)); + enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ScreenSpaceShadowHistoryBuffer{1}", viewName, frameIndex)); } @@ -77,7 +77,7 @@ static RTHandle ShadowHistoryValidityBufferAllocatorFunction(string viewName, in GraphicsFormat graphicsFormat = (GraphicsFormat)hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.screenSpaceShadowBufferFormat; int numShadowSlices = Math.Max((int)Math.Ceiling(hdrp.m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: graphicsFormat, - enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("ShadowHistoryValidityBuffer{0}", frameIndex)); + enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ShadowHistoryValidityBuffer{1}", viewName, frameIndex)); } static RTHandle ShadowHistoryDistanceBufferAllocatorFunction(string viewName, int frameIndex, RTHandleSystem rtHandleSystem) @@ -87,7 +87,7 @@ static RTHandle ShadowHistoryDistanceBufferAllocatorFunction(string viewName, in GraphicsFormat graphicsFormat = (GraphicsFormat)hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.screenSpaceShadowBufferFormat; int numShadowSlices = Math.Max((int)Math.Ceiling(hdrp.m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: graphicsFormat, - enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("ShadowHistoryDistanceBuffer{0}", frameIndex)); + enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ShadowHistoryDistanceBuffer{1}", viewName, frameIndex)); } // The three types of shadows that we currently support diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs index 705aa120dab..f6bd5d4c157 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs @@ -271,7 +271,7 @@ static RTHandle SubSurfaceHistoryBufferAllocatorFunction(string viewName, int fr { return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: false, autoGenerateMips: false, - name: string.Format("SubSurfaceHistoryBuffer{0}", frameIndex)); + name: string.Format("{0}_SubSurfaceHistoryBuffer{1}", viewName, frameIndex)); } void RenderSubsurfaceScattering(HDCamera hdCamera, CommandBuffer cmd, RTHandle colorBufferRT, diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index d5dffe9bc43..5ffa4b2cb04 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -824,7 +824,7 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { // r: multiplier, g: EV100 return rtHandleSystem.Alloc(1, 1, colorFormat: k_ExposureFormat, - enableRandomWrite: true, name: $"Exposure Texture ({id}) {frameIndex}" + enableRandomWrite: true, name: $"{id} Exposure Texture {frameIndex}" ); } @@ -1056,7 +1056,7 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) return rtHandleSystem.Alloc( Vector2.one, TextureXR.slices, DepthBits.None, dimension: TextureXR.dimension, filterMode: FilterMode.Bilinear, colorFormat: m_ColorFormat, - enableRandomWrite: true, useDynamicScale: true, name: "TAA History" + enableRandomWrite: true, useDynamicScale: true, name: $"{id} TAA History" ); } @@ -1072,7 +1072,7 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) return rtHandleSystem.Alloc( Vector2.one, TextureXR.slices, DepthBits.None, dimension: TextureXR.dimension, filterMode: FilterMode.Bilinear, colorFormat: GraphicsFormat.R16_SFloat, - enableRandomWrite: true, useDynamicScale: true, name: "Velocity magnitude" + enableRandomWrite: true, useDynamicScale: true, name: $"{id} Velocity magnitude" ); } @@ -1698,7 +1698,7 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { return rtHandleSystem.Alloc( Vector2.one, TextureXR.slices, DepthBits.None, GraphicsFormat.R16_SFloat, - dimension: TextureXR.dimension, enableRandomWrite: true, useDynamicScale: true, name: "CoC History" + dimension: TextureXR.dimension, enableRandomWrite: true, useDynamicScale: true, name: $"{id} CoC History" ); } diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs index 74ad3623b32..ff8b1099c42 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs @@ -784,7 +784,7 @@ struct AmbientOcclusionAllocator public RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { - return rtHandleSystem.Alloc(Vector2.one * scaleFactor, TextureXR.slices, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R32_UInt, dimension: TextureXR.dimension, useDynamicScale: true, enableRandomWrite: true, name: string.Format("AO Packed history_{0}", frameIndex)); + return rtHandleSystem.Alloc(Vector2.one * scaleFactor, TextureXR.slices, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R32_UInt, dimension: TextureXR.dimension, useDynamicScale: true, enableRandomWrite: true, name: string.Format("{0}_AO Packed history_{1}", id, frameIndex)); } } @@ -1230,7 +1230,7 @@ static RTHandle HistoryBufferAllocatorFunction(string viewName, int frameIndex, return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: (GraphicsFormat)hdPipeline.currentPlatformRenderPipelineSettings.colorBufferFormat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: true, autoGenerateMips: false, useDynamicScale: true, - name: string.Format("CameraColorBufferMipChain{0}", frameIndex)); + name: string.Format("{0}_CameraColorBufferMipChain{1}", viewName, frameIndex)); } void ReleaseHistoryBuffer() diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 924831a7303..00b5f363e65 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -2135,7 +2135,7 @@ AOVRequestData aovRequest if (m_EnableRenderGraph) { - ExecuteWithRenderGraph(renderRequest, aovRequest, aovBuffers, renderContext, cmd); + //ExecuteWithRenderGraph(renderRequest, aovRequest, aovBuffers, renderContext, cmd); return; } @@ -4828,7 +4828,7 @@ void SendGeometryGraphicsBuffers(CommandBuffer cmd, HDCamera hdCamera) RTHandle mainNormalBuffer = m_SharedRTManager.GetNormalBuffer(); RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { - return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: mainNormalBuffer.rt.graphicsFormat, dimension: TextureXR.dimension, enableRandomWrite: mainNormalBuffer.rt.enableRandomWrite, name: $"Normal History Buffer" + return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: mainNormalBuffer.rt.graphicsFormat, dimension: TextureXR.dimension, enableRandomWrite: mainNormalBuffer.rt.enableRandomWrite, name: $"{id}_Normal History Buffer" ); } @@ -4843,7 +4843,7 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) RTHandle mainDepthBuffer = m_SharedRTManager.GetDepthTexture(); RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem) { - return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: mainDepthBuffer.rt.graphicsFormat, dimension: TextureXR.dimension, enableRandomWrite: mainDepthBuffer.rt.enableRandomWrite, name: $"Depth History Buffer" + return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: mainDepthBuffer.rt.graphicsFormat, dimension: TextureXR.dimension, enableRandomWrite: mainDepthBuffer.rt.enableRandomWrite, name: $"{id}_Depth History Buffer" ); } diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs index be059b353ca..a99363991e8 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs @@ -207,7 +207,7 @@ static RTHandle PathTracingHistoryBufferAllocatorFunction(string viewName, int f { return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R32G32B32A32_SFloat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: false, autoGenerateMips: false, - name: string.Format("PathTracingHistoryBuffer{0}", frameIndex)); + name: string.Format("{0}_PathTracingHistoryBuffer{1}", viewName, frameIndex)); } void RenderPathTracing(HDCamera hdCamera, CommandBuffer cmd, RTHandle outputTexture) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingAmbientOcclusion.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingAmbientOcclusion.cs index c295d1ae076..ebd651e95a9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingAmbientOcclusion.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingAmbientOcclusion.cs @@ -52,7 +52,7 @@ static RTHandle AmbientOcclusionHistoryBufferAllocatorFunction(string viewName, { return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R16G16_SFloat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: false, autoGenerateMips: false, - name: string.Format("AmbientOcclusionHistoryBuffer{0}", frameIndex)); + name: string.Format("{0}_AmbientOcclusionHistoryBuffer{1}", viewName, frameIndex)); } diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingIndirectDiffuse.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingIndirectDiffuse.cs index 740f1e1ef71..9b9480955c3 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingIndirectDiffuse.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingIndirectDiffuse.cs @@ -33,7 +33,7 @@ RTHandle IndirectDiffuseHistoryBufferAllocatorFunction(string viewName, int fram { return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: false, autoGenerateMips: false, - name: string.Format("IndirectDiffuseHistoryBuffer{0}", frameIndex)); + name: string.Format("{0}_IndirectDiffuseHistoryBuffer{1}", viewName, frameIndex)); } RTHandle GetIndirectDiffuseTexture() diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingReflection.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingReflection.cs index cc729748287..789ec52c2af 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingReflection.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingReflection.cs @@ -17,7 +17,7 @@ static RTHandle ReflectionHistoryBufferAllocatorFunction(string viewName, int fr { return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: false, autoGenerateMips: false, - name: string.Format("ReflectionHistoryBuffer{0}", frameIndex)); + name: string.Format("{0}_ReflectionHistoryBuffer{1}", viewName, frameIndex)); } void ReleaseRayTracedReflections() From 8bb3fe65771374fa34496f9f8e69228334b539b0 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Mon, 27 Apr 2020 10:18:51 +0200 Subject: [PATCH 04/19] LIght volume debug and Volumetric (WIP) --- .../Runtime/Debug/DebugLightVolumes.cs | 19 +++-- .../VolumetricLighting/VolumetricLighting.cs | 75 ++++++++----------- .../RenderPipeline/HDRenderPipeline.cs | 6 +- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugLightVolumes.cs b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugLightVolumes.cs index 47495addf93..515e26a57b4 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugLightVolumes.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugLightVolumes.cs @@ -54,6 +54,19 @@ public void InitData(RenderPipelineResources renderPipelineResources) m_Blit = CoreUtils.CreateEngineMaterial(renderPipelineResources.shaders.blitPS); + InitializeNonRenderGraphResources(); + } + + public void ReleaseData() + { + CoreUtils.Destroy(m_Blit); + CoreUtils.Destroy(m_DebugLightVolumeMaterial); + + CleanupNonRenderGraphResources(); + } + + public void InitializeNonRenderGraphResources() + { m_LightCountBuffer = RTHandles.Alloc(Vector2.one, TextureXR.slices, dimension: TextureXR.dimension, colorFormat: GraphicsFormat.R32_SFloat, enableRandomWrite: false, useMipMap: false, name: "LightVolumeCount"); m_ColorAccumulationBuffer = RTHandles.Alloc(Vector2.one, TextureXR.slices, dimension: TextureXR.dimension, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: false, useMipMap: false, name: "LightVolumeColorAccumulation"); m_DebugLightVolumesTexture = RTHandles.Alloc(Vector2.one, TextureXR.slices, dimension: TextureXR.dimension, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useMipMap: false, name: "LightVolumeDebugLightVolumesTexture"); @@ -63,16 +76,12 @@ public void InitData(RenderPipelineResources renderPipelineResources) m_RTIDs[1] = m_ColorAccumulationBuffer; } - public void ReleaseData() + public void CleanupNonRenderGraphResources() { - CoreUtils.Destroy(m_Blit); - RTHandles.Release(m_DepthBuffer); RTHandles.Release(m_DebugLightVolumesTexture); RTHandles.Release(m_ColorAccumulationBuffer); RTHandles.Release(m_LightCountBuffer); - - CoreUtils.Destroy(m_DebugLightVolumeMaterial); } public struct RenderLightVolumesParameters diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs index 60d4a5d2fe6..0a894489409 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs @@ -445,29 +445,40 @@ internal void CreateVolumetricLightingBuffers() m_VisibleVolumeBoundsBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(OrientedBBox))); m_VisibleVolumeDataBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(DensityVolumeEngineData))); + VolumetricInitializeNonRenderGraphResource(); + } + + internal void DestroyVolumetricLightingBuffers() + { + VolumetricCleanupNonRenderGraphResource(); + + CoreUtils.SafeRelease(m_VisibleVolumeDataBuffer); + CoreUtils.SafeRelease(m_VisibleVolumeBoundsBuffer); + + m_VisibleVolumeData = null; // free() + m_VisibleVolumeBounds = null; // free() + } + + void VolumetricInitializeNonRenderGraphResource() + { // Allocate the smallest possible 3D texture. // We will perform rescaling manually, in a custom manner, based on volume parameters. const int minSize = 4; - m_DensityBuffer = RTHandles.Alloc(minSize, minSize, minSize, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough + m_DensityBuffer = RTHandles.Alloc(minSize, minSize, minSize, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: "VBufferDensity"); m_LightingBuffer = RTHandles.Alloc(minSize, minSize, minSize, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: "VBufferLighting"); } - internal void DestroyVolumetricLightingBuffers() + void VolumetricCleanupNonRenderGraphResource() { RTHandles.Release(m_LightingBuffer); RTHandles.Release(m_DensityBuffer); - - CoreUtils.SafeRelease(m_VisibleVolumeDataBuffer); - CoreUtils.SafeRelease(m_VisibleVolumeBoundsBuffer); - - m_VisibleVolumeData = null; // free() - m_VisibleVolumeBounds = null; // free() } + // Must be called AFTER UpdateVolumetricBufferParams. internal void ResizeVolumetricLightingBuffers(HDCamera hdCamera, int frameIndex) { @@ -488,14 +499,17 @@ internal void ResizeVolumetricLightingBuffers(HDCamera hdCamera, int frameIndex) var currIdx = (frameIndex + 0) & 1; var prevIdx = (frameIndex + 1) & 1; - var currentParams = hdCamera.vBufferParams[currIdx]; - - ResizeVolumetricBuffer(ref m_DensityBuffer, "VBufferDensity", currentParams.viewportSize.x, - currentParams.viewportSize.y, - currentParams.viewportSize.z); - ResizeVolumetricBuffer(ref m_LightingBuffer, "VBufferLighting", currentParams.viewportSize.x, - currentParams.viewportSize.y, - currentParams.viewportSize.z); + if (!m_EnableRenderGraph) // Render Texture are not allocated when render graph is enabled. + { + var currentParams = hdCamera.vBufferParams[currIdx]; + + ResizeVolumetricBuffer(ref m_DensityBuffer, "VBufferDensity", currentParams.viewportSize.x, + currentParams.viewportSize.y, + currentParams.viewportSize.z); + ResizeVolumetricBuffer(ref m_LightingBuffer, "VBufferLighting", currentParams.viewportSize.x, + currentParams.viewportSize.y, + currentParams.viewportSize.z); + } } void InitializeVolumetricLighting() @@ -550,16 +564,13 @@ void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, in RTH int currIdx = (frameIndex + 0) & 1; var currParams = hdCamera.vBufferParams[currIdx]; - + GizmoSubset,kgmsjrhl // The lighting & density buffers are shared by all cameras. // The history & feedback buffers are specific to the camera. // These 2 types of buffers can have different sizes. // Additionally, history buffers can have different sizes, since they are not resized at the same time. Vector3Int lightingBufferSize = new Vector3Int(m_LightingBuffer.rt.width, m_LightingBuffer.rt.height, m_LightingBuffer.rt.volumeDepth); - Debug.Assert(m_LightingBuffer.rt.width == m_DensityBuffer.rt.width); - Debug.Assert(m_LightingBuffer.rt.height == m_DensityBuffer.rt.height); - var cvp = currParams.viewportSize; // Adjust slices for XR rendering: VBuffer is shared for all single-pass views @@ -576,18 +587,6 @@ void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, in RTH cb._VBufferRcpInstancedViewCount = 1.0f / hdCamera.viewCount; } - void PushVolumetricLightingGlobalParams(HDCamera hdCamera, CommandBuffer cmd, int frameIndex) - { - if (!Fog.IsVolumetricFogEnabled(hdCamera)) - { - cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, HDUtils.clearTexture3D); - } - else - { - cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_LightingBuffer); - } - } - DensityVolumeList PrepareVisibleDensityVolumeList(HDCamera hdCamera, CommandBuffer cmd, float time) { DensityVolumeList densityVolumes = new DensityVolumeList(); @@ -722,24 +721,12 @@ unsafe void UpdateShaderVariableslVolumetrics(ref ShaderVariablesVolumetric cb, // The history & feedback buffers are specific to the camera. // These 2 types of buffers can have different sizes. // Additionally, history buffers can have different sizes, since they are not resized at the same time. - Vector3Int lightingBufferSize = new Vector3Int(m_LightingBuffer.rt.width, m_LightingBuffer.rt.height, m_LightingBuffer.rt.volumeDepth); - - Debug.Assert(m_LightingBuffer.rt.width == m_DensityBuffer.rt.width); - Debug.Assert(m_LightingBuffer.rt.height == m_DensityBuffer.rt.height); - Vector3Int historyBufferSize = Vector3Int.zero; if (hdCamera.IsVolumetricReprojectionEnabled()) { RTHandle historyRT = hdCamera.volumetricHistoryBuffers[prevIdx]; - historyBufferSize = new Vector3Int(historyRT.rt.width, historyRT.rt.height, historyRT.rt.volumeDepth); - - // Handle case of first frame. When we are on the first frame, we reuse the value of original frame. - if (historyBufferSize.x == 0.0f && historyBufferSize.y == 0.0f) - { - historyBufferSize = lightingBufferSize; - } } cb._VBufferVoxelSize = currParams.voxelSize; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 00b5f363e65..23c527fe2e2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -882,6 +882,8 @@ void InitializeNonRenderGraphResources() m_ShadowManager.InitializeNonRenderGraphResources(); m_AmbientOcclusionSystem.InitializeNonRenderGraphResources(); m_PostProcessSystem.InitializeNonRenderGraphResources(asset); + VolumetricInitializeNonRenderGraphResource(); + s_lightVolumes.InitializeNonRenderGraphResources(); } void CleanupNonRenderGraphResources() @@ -890,6 +892,8 @@ void CleanupNonRenderGraphResources() m_ShadowManager.CleanupNonRenderGraphResources(); m_AmbientOcclusionSystem.CleanupNonRenderGraphResources(); m_PostProcessSystem.CleanupNonRenderGraphResources(); + VolumetricCleanupNonRenderGraphResource(); + s_lightVolumes.CleanupNonRenderGraphResources(); } void InitializeDebugMaterials() @@ -2135,7 +2139,7 @@ AOVRequestData aovRequest if (m_EnableRenderGraph) { - //ExecuteWithRenderGraph(renderRequest, aovRequest, aovBuffers, renderContext, cmd); + ExecuteWithRenderGraph(renderRequest, aovRequest, aovBuffers, renderContext, cmd); return; } From 4baa326f6d0f15c30d1a78aae2e3509a914b029b Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Wed, 29 Apr 2020 14:07:53 +0200 Subject: [PATCH 05/19] Fixed volumetric --- .../VolumetricLighting/VolumetricLighting.cs | 25 +++++++++++++------ .../HDRenderPipeline.LightLoop.cs | 1 - .../RenderPipeline/HDRenderPipeline.cs | 4 +-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs index 0a894489409..75e1f2e48b4 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs @@ -212,6 +212,7 @@ public partial class HDRenderPipeline // These two buffers do not depend on the frameID and are therefore shared by all views. RTHandle m_DensityBuffer; RTHandle m_LightingBuffer; + Vector3Int m_CurrentVolumetricBufferSize; ShaderVariablesVolumetric m_ShaderVariablesVolumetricCB = new ShaderVariablesVolumetric(); @@ -339,7 +340,7 @@ static internal void UpdateVolumetricBufferParams(HDCamera hdCamera, int frameIn // Do not access 'rt.name', it allocates memory every time... // Have to manually cache and pass the name. - static internal void ResizeVolumetricBuffer(ref RTHandle rt, string name, int viewportWidth, int viewportHeight, int viewportDepth) + static internal bool ResizeVolumetricBuffer(ref RTHandle rt, string name, int viewportWidth, int viewportHeight, int viewportDepth) { Debug.Assert(rt != null); @@ -359,7 +360,11 @@ static internal void ResizeVolumetricBuffer(ref RTHandle rt, string name, int vi rt = RTHandles.Alloc(width, height, depth, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: name); + + return true; } + + return false; } static internal void CreateVolumetricHistoryBuffers(HDCamera hdCamera, int bufferCount) @@ -502,13 +507,19 @@ internal void ResizeVolumetricLightingBuffers(HDCamera hdCamera, int frameIndex) if (!m_EnableRenderGraph) // Render Texture are not allocated when render graph is enabled. { var currentParams = hdCamera.vBufferParams[currIdx]; + bool bufferResized = false; - ResizeVolumetricBuffer(ref m_DensityBuffer, "VBufferDensity", currentParams.viewportSize.x, + bufferResized |= ResizeVolumetricBuffer(ref m_DensityBuffer, "VBufferDensity", currentParams.viewportSize.x, currentParams.viewportSize.y, currentParams.viewportSize.z); ResizeVolumetricBuffer(ref m_LightingBuffer, "VBufferLighting", currentParams.viewportSize.x, currentParams.viewportSize.y, currentParams.viewportSize.z); + + if (bufferResized) + { + m_CurrentVolumetricBufferSize = currentParams.viewportSize; + } } } @@ -551,7 +562,7 @@ static float CornetteShanksPhasePartConstant(float anisotropy) return (3.0f / (8.0f * Mathf.PI)) * (1.0f - g * g) / (2.0f + g * g); } - void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, in RTHandleProperties sharedRTHandleProperties, HDCamera hdCamera) + void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, HDCamera hdCamera) { if (!Fog.IsVolumetricFogEnabled(hdCamera)) { @@ -564,13 +575,11 @@ void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, in RTH int currIdx = (frameIndex + 0) & 1; var currParams = hdCamera.vBufferParams[currIdx]; - GizmoSubset,kgmsjrhl + // The lighting & density buffers are shared by all cameras. // The history & feedback buffers are specific to the camera. // These 2 types of buffers can have different sizes. // Additionally, history buffers can have different sizes, since they are not resized at the same time. - Vector3Int lightingBufferSize = new Vector3Int(m_LightingBuffer.rt.width, m_LightingBuffer.rt.height, m_LightingBuffer.rt.volumeDepth); - var cvp = currParams.viewportSize; // Adjust slices for XR rendering: VBuffer is shared for all single-pass views @@ -579,8 +588,8 @@ void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, in RTH cb._VBufferViewportSize = new Vector4(cvp.x, cvp.y, 1.0f / cvp.x, 1.0f / cvp.y); cb._VBufferSliceCount = sliceCount; cb._VBufferRcpSliceCount = 1.0f / sliceCount; - cb._VBufferLightingViewportScale = currParams.ComputeViewportScale(lightingBufferSize); - cb._VBufferLightingViewportLimit = currParams.ComputeViewportLimit(lightingBufferSize); + cb._VBufferLightingViewportScale = currParams.ComputeViewportScale(m_CurrentVolumetricBufferSize); + cb._VBufferLightingViewportLimit = currParams.ComputeViewportLimit(m_CurrentVolumetricBufferSize); cb._VBufferDistanceEncodingParams = currParams.depthEncodingParams; cb._VBufferDistanceDecodingParams = currParams.depthDecodingParams; cb._VBufferLastSliceDist = currParams.ComputeLastSliceDistance(sliceCount); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs index 81211667b5d..9392597b570 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs @@ -408,7 +408,6 @@ class RenderContactShadowPassData public TextureHandle depthTexture; public TextureHandle contactShadowsTexture; public ComputeBufferHandle lightList; - public HDShadowManager shadowManager; } TextureHandle RenderContactShadows(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthTexture, BuildGPULightListOutput lightLists, int firstMipOffsetY) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 23c527fe2e2..452a0be7cd6 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -1072,7 +1072,7 @@ void DisposeProbeCameraPool() // Dispose of Render Pipeline can be call either by OnValidate() or by OnDisable(). // Inside an OnValidate() call we can't call a DestroyImmediate(). // Here we are releasing our singleton to not leak while doing a domain reload. - // However this is doing a call to DestroyImmediate(). + // However this is doing a call to DestroyImmediate(). // To workaround this, and was we only leak with Singleton while doing domain reload (and not in OnValidate) // we are detecting if we are in an OnValidate call and releasing the Singleton only if it is not the case. if (!m_Asset.isInOnValidateCall) @@ -1111,7 +1111,7 @@ void UpdateShaderVariablesGlobalCB(HDCamera hdCamera, CommandBuffer cmd) Fog.UpdateShaderVariablesGlobalCB(ref m_ShaderVariablesGlobalCB, hdCamera); UpdateShaderVariablesGlobalSubsurface(ref m_ShaderVariablesGlobalCB, hdCamera); UpdateShaderVariablesGlobalDecal(ref m_ShaderVariablesGlobalCB, hdCamera); - UpdateShaderVariablesGlobalVolumetrics(ref m_ShaderVariablesGlobalCB, RTHandles.rtHandleProperties, hdCamera); + UpdateShaderVariablesGlobalVolumetrics(ref m_ShaderVariablesGlobalCB, hdCamera); m_ShadowManager.UpdateShaderVariablesGlobalCB(ref m_ShaderVariablesGlobalCB); UpdateShaderVariablesGlobalLightLoop(ref m_ShaderVariablesGlobalCB, hdCamera); UpdateShaderVariablesGlobalProbeVolumes(ref m_ShaderVariablesGlobalCB, hdCamera); From c7cca48ec2295f28ac421d53fa49e6a8cf92b67d Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Wed, 29 Apr 2020 16:26:26 +0200 Subject: [PATCH 06/19] Fixed deallocation of SSS buffers --- .../Runtime/Textures/RTHandleSystem.cs | 10 +++++++++- .../SubsurfaceScatteringManager.cs | 9 ++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Textures/RTHandleSystem.cs b/com.unity.render-pipelines.core/Runtime/Textures/RTHandleSystem.cs index e5ce6686619..e008a53ecb2 100644 --- a/com.unity.render-pipelines.core/Runtime/Textures/RTHandleSystem.cs +++ b/com.unity.render-pipelines.core/Runtime/Textures/RTHandleSystem.cs @@ -96,7 +96,15 @@ public void Dispose() /// Number of MSAA samples for automatically scaled RTHandles. public void Initialize(int width, int height, bool scaledRTsupportsMSAA, MSAASamples scaledRTMSAASamples) { - Debug.Assert(m_AutoSizedRTs.Count == 0, "RTHandle.Initialize should only be called once before allocating any Render Texture. This may be caused by an unreleased RTHandle resource."); + if (m_AutoSizedRTs.Count != 0) + { + string leakingResources = "Unreleased RTHandles:"; + foreach (var rt in m_AutoSizedRTs) + { + leakingResources = string.Format("{0}\n {1}", leakingResources, rt.name); + } + Debug.LogError(string.Format("RTHandle.Initialize should only be called once before allocating any Render Texture. This may be caused by an unreleased RTHandle resource.\n{0}\n", leakingResources)); + } m_MaxWidths = width; m_MaxHeights = height; diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs index f6bd5d4c157..59b7da33195 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs @@ -84,6 +84,10 @@ void DestroySSSBuffers() { RTHandles.Release(m_SSSColorMSAA); RTHandles.Release(m_SSSCameraFilteringBuffer); + if (!m_SSSReuseGBufferMemory) + { + RTHandles.Release(m_SSSColor); + } } RTHandle GetSSSBuffer() @@ -117,11 +121,6 @@ void CleanupSubsurfaceScattering() { CoreUtils.Destroy(m_CombineLightingPass); CoreUtils.Destroy(m_SSSCopyStencilForSplitLighting); - if (!m_SSSReuseGBufferMemory) - { - RTHandles.Release(m_SSSColor); - } - DestroySSSBuffers(); } From 960c0a524cde63ba998ca5a974cef8c4528415ca Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Wed, 29 Apr 2020 16:33:30 +0200 Subject: [PATCH 07/19] Review feedback fixes. --- .../RenderGraph/RenderGraphDefaultResources.cs | 2 +- .../Runtime/PostProcessing/PostProcessSystem.cs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs index 87a8bb68e30..05f8ad1c2d8 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs @@ -25,7 +25,7 @@ public class RenderGraphDefaultResources public TextureHandle blackTextureXR { get; private set; } /// Default black (UInt) XR 2D texture. public TextureHandle blackUIntTextureXR { get; private set; } - /// Default blac XR 3D texture. + /// Default black XR 3D texture. public TextureHandle blackTexture3DXR { get; private set; } /// Default white XR 2D texture. public TextureHandle whiteTextureXR { get; private set; } diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 5ffa4b2cb04..f2bf55041de 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -157,9 +157,10 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources m_UseSafePath = SystemInfo.graphicsDeviceVendor .ToLowerInvariant().Contains("intel"); - var settings = hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings; - m_LutSize = settings.lutSize; + var postProcessSettings = hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings; + m_LutSize = postProcessSettings.lutSize; + // Call after initializing m_LutSize as it's needed for render target allocation. InitializeNonRenderGraphResources(hdAsset); // Grading specific @@ -180,16 +181,16 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources // relying on (breaks determinism in their code) m_Random = new System.Random(); - m_ColorFormat = (GraphicsFormat)settings.bufferFormat; + m_ColorFormat = (GraphicsFormat)postProcessSettings.bufferFormat; m_KeepAlpha = false; // if both rendering and post-processing support an alpha channel, then post-processing will process (or copy) the alpha - m_EnableAlpha = settings.supportsAlpha && settings.supportsAlpha; + m_EnableAlpha = hdAsset.currentPlatformRenderPipelineSettings.supportsAlpha && postProcessSettings.supportsAlpha; if (m_EnableAlpha == false) { // if only rendering has an alpha channel (and not post-processing), then we just copy the alpha to the output (but we don't process it). - m_KeepAlpha = settings.supportsAlpha; + m_KeepAlpha = hdAsset.currentPlatformRenderPipelineSettings.supportsAlpha; } } From 4c67bfdb0633fc53110b72f9a5c4280f4608a049 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Wed, 29 Apr 2020 16:38:37 +0200 Subject: [PATCH 08/19] Init order fix for post process --- .../Runtime/PostProcessing/PostProcessSystem.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index f2bf55041de..af115aa692b 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -160,9 +160,6 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources var postProcessSettings = hdAsset.currentPlatformRenderPipelineSettings.postProcessSettings; m_LutSize = postProcessSettings.lutSize; - // Call after initializing m_LutSize as it's needed for render target allocation. - InitializeNonRenderGraphResources(hdAsset); - // Grading specific m_HableCurve = new HableCurve(); @@ -172,8 +169,6 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources // TODO: Write a version that uses structured buffer instead of texture to do atomic as Metal doesn't support atomics on textures. m_MotionBlurSupportsScattering = m_MotionBlurSupportsScattering && (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Metal); - FillEmptyExposureTexture(); - // Initialize our target pool to ease RT management m_Pool = new TargetPool(); @@ -192,6 +187,9 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources // if only rendering has an alpha channel (and not post-processing), then we just copy the alpha to the output (but we don't process it). m_KeepAlpha = hdAsset.currentPlatformRenderPipelineSettings.supportsAlpha; } + + // Call after initializing m_LutSize and m_KeepAlpha as it's needed for render target allocation. + InitializeNonRenderGraphResources(hdAsset); } public void Cleanup() @@ -257,6 +255,8 @@ public void InitializeNonRenderGraphResources(HDRenderPipelineAsset hdAsset) enableRandomWrite: true, name: "Empty EV100 Exposure" ); + FillEmptyExposureTexture(); + // Misc targets m_TempTexture1024 = RTHandles.Alloc( 1024, 1024, colorFormat: GraphicsFormat.R16G16_SFloat, From 6c38c3ff0339c8668ae62f1af99f4d0e01de0076 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Tue, 5 May 2020 17:39:50 +0200 Subject: [PATCH 09/19] WIP: refactoring of render graph compilation and resource allocation to prepare for async dependencies. --- .../Runtime/RenderGraph/RenderGraph.cs | 440 ++++++++++++------ .../Runtime/RenderGraph/RenderGraphBuilder.cs | 67 ++- .../Runtime/RenderGraph/RenderGraphLogger.cs | 4 +- .../Runtime/RenderGraph/RenderGraphPass.cs | 154 ++++++ .../RenderGraph/RenderGraphPass.cs.meta | 11 + .../RenderGraphResourceRegistry.cs | 144 +++--- .../AmbientOcclusion.RenderGraph.cs | 4 +- .../PostProcessSystem.RenderGraph.cs | 6 +- .../Runtime/RenderPipeline/Camera/HDCamera.cs | 4 +- .../RenderPipeline/HDRenderPipeline.Debug.cs | 12 +- .../HDRenderPipeline.LightLoop.cs | 8 +- .../HDRenderPipeline.Prepass.cs | 9 +- .../HDRenderPipeline.RenderGraph.cs | 34 +- .../HDRenderPipeline.SubsurfaceScattering.cs | 4 +- .../RenderPipeline/HDRenderPipeline.cs | 46 +- 15 files changed, 638 insertions(+), 309 deletions(-) create mode 100644 com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs create mode 100644 com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs.meta diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index b6758e37ad1..772fe1ceefe 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -1,8 +1,6 @@ using System; -using System.Diagnostics; using System.Collections.Generic; using UnityEngine.Rendering; -using UnityEngine.Profiling; namespace UnityEngine.Experimental.Rendering.RenderGraphModule { @@ -95,106 +93,64 @@ public class RenderGraph ///Maximum number of MRTs supported by Render Graph. public static readonly int kMaxMRTCount = 8; - [DebuggerDisplay("RenderPass ({name})")] - internal abstract class RenderPass - { - internal RenderFunc GetExecuteDelegate() - where PassData : class, new() => ((RenderPass)this).renderFunc; - - internal abstract void Execute(RenderGraphContext renderGraphContext); - internal abstract void Release(RenderGraphContext renderGraphContext); - internal abstract bool HasRenderFunc(); - - internal string name; - internal int index; - internal ProfilingSampler customSampler; - internal List textureReadList = new List(); - internal List textureWriteList = new List(); - internal List bufferReadList = new List(); - internal List bufferWriteList = new List(); - internal List usedRendererListList = new List(); - internal bool enableAsyncCompute; - internal TextureHandle depthBuffer { get { return m_DepthBuffer; } } - internal TextureHandle[] colorBuffers { get { return m_ColorBuffers; } } - internal int colorBufferMaxIndex { get { return m_MaxColorBufferIndex; } } - - protected TextureHandle[] m_ColorBuffers = new TextureHandle[kMaxMRTCount]; - protected TextureHandle m_DepthBuffer; - protected int m_MaxColorBufferIndex = -1; - - internal void Clear() - { - name = ""; - index = -1; - customSampler = null; - textureReadList.Clear(); - textureWriteList.Clear(); - bufferReadList.Clear(); - bufferWriteList.Clear(); - usedRendererListList.Clear(); - enableAsyncCompute = false; - - // Invalidate everything - m_MaxColorBufferIndex = -1; - m_DepthBuffer = new TextureHandle(); - for (int i = 0; i < RenderGraph.kMaxMRTCount; ++i) - { - m_ColorBuffers[i] = new TextureHandle(); - } - } - - internal void SetColorBuffer(TextureHandle resource, int index) - { - Debug.Assert(index < RenderGraph.kMaxMRTCount && index >= 0); - m_MaxColorBufferIndex = Math.Max(m_MaxColorBufferIndex, index); - m_ColorBuffers[index] = resource; - textureWriteList.Add(resource); - } + internal struct ResourceUsageInfo + { + public List producers; + public bool resourceCreated; + public int lastReadPassIndex; + public int firstWritePassIndex; + public int refCount; - internal void SetDepthBuffer(TextureHandle resource, DepthAccess flags) + public void Reset() { - m_DepthBuffer = resource; - if ((flags | DepthAccess.Read) != 0) - textureReadList.Add(resource); - if ((flags | DepthAccess.Write) != 0) - textureWriteList.Add(resource); - + if (producers == null) + producers = new List(); + + producers.Clear(); + resourceCreated = false; + lastReadPassIndex = -1; + firstWritePassIndex = int.MaxValue; + refCount = 0; } } - internal sealed class RenderPass : RenderPass - where PassData : class, new() + internal struct PassExecutionInfo { - internal PassData data; - internal RenderFunc renderFunc; + public List textureCreateList; + public List textureReleaseList; + public int refCount; + public bool pruned; + public bool hasSideEffect; - internal override void Execute(RenderGraphContext renderGraphContext) + public void Reset() { - GetExecuteDelegate()(data, renderGraphContext); - } - - internal override void Release(RenderGraphContext renderGraphContext) - { - Clear(); - renderGraphContext.renderGraphPool.Release(data); - data = null; - renderFunc = null; - renderGraphContext.renderGraphPool.Release(this); - } + if (textureCreateList == null) + { + textureCreateList = new List(); + textureReleaseList = new List(); + } - internal override bool HasRenderFunc() - { - return renderFunc != null; + textureCreateList.Clear(); + textureReleaseList.Clear(); + refCount = 0; + pruned = false; + hasSideEffect = false; } } - RenderGraphResourceRegistry m_Resources; - RenderGraphObjectPool m_RenderGraphPool = new RenderGraphObjectPool(); - List m_RenderPasses = new List(); - List m_RendererLists = new List(); - RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams(); - RenderGraphLogger m_Logger = new RenderGraphLogger(); - RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources(); + RenderGraphResourceRegistry m_Resources; + RenderGraphObjectPool m_RenderGraphPool = new RenderGraphObjectPool(); + List m_RenderPasses = new List(); + List m_RendererLists = new List(); + RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams(); + RenderGraphLogger m_Logger = new RenderGraphLogger(); + RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources(); + + // Compiled Render Graph info. + DynamicArray m_TextureUsageInfo = new DynamicArray(); + DynamicArray m_BufferUsageInfo = new DynamicArray(); + DynamicArray m_PassExecutionInfo = new DynamicArray(); + Stack m_PruningStack = new Stack(); #region Public Interface @@ -336,12 +292,8 @@ public ComputeBufferHandle ImportComputeBuffer(ComputeBuffer computeBuffer) /// A new instance of a RenderGraphBuilder used to setup the new Render Pass. public RenderGraphBuilder AddRenderPass(string passName, out PassData passData, ProfilingSampler sampler = null) where PassData : class, new() { - var renderPass = m_RenderGraphPool.Get>(); - renderPass.Clear(); - renderPass.index = m_RenderPasses.Count; - renderPass.data = m_RenderGraphPool.Get(); - renderPass.name = passName; - renderPass.customSampler = sampler; + var renderPass = m_RenderGraphPool.Get>(); + renderPass.Initialize(m_RenderPasses.Count, m_RenderGraphPool.Get(), passName, sampler); passData = renderPass.data; @@ -350,37 +302,167 @@ public ComputeBufferHandle ImportComputeBuffer(ComputeBuffer computeBuffer) return new RenderGraphBuilder(renderPass, m_Resources); } - /// - /// Execute the Render Graph in its current state. - /// - /// ScriptableRenderContext used to execute Scriptable Render Pipeline. - /// Command Buffer used for Render Passes rendering. - /// Render Graph execution parameters. - public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in RenderGraphExecuteParams parameters) + void CountReferences() { - m_Logger.Initialize(); + for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) + { + RenderGraphPass pass = m_RenderPasses[passIndex]; + ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; + + var textureRead = pass.textureReadList; + foreach (TextureHandle texture in textureRead) + { + ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + info.refCount++; + } - // Update RTHandleSystem with size for this rendering pass. - m_Resources.SetRTHandleReferenceSize(parameters.renderingWidth, parameters.renderingHeight, parameters.msaaSamples); + var textureWrite = pass.textureWriteList; + foreach (TextureHandle texture in textureWrite) + { + ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + info.producers.Add(passIndex); + passInfo.refCount++; - LogFrameInformation(parameters.renderingWidth, parameters.renderingHeight); + // Writing to an imported texture is considered as a side effect because we don't know what users will do with it outside of render graph. + if (m_Resources.IsTextureImported(texture)) + passInfo.hasSideEffect = true; + } - // First pass, traversal and pruning + // Can't share the code with a generic func as TextureHandle and ComputeBufferHandle are both struct and can't inherit from a common struct with a shared API (thanks C#) + var bufferRead = pass.bufferReadList; + foreach (ComputeBufferHandle buffer in bufferRead) + { + ref ResourceUsageInfo info = ref m_BufferUsageInfo[buffer]; + info.refCount++; + } + + var bufferWrite = pass.bufferWriteList; + foreach (ComputeBufferHandle buffer in bufferWrite) + { + ref ResourceUsageInfo info = ref m_BufferUsageInfo[buffer]; + passInfo.refCount++; + } + } + } + + void PruneUnusedPasses(DynamicArray resourceUsageList) + { + // First gather resources that are never read. + m_PruningStack.Clear(); + for (int i = 0; i < resourceUsageList.size; ++i) + { + if (resourceUsageList[i].refCount == 0) + { + m_PruningStack.Push(i); + } + } + + while (m_PruningStack.Count != 0) + { + var unusedResource = resourceUsageList[m_PruningStack.Pop()]; + foreach (var producerIndex in unusedResource.producers) + { + ref var producerInfo = ref m_PassExecutionInfo[producerIndex]; + producerInfo.refCount--; + if (producerInfo.refCount == 0 && !producerInfo.hasSideEffect) + { + // Producer is not necessary anymore as it produces zero resources + // Prune it and decrement refCount of all the textures it reads. + producerInfo.pruned = true; + RenderGraphPass pass = m_RenderPasses[producerIndex]; + foreach (var textureIndex in pass.textureReadList) + { + ref ResourceUsageInfo textureInfo = ref resourceUsageList[textureIndex]; + textureInfo.refCount--; + // If a texture is not used anymore, add it to the stack to be processed in subsequent iteration. + if (textureInfo.refCount == 0) + m_PruningStack.Push(textureIndex); + } + } + } + } + } + + void PruneUnusedPasses() + { + PruneUnusedPasses(m_TextureUsageInfo); + PruneUnusedPasses(m_BufferUsageInfo); + LogPrunedPasses(); + } + + void UpdateResourceAllocation() + { + // First go through all passes. + // - Update the last pass read index for each resource. + // - Add texture to creation list for passes that first write to a texture. for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) { - var pass = m_RenderPasses[passIndex]; + ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; + + if (passInfo.pruned) + continue; + + RenderGraphPass pass = m_RenderPasses[passIndex]; + + foreach (TextureHandle texture in pass.textureReadList) + { + ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + info.lastReadPassIndex = Math.Max(info.lastReadPassIndex, passIndex); + } - // TODO: Pruning + foreach (TextureHandle texture in pass.textureWriteList) + { + ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + if (info.firstWritePassIndex == int.MaxValue) + { + info.firstWritePassIndex = Math.Min(info.firstWritePassIndex, passIndex); + passInfo.textureCreateList.Add(texture); + } + passInfo.refCount++; + } + + // Add transient resources that are only used during this pass. + foreach (TextureHandle texture in pass.transientTextureList) + { + passInfo.textureCreateList.Add(texture); + passInfo.textureReleaseList.Add(texture); + } // Gather all renderer lists - m_RendererLists.AddRange(pass.usedRendererListList); + m_RendererLists.AddRange(m_RenderPasses[passIndex].usedRendererListList); + } + + // Now push textures to the release list of the pass that reads it last. + for (int i = 0; i < m_TextureUsageInfo.size; ++i) + { + ResourceUsageInfo textureInfo = m_TextureUsageInfo[i]; + if (textureInfo.lastReadPassIndex != -1) + { + ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[textureInfo.lastReadPassIndex]; + passInfo.textureReleaseList.Add(new TextureHandle(i)); + } } // Creates all renderer lists m_Resources.CreateRendererLists(m_RendererLists); + } + + // Traverse the render graph: + // - Determines when resources are created/released + // - Determines async compute pass synchronization + // - Prune unused render passes. + void CompileRenderGraph() + { + InitializeCompilationData(); + CountReferences(); + PruneUnusedPasses(); + UpdateResourceAllocation(); LogRendererListsCreation(); + } - // Second pass, execution + // Execute the compiled render graph + void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd) + { RenderGraphContext rgContext = new RenderGraphContext(); rgContext.cmd = cmd; rgContext.renderContext = renderContext; @@ -388,40 +470,59 @@ public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in rgContext.resources = m_Resources; rgContext.defaultResources = m_DefaultResources; - try + for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) { - for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) - { - var pass = m_RenderPasses[passIndex]; + var passInfo = m_PassExecutionInfo[passIndex]; + if (passInfo.pruned) + continue; - if (!pass.HasRenderFunc()) - { - throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", pass.name)); - } + var pass = m_RenderPasses[passIndex]; + if (!pass.HasRenderFunc()) + { + throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", pass.name)); + } - using (new ProfilingScope(cmd, pass.customSampler)) + using (new ProfilingScope(cmd, pass.customSampler)) + { + LogRenderPassBegin(pass); + using (new RenderGraphLogIndent(m_Logger)) { - LogRenderPassBegin(pass); - using (new RenderGraphLogIndent(m_Logger)) - { - PreRenderPassExecute(passIndex, pass, rgContext); - pass.Execute(rgContext); - PostRenderPassExecute(passIndex, pass, rgContext); - } + PreRenderPassExecute(passIndex, rgContext); + pass.Execute(rgContext); + PostRenderPassExecute(passIndex, rgContext); } } } - catch(Exception e) + } + + /// + /// Execute the Render Graph in its current state. + /// + /// ScriptableRenderContext used to execute Scriptable Render Pipeline. + /// Command Buffer used for Render Passes rendering. + /// Render Graph execution parameters. + public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in RenderGraphExecuteParams parameters) + { + try + { + m_Logger.Initialize(); + + // Update RTHandleSystem with size for this rendering pass. + m_Resources.SetRTHandleReferenceSize(parameters.renderingWidth, parameters.renderingHeight, parameters.msaaSamples); + + LogFrameInformation(parameters.renderingWidth, parameters.renderingHeight); + + CompileRenderGraph(); + ExecuteRenderGraph(renderContext, cmd); + } + catch (Exception e) { Debug.LogError("Render Graph Execution error"); Debug.LogException(e); } finally { - ClearRenderPasses(); - m_Resources.Clear(); - m_DefaultResources.Clear(); - m_RendererLists.Clear(); + ClearCompiledGraph(); if (m_DebugParameters.logFrameInformation || m_DebugParameters.logResources) Debug.Log(m_Logger.GetLog()); @@ -438,8 +539,33 @@ private RenderGraph() } - void PreRenderPassSetRenderTargets(in RenderPass pass, RenderGraphContext rgContext) + void ClearCompiledGraph() + { + ClearRenderPasses(); + m_Resources.Clear(); + m_DefaultResources.Clear(); + m_RendererLists.Clear(); + m_BufferUsageInfo.Clear(); + m_TextureUsageInfo.Clear(); + m_PassExecutionInfo.Clear(); + } + + void InitializeCompilationData() + { + m_BufferUsageInfo.Resize(m_Resources.GetComputeBufferResourceCount()); + for (int i = 0; i < m_BufferUsageInfo.size; ++i) + m_BufferUsageInfo[i].Reset(); + m_TextureUsageInfo.Resize(m_Resources.GetTextureResourceCount()); + for (int i = 0; i < m_TextureUsageInfo.size; ++i) + m_TextureUsageInfo[i].Reset(); + m_PassExecutionInfo.Resize(m_RenderPasses.Count); + for (int i = 0; i < m_PassExecutionInfo.size; ++i) + m_PassExecutionInfo[i].Reset(); + } + + void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) { + var pass = m_RenderPasses[passIndex]; if (pass.depthBuffer.IsValid() || pass.colorBufferMaxIndex != -1) { var mrtArray = rgContext.renderGraphPool.GetTempArray(pass.colorBufferMaxIndex + 1); @@ -481,22 +607,29 @@ void PreRenderPassSetRenderTargets(in RenderPass pass, RenderGraphContext rgCont } } - void PreRenderPassExecute(int passIndex, in RenderPass pass, RenderGraphContext rgContext) + void PreRenderPassExecute(int passIndex, RenderGraphContext rgContext) { - // TODO merge clear and setup here if possible - m_Resources.CreateAndClearTexturesForPass(rgContext, pass.index, pass.textureWriteList); - PreRenderPassSetRenderTargets(pass, rgContext); - m_Resources.PreRenderPassSetGlobalTextures(rgContext, pass.textureReadList); + // TODO RENDERGRAPH merge clear and setup here if possible + PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; + foreach (var texture in passInfo.textureCreateList) + m_Resources.CreateAndClearTexture(rgContext, texture); + + PreRenderPassSetRenderTargets(passIndex, rgContext); + m_Resources.PreRenderPassSetGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); } - void PostRenderPassExecute(int passIndex, in RenderPass pass, RenderGraphContext rgContext) + void PostRenderPassExecute(int passIndex, RenderGraphContext rgContext) { if (m_DebugParameters.unbindGlobalTextures) - m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, pass.textureReadList); + m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); m_RenderGraphPool.ReleaseAllTempAlloc(); - m_Resources.ReleaseTexturesForPass(rgContext, pass.index, pass.textureReadList, pass.textureWriteList); - pass.Release(rgContext); + + PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; + foreach (var texture in passInfo.textureReleaseList) + m_Resources.ReleaseTexture(rgContext, texture); + + m_RenderPasses[passIndex].Release(rgContext); } void ClearRenderPasses() @@ -521,7 +654,7 @@ void LogRendererListsCreation() } } - void LogRenderPassBegin(in RenderPass pass) + void LogRenderPassBegin(in RenderGraphPass pass) { if (m_DebugParameters.logFrameInformation) { @@ -529,6 +662,25 @@ void LogRenderPassBegin(in RenderPass pass) } } + void LogPrunedPasses() + { + if (m_DebugParameters.logFrameInformation) + { + m_Logger.LogLine("Pass pruning report:"); + using (new RenderGraphLogIndent(m_Logger)) + { + for (int i = 0; i < m_PassExecutionInfo.size; ++i) + { + if (m_PassExecutionInfo[i].pruned) + { + var pass = m_RenderPasses[i]; + m_Logger.LogLine("{0} (index: {1})", pass.name, pass.index); + } + } + } + } + } + #endregion } } diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs index b100ba50abc..404565f4297 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs @@ -8,7 +8,7 @@ namespace UnityEngine.Experimental.Rendering.RenderGraphModule /// public struct RenderGraphBuilder : IDisposable { - RenderGraph.RenderPass m_RenderPass; + RenderGraphPass m_RenderPass; RenderGraphResourceRegistry m_Resources; bool m_Disposed; @@ -22,8 +22,9 @@ public struct RenderGraphBuilder : IDisposable /// An updated resource handle to the input resource. public TextureHandle UseColorBuffer(TextureHandle input, int index) { + CheckTransientTexture(input); + m_RenderPass.SetColorBuffer(input, index); - m_Resources.UpdateTextureFirstWrite(input, m_RenderPass.index); return input; } @@ -35,11 +36,9 @@ public TextureHandle UseColorBuffer(TextureHandle input, int index) /// An updated resource handle to the input resource. public TextureHandle UseDepthBuffer(TextureHandle input, DepthAccess flags) { + CheckTransientTexture(input); + m_RenderPass.SetDepthBuffer(input, flags); - if ((flags | DepthAccess.Read) != 0) - m_Resources.UpdateTextureLastRead(input, m_RenderPass.index); - if ((flags | DepthAccess.Write) != 0) - m_Resources.UpdateTextureFirstWrite(input, m_RenderPass.index); return input; } @@ -50,8 +49,9 @@ public TextureHandle UseDepthBuffer(TextureHandle input, DepthAccess flags) /// An updated resource handle to the input resource. public TextureHandle ReadTexture(TextureHandle input) { - m_RenderPass.textureReadList.Add(input); - m_Resources.UpdateTextureLastRead(input, m_RenderPass.index); + CheckTransientTexture(input); + + m_RenderPass.AddTextureRead(input); return input; } @@ -62,12 +62,39 @@ public TextureHandle ReadTexture(TextureHandle input) /// An updated resource handle to the input resource. public TextureHandle WriteTexture(TextureHandle input) { + CheckTransientTexture(input); + // TODO: Manage resource "version" for debugging purpose - m_RenderPass.textureWriteList.Add(input); - m_Resources.UpdateTextureFirstWrite(input, m_RenderPass.index); + m_RenderPass.AddTextureWrite(input); return input; } + /// + /// Create a new Render Graph Texture resource. + /// This texture will only be available for the current pass and will be assumed to be both written and read so users don't need to add explicit read/write declarations. + /// + /// Texture descriptor. + /// A new transient TextureHandle. + public TextureHandle CreateTransientTexture(in TextureDesc desc) + { + var result = m_Resources.CreateTexture(desc, 0, m_RenderPass.index); + m_RenderPass.AddTransientTexture(result); + return result; + } + + /// + /// Create a new Render Graph Texture resource using the descriptor from another texture. + /// + /// Texture from which the descriptor should be used. + /// A new transient TextureHandle. + public TextureHandle CreateTransientTexture(TextureHandle texture) + { + var desc = m_Resources.GetTextureResourceDesc(texture); + var result = m_Resources.CreateTexture(desc, 0, m_RenderPass.index); + m_RenderPass.AddTransientTexture(result); + return result; + } + /// /// Specify a Renderer List resource to use during the pass. /// @@ -75,7 +102,7 @@ public TextureHandle WriteTexture(TextureHandle input) /// An updated resource handle to the input resource. public RendererListHandle UseRendererList(RendererListHandle input) { - m_RenderPass.usedRendererListList.Add(input); + m_RenderPass.UseRendererList(input); return input; } @@ -86,7 +113,7 @@ public RendererListHandle UseRendererList(RendererListHandle input) /// An updated resource handle to the input resource. public ComputeBufferHandle ReadComputeBuffer(ComputeBufferHandle input) { - m_RenderPass.bufferReadList.Add(input); + m_RenderPass.AddBufferRead(input); return input; } @@ -97,7 +124,7 @@ public ComputeBufferHandle ReadComputeBuffer(ComputeBufferHandle input) /// An updated resource handle to the input resource. public ComputeBufferHandle WriteComputeBuffer(ComputeBufferHandle input) { - m_RenderPass.bufferWriteList.Add(input); + m_RenderPass.AddBufferWrite(input); return input; } @@ -109,7 +136,7 @@ public ComputeBufferHandle WriteComputeBuffer(ComputeBufferHandle input) /// Render function for the pass. public void SetRenderFunc(RenderFunc renderFunc) where PassData : class, new() { - ((RenderGraph.RenderPass)m_RenderPass).renderFunc = renderFunc; + ((RenderGraphPass)m_RenderPass).renderFunc = renderFunc; } /// @@ -118,7 +145,7 @@ public ComputeBufferHandle WriteComputeBuffer(ComputeBufferHandle input) /// Set to true to enable asynchronous compute. public void EnableAsyncCompute(bool value) { - m_RenderPass.enableAsyncCompute = value; + m_RenderPass.EnableAsyncCompute(value); } /// @@ -131,7 +158,7 @@ public void Dispose() #endregion #region Internal Interface - internal RenderGraphBuilder(RenderGraph.RenderPass renderPass, RenderGraphResourceRegistry resources) + internal RenderGraphBuilder(RenderGraphPass renderPass, RenderGraphResourceRegistry resources) { m_RenderPass = renderPass; m_Resources = resources; @@ -145,6 +172,14 @@ void Dispose(bool disposing) m_Disposed = true; } + + void CheckTransientTexture(TextureHandle input) + { + if (input.transientPassIndex != -1 && input.transientPassIndex != m_RenderPass.index) + { + throw new ArgumentException($"Trying to use a transient texture (pass index {input.transientPassIndex}) in a different pass (pass index {m_RenderPass.index}."); + } + } #endregion } } diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphLogger.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphLogger.cs index b41e1fcfe29..df946c91743 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphLogger.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphLogger.cs @@ -25,10 +25,12 @@ public void Dispose() void Dispose(bool disposing) { + Debug.Assert(m_Logger != null, "RenderGraphLogIndent: logger parameter should not be null."); + if (m_Disposed) return; - if (disposing) + if (disposing && m_Logger != null) { m_Logger.DecrementIndentation(m_Indentation); } diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs new file mode 100644 index 00000000000..65ba5ade4bd --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs @@ -0,0 +1,154 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace UnityEngine.Experimental.Rendering.RenderGraphModule +{ + [DebuggerDisplay("RenderPass ({name})")] + abstract class RenderGraphPass + { + public RenderFunc GetExecuteDelegate() + where PassData : class, new() => ((RenderGraphPass)this).renderFunc; + + public abstract void Execute(RenderGraphContext renderGraphContext); + public abstract void Release(RenderGraphContext renderGraphContext); + public abstract bool HasRenderFunc(); + + public string name { get; protected set; } + public int index { get; protected set; } + public ProfilingSampler customSampler { get; protected set; } + public bool enableAsyncCompute { get; protected set; } + + public TextureHandle depthBuffer { get; protected set; } + public TextureHandle[] colorBuffers { get; protected set; } = new TextureHandle[RenderGraph.kMaxMRTCount]; + public int colorBufferMaxIndex { get; protected set; } = -1; + public int refCount { get; protected set; } + + List m_TextureReadList = new List(); + List m_TextureWriteList = new List(); + List m_TransientTextureList = new List(); + List m_BufferReadList = new List(); + List m_BufferWriteList = new List(); + List m_UsedRendererListList = new List(); + + public IReadOnlyCollection textureReadList { get { return m_TextureReadList; } } + public IReadOnlyCollection textureWriteList { get { return m_TextureWriteList; } } + public IReadOnlyCollection transientTextureList { get { return m_TransientTextureList; } } + public IReadOnlyCollection bufferReadList { get { return m_BufferReadList; } } + public IReadOnlyCollection bufferWriteList { get { return m_BufferWriteList; } } + public IReadOnlyCollection usedRendererListList { get { return m_UsedRendererListList; } } + + public void Clear() + { + name = ""; + index = -1; + customSampler = null; + m_TextureReadList.Clear(); + m_TextureWriteList.Clear(); + m_BufferReadList.Clear(); + m_BufferWriteList.Clear(); + m_TransientTextureList.Clear(); + m_UsedRendererListList.Clear(); + enableAsyncCompute = false; + refCount = 0; + + // Invalidate everything + colorBufferMaxIndex = -1; + depthBuffer = new TextureHandle(); + for (int i = 0; i < RenderGraph.kMaxMRTCount; ++i) + { + colorBuffers[i] = new TextureHandle(); + } + } + + public void AddTextureWrite(TextureHandle texture) + { + m_TextureWriteList.Add(texture); + refCount++; + } + + public void AddTextureRead(TextureHandle texture) + { + m_TextureReadList.Add(texture); + } + + public void AddBufferWrite(ComputeBufferHandle buffer) + { + m_BufferWriteList.Add(buffer); + refCount++; + } + + public void AddTransientTexture(TextureHandle texture) + { + m_TransientTextureList.Add(texture); + } + + public void AddBufferRead(ComputeBufferHandle buffer) + { + m_BufferReadList.Add(buffer); + } + + public void UseRendererList(RendererListHandle rendererList) + { + m_UsedRendererListList.Add(rendererList); + } + + public void EnableAsyncCompute(bool value) + { + enableAsyncCompute = value; + } + + public void SetColorBuffer(TextureHandle resource, int index) + { + Debug.Assert(index < RenderGraph.kMaxMRTCount && index >= 0); + colorBufferMaxIndex = Math.Max(colorBufferMaxIndex, index); + colorBuffers[index] = resource; + AddTextureWrite(resource); + } + + public void SetDepthBuffer(TextureHandle resource, DepthAccess flags) + { + depthBuffer = resource; + if ((flags | DepthAccess.Read) != 0) + AddTextureRead(resource); + if ((flags | DepthAccess.Write) != 0) + AddTextureWrite(resource); + } + } + + internal sealed class RenderGraphPass : RenderGraphPass + where PassData : class, new() + { + internal PassData data; + internal RenderFunc renderFunc; + + public override void Execute(RenderGraphContext renderGraphContext) + { + GetExecuteDelegate()(data, renderGraphContext); + } + + public void Initialize(int passIndex, PassData passData, string passName, ProfilingSampler sampler) + { + Clear(); + index = passIndex; + data = passData; + name = passName; + customSampler = sampler; + } + + public override void Release(RenderGraphContext renderGraphContext) + { + Clear(); + renderGraphContext.renderGraphPool.Release(data); + data = null; + renderFunc = null; + renderGraphContext.renderGraphPool.Release(this); + } + + public override bool HasRenderFunc() + { + return renderFunc != null; + } + } +} diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs.meta b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs.meta new file mode 100644 index 00000000000..9f00928f05e --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 377a2b96156b1344eaf58df67e35de17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs index 51c76b3bedc..0126d0dc40f 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs @@ -18,7 +18,8 @@ public struct TextureHandle { bool m_IsValid; internal int handle { get; private set; } - internal TextureHandle(int handle) { this.handle = handle; m_IsValid = true; } + internal int transientPassIndex { get; private set; } + internal TextureHandle(int handle, int transientPassIndex = -1) { this.handle = handle; m_IsValid = true; this.transientPassIndex = transientPassIndex; } /// /// Conversion to int. /// @@ -30,6 +31,7 @@ public struct TextureHandle /// /// True if the handle is valid. public bool IsValid() => m_IsValid; + } /// @@ -292,8 +294,6 @@ internal struct TextureResource public bool imported; public RTHandle rt; public int cachedHash; - public int firstWritePassIndex; - public int lastReadPassIndex; public int shaderProperty; public bool wasReleased; @@ -321,8 +321,6 @@ void Reset() imported = false; rt = null; cachedHash = -1; - firstWritePassIndex = int.MaxValue; - lastReadPassIndex = -1; wasReleased = false; } } @@ -441,6 +439,11 @@ internal TextureHandle ImportTexture(RTHandle rt, int shaderProperty = 0) return new TextureHandle(newHandle); } + internal bool IsTextureImported(TextureHandle handle) + { + return handle.IsValid() ? GetTextureResource(handle).imported : false; + } + internal TextureHandle ImportBackbuffer(RenderTargetIdentifier rt) { if (m_CurrentBackbuffer != null) @@ -452,36 +455,17 @@ internal TextureHandle ImportBackbuffer(RenderTargetIdentifier rt) return new TextureHandle(newHandle); } - internal TextureHandle CreateTexture(in TextureDesc desc, int shaderProperty = 0) + internal TextureHandle CreateTexture(in TextureDesc desc, int shaderProperty = 0, int transientPassIndex = -1) { ValidateTextureDesc(desc); int newHandle = m_TextureResources.Add(new TextureResource(desc, shaderProperty)); - return new TextureHandle(newHandle); + return new TextureHandle(newHandle, transientPassIndex); } - internal void UpdateTextureFirstWrite(TextureHandle tex, int passIndex) + internal int GetTextureResourceCount() { - ref var res = ref GetTextureResource(tex); - res.firstWritePassIndex = Math.Min(passIndex, res.firstWritePassIndex); - - //// We increment lastRead index here so that a resource used only for a single pass can be released at the end of said pass. - //// This will also keep the resource alive as long as it is written to. - //// Typical example is a depth buffer that may never be explicitly read from but is necessary all along - /// - // PROBLEM: Increasing last read on write operation will keep the target alive even if it's not used at all so it's not good. - // If we don't do it though, it means that client code cannot write "by default" into a target as it will try to write to an already released target. - // Example: - // DepthPrepass: Writes to Depth and Normal buffers (pass will create normal buffer) - // ObjectMotion: Writes to MotionVectors and Normal => Exception because NormalBuffer is already released as it not used. - // => Solution includes : Shader Combination (without MRT for example) / Dummy Targets - //res.lastReadPassIndex = Math.Max(passIndex, res.lastReadPassIndex); - } - - internal void UpdateTextureLastRead(TextureHandle tex, int passIndex) - { - ref var res = ref GetTextureResource(tex); - res.lastReadPassIndex = Math.Max(passIndex, res.lastReadPassIndex); + return m_TextureResources.size; } ref TextureResource GetTextureResource(TextureHandle res) @@ -508,29 +492,36 @@ internal ComputeBufferHandle ImportComputeBuffer(ComputeBuffer computeBuffer) return new ComputeBufferHandle(newHandle); } - internal void CreateAndClearTexturesForPass(RenderGraphContext rgContext, int passIndex, List textures) + internal int GetComputeBufferResourceCount() + { + return m_ComputeBufferResources.size; + } + + internal ref ComputeBufferResource GetComputeBufferResource(ComputeBufferHandle res) + { + return ref m_ComputeBufferResources[res]; + } + + internal void CreateAndClearTexture(RenderGraphContext rgContext, TextureHandle texture) { - foreach (var rgResource in textures) + ref var resource = ref GetTextureResource(texture); + if (!resource.imported) { - ref var resource = ref GetTextureResource(rgResource); - if (!resource.imported && resource.firstWritePassIndex == passIndex) - { - CreateTextureForPass(ref resource); + CreateTextureForPass(ref resource); - if (resource.desc.clearBuffer || m_RenderGraphDebug.clearRenderTargetsAtCreation) + if (resource.desc.clearBuffer || m_RenderGraphDebug.clearRenderTargetsAtCreation) + { + bool debugClear = m_RenderGraphDebug.clearRenderTargetsAtCreation && !resource.desc.clearBuffer; + var name = debugClear ? "RenderGraph: Clear Buffer (Debug)" : "RenderGraph: Clear Buffer"; + using (new ProfilingScope(rgContext.cmd, ProfilingSampler.Get(RenderGraphProfileId.RenderGraphClear))) { - bool debugClear = m_RenderGraphDebug.clearRenderTargetsAtCreation && !resource.desc.clearBuffer; - var name = debugClear ? "RenderGraph: Clear Buffer (Debug)" : "RenderGraph: Clear Buffer"; - using (new ProfilingScope(rgContext.cmd, ProfilingSampler.Get(RenderGraphProfileId.RenderGraphClear))) - { - var clearFlag = resource.desc.depthBufferBits != DepthBits.None ? ClearFlag.Depth : ClearFlag.Color; - var clearColor = debugClear ? Color.magenta : resource.desc.clearColor; - CoreUtils.SetRenderTarget(rgContext.cmd, resource.rt, clearFlag, clearColor); - } + var clearFlag = resource.desc.depthBufferBits != DepthBits.None ? ClearFlag.Depth : ClearFlag.Color; + var clearColor = debugClear ? Color.magenta : resource.desc.clearColor; + CoreUtils.SetRenderTarget(rgContext.cmd, resource.rt, clearFlag, clearColor); } - - LogTextureCreation(resource.rt, resource.desc.clearBuffer || m_RenderGraphDebug.clearRenderTargetsAtCreation); } + + LogTextureCreation(resource.rt, resource.desc.clearBuffer || m_RenderGraphDebug.clearRenderTargetsAtCreation); } } @@ -578,7 +569,7 @@ void CreateTextureForPass(ref TextureResource resource) resource.cachedHash = hashCode; } - void SetGlobalTextures(RenderGraphContext rgContext, List textures, bool bindDummyTexture) + void SetGlobalTextures(RenderGraphContext rgContext, IReadOnlyCollection textures, bool bindDummyTexture) { foreach (var resource in textures) { @@ -595,65 +586,42 @@ void SetGlobalTextures(RenderGraphContext rgContext, List texture } - internal void PreRenderPassSetGlobalTextures(RenderGraphContext rgContext, List textures) + internal void PreRenderPassSetGlobalTextures(RenderGraphContext rgContext, IReadOnlyCollection textures) { SetGlobalTextures(rgContext, textures, false); } - internal void PostRenderPassUnbindGlobalTextures(RenderGraphContext rgContext, List textures) + internal void PostRenderPassUnbindGlobalTextures(RenderGraphContext rgContext, IReadOnlyCollection textures) { SetGlobalTextures(rgContext, textures, true); } - internal void ReleaseTexturesForPass(RenderGraphContext rgContext, int passIndex, List readTextures, List writtenTextures) + internal void ReleaseTexture(RenderGraphContext rgContext, TextureHandle resource) { - foreach (var resource in readTextures) + ref var resourceDesc = ref GetTextureResource(resource); + if (!resourceDesc.imported) { - ref var resourceDesc = ref GetTextureResource(resource); - if (!resourceDesc.imported && resourceDesc.lastReadPassIndex == passIndex) + if (m_RenderGraphDebug.clearRenderTargetsAtRelease) { - if (m_RenderGraphDebug.clearRenderTargetsAtRelease) + using (new ProfilingScope(rgContext.cmd, ProfilingSampler.Get(RenderGraphProfileId.RenderGraphClearDebug))) { - using (new ProfilingScope(rgContext.cmd, ProfilingSampler.Get(RenderGraphProfileId.RenderGraphClearDebug))) - { - var clearFlag = resourceDesc.desc.depthBufferBits != DepthBits.None ? ClearFlag.Depth : ClearFlag.Color; - CoreUtils.SetRenderTarget(rgContext.cmd, GetTexture(resource), clearFlag, Color.magenta); - } + var clearFlag = resourceDesc.desc.depthBufferBits != DepthBits.None ? ClearFlag.Depth : ClearFlag.Color; + CoreUtils.SetRenderTarget(rgContext.cmd, GetTexture(resource), clearFlag, Color.magenta); } - - ReleaseTextureForPass(resource); } - } - // If a resource was created for only a single pass, we don't want users to have to declare explicitly the read operation. - // So to do that, we also update lastReadIndex on resource writes. - // This means that we need to check written resources for destruction too - foreach (var resource in writtenTextures) - { - ref var resourceDesc = ref GetTextureResource(resource); - // <= because a texture that is only declared as written in a single pass (and read implicitly in the same pass) will have the default lastReadPassIndex at -1 - if (!resourceDesc.imported && resourceDesc.lastReadPassIndex <= passIndex) + //// This can happen because we release texture in two passes (see ReleaseTexturesForPass) and texture can be present in both passes + //if (resourceDesc.rt != null) { - ReleaseTextureForPass(resource); + LogTextureRelease(resourceDesc.rt); + ReleaseTextureResource(resourceDesc.cachedHash, resourceDesc.rt); + resourceDesc.cachedHash = -1; + resourceDesc.rt = null; + resourceDesc.wasReleased = true; } } } - void ReleaseTextureForPass(TextureHandle res) - { - ref var resource = ref m_TextureResources[res]; - - // This can happen because we release texture in two passes (see ReleaseTexturesForPass) and texture can be present in both passes - if (resource.rt != null) - { - LogTextureRelease(resource.rt); - ReleaseTextureResource(resource.cachedHash, resource.rt); - resource.cachedHash = -1; - resource.rt = null; - resource.wasReleased = true; - } - } - void ReleaseTextureResource(int hash, RTHandle rt) { if (!m_TexturePool.TryGetValue(hash, out var stack)) @@ -761,12 +729,16 @@ internal void Clear() #if DEVELOPMENT_BUILD || UNITY_EDITOR if (m_AllocatedTextures.Count != 0) { - Debug.LogWarning("RenderGraph: Not all textures were released."); + string logMessage = "RenderGraph: Not all textures were released."; + List<(int, RTHandle)> tempList = new List<(int, RTHandle)>(m_AllocatedTextures); foreach (var value in tempList) { + logMessage = $"{logMessage}\n\t{value.Item2.name}"; ReleaseTextureResource(value.Item1, value.Item2); } + + Debug.LogWarning(logMessage); } #endif } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs index 926a23f2f84..f6d49c4a34e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs @@ -102,8 +102,8 @@ TextureHandle DenoiseAO( RenderGraph renderGraph, passData.parameters = parameters; passData.packedData = builder.ReadTexture(aoPackedData); passData.motionVectors = builder.ReadTexture(motionVectors); - passData.packedDataBlurred = builder.WriteTexture(renderGraph.CreateTexture( - new TextureDesc(Vector2.one * scaleFactor, true, true) { colorFormat = GraphicsFormat.R32_UInt, enableRandomWrite = true, name = "AO Packed blurred data" } )); + passData.packedDataBlurred = builder.CreateTransientTexture( + new TextureDesc(Vector2.one * scaleFactor, true, true) { colorFormat = GraphicsFormat.R32_UInt, enableRandomWrite = true, name = "AO Packed blurred data" } ); passData.currentHistory = builder.ReadTexture(currentHistory); // can also be written on first frame, but since it's an imported resource, it doesn't matter in term of lifetime. passData.outputHistory = builder.WriteTexture(outputHistory); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index 5b55edea50a..692f3918445 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -5,9 +5,9 @@ namespace UnityEngine.Rendering.HighDefinition { partial class PostProcessSystem { - public void Render( RenderGraph renderGraph, - HDCamera hdCamera, - BlueNoise blueNoise, + public void Render( RenderGraph renderGraph, + HDCamera hdCamera, + BlueNoise blueNoise, TextureHandle colorBuffer, TextureHandle afterPostProcessTexture, TextureHandle depthBuffer, diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs index ff8b1099c42..f39a25adcf4 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs @@ -713,8 +713,8 @@ internal void ExecuteCaptureActions(RenderGraph renderGraph, TextureHandle input passData.input = builder.ReadTexture(input); // We need to blit to an intermediate texture because input resolution can be bigger than the camera resolution // Since recorder does not know about this, we need to send a texture of the right size. - passData.tempTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(actualWidth, actualHeight) - { colorFormat = inputDesc.colorFormat, name = "TempCaptureActions" })); + passData.tempTexture = builder.CreateTransientTexture(new TextureDesc(actualWidth, actualHeight) + { colorFormat = inputDesc.colorFormat, name = "TempCaptureActions" }); builder.SetRenderFunc( (ExecuteCaptureActionsPassData data, RenderGraphContext ctx) => diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs index 8eda7f371ca..fe353879da5 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs @@ -137,12 +137,12 @@ static void RenderLightVolumes(RenderGraph renderGraph, in DebugParameters debug using (var builder = renderGraph.AddRenderPass("LightVolumes", out var passData)) { passData.parameters = s_lightVolumes.PrepareLightVolumeParameters(debugParameters.hdCamera, debugParameters.debugDisplaySettings.data.lightingDebugSettings, cullResults); - passData.lightCountBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) - { colorFormat= GraphicsFormat.R32_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeCount" })); - passData.colorAccumulationBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) - { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeColorAccumulation" })); - passData.debugLightVolumesTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) - { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, enableRandomWrite = true, name = "LightVolumeDebugLightVolumesTexture" })); + passData.lightCountBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) + { colorFormat= GraphicsFormat.R32_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeCount" }); + passData.colorAccumulationBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) + { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeColorAccumulation" }); + passData.debugLightVolumesTexture = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) + { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, enableRandomWrite = true, name = "LightVolumeDebugLightVolumesTexture" }); passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.destination = builder.WriteTexture(destination); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs index 9392597b570..1d686ca1ede 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs @@ -235,7 +235,7 @@ LightingOutput RenderDeferredLighting( RenderGraph renderGraph, // TODO RENDERGRAPH: Check how to avoid this kind of pattern. // Unfortunately, the low level needs this texture to always be bound with UAV enabled, so in order to avoid effectively creating the full resolution texture here, // we need to create a small dummy texture. - passData.sssDiffuseLightingBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(1, 1, true, true) { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true } )); + passData.sssDiffuseLightingBuffer = builder.CreateTransientTexture(new TextureDesc(1, 1, true, true) { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true } ); } passData.depthBuffer = builder.ReadTexture(depthStencilBuffer); passData.depthTexture = builder.ReadTexture(depthPyramidTexture); @@ -274,7 +274,7 @@ LightingOutput RenderDeferredLighting( RenderGraph renderGraph, resources.tileListBuffer = context.resources.GetComputeBuffer(data.tileListBuffer); resources.dispatchIndirectBuffer = context.resources.GetComputeBuffer(data.dispatchIndirectBuffer); - // RENDERGRAPH TODO: try to find a better way to bind this. + // TODO RENDERGRAPH: try to find a better way to bind this. // Issue is that some GBuffers have several names (for example normal buffer is both NormalBuffer and GBuffer1) // So it's not possible to use auto binding via dependency to shaderTagID // Should probably get rid of auto binding and go explicit all the way (might need to wait for us to remove non rendergraph code path). @@ -362,8 +362,8 @@ TextureHandle RenderSSR( RenderGraph renderGraph, // In practice, these textures are sparse (mostly black). Therefore, clearing them is fast (due to CMASK), // and much faster than fully overwriting them from within SSR shaders. - passData.hitPointsTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) - { colorFormat = GraphicsFormat.R16G16_UNorm, clearBuffer = true, clearColor = Color.clear, enableRandomWrite = true, name = "SSR_Hit_Point_Texture" })); + passData.hitPointsTexture = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) + { colorFormat = GraphicsFormat.R16G16_UNorm, clearBuffer = true, clearColor = Color.clear, enableRandomWrite = true, name = "SSR_Hit_Point_Texture" }); passData.lightingTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.clear, enableRandomWrite = true, name = "SSR_Lighting_Texture" }, HDShaderIDs._SsrLightingTexture)); //passData.hitPointsTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs index ffb4c42da01..c6bafbc3155 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Prepass.cs @@ -492,7 +492,7 @@ class ResolveStencilPassData public BuildCoarseStencilAndResolveParameters parameters; public TextureHandle inputDepth; public TextureHandle resolvedStencil; - public ComputeBuffer coarseStencilBuffer; + public ComputeBufferHandle coarseStencilBuffer; } void BuildCoarseStencilAndResolveIfNeeded(RenderGraph renderGraph, HDCamera hdCamera, ref PrepassOutput output) @@ -501,8 +501,9 @@ void BuildCoarseStencilAndResolveIfNeeded(RenderGraph renderGraph, HDCamera hdCa { passData.parameters = PrepareBuildCoarseStencilParameters(hdCamera); passData.inputDepth = output.depthBuffer; - passData.coarseStencilBuffer = m_SharedRTManager.GetCoarseStencilBuffer(); - passData.resolvedStencil = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R8G8_UInt, enableRandomWrite = true, name = "StencilBufferResolved" })); + passData.coarseStencilBuffer = builder.WriteComputeBuffer(renderGraph.ImportComputeBuffer(m_SharedRTManager.GetCoarseStencilBuffer())); + if (passData.parameters.resolveIsNecessary) + passData.resolvedStencil = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R8G8_UInt, enableRandomWrite = true, name = "StencilBufferResolved" })); builder.SetRenderFunc( (ResolveStencilPassData data, RenderGraphContext context) => { @@ -510,7 +511,7 @@ void BuildCoarseStencilAndResolveIfNeeded(RenderGraph renderGraph, HDCamera hdCa BuildCoarseStencilAndResolveIfNeeded(data.parameters, res.GetTexture(data.inputDepth), res.GetTexture(data.resolvedStencil), - data.coarseStencilBuffer, + res.GetComputeBuffer(data.coarseStencilBuffer), context.cmd); } ); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs index 1e40fb46dbe..1d15adf2a88 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs @@ -206,14 +206,14 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, hdCamera.ExecuteCaptureActions(m_RenderGraph, colorBuffer); postProcessDest = RenderDebug( m_RenderGraph, - hdCamera, + hdCamera, postProcessDest, - prepassOutput.depthBuffer, - prepassOutput.depthPyramidTexture, - m_DebugFullScreenTexture, - colorPickerTexture, - shadowResult, - cullingResults); + prepassOutput.depthBuffer, + prepassOutput.depthPyramidTexture, + m_DebugFullScreenTexture, + colorPickerTexture, + shadowResult, + cullingResults); BlitFinalCameraTexture(m_RenderGraph, hdCamera, postProcessDest, backBuffer, prepassOutput.resolvedMotionVectorsBuffer, prepassOutput.resolvedNormalBuffer); @@ -470,7 +470,7 @@ void RenderForwardTransparent( RenderGraph renderGraph, // It doesn't really matter what gets bound here since the color mask state set will prevent this from ever being written to. However, we still need to bind something // to avoid warnings about unbound render targets. The following rendertarget could really be anything if renderVelocitiesForTransparent // Create a new target here should reuse existing already released one - mrt1 = renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R8G8B8A8_SRGB, name = "Transparency Velocity Dummy" }); + mrt1 = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R8G8B8A8_SRGB, name = "Transparency Velocity Dummy" }); } passData.renderTargetCount = 2; @@ -778,16 +778,16 @@ void RenderForwardError(RenderGraph renderGraph, class RenderSkyPassData { - public VisualEnvironment visualEnvironment; - public Light sunLight; - public HDCamera hdCamera; + public VisualEnvironment visualEnvironment; + public Light sunLight; + public HDCamera hdCamera; public TextureHandle volumetricLighting; public TextureHandle colorBuffer; public TextureHandle depthStencilBuffer; public TextureHandle intermediateBuffer; - public DebugDisplaySettings debugDisplaySettings; - public SkyManager skyManager; - public int frameCount; + public DebugDisplaySettings debugDisplaySettings; + public SkyManager skyManager; + public int frameCount; } void RenderSky(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer, TextureHandle volumetricLighting, TextureHandle depthStencilBuffer, TextureHandle depthTexture) @@ -805,7 +805,7 @@ void RenderSky(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBu passData.volumetricLighting = builder.ReadTexture(volumetricLighting); passData.colorBuffer = builder.WriteTexture(colorBuffer); passData.depthStencilBuffer = builder.WriteTexture(depthStencilBuffer); - passData.intermediateBuffer = builder.WriteTexture(renderGraph.CreateTexture(colorBuffer)); + passData.intermediateBuffer = builder.CreateTransientTexture(colorBuffer); passData.debugDisplaySettings = m_CurrentDebugDisplaySettings; passData.skyManager = m_SkyManager; passData.frameCount = m_FrameCount; @@ -923,8 +923,8 @@ class RenderDistortionPassData public Vector4 size; } - void RenderDistortion( RenderGraph renderGraph, - HDCamera hdCamera, + void RenderDistortion( RenderGraph renderGraph, + HDCamera hdCamera, TextureHandle colorBuffer, TextureHandle depthStencilBuffer, TextureHandle colorPyramidBuffer, diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs index 1830c6829c9..1204288ec02 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs @@ -53,9 +53,9 @@ void RenderSubsurfaceScattering(RenderGraph renderGraph, HDCamera hdCamera, Text passData.sssBuffer = builder.ReadTexture(lightingBuffers.sssBuffer); if (passData.parameters.needTemporaryBuffer) { - passData.cameraFilteringBuffer = builder.WriteTexture(renderGraph.CreateTexture( + passData.cameraFilteringBuffer = builder.CreateTransientTexture( new TextureDesc(Vector2.one, true, true) - { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true, clearBuffer = true, clearColor = Color.clear, name = "SSSCameraFiltering" })); + { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true, clearBuffer = true, clearColor = Color.clear, name = "SSSCameraFiltering" }); } builder.SetRenderFunc( diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 452a0be7cd6..52d515eaf78 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -1190,8 +1190,10 @@ void CopyDepthBufferIfNeeded(HDCamera hdCamera, CommandBuffer cmd) struct BuildCoarseStencilAndResolveParameters { - public HDCamera hdCamera; - public ComputeShader resolveStencilCS; + public HDCamera hdCamera; + public ComputeShader resolveStencilCS; + public int resolveKernel; + public bool resolveIsNecessary; } BuildCoarseStencilAndResolveParameters PrepareBuildCoarseStencilParameters(HDCamera hdCamera) @@ -1199,6 +1201,19 @@ BuildCoarseStencilAndResolveParameters PrepareBuildCoarseStencilParameters(HDCam var parameters = new BuildCoarseStencilAndResolveParameters(); parameters.hdCamera = hdCamera; parameters.resolveStencilCS = defaultResources.shaders.resolveStencilCS; + + bool MSAAEnabled = hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA); + + // The following features require a copy of the stencil, if none are active, no need to do the resolve. + bool resolveIsNecessary = GetFeatureVariantsEnabled(hdCamera.frameSettings); + resolveIsNecessary = resolveIsNecessary || hdCamera.IsSSREnabled() + || hdCamera.IsTransparentSSREnabled(); + // We need the resolve only with msaa + parameters.resolveIsNecessary = resolveIsNecessary && MSAAEnabled; + + int kernel = SampleCountToPassIndex(MSAAEnabled ? hdCamera.msaaSamples : MSAASamples.None); + parameters.resolveKernel = parameters.resolveIsNecessary ? kernel + 3 : kernel; // We have a different variant if we need to resolve to non-MSAA stencil + return parameters; } @@ -1216,31 +1231,18 @@ static void BuildCoarseStencilAndResolveIfNeeded(BuildCoarseStencilAndResolvePar { using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.CoarseStencilGeneration))) { - var hdCamera = parameters.hdCamera; - bool MSAAEnabled = hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA); - - // The following features require a copy of the stencil, if none are active, no need to do the resolve. - bool resolveIsNecessary = GetFeatureVariantsEnabled(hdCamera.frameSettings); - resolveIsNecessary = resolveIsNecessary || hdCamera.IsSSREnabled() - || hdCamera.IsTransparentSSREnabled(); - - // We need the resolve only with msaa - resolveIsNecessary = resolveIsNecessary && MSAAEnabled; - ComputeShader cs = parameters.resolveStencilCS; - int kernel = SampleCountToPassIndex(MSAAEnabled ? hdCamera.msaaSamples : MSAASamples.None); - kernel = resolveIsNecessary ? kernel + 3 : kernel; // We have a different variant if we need to resolve to non-MSAA stencil - cmd.SetComputeBufferParam(cs, kernel, HDShaderIDs._CoarseStencilBuffer, coarseStencilBuffer); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._StencilTexture, depthStencilBuffer, 0, RenderTextureSubElement.Stencil); + cmd.SetComputeBufferParam(cs, parameters.resolveKernel, HDShaderIDs._CoarseStencilBuffer, coarseStencilBuffer); + cmd.SetComputeTextureParam(cs, parameters.resolveKernel, HDShaderIDs._StencilTexture, depthStencilBuffer, 0, RenderTextureSubElement.Stencil); - if (resolveIsNecessary) + if (parameters.resolveIsNecessary) { - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputStencilBuffer, resolvedStencilBuffer); + cmd.SetComputeTextureParam(cs, parameters.resolveKernel, HDShaderIDs._OutputStencilBuffer, resolvedStencilBuffer); } - int coarseStencilWidth = HDUtils.DivRoundUp(hdCamera.actualWidth, 8); - int coarseStencilHeight = HDUtils.DivRoundUp(hdCamera.actualHeight, 8); - cmd.DispatchCompute(cs, kernel, coarseStencilWidth, coarseStencilHeight, hdCamera.viewCount); + int coarseStencilWidth = HDUtils.DivRoundUp(parameters.hdCamera.actualWidth, 8); + int coarseStencilHeight = HDUtils.DivRoundUp(parameters.hdCamera.actualHeight, 8); + cmd.DispatchCompute(cs, parameters.resolveKernel, coarseStencilWidth, coarseStencilHeight, parameters.hdCamera.viewCount); } } From 1898564244f0c51535dbf2828fffc39edbd08ffe Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Thu, 7 May 2020 09:47:14 +0200 Subject: [PATCH 10/19] Implementation of async resource synchronization. --- .../Runtime/RenderGraph/RenderGraph.cs | 119 ++++++++++++++++-- .../RenderGraphResourceRegistry.cs | 2 +- .../PostProcessing/PostProcessSystem.cs | 30 ++--- .../HDRenderPipeline.RenderGraph.cs | 12 +- 4 files changed, 131 insertions(+), 32 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 772fe1ceefe..fd200a0d4fa 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -121,6 +121,9 @@ internal struct PassExecutionInfo public int refCount; public bool pruned; public bool hasSideEffect; + public int syncWithPassIndex; + public bool needGraphicsFence; + public GraphicsFence fence; public void Reset() { @@ -135,6 +138,8 @@ public void Reset() refCount = 0; pruned = false; hasSideEffect = false; + syncWithPassIndex = -1; + needGraphicsFence = false; } } @@ -154,7 +159,7 @@ public void Reset() #region Public Interface - // TODO: Currently only needed by SSAO to sample correctly depth texture mips. Need to figure out a way to hide this behind a proper formalization. + // TODO RENDERGRAPH: Currently only needed by SSAO to sample correctly depth texture mips. Need to figure out a way to hide this behind a proper formalization. /// /// Gets the RTHandleProperties structure associated with the Render Graph's RTHandle System. /// @@ -390,11 +395,55 @@ void PruneUnusedPasses() LogPrunedPasses(); } - void UpdateResourceAllocation() + int GetLatestProducerIndex(in ResourceUsageInfo info) { + return info.producers.Count == 0 ? -1 : info.producers[info.producers.Count - 1]; + } + + void UpdateResourceSynchronization(ref int lastGraphicsPipeSync, ref int lastComputePipeSync, int currentPassIndex, in ResourceUsageInfo resource) + { + int lastProducer = GetLatestProducerIndex(resource); + if (lastProducer != -1) + { + RenderGraphPass currentPass = m_RenderPasses[currentPassIndex]; + PassExecutionInfo currentPassInfo = m_PassExecutionInfo[currentPassIndex]; + + RenderGraphPass producerPass = m_RenderPasses[lastProducer]; + //If the passes are on different pipes, we need synchronization. + if (producerPass.enableAsyncCompute != currentPass.enableAsyncCompute) + { + // Pass is on compute pipe, need sync with graphics pipe. + if (currentPass.enableAsyncCompute) + { + if (lastProducer > lastGraphicsPipeSync) + { + currentPassInfo.syncWithPassIndex = lastProducer; + lastGraphicsPipeSync = lastProducer; + m_PassExecutionInfo[lastProducer].needGraphicsFence = true; + } + } + else + { + if (lastProducer > lastComputePipeSync) + { + currentPassInfo.syncWithPassIndex = lastProducer; + lastComputePipeSync = lastProducer; + m_PassExecutionInfo[lastProducer].needGraphicsFence = true; + } + } + } + } + } + + void UpdateResourceAllocationAndSynchronization() + { + int lastGraphicsPipeSync = -1; + int lastComputePipeSync = -1; + // First go through all passes. // - Update the last pass read index for each resource. // - Add texture to creation list for passes that first write to a texture. + // - Update synchronization points for all resources between compute and graphics pipes. for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) { ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; @@ -408,6 +457,7 @@ void UpdateResourceAllocation() { ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; info.lastReadPassIndex = Math.Max(info.lastReadPassIndex, passIndex); + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, info); } foreach (TextureHandle texture in pass.textureWriteList) @@ -419,6 +469,16 @@ void UpdateResourceAllocation() passInfo.textureCreateList.Add(texture); } passInfo.refCount++; + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, info); + } + + foreach (ComputeBufferHandle texture in pass.bufferReadList) + { + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, m_BufferUsageInfo[texture]); + } + foreach (ComputeBufferHandle texture in pass.bufferWriteList) + { + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, m_BufferUsageInfo[texture]); } // Add transient resources that are only used during this pass. @@ -456,7 +516,7 @@ void CompileRenderGraph() InitializeCompilationData(); CountReferences(); PruneUnusedPasses(); - UpdateResourceAllocation(); + UpdateResourceAllocationAndSynchronization(); LogRendererListsCreation(); } @@ -484,12 +544,12 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd using (new ProfilingScope(cmd, pass.customSampler)) { - LogRenderPassBegin(pass); + LogRenderPassBegin(passIndex); using (new RenderGraphLogIndent(m_Logger)) { PreRenderPassExecute(passIndex, rgContext); pass.Execute(rgContext); - PostRenderPassExecute(passIndex, rgContext); + PostRenderPassExecute(cmd, passIndex, rgContext); } } } @@ -610,22 +670,54 @@ void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) void PreRenderPassExecute(int passIndex, RenderGraphContext rgContext) { // TODO RENDERGRAPH merge clear and setup here if possible + RenderGraphPass pass = m_RenderPasses[passIndex]; PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; foreach (var texture in passInfo.textureCreateList) m_Resources.CreateAndClearTexture(rgContext, texture); PreRenderPassSetRenderTargets(passIndex, rgContext); - m_Resources.PreRenderPassSetGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); + m_Resources.PreRenderPassSetGlobalTextures(rgContext, pass.textureReadList); + + // TODO RENDERGRAPH: See if we can keep the same command buffer between passes on the same pipe (and if that's useful at all) + if (pass.enableAsyncCompute) + { + // Flush first the current command buffer on the render context. + rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd); + rgContext.cmd.Clear(); + + CommandBuffer asyncCmd = CommandBufferPool.Get(pass.name); + asyncCmd.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute); + rgContext.cmd = asyncCmd; + } + + // Synchronize with graphics or compute pipe if needed. + if (passInfo.syncWithPassIndex != -1) + { + rgContext.cmd.WaitOnAsyncGraphicsFence(m_PassExecutionInfo[passInfo.syncWithPassIndex].fence); + } } - void PostRenderPassExecute(int passIndex, RenderGraphContext rgContext) + void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, RenderGraphContext rgContext) { + RenderGraphPass pass = m_RenderPasses[passIndex]; + ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; + + if (passInfo.needGraphicsFence) + passInfo.fence = rgContext.cmd.CreateAsyncGraphicsFence(); + + if (pass.enableAsyncCompute) + { + // The command buffer has been filled. We can kick the async task. + rgContext.renderContext.ExecuteCommandBufferAsync(rgContext.cmd, ComputeQueueType.Background); + CommandBufferPool.Release(rgContext.cmd); + rgContext.cmd = mainCmd; // Restore the main command buffer. + } + if (m_DebugParameters.unbindGlobalTextures) m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); m_RenderGraphPool.ReleaseAllTempAlloc(); - PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; foreach (var texture in passInfo.textureReleaseList) m_Resources.ReleaseTexture(rgContext, texture); @@ -654,11 +746,20 @@ void LogRendererListsCreation() } } - void LogRenderPassBegin(in RenderGraphPass pass) + void LogRenderPassBegin(int passIndex) { if (m_DebugParameters.logFrameInformation) { + RenderGraphPass pass = m_RenderPasses[passIndex]; + PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; + m_Logger.LogLine("Executing pass \"{0}\" (index: {1})", pass.name, pass.index); + using (new RenderGraphLogIndent(m_Logger)) + { + m_Logger.LogLine("Queue: {0}", pass.enableAsyncCompute ? "Compute" : "Graphics"); + if (passInfo.syncWithPassIndex != -1) + m_Logger.LogLine("Synchronize with pass index: {0}", passInfo.syncWithPassIndex); + } } } diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs index 0126d0dc40f..34b4eab81c8 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs @@ -531,7 +531,7 @@ void CreateTextureForPass(ref TextureResource resource) int hashCode = desc.GetHashCode(); if(resource.rt != null) - throw new InvalidOperationException(string.Format("Trying to create an already created texture ({0}). Texture was probably declared for writing more than once.", resource.desc.name)); + throw new InvalidOperationException(string.Format("Trying to create an already created texture ({0}). Texture was probably declared for writing more than once in the same pass.", resource.desc.name)); resource.rt = null; if (!TryGetRenderTarget(hashCode, out resource.rt)) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index af115aa692b..28f6fe70713 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -188,6 +188,15 @@ public PostProcessSystem(HDRenderPipelineAsset hdAsset, RenderPipelineResources m_KeepAlpha = hdAsset.currentPlatformRenderPipelineSettings.supportsAlpha; } + // Setup a default exposure textures and clear it to neutral values so that the exposure + // multiplier is 1 and thus has no effect + // Beware that 0 in EV100 maps to a multiplier of 0.833 so the EV100 value in this + // neutral exposure texture isn't 0 + m_EmptyExposureTexture = RTHandles.Alloc(1, 1, colorFormat: k_ExposureFormat, + enableRandomWrite: true, name: "Empty EV100 Exposure"); + + FillEmptyExposureTexture(); + // Call after initializing m_LutSize and m_KeepAlpha as it's needed for render target allocation. InitializeNonRenderGraphResources(hdAsset); } @@ -196,6 +205,9 @@ public void Cleanup() { CleanupNonRenderGraphResources(); + RTHandles.Release(m_EmptyExposureTexture); + m_EmptyExposureTexture = null; + CoreUtils.Destroy(m_ExposureCurveTexture); CoreUtils.Destroy(m_InternalSpectralLut); CoreUtils.Destroy(m_FinalPassMaterial); @@ -247,16 +259,6 @@ public void InitializeNonRenderGraphResources(HDRenderPipelineAsset hdAsset) enableRandomWrite: true ); - // Setup a default exposure textures and clear it to neutral values so that the exposure - // multiplier is 1 and thus has no effect - // Beware that 0 in EV100 maps to a multiplier of 0.833 so the EV100 value in this - // neutral exposure texture isn't 0 - m_EmptyExposureTexture = RTHandles.Alloc(1, 1, colorFormat: k_ExposureFormat, - enableRandomWrite: true, name: "Empty EV100 Exposure" - ); - - FillEmptyExposureTexture(); - // Misc targets m_TempTexture1024 = RTHandles.Alloc( 1024, 1024, colorFormat: GraphicsFormat.R16G16_SFloat, @@ -283,13 +285,11 @@ public void CleanupNonRenderGraphResources() m_Pool.Cleanup(); - RTHandles.Release(m_EmptyExposureTexture); RTHandles.Release(m_TempTexture1024); RTHandles.Release(m_TempTexture32); RTHandles.Release(m_AlphaTexture); RTHandles.Release(m_InternalLogLut); - m_EmptyExposureTexture = null; m_TempTexture1024 = null; m_TempTexture32 = null; m_AlphaTexture = null; @@ -301,12 +301,12 @@ public void CleanupNonRenderGraphResources() // This is not the case when these textures are used exclusively with Compute Shaders. So to make sure they work in this case, we recreate them here. void CheckRenderTexturesValidity() { - if (!m_NonRenderGraphResourcesAvailable) - return; - if (!m_EmptyExposureTexture.rt.IsCreated()) FillEmptyExposureTexture(); + if (!m_NonRenderGraphResourcesAvailable) + return; + HDUtils.CheckRTCreated(m_InternalLogLut.rt); HDUtils.CheckRTCreated(m_TempTexture1024.rt); HDUtils.CheckRTCreated(m_TempTexture32.rt); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs index 1d15adf2a88..7f980c8105f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs @@ -454,10 +454,12 @@ void RenderForwardTransparent( RenderGraph renderGraph, bool renderMotionVecForTransparent = NeedMotionVectorForTransparent(hdCamera.frameSettings); - TextureHandle mrt1; + passData.renderTargetCount = 2; + passData.renderTarget[0] = builder.WriteTexture(colorBuffer); + if (renderMotionVecForTransparent) { - mrt1 = motionVectorBuffer; + passData.renderTarget[1] = builder.WriteTexture(motionVectorBuffer); // TODO RENDERGRAPH // WORKAROUND VELOCITY-MSAA // This is a workaround for velocity with MSAA. Currently motion vector resolve is not implemented with MSAA @@ -470,13 +472,9 @@ void RenderForwardTransparent( RenderGraph renderGraph, // It doesn't really matter what gets bound here since the color mask state set will prevent this from ever being written to. However, we still need to bind something // to avoid warnings about unbound render targets. The following rendertarget could really be anything if renderVelocitiesForTransparent // Create a new target here should reuse existing already released one - mrt1 = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R8G8B8A8_SRGB, name = "Transparency Velocity Dummy" }); + passData.renderTarget[1] = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R8G8B8A8_SRGB, name = "Transparency Velocity Dummy" }); } - passData.renderTargetCount = 2; - passData.renderTarget[0] = builder.WriteTexture(colorBuffer); - passData.renderTarget[1] = builder.WriteTexture(mrt1); - if (colorPyramid != null && hdCamera.frameSettings.IsEnabled(FrameSettingsField.Refraction) && !preRefractionPass) { builder.ReadTexture(colorPyramid.Value); From ac2166ac03ee271d13651201737f1e96a0ca9a48 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Thu, 7 May 2020 15:33:16 +0200 Subject: [PATCH 11/19] Fixed synchronization (only partial fix) --- .../Runtime/RenderGraph/RenderGraph.cs | 41 +++++++++++++------ .../Runtime/RenderGraph/RenderGraphPass.cs | 3 +- .../AmbientOcclusion.RenderGraph.cs | 2 +- .../ScreenSpaceLighting/AmbientOcclusion.cs | 4 +- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index fd200a0d4fa..918052628ad 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -395,18 +395,29 @@ void PruneUnusedPasses() LogPrunedPasses(); } - int GetLatestProducerIndex(in ResourceUsageInfo info) + int GetLatestProducerIndex(int passIndex, in ResourceUsageInfo info) { - return info.producers.Count == 0 ? -1 : info.producers[info.producers.Count - 1]; + // We want to know the highest pass index below the current pass that writes to the resource. + int result = -1; + foreach(var producer in info.producers) + { + // producers are by construction in increasing order. + if (producer < passIndex) + result = producer; + else + return result; + } + + return result; } void UpdateResourceSynchronization(ref int lastGraphicsPipeSync, ref int lastComputePipeSync, int currentPassIndex, in ResourceUsageInfo resource) { - int lastProducer = GetLatestProducerIndex(resource); + int lastProducer = GetLatestProducerIndex(currentPassIndex, resource); if (lastProducer != -1) { RenderGraphPass currentPass = m_RenderPasses[currentPassIndex]; - PassExecutionInfo currentPassInfo = m_PassExecutionInfo[currentPassIndex]; + ref PassExecutionInfo currentPassInfo = ref m_PassExecutionInfo[currentPassIndex]; RenderGraphPass producerPass = m_RenderPasses[lastProducer]; //If the passes are on different pipes, we need synchronization. @@ -542,14 +553,16 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", pass.name)); } + bool previousPassIsAsync = false; + using (new ProfilingScope(cmd, pass.customSampler)) { LogRenderPassBegin(passIndex); using (new RenderGraphLogIndent(m_Logger)) { - PreRenderPassExecute(passIndex, rgContext); + previousPassIsAsync = PreRenderPassExecute(passIndex, previousPassIsAsync, ref rgContext); pass.Execute(rgContext); - PostRenderPassExecute(cmd, passIndex, rgContext); + PostRenderPassExecute(cmd, passIndex, ref rgContext); } } } @@ -667,7 +680,7 @@ void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) } } - void PreRenderPassExecute(int passIndex, RenderGraphContext rgContext) + bool PreRenderPassExecute(int passIndex, bool previousPassIsAsync, ref RenderGraphContext rgContext) { // TODO RENDERGRAPH merge clear and setup here if possible RenderGraphPass pass = m_RenderPasses[passIndex]; @@ -678,12 +691,14 @@ void PreRenderPassExecute(int passIndex, RenderGraphContext rgContext) PreRenderPassSetRenderTargets(passIndex, rgContext); m_Resources.PreRenderPassSetGlobalTextures(rgContext, pass.textureReadList); - // TODO RENDERGRAPH: See if we can keep the same command buffer between passes on the same pipe (and if that's useful at all) if (pass.enableAsyncCompute) { - // Flush first the current command buffer on the render context. - rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd); - rgContext.cmd.Clear(); + if (!previousPassIsAsync) + { + // Flush first the current command buffer on the render context. + rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd); + rgContext.cmd.Clear(); + } CommandBuffer asyncCmd = CommandBufferPool.Get(pass.name); asyncCmd.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute); @@ -695,9 +710,11 @@ void PreRenderPassExecute(int passIndex, RenderGraphContext rgContext) { rgContext.cmd.WaitOnAsyncGraphicsFence(m_PassExecutionInfo[passInfo.syncWithPassIndex].fence); } + + return pass.enableAsyncCompute; } - void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, RenderGraphContext rgContext) + void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraphContext rgContext) { RenderGraphPass pass = m_RenderPasses[passIndex]; ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs index 65ba5ade4bd..d3a39ac4840 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs @@ -5,7 +5,7 @@ namespace UnityEngine.Experimental.Rendering.RenderGraphModule { - [DebuggerDisplay("RenderPass ({name})")] + [DebuggerDisplay("RenderPass: {name} ({index})")] abstract class RenderGraphPass { public RenderFunc GetExecuteDelegate() @@ -117,6 +117,7 @@ public void SetDepthBuffer(TextureHandle resource, DepthAccess flags) } } + [DebuggerDisplay("RenderPass: {name} ({index})")] internal sealed class RenderGraphPass : RenderGraphPass where PassData : class, new() { diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs index f6d49c4a34e..49bd699a153 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.RenderGraph.cs @@ -30,7 +30,7 @@ public TextureHandle Render(RenderGraph renderGraph, HDCamera hdCamera, TextureH historyRT.referenceSize.y * historyRT.scaleFactor.y); var rtScaleForHistory = hdCamera.historyRTHandleProperties.rtHandleScale; - var aoParameters = PrepareRenderAOParameters(hdCamera, renderGraph.rtHandleProperties, historySize * rtScaleForHistory, frameCount); + var aoParameters = PrepareRenderAOParameters(hdCamera, historySize * rtScaleForHistory, frameCount); var packedData = RenderAO(renderGraph, aoParameters, depthPyramid); result = DenoiseAO(renderGraph, aoParameters, motionVectors, packedData, currentHistory, outputHistory); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs index 40bf78c2e80..0e29080566b 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs @@ -300,7 +300,7 @@ struct RenderAOParameters public ShaderVariablesAmbientOcclusion cb; } - RenderAOParameters PrepareRenderAOParameters(HDCamera camera, RTHandleProperties rtHandleProperties, Vector2 historySize, int frameCount) + RenderAOParameters PrepareRenderAOParameters(HDCamera camera, Vector2 historySize, int frameCount) { var parameters = new RenderAOParameters(); @@ -567,7 +567,7 @@ internal void Dispatch(CommandBuffer cmd, HDCamera camera, int frameCount) currentHistory.referenceSize.y * currentHistory.scaleFactor.y); var rtScaleForHistory = camera.historyRTHandleProperties.rtHandleScale; - var aoParameters = PrepareRenderAOParameters(camera, RTHandles.rtHandleProperties, historySize * rtScaleForHistory, frameCount); + var aoParameters = PrepareRenderAOParameters(camera, historySize * rtScaleForHistory, frameCount); using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.HorizonSSAO))) { RenderAO(aoParameters, m_PackedDataTex, m_Resources, cmd); From d62e8a7a0c1b6e3f2b2a049dc2a0ba9fb669067e Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Thu, 7 May 2020 17:59:58 +0200 Subject: [PATCH 12/19] Added default profiling sampler for render graph passes not providing one. --- .../Runtime/RenderGraph/RenderGraph.cs | 175 ++++++++++-------- 1 file changed, 94 insertions(+), 81 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 918052628ad..a4b25408c1b 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -143,19 +143,20 @@ public void Reset() } } - RenderGraphResourceRegistry m_Resources; - RenderGraphObjectPool m_RenderGraphPool = new RenderGraphObjectPool(); - List m_RenderPasses = new List(); - List m_RendererLists = new List(); - RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams(); - RenderGraphLogger m_Logger = new RenderGraphLogger(); - RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources(); + RenderGraphResourceRegistry m_Resources; + RenderGraphObjectPool m_RenderGraphPool = new RenderGraphObjectPool(); + List m_RenderPasses = new List(); + List m_RendererLists = new List(); + RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams(); + RenderGraphLogger m_Logger = new RenderGraphLogger(); + RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources(); + Dictionary m_DefaultProfilingSamplers = new Dictionary(); // Compiled Render Graph info. - DynamicArray m_TextureUsageInfo = new DynamicArray(); - DynamicArray m_BufferUsageInfo = new DynamicArray(); - DynamicArray m_PassExecutionInfo = new DynamicArray(); - Stack m_PruningStack = new Stack(); + DynamicArray m_TextureUsageInfo = new DynamicArray(); + DynamicArray m_BufferUsageInfo = new DynamicArray(); + DynamicArray m_PassExecutionInfo = new DynamicArray(); + Stack m_PruningStack = new Stack(); #region Public Interface @@ -298,7 +299,7 @@ public ComputeBufferHandle ImportComputeBuffer(ComputeBuffer computeBuffer) public RenderGraphBuilder AddRenderPass(string passName, out PassData passData, ProfilingSampler sampler = null) where PassData : class, new() { var renderPass = m_RenderGraphPool.Get>(); - renderPass.Initialize(m_RenderPasses.Count, m_RenderGraphPool.Get(), passName, sampler); + renderPass.Initialize(m_RenderPasses.Count, m_RenderGraphPool.Get(), passName, sampler != null ? sampler : GetDefaultProfilingSampler(passName)); passData = renderPass.data; @@ -307,6 +308,74 @@ public ComputeBufferHandle ImportComputeBuffer(ComputeBuffer computeBuffer) return new RenderGraphBuilder(renderPass, m_Resources); } + /// + /// Execute the Render Graph in its current state. + /// + /// ScriptableRenderContext used to execute Scriptable Render Pipeline. + /// Command Buffer used for Render Passes rendering. + /// Render Graph execution parameters. + public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in RenderGraphExecuteParams parameters) + { + try + { + m_Logger.Initialize(); + + // Update RTHandleSystem with size for this rendering pass. + m_Resources.SetRTHandleReferenceSize(parameters.renderingWidth, parameters.renderingHeight, parameters.msaaSamples); + + LogFrameInformation(parameters.renderingWidth, parameters.renderingHeight); + + CompileRenderGraph(); + ExecuteRenderGraph(renderContext, cmd); + } + catch (Exception e) + { + Debug.LogError("Render Graph Execution error"); + Debug.LogException(e); + } + finally + { + ClearCompiledGraph(); + + if (m_DebugParameters.logFrameInformation || m_DebugParameters.logResources) + Debug.Log(m_Logger.GetLog()); + + m_DebugParameters.logFrameInformation = false; + m_DebugParameters.logResources = false; + } + } + #endregion + + #region Internal Interface + private RenderGraph() + { + + } + + void ClearCompiledGraph() + { + ClearRenderPasses(); + m_Resources.Clear(); + m_DefaultResources.Clear(); + m_RendererLists.Clear(); + m_BufferUsageInfo.Clear(); + m_TextureUsageInfo.Clear(); + m_PassExecutionInfo.Clear(); + } + + void InitializeCompilationData() + { + m_BufferUsageInfo.Resize(m_Resources.GetComputeBufferResourceCount()); + for (int i = 0; i < m_BufferUsageInfo.size; ++i) + m_BufferUsageInfo[i].Reset(); + m_TextureUsageInfo.Resize(m_Resources.GetTextureResourceCount()); + for (int i = 0; i < m_TextureUsageInfo.size; ++i) + m_TextureUsageInfo[i].Reset(); + m_PassExecutionInfo.Resize(m_RenderPasses.Count); + for (int i = 0; i < m_PassExecutionInfo.size; ++i) + m_PassExecutionInfo[i].Reset(); + } + void CountReferences() { for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) @@ -399,7 +468,7 @@ int GetLatestProducerIndex(int passIndex, in ResourceUsageInfo info) { // We want to know the highest pass index below the current pass that writes to the resource. int result = -1; - foreach(var producer in info.producers) + foreach (var producer in info.producers) { // producers are by construction in increasing order. if (producer < passIndex) @@ -568,74 +637,6 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd } } - /// - /// Execute the Render Graph in its current state. - /// - /// ScriptableRenderContext used to execute Scriptable Render Pipeline. - /// Command Buffer used for Render Passes rendering. - /// Render Graph execution parameters. - public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, in RenderGraphExecuteParams parameters) - { - try - { - m_Logger.Initialize(); - - // Update RTHandleSystem with size for this rendering pass. - m_Resources.SetRTHandleReferenceSize(parameters.renderingWidth, parameters.renderingHeight, parameters.msaaSamples); - - LogFrameInformation(parameters.renderingWidth, parameters.renderingHeight); - - CompileRenderGraph(); - ExecuteRenderGraph(renderContext, cmd); - } - catch (Exception e) - { - Debug.LogError("Render Graph Execution error"); - Debug.LogException(e); - } - finally - { - ClearCompiledGraph(); - - if (m_DebugParameters.logFrameInformation || m_DebugParameters.logResources) - Debug.Log(m_Logger.GetLog()); - - m_DebugParameters.logFrameInformation = false; - m_DebugParameters.logResources = false; - } - } - #endregion - - #region Internal Interface - private RenderGraph() - { - - } - - void ClearCompiledGraph() - { - ClearRenderPasses(); - m_Resources.Clear(); - m_DefaultResources.Clear(); - m_RendererLists.Clear(); - m_BufferUsageInfo.Clear(); - m_TextureUsageInfo.Clear(); - m_PassExecutionInfo.Clear(); - } - - void InitializeCompilationData() - { - m_BufferUsageInfo.Resize(m_Resources.GetComputeBufferResourceCount()); - for (int i = 0; i < m_BufferUsageInfo.size; ++i) - m_BufferUsageInfo[i].Reset(); - m_TextureUsageInfo.Resize(m_Resources.GetTextureResourceCount()); - for (int i = 0; i < m_TextureUsageInfo.size; ++i) - m_TextureUsageInfo[i].Reset(); - m_PassExecutionInfo.Resize(m_RenderPasses.Count); - for (int i = 0; i < m_PassExecutionInfo.size; ++i) - m_PassExecutionInfo[i].Reset(); - } - void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) { var pass = m_RenderPasses[passIndex]; @@ -799,6 +800,18 @@ void LogPrunedPasses() } } + ProfilingSampler GetDefaultProfilingSampler(string name) + { + int hash = name.GetHashCode(); + if (!m_DefaultProfilingSamplers.TryGetValue(hash, out var sampler)) + { + sampler = new ProfilingSampler(name); + m_DefaultProfilingSamplers.Add(hash, sampler); + } + + return sampler; + } + #endregion } } From 9d7c910ff43544c88f25a5ababb7720c0da5d23b Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Tue, 12 May 2020 10:06:38 +0200 Subject: [PATCH 13/19] Async WIP --- .../Runtime/Debugging/ProfilingScope.cs | 80 ++++++++++--------- .../Runtime/RenderGraph/RenderGraph.cs | 54 ++++++++----- .../Runtime/RenderGraph/RenderGraphPass.cs | 4 +- .../RenderPipeline/Settings/FrameSettings.cs | 4 +- 4 files changed, 79 insertions(+), 63 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Debugging/ProfilingScope.cs b/com.unity.render-pipelines.core/Runtime/Debugging/ProfilingScope.cs index e0e17821416..1a7176e509e 100644 --- a/com.unity.render-pipelines.core/Runtime/Debugging/ProfilingScope.cs +++ b/com.unity.render-pipelines.core/Runtime/Debugging/ProfilingScope.cs @@ -98,6 +98,42 @@ public ProfilingSampler(string name) #endif } + /// + /// Begin the profiling block. + /// + /// Command buffer used by the profiling block. + public void Begin(CommandBuffer cmd) + { + if (cmd != null) +#if UNITY_USE_RECORDER + if (sampler != null) + cmd.BeginSample(sampler); + else + cmd.BeginSample(name); +#else + cmd.BeginSample(name); +#endif + inlineSampler?.Begin(); + } + + /// + /// End the profiling block. + /// + /// Command buffer used by the profiling block. + public void End(CommandBuffer cmd) + { + if (cmd != null) +#if UNITY_USE_RECORDER + if (sampler != null) + cmd.EndSample(sampler); + else + cmd.EndSample(name); +#else + m_Cmd.EndSample(name); +#endif + inlineSampler?.End(); + } + internal bool IsValid() { return (sampler != null && inlineSampler != null); } internal CustomSampler sampler { get; private set; } @@ -187,11 +223,9 @@ public bool enableRecording /// public struct ProfilingScope : IDisposable { - string m_Name; - CommandBuffer m_Cmd; - bool m_Disposed; - CustomSampler m_Sampler; - CustomSampler m_InlineSampler; + CommandBuffer m_Cmd; + bool m_Disposed; + ProfilingSampler m_Sampler; /// /// Profiling Scope constructor @@ -202,29 +236,8 @@ public ProfilingScope(CommandBuffer cmd, ProfilingSampler sampler) { m_Cmd = cmd; m_Disposed = false; - if (sampler != null) - { - m_Name = sampler.name; // Don't use CustomSampler.name because it causes garbage - m_Sampler = sampler.sampler; - m_InlineSampler = sampler.inlineSampler; - } - else - { - m_Name = "NullProfilingSampler"; // Don't use CustomSampler.name because it causes garbage - m_Sampler = null; - m_InlineSampler = null; - } - - if (cmd != null) -#if UNITY_USE_RECORDER - if (m_Sampler != null) - cmd.BeginSample(m_Sampler); - else - cmd.BeginSample(m_Name); -#else - cmd.BeginSample(m_Name); -#endif - m_InlineSampler?.Begin(); + m_Sampler = sampler; + m_Sampler?.Begin(m_Cmd); } /// @@ -246,16 +259,7 @@ void Dispose(bool disposing) // this but will generate garbage on every frame (and this struct is used quite a lot). if (disposing) { - if (m_Cmd != null) -#if UNITY_USE_RECORDER - if (m_Sampler != null) - m_Cmd.EndSample(m_Sampler); - else - m_Cmd.EndSample(m_Name); -#else - m_Cmd.EndSample(m_Name); -#endif - m_InlineSampler?.End(); + m_Sampler?.End(m_Cmd); } m_Disposed = true; diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index a4b25408c1b..21a0f367c1e 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -622,17 +622,12 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", pass.name)); } - bool previousPassIsAsync = false; - - using (new ProfilingScope(cmd, pass.customSampler)) + LogRenderPassBegin(passIndex); + using (new RenderGraphLogIndent(m_Logger)) { - LogRenderPassBegin(passIndex); - using (new RenderGraphLogIndent(m_Logger)) - { - previousPassIsAsync = PreRenderPassExecute(passIndex, previousPassIsAsync, ref rgContext); - pass.Execute(rgContext); - PostRenderPassExecute(cmd, passIndex, ref rgContext); - } + PreRenderPassExecute(passIndex, ref rgContext); + pass.Execute(rgContext); + PostRenderPassExecute(cmd, passIndex, ref rgContext); } } } @@ -681,26 +676,43 @@ void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) } } - bool PreRenderPassExecute(int passIndex, bool previousPassIsAsync, ref RenderGraphContext rgContext) + void PushKickAsyncJobMarker(in RenderGraphContext rgContext, RenderGraphPass pass) + { + //var sampler = GetDefaultProfilingSampler($"Kick Async Job: {pass.name}"); + //sampler.Begin(rgContext.cmd); + //sampler.End(rgContext.cmd); + var name = $"Kick Async Job: {pass.name}"; + rgContext.cmd.BeginSample(name); + rgContext.cmd.EndSample(name); + } + + void PreRenderPassExecute(int passIndex, ref RenderGraphContext rgContext) { // TODO RENDERGRAPH merge clear and setup here if possible RenderGraphPass pass = m_RenderPasses[passIndex]; PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; + + // TODO RENDERGRAPH remove this when we do away with auto global texture setup + // (can't put it in the profiling scope otherwise it might be executed on compute queue which is not possible for global sets) + m_Resources.PreRenderPassSetGlobalTextures(rgContext, pass.textureReadList); + + //// Just mark the place where we kick the async job on graphics pipe. + //if (pass.enableAsyncCompute) + // PushKickAsyncJobMarker(rgContext, pass); + + pass.customSampler?.Begin(rgContext.cmd); + foreach (var texture in passInfo.textureCreateList) m_Resources.CreateAndClearTexture(rgContext, texture); PreRenderPassSetRenderTargets(passIndex, rgContext); - m_Resources.PreRenderPassSetGlobalTextures(rgContext, pass.textureReadList); + + // Flush first the current command buffer on the render context. + rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd); + rgContext.cmd.Clear(); if (pass.enableAsyncCompute) { - if (!previousPassIsAsync) - { - // Flush first the current command buffer on the render context. - rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd); - rgContext.cmd.Clear(); - } - CommandBuffer asyncCmd = CommandBufferPool.Get(pass.name); asyncCmd.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute); rgContext.cmd = asyncCmd; @@ -711,8 +723,6 @@ bool PreRenderPassExecute(int passIndex, bool previousPassIsAsync, ref RenderGra { rgContext.cmd.WaitOnAsyncGraphicsFence(m_PassExecutionInfo[passInfo.syncWithPassIndex].fence); } - - return pass.enableAsyncCompute; } void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraphContext rgContext) @@ -734,6 +744,8 @@ void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraph if (m_DebugParameters.unbindGlobalTextures) m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); + pass.customSampler?.End(rgContext.cmd); + m_RenderGraphPool.ReleaseAllTempAlloc(); foreach (var texture in passInfo.textureReleaseList) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs index d3a39ac4840..7a3c5b5ca67 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs @@ -5,7 +5,7 @@ namespace UnityEngine.Experimental.Rendering.RenderGraphModule { - [DebuggerDisplay("RenderPass: {name} ({index})")] + [DebuggerDisplay("RenderPass: {name} (Index:{index} Async:{enableAsyncCompute})")] abstract class RenderGraphPass { public RenderFunc GetExecuteDelegate() @@ -117,7 +117,7 @@ public void SetDepthBuffer(TextureHandle resource, DepthAccess flags) } } - [DebuggerDisplay("RenderPass: {name} ({index})")] + [DebuggerDisplay("RenderPass: {name} (Index:{index} Async:{enableAsyncCompute})")] internal sealed class RenderGraphPass : RenderGraphPass where PassData : class, new() { diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs index fd48e4900f2..83e26a91f05 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs @@ -313,7 +313,7 @@ public enum FrameSettingsField [FrameSettingsField(2, displayedName: "SS Ambient Occlusion", positiveDependencies: new[] { AsyncCompute }, tooltip: "When enabled, HDRP calculates screen space ambient occlusion asynchronously.")] SSAOAsync = 43, // TODO: Enable thing when the render graph will be the default renderer. - // [FrameSettingsField(2, displayedName: "Contact Shadows", positiveDependencies: new[] { AsyncCompute }, tooltip: "When enabled, HDRP calculates Contact Shadows asynchronously.")] + [FrameSettingsField(2, displayedName: "Contact Shadows", positiveDependencies: new[] { AsyncCompute }, tooltip: "When enabled, HDRP calculates Contact Shadows asynchronously.")] /// When enabled, HDRP calculates Contact Shadows asynchronously. ContactShadowsAsync = 44, /// When enabled, HDRP calculates volumetric voxelization asynchronously. @@ -665,7 +665,7 @@ public int GetResolvedSssSampleBudget(HDRenderPipelineAsset hdrp) internal bool SSRRunsAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.SSRAsync]; internal bool SSAORunsAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.SSAOAsync]; // TODO: Re-enable this when the render graph will be used by default. - internal bool ContactShadowsRunAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && /* bitDatas[(int)FrameSettingsField.ContactShadowsAsync] */ false; + internal bool ContactShadowsRunAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.ContactShadowsAsync]; internal bool VolumeVoxelizationRunsAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.VolumeVoxelizationsAsync]; /// Override a frameSettings according to a mask. From 3a579d07ff7367987a0988a69a362c577e5cbcc8 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Mon, 18 May 2020 18:12:53 +0200 Subject: [PATCH 14/19] Fixed async synchronization by extending lifetime of resources freed during async pass to the first graphics task that wait for async. --- .../Runtime/RenderGraph/RenderGraph.cs | 102 +++++++++++++----- 1 file changed, 75 insertions(+), 27 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 21a0f367c1e..b83e2e816c8 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -121,7 +121,8 @@ internal struct PassExecutionInfo public int refCount; public bool pruned; public bool hasSideEffect; - public int syncWithPassIndex; + public int syncToPassIndex; // Index of the pass that needs to be waited for. + public int syncFromPassIndex; // Smaller pass index that waits for this pass. public bool needGraphicsFence; public GraphicsFence fence; @@ -138,7 +139,8 @@ public void Reset() refCount = 0; pruned = false; hasSideEffect = false; - syncWithPassIndex = -1; + syncToPassIndex = -1; + syncFromPassIndex = -1; needGraphicsFence = false; } } @@ -480,6 +482,22 @@ int GetLatestProducerIndex(int passIndex, in ResourceUsageInfo info) return result; } + + void UpdatePassSynchronization(ref PassExecutionInfo currentPassInfo, ref PassExecutionInfo producerPassInfo, int currentPassIndex, int lastProducer, ref int intLastSyncIndex) + { + // Current pass needs to waoit for pass index lastProducer + currentPassInfo.syncToPassIndex = lastProducer; + // Update latest pass waiting for the other pipe. + intLastSyncIndex = lastProducer; + + // Producer will need a graphics fence that this pass will wait on. + producerPassInfo.needGraphicsFence = true; + // We update the producer pass with the index of the smallest pass waiting for it. + // This will be used to "lock" resource from being reused until the pipe has been synchronized. + if (producerPassInfo.syncFromPassIndex == -1) + producerPassInfo.syncFromPassIndex = currentPassIndex; + } + void UpdateResourceSynchronization(ref int lastGraphicsPipeSync, ref int lastComputePipeSync, int currentPassIndex, in ResourceUsageInfo resource) { int lastProducer = GetLatestProducerIndex(currentPassIndex, resource); @@ -497,18 +515,14 @@ void UpdateResourceSynchronization(ref int lastGraphicsPipeSync, ref int lastCom { if (lastProducer > lastGraphicsPipeSync) { - currentPassInfo.syncWithPassIndex = lastProducer; - lastGraphicsPipeSync = lastProducer; - m_PassExecutionInfo[lastProducer].needGraphicsFence = true; + UpdatePassSynchronization(ref currentPassInfo, ref m_PassExecutionInfo[lastProducer], currentPassIndex, lastProducer, ref lastGraphicsPipeSync); } } else { if (lastProducer > lastComputePipeSync) { - currentPassInfo.syncWithPassIndex = lastProducer; - lastComputePipeSync = lastProducer; - m_PassExecutionInfo[lastProducer].needGraphicsFence = true; + UpdatePassSynchronization(ref currentPassInfo, ref m_PassExecutionInfo[lastProducer], currentPassIndex, lastProducer, ref lastComputePipeSync); } } } @@ -565,7 +579,9 @@ void UpdateResourceAllocationAndSynchronization() foreach (TextureHandle texture in pass.transientTextureList) { passInfo.textureCreateList.Add(texture); - passInfo.textureReleaseList.Add(texture); + + ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + info.lastReadPassIndex = passIndex; } // Gather all renderer lists @@ -578,8 +594,37 @@ void UpdateResourceAllocationAndSynchronization() ResourceUsageInfo textureInfo = m_TextureUsageInfo[i]; if (textureInfo.lastReadPassIndex != -1) { - ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[textureInfo.lastReadPassIndex]; - passInfo.textureReleaseList.Add(new TextureHandle(i)); + RenderGraphPass pass = m_RenderPasses[textureInfo.lastReadPassIndex]; + // In case of async passes, we need to extend lifetime of resource to the first pass on the graphics pipeline that wait for async passes to be over. + // Otherwise, if we freed the resource right away during an async pass, another non async pass could reuse the resource even though the async pipe is not done. + if (pass.enableAsyncCompute) + { + int currentPassIndex = textureInfo.lastReadPassIndex; + int firstWaitingPassIndex = m_PassExecutionInfo[currentPassIndex].syncFromPassIndex; + // Find the first async pass that is synchronized by the graphics pipeline (ie: passInfo.syncFromPassIndex != -1) + while (firstWaitingPassIndex == -1 && currentPassIndex < m_RenderPasses.Count) + { + currentPassIndex++; + if(m_RenderPasses[currentPassIndex].enableAsyncCompute) + firstWaitingPassIndex = m_PassExecutionInfo[currentPassIndex].syncFromPassIndex; + } + + // Finally add the release command to the pass before the first pass that waits for the compute pipe. + ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[Math.Max(0, firstWaitingPassIndex - 1)]; + passInfo.textureReleaseList.Add(new TextureHandle(i)); + + // Fail safe in case render graph is badly formed. + if (currentPassIndex == m_RenderPasses.Count) + { + RenderGraphPass invalidPass = m_RenderPasses[textureInfo.lastReadPassIndex]; + throw new InvalidOperationException($"Asynchronous pass {invalidPass.name} was never synchronized on the graphics pipeline."); + } + } + else + { + ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[textureInfo.lastReadPassIndex]; + passInfo.textureReleaseList.Add(new TextureHandle(i)); + } } } @@ -622,12 +667,15 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", pass.name)); } - LogRenderPassBegin(passIndex); - using (new RenderGraphLogIndent(m_Logger)) + using (new ProfilingScope(rgContext.cmd, pass.customSampler)) { - PreRenderPassExecute(passIndex, ref rgContext); - pass.Execute(rgContext); - PostRenderPassExecute(cmd, passIndex, ref rgContext); + LogRenderPassBegin(passIndex); + using (new RenderGraphLogIndent(m_Logger)) + { + PreRenderPassExecute(passIndex, ref rgContext); + pass.Execute(rgContext); + PostRenderPassExecute(cmd, passIndex, ref rgContext); + } } } } @@ -700,7 +748,7 @@ void PreRenderPassExecute(int passIndex, ref RenderGraphContext rgContext) //if (pass.enableAsyncCompute) // PushKickAsyncJobMarker(rgContext, pass); - pass.customSampler?.Begin(rgContext.cmd); + //pass.customSampler?.Begin(rgContext.cmd); foreach (var texture in passInfo.textureCreateList) m_Resources.CreateAndClearTexture(rgContext, texture); @@ -719,9 +767,9 @@ void PreRenderPassExecute(int passIndex, ref RenderGraphContext rgContext) } // Synchronize with graphics or compute pipe if needed. - if (passInfo.syncWithPassIndex != -1) + if (passInfo.syncToPassIndex != -1) { - rgContext.cmd.WaitOnAsyncGraphicsFence(m_PassExecutionInfo[passInfo.syncWithPassIndex].fence); + rgContext.cmd.WaitOnAsyncGraphicsFence(m_PassExecutionInfo[passInfo.syncToPassIndex].fence); } } @@ -744,7 +792,7 @@ void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraph if (m_DebugParameters.unbindGlobalTextures) m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); - pass.customSampler?.End(rgContext.cmd); + //pass.customSampler?.End(rgContext.cmd); m_RenderGraphPool.ReleaseAllTempAlloc(); @@ -764,7 +812,7 @@ void LogFrameInformation(int renderingWidth, int renderingHeight) if (m_DebugParameters.logFrameInformation) { m_Logger.LogLine("==== Staring frame at resolution ({0}x{1}) ====", renderingWidth, renderingHeight); - m_Logger.LogLine("Number of passes declared: {0}", m_RenderPasses.Count); + m_Logger.LogLine("Number of passes declared: {0}\n", m_RenderPasses.Count); } } @@ -772,7 +820,7 @@ void LogRendererListsCreation() { if (m_DebugParameters.logFrameInformation) { - m_Logger.LogLine("Number of renderer lists created: {0}", m_RendererLists.Count); + m_Logger.LogLine("Number of renderer lists created: {0}\n", m_RendererLists.Count); } } @@ -783,12 +831,11 @@ void LogRenderPassBegin(int passIndex) RenderGraphPass pass = m_RenderPasses[passIndex]; PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; - m_Logger.LogLine("Executing pass \"{0}\" (index: {1})", pass.name, pass.index); + m_Logger.LogLine("[{0}][{1}] \"{2}\"", pass.index, pass.enableAsyncCompute ? "Compute" : "Graphics", pass.name); using (new RenderGraphLogIndent(m_Logger)) { - m_Logger.LogLine("Queue: {0}", pass.enableAsyncCompute ? "Compute" : "Graphics"); - if (passInfo.syncWithPassIndex != -1) - m_Logger.LogLine("Synchronize with pass index: {0}", passInfo.syncWithPassIndex); + if (passInfo.syncToPassIndex != -1) + m_Logger.LogLine("Synchronize with [{0}]", passInfo.syncToPassIndex); } } } @@ -805,9 +852,10 @@ void LogPrunedPasses() if (m_PassExecutionInfo[i].pruned) { var pass = m_RenderPasses[i]; - m_Logger.LogLine("{0} (index: {1})", pass.name, pass.index); + m_Logger.LogLine("[{0}] {1}", pass.index, pass.name); } } + m_Logger.LogLine("\n"); } } } From 96f556321479b18025be6667c6b899b04ccb20dd Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Tue, 19 May 2020 16:28:10 +0200 Subject: [PATCH 15/19] Post merge fix --- .../VolumetricLighting/VolumetricLighting.cs | 31 +++++-------------- .../RenderPipeline/HDRenderPipeline.cs | 2 -- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs index 4718a0b7021..7c3280d4d4f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs @@ -342,7 +342,7 @@ static internal void UpdateVolumetricBufferParams(HDCamera hdCamera, int frameIn // Do not access 'rt.name', it allocates memory every time... // Have to manually cache and pass the name. - static internal bool ResizeVolumetricBuffer(ref RTHandle rt, string name, int viewportWidth, int viewportHeight, int viewportDepth) + static internal void ResizeVolumetricBuffer(ref RTHandle rt, string name, int viewportWidth, int viewportHeight, int viewportDepth) { Debug.Assert(rt != null); @@ -362,11 +362,7 @@ static internal bool ResizeVolumetricBuffer(ref RTHandle rt, string name, int vi rt = RTHandles.Alloc(width, height, depth, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: name); - - return true; } - - return false; } static internal void CreateVolumetricHistoryBuffers(HDCamera hdCamera, int bufferCount) @@ -452,22 +448,6 @@ internal void CreateVolumetricLightingBuffers() m_VisibleVolumeBoundsBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(OrientedBBox))); m_VisibleVolumeDataBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(DensityVolumeEngineData))); - VolumetricInitializeNonRenderGraphResource(); - } - - internal void DestroyVolumetricLightingBuffers() - { - VolumetricCleanupNonRenderGraphResource(); - - CoreUtils.SafeRelease(m_VisibleVolumeDataBuffer); - CoreUtils.SafeRelease(m_VisibleVolumeBoundsBuffer); - - m_VisibleVolumeData = null; // free() - m_VisibleVolumeBounds = null; // free() - } - - void VolumetricInitializeNonRenderGraphResource() - { // Allocate the smallest possible 3D texture. // We will perform rescaling manually, in a custom manner, based on volume parameters. const int minSize = 4; @@ -479,12 +459,17 @@ void VolumetricInitializeNonRenderGraphResource() dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: "VBufferLighting"); } - void VolumetricCleanupNonRenderGraphResource() + internal void DestroyVolumetricLightingBuffers() { RTHandles.Release(m_LightingBuffer); RTHandles.Release(m_DensityBuffer); - } + CoreUtils.SafeRelease(m_VisibleVolumeDataBuffer); + CoreUtils.SafeRelease(m_VisibleVolumeBoundsBuffer); + + m_VisibleVolumeData = null; // free() + m_VisibleVolumeBounds = null; // free() + } // Must be called AFTER UpdateVolumetricBufferParams. internal void ResizeVolumetricLightingBuffers(HDCamera hdCamera, int frameIndex) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index bd593850548..ae1056e15aa 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -925,7 +925,6 @@ void InitializeNonRenderGraphResources() m_ShadowManager.InitializeNonRenderGraphResources(); m_AmbientOcclusionSystem.InitializeNonRenderGraphResources(); m_PostProcessSystem.InitializeNonRenderGraphResources(asset); - VolumetricInitializeNonRenderGraphResource(); s_lightVolumes.InitializeNonRenderGraphResources(); } @@ -935,7 +934,6 @@ void CleanupNonRenderGraphResources() m_ShadowManager.CleanupNonRenderGraphResources(); m_AmbientOcclusionSystem.CleanupNonRenderGraphResources(); m_PostProcessSystem.CleanupNonRenderGraphResources(); - VolumetricCleanupNonRenderGraphResource(); s_lightVolumes.CleanupNonRenderGraphResources(); } From fdec415480df2e888b5dee94e5465b4ba1da9f5e Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Tue, 19 May 2020 17:45:51 +0200 Subject: [PATCH 16/19] Cleanup --- .../Runtime/RenderGraph/RenderGraph.cs | 222 ++++++++---------- 1 file changed, 100 insertions(+), 122 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 56aef80df5b..b9782ac0486 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -93,7 +93,7 @@ public class RenderGraph ///Maximum number of MRTs supported by Render Graph. public static readonly int kMaxMRTCount = 8; - internal struct ResourceUsageInfo + internal struct CompiledResourceInfo { public List producers; public bool resourceCreated; @@ -114,8 +114,9 @@ public void Reset() } } - internal struct PassExecutionInfo + internal struct CompiledPassInfo { + public RenderGraphPass pass; public List textureCreateList; public List textureReleaseList; public int refCount; @@ -126,8 +127,12 @@ internal struct PassExecutionInfo public bool needGraphicsFence; public GraphicsFence fence; - public void Reset() + public bool enableAsyncCompute { get { return pass.enableAsyncCompute; } } + + public void Reset(RenderGraphPass pass) { + this.pass = pass; + if (textureCreateList == null) { textureCreateList = new List(); @@ -155,9 +160,9 @@ public void Reset() Dictionary m_DefaultProfilingSamplers = new Dictionary(); // Compiled Render Graph info. - DynamicArray m_TextureUsageInfo = new DynamicArray(); - DynamicArray m_BufferUsageInfo = new DynamicArray(); - DynamicArray m_PassExecutionInfo = new DynamicArray(); + DynamicArray m_CompiledTextureInfos = new DynamicArray(); + DynamicArray m_CompiledBufferInfos = new DynamicArray(); + DynamicArray m_CompiledPassInfos = new DynamicArray(); Stack m_PruningStack = new Stack(); #region Public Interface @@ -371,42 +376,41 @@ void ClearCompiledGraph() m_Resources.Clear(); m_DefaultResources.Clear(); m_RendererLists.Clear(); - m_BufferUsageInfo.Clear(); - m_TextureUsageInfo.Clear(); - m_PassExecutionInfo.Clear(); + m_CompiledBufferInfos.Clear(); + m_CompiledTextureInfos.Clear(); + m_CompiledPassInfos.Clear(); } void InitializeCompilationData() { - m_BufferUsageInfo.Resize(m_Resources.GetComputeBufferResourceCount()); - for (int i = 0; i < m_BufferUsageInfo.size; ++i) - m_BufferUsageInfo[i].Reset(); - m_TextureUsageInfo.Resize(m_Resources.GetTextureResourceCount()); - for (int i = 0; i < m_TextureUsageInfo.size; ++i) - m_TextureUsageInfo[i].Reset(); - m_PassExecutionInfo.Resize(m_RenderPasses.Count); - for (int i = 0; i < m_PassExecutionInfo.size; ++i) - m_PassExecutionInfo[i].Reset(); + m_CompiledBufferInfos.Resize(m_Resources.GetComputeBufferResourceCount()); + for (int i = 0; i < m_CompiledBufferInfos.size; ++i) + m_CompiledBufferInfos[i].Reset(); + m_CompiledTextureInfos.Resize(m_Resources.GetTextureResourceCount()); + for (int i = 0; i < m_CompiledTextureInfos.size; ++i) + m_CompiledTextureInfos[i].Reset(); + m_CompiledPassInfos.Resize(m_RenderPasses.Count); + for (int i = 0; i < m_CompiledPassInfos.size; ++i) + m_CompiledPassInfos[i].Reset(m_RenderPasses[i]); } void CountReferences() { - for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) + for (int passIndex = 0; passIndex < m_CompiledPassInfos.size; ++passIndex) { - RenderGraphPass pass = m_RenderPasses[passIndex]; - ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; + ref CompiledPassInfo passInfo = ref m_CompiledPassInfos[passIndex]; - var textureRead = pass.textureReadList; + var textureRead = passInfo.pass.textureReadList; foreach (TextureHandle texture in textureRead) { - ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + ref CompiledResourceInfo info = ref m_CompiledTextureInfos[texture]; info.refCount++; } - var textureWrite = pass.textureWriteList; + var textureWrite = passInfo.pass.textureWriteList; foreach (TextureHandle texture in textureWrite) { - ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + ref CompiledResourceInfo info = ref m_CompiledTextureInfos[texture]; info.producers.Add(passIndex); passInfo.refCount++; @@ -416,23 +420,23 @@ void CountReferences() } // Can't share the code with a generic func as TextureHandle and ComputeBufferHandle are both struct and can't inherit from a common struct with a shared API (thanks C#) - var bufferRead = pass.bufferReadList; + var bufferRead = passInfo.pass.bufferReadList; foreach (ComputeBufferHandle buffer in bufferRead) { - ref ResourceUsageInfo info = ref m_BufferUsageInfo[buffer]; + ref CompiledResourceInfo info = ref m_CompiledBufferInfos[buffer]; info.refCount++; } - var bufferWrite = pass.bufferWriteList; + var bufferWrite = passInfo.pass.bufferWriteList; foreach (ComputeBufferHandle buffer in bufferWrite) { - ref ResourceUsageInfo info = ref m_BufferUsageInfo[buffer]; + ref CompiledResourceInfo info = ref m_CompiledBufferInfos[buffer]; passInfo.refCount++; } } } - void PruneUnusedPasses(DynamicArray resourceUsageList) + void PruneUnusedPasses(DynamicArray resourceUsageList) { // First gather resources that are never read. m_PruningStack.Clear(); @@ -449,20 +453,19 @@ void PruneUnusedPasses(DynamicArray resourceUsageList) var unusedResource = resourceUsageList[m_PruningStack.Pop()]; foreach (var producerIndex in unusedResource.producers) { - ref var producerInfo = ref m_PassExecutionInfo[producerIndex]; + ref var producerInfo = ref m_CompiledPassInfos[producerIndex]; producerInfo.refCount--; if (producerInfo.refCount == 0 && !producerInfo.hasSideEffect) { // Producer is not necessary anymore as it produces zero resources // Prune it and decrement refCount of all the textures it reads. producerInfo.pruned = true; - RenderGraphPass pass = m_RenderPasses[producerIndex]; - foreach (var textureIndex in pass.textureReadList) + foreach (var textureIndex in producerInfo.pass.textureReadList) { - ref ResourceUsageInfo textureInfo = ref resourceUsageList[textureIndex]; - textureInfo.refCount--; + ref CompiledResourceInfo resourceInfo = ref resourceUsageList[textureIndex]; + resourceInfo.refCount--; // If a texture is not used anymore, add it to the stack to be processed in subsequent iteration. - if (textureInfo.refCount == 0) + if (resourceInfo.refCount == 0) m_PruningStack.Push(textureIndex); } } @@ -472,12 +475,12 @@ void PruneUnusedPasses(DynamicArray resourceUsageList) void PruneUnusedPasses() { - PruneUnusedPasses(m_TextureUsageInfo); - PruneUnusedPasses(m_BufferUsageInfo); + PruneUnusedPasses(m_CompiledTextureInfos); + PruneUnusedPasses(m_CompiledBufferInfos); LogPrunedPasses(); } - int GetLatestProducerIndex(int passIndex, in ResourceUsageInfo info) + int GetLatestProducerIndex(int passIndex, in CompiledResourceInfo info) { // We want to know the highest pass index below the current pass that writes to the resource. int result = -1; @@ -494,7 +497,7 @@ int GetLatestProducerIndex(int passIndex, in ResourceUsageInfo info) } - void UpdatePassSynchronization(ref PassExecutionInfo currentPassInfo, ref PassExecutionInfo producerPassInfo, int currentPassIndex, int lastProducer, ref int intLastSyncIndex) + void UpdatePassSynchronization(ref CompiledPassInfo currentPassInfo, ref CompiledPassInfo producerPassInfo, int currentPassIndex, int lastProducer, ref int intLastSyncIndex) { // Current pass needs to waoit for pass index lastProducer currentPassInfo.syncToPassIndex = lastProducer; @@ -509,31 +512,29 @@ void UpdatePassSynchronization(ref PassExecutionInfo currentPassInfo, ref PassEx producerPassInfo.syncFromPassIndex = currentPassIndex; } - void UpdateResourceSynchronization(ref int lastGraphicsPipeSync, ref int lastComputePipeSync, int currentPassIndex, in ResourceUsageInfo resource) + void UpdateResourceSynchronization(ref int lastGraphicsPipeSync, ref int lastComputePipeSync, int currentPassIndex, in CompiledResourceInfo resource) { int lastProducer = GetLatestProducerIndex(currentPassIndex, resource); if (lastProducer != -1) { - RenderGraphPass currentPass = m_RenderPasses[currentPassIndex]; - ref PassExecutionInfo currentPassInfo = ref m_PassExecutionInfo[currentPassIndex]; + ref CompiledPassInfo currentPassInfo = ref m_CompiledPassInfos[currentPassIndex]; - RenderGraphPass producerPass = m_RenderPasses[lastProducer]; //If the passes are on different pipes, we need synchronization. - if (producerPass.enableAsyncCompute != currentPass.enableAsyncCompute) + if (m_CompiledPassInfos[lastProducer].enableAsyncCompute != currentPassInfo.enableAsyncCompute) { // Pass is on compute pipe, need sync with graphics pipe. - if (currentPass.enableAsyncCompute) + if (currentPassInfo.enableAsyncCompute) { if (lastProducer > lastGraphicsPipeSync) { - UpdatePassSynchronization(ref currentPassInfo, ref m_PassExecutionInfo[lastProducer], currentPassIndex, lastProducer, ref lastGraphicsPipeSync); + UpdatePassSynchronization(ref currentPassInfo, ref m_CompiledPassInfos[lastProducer], currentPassIndex, lastProducer, ref lastGraphicsPipeSync); } } else { if (lastProducer > lastComputePipeSync) { - UpdatePassSynchronization(ref currentPassInfo, ref m_PassExecutionInfo[lastProducer], currentPassIndex, lastProducer, ref lastComputePipeSync); + UpdatePassSynchronization(ref currentPassInfo, ref m_CompiledPassInfos[lastProducer], currentPassIndex, lastProducer, ref lastComputePipeSync); } } } @@ -549,83 +550,80 @@ void UpdateResourceAllocationAndSynchronization() // - Update the last pass read index for each resource. // - Add texture to creation list for passes that first write to a texture. // - Update synchronization points for all resources between compute and graphics pipes. - for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) + for (int passIndex = 0; passIndex < m_CompiledPassInfos.size; ++passIndex) { - ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; + ref CompiledPassInfo passInfo = ref m_CompiledPassInfos[passIndex]; if (passInfo.pruned) continue; - RenderGraphPass pass = m_RenderPasses[passIndex]; - - foreach (TextureHandle texture in pass.textureReadList) + foreach (TextureHandle texture in passInfo.pass.textureReadList) { - ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; - info.lastReadPassIndex = Math.Max(info.lastReadPassIndex, passIndex); - UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, info); + ref CompiledResourceInfo resourceInfo = ref m_CompiledTextureInfos[texture]; + resourceInfo.lastReadPassIndex = Math.Max(resourceInfo.lastReadPassIndex, passIndex); + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, resourceInfo); } - foreach (TextureHandle texture in pass.textureWriteList) + foreach (TextureHandle texture in passInfo.pass.textureWriteList) { - ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; - if (info.firstWritePassIndex == int.MaxValue) + ref CompiledResourceInfo resourceInfo = ref m_CompiledTextureInfos[texture]; + if (resourceInfo.firstWritePassIndex == int.MaxValue) { - info.firstWritePassIndex = Math.Min(info.firstWritePassIndex, passIndex); + resourceInfo.firstWritePassIndex = Math.Min(resourceInfo.firstWritePassIndex, passIndex); passInfo.textureCreateList.Add(texture); } passInfo.refCount++; - UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, info); + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, resourceInfo); } - foreach (ComputeBufferHandle texture in pass.bufferReadList) + foreach (ComputeBufferHandle texture in passInfo.pass.bufferReadList) { - UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, m_BufferUsageInfo[texture]); + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, m_CompiledBufferInfos[texture]); } - foreach (ComputeBufferHandle texture in pass.bufferWriteList) + foreach (ComputeBufferHandle texture in passInfo.pass.bufferWriteList) { - UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, m_BufferUsageInfo[texture]); + UpdateResourceSynchronization(ref lastGraphicsPipeSync, ref lastComputePipeSync, passIndex, m_CompiledBufferInfos[texture]); } // Add transient resources that are only used during this pass. - foreach (TextureHandle texture in pass.transientTextureList) + foreach (TextureHandle texture in passInfo.pass.transientTextureList) { passInfo.textureCreateList.Add(texture); - ref ResourceUsageInfo info = ref m_TextureUsageInfo[texture]; + ref CompiledResourceInfo info = ref m_CompiledTextureInfos[texture]; info.lastReadPassIndex = passIndex; } // Gather all renderer lists - m_RendererLists.AddRange(m_RenderPasses[passIndex].usedRendererListList); + m_RendererLists.AddRange(passInfo.pass.usedRendererListList); } // Now push textures to the release list of the pass that reads it last. - for (int i = 0; i < m_TextureUsageInfo.size; ++i) + for (int i = 0; i < m_CompiledTextureInfos.size; ++i) { - ResourceUsageInfo textureInfo = m_TextureUsageInfo[i]; + CompiledResourceInfo textureInfo = m_CompiledTextureInfos[i]; if (textureInfo.lastReadPassIndex != -1) { - RenderGraphPass pass = m_RenderPasses[textureInfo.lastReadPassIndex]; // In case of async passes, we need to extend lifetime of resource to the first pass on the graphics pipeline that wait for async passes to be over. // Otherwise, if we freed the resource right away during an async pass, another non async pass could reuse the resource even though the async pipe is not done. - if (pass.enableAsyncCompute) + if (m_CompiledPassInfos[textureInfo.lastReadPassIndex].enableAsyncCompute) { int currentPassIndex = textureInfo.lastReadPassIndex; - int firstWaitingPassIndex = m_PassExecutionInfo[currentPassIndex].syncFromPassIndex; + int firstWaitingPassIndex = m_CompiledPassInfos[currentPassIndex].syncFromPassIndex; // Find the first async pass that is synchronized by the graphics pipeline (ie: passInfo.syncFromPassIndex != -1) - while (firstWaitingPassIndex == -1 && currentPassIndex < m_RenderPasses.Count) + while (firstWaitingPassIndex == -1 && currentPassIndex < m_CompiledPassInfos.size) { currentPassIndex++; - if(m_RenderPasses[currentPassIndex].enableAsyncCompute) - firstWaitingPassIndex = m_PassExecutionInfo[currentPassIndex].syncFromPassIndex; + if(m_CompiledPassInfos[currentPassIndex].enableAsyncCompute) + firstWaitingPassIndex = m_CompiledPassInfos[currentPassIndex].syncFromPassIndex; } // Finally add the release command to the pass before the first pass that waits for the compute pipe. - ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[Math.Max(0, firstWaitingPassIndex - 1)]; + ref CompiledPassInfo passInfo = ref m_CompiledPassInfos[Math.Max(0, firstWaitingPassIndex - 1)]; passInfo.textureReleaseList.Add(new TextureHandle(i)); // Fail safe in case render graph is badly formed. - if (currentPassIndex == m_RenderPasses.Count) + if (currentPassIndex == m_CompiledPassInfos.size) { RenderGraphPass invalidPass = m_RenderPasses[textureInfo.lastReadPassIndex]; throw new InvalidOperationException($"Asynchronous pass {invalidPass.name} was never synchronized on the graphics pipeline."); @@ -633,7 +631,7 @@ void UpdateResourceAllocationAndSynchronization() } else { - ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[textureInfo.lastReadPassIndex]; + ref CompiledPassInfo passInfo = ref m_CompiledPassInfos[textureInfo.lastReadPassIndex]; passInfo.textureReleaseList.Add(new TextureHandle(i)); } } @@ -666,34 +664,33 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd rgContext.resources = m_Resources; rgContext.defaultResources = m_DefaultResources; - for (int passIndex = 0; passIndex < m_RenderPasses.Count; ++passIndex) + for (int passIndex = 0; passIndex < m_CompiledPassInfos.size; ++passIndex) { - var passInfo = m_PassExecutionInfo[passIndex]; + ref var passInfo = ref m_CompiledPassInfos[passIndex]; if (passInfo.pruned) continue; - var pass = m_RenderPasses[passIndex]; - if (!pass.HasRenderFunc()) + if (!passInfo.pass.HasRenderFunc()) { - throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", pass.name)); + throw new InvalidOperationException(string.Format("RenderPass {0} was not provided with an execute function.", passInfo.pass.name)); } - using (new ProfilingScope(rgContext.cmd, pass.customSampler)) + using (new ProfilingScope(rgContext.cmd, passInfo.pass.customSampler)) { - LogRenderPassBegin(passIndex); + LogRenderPassBegin(passInfo); using (new RenderGraphLogIndent(m_Logger)) { - PreRenderPassExecute(passIndex, ref rgContext); - pass.Execute(rgContext); - PostRenderPassExecute(cmd, passIndex, ref rgContext); + PreRenderPassExecute(passInfo, ref rgContext); + passInfo.pass.Execute(rgContext); + PostRenderPassExecute(cmd, ref passInfo, ref rgContext); } } } } - void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) + void PreRenderPassSetRenderTargets(in CompiledPassInfo passInfo, RenderGraphContext rgContext) { - var pass = m_RenderPasses[passIndex]; + var pass = passInfo.pass; if (pass.depthBuffer.IsValid() || pass.colorBufferMaxIndex != -1) { var mrtArray = rgContext.renderGraphPool.GetTempArray(pass.colorBufferMaxIndex + 1); @@ -735,36 +732,19 @@ void PreRenderPassSetRenderTargets(int passIndex, RenderGraphContext rgContext) } } - void PushKickAsyncJobMarker(in RenderGraphContext rgContext, RenderGraphPass pass) - { - //var sampler = GetDefaultProfilingSampler($"Kick Async Job: {pass.name}"); - //sampler.Begin(rgContext.cmd); - //sampler.End(rgContext.cmd); - var name = $"Kick Async Job: {pass.name}"; - rgContext.cmd.BeginSample(name); - rgContext.cmd.EndSample(name); - } - - void PreRenderPassExecute(int passIndex, ref RenderGraphContext rgContext) + void PreRenderPassExecute(in CompiledPassInfo passInfo, ref RenderGraphContext rgContext) { // TODO RENDERGRAPH merge clear and setup here if possible - RenderGraphPass pass = m_RenderPasses[passIndex]; - PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; + RenderGraphPass pass = passInfo.pass; // TODO RENDERGRAPH remove this when we do away with auto global texture setup // (can't put it in the profiling scope otherwise it might be executed on compute queue which is not possible for global sets) m_Resources.PreRenderPassSetGlobalTextures(rgContext, pass.textureReadList); - //// Just mark the place where we kick the async job on graphics pipe. - //if (pass.enableAsyncCompute) - // PushKickAsyncJobMarker(rgContext, pass); - - //pass.customSampler?.Begin(rgContext.cmd); - foreach (var texture in passInfo.textureCreateList) m_Resources.CreateAndClearTexture(rgContext, texture); - PreRenderPassSetRenderTargets(passIndex, rgContext); + PreRenderPassSetRenderTargets(passInfo, rgContext); // Flush first the current command buffer on the render context. rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd); @@ -780,14 +760,13 @@ void PreRenderPassExecute(int passIndex, ref RenderGraphContext rgContext) // Synchronize with graphics or compute pipe if needed. if (passInfo.syncToPassIndex != -1) { - rgContext.cmd.WaitOnAsyncGraphicsFence(m_PassExecutionInfo[passInfo.syncToPassIndex].fence); + rgContext.cmd.WaitOnAsyncGraphicsFence(m_CompiledPassInfos[passInfo.syncToPassIndex].fence); } } - void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraphContext rgContext) + void PostRenderPassExecute(CommandBuffer mainCmd, ref CompiledPassInfo passInfo, ref RenderGraphContext rgContext) { - RenderGraphPass pass = m_RenderPasses[passIndex]; - ref PassExecutionInfo passInfo = ref m_PassExecutionInfo[passIndex]; + RenderGraphPass pass = passInfo.pass; if (passInfo.needGraphicsFence) passInfo.fence = rgContext.cmd.CreateAsyncGraphicsFence(); @@ -801,7 +780,7 @@ void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraph } if (m_DebugParameters.unbindGlobalTextures) - m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, m_RenderPasses[passIndex].textureReadList); + m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, pass.textureReadList); //pass.customSampler?.End(rgContext.cmd); @@ -810,7 +789,7 @@ void PostRenderPassExecute(CommandBuffer mainCmd, int passIndex, ref RenderGraph foreach (var texture in passInfo.textureReleaseList) m_Resources.ReleaseTexture(rgContext, texture); - m_RenderPasses[passIndex].Release(rgContext); + pass.Release(rgContext); } void ClearRenderPasses() @@ -835,12 +814,11 @@ void LogRendererListsCreation() } } - void LogRenderPassBegin(int passIndex) + void LogRenderPassBegin(in CompiledPassInfo passInfo) { if (m_DebugParameters.logFrameInformation) { - RenderGraphPass pass = m_RenderPasses[passIndex]; - PassExecutionInfo passInfo = m_PassExecutionInfo[passIndex]; + RenderGraphPass pass = passInfo.pass; m_Logger.LogLine("[{0}][{1}] \"{2}\"", pass.index, pass.enableAsyncCompute ? "Compute" : "Graphics", pass.name); using (new RenderGraphLogIndent(m_Logger)) @@ -858,9 +836,9 @@ void LogPrunedPasses() m_Logger.LogLine("Pass pruning report:"); using (new RenderGraphLogIndent(m_Logger)) { - for (int i = 0; i < m_PassExecutionInfo.size; ++i) + for (int i = 0; i < m_CompiledPassInfos.size; ++i) { - if (m_PassExecutionInfo[i].pruned) + if (m_CompiledPassInfos[i].pruned) { var pass = m_RenderPasses[i]; m_Logger.LogLine("[{0}] {1}", pass.index, pass.name); From e5f899329f749268edc7ffba7944dfc1c730aaa6 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Tue, 19 May 2020 17:49:11 +0200 Subject: [PATCH 17/19] Removed comment. --- .../Runtime/RenderGraph/RenderGraph.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index b9782ac0486..82c8b680e36 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -782,8 +782,6 @@ void PostRenderPassExecute(CommandBuffer mainCmd, ref CompiledPassInfo passInfo, if (m_DebugParameters.unbindGlobalTextures) m_Resources.PostRenderPassUnbindGlobalTextures(rgContext, pass.textureReadList); - //pass.customSampler?.End(rgContext.cmd); - m_RenderGraphPool.ReleaseAllTempAlloc(); foreach (var texture in passInfo.textureReleaseList) From 6728b7e51be271cdb2b75da9e332ac008acf1d95 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Tue, 19 May 2020 17:53:52 +0200 Subject: [PATCH 18/19] Disabled async contact shadows again. --- .../Runtime/RenderPipeline/Settings/FrameSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs index 58e0af78d26..f64263a22bd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs @@ -315,7 +315,7 @@ public enum FrameSettingsField [FrameSettingsField(2, displayedName: "SS Ambient Occlusion", positiveDependencies: new[] { AsyncCompute }, tooltip: "When enabled, HDRP calculates screen space ambient occlusion asynchronously.")] SSAOAsync = 43, // TODO: Enable thing when the render graph will be the default renderer. - [FrameSettingsField(2, displayedName: "Contact Shadows", positiveDependencies: new[] { AsyncCompute }, tooltip: "When enabled, HDRP calculates Contact Shadows asynchronously.")] + //[FrameSettingsField(2, displayedName: "Contact Shadows", positiveDependencies: new[] { AsyncCompute }, tooltip: "When enabled, HDRP calculates Contact Shadows asynchronously.")] /// When enabled, HDRP calculates Contact Shadows asynchronously. ContactShadowsAsync = 44, /// When enabled, HDRP calculates volumetric voxelization asynchronously. @@ -670,7 +670,7 @@ public int GetResolvedSssSampleBudget(HDRenderPipelineAsset hdrp) internal bool SSRRunsAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.SSRAsync]; internal bool SSAORunsAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.SSAOAsync]; // TODO: Re-enable this when the render graph will be used by default. - internal bool ContactShadowsRunAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.ContactShadowsAsync]; + internal bool ContactShadowsRunAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && /*bitDatas[(int)FrameSettingsField.ContactShadowsAsync]*/ false; internal bool VolumeVoxelizationRunsAsync() => SystemInfo.supportsAsyncCompute && bitDatas[(int)FrameSettingsField.AsyncCompute] && bitDatas[(int)FrameSettingsField.VolumeVoxelizationsAsync]; /// Override a frameSettings according to a mask. From 6c7e6ddd851c415c1e879e287258299f91448412 Mon Sep 17 00:00:00 2001 From: Julien Ignace Date: Wed, 20 May 2020 15:37:49 +0200 Subject: [PATCH 19/19] Small cleanup --- .../Runtime/RenderGraph/RenderGraph.cs | 2 +- .../RenderGraph/RenderGraphResourceRegistry.cs | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 82c8b680e36..8cd7f991fbc 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -499,7 +499,7 @@ int GetLatestProducerIndex(int passIndex, in CompiledResourceInfo info) void UpdatePassSynchronization(ref CompiledPassInfo currentPassInfo, ref CompiledPassInfo producerPassInfo, int currentPassIndex, int lastProducer, ref int intLastSyncIndex) { - // Current pass needs to waoit for pass index lastProducer + // Current pass needs to wait for pass index lastProducer currentPassInfo.syncToPassIndex = lastProducer; // Update latest pass waiting for the other pipe. intLastSyncIndex = lastProducer; diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs index ca3f3ea16bc..c186e92c47f 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs @@ -610,15 +610,11 @@ internal void ReleaseTexture(RenderGraphContext rgContext, TextureHandle resourc } } - //// This can happen because we release texture in two passes (see ReleaseTexturesForPass) and texture can be present in both passes - //if (resourceDesc.rt != null) - { - LogTextureRelease(resourceDesc.rt); - ReleaseTextureResource(resourceDesc.cachedHash, resourceDesc.rt); - resourceDesc.cachedHash = -1; - resourceDesc.rt = null; - resourceDesc.wasReleased = true; - } + LogTextureRelease(resourceDesc.rt); + ReleaseTextureResource(resourceDesc.cachedHash, resourceDesc.rt); + resourceDesc.cachedHash = -1; + resourceDesc.rt = null; + resourceDesc.wasReleased = true; } }