/// <summary> /// Initializes a portion of the buffer's data with the specified data. /// </summary> /// <typeparam name="T">The type of each item.</typeparam> /// <param name="data">The data used to initialize the buffer's data.</param> /// <param name="offsetInBytes">The offset where data replacement will begin</param> /// <exception cref="ArgumentOutOfRangeException">The specified range includes data /// outside the buffer's current capacity.</exception> public void SetSubData <T>(T data, int offsetInBytes) where T : struct { int itemSizeInBytes = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); if (!BufferValidation.IsValidAccess(offsetInBytes, itemSizeInBytes, 1, SizeInBytes)) { throw new ArgumentOutOfRangeException("", BufferExceptionMessages.outOfRange); } Bind(); GL.BufferSubData(Target, new IntPtr(offsetInBytes), itemSizeInBytes, ref data); }
/// <summary> /// Binds the buffer and reads <paramref name="itemCount"/> elements of type <typeparamref name="T"/> /// starting at <paramref name="offsetInBytes"/>. /// </summary> /// <typeparam name="T">The type of each item. This includes arithmetic types like <see cref="int"/>.</typeparam> /// <param name="offsetInBytes">The starting offset for reading</param> /// <param name="itemCount">The number of items of type <typeparamref name="T"/> to read.</param> /// <returns>An array of size <paramref name="itemCount"/></returns> /// <exception cref="ArgumentOutOfRangeException">The specified range includes data outside the buffer's current capacity.</exception> public T[] GetSubData <T>(int offsetInBytes, int itemCount) where T : struct { int itemSizeInBytes = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); if (!BufferValidation.IsValidAccess(offsetInBytes, itemSizeInBytes, itemCount, SizeInBytes)) { throw new ArgumentOutOfRangeException("", BufferExceptionMessages.outOfRange); } Bind(); T[] data = new T[itemCount]; GL.GetBufferSubData(Target, new IntPtr(offsetInBytes), itemCount * itemSizeInBytes, data); return(data); }
/// <summary> /// Configures the data source for a floating point vertex attribute. /// An exception is thrown if the specified parameters would result in an invalid buffer access. /// </summary> /// <param name="vertexAttribute">The vertex attribute information></param> /// <param name="bufferName">The name of the buffer used for <see cref="AddBuffer{T}(string, T[])"/></param> /// <param name="offsetInBytes">The offset in bytes for the start of the vertex data in the buffer</param> /// <param name="strideInBytes">The stride in bytes for the buffer data</param> /// <exception cref="ArgumentOutOfRangeException">The specified parameters would result in an invalid buffer access.</exception> public void ConfigureAttribute(VertexAttribute vertexAttribute, string bufferName, int offsetInBytes, int strideInBytes) { if (strideInBytes < 0) { throw new ArgumentOutOfRangeException(nameof(strideInBytes), invalidAccessMessage); } if (!bufferByName.ContainsKey(bufferName)) { throw new ArgumentException($"The buffer {bufferName} has not been added.", nameof(bufferName)); } var buffer = bufferByName[bufferName]; var elementSize = AttribPointerUtils.GetSizeInBytes(vertexAttribute.Type) * (int)vertexAttribute.ValueCount; if (!BufferValidation.IsValidAccess(offsetInBytes, strideInBytes, elementSize, VertexCount, buffer.SizeInBytes)) { throw new ArgumentOutOfRangeException("", invalidAccessMessage); } // Associate attributes with the appropriate buffer, so the buffer can be bound later. attributesByBuffer[buffer].Add(new VertexAttributeExtended(vertexAttribute, offsetInBytes, strideInBytes)); }
public void NegativeElementSize() { Assert.IsFalse(BufferValidation.IsValidAccess(0, 4, -4, 4, 16)); }
public void ValidWriteEmptyBuffer() { Assert.IsTrue(BufferValidation.IsValidAccess(0, 0, 0, 0)); }
public void ElementSizeLessThanStride() { // The difference between stride and element size is just padding and won't actually be read for the last element. // Read: element + pad 1 + element + pad 1 + element + pad 1 + element + *skip padding* = 19 bytes Assert.IsTrue(BufferValidation.IsValidAccess(0, 5, 4, 4, 19)); }
public void ElementSizeGreaterThanStride() { // The element size is valid but the stride is not. Assert.IsFalse(BufferValidation.IsValidAccess(0, 3, 4, 4, 16)); }
public void NegativeElementCountNegativeStride() { // This may work for a naive implementation. Assert.IsFalse(BufferValidation.IsValidAccess(0, -4, -4, 16)); }
public void NegativeLength() { // This may work for a naive implementation. Assert.IsFalse(BufferValidation.IsValidAccess(0, -4, 4, -16)); }
public void NegativeStride() { Assert.IsFalse(BufferValidation.IsValidAccess(0, -4, 4, 16)); }
public void ReadOnePastEnd() { Assert.IsFalse(BufferValidation.IsValidAccess(1, 4, 4, 16)); }
public void ReadHalfBuffer() { Assert.IsTrue(BufferValidation.IsValidAccess(8, 4, 2, 16)); }
public void ReadWholeBuffer() { Assert.IsTrue(BufferValidation.IsValidAccess(0, 4, 4, 16)); }
public void NegativeOffset() { Assert.IsFalse(BufferValidation.IsValidAccess(-4, 4, 4, 32)); }