Files
2026-02-21 16:45:37 +08:00

175 lines
4.6 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace UltimateWater.Internal
{
public class RenderTexturesCache
{
[ExecuteInEditMode]
public class RenderTexturesUpdater : MonoBehaviour
{
private static RenderTexturesUpdater _Instance;
public static void EnsureInstance()
{
if (!(_Instance != null))
{
GameObject gameObject = new GameObject("Water.RenderTexturesCache");
gameObject.hideFlags = HideFlags.HideAndDontSave;
GameObject gameObject2 = gameObject;
if (Application.isPlaying)
{
Object.DontDestroyOnLoad(gameObject2);
}
_Instance = gameObject2.AddComponent<RenderTexturesUpdater>();
}
}
private void Update()
{
int frameCount = Time.frameCount;
Dictionary<ulong, RenderTexturesCache>.Enumerator enumerator = _Cache.GetEnumerator();
while (enumerator.MoveNext())
{
enumerator.Current.Value.Update(frameCount);
}
enumerator.Dispose();
}
private void OnApplicationQuit()
{
Dictionary<ulong, RenderTexturesCache>.Enumerator enumerator = _Cache.GetEnumerator();
while (enumerator.MoveNext())
{
enumerator.Current.Value.Release();
}
enumerator.Dispose();
}
}
private static readonly Dictionary<ulong, RenderTexturesCache> _Cache = new Dictionary<ulong, RenderTexturesCache>(UInt64EqualityComparer.Default);
private readonly Queue<RenderTexture> _RenderTextures;
private int _LastFrameAllUsed;
private readonly ulong _Hash;
private readonly int _Width;
private readonly int _Height;
private readonly int _DepthBuffer;
private readonly RenderTextureFormat _Format;
private readonly bool _Linear;
private readonly bool _Uav;
private readonly bool _MipMaps;
public RenderTexturesCache(ulong hash, int width, int height, int depthBuffer, RenderTextureFormat format, bool linear, bool uav, bool mipMaps)
{
_Hash = hash;
_Width = width;
_Height = height;
_DepthBuffer = depthBuffer;
_Format = format;
_Linear = linear;
_Uav = uav;
_MipMaps = mipMaps;
_RenderTextures = new Queue<RenderTexture>();
}
public static RenderTexturesCache GetCache(int width, int height, int depthBuffer, RenderTextureFormat format, bool linear, bool uav, bool mipMaps = false)
{
RenderTexturesUpdater.EnsureInstance();
ulong num = 0uL;
num |= (uint)width;
num |= (uint)(height << 16);
num |= (ulong)((long)depthBuffer << 29);
num |= (ulong)((long)((!linear) ? 0 : 1) << 34);
num |= (ulong)((long)((!uav) ? 0 : 1) << 35);
num |= (ulong)((long)((!mipMaps) ? 0 : 1) << 36);
num |= (ulong)((long)format << 37);
RenderTexturesCache value;
if (!_Cache.TryGetValue(num, out value))
{
value = (_Cache[num] = new RenderTexturesCache(num, width, height, depthBuffer, format, linear, uav, mipMaps));
}
return value;
}
public static TemporaryRenderTexture GetTemporary(int width, int height, int depthBuffer, RenderTextureFormat format, bool linear, bool uav, bool mipMaps = false)
{
return GetCache(width, height, depthBuffer, format, linear, uav, mipMaps).GetTemporary();
}
public TemporaryRenderTexture GetTemporary()
{
return new TemporaryRenderTexture(this);
}
public RenderTexture GetTemporaryDirect()
{
RenderTexture renderTexture;
if (_RenderTextures.Count == 0)
{
renderTexture = new RenderTexture(_Width, _Height, _DepthBuffer, _Format, _Linear ? RenderTextureReadWrite.Linear : RenderTextureReadWrite.sRGB);
renderTexture.hideFlags = HideFlags.DontSave;
renderTexture.name = "[UWS] RenderTexturesCache - Temporary#" + _Hash;
renderTexture.filterMode = FilterMode.Point;
renderTexture.anisoLevel = 1;
renderTexture.wrapMode = TextureWrapMode.Repeat;
renderTexture.useMipMap = _MipMaps;
renderTexture.autoGenerateMips = _MipMaps;
if (_Uav)
{
renderTexture.enableRandomWrite = true;
}
}
else
{
renderTexture = _RenderTextures.Dequeue();
}
if (_Uav && !renderTexture.IsCreated())
{
renderTexture.Create();
}
if (_RenderTextures.Count == 0)
{
_LastFrameAllUsed = Time.frameCount;
}
return renderTexture;
}
public void ReleaseTemporaryDirect(RenderTexture renderTexture)
{
_RenderTextures.Enqueue(renderTexture);
}
internal void Update(int frame)
{
if (frame - _LastFrameAllUsed > 3 && _RenderTextures.Count != 0)
{
RenderTexture obj = _RenderTextures.Dequeue();
obj.Destroy();
}
}
internal void Release()
{
foreach (RenderTexture renderTexture in _RenderTextures)
{
if (renderTexture != null)
{
renderTexture.Release();
renderTexture.Destroy();
}
}
_RenderTextures.Clear();
}
}
}