using System; using UnityEditor; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Profiling; namespace Coffee.UISoftMaskInternal { /// /// Utility class for managing temporary render textures. /// internal static class RenderTextureRepository { private static readonly ObjectRepository s_Repository = new ObjectRepository(); #if UNITY_2021_3_OR_NEWER private static readonly GraphicsFormat s_StencilFormat = GraphicsFormatUtility.GetDepthStencilFormat(0, 8); #endif public static int count => s_Repository.count; #if UNITY_EDITOR [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void Clear() { s_Repository.Clear(); } #endif /// /// Retrieves a cached RenderTexture based on the hash. /// public static bool Valid(Hash128 hash, RenderTexture rt) { Profiler.BeginSample("(COF)[RTRepository] Valid"); var ret = s_Repository.Valid(hash, rt); Profiler.EndSample(); return ret; } /// /// Adds or retrieves a cached RenderTexture based on the hash. /// public static void Get(Hash128 hash, ref RenderTexture rt, Func onCreate, T source) { Profiler.BeginSample("(COF)[RTRepository] Get"); s_Repository.Get(hash, ref rt, onCreate, source); Profiler.EndSample(); } /// /// Adds or retrieves a cached RenderTexture based on the hash. /// public static RenderTextureDescriptor GetDescriptor(Vector2Int size, bool useStencil, RenderTextureFormat format = RenderTextureFormat.ARGB32) { Profiler.BeginSample("(COF)[RTRepository] GetDescriptor"); var graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(format, RenderTextureReadWrite.Default); var rtd = new RenderTextureDescriptor( Mathf.Max(8, size.x), Mathf.Max(8, size.y), graphicsFormat, useStencil ? 24 : 0) { sRGB = QualitySettings.activeColorSpace == ColorSpace.Linear, mipCount = -1, #if UNITY_2021_3_OR_NEWER depthStencilFormat = useStencil ? s_StencilFormat : GraphicsFormat.None #endif }; Profiler.EndSample(); return rtd; } /// /// Releases the RenderTexture buffer. /// public static void Release(ref RenderTexture rt) { Profiler.BeginSample("(COF)[RTRepository] Release"); s_Repository.Release(ref rt); Profiler.EndSample(); } public static Vector2Int GetPreferSize(Vector2Int size, int downSamplingRate) { var aspect = (float)size.x / size.y; var screenSize = GetScreenSize(); // Clamp to screen size. size.x = Mathf.Clamp(size.x, 8, screenSize.x); size.y = Mathf.Clamp(size.y, 8, screenSize.y); if (downSamplingRate <= 0) { if (size.x < size.y) { size.x = Mathf.CeilToInt(size.y * aspect); } else { size.y = Mathf.CeilToInt(size.x / aspect); } return size; } if (size.x < size.y) { size.y = Mathf.NextPowerOfTwo(size.y / 2) / downSamplingRate; size.x = Mathf.CeilToInt(size.y * aspect); } else { size.x = Mathf.NextPowerOfTwo(size.x / 2) / downSamplingRate; size.y = Mathf.CeilToInt(size.x / aspect); } return size; } public static Vector2Int GetScreenSize(int downSamplingRate) { return GetPreferSize(GetScreenSize(), downSamplingRate); } public static Vector2Int GetScreenSize() { #if UNITY_EDITOR int ParseToInt(string s, int start, int end) { var result = 0; for (var i = start; i < end; i++) { result = result * 10 + (s[i] - '0'); } return result; } Profiler.BeginSample("(COF)[RTRepository] GetScreenSize (Editor)"); var screenRes = UnityStats.screenRes; var separator = screenRes.IndexOf('x'); var w = Mathf.Max(8, ParseToInt(screenRes, 0, separator)); var h = Mathf.Max(8, ParseToInt(screenRes, separator + 1, screenRes.Length)); Profiler.EndSample(); return new Vector2Int(w, h); #else return new Vector2Int(Screen.width, Screen.height); #endif } } }