Skip to content

Correctly dealloc/realloc resources when switching RenderGraph on and off. #328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 19, 2020
30 changes: 19 additions & 11 deletions com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public ref struct RenderGraphContext
public RenderGraphObjectPool renderGraphPool;
///<summary>Render Graph Resource Registry used for accessing resources.</summary>
public RenderGraphResourceRegistry resources;
///<summary>Render Graph default resources.</summary>
public RenderGraphDefaultResources defaultResources;
}

/// <summary>
Expand All @@ -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;
Expand All @@ -61,16 +62,15 @@ class RenderGraphDebugParams
public void RegisterDebug()
{
var list = new List<DebugUI.Widget>();
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 });
list.Add(new DebugUI.BoolField { displayName = "Unbind Global Textures", getter = () => unbindGlobalTextures, setter = value => unbindGlobalTextures = value });
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()
Expand Down Expand Up @@ -194,20 +194,25 @@ internal override bool HasRenderFunc()
List<RendererListHandle> m_RendererLists = new List<RendererListHandle>();
RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams();
RenderGraphLogger m_Logger = new RenderGraphLogger();
RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources();

#region Public Interface

/// <summary>
/// Returns true if rendering with Render Graph is enabled.
/// </summary>
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.
/// <summary>
/// Gets the RTHandleProperties structure associated with the Render Graph's RTHandle System.
/// </summary>
public RTHandleProperties rtHandleProperties { get { return m_Resources.GetRTHandleProperties(); } }

public RenderGraphDefaultResources defaultResources
{
get
{
m_DefaultResources.InitializeForRendering(this);
return m_DefaultResources;
}
}

/// <summary>
/// Render Graph constructor.
/// </summary>
Expand All @@ -224,22 +229,23 @@ public RenderGraph(bool supportMSAA, MSAASamples initialSampleCount)
public void Cleanup()
{
m_Resources.Cleanup();
m_DefaultResources.Cleanup();
}

/// <summary>
/// Register this Render Graph to the debug window.
/// </summary>
public void RegisterDebug()
{
//m_DebugParameters.RegisterDebug();
m_DebugParameters.RegisterDebug();
}

/// <summary>
/// Unregister this Render Graph from the debug window.
/// </summary>
public void UnRegisterDebug()
{
//m_DebugParameters.UnRegisterDebug();
m_DebugParameters.UnRegisterDebug();
}

/// <summary>
Expand Down Expand Up @@ -391,6 +397,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
{
Expand Down Expand Up @@ -424,6 +431,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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using UnityEngine.Rendering;

namespace UnityEngine.Experimental.Rendering.RenderGraphModule
{
/// <summary>
/// Helper class allowing access to default resources (black or white texture, etc.) during render passes.
/// </summary>
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;

/// <summary>Default black 2D texture.</summary>
public TextureHandle blackTexture { get; private set; }
/// <summary>Default white 2D texture.</summary>
public TextureHandle whiteTexture { get; private set; }
/// <summary>Default clear color XR 2D texture.</summary>
public TextureHandle clearTextureXR { get; private set; }
/// <summary>Default magenta XR 2D texture.</summary>
public TextureHandle magentaTextureXR { get; private set; }
/// <summary>Default black XR 2D texture.</summary>
public TextureHandle blackTextureXR { get; private set; }
/// <summary>Default black (UInt) XR 2D texture.</summary>
public TextureHandle blackUIntTextureXR { get; private set; }
/// <summary>Default black XR 3D texture.</summary>
public TextureHandle blackTexture3DXR { get; private set; }
/// <summary>Default white XR 2D texture.</summary>
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;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,15 @@ public void Dispose()
/// <param name="scaledRTMSAASamples">Number of MSAA samples for automatically scaled RTHandles.</param>
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,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");
Expand All @@ -64,16 +77,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,7 @@ bool PrepareLightsForGPU(CommandBuffer cmd, HDCamera hdCamera, CullingResults cu
}

PushLightDataGlobalParams(cmd);
PushShadowGlobalParams(cmd);
}

m_EnableBakeShadowMask = m_EnableBakeShadowMask && hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask);
Expand Down Expand Up @@ -3402,20 +3403,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;
Expand Down Expand Up @@ -3510,16 +3497,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)
Expand Down Expand Up @@ -3550,8 +3530,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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading