123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- using System.Collections.Generic;
- using Unity.Collections;
- using UnityEngine.Profiling;
- using UnityEngine.Rendering;
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
-
- namespace UnityEngine.U2D.Animation
- {
- internal class VertexBuffer
- {
- /// <summary>
- /// Number of buffers currently allocated.
- /// </summary>
- public int bufferCount => m_Buffers.Length;
-
- private readonly int m_Id;
- private bool m_IsActive = true;
- private int m_DeactivateFrame = -1;
-
- private NativeByteArray[] m_Buffers;
- private int m_ActiveIndex = 0;
-
- public VertexBuffer(int id, int size, bool needDoubleBuffering)
- {
- m_Id = id;
-
- var noOfBuffers = needDoubleBuffering ? 2 : 1;
- m_Buffers = new NativeByteArray[noOfBuffers];
- for (var i = 0; i < noOfBuffers; i++)
- m_Buffers[i] = new NativeByteArray(new NativeArray<byte>(size, Allocator.Persistent, NativeArrayOptions.UninitializedMemory));
- }
-
- public override int GetHashCode() => m_Id;
- private static int GetCurrentFrame() => Time.frameCount;
-
- public NativeByteArray GetBuffer(int size)
- {
- if (!m_IsActive)
- {
- Debug.LogError($"Cannot request deactivated buffer. ID: {m_Id}");
- return null;
- }
-
- m_ActiveIndex = (m_ActiveIndex + 1) % m_Buffers.Length;
- if (m_Buffers[m_ActiveIndex].Length != size)
- ResizeBuffer(m_ActiveIndex, size);
-
- return m_Buffers[m_ActiveIndex];
- }
-
- private void ResizeBuffer(int bufferId, int newSize)
- {
- m_Buffers[bufferId].Dispose();
- m_Buffers[bufferId] = new NativeByteArray(new NativeArray<byte>(newSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory));
- }
-
- public void Deactivate()
- {
- if (!m_IsActive)
- return;
-
- m_IsActive = false;
- m_DeactivateFrame = GetCurrentFrame();
- }
-
- public void Dispose()
- {
- for (var i = 0; i < m_Buffers.Length; i++)
- {
- if (m_Buffers[i].IsCreated)
- m_Buffers[i].Dispose();
- }
- }
-
- public bool IsSafeToDispose() => !m_IsActive && GetCurrentFrame() > m_DeactivateFrame;
- }
-
- internal class BufferManager : ScriptableObject
- {
- private static BufferManager s_Instance;
-
- private Dictionary<int, VertexBuffer> m_Buffers = new Dictionary<int, VertexBuffer>();
- private Queue<VertexBuffer> m_BuffersToDispose = new Queue<VertexBuffer>();
-
- /// <summary>
- /// Number of buffers currently allocated.
- /// </summary>
- public int bufferCount
- {
- get
- {
- var count = 0;
- foreach (var buffer in m_Buffers.Values)
- count += buffer.bufferCount;
- return count;
- }
- }
-
- /// <summary>
- /// Creates two buffers instead of one if enabled.
- /// </summary>
- public bool needDoubleBuffering
- {
- get;
- set;
- }
-
- public static BufferManager instance
- {
- get
- {
- if (s_Instance == null)
- {
- var bufferMGRs = Resources.FindObjectsOfTypeAll<BufferManager>();
- if (bufferMGRs.Length > 0)
- s_Instance = bufferMGRs[0];
- else
- s_Instance = ScriptableObject.CreateInstance<BufferManager>();
- s_Instance.hideFlags = HideFlags.HideAndDontSave;
- }
- return s_Instance;
- }
- }
-
- private void OnEnable()
- {
- if (s_Instance == null)
- s_Instance = this;
-
- needDoubleBuffering = SystemInfo.renderingThreadingMode != RenderingThreadingMode.Direct;
- #if UNITY_EDITOR
- EditorApplication.update += Update;
- #else
- Application.onBeforeRender += Update;
- #endif
- }
-
- private void OnDisable()
- {
- if (s_Instance == this)
- s_Instance = null;
-
- ForceClearBuffers();
-
- #if UNITY_EDITOR
- EditorApplication.update -= Update;
- #else
- Application.onBeforeRender -= Update;
- #endif
- }
-
- private void ForceClearBuffers()
- {
- foreach (var vertexBuffer in m_Buffers.Values)
- vertexBuffer.Dispose();
- foreach (var vertexBuffer in m_BuffersToDispose)
- vertexBuffer.Dispose();
-
- m_Buffers.Clear();
- m_BuffersToDispose.Clear();
- }
-
- public NativeByteArray GetBuffer(int id, int bufferSize)
- {
- Profiler.BeginSample("BufferManager.GetBuffer");
- var foundBuffer = m_Buffers.TryGetValue(id, out var buffer);
- if (!foundBuffer)
- buffer = CreateBuffer(id, bufferSize);
-
- Profiler.EndSample();
- return buffer?.GetBuffer(bufferSize);
- }
-
- private VertexBuffer CreateBuffer(int id, int bufferSize)
- {
- if (bufferSize < 1)
- {
- Debug.LogError("Cannot create a buffer smaller than 1 byte.");
- return null;
- }
-
- var buffer = new VertexBuffer(id, bufferSize, needDoubleBuffering);
- m_Buffers.Add(id, buffer);
-
- return buffer;
- }
-
- public void ReturnBuffer(int id)
- {
- Profiler.BeginSample("BufferManager.ReturnBuffer");
- if (m_Buffers.TryGetValue(id, out var buffer))
- {
- buffer.Deactivate();
- m_BuffersToDispose.Enqueue(buffer);
- m_Buffers.Remove(id);
- }
-
- Profiler.EndSample();
- }
-
- private void Update()
- {
- Profiler.BeginSample("BufferManager.Update");
-
- while (m_BuffersToDispose.Count > 0 && m_BuffersToDispose.Peek().IsSafeToDispose())
- {
- var buffer = m_BuffersToDispose.Dequeue();
- buffer.Dispose();
- }
-
- Profiler.EndSample();
- }
- }
- }
|