123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- using System;
- using System.Runtime.InteropServices;
- using Unity.Collections;
- using UnityEngine.Rendering.Universal.Internal;
- namespace UnityEngine.Rendering.Universal
- {
- class DeferredShaderData : IDisposable
- {
- static DeferredShaderData m_Instance = null;
- struct ComputeBufferInfo
- {
- public uint frameUsed;
- public ComputeBufferType type; // There is no interface to retrieve the type of a ComputeBuffer, so we must save it on our side
- }
- // Precomputed tiles (for each tiler).
- NativeArray<PreTile>[] m_PreTiles = null;
- // Structured buffers and constant buffers are all allocated from this array.
- ComputeBuffer[] m_Buffers = null;
- // We need to store extra info per ComputeBuffer.
- ComputeBufferInfo[] m_BufferInfos;
- // How many buffers have been created so far. This is <= than m_Buffers.Length.
- int m_BufferCount = 0;
- // Remember index of last buffer used. This optimizes the search for available buffer.
- int m_CachedBufferIndex = 0;
- // This counter is allowed to cycle back to 0.
- uint m_FrameIndex = 0;
- DeferredShaderData()
- {
- m_PreTiles = new NativeArray<PreTile>[DeferredConfig.kTilerDepth];
- m_Buffers = new ComputeBuffer[64];
- m_BufferInfos = new ComputeBufferInfo[64];
- }
- internal static DeferredShaderData instance
- {
- get
- {
- if (m_Instance == null)
- m_Instance = new DeferredShaderData();
- return m_Instance;
- }
- }
- public void Dispose()
- {
- DisposeNativeArrays(ref m_PreTiles);
- for (int i = 0; i < m_Buffers.Length; ++i)
- {
- if (m_Buffers[i] != null)
- {
- m_Buffers[i].Dispose();
- m_Buffers[i] = null;
- }
- }
- m_BufferCount = 0;
- }
- internal void ResetBuffers()
- {
- ++m_FrameIndex; // Allowed to cycle back to 0.
- }
- internal NativeArray<PreTile> GetPreTiles(int level, int count)
- {
- return GetOrUpdateNativeArray<PreTile>(ref m_PreTiles, level, count);
- }
- internal ComputeBuffer ReserveBuffer<T>(int count, bool asCBuffer) where T : struct
- {
- int stride = Marshal.SizeOf<T>();
- int paddedCount = asCBuffer ? Align(stride * count, 16) / stride : count;
- return GetOrUpdateBuffer(paddedCount, stride, asCBuffer);
- }
- NativeArray<T> GetOrUpdateNativeArray<T>(ref NativeArray<T>[] nativeArrays, int level, int count) where T : struct
- {
- if (!nativeArrays[level].IsCreated)
- {
- nativeArrays[level] = new NativeArray<T>(count, Allocator.Persistent);
- }
- else if (count > nativeArrays[level].Length)
- {
- nativeArrays[level].Dispose();
- nativeArrays[level] = new NativeArray<T>(count, Allocator.Persistent);
- }
- return nativeArrays[level];
- }
- void DisposeNativeArrays<T>(ref NativeArray<T>[] nativeArrays) where T : struct
- {
- for (int i = 0; i < nativeArrays.Length; ++i)
- {
- if (nativeArrays[i].IsCreated)
- nativeArrays[i].Dispose();
- }
- }
- ComputeBuffer GetOrUpdateBuffer(int count, int stride, bool isConstantBuffer)
- {
- ComputeBufferType type = isConstantBuffer ? ComputeBufferType.Constant : ComputeBufferType.Structured;
- #if UNITY_SWITCH // maxQueuedFrames returns -1 on Switch!
- int maxQueuedFrames = 3;
- #else
- int maxQueuedFrames = QualitySettings.maxQueuedFrames;
- Assertions.Assert.IsTrue(maxQueuedFrames >= 1, "invalid QualitySettings.maxQueuedFrames");
- #endif
- for (int i = 0; i < m_BufferCount; ++i)
- {
- int bufferIndex = (m_CachedBufferIndex + i + 1) % m_BufferCount;
- if (IsLessCircular(m_BufferInfos[bufferIndex].frameUsed + (uint)maxQueuedFrames, m_FrameIndex)
- && m_BufferInfos[bufferIndex].type == type && m_Buffers[bufferIndex].count == count && m_Buffers[bufferIndex].stride == stride)
- {
- m_BufferInfos[bufferIndex].frameUsed = m_FrameIndex;
- m_CachedBufferIndex = bufferIndex;
- return m_Buffers[bufferIndex];
- }
- }
- if (m_BufferCount == m_Buffers.Length) // If all buffers used: allocate more space.
- {
- ComputeBuffer[] newBuffers = new ComputeBuffer[m_BufferCount * 2];
- for (int i = 0; i < m_BufferCount; ++i)
- newBuffers[i] = m_Buffers[i];
- m_Buffers = newBuffers;
- ComputeBufferInfo[] newBufferInfos = new ComputeBufferInfo[m_BufferCount * 2];
- for (int i = 0; i < m_BufferCount; ++i)
- newBufferInfos[i] = m_BufferInfos[i];
- m_BufferInfos = newBufferInfos;
- }
- // Create new buffer.
- m_Buffers[m_BufferCount] = new ComputeBuffer(count, stride, type, ComputeBufferMode.Immutable);
- m_BufferInfos[m_BufferCount].frameUsed = m_FrameIndex;
- m_BufferInfos[m_BufferCount].type = type;
- m_CachedBufferIndex = m_BufferCount;
- return m_Buffers[m_BufferCount++];
- }
- void DisposeBuffers(ComputeBuffer[,] buffers)
- {
- for (int i = 0; i < buffers.GetLength(0); ++i)
- {
- for (int j = 0; j < buffers.GetLength(1); ++j)
- {
- if (buffers[i, j] != null)
- {
- buffers[i, j].Dispose();
- buffers[i, j] = null;
- }
- }
- }
- }
- static bool IsLessCircular(uint a, uint b)
- {
- return a != b ? (b - a) < 0x80000000 : false;
- }
- static int Align(int s, int alignment)
- {
- return ((s + alignment - 1) / alignment) * alignment;
- }
- }
- }
|