using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using UnityEngine.Experimental.Rendering; using UnityEngine.Scripting.APIUpdating; // Typedef for the in-engine RendererList API (to avoid conflicts with the experimental version) using CoreRendererListDesc = UnityEngine.Rendering.RendererUtils.RendererListDesc; namespace UnityEngine.Rendering.RenderGraphModule { /// /// This class specifies the context given to every render pass. This context type passes a generic /// command buffer that can be used to schedule all commands. This will eventually be deprecated /// in favor of more specific contexts that have more specific command buffer types. /// [MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")] [Obsolete("RenderGraphContext is deprecated, use RasterGraphContext/ComputeGraphContext/UnsafeGraphContext instead.", true)] public struct RenderGraphContext : IDerivedRendergraphContext { private InternalRenderGraphContext wrappedContext; /// public void FromInternalContext(InternalRenderGraphContext context) { wrappedContext = context; } /// public readonly TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle) { return TextureUVOrigin.BottomLeft; } ///Scriptable Render Context used for rendering. public ScriptableRenderContext renderContext { get => wrappedContext.renderContext; } ///Command Buffer used for rendering. public CommandBuffer cmd { get => wrappedContext.cmd; } ///Render Graph pool used for temporary data. public RenderGraphObjectPool renderGraphPool { get => wrappedContext.renderGraphPool; } ///Render Graph default resources. public RenderGraphDefaultResources defaultResources { get => wrappedContext.defaultResources; } } public partial class RenderGraph { /// /// Import the final backbuffer to render graph. /// This function can only be used when nativeRenderPassesEnabled is false. /// /// /// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc(). /// /// Backbuffer render target identifier. /// A new TextureHandle that represents the imported texture in the context of this rendergraph. [Obsolete("This overload is deprecated, use ImportBackbuffer(RenderTargetIdentifier, RenderTargetInfo, ImportResourceParams) instead.", true)] public TextureHandle ImportBackbuffer(RenderTargetIdentifier rt) { return new TextureHandle(); } /// /// Create a new Render Graph Shared Texture resource. /// This texture will be persistent across render graph executions. /// /// /// This API should not be used with URP NRP Render Graph. This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph(). /// /// Creation descriptor of the texture. /// Set to true if you want to manage the lifetime of the resource yourself. Otherwise the resource will be released automatically if unused for a time. /// A new TextureHandle. [Obsolete("CreateSharedTexture() and shared texture workflow are deprecated, use ImportTexture() workflow instead.", true)] public TextureHandle CreateSharedTexture(in TextureDesc desc, bool explicitRelease = false) { return new TextureHandle(); } /// /// Refresh a shared texture with a new descriptor. /// /// /// This API should not be used with URP NRP Render Graph. /// /// Shared texture that needs to be updated. /// New Descriptor for the texture. [Obsolete("RefreshSharedTextureDesc() and shared texture workflow are deprecated, use ImportTexture() workflow instead.", true)] public void RefreshSharedTextureDesc(TextureHandle handle, in TextureDesc desc) {} /// /// Release a Render Graph shared texture resource. /// /// /// This API should not be used with URP NRP Render Graph. This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph(). /// /// The handle to the texture that needs to be release. [Obsolete("ReleaseSharedTexture() and shared texture workflow are deprecated, use ImportTexture() workflow instead.", true)] public void ReleaseSharedTexture(TextureHandle texture) {} /// /// Import an external Graphics Buffer to the Render Graph. /// Any pass writing to an imported graphics buffer will be considered having side effects and can't be automatically culled. /// /// /// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc(). /// /// External Graphics Buffer that needs to be imported. /// The imported graphics buffer will be released after usage. /// A new GraphicsBufferHandle. [Obsolete("ImportBuffer with forceRelease parameter is deprecated. Use ImportBuffer without it instead. #from(6000.3)", true)] public BufferHandle ImportBuffer(GraphicsBuffer graphicsBuffer, bool forceRelease = false) { return new BufferHandle(); } /// /// Add a new Render Pass to the Render Graph. /// /// Type of the class to use to provide data to the Render Pass. /// Name of the new Render Pass (this is also be used to generate a GPU profiling marker). /// Instance of PassData that is passed to the render function and you must fill. /// Profiling sampler used around the pass. /// File name of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it. /// File line of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it. /// A new instance of a RenderGraphBuilder used to setup the new Render Pass. [Obsolete("AddRenderPass() is deprecated, use AddRasterRenderPass/AddComputePass/AddUnsafePass() instead.", true)] public RenderGraphBuilder AddRenderPass(string passName, out PassData passData, ProfilingSampler sampler #if !CORE_PACKAGE_DOCTOOLS ,[CallerFilePath] string file = "", [CallerLineNumber] int line = 0 #endif ) where PassData : class, new() { passData = null; return new RenderGraphBuilder(null, m_Resources, this); } /// /// Add a new Render Pass to the Render Graph. /// /// /// This API should not be used with URP NRP Render Graph. In addition, it cannot be called when Render Graph records a pass, please call it within SetRenderFunc() or outside of AddUnsafePass()/AddComputePass()/AddRasterRenderPass(). /// /// Type of the class to use to provide data to the Render Pass. /// Name of the new Render Pass (this is also be used to generate a GPU profiling marker). /// Instance of PassData that is passed to the render function and you must fill. /// File name of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it. /// File line of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it. /// A new instance of a RenderGraphBuilder used to setup the new Render Pass. [Obsolete("AddRenderPass() is deprecated, use AddRasterRenderPass/AddComputePass/AddUnsafePass() instead.", true)] public RenderGraphBuilder AddRenderPass(string passName, out PassData passData #if !CORE_PACKAGE_DOCTOOLS ,[CallerFilePath] string file = "", [CallerLineNumber] int line = 0 #endif ) where PassData : class, new() { return AddRenderPass(passName, out passData, GetDefaultProfilingSampler(passName), file, line); } } /// /// Use this struct to set up a new Render Pass. /// [MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")] [Obsolete("RenderGraphBuilder is deprecated, use IComputeRenderGraphBuilder/IRasterRenderGraphBuilder/IUnsafeRenderGraphBuilder instead.", true)] public struct RenderGraphBuilder : IDisposable { RenderGraphPass m_RenderPass; RenderGraphResourceRegistry m_Resources; RenderGraph m_RenderGraph; bool m_Disposed; #region Public Interface /// /// Specify that the pass will use a Texture resource as a color render target. /// This has the same effect as WriteTexture and also automatically sets the Texture to use as a render target. /// /// The Texture resource to use as a color render target. /// Index for multiple render target usage. /// An updated resource handle to the input resource. public TextureHandle UseColorBuffer(in TextureHandle input, int index) { CheckResource(input.handle, false); m_Resources.IncrementWriteCount(input.handle); m_RenderPass.SetColorBuffer(input, index); return input; } /// /// Specify that the pass will use a Texture resource as a depth buffer. /// /// The Texture resource to use as a depth buffer during the pass. /// Specify the access level for the depth buffer. This allows you to say whether you will read from or write to the depth buffer, or do both. /// An updated resource handle to the input resource. public TextureHandle UseDepthBuffer(in TextureHandle input, DepthAccess flags) { CheckResource(input.handle, false); if ((flags & DepthAccess.Write) != 0) m_Resources.IncrementWriteCount(input.handle); if ((flags & DepthAccess.Read) != 0) { if (!m_Resources.IsRenderGraphResourceImported(input.handle) && m_Resources.TextureNeedsFallback(input)) WriteTexture(input); } m_RenderPass.SetDepthBuffer(input, flags); return input; } /// /// Specify a Texture resource to read from during the pass. /// /// The Texture resource to read from during the pass. /// An updated resource handle to the input resource. public TextureHandle ReadTexture(in TextureHandle input) { CheckResource(input.handle); if (!m_Resources.IsRenderGraphResourceImported(input.handle) && m_Resources.TextureNeedsFallback(input)) { var textureResource = m_Resources.GetTextureResource(input.handle); // Ensure we get a fallback to black textureResource.desc.clearBuffer = true; textureResource.desc.clearColor = Color.black; // If texture is read from but never written to, return a fallback black texture to have valid reads // Return one from the preallocated default textures if possible if (m_RenderGraph.GetImportedFallback(textureResource.desc, out var fallback)) return fallback; // If not, simulate a write to the texture so that it gets allocated WriteTexture(input); } m_RenderPass.AddResourceRead(input.handle); return input; } /// /// Specify a Texture resource to write to during the pass. /// /// The Texture resource to write to during the pass. /// An updated resource handle to the input resource. public TextureHandle WriteTexture(in TextureHandle input) { CheckResource(input.handle); m_Resources.IncrementWriteCount(input.handle); m_RenderPass.AddResourceWrite(input.handle); return input; } /// /// Specify a Texture resource to read and write to during the pass. /// /// The Texture resource to read and write to during the pass. /// An updated resource handle to the input resource. public TextureHandle ReadWriteTexture(in TextureHandle input) { CheckResource(input.handle); m_Resources.IncrementWriteCount(input.handle); m_RenderPass.AddResourceWrite(input.handle); m_RenderPass.AddResourceRead(input.handle); 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, m_RenderPass.index); m_RenderPass.AddTransientResource(result.handle); return result; } /// /// Create a new Render Graph Texture resource using the descriptor from another texture. /// 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 from which the descriptor should be used. /// A new transient TextureHandle. public TextureHandle CreateTransientTexture(in TextureHandle texture) { ref readonly var desc = ref m_Resources.GetTextureResourceDesc(texture.handle); var result = m_Resources.CreateTexture(desc, m_RenderPass.index); m_RenderPass.AddTransientResource(result.handle); return result; } /// /// Specify a RayTracingAccelerationStructure resource to build during the pass. /// /// The RayTracingAccelerationStructure resource to build during the pass. /// An updated resource handle to the input resource. public RayTracingAccelerationStructureHandle WriteRayTracingAccelerationStructure(in RayTracingAccelerationStructureHandle input) { CheckResource(input.handle); m_Resources.IncrementWriteCount(input.handle); m_RenderPass.AddResourceWrite(input.handle); return input; } /// /// Specify a RayTracingAccelerationStructure resource to use during the pass. /// /// The RayTracingAccelerationStructure resource to use during the pass. /// An updated resource handle to the input resource. public RayTracingAccelerationStructureHandle ReadRayTracingAccelerationStructure(in RayTracingAccelerationStructureHandle input) { CheckResource(input.handle); m_RenderPass.AddResourceRead(input.handle); return input; } /// /// Specify a Renderer List resource to use during the pass. /// /// The Renderer List resource to use during the pass. /// An updated resource handle to the input resource. public RendererListHandle UseRendererList(in RendererListHandle input) { if(input.IsValid()) m_RenderPass.UseRendererList(input); return input; } /// /// Specify a Graphics Buffer resource to read from during the pass. /// /// The Graphics Buffer resource to read from during the pass. /// An updated resource handle to the input resource. public BufferHandle ReadBuffer(in BufferHandle input) { CheckResource(input.handle); m_RenderPass.AddResourceRead(input.handle); return input; } /// /// Specify a Graphics Buffer resource to write to during the pass. /// /// The Graphics Buffer resource to write to during the pass. /// An updated resource handle to the input resource. public BufferHandle WriteBuffer(in BufferHandle input) { CheckResource(input.handle); m_RenderPass.AddResourceWrite(input.handle); m_Resources.IncrementWriteCount(input.handle); return input; } /// /// Create a new Render Graph Graphics Buffer resource. /// This Graphics Buffer 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. /// /// Graphics Buffer descriptor. /// A new transient GraphicsBufferHandle. public BufferHandle CreateTransientBuffer(in BufferDesc desc) { var result = m_Resources.CreateBuffer(desc, m_RenderPass.index); m_RenderPass.AddTransientResource(result.handle); return result; } /// /// Create a new Render Graph Graphics Buffer resource using the descriptor from another Graphics Buffer. /// This Graphics Buffer 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. /// /// Graphics Buffer from which the descriptor should be used. /// A new transient GraphicsBufferHandle. public BufferHandle CreateTransientBuffer(in BufferHandle graphicsbuffer) { ref readonly var desc = ref m_Resources.GetBufferResourceDesc(graphicsbuffer.handle); var result = m_Resources.CreateBuffer(desc, m_RenderPass.index); m_RenderPass.AddTransientResource(result.handle); return result; } /// /// Specify the render function to use for this pass. /// A call to this is mandatory for the pass to be valid. /// /// The Type of the class that provides data to the Render Pass. /// Render function for the pass. public void SetRenderFunc(BaseRenderFunc renderFunc) where PassData : class, new() { ((RenderGraphPass)m_RenderPass).renderFunc = renderFunc; } /// /// Enable asynchronous compute for this pass. /// /// Set to true to enable asynchronous compute. public void EnableAsyncCompute(bool value) { m_RenderPass.EnableAsyncCompute(value); } /// /// 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 cull this pass. /// /// True to allow pass culling. public void AllowPassCulling(bool value) { m_RenderPass.AllowPassCulling(value); } /// /// Enable foveated rendering for this pass. /// /// True to enable foveated rendering. public void EnableFoveatedRasterization(bool value) { m_RenderPass.EnableFoveatedRasterization(value); } /// /// Dispose the RenderGraphBuilder instance. /// public void Dispose() { Dispose(true); } /// /// Allow or not pass culling based on renderer list results /// By default all passes can be culled out if the render graph detects they are using a renderer list that is empty (does not draw any geometry) /// 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 cull this pass. /// /// True to allow pass culling. public void AllowRendererListCulling(bool value) { m_RenderPass.AllowRendererListCulling(value); } /// /// Used to indicate that a pass depends on an external renderer list (that is not directly used in this pass). /// /// The renderer list handle this pass depends on. /// A public RendererListHandle DependsOn(in RendererListHandle input) { m_RenderPass.UseRendererList(input); return input; } #endregion #region Internal Interface internal RenderGraphBuilder(RenderGraphPass renderPass, RenderGraphResourceRegistry resources, RenderGraph renderGraph) { m_RenderPass = renderPass; m_Resources = resources; m_RenderGraph = renderGraph; m_Disposed = false; } void Dispose(bool disposing) { if (m_Disposed) return; m_RenderGraph.RenderGraphState = RenderGraphState.RecordingGraph; m_Disposed = true; } [Conditional("UNITY_ENABLE_CHECKS")] void CheckResource(in ResourceHandle res, bool checkTransientReadWrite = true) { if(RenderGraph.enableValidityChecks) { if (res.IsValid()) { int transientIndex = m_Resources.GetRenderGraphResourceTransientIndex(res); // We have dontCheckTransientReadWrite here because users may want to use UseColorBuffer/UseDepthBuffer API to benefit from render target auto binding. In this case we don't want to raise the error. if (transientIndex == m_RenderPass.index && checkTransientReadWrite) { Debug.LogError($"Trying to read or write a transient resource at pass {m_RenderPass.name}.Transient resource are always assumed to be both read and written."); } if (transientIndex != -1 && transientIndex != m_RenderPass.index) { throw new ArgumentException($"Trying to use a transient texture (pass index {transientIndex}) in a different pass (pass index {m_RenderPass.index})."); } } else { throw new ArgumentException($"Trying to use an invalid resource (pass {m_RenderPass.name})."); } } } internal void GenerateDebugData(bool value) { m_RenderPass.GenerateDebugData(value); } #endregion } }