You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.9 KiB
163 lines
5.9 KiB
using System;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
|
|
namespace UnityEngine.Rendering
|
|
{
|
|
/// <summary>
|
|
/// A list that stores value on a provided memory buffer.
|
|
///
|
|
/// Usually use this to have a list on stack allocated memory.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the data stored in the list.</typeparam>
|
|
public unsafe struct ListBuffer<T>
|
|
where T : unmanaged
|
|
{
|
|
private T* m_BufferPtr;
|
|
private int m_Capacity;
|
|
private int* m_CountPtr;
|
|
|
|
/// <summary>
|
|
/// The pointer to the memory storage.
|
|
/// </summary>
|
|
internal T* BufferPtr => m_BufferPtr;
|
|
|
|
/// <summary>
|
|
/// The number of item in the list.
|
|
/// </summary>
|
|
public int Count => *m_CountPtr;
|
|
|
|
/// <summary>
|
|
/// The maximum number of item stored in this list.
|
|
/// </summary>
|
|
public int Capacity => m_Capacity;
|
|
|
|
/// <summary>
|
|
/// Instantiate a new list.
|
|
/// </summary>
|
|
/// <param name="bufferPtr">The address in memory to store the data.</param>
|
|
/// <param name="countPtr">The address in memory to store the number of item of this list..</param>
|
|
/// <param name="capacity">The number of <typeparamref name="T"/> that can be stored in the buffer.</param>
|
|
public ListBuffer(T* bufferPtr, int* countPtr, int capacity)
|
|
{
|
|
m_BufferPtr = bufferPtr;
|
|
m_Capacity = capacity;
|
|
m_CountPtr = countPtr;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get an item from the list.
|
|
/// </summary>
|
|
/// <param name="index">The index of the item to get.</param>
|
|
/// <value>A reference to the item.</value>
|
|
/// <exception cref="IndexOutOfRangeException">If the index is invalid.</exception>
|
|
public ref T this[in int index]
|
|
{
|
|
get
|
|
{
|
|
if (index < 0 || index >= Count)
|
|
throw new IndexOutOfRangeException(
|
|
$"Expected a value between 0 and {Count}, but received {index}.");
|
|
return ref m_BufferPtr[index];
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get an item from the list.
|
|
///
|
|
/// Safety: index must be inside the bounds of the list.
|
|
/// </summary>
|
|
/// <param name="index">The index of the item to get.</param>
|
|
/// <returns>A reference to the item.</returns>
|
|
public unsafe ref T GetUnchecked(in int index) => ref m_BufferPtr[index];
|
|
|
|
/// <summary>
|
|
/// Try to add a value in the list.
|
|
/// </summary>
|
|
/// <param name="value">A reference to the value to add.</param>
|
|
/// <returns>
|
|
/// <c>true</c> when the value was added,
|
|
/// <c>false</c> when the value was not added because the capacity was reached.
|
|
/// </returns>
|
|
public bool TryAdd(in T value)
|
|
{
|
|
if (Count >= m_Capacity)
|
|
return false;
|
|
|
|
m_BufferPtr[Count] = value;
|
|
++*m_CountPtr;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the content of this list into another buffer in memory.
|
|
///
|
|
/// Safety:
|
|
/// * The destination must have enough memory to receive the copied data.
|
|
/// </summary>
|
|
/// <param name="dstBuffer">The destination buffer of the copy operation.</param>
|
|
/// <param name="startDstIndex">The index of the first element that will be copied in the destination buffer.</param>
|
|
/// <param name="copyCount">The number of item to copy.</param>
|
|
public unsafe void CopyTo(T* dstBuffer, int startDstIndex, int copyCount)
|
|
{
|
|
UnsafeUtility.MemCpy(dstBuffer + startDstIndex, m_BufferPtr,
|
|
UnsafeUtility.SizeOf<T>() * copyCount);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to copy the list into another list.
|
|
/// </summary>
|
|
/// <param name="other">The destination of the copy.</param>
|
|
/// <returns>
|
|
/// * <c>true</c> when the copy was performed.
|
|
/// * <c>false</c> when the copy was aborted because the destination have a capacity too small.
|
|
/// </returns>
|
|
public bool TryCopyTo(ListBuffer<T> other)
|
|
{
|
|
if (other.Count + Count >= other.m_Capacity)
|
|
return false;
|
|
|
|
UnsafeUtility.MemCpy(other.m_BufferPtr + other.Count, m_BufferPtr, UnsafeUtility.SizeOf<T>() * Count);
|
|
*other.m_CountPtr += Count;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to copy the data from a buffer in this list.
|
|
/// </summary>
|
|
/// <param name="srcPtr">The pointer of the source memory to copy.</param>
|
|
/// <param name="count">The number of item to copy from the source buffer.</param>
|
|
/// <returns>
|
|
/// * <c>true</c> when the copy was performed.
|
|
/// * <c>false</c> when the copy was aborted because the capacity of this list is too small.
|
|
/// </returns>
|
|
public bool TryCopyFrom(T* srcPtr, int count)
|
|
{
|
|
if (count + Count > m_Capacity)
|
|
return false;
|
|
|
|
UnsafeUtility.MemCpy(m_BufferPtr + Count, srcPtr, UnsafeUtility.SizeOf<T>() * count);
|
|
*m_CountPtr += count;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extensions for <see cref="ListBuffer{T}"/>.
|
|
/// </summary>
|
|
public static class ListBufferExtensions
|
|
{
|
|
/// <summary>
|
|
/// Perform a quick sort on a <see cref="ListBuffer{T}"/>.
|
|
/// </summary>
|
|
/// <param name="self">The list to sort.</param>
|
|
/// <typeparam name="T">The type of the element in the list.</typeparam>
|
|
public static void QuickSort<T>(this ListBuffer<T> self)
|
|
where T : unmanaged, IComparable<T>
|
|
{
|
|
unsafe
|
|
{
|
|
CoreUnsafeUtils.QuickSort<int>(self.Count, self.BufferPtr);
|
|
}
|
|
}
|
|
}
|
|
}
|