/// <summary> /// Adds a range of items to the end of the list /// </summary> /// <param name="range"></param> public void AddRange(IEnumerable <T> range) { if (range == null) { throw new ArgumentNullException(); } int dataSize = Marshal.SizeOf(typeof(T)); if (range is GPUList <T> && range != this) { GPUList <T> list = range as GPUList <T>; if (list.Count == 0) { return; } if (Count + list.Count > Capacity) { setCapacity(2 * Count + list.Count); } count += list.Count; list.CopyRangeTo(0, list.Count, this, Count - list.Count); } else { T[] data = null; if (range is T[]) { data = (T[])range; } else if (range is List <T> ) { data = (range as List <T>).ToArray(); } else { List <T> dataList = new List <T>(range); data = dataList.ToArray(); } if (data.Length == 0) { return; } if (Count + data.Length > Capacity) { setCapacity(2 * Count + data.Length); } count += data.Length; SetRange(Count - data.Length, data, 0, data.Length); } }
/// <summary> /// Copies a range of data to another GPUList /// </summary> /// <param name="index">Index from which to start copying</param> /// <param name="count">Number of elements to copy</param> /// <param name="list">Destination list to copy to</param> /// <param name="listIndex">Destination list index to copy to</param> public void CopyRangeTo(int index, int count, GPUList <T> list, int listIndex) { if (count == 0) { return; } if (list == this) { throw new Exception("Cannot copy range into self...yet"); } if (count < 0) { throw new IndexOutOfRangeException(); } if (index < 0 || index >= Count) { throw new IndexOutOfRangeException(); } if (index + count < 0 || index + count > Count) { throw new IndexOutOfRangeException(); } if (list == null) { throw new ArgumentNullException(); } if (listIndex < 0 || listIndex >= list.Count) { throw new IndexOutOfRangeException(); } if (listIndex + list.Count < 0 || listIndex + count > list.Count) { throw new IndexOutOfRangeException(); } int dataSize = Marshal.SizeOf(typeof(T)); context.CopySubresourceRegion(buffer, 0, new ResourceRegion(dataSize * index, 0, 0, dataSize * (index + count), 1, 1), list.buffer, 0, dataSize * listIndex, 0, 0); }
/// <summary> /// Removes a range of items from the list /// </summary> /// <param name="index">Index to start removing</param> /// <param name="count">Number of items to remove</param> public void RemoveRange(int index, int count) { if (count == 0) { return; } if (count < 0) { throw new IndexOutOfRangeException(); } if (index < 0 || index >= Count) { throw new IndexOutOfRangeException(); } if (index + count < 0 || index + count > Count) { throw new IndexOutOfRangeException(); } if (index + count == Count) { this.count -= count; return; } GPUList <T> newList = new GPUList <T>(Context, Capacity); newList.count = this.count - count; this.CopyRangeTo(0, index, newList, 0); this.CopyRangeTo(index + count, this.count - (index + count), newList, index); setCapacity(0); this.count = newList.count; this.capacity = newList.capacity; this.buffer = newList.buffer; this.shaderResourceView = newList.shaderResourceView; this.unorderedAccessView = newList.unorderedAccessView; }
/// <summary> /// Copys the list to another GPUList /// </summary> /// <param name="array">The list to copy data to</param> /// <param name="arrayIndex">The starting index in the array</param> public void CopyTo(GPUList <T> list, int listIndex) { CopyRangeTo(0, count, list, listIndex); }
/// <summary> /// Inserts a range of items into the list /// </summary> /// <param name="index">Position in the list to insert items</param> /// <param name="range">The range of items to insert</param> public void InsertRange(int index, IEnumerable <T> range) { if (range == null) { throw new ArgumentNullException(); } if (index < 0 || index > Count) { throw new IndexOutOfRangeException(); } if (index == Count) { AddRange(range); } else { GPUList <T> newList = null; if (range is GPUList <T> ) { GPUList <T> list = range as GPUList <T>; if (list.Count == 0) { return; } newList = new GPUList <T>(Context, list.Count + Count); newList.count = list.Count + Count; this.CopyRangeTo(0, index, newList, 0); list.CopyTo(newList, index); this.CopyRangeTo(index, Count - index, newList, index + list.Count); } else { T[] data = null; if (range is T[]) { data = (T[])range; } else if (range is List <T> ) { data = (range as List <T>).ToArray(); } else { List <T> dataList = new List <T>(range); data = dataList.ToArray(); } if (data.Length == 0) { return; } newList = new GPUList <T>(Context, data.Length + Count); newList.count = data.Length + Count; this.CopyRangeTo(0, index, newList, 0); newList.SetRange(index, data, 0, data.Length); this.CopyRangeTo(index, Count - index, newList, index + data.Length); } setCapacity(0); count = newList.count; capacity = newList.capacity; buffer = newList.buffer; shaderResourceView = newList.shaderResourceView; unorderedAccessView = newList.unorderedAccessView; } }