Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using System.Collections.Generic;
  2. using Unity.Collections;
  3. using UnityEngine.Profiling;
  4. using UnityEngine.Rendering;
  5. #if UNITY_EDITOR
  6. using UnityEditor;
  7. #endif
  8. namespace UnityEngine.U2D.Animation
  9. {
  10. internal class VertexBuffer
  11. {
  12. /// <summary>
  13. /// Number of buffers currently allocated.
  14. /// </summary>
  15. public int bufferCount => m_Buffers.Length;
  16. private readonly int m_Id;
  17. private bool m_IsActive = true;
  18. private int m_DeactivateFrame = -1;
  19. private NativeByteArray[] m_Buffers;
  20. private int m_ActiveIndex = 0;
  21. public VertexBuffer(int id, int size, bool needDoubleBuffering)
  22. {
  23. m_Id = id;
  24. var noOfBuffers = needDoubleBuffering ? 2 : 1;
  25. m_Buffers = new NativeByteArray[noOfBuffers];
  26. for (var i = 0; i < noOfBuffers; i++)
  27. m_Buffers[i] = new NativeByteArray(new NativeArray<byte>(size, Allocator.Persistent, NativeArrayOptions.UninitializedMemory));
  28. }
  29. public override int GetHashCode() => m_Id;
  30. private static int GetCurrentFrame() => Time.frameCount;
  31. public NativeByteArray GetBuffer(int size)
  32. {
  33. if (!m_IsActive)
  34. {
  35. Debug.LogError($"Cannot request deactivated buffer. ID: {m_Id}");
  36. return null;
  37. }
  38. m_ActiveIndex = (m_ActiveIndex + 1) % m_Buffers.Length;
  39. if (m_Buffers[m_ActiveIndex].Length != size)
  40. ResizeBuffer(m_ActiveIndex, size);
  41. return m_Buffers[m_ActiveIndex];
  42. }
  43. private void ResizeBuffer(int bufferId, int newSize)
  44. {
  45. m_Buffers[bufferId].Dispose();
  46. m_Buffers[bufferId] = new NativeByteArray(new NativeArray<byte>(newSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory));
  47. }
  48. public void Deactivate()
  49. {
  50. if (!m_IsActive)
  51. return;
  52. m_IsActive = false;
  53. m_DeactivateFrame = GetCurrentFrame();
  54. }
  55. public void Dispose()
  56. {
  57. for (var i = 0; i < m_Buffers.Length; i++)
  58. {
  59. if (m_Buffers[i].IsCreated)
  60. m_Buffers[i].Dispose();
  61. }
  62. }
  63. public bool IsSafeToDispose() => !m_IsActive && GetCurrentFrame() > m_DeactivateFrame;
  64. }
  65. internal class BufferManager : ScriptableObject
  66. {
  67. private static BufferManager s_Instance;
  68. private Dictionary<int, VertexBuffer> m_Buffers = new Dictionary<int, VertexBuffer>();
  69. private Queue<VertexBuffer> m_BuffersToDispose = new Queue<VertexBuffer>();
  70. /// <summary>
  71. /// Number of buffers currently allocated.
  72. /// </summary>
  73. public int bufferCount
  74. {
  75. get
  76. {
  77. var count = 0;
  78. foreach (var buffer in m_Buffers.Values)
  79. count += buffer.bufferCount;
  80. return count;
  81. }
  82. }
  83. /// <summary>
  84. /// Creates two buffers instead of one if enabled.
  85. /// </summary>
  86. public bool needDoubleBuffering
  87. {
  88. get;
  89. set;
  90. }
  91. public static BufferManager instance
  92. {
  93. get
  94. {
  95. if (s_Instance == null)
  96. {
  97. var bufferMGRs = Resources.FindObjectsOfTypeAll<BufferManager>();
  98. if (bufferMGRs.Length > 0)
  99. s_Instance = bufferMGRs[0];
  100. else
  101. s_Instance = ScriptableObject.CreateInstance<BufferManager>();
  102. s_Instance.hideFlags = HideFlags.HideAndDontSave;
  103. }
  104. return s_Instance;
  105. }
  106. }
  107. private void OnEnable()
  108. {
  109. if (s_Instance == null)
  110. s_Instance = this;
  111. needDoubleBuffering = SystemInfo.renderingThreadingMode != RenderingThreadingMode.Direct;
  112. #if UNITY_EDITOR
  113. EditorApplication.update += Update;
  114. #else
  115. Application.onBeforeRender += Update;
  116. #endif
  117. }
  118. private void OnDisable()
  119. {
  120. if (s_Instance == this)
  121. s_Instance = null;
  122. ForceClearBuffers();
  123. #if UNITY_EDITOR
  124. EditorApplication.update -= Update;
  125. #else
  126. Application.onBeforeRender -= Update;
  127. #endif
  128. }
  129. private void ForceClearBuffers()
  130. {
  131. foreach (var vertexBuffer in m_Buffers.Values)
  132. vertexBuffer.Dispose();
  133. foreach (var vertexBuffer in m_BuffersToDispose)
  134. vertexBuffer.Dispose();
  135. m_Buffers.Clear();
  136. m_BuffersToDispose.Clear();
  137. }
  138. public NativeByteArray GetBuffer(int id, int bufferSize)
  139. {
  140. Profiler.BeginSample("BufferManager.GetBuffer");
  141. var foundBuffer = m_Buffers.TryGetValue(id, out var buffer);
  142. if (!foundBuffer)
  143. buffer = CreateBuffer(id, bufferSize);
  144. Profiler.EndSample();
  145. return buffer?.GetBuffer(bufferSize);
  146. }
  147. private VertexBuffer CreateBuffer(int id, int bufferSize)
  148. {
  149. if (bufferSize < 1)
  150. {
  151. Debug.LogError("Cannot create a buffer smaller than 1 byte.");
  152. return null;
  153. }
  154. var buffer = new VertexBuffer(id, bufferSize, needDoubleBuffering);
  155. m_Buffers.Add(id, buffer);
  156. return buffer;
  157. }
  158. public void ReturnBuffer(int id)
  159. {
  160. Profiler.BeginSample("BufferManager.ReturnBuffer");
  161. if (m_Buffers.TryGetValue(id, out var buffer))
  162. {
  163. buffer.Deactivate();
  164. m_BuffersToDispose.Enqueue(buffer);
  165. m_Buffers.Remove(id);
  166. }
  167. Profiler.EndSample();
  168. }
  169. private void Update()
  170. {
  171. Profiler.BeginSample("BufferManager.Update");
  172. while (m_BuffersToDispose.Count > 0 && m_BuffersToDispose.Peek().IsSafeToDispose())
  173. {
  174. var buffer = m_BuffersToDispose.Dequeue();
  175. buffer.Dispose();
  176. }
  177. Profiler.EndSample();
  178. }
  179. }
  180. }