diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 6cd96a853f2..0e28247f265 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -51,20 +51,36 @@ public struct RenderGraphExecuteParams class RenderGraphDebugParams { - public bool tagResourceNamesWithRG; public bool clearRenderTargetsAtCreation; public bool clearRenderTargetsAtRelease; + public bool disablePassCulling; public bool logFrameInformation; public bool logResources; public void RegisterDebug() { var list = new List(); - 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.Button { displayName = "Log Frame Information", action = () => logFrameInformation = true }); - list.Add(new DebugUI.Button { displayName = "Log Resources", action = () => logResources = true }); + list.Add(new DebugUI.BoolField { displayName = "Disable Pass Culling", getter = () => disablePassCulling, setter = value => disablePassCulling = value }); + list.Add(new DebugUI.Button { displayName = "Log Frame Information", + action = () => + { + logFrameInformation = true; + #if UNITY_EDITOR + UnityEditor.SceneView.RepaintAll(); + #endif + } + }); + list.Add(new DebugUI.Button { displayName = "Log Resources", + action = () => + { + logResources = true; + #if UNITY_EDITOR + UnityEditor.SceneView.RepaintAll(); + #endif + } + }); var panel = DebugManager.instance.GetPanel("Render Graph", true); panel.children.Add(list.ToArray()); @@ -120,7 +136,7 @@ internal struct CompiledPassInfo public List[] resourceCreateList; public List[] resourceReleaseList; public int refCount; - public bool pruned; + public bool culled; public bool hasSideEffect; public int syncToPassIndex; // Index of the pass that needs to be waited for. public int syncFromPassIndex; // Smaller pass index that waits for this pass. @@ -128,7 +144,7 @@ internal struct CompiledPassInfo public GraphicsFence fence; public bool enableAsyncCompute { get { return pass.enableAsyncCompute; } } - public bool allowPassPruning { get { return pass.allowPassPruning; } } + public bool allowPassCulling { get { return pass.allowPassCulling; } } #if DEVELOPMENT_BUILD || UNITY_EDITOR // This members are only here to ease debugging. @@ -168,7 +184,7 @@ public void Reset(RenderGraphPass pass) } refCount = 0; - pruned = false; + culled = false; hasSideEffect = false; syncToPassIndex = -1; syncFromPassIndex = -1; @@ -198,7 +214,7 @@ public void Reset(RenderGraphPass pass) // Compiled Render Graph info. DynamicArray[] m_CompiledResourcesInfos = new DynamicArray[(int)RenderGraphResourceType.Count]; DynamicArray m_CompiledPassInfos = new DynamicArray(); - Stack m_PruningStack = new Stack(); + Stack m_CullingStack = new Stack(); #region Public Interface @@ -262,7 +278,7 @@ public void PurgeUnusedResources() /// /// Import an external texture to the Render Graph. - /// Any pass writing to an imported texture will be considered having side effects and can't be automatically pruned. + /// Any pass writing to an imported texture will be considered having side effects and can't be automatically culled. /// /// External RTHandle that needs to be imported. /// A new TextureHandle. @@ -323,7 +339,7 @@ public RendererListHandle CreateRendererList(in RendererListDesc desc) /// /// Import an external Compute Buffer to the Render Graph - /// Any pass writing to an imported compute buffer will be considered having side effects and can't be automatically pruned. + /// Any pass writing to an imported compute buffer will be considered having side effects and can't be automatically culled. /// /// External Compute Buffer that needs to be imported. /// A new ComputeBufferHandle. @@ -511,21 +527,21 @@ void CountReferences() } } - void PruneOutputlessPasses() + void CullOutputlessPasses() { - // Gather passes that don't produce anything and prune them. - m_PruningStack.Clear(); + // Gather passes that don't produce anything and cull them. + m_CullingStack.Clear(); for (int pass = 0; pass < m_CompiledPassInfos.size; ++pass) { ref CompiledPassInfo passInfo = ref m_CompiledPassInfos[pass]; - if (passInfo.refCount == 0 && !passInfo.hasSideEffect && passInfo.allowPassPruning) + if (passInfo.refCount == 0 && !passInfo.hasSideEffect && passInfo.allowPassCulling) { // Producer is not necessary as it produces zero resources - // Prune it and decrement refCount of all the resources it reads. + // Cull it and decrement refCount of all the resources it reads. // We don't need to go recursively here because we decrement ref count of read resources - // so the subsequent passes of pruning will detect those and remove the related passes. - passInfo.pruned = true; + // so the subsequent passes of culling will detect those and remove the related passes. + passInfo.culled = true; for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type) { foreach (var index in passInfo.pass.resourceReadLists[type]) @@ -538,40 +554,49 @@ void PruneOutputlessPasses() } } - void PruneUnusedPasses() + void CullUnusedPasses() { - // TODO RENDERGRAPH: temporarily remove pruning of passes without product. - // Many passes are used just to set global variables so we don't want to force users to disallow pruning on those explicitly every time. - // This will prune passes with no outputs. - //PruneOutputlessPasses(); + if (m_DebugParameters.disablePassCulling) + { + if (m_DebugParameters.logFrameInformation) + { + m_Logger.LogLine("- Pass Culling Disabled -\n"); + } + return; + } - // This will prune all passes that produce resource that are never read. + // TODO RENDERGRAPH: temporarily remove culling of passes without product. + // Many passes are used just to set global variables so we don't want to force users to disallow culling on those explicitly every time. + // This will cull passes with no outputs. + //CullOutputlessPasses(); + + // This will cull all passes that produce resource that are never read. for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type) { DynamicArray resourceUsageList = m_CompiledResourcesInfos[type]; // Gather resources that are never read. - m_PruningStack.Clear(); + m_CullingStack.Clear(); for (int i = 0; i < resourceUsageList.size; ++i) { if (resourceUsageList[i].refCount == 0) { - m_PruningStack.Push(i); + m_CullingStack.Push(i); } } - while (m_PruningStack.Count != 0) + while (m_CullingStack.Count != 0) { - var unusedResource = resourceUsageList[m_PruningStack.Pop()]; + var unusedResource = resourceUsageList[m_CullingStack.Pop()]; foreach (var producerIndex in unusedResource.producers) { ref var producerInfo = ref m_CompiledPassInfos[producerIndex]; producerInfo.refCount--; - if (producerInfo.refCount == 0 && !producerInfo.hasSideEffect && producerInfo.allowPassPruning) + if (producerInfo.refCount == 0 && !producerInfo.hasSideEffect && producerInfo.allowPassCulling) { // Producer is not necessary anymore as it produces zero resources - // Prune it and decrement refCount of all the textures it reads. - producerInfo.pruned = true; + // Cull it and decrement refCount of all the textures it reads. + producerInfo.culled = true; foreach (var resourceIndex in producerInfo.pass.resourceReadLists[type]) { @@ -579,14 +604,14 @@ void PruneUnusedPasses() resourceInfo.refCount--; // If a resource is not used anymore, add it to the stack to be processed in subsequent iteration. if (resourceInfo.refCount == 0) - m_PruningStack.Push(resourceIndex); + m_CullingStack.Push(resourceIndex); } } } } } - LogPrunedPasses(); + LogCulledPasses(); } void UpdatePassSynchronization(ref CompiledPassInfo currentPassInfo, ref CompiledPassInfo producerPassInfo, int currentPassIndex, int lastProducer, ref int intLastSyncIndex) @@ -657,7 +682,7 @@ int GetLatestValidReadIndex(in CompiledResourceInfo info) var consumers = info.consumers; for (int i = consumers.Count - 1; i >= 0; --i) { - if (!m_CompiledPassInfos[consumers[i]].pruned) + if (!m_CompiledPassInfos[consumers[i]].culled) return consumers[i]; } @@ -672,7 +697,7 @@ int GetFirstValidWriteIndex(in CompiledResourceInfo info) var producers = info.producers; for (int i = 0; i < producers.Count; i++) { - if (!m_CompiledPassInfos[producers[i]].pruned) + if (!m_CompiledPassInfos[producers[i]].culled) return producers[i]; } @@ -687,7 +712,7 @@ int GetLatestValidWriteIndex(in CompiledResourceInfo info) var producers = info.producers; for (int i = producers.Count - 1; i >= 0; --i) { - if (!m_CompiledPassInfos[producers[i]].pruned) + if (!m_CompiledPassInfos[producers[i]].culled) return producers[i]; } @@ -708,7 +733,7 @@ void UpdateResourceAllocationAndSynchronization() { ref CompiledPassInfo passInfo = ref m_CompiledPassInfos[passIndex]; - if (passInfo.pruned) + if (passInfo.culled) continue; for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type) @@ -789,16 +814,16 @@ void UpdateResourceAllocationAndSynchronization() m_Resources.CreateRendererLists(m_RendererLists); } - // Internal for testing purpose only + // Internal visibility for testing purpose only // Traverse the render graph: // - Determines when resources are created/released // - Determines async compute pass synchronization - // - Prune unused render passes. + // - Cull unused render passes. internal void CompileRenderGraph() { InitializeCompilationData(); CountReferences(); - PruneUnusedPasses(); + CullUnusedPasses(); UpdateResourceAllocationAndSynchronization(); LogRendererListsCreation(); } @@ -814,7 +839,7 @@ void ExecuteRenderGraph(ScriptableRenderContext renderContext, CommandBuffer cmd for (int passIndex = 0; passIndex < m_CompiledPassInfos.size; ++passIndex) { ref var passInfo = ref m_CompiledPassInfos[passIndex]; - if (passInfo.pruned) + if (passInfo.culled) continue; if (!passInfo.pass.HasRenderFunc()) @@ -982,16 +1007,16 @@ void LogRenderPassBegin(in CompiledPassInfo passInfo) } } - void LogPrunedPasses() + void LogCulledPasses() { if (m_DebugParameters.logFrameInformation) { - m_Logger.LogLine("Pass pruning report:"); + m_Logger.LogLine("Pass Culling Report:"); using (new RenderGraphLogIndent(m_Logger)) { for (int i = 0; i < m_CompiledPassInfos.size; ++i) { - if (m_CompiledPassInfos[i].pruned) + if (m_CompiledPassInfos[i].culled) { var pass = m_RenderPasses[i]; m_Logger.LogLine("[{0}] {1}", pass.index, pass.name); diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs index 0633c1a92cd..ef8318ac8c1 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs @@ -175,15 +175,15 @@ public void EnableAsyncCompute(bool value) } /// - /// Allow or not pass pruning - /// By default all passes can be pruned out if the render graph detects it's not actually used. + /// Allow or not pass culling + /// By default all passes can be culled out if the render graph detects it's not actually used. /// In some cases, a pass may not write or read any texture but rather do something with side effects (like setting a global texture parameter for example). - /// This function can be used to tell the system that it should not prune this pass. + /// This function can be used to tell the system that it should not cull this pass. /// - /// - public void AllowPassPruning(bool value) + /// True to allow pass culling. + public void AllowPassCulling(bool value) { - m_RenderPass.AllowPassPruning(value); + m_RenderPass.AllowPassCulling(value); } /// diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs index 05f8ad1c2d8..367fdfcd0dc 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs @@ -23,6 +23,8 @@ public class RenderGraphDefaultResources public TextureHandle magentaTextureXR { get; private set; } /// Default black XR 2D texture. public TextureHandle blackTextureXR { get; private set; } + /// Default black XR 2D Array texture. + public TextureHandle blackTextureArrayXR { get; private set; } /// Default black (UInt) XR 2D texture. public TextureHandle blackUIntTextureXR { get; private set; } /// Default black XR 3D texture. @@ -52,6 +54,7 @@ internal void InitializeForRendering(RenderGraph renderGraph) clearTextureXR = renderGraph.ImportTexture(TextureXR.GetClearTexture()); magentaTextureXR = renderGraph.ImportTexture(TextureXR.GetMagentaTexture()); blackTextureXR = renderGraph.ImportTexture(TextureXR.GetBlackTexture()); + blackTextureArrayXR = renderGraph.ImportTexture(TextureXR.GetBlackTextureArray()); blackUIntTextureXR = renderGraph.ImportTexture(TextureXR.GetBlackUIntTexture()); blackTexture3DXR = renderGraph.ImportTexture(TextureXR.GetBlackTexture3D()); whiteTextureXR = renderGraph.ImportTexture(TextureXR.GetWhiteTexture()); diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs index 3bc1715b7ca..f9ce8cc88ae 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs @@ -19,7 +19,7 @@ public RenderFunc GetExecuteDelegate() public int index { get; protected set; } public ProfilingSampler customSampler { get; protected set; } public bool enableAsyncCompute { get; protected set; } - public bool allowPassPruning { get; protected set; } + public bool allowPassCulling { get; protected set; } public TextureHandle depthBuffer { get; protected set; } public TextureHandle[] colorBuffers { get; protected set; } = new TextureHandle[RenderGraph.kMaxMRTCount]; @@ -56,15 +56,15 @@ public void Clear() usedRendererListList.Clear(); enableAsyncCompute = false; - allowPassPruning = true; + allowPassCulling = true; refCount = 0; // Invalidate everything colorBufferMaxIndex = -1; - depthBuffer = new TextureHandle(); + depthBuffer = TextureHandle.nullHandle; for (int i = 0; i < RenderGraph.kMaxMRTCount; ++i) { - colorBuffers[i] = new TextureHandle(); + colorBuffers[i] = TextureHandle.nullHandle; } } @@ -93,9 +93,9 @@ public void EnableAsyncCompute(bool value) enableAsyncCompute = value; } - public void AllowPassPruning(bool value) + public void AllowPassCulling(bool value) { - allowPassPruning = value; + allowPassCulling = value; } public void SetColorBuffer(TextureHandle resource, int index) diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourcePool.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourcePool.cs index 29f1a46c9e7..5bfaa45c17e 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourcePool.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourcePool.cs @@ -6,7 +6,7 @@ namespace UnityEngine.Experimental.Rendering.RenderGraphModule abstract class RenderGraphResourcePool where Type : class { - // Dictionary tracks resources by hash and stores resources with same hash in a List (list instead of a stack because we need to be able to remove stale allocations). + // Dictionary tracks resources by hash and stores resources with same hash in a List (list instead of a stack because we need to be able to remove stale allocations, potentially in the middle of the stack). protected Dictionary> m_ResourcePool = new Dictionary>(); #if DEVELOPMENT_BUILD || UNITY_EDITOR diff --git a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs index 2de34972e8a..bf28006cb86 100644 --- a/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs +++ b/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs @@ -25,7 +25,7 @@ internal static RenderGraphResourceRegistry current } set { - m_CurrentRegistry = value; + m_CurrentRegistry = value; } } @@ -326,33 +326,27 @@ internal void CreateAndClearTexture(RenderGraphContext rgContext, int index) resource.resource = null; if (!m_TexturePool.TryGetResource(hashCode, out resource.resource)) { - string name = desc.name; - if (m_RenderGraphDebug.tagResourceNamesWithRG) - name = $"RenderGraph_{name}"; + // Textures are going to be reused under different aliases along the frame so we can't provide a specific name upon creation. + // The name in the desc is going to be used for debugging purpose and render graph visualization. + string name = "RenderGraphTexture"; - // Note: Name used here will be the one visible in the memory profiler so it means that whatever is the first pass that actually allocate the texture will set the name. - // TODO: Find a way to display name by pass. switch (desc.sizeMode) { case TextureSizeMode.Explicit: resource.resource = RTHandles.Alloc(desc.width, desc.height, desc.slices, desc.depthBufferBits, desc.colorFormat, desc.filterMode, desc.wrapMode, desc.dimension, desc.enableRandomWrite, - desc.useMipMap, desc.autoGenerateMips, desc.isShadowMap, desc.anisoLevel, desc.mipMapBias, desc.msaaSamples, desc.bindTextureMS, desc.useDynamicScale, desc.memoryless, desc.name); + desc.useMipMap, desc.autoGenerateMips, desc.isShadowMap, desc.anisoLevel, desc.mipMapBias, desc.msaaSamples, desc.bindTextureMS, desc.useDynamicScale, desc.memoryless, name); break; case TextureSizeMode.Scale: resource.resource = RTHandles.Alloc(desc.scale, desc.slices, desc.depthBufferBits, desc.colorFormat, desc.filterMode, desc.wrapMode, desc.dimension, desc.enableRandomWrite, - desc.useMipMap, desc.autoGenerateMips, desc.isShadowMap, desc.anisoLevel, desc.mipMapBias, desc.enableMSAA, desc.bindTextureMS, desc.useDynamicScale, desc.memoryless, desc.name); + desc.useMipMap, desc.autoGenerateMips, desc.isShadowMap, desc.anisoLevel, desc.mipMapBias, desc.enableMSAA, desc.bindTextureMS, desc.useDynamicScale, desc.memoryless, name); break; case TextureSizeMode.Functor: resource.resource = RTHandles.Alloc(desc.func, desc.slices, desc.depthBufferBits, desc.colorFormat, desc.filterMode, desc.wrapMode, desc.dimension, desc.enableRandomWrite, - desc.useMipMap, desc.autoGenerateMips, desc.isShadowMap, desc.anisoLevel, desc.mipMapBias, desc.enableMSAA, desc.bindTextureMS, desc.useDynamicScale, desc.memoryless, desc.name); + desc.useMipMap, desc.autoGenerateMips, desc.isShadowMap, desc.anisoLevel, desc.mipMapBias, desc.enableMSAA, desc.bindTextureMS, desc.useDynamicScale, desc.memoryless, name); break; } } - //// Try to update name when re-using a texture. - //// TODO RENDERGRAPH: Check if that actually works. - //resource.rt.name = desc.name; - resource.cachedHash = hashCode; #if UNITY_2020_2_OR_NEWER @@ -376,7 +370,7 @@ internal void CreateAndClearTexture(RenderGraphContext rgContext, int index) } m_TexturePool.RegisterFrameAllocation(hashCode, resource.resource); - LogTextureCreation(resource.resource, resource.desc.clearBuffer || m_RenderGraphDebug.clearRenderTargetsAtCreation); + LogTextureCreation(resource); } } @@ -395,12 +389,12 @@ internal void CreateComputeBuffer(RenderGraphContext rgContext, int index) if (!m_ComputeBufferPool.TryGetResource(hashCode, out resource.resource)) { resource.resource = new ComputeBuffer(resource.desc.count, resource.desc.stride, resource.desc.type); - resource.resource.name = m_RenderGraphDebug.tagResourceNamesWithRG ? $"RenderGraph_{resource.desc.name}" : resource.desc.name; + resource.resource.name = $"RenderGraphComputeBuffer_{resource.desc.count}_{resource.desc.stride}_{resource.desc.type}"; } resource.cachedHash = hashCode; m_ComputeBufferPool.RegisterFrameAllocation(hashCode, resource.resource); - LogComputeBufferCreation(resource.resource); + LogComputeBufferCreation(resource); } } @@ -424,7 +418,7 @@ internal void ReleaseTexture(RenderGraphContext rgContext, int index) } } - LogTextureRelease(resource.resource); + LogTextureRelease(resource); m_TexturePool.ReleaseResource(resource.cachedHash, resource.resource, m_CurrentFrameIndex); m_TexturePool.UnregisterFrameAllocation(resource.cachedHash, resource.resource); resource.cachedHash = -1; @@ -442,7 +436,7 @@ internal void ReleaseComputeBuffer(RenderGraphContext rgContext, int index) if (resource.resource == null) throw new InvalidOperationException($"Tried to release a compute buffer ({resource.desc.name}) that was never created. Check that there is at least one pass writing to it first."); - LogComputeBufferRelease(resource.resource); + LogComputeBufferRelease(resource); m_ComputeBufferPool.ReleaseResource(resource.cachedHash, resource.resource, m_CurrentFrameIndex); m_ComputeBufferPool.UnregisterFrameAllocation(resource.cachedHash, resource.resource); resource.cachedHash = -1; @@ -510,7 +504,6 @@ void ValidateRendererListDesc(in RendererListDesc desc) void ValidateComputeBufferDesc(in ComputeBufferDesc desc) { #if DEVELOPMENT_BUILD || UNITY_EDITOR - // TODO RENDERGRAPH: Check actual condition on stride. if (desc.stride % 4 != 0) { throw new ArgumentException("Invalid Compute Buffer creation descriptor: Compute Buffer stride must be at least 4."); @@ -562,35 +555,35 @@ internal void Cleanup() m_ComputeBufferPool.Cleanup(); } - void LogTextureCreation(RTHandle rt, bool cleared) + void LogTextureCreation(TextureResource rt) { if (m_RenderGraphDebug.logFrameInformation) { - m_Logger.LogLine($"Created Texture: {rt.rt.name} (Cleared: {cleared})"); + m_Logger.LogLine($"Created Texture: {rt.desc.name} (Cleared: {rt.desc.clearBuffer || m_RenderGraphDebug.clearRenderTargetsAtCreation})"); } } - void LogTextureRelease(RTHandle rt) + void LogTextureRelease(TextureResource rt) { if (m_RenderGraphDebug.logFrameInformation) { - m_Logger.LogLine($"Released Texture: {rt.rt.name}"); + m_Logger.LogLine($"Released Texture: {rt.desc.name}"); } } - void LogComputeBufferCreation(ComputeBuffer buffer) + void LogComputeBufferCreation(ComputeBufferResource buffer) { if (m_RenderGraphDebug.logFrameInformation) { - m_Logger.LogLine($"Created ComputeBuffer: {buffer}"); + m_Logger.LogLine($"Created ComputeBuffer: {buffer.desc.name}"); } } - void LogComputeBufferRelease(ComputeBuffer buffer) + void LogComputeBufferRelease(ComputeBufferResource buffer) { if (m_RenderGraphDebug.logFrameInformation) { - m_Logger.LogLine($"Released ComputeBuffer: {buffer}"); + m_Logger.LogLine($"Released ComputeBuffer: {buffer.desc.name}"); } } diff --git a/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs b/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs index ab01a3f3542..764d43156ca 100644 --- a/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs +++ b/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs @@ -20,9 +20,9 @@ class RenderGraphTestPassData public ComputeBufferHandle[] buffers = new ComputeBufferHandle[8]; } - // Final output (back buffer) of render graph needs to be explicitly imported in order to know that the chain of dependency should not be pruned. + // Final output (back buffer) of render graph needs to be explicitly imported in order to know that the chain of dependency should not be culled. [Test] - public void WriteToBackBufferNotPruned() + public void WriteToBackBufferNotCulled() { using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { @@ -34,12 +34,12 @@ public void WriteToBackBufferNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(1, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[0].pruned); + Assert.AreEqual(false, compiledPasses[0].culled); } - // If no back buffer is ever written to, everything should be pruned. + // If no back buffer is ever written to, everything should be culled. [Test] - public void NoWriteToBackBufferPruned() + public void NoWriteToBackBufferCulled() { using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { @@ -51,12 +51,12 @@ public void NoWriteToBackBufferPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(1, compiledPasses.size); - Assert.AreEqual(true, compiledPasses[0].pruned); + Assert.AreEqual(true, compiledPasses[0].culled); } - // Writing to imported resource is considered as a side effect so passes should not be pruned. + // Writing to imported resource is considered as a side effect so passes should not be culled. [Test] - public void WriteToImportedTextureNotPruned() + public void WriteToImportedTextureNotCulled() { using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { @@ -68,11 +68,11 @@ public void WriteToImportedTextureNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(1, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[0].pruned); + Assert.AreEqual(false, compiledPasses[0].culled); } [Test] - public void WriteToImportedComputeBufferNotPruned() + public void WriteToImportedComputeBufferNotCulled() { using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { @@ -84,15 +84,15 @@ public void WriteToImportedComputeBufferNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(1, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[0].pruned); + Assert.AreEqual(false, compiledPasses[0].culled); } - // TODO RENDERGRAPH : Temporarily removed. See RenderGraph.cs pass pruning - //// A pass not writing to anything is useless and should be pruned. + // TODO RENDERGRAPH : Temporarily removed. See RenderGraph.cs pass culling + //// A pass not writing to anything is useless and should be culled. //[Test] - //public void PrunePassWithNoProduct() + //public void CullPassWithNoProduct() //{ - // // This pass reads an input but does not produce anything (no writes) so it should be pruned. + // // This pass reads an input but does not produce anything (no writes) so it should be culled. // TextureHandle texture = m_RenderGraph.CreateTexture(new TextureDesc(Vector2.one) { colorFormat = GraphicsFormat.R8G8B8A8_UNorm }); // using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) // { @@ -104,15 +104,15 @@ public void WriteToImportedComputeBufferNotPruned() // var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); // Assert.AreEqual(1, compiledPasses.size); - // Assert.AreEqual(true, compiledPasses[0].pruned); + // Assert.AreEqual(true, compiledPasses[0].culled); //} - //// A series of passes with no final product should be pruned. + //// A series of passes with no final product should be culled. //[Test] - //public void PrunePassWithTextureDependenciesAndNoProduct() + //public void CullPassWithTextureDependenciesAndNoProduct() //{ // // First pass produces an output that is read by second pass. - // // Second pass does not produce anything so it should be pruned as well as all its unused dependencies. + // // Second pass does not produce anything so it should be culled as well as all its unused dependencies. // TextureHandle texture; // using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) // { @@ -130,18 +130,18 @@ public void WriteToImportedComputeBufferNotPruned() // var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); // Assert.AreEqual(2, compiledPasses.size); - // Assert.AreEqual(true, compiledPasses[0].pruned); - // Assert.AreEqual(true, compiledPasses[1].pruned); + // Assert.AreEqual(true, compiledPasses[0].culled); + // Assert.AreEqual(true, compiledPasses[1].culled); //} - //// A series of passes with no final product should be pruned. - //// Here first pass is not pruned because Compute Buffer is imported. + //// A series of passes with no final product should be culled. + //// Here first pass is not culled because Compute Buffer is imported. //// TODO: Add test where compute buffer is created instead of imported once the API exists. //[Test] - //public void PrunePassWithBufferDependenciesAndNoProduct() + //public void CullPassWithBufferDependenciesAndNoProduct() //{ // // First pass produces an output that is read by second pass. - // // Second pass does not produce anything so it should be pruned as well as all its unused dependencies. + // // Second pass does not produce anything so it should be culled as well as all its unused dependencies. // ComputeBufferHandle computeBuffer; // using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) // { @@ -159,14 +159,14 @@ public void WriteToImportedComputeBufferNotPruned() // var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); // Assert.AreEqual(2, compiledPasses.size); - // Assert.AreEqual(false, compiledPasses[0].pruned); // Not pruned because writing to an imported resource is a side effect. - // Assert.AreEqual(true, compiledPasses[1].pruned); + // Assert.AreEqual(false, compiledPasses[0].culled); // Not culled because writing to an imported resource is a side effect. + // Assert.AreEqual(true, compiledPasses[1].culled); //} [Test] - public void PassWriteResourcePartialNotReadAfterNotPruned() + public void PassWriteResourcePartialNotReadAfterNotCulled() { - // If a pass writes to a resource that is not unused globally by the graph but not read ever AFTER the pass then the pass should be pruned unless it writes to another used resource. + // If a pass writes to a resource that is not unused globally by the graph but not read ever AFTER the pass then the pass should be culled unless it writes to another used resource. TextureHandle texture0; using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { @@ -182,9 +182,9 @@ public void PassWriteResourcePartialNotReadAfterNotPruned() builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } - // This pass writes to texture0 which is used so will not be pruned out. - // Since texture0 is never read after this pass, we should decrement refCount for this pass and potentially prune it. - // However, it also writes to texture1 which is used in the last pass so we musn't prune it. + // This pass writes to texture0 which is used so will not be culled out. + // Since texture0 is never read after this pass, we should decrement refCount for this pass and potentially cull it. + // However, it also writes to texture1 which is used in the last pass so we mustn't cull it. using (var builder = m_RenderGraph.AddRenderPass("TestPass2", out var passData)) { builder.WriteTexture(texture0); @@ -195,7 +195,7 @@ public void PassWriteResourcePartialNotReadAfterNotPruned() using (var builder = m_RenderGraph.AddRenderPass("TestPass3", out var passData)) { builder.ReadTexture(texture1); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -203,19 +203,19 @@ public void PassWriteResourcePartialNotReadAfterNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(4, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[0].pruned); - Assert.AreEqual(false, compiledPasses[1].pruned); - Assert.AreEqual(false, compiledPasses[2].pruned); - Assert.AreEqual(false, compiledPasses[3].pruned); + Assert.AreEqual(false, compiledPasses[0].culled); + Assert.AreEqual(false, compiledPasses[1].culled); + Assert.AreEqual(false, compiledPasses[2].culled); + Assert.AreEqual(false, compiledPasses[3].culled); } [Test] - public void PassDisallowPruningNotPruned() + public void PassDisallowCullingNotCulled() { - // This pass does nothing so should be pruned but we explicitly disallow it. + // This pass does nothing so should be culled but we explicitly disallow it. using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { - builder.AllowPassPruning(false); + builder.AllowPassCulling(false); builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -223,12 +223,12 @@ public void PassDisallowPruningNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(1, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[0].pruned); + Assert.AreEqual(false, compiledPasses[0].culled); } - // First pass produces two textures and second pass only read one of the two. Pass one should not be pruned. + // First pass produces two textures and second pass only read one of the two. Pass one should not be culled. [Test] - public void PartialUnusedProductNotPruned() + public void PartialUnusedProductNotCulled() { TextureHandle texture; using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) @@ -249,8 +249,8 @@ public void PartialUnusedProductNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(2, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[0].pruned); - Assert.AreEqual(false, compiledPasses[1].pruned); + Assert.AreEqual(false, compiledPasses[0].culled); + Assert.AreEqual(false, compiledPasses[1].culled); } // Simple cycle of create/release of a texture across multiple passes. @@ -276,7 +276,7 @@ public void SimpleCreateReleaseTexture() using (var builder = m_RenderGraph.AddRenderPass("TestPass2", out var passData)) { builder.ReadTexture(texture); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -303,7 +303,7 @@ public void UseTransientOutsidePassRaiseException() using (var builder = m_RenderGraph.AddRenderPass("TestPass1", out var passData)) { builder.ReadTexture(texture); // This is illegal (transient resource was created in previous pass) - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -318,7 +318,7 @@ public void TransientCreateReleaseInSamePass() using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) { texture = builder.CreateTransientTexture(new TextureDesc(Vector2.one) { colorFormat = GraphicsFormat.R8G8B8A8_UNorm }); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -387,7 +387,7 @@ public void AsyncPassReleaseTextureOnGraphicsPipe() { builder.ReadTexture(texture1); builder.ReadTexture(texture3); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.EnableAsyncCompute(false); builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -401,7 +401,7 @@ public void AsyncPassReleaseTextureOnGraphicsPipe() } [Test] - public void TransientResourceNotPruned() + public void TransientResourceNotCulled() { TextureHandle texture0; using (var builder = m_RenderGraph.AddRenderPass("TestPass0", out var passData)) @@ -421,7 +421,7 @@ public void TransientResourceNotPruned() using (var builder = m_RenderGraph.AddRenderPass("TestPass5", out var passData)) { builder.ReadTexture(texture0); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.EnableAsyncCompute(false); builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -430,7 +430,7 @@ public void TransientResourceNotPruned() var compiledPasses = m_RenderGraph.GetCompiledPassInfos(); Assert.AreEqual(3, compiledPasses.size); - Assert.AreEqual(false, compiledPasses[1].pruned); + Assert.AreEqual(false, compiledPasses[1].culled); } [Test] @@ -453,7 +453,7 @@ public void AsyncPassWriteWaitOnGraphcisPipe() using (var builder = m_RenderGraph.AddRenderPass("TestPass2", out var passData)) { builder.ReadTexture(texture0); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -487,7 +487,7 @@ public void AsyncPassReadWaitOnGraphcisPipe() using (var builder = m_RenderGraph.AddRenderPass("TestPass2", out var passData)) { builder.ReadTexture(texture1); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -513,7 +513,7 @@ public void GraphicsPassWriteWaitOnAsyncPipe() using (var builder = m_RenderGraph.AddRenderPass("TestPass1", out var passData)) { builder.WriteTexture(texture0); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } @@ -539,7 +539,7 @@ public void GraphicsPassReadWaitOnAsyncPipe() using (var builder = m_RenderGraph.AddRenderPass("TestPass1", out var passData)) { builder.ReadTexture(texture0); - builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be pruned + builder.WriteTexture(m_RenderGraph.ImportBackbuffer(0)); // Needed for the passes to not be culled builder.SetRenderFunc((RenderGraphTestPassData data, RenderGraphContext context) => { }); } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Reflection/HDProbe.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Reflection/HDProbe.cs index 18024aed0ee..56a4ddbcbe0 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Reflection/HDProbe.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Reflection/HDProbe.cs @@ -192,6 +192,7 @@ public RenderTexture realtimeTexture if (m_RealtimeTexture != null) m_RealtimeTexture.Release(); m_RealtimeTexture = RTHandles.Alloc(value); + m_RealtimeTexture.rt.name = $"ProbeRealTimeTexture_{name}"; } } @@ -209,6 +210,7 @@ public RenderTexture realtimeDepthTexture if (m_RealtimeDepthBuffer != null) m_RealtimeDepthBuffer.Release(); m_RealtimeDepthBuffer = RTHandles.Alloc(value); + m_RealtimeDepthBuffer.rt.name = $"ProbeRealTimeDepthTexture_{name}"; } } 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 c22bc4b2499..79625322a12 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 @@ -48,6 +48,7 @@ internal ShadowResult RenderShadows(RenderGraph renderGraph, in ShaderVariablesG // 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) + // We can probably remove this when we have only one code path and can clean things up a bit. BindShadowGlobalResources(renderGraph, result); return result; @@ -72,7 +73,7 @@ void BindShadowGlobalResources(RenderGraph renderGraph, in ShadowResult shadowRe using (var builder = renderGraph.AddRenderPass("BindShadowGlobalResources", out var passData)) { passData.shadowResult = ReadShadowResult(shadowResult, builder); - builder.AllowPassPruning(false); + builder.AllowPassCulling(false); builder.SetRenderFunc( (BindShadowGlobalResourcesPassData data, RenderGraphContext ctx) => { @@ -108,7 +109,7 @@ TextureHandle AllocateMomentAtlas(RenderGraph renderGraph, string name) internal TextureHandle RenderShadows(RenderGraph renderGraph, CullingResults cullResults, in ShaderVariablesGlobal globalCB, FrameSettings frameSettings, string shadowPassName) { - TextureHandle result = new TextureHandle(); + TextureHandle result = TextureHandle.nullHandle; if (m_ShadowRequests.Count == 0) return result; 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 797ae62e431..c18b37971d5 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 @@ -323,16 +323,24 @@ public void InitializeNonRenderGraphResources() { m_Atlas.AllocateRenderTexture(); m_CascadeAtlas.AllocateRenderTexture(); + cachedShadowManager.punctualShadowAtlas.AllocateRenderTexture(); if (ShaderConfig.s_AreaLights == 1) + { m_AreaLightShadowAtlas.AllocateRenderTexture(); + cachedShadowManager.areaShadowAtlas.AllocateRenderTexture(); + } } public void CleanupNonRenderGraphResources() { m_Atlas.Release(); m_CascadeAtlas.Release(); + cachedShadowManager.punctualShadowAtlas.Release(); if (ShaderConfig.s_AreaLights == 1) + { m_AreaLightShadowAtlas.Release(); + cachedShadowManager.areaShadowAtlas.Release(); + } } // Keep in sync with both HDShadowSampling.hlsl 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 b09053fd75c..03b5316494c 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 @@ -1,5 +1,6 @@ using System; using UnityEngine.Experimental.Rendering; +using UnityEngine.Experimental.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.HighDefinition { @@ -264,6 +265,11 @@ void RenderScreenSpaceShadows(HDCamera hdCamera, CommandBuffer cmd) } } + TextureHandle RenderScreenSpaceShadows(RenderGraph renderGraph, HDCamera hdCamera) + { + return renderGraph.defaultResources.blackTextureArrayXR; + } + // Generic function that writes in the screen space shadow buffer void WriteToScreenSpaceShadowBuffer(CommandBuffer cmd, HDCamera hdCamera, RTHandle source, int shadowSlot, ScreenSpaceShadowType shadowType) { 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 799116bf22b..0a8477a7e79 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 @@ -145,12 +145,12 @@ void FillBloomMipsTextureHandles(BloomData bloomData, RenderGraph renderGraph, R var pixelSize = new Vector2Int((int)m_BloomMipsInfo[i].x, (int)m_BloomMipsInfo[i].y); bloomData.mipsDown[i] = builder.CreateTransientTexture(new TextureDesc(scale, true, true) - { colorFormat = m_ColorFormat, enableRandomWrite = true }); + { colorFormat = m_ColorFormat, enableRandomWrite = true, name = "BloomMipDown" }); if (i != 0) { bloomData.mipsUp[i] = builder.CreateTransientTexture(new TextureDesc(scale, true, true) - { colorFormat = m_ColorFormat, enableRandomWrite = true }); + { colorFormat = m_ColorFormat, enableRandomWrite = true, name = "BloomMipUp" }); } } 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 efbcddc6137..3f4caee8c25 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 @@ -22,7 +22,7 @@ void RenderTransparencyOverdraw(RenderGraph renderGraph, TextureHandle depthBuff { if (m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled() && m_CurrentDebugDisplaySettings.data.fullScreenDebugMode == FullScreenDebugMode.TransparencyOverdraw) { - TextureHandle transparencyOverdrawOutput = new TextureHandle(); + TextureHandle transparencyOverdrawOutput = TextureHandle.nullHandle; using (var builder = renderGraph.AddRenderPass("Transparency Overdraw", out var passData)) { passData.parameters = PrepareTransparencyOverdrawParameters(hdCamera, cull); 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 a0ea0620acb..1987286b21e 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 @@ -18,6 +18,7 @@ struct LightingBuffers public TextureHandle ambientOcclusionBuffer; public TextureHandle ssrLightingBuffer; public TextureHandle contactShadowsBuffer; + public TextureHandle screenspaceShadowBuffer; } static LightingBuffers ReadLightingBuffers(in LightingBuffers buffers, RenderGraphBuilder builder) @@ -27,6 +28,7 @@ static LightingBuffers ReadLightingBuffers(in LightingBuffers buffers, RenderGra result.ambientOcclusionBuffer = builder.ReadTexture(buffers.ambientOcclusionBuffer); result.ssrLightingBuffer = builder.ReadTexture(buffers.ssrLightingBuffer); result.contactShadowsBuffer = builder.ReadTexture(buffers.contactShadowsBuffer); + result.screenspaceShadowBuffer = builder.ReadTexture(buffers.screenspaceShadowBuffer); return result; } @@ -36,6 +38,7 @@ static void BindGlobalLightingBuffers(in LightingBuffers buffers, CommandBuffer cmd.SetGlobalTexture(HDShaderIDs._AmbientOcclusionTexture, buffers.ambientOcclusionBuffer); cmd.SetGlobalTexture(HDShaderIDs._SsrLightingTexture, buffers.ssrLightingBuffer); cmd.SetGlobalTexture(HDShaderIDs._ContactShadowTexture, buffers.contactShadowsBuffer); + cmd.SetGlobalTexture(HDShaderIDs._ScreenSpaceShadowsTexture, buffers.screenspaceShadowBuffer); } class BuildGPULightListPassData @@ -570,7 +573,7 @@ TextureHandle VolumeVoxelizationPass( RenderGraph renderGraph, return passData.densityBuffer; } } - return new TextureHandle(); + return TextureHandle.nullHandle; } class VolumetricLightingPassData 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 402c2be2dbf..adde65907f0 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 @@ -114,8 +114,6 @@ TextureHandle CreateMotionVectorBuffer(RenderGraph renderGraph, bool msaa, bool return renderGraph.CreateTexture(motionVectorDesc); } - // TODO RENDERGRAPH: in someplaces we auto bind and in others we have to generate MRT because of discrepancy with non render graph path. - // Clean this once we only have one path. void BindPrepassColorBuffers(in RenderGraphBuilder builder, in PrepassOutput prepassOutput, HDCamera hdCamera) { int index = 0; @@ -677,7 +675,7 @@ class RenderDBufferPassData public TextureHandle depthStencilBuffer; public TextureHandle depthTexture; public ComputeBufferHandle propertyMaskBuffer; - public TextureHandle decalBuffer; + public TextureHandle decalBuffer; } struct DBufferOutput @@ -786,7 +784,7 @@ void RenderDBuffer(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle dec data.meshDecalsRendererList, data.propertyMaskBuffer, data.decalBuffer, - context.renderContext, + context.renderContext, 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 3fca931cd83..81f54e91a81 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 @@ -140,7 +140,7 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, // Temporary workaround otherwise the texture is not bound when executing directly with rendergraph using (var builder = m_RenderGraph.AddRenderPass("TempPass", out var passData)) { - builder.AllowPassPruning(false); + builder.AllowPassCulling(false); builder.SetRenderFunc( (TempPassData data, RenderGraphContext context) => { @@ -150,7 +150,7 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, // TODO RENDERGRAPH - //RenderScreenSpaceShadows(hdCamera, cmd); + lightingBuffers.screenspaceShadowBuffer = RenderScreenSpaceShadows(m_RenderGraph, hdCamera); var volumetricLighting = VolumetricLightingPass(m_RenderGraph, hdCamera, prepassOutput.depthPyramidTexture, volumetricDensityBuffer, gpuLightListOutput.bigTileLightList, shadowResult, m_FrameCount); @@ -158,7 +158,7 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, RenderForwardOpaque(m_RenderGraph, hdCamera, colorBuffer, lightingBuffers, gpuLightListOutput, prepassOutput.depthBuffer, shadowResult, prepassOutput.dbuffer, cullingResults); - // TODO RENDERGRAPH : Move this to the end after we do move semantic and graph pruning to avoid doing the rest of the frame for nothing + // TODO RENDERGRAPH : Move this to the end after we do move semantic and graph culling to avoid doing the rest of the frame for nothing aovRequest.PushCameraTexture(m_RenderGraph, AOVBuffers.Normals, hdCamera, prepassOutput.resolvedNormalBuffer, aovBuffers); lightingBuffers.diffuseLightingBuffer = ResolveMSAAColor(m_RenderGraph, hdCamera, lightingBuffers.diffuseLightingBuffer); @@ -190,7 +190,7 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, if (m_Asset.currentPlatformRenderPipelineSettings.supportMotionVectors) PushFullScreenDebugTexture(m_RenderGraph, prepassOutput.motionVectorsBuffer, FullScreenDebugMode.MotionVectors); - // TODO RENDERGRAPH : Move this to the end after we do move semantic and graph pruning to avoid doing the rest of the frame for nothing + // TODO RENDERGRAPH : Move this to the end after we do move semantic and graph culling to avoid doing the rest of the frame for nothing // Transparent objects may write to the depth and motion vectors buffers. aovRequest.PushCameraTexture(m_RenderGraph, AOVBuffers.DepthStencil, hdCamera, prepassOutput.resolvedDepthBuffer, aovBuffers); if (m_Asset.currentPlatformRenderPipelineSettings.supportMotionVectors) @@ -234,24 +234,7 @@ void ExecuteWithRenderGraph( RenderRequest renderRequest, RenderCustomPass(m_RenderGraph, hdCamera, postProcessDest, prepassOutput.depthBuffer, prepassOutput.normalBuffer, customPassCullingResults, CustomPassInjectionPoint.AfterPostProcess, aovRequest, aovBuffers); - // TODO RENDERGRAPH - //// Copy and rescale depth buffer for XR devices - //if (hdCamera.xr.enabled && hdCamera.xr.copyDepth) - //{ - // using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.XRDepthCopy))) - // { - // var depthBuffer = m_SharedRTManager.GetDepthStencilBuffer(); - // var rtScale = depthBuffer.rtHandleProperties.rtHandleScale / DynamicResolutionHandler.instance.GetCurrentScale(); - - // m_CopyDepthPropertyBlock.SetTexture(HDShaderIDs._InputDepth, depthBuffer); - // m_CopyDepthPropertyBlock.SetVector(HDShaderIDs._BlitScaleBias, rtScale); - // m_CopyDepthPropertyBlock.SetInt("_FlipY", 1); - - // cmd.SetRenderTarget(target.id, 0, CubemapFace.Unknown, -1); - // cmd.SetViewport(hdCamera.finalViewport); - // CoreUtils.DrawFullScreen(cmd, m_CopyDepth, m_CopyDepthPropertyBlock); - // } - //} + CopyXRDepth(m_RenderGraph, hdCamera, prepassOutput.depthBuffer, backBuffer); // In developer build, we always render post process in m_AfterPostProcessBuffer at (0,0) in which we will then render debug. // Because of this, we need another blit here to the final render target at the right viewport. @@ -391,6 +374,44 @@ void SetFinalTarget(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle de } } + class CopyXRDepthPassData + { + public Material copyDepth; + public Rect viewport; + public TextureHandle depthBuffer; + public TextureHandle output; + } + + void CopyXRDepth(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle output) + { + // Copy and rescale depth buffer for XR devices + if (hdCamera.xr.enabled && hdCamera.xr.copyDepth) + { + using (var builder = renderGraph.AddRenderPass("Copy XR Depth", out var passData, ProfilingSampler.Get(HDProfileId.XRDepthCopy))) + { + passData.copyDepth = m_CopyDepth; + passData.viewport = hdCamera.finalViewport; + passData.depthBuffer = builder.ReadTexture(depthBuffer); + passData.output = builder.WriteTexture(output); + + builder.SetRenderFunc( + (CopyXRDepthPassData data, RenderGraphContext ctx) => + { + var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); + RTHandle depthRT = data.depthBuffer; + + mpb.SetTexture(HDShaderIDs._InputDepth, data.depthBuffer); + mpb.SetVector(HDShaderIDs._BlitScaleBias, depthRT.rtHandleProperties.rtHandleScale / DynamicResolutionHandler.instance.GetCurrentScale()); + mpb.SetInt("_FlipY", 1); + + ctx.cmd.SetRenderTarget(data.output, 0, CubemapFace.Unknown, -1); + ctx.cmd.SetViewport(data.viewport); + CoreUtils.DrawFullScreen(ctx.cmd, data.copyDepth, mpb); + }); + } + } + } + class ForwardPassData { public RendererListHandle rendererList; @@ -708,7 +729,7 @@ TextureHandle RenderLowResTransparent(RenderGraph renderGraph, HDCamera hdCamera class UpsampleTransparentPassData { - public Material upsampleMaterial; + public Material upsampleMaterial; public TextureHandle colorBuffer; public TextureHandle lowResTransparentBuffer; public TextureHandle downsampledDepthBuffer; @@ -743,6 +764,25 @@ void UpsampleTransparent(RenderGraph renderGraph, HDCamera hdCamera, TextureHand } } + class SetGlobalColorPassData + { + public TextureHandle colorBuffer; + } + + void SetGlobalColorForCustomPass(RenderGraph renderGraph, TextureHandle colorBuffer) + { + using (var builder = renderGraph.AddRenderPass("SetGlobalColorForCustomPass", out var passData)) + { + passData.colorBuffer = builder.ReadTexture(colorBuffer); + builder.SetRenderFunc( (SetGlobalColorPassData data, RenderGraphContext context) => + { + RTHandle colorPyramid = data.colorBuffer; + if (colorPyramid != null) + context.cmd.SetGlobalTexture(HDShaderIDs._ColorPyramidTexture, data.colorBuffer); + }); + } + } + TextureHandle RenderTransparency( RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer, @@ -763,9 +803,9 @@ TextureHandle RenderTransparency( RenderGraph renderGraph, //RenderRayTracingPrepass(cullingResults, hdCamera, renderContext, cmd, true); //RaytracingRecursiveRender(hdCamera, cmd, renderContext, cullingResults); - // TODO RENDERGRAPH - //// To allow users to fetch the current color buffer, we temporarily bind the camera color buffer - //cmd.SetGlobalTexture(HDShaderIDs._ColorPyramidTexture, m_CameraColorBuffer); + // TODO RENDERGRAPH: Remove this when we properly convert custom passes to full render graph with explicit color buffer reads. + // To allow users to fetch the current color buffer, we temporarily bind the camera color buffer + SetGlobalColorForCustomPass(renderGraph, currentColorPyramid); RenderCustomPass(m_RenderGraph, hdCamera, colorBuffer, prepassOutput.depthBuffer, prepassOutput.normalBuffer, customPassCullingResults, CustomPassInjectionPoint.BeforePreRefraction, aovRequest, aovBuffers); @@ -872,7 +912,7 @@ void SendGeometryGraphicsBuffers(RenderGraph renderGraph, TextureHandle normalBu using (var builder = renderGraph.AddRenderPass("Send Geometry Buffers", out var passData)) { - builder.AllowPassPruning(false); + builder.AllowPassCulling(false); passData.parameters = parameters; passData.normalBuffer = builder.ReadTexture(normalBuffer); @@ -895,7 +935,7 @@ void SendColorGraphicsBuffer(RenderGraph renderGraph, HDCamera hdCamera) { using (var builder = renderGraph.AddRenderPass("Send Color Buffers", out var passData)) { - builder.AllowPassPruning(false); + builder.AllowPassCulling(false); passData.hdCamera = hdCamera; @@ -1032,9 +1072,9 @@ class GenerateColorPyramidData void GenerateColorPyramid(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle inputColor, TextureHandle output, bool isPreRefraction) { - // Here we cannot rely on automatic pass pruning if the result is not read + // Here we cannot rely on automatic pass culling if the result is not read // because the output texture is imported from outside of render graph (as it is persistent) - // and in this case the pass is considered as having side effect and cannot be pruned. + // and in this case the pass is considered as having side effect and cannot be culled. if (isPreRefraction) { if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.Refraction))