UnityGame/Library/PackageCache/com.unity.render-pipelines.core/Runtime/Textures/RTHandle.cs

324 lines
13 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Rendering
{
/// <summary>
/// This struct contains some static helpers that can be used when converting RTid to RThandle
/// The common use case is to convert rtId to rtHandle and use the handle with other handle compatible core APIs
/// </summary>
public struct RTHandleStaticHelpers
{
/// <summary>
/// Static RTHandle wrapper around RenderTargetIdentifier to avoid gc.alloc
/// Set this wrapper through `RTHandleStaticHelpers.SetRTHandleStaticWrapper`
/// </summary>
public static RTHandle s_RTHandleWrapper;
/// <summary>
/// Set static RTHandle wrapper given a RTid. The static RTHandle wrapper is treated as external handle in RTHandleSystem
/// Get the static wrapper through `RTHandleStaticHelpers.s_RTHandleWrapper`.
/// </summary>
/// <param name="rtId">Input render target identifier to be converted.</param>
public static void SetRTHandleStaticWrapper(RenderTargetIdentifier rtId)
{
if (s_RTHandleWrapper == null)
s_RTHandleWrapper = RTHandles.Alloc(rtId);
else
s_RTHandleWrapper.SetTexture(rtId);
}
/// <summary>
/// Set user managed RTHandle wrapper given a RTid. The wrapper is treated as external handle in RTHandleSystem
/// </summary>
/// <param name="rtWrapper">User managed RTHandle wrapper.</param>
/// <param name="rtId">Input render target identifier to be set.</param>
public static void SetRTHandleUserManagedWrapper(ref RTHandle rtWrapper, RenderTargetIdentifier rtId)
{
// User managed wrapper is null, just return here.
if (rtWrapper == null)
return;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
// Check user managed RTHandle wrapper is actually a wrapper around RTid
if (rtWrapper.m_RT != null)
throw new ArgumentException($"Input wrapper must be a wrapper around RenderTargetIdentifier. Passed in wrapper contains valid RenderTexture {rtWrapper.m_RT.name} and cannot be used as wrapper.");
if (rtWrapper.m_ExternalTexture != null)
throw new ArgumentException($"Input wrapper must be a wrapper around RenderTargetIdentifier. Passed in wrapper contains valid Texture {rtWrapper.m_ExternalTexture.name} and cannot be used as wrapper.");
#endif
rtWrapper.SetTexture(rtId);
}
}
/// <summary>
/// A RTHandle is a RenderTexture that scales automatically with the camera size.
/// This allows proper reutilization of RenderTexture memory when different cameras with various sizes are used during rendering.
/// <see cref="RTHandleSystem"/>
/// </summary>
public class RTHandle
{
internal RTHandleSystem m_Owner;
internal RenderTexture m_RT;
internal Texture m_ExternalTexture;
internal RenderTargetIdentifier m_NameID;
internal bool m_EnableMSAA = false;
internal bool m_EnableRandomWrite = false;
internal bool m_EnableHWDynamicScale = false;
internal bool m_RTHasOwnership = true;
internal string m_Name;
internal bool m_UseCustomHandleScales = false;
internal RTHandleProperties m_CustomHandleProperties;
/// <summary>
/// By default, rtHandleProperties gets the global state of scalers against the global reference mode.
/// This method lets the current RTHandle use a local custom RTHandleProperties. This function is being used
/// by scalers such as TAAU and DLSS, which require to have a different resolution for color (independent of the RTHandleSystem).
/// </summary>
/// <param name="properties">Properties to set.</param>
public void SetCustomHandleProperties(in RTHandleProperties properties)
{
m_UseCustomHandleScales = true;
m_CustomHandleProperties = properties;
}
/// <summary>
/// Method that clears any custom handle property being set.
/// </summary>
public void ClearCustomHandleProperties()
{
m_UseCustomHandleScales = false;
}
/// <summary>
/// Scale factor applied to the RTHandle reference size.
/// </summary>
public Vector2 scaleFactor { get; internal set; }
internal ScaleFunc scaleFunc;
/// <summary>
/// Returns true if the RTHandle uses automatic scaling.
/// </summary>
public bool useScaling { get; internal set; }
/// <summary>
/// Reference size of the RTHandle System associated with the RTHandle
/// </summary>
public Vector2Int referenceSize { get; internal set; }
/// <summary>
/// Current properties of the RTHandle System. If a custom property has been set through SetCustomHandleProperties method, it will be used that one instead.
/// </summary>
public RTHandleProperties rtHandleProperties { get { return m_UseCustomHandleScales ? m_CustomHandleProperties : m_Owner.rtHandleProperties; } }
/// <summary>
/// RenderTexture associated with the RTHandle
/// </summary>
public RenderTexture rt { get { return m_RT; } }
/// <summary>
/// Texture associated with the RTHandle when constructed from an external Texture or RenderTexture
/// </summary>
public Texture externalTexture { get { return m_ExternalTexture; } }
/// <summary>
/// RenderTargetIdentifier associated with the RTHandle
/// </summary>
public RenderTargetIdentifier nameID { get { return m_NameID; } }
/// <summary>
/// Name of the RTHandle
/// </summary>
public string name { get { return m_Name; } }
/// <summary>
/// Returns true is MSAA is enabled, false otherwise.
/// </summary>
public bool isMSAAEnabled { get { return m_EnableMSAA; } }
// Keep constructor private
internal RTHandle(RTHandleSystem owner)
{
m_Owner = owner;
}
/// <summary>
/// Implicit conversion operator to RenderTargetIdentifier
/// </summary>
/// <param name="handle">Input RTHandle</param>
/// <returns>RenderTargetIdentifier representation of the RTHandle.</returns>
public static implicit operator RenderTargetIdentifier(RTHandle handle)
{
return handle != null ? handle.nameID : default(RenderTargetIdentifier);
}
/// <summary>
/// Implicit conversion operator to Texture
/// </summary>
/// <param name="handle">Input RTHandle</param>
/// <returns>Texture representation of the RTHandle.</returns>
public static implicit operator Texture(RTHandle handle)
{
// If RTHandle is null then conversion should give a null Texture
if (handle == null)
return null;
Debug.Assert(handle.m_ExternalTexture != null || handle.rt != null);
return (handle.rt != null) ? handle.rt : handle.m_ExternalTexture;
}
/// <summary>
/// Implicit conversion operator to RenderTexture
/// </summary>
/// <param name="handle">Input RTHandle</param>
/// <returns>RenderTexture representation of the RTHandle.</returns>
public static implicit operator RenderTexture(RTHandle handle)
{
// If RTHandle is null then conversion should give a null RenderTexture
if (handle == null)
return null;
Debug.Assert(handle.rt != null, "RTHandle was created using a regular Texture and is used as a RenderTexture");
return handle.rt;
}
internal void SetRenderTexture(RenderTexture rt, bool transferOwnership = true)
{
m_RT = rt;
m_ExternalTexture = null;
m_RTHasOwnership = transferOwnership;
m_NameID = new RenderTargetIdentifier(rt);
}
internal void SetTexture(Texture tex)
{
m_RT = null;
m_ExternalTexture = tex;
m_NameID = new RenderTargetIdentifier(tex);
}
internal void SetTexture(RenderTargetIdentifier tex)
{
m_RT = null;
m_ExternalTexture = null;
m_NameID = tex;
}
/// <summary>
/// Get the Instance ID of the RTHandle.
/// </summary>
/// <returns>The RTHandle Instance ID.</returns>
public int GetInstanceID()
{
if (m_RT != null)
return m_RT.GetInstanceID();
else if (m_ExternalTexture != null)
return m_ExternalTexture.GetInstanceID();
else
return m_NameID.GetHashCode(); // No instance ID so we return the hash code.
}
/// <summary>
/// Release the RTHandle
/// </summary>
public void Release()
{
m_Owner.Remove(this);
if (m_RTHasOwnership)
CoreUtils.Destroy(m_RT);
m_NameID = BuiltinRenderTextureType.None;
m_RT = null;
m_ExternalTexture = null;
m_RTHasOwnership = true;
}
/// <summary>
/// Return the input size, scaled by the RTHandle scale factor.
/// </summary>
/// <param name="refSize">Input size</param>
/// <returns>Input size scaled by the RTHandle scale factor.</returns>
public Vector2Int GetScaledSize(Vector2Int refSize)
{
if (!useScaling)
return refSize;
if (scaleFunc != null)
{
return scaleFunc(refSize);
}
else
{
return new Vector2Int(
x: Mathf.RoundToInt(scaleFactor.x * refSize.x),
y: Mathf.RoundToInt(scaleFactor.y * refSize.y)
);
}
}
/// <summary>
/// Return the scaled size of the RTHandle.
/// </summary>
/// <returns>The scaled size of the RTHandle.</returns>
public Vector2Int GetScaledSize()
{
if (!useScaling)
return referenceSize;
if (scaleFunc != null)
{
return scaleFunc(referenceSize);
}
else
{
return new Vector2Int(
x: Mathf.RoundToInt(scaleFactor.x * referenceSize.x),
y: Mathf.RoundToInt(scaleFactor.y * referenceSize.y)
);
}
}
#if UNITY_2020_2_OR_NEWER
/// <summary>
/// Switch the render target to fast memory on platform that have it.
/// </summary>
/// <param name="cmd">Command buffer used for rendering.</param>
/// <param name="residencyFraction">How much of the render target is to be switched into fast memory (between 0 and 1).</param>
/// <param name="flags">Flag to determine what parts of the render target is spilled if not fully resident in fast memory.</param>
/// <param name="copyContents">Whether the content of render target are copied or not when switching to fast memory.</param>
public void SwitchToFastMemory(CommandBuffer cmd,
float residencyFraction = 1.0f,
FastMemoryFlags flags = FastMemoryFlags.SpillTop,
bool copyContents = false
)
{
residencyFraction = Mathf.Clamp01(residencyFraction);
cmd.SwitchIntoFastMemory(m_RT, flags, residencyFraction, copyContents);
}
/// <summary>
/// Switch the render target to fast memory on platform that have it and copies the content.
/// </summary>
/// <param name="cmd">Command buffer used for rendering.</param>
/// <param name="residencyFraction">How much of the render target is to be switched into fast memory (between 0 and 1).</param>
/// <param name="flags">Flag to determine what parts of the render target is spilled if not fully resident in fast memory.</param>
public void CopyToFastMemory(CommandBuffer cmd,
float residencyFraction = 1.0f,
FastMemoryFlags flags = FastMemoryFlags.SpillTop
)
{
SwitchToFastMemory(cmd, residencyFraction, flags, copyContents: true);
}
/// <summary>
/// Switch out the render target from fast memory back to main memory on platforms that have fast memory.
/// </summary>
/// <param name="cmd">Command buffer used for rendering.</param>
/// <param name="copyContents">Whether the content of render target are copied or not when switching out fast memory.</param>
public void SwitchOutFastMemory(CommandBuffer cmd, bool copyContents = true)
{
cmd.SwitchOutOfFastMemory(m_RT, copyContents);
}
#endif
}
}