123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- using System;
- using System.Diagnostics;
- using System.Runtime.CompilerServices;
- using UnityEngine.Experimental.Rendering;
- using UnityEngine.Rendering;
- using UnityEngine.Scripting.APIUpdating;
-
- namespace UnityEngine.Rendering.RenderGraphModule
- {
- internal struct TextureAccess
- {
- public TextureHandle textureHandle;
- public int mipLevel;
- public int depthSlice;
- public AccessFlags flags;
-
- public TextureAccess(TextureHandle handle, AccessFlags flags, int mipLevel, int depthSlice)
- {
- this.textureHandle = handle;
- this.flags = flags;
- this.mipLevel = mipLevel;
- this.depthSlice = depthSlice;
- }
- }
-
-
- /// <summary>
- /// An abstract handle representing a texture resource as known by one particular record + execute of the render graph.
- /// TextureHandles should not be used outside of the context of a render graph execution.
- ///
- /// A render graph needs to do additional state tracking on texture resources (lifetime, how is it used,...) to enable
- /// this all textures relevant to the render graph need to be make known to it. A texture handle specifies such a texture as
- /// known to the render graph.
- ///
- /// It is important to understand that a render graph texture handle does not necessarily represent an actual texture. For example
- /// textures could be created the render graph that are only referenced by passes that are later culled when executing the graph.
- /// Such textures would never be allocated as actual RenderTextures.
- ///
- /// Texture handles are only relevant to one particular record+execute phase of the render graph. After execution all texture
- /// handles are invalidated. The system will catch texture handles from a different execution of the render graph but still
- /// users should be careful to avoid keeping texture handles around from other render graph executions.
- ///
- /// Texture handles do not need to be disposed/freed (they are auto-invalidated at the end of graph execution). The RenderTextures they represent
- /// are either freed by the render graph internally (when the handle was acquired through RenderGraph.CreateTexture) or explicitly managed by
- /// some external system (when acquired through RenderGraph.ImportTexture).
- ///
- /// </summary>
- [DebuggerDisplay("Texture ({handle.index})")]
- [MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
- public struct TextureHandle
- {
- private static TextureHandle s_NullHandle = new TextureHandle();
-
- /// <summary>
- /// Returns a null texture handle
- /// </summary>
- /// <value>A null texture handle.</value>
- public static TextureHandle nullHandle { get { return s_NullHandle; } }
-
- internal ResourceHandle handle;
-
- private bool builtin;
-
- internal TextureHandle(in ResourceHandle h)
- {
- handle = h;
- builtin = false;
- }
-
- internal TextureHandle(int handle, bool shared = false, bool builtin = false)
- {
- this.handle = new ResourceHandle(handle, RenderGraphResourceType.Texture, shared);
- this.builtin = builtin;
- }
-
- /// <summary>
- /// Cast to RenderTargetIdentifier
- /// </summary>
- /// <param name="texture">Input TextureHandle.</param>
- /// <returns>Resource as a RenderTargetIdentifier.</returns>
- public static implicit operator RenderTargetIdentifier(TextureHandle texture) => texture.IsValid() ? RenderGraphResourceRegistry.current.GetTexture(texture) : default(RenderTargetIdentifier);
-
- /// <summary>
- /// Cast to Texture
- /// </summary>
- /// <param name="texture">Input TextureHandle.</param>
- /// <returns>Resource as a Texture.</returns>
- public static implicit operator Texture(TextureHandle texture) => texture.IsValid() ? RenderGraphResourceRegistry.current.GetTexture(texture) : null;
-
- /// <summary>
- /// Cast to RenderTexture
- /// </summary>
- /// <param name="texture">Input TextureHandle.</param>
- /// <returns>Resource as a RenderTexture.</returns>
- public static implicit operator RenderTexture(TextureHandle texture) => texture.IsValid() ? RenderGraphResourceRegistry.current.GetTexture(texture) : null;
-
- /// <summary>
- /// Cast to RTHandle
- /// </summary>
- /// <param name="texture">Input TextureHandle.</param>
- /// <returns>Resource as a RTHandle.</returns>
- public static implicit operator RTHandle(TextureHandle texture) => texture.IsValid() ? RenderGraphResourceRegistry.current.GetTexture(texture) : null;
-
- /// <summary>
- /// Return true if the handle is valid.
- /// </summary>
- /// <returns>True if the handle is valid.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsValid() => handle.IsValid();
-
- /// <summary>
- /// Return true if the handle is a builtin handle managed by RenderGraph internally.
- /// </summary>
- /// <returns>True if the handle is a builtin handle.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool IsBuiltin() => this.builtin;
-
- /// <summary>
- /// Get the Descriptor of the texture. This simply calls RenderGraph.GetTextureDesc but is more easily discoverable through auto complete.
- /// </summary>
- /// <param name="renderGraph">The rendergraph instance that was used to create the texture on. Texture handles are a lightweight object, all information is stored on the RenderGraph itself.</param>
- /// <returns>The texture descriptor for the given texture handle.</returns>
- public TextureDesc GetDescriptor(RenderGraph renderGraph) { return renderGraph.GetTextureDesc(this); }
- }
-
- /// <summary>
- /// The mode that determines the size of a Texture.
- /// </summary>
- public enum TextureSizeMode
- {
- ///<summary>Explicit size.</summary>
- Explicit,
- ///<summary>Size automatically scaled by a Vector.</summary>
- Scale,
- ///<summary>Size automatically scaled by a Functor.</summary>
- Functor
- }
-
- #if UNITY_2020_2_OR_NEWER
- /// <summary>
- /// Subset of the texture desc containing information for fast memory allocation (when platform supports it)
- /// </summary>
- public struct FastMemoryDesc
- {
- ///<summary>Whether the texture will be in fast memory.</summary>
- public bool inFastMemory;
- ///<summary>Flag to determine what parts of the render target is spilled if not fully resident in fast memory.</summary>
- public FastMemoryFlags flags;
- ///<summary>How much of the render target is to be switched into fast memory (between 0 and 1).</summary>
- public float residencyFraction;
- }
- #endif
-
- /// <summary>
- /// Descriptor used to create texture resources
- /// </summary>
- public struct TextureDesc
- {
- ///<summary>Texture sizing mode.</summary>
- public TextureSizeMode sizeMode;
- ///<summary>Texture width.</summary>
- public int width;
- ///<summary>Texture height.</summary>
- public int height;
- ///<summary>Number of texture slices..</summary>
- public int slices;
- ///<summary>Texture scale.</summary>
- public Vector2 scale;
- ///<summary>Texture scale function.</summary>
- public ScaleFunc func;
- ///<summary>Depth buffer bit depth.</summary>
- public DepthBits depthBufferBits;
- ///<summary>Color format.</summary>
- public GraphicsFormat colorFormat;
- ///<summary>Filtering mode.</summary>
- public FilterMode filterMode;
- ///<summary>Addressing mode.</summary>
- public TextureWrapMode wrapMode;
- ///<summary>Texture dimension.</summary>
- public TextureDimension dimension;
- ///<summary>Enable random UAV read/write on the texture.</summary>
- public bool enableRandomWrite;
- ///<summary>Texture needs mip maps.</summary>
- public bool useMipMap;
- ///<summary>Automatically generate mip maps.</summary>
- public bool autoGenerateMips;
- ///<summary>Texture is a shadow map.</summary>
- public bool isShadowMap;
- ///<summary>Anisotropic filtering level.</summary>
- public int anisoLevel;
- ///<summary>Mip map bias.</summary>
- public float mipMapBias;
- ///<summary>Number of MSAA samples.</summary>
- public MSAASamples msaaSamples;
- ///<summary>Bind texture multi sampled.</summary>
- public bool bindTextureMS;
- ///<summary>[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</summary>
- public bool useDynamicScale;
- ///<summary>[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</summary>
- public bool useDynamicScaleExplicit;
- ///<summary>Memory less flag.</summary>
- public RenderTextureMemoryless memoryless;
- ///<summary>Special treatment of the VR eye texture used in stereoscopic rendering.</summary>
- public VRTextureUsage vrUsage;
- ///<summary>Texture name.</summary>
- public string name;
- #if UNITY_2020_2_OR_NEWER
- ///<summary>Descriptor to determine how the texture will be in fast memory on platform that supports it.</summary>
- public FastMemoryDesc fastMemoryDesc;
- #endif
- ///<summary>Determines whether the texture will fallback to a black texture if it is read without ever writing to it.</summary>
- public bool fallBackToBlackTexture;
- ///<summary>
- ///If all passes writing to a texture are culled by Dynamic Render Pass Culling, it will automatically fallback to a similar preallocated texture.
- ///Set this to true to force the allocation.
- ///</summary>
- public bool disableFallBackToImportedTexture;
-
- // Initial state. Those should not be used in the hash
- ///<summary>Texture needs to be cleared on first use.</summary>
- public bool clearBuffer;
- ///<summary>Clear color.</summary>
- public Color clearColor;
-
- ///<summary>Texture needs to be discarded on last use.</summary>
- public bool discardBuffer;
-
- void InitDefaultValues(bool dynamicResolution, bool xrReady)
- {
- useDynamicScale = dynamicResolution;
- vrUsage = VRTextureUsage.None;
- // XR Ready
- if (xrReady)
- {
- slices = TextureXR.slices;
- dimension = TextureXR.dimension;
- }
- else
- {
- slices = 1;
- dimension = TextureDimension.Tex2D;
- }
-
- discardBuffer = false;
- }
-
- /// <summary>
- /// TextureDesc constructor for a texture using explicit size
- /// </summary>
- /// <param name="width">Texture width</param>
- /// <param name="height">Texture height</param>
- /// <param name="dynamicResolution">Use dynamic resolution</param>
- /// <param name="xrReady">Set this to true if the Texture is a render texture in an XR setting.</param>
- public TextureDesc(int width, int height, bool dynamicResolution = false, bool xrReady = false)
- : this()
- {
- // Size related init
- sizeMode = TextureSizeMode.Explicit;
- this.width = width;
- this.height = height;
- // Important default values not handled by zero construction in this()
- msaaSamples = MSAASamples.None;
- InitDefaultValues(dynamicResolution, xrReady);
- }
-
- /// <summary>
- /// TextureDesc constructor for a texture using a fixed scaling
- /// </summary>
- /// <param name="scale">RTHandle scale used for this texture</param>
- /// <param name="dynamicResolution">Use dynamic resolution</param>
- /// <param name="xrReady">Set this to true if the Texture is a render texture in an XR setting.</param>
- public TextureDesc(Vector2 scale, bool dynamicResolution = false, bool xrReady = false)
- : this()
- {
- // Size related init
- sizeMode = TextureSizeMode.Scale;
- this.scale = scale;
- // Important default values not handled by zero construction in this()
- msaaSamples = MSAASamples.None;
- dimension = TextureDimension.Tex2D;
- InitDefaultValues(dynamicResolution, xrReady);
- }
-
- /// <summary>
- /// TextureDesc constructor for a texture using a functor for scaling
- /// </summary>
- /// <param name="func">Function used to determine the texture size</param>
- /// <param name="dynamicResolution">Use dynamic resolution</param>
- /// <param name="xrReady">Set this to true if the Texture is a render texture in an XR setting.</param>
- public TextureDesc(ScaleFunc func, bool dynamicResolution = false, bool xrReady = false)
- : this()
- {
- // Size related init
- sizeMode = TextureSizeMode.Functor;
- this.func = func;
- // Important default values not handled by zero construction in this()
- msaaSamples = MSAASamples.None;
- dimension = TextureDimension.Tex2D;
- InitDefaultValues(dynamicResolution, xrReady);
- }
-
- /// <summary>
- /// Copy constructor
- /// </summary>
- /// <param name="input">The TextureDesc instance to copy from.</param>
- public TextureDesc(TextureDesc input)
- {
- this = input;
- }
-
- /// <summary>
- /// Do a best effort conversion from a RenderTextureDescriptor to a TextureDesc. This tries to initialize a descriptor to be as close as possible to the given render texture descriptor but there might be subtle differences when creating
- /// render graph textures using this TextureDesc due to the underlying RTHandle system.
- /// Some parameters of the TextureDesc (like name and filtering modes) are not present in the RenderTextureDescriptor for these the returned TextureDesc will contain plausible default values.
- /// </summary>
- /// <param name="input">The texture descriptor to create a TextureDesc from</param>
- public TextureDesc(RenderTextureDescriptor input)
- {
- sizeMode = TextureSizeMode.Explicit;
- width = input.width;
- height = input.height;
- slices = input.volumeDepth;
- scale = Vector2.one;
- func = null;
- depthBufferBits = (DepthBits)input.depthBufferBits;
- colorFormat = input.graphicsFormat;
- filterMode = FilterMode.Bilinear;
- wrapMode = TextureWrapMode.Clamp;
- dimension = input.dimension;
- enableRandomWrite = input.enableRandomWrite;
- useMipMap = input.useMipMap;
- autoGenerateMips = input.autoGenerateMips;
- isShadowMap = (input.shadowSamplingMode != ShadowSamplingMode.None);
- anisoLevel = 1;
- mipMapBias = 0;
- msaaSamples = (MSAASamples)input.msaaSamples;
- bindTextureMS = input.bindMS;
- useDynamicScale = input.useDynamicScale;
- useDynamicScaleExplicit = false;
- memoryless = input.memoryless;
- vrUsage = input.vrUsage;
- name = "UnNamedFromRenderTextureDescriptor";
- fastMemoryDesc = new FastMemoryDesc();
- fastMemoryDesc.inFastMemory = false;
- fallBackToBlackTexture = false;
- disableFallBackToImportedTexture = true;
- clearBuffer = true;
- clearColor = Color.black;
- discardBuffer = false;
- }
-
- /// <summary>
- /// Do a best effort conversion from a RenderTexture to a TextureDesc. This tries to initialize a descriptor to be as close as possible to the given render texture but there might be subtle differences when creating
- /// render graph textures using this TextureDesc due to the underlying RTHandle system.
- /// </summary>
- /// <param name="input">The texture to create a TextureDesc from</param>
- public TextureDesc(RenderTexture input) : this(input.descriptor)
- {
- filterMode = input.filterMode;
- wrapMode = input.wrapMode;
- anisoLevel = input.anisoLevel;
- mipMapBias = input.mipMapBias;
- this.name = "UnNamedFromRenderTextureDescriptor";
- }
-
- /// <summary>
- /// Hash function
- /// </summary>
- /// <returns>The texture descriptor hash.</returns>
- public override int GetHashCode()
- {
- int hashCode = 17;
-
- unchecked
- {
- switch (sizeMode)
- {
- case TextureSizeMode.Explicit:
- hashCode = hashCode * 23 + width;
- hashCode = hashCode * 23 + height;
- break;
- case TextureSizeMode.Functor:
- if (func != null)
- hashCode = hashCode * 23 + func.GetHashCode();
- break;
- case TextureSizeMode.Scale:
- hashCode = hashCode * 23 + scale.x.GetHashCode();
- hashCode = hashCode * 23 + scale.y.GetHashCode();
- break;
- }
-
- hashCode = hashCode * 23 + mipMapBias.GetHashCode();
- hashCode = hashCode * 23 + slices;
- hashCode = hashCode * 23 + (int)depthBufferBits;
- hashCode = hashCode * 23 + (int)colorFormat;
- hashCode = hashCode * 23 + (int)filterMode;
- hashCode = hashCode * 23 + (int)wrapMode;
- hashCode = hashCode * 23 + (int)dimension;
- hashCode = hashCode * 23 + (int)memoryless;
- hashCode = hashCode * 23 + (int)vrUsage;
- hashCode = hashCode * 23 + anisoLevel;
- hashCode = hashCode * 23 + (enableRandomWrite ? 1 : 0);
- hashCode = hashCode * 23 + (useMipMap ? 1 : 0);
- hashCode = hashCode * 23 + (autoGenerateMips ? 1 : 0);
- hashCode = hashCode * 23 + (isShadowMap ? 1 : 0);
- hashCode = hashCode * 23 + (bindTextureMS ? 1 : 0);
- hashCode = hashCode * 23 + (useDynamicScale ? 1 : 0);
- hashCode = hashCode * 23 + (int)msaaSamples;
- #if UNITY_2020_2_OR_NEWER
- hashCode = hashCode * 23 + (fastMemoryDesc.inFastMemory ? 1 : 0);
- #endif
- }
-
- return hashCode;
- }
-
- /// <summary>
- /// Calculate the final size of the texture descriptor in pixels. This takes into account the sizeMode set for this descriptor.
- /// For the automatically scaled sizes the size will be relative to the RTHandle reference size <see cref="RTHandles.SetReferenceSize">SetReferenceSize</see>.
- /// </summary>
- /// <returns>The calculated size.</returns>
- /// <exception cref="ArgumentOutOfRangeException">Thrown if the texture descriptor's size mode falls outside the expected range.</exception>
- public Vector2Int CalculateFinalDimensions()
- {
- return sizeMode switch
- {
- TextureSizeMode.Explicit => new Vector2Int(width, height),
- TextureSizeMode.Scale => RTHandles.CalculateDimensions(scale),
- TextureSizeMode.Functor => RTHandles.CalculateDimensions(func),
- _ => throw new ArgumentOutOfRangeException()
- };
-
- }
- }
-
- [DebuggerDisplay("TextureResource ({desc.name})")]
- class TextureResource : RenderGraphResource<TextureDesc, RTHandle>
- {
- static int m_TextureCreationIndex;
-
- public override string GetName()
- {
- if (imported && !shared)
- return graphicsResource != null ? graphicsResource.name : "null resource";
- else
- return desc.name;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetDescHashCode() { return desc.GetHashCode(); }
-
- public override void CreateGraphicsResource()
- {
- var name = GetName();
-
- // 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.
- if (name == "")
- name = $"RenderGraphTexture_{m_TextureCreationIndex++}";
-
- switch (desc.sizeMode)
- {
- case TextureSizeMode.Explicit:
- graphicsResource = 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.useDynamicScaleExplicit, desc.memoryless, desc.vrUsage, name);
- break;
- case TextureSizeMode.Scale:
- graphicsResource = 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.msaaSamples, desc.bindTextureMS, desc.useDynamicScale, desc.useDynamicScaleExplicit, desc.memoryless, desc.vrUsage, name);
- break;
- case TextureSizeMode.Functor:
- graphicsResource = 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.msaaSamples, desc.bindTextureMS, desc.useDynamicScale, desc.useDynamicScaleExplicit, desc.memoryless, desc.vrUsage, name);
- break;
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override void UpdateGraphicsResource()
- {
- if (graphicsResource != null)
- graphicsResource.m_Name = GetName();
- }
-
- public override void ReleaseGraphicsResource()
- {
- if (graphicsResource != null)
- graphicsResource.Release();
- base.ReleaseGraphicsResource();
- }
-
- public override void LogCreation(RenderGraphLogger logger)
- {
- logger.LogLine($"Created Texture: {desc.name} (Cleared: {desc.clearBuffer})");
- }
-
- public override void LogRelease(RenderGraphLogger logger)
- {
- logger.LogLine($"Released Texture: {desc.name}");
- }
- }
-
- class TexturePool : RenderGraphResourcePool<RTHandle>
- {
- protected override void ReleaseInternalResource(RTHandle res)
- {
- res.Release();
- }
-
- protected override string GetResourceName(in RTHandle res)
- {
- return res.rt.name;
- }
-
- protected override long GetResourceSize(in RTHandle res)
- {
- return Profiling.Profiler.GetRuntimeMemorySizeLong(res.rt);
- }
-
- override protected string GetResourceTypeName()
- {
- return "Texture";
- }
-
- override protected int GetSortIndex(RTHandle res)
- {
- return res.GetInstanceID();
- }
- }
- }
|