123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- using System;
- using System.Collections;
- using System.Runtime.InteropServices;
- using Unity.Collections;
- using UnityEngine.Assertions;
-
- namespace UnityEngine.Rendering.UnifiedRayTracing
- {
- internal class PersistentGpuArray<Tstruct> : IDisposable
- where Tstruct : struct
- {
- BlockAllocator m_SlotAllocator;
- ComputeBuffer m_GpuBuffer;
- NativeArray<Tstruct> m_CpuList;
- BitArray m_Updates;
- bool m_gpuBufferDirty = true;
- int m_ElementCount = 0;
- public int elementCount { get { return m_ElementCount; } }
-
- public PersistentGpuArray(int initialSize)
- {
- m_SlotAllocator.Initialize(initialSize);
- m_GpuBuffer = new ComputeBuffer(initialSize, Marshal.SizeOf<Tstruct>());
- m_CpuList = new NativeArray<Tstruct>(initialSize, Allocator.Persistent);
- m_Updates = new BitArray(initialSize);
- m_ElementCount = 0;
- }
-
- public void Dispose()
- {
- m_ElementCount = 0;
- m_SlotAllocator.Dispose();
- m_GpuBuffer.Dispose();
- m_CpuList.Dispose();
- }
-
- public BlockAllocator.Allocation Add(Tstruct element)
- {
- m_ElementCount++;
- var slotAllocation = m_SlotAllocator.Allocate(1);
- if (!slotAllocation.valid)
- {
- Grow();
- slotAllocation = m_SlotAllocator.Allocate(1);
- Assert.IsTrue(slotAllocation.valid);
- }
- m_CpuList[slotAllocation.block.offset] = element;
- m_Updates[slotAllocation.block.offset] = true;
- m_gpuBufferDirty = true;
-
- return slotAllocation;
- }
-
- public void Remove(BlockAllocator.Allocation allocation)
- {
- m_ElementCount--;
- m_SlotAllocator.FreeAllocation(allocation);
- }
-
- public void Clear()
- {
- m_ElementCount = 0;
- var currentCapacity = m_SlotAllocator.capacity;
- m_SlotAllocator.Dispose();
- m_SlotAllocator = new BlockAllocator();
- m_SlotAllocator.Initialize(currentCapacity);
- m_Updates = new BitArray(currentCapacity);
- m_gpuBufferDirty = false;
- }
-
- public void Set(BlockAllocator.Allocation allocation, Tstruct element)
- {
- m_CpuList[allocation.block.offset] = element;
- m_Updates[allocation.block.offset] = true;
- }
-
- public Tstruct Get(BlockAllocator.Allocation allocation)
- {
- return m_CpuList[allocation.block.offset];
- }
-
- public void ModifyForEach(Func<Tstruct, Tstruct> lambda)
- {
- for (int i = 0; i < m_CpuList.Length; ++i)
- {
- m_CpuList[i] = lambda(m_CpuList[i]);
- m_Updates[i] = true;
- }
- m_gpuBufferDirty = true;
- }
-
- // Note: this should ideally be used with only one command buffer. If used with more than one cmd buffers, the order of their execution is important.
- public ComputeBuffer GetGpuBuffer(CommandBuffer cmd)
- {
- if (m_gpuBufferDirty)
- {
- int copyStartIndex = -1;
- for (int i = 0; i < m_Updates.Length; ++i)
- {
- if (m_Updates[i])
- {
- if (copyStartIndex == -1)
- copyStartIndex = i;
-
- m_Updates[i] = false;
- }
- else if (copyStartIndex != -1)
- {
- int copyEndIndex = i;
- cmd.SetBufferData(m_GpuBuffer, m_CpuList, copyStartIndex, copyStartIndex, copyEndIndex - copyStartIndex);
- copyStartIndex = -1;
- }
- }
-
- if (copyStartIndex != -1)
- {
- int copyEndIndex = m_Updates.Length;
- cmd.SetBufferData(m_GpuBuffer, m_CpuList, copyStartIndex, copyStartIndex, copyEndIndex - copyStartIndex);
- }
-
- m_gpuBufferDirty = false;
- }
-
- return m_GpuBuffer;
- }
-
- private void Grow()
- {
- var oldCapacity = m_SlotAllocator.capacity;
- m_SlotAllocator.Grow(m_SlotAllocator.capacity + 1);
-
- m_GpuBuffer.Dispose();
- m_GpuBuffer = new ComputeBuffer(m_SlotAllocator.capacity, Marshal.SizeOf<Tstruct>());
-
- var oldList = m_CpuList;
- m_CpuList = new NativeArray<Tstruct>(m_SlotAllocator.capacity, Allocator.Persistent);
- NativeArray<Tstruct>.Copy(oldList, m_CpuList, oldCapacity);
- oldList.Dispose();
-
- var oldUpdates = m_Updates;
- m_Updates = new BitArray(m_SlotAllocator.capacity);
- for (int i = 0; i < oldCapacity; ++i)
- m_Updates[i] = oldUpdates[i];
- }
- }
- }
|