You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

329 lines
12 KiB

using System;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler;
namespace UnityEngine.Rendering.RenderGraphModule
{
public partial class RenderGraph
{
// Convenience class that wraps execution id and name for display purposes
internal class DebugExecutionItem
{
public EntityId id { get; }
public string name { get; }
public DebugExecutionItem(EntityId id, string name)
{
this.id = id;
this.name = name;
}
}
/// <summary>
/// Debug data interface shared by HDRP RG Compiler and NRP RG Compiler.
/// Some data is optional, depending on the value of isNRPCompiler.
/// </summary>
[Serializable]
internal class DebugData
{
public DebugData(string executionName)
{
this.executionName = executionName;
}
public string executionName;
// Set to true when data has been set
public bool valid = false;
// Compilation hash of the render graph that produced this DebugData.
public int graphHash;
// If true, the data was output by NRP compiler, in which case PassData.nrpInfo is available.
public bool isNRPCompiler;
[Serializable]
public class ResourceLists<T>
{
[SerializeField] private List<T> m_Textures = new();
[SerializeField] private List<T> m_Buffers = new();
[SerializeField] private List<T> m_AccelerationStructures = new();
// Indexer to access the lists by index
public List<T> this[int index]
{
get
{
return index switch
{
(int)RenderGraphResourceType.Texture => m_Textures,
(int)RenderGraphResourceType.Buffer => m_Buffers,
(int)RenderGraphResourceType.AccelerationStructure => m_AccelerationStructures,
_ => throw new ArgumentOutOfRangeException(nameof(index))
};
}
set
{
switch (index)
{
case (int)RenderGraphResourceType.Texture:
m_Textures = value ?? new List<T>();
break;
case (int)RenderGraphResourceType.Buffer:
m_Buffers = value ?? new List<T>();
break;
case (int)RenderGraphResourceType.AccelerationStructure:
m_AccelerationStructures = value ?? new List<T>();
break;
default:
throw new ArgumentOutOfRangeException(nameof(index));
}
}
}
public void Clear()
{
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
{
if (this[i] == null)
this[i] = new List<T>();
else
this[i].Clear();
}
}
}
// Debug data for passes.
public List<PassData> passList = new List<PassData>();
// Debug data for resources.
[Serializable]
public class ResourceDataLists : ResourceLists<ResourceData>
{ }
public ResourceDataLists resourceLists = new();
// NOTE: Cannot use NativePassAttachment for DebugData directly because readonly fields are not serialized.
// This class duplicates the relevant contents.
[Serializable]
public class SerializableNativePassAttachment
{
public RenderBufferLoadAction loadAction;
public RenderBufferStoreAction storeAction;
public bool memoryless;
public int mipLevel;
public int depthSlice;
public SerializableNativePassAttachment(NativePassAttachment att)
{
loadAction = att.loadAction;
storeAction = att.storeAction;
memoryless = att.memoryless;
mipLevel = att.mipLevel;
depthSlice = att.depthSlice;
}
}
[Serializable]
[DebuggerDisplay("PassDebug: {name}")]
public struct PassData
{
// Render pass name.
public string name;
// Render graph pass type.
public RenderGraphPassType type;
[Serializable]
public class ResourceIdLists : ResourceLists<int>
{}
// List of ResourceHandle.index's for each resource type read by this pass.
public ResourceIdLists resourceReadLists;
// List of ResourceHandle.index's for each resource type written by this pass.
public ResourceIdLists resourceWriteLists;
// Whether the pass was culled.
public bool culled;
// Whether the pass is an async compute pass.
public bool async;
// Native subpass index.
public int nativeSubPassIndex;
// Index of the pass that needs to be waited for.
public int syncToPassIndex;
// Smaller pass index that waits for this pass.
public int syncFromPassIndex;
// We have this member instead of removing the pass altogether because we need the full list of passes in
// order to be able to remap them correctly when we remove them from display in the viewer.
public bool generateDebugData;
[Serializable]
public class NRPInfo
{
[Serializable]
public class NativeRenderPassInfo
{
[Serializable]
public class AttachmentInfo
{
public string resourceName;
public string loadReason;
public string storeReason;
public string storeMsaaReason;
public int attachmentIndex;
public SerializableNativePassAttachment attachment;
}
[Serializable]
public struct PassCompatibilityInfo
{
public string message;
public bool isCompatible;
}
public string passBreakReasoning;
public List<AttachmentInfo> attachmentInfos;
public SerializedDictionary<int, PassCompatibilityInfo> passCompatibility;
public List<int> mergedPassIds;
}
// If this pass is part of a Native Render Pass, this is available, null otherwise.
[SerializeReference]
public NativeRenderPassInfo nativePassInfo;
// List of ResourceHandle.index's for each texture resource that is accessed using framebuffer fetch.
public List<int> textureFBFetchList = new();
// List of ResourceHandle.index's for each texture resource that this pass called PostSetGlobalTexture() for.
public List<int> setGlobals = new();
// Fragment info
public int width;
public int height;
public int volumeDepth;
public int samples;
public bool hasDepth;
}
// Only available when isNRPCompiler = true, null otherwise.
[SerializeReference]
public NRPInfo nrpInfo;
// File path and line number where the render pass is defined.
public PassScriptInfo scriptInfo;
}
[Serializable]
public class BufferResourceData
{
// Number of elements in buffer.
public int count;
// Size of one element in the buffer.
public int stride;
// Buffer usage type.
public GraphicsBuffer.Target target;
// Buffer usage flags.
public GraphicsBuffer.UsageFlags usage;
}
[Serializable]
public class TextureResourceData
{
// Texture width & height.
public int width;
public int height;
// Texture depth (volume texture).
public int depth;
// Whether the texture is bound with multi sampling.
public bool bindMS;
// Number of texture MSAA samples.
public int samples;
// Render texture graphics format.
public GraphicsFormat format;
// Whether texture is cleared on first use.
public bool clearBuffer;
}
[Serializable]
[DebuggerDisplay("ResourceDebug: {name} [{creationPassIndex}:{releasePassIndex}]")]
public struct ResourceData
{
// Resource name.
public string name;
// Whether the resource is imported outside of render graph.
public bool imported;
// Pass that creates the resource (for imported resources, the first pass that uses the resource).
public int creationPassIndex;
// Pass that releases the resource (for imported resources, the last pass that uses the resource).
public int releasePassIndex;
// List of passes that read the resource.
public List<int> consumerList;
// List of passes that write the resource.
public List<int> producerList;
// Whether the resource is memoryless (i.e resources that are created/destroyed within the same native render pass).
// Available if isNRPCompiler = true.
public bool memoryless;
// Texture-specific resource data.
[SerializeReference]
public TextureResourceData textureData;
// Buffer-specific resource data.
[SerializeReference]
public BufferResourceData bufferData;
}
public void Clear()
{
passList.Clear();
resourceLists.Clear();
valid = false;
}
// Pass script metadata.
[Serializable]
public struct PassScriptInfo
{
public string filePath;
public int line;
}
}
[Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD")]
void AddPassDebugMetadata(RenderGraphPass renderPass, string file, int line)
{
#if UNITY_EDITOR || DEVELOPMENT_BUILD
// Does nothing unless debug session is active.
if (!RenderGraphDebugSession.hasActiveDebugSession)
return;
renderPass.debugScriptInfo = new DebugData.PassScriptInfo { filePath = file, line = line };
#endif
}
}
}