Example #1
0
        /// <summary>
        /// Copies data from a source <see cref="DataBufferSubset{T}"/> to a destination <see cref="DataBufferSubset{T}"/>.
        /// </summary>
        /// <param name="source">The <see cref="DataBufferSubset{T}"/> to copy data from.</param>
        /// <param name="sourceOffset">The index of the first element to copy from the source subset.</param>
        /// <param name="dest">The <see cref="DataBufferSubset{T}"/> to write data to.</param>
        /// <param name="destOffset">The index of of the first element to write on the dest subset.</param>
        /// <param name="dataLength">The amount of elements to copy.</param>
        public static void CopyBuffers <T>(DataBufferSubset <T> source, uint sourceOffset, DataBufferSubset <T> dest, uint destOffset, uint dataLength) where T : unmanaged
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            GraphicsDevice g = source.Buffer.GraphicsDevice;

            if (g != dest.Buffer.GraphicsDevice)
            {
                throw new InvalidOperationException("You can't copy data between buffers from different " + nameof(GraphicsDevice) + "-s");
            }

            if (sourceOffset < 0 || sourceOffset > source.StorageLength)
            {
                throw new ArgumentOutOfRangeException(nameof(sourceOffset), sourceOffset, nameof(sourceOffset) + " must be in the range [0, " + nameof(source.StorageLength) + ")");
            }

            if (destOffset < 0 || destOffset > dest.StorageLength)
            {
                throw new ArgumentOutOfRangeException(nameof(destOffset), destOffset, nameof(destOffset) + " must be in the range [0, " + nameof(dest.StorageLength) + ")");
            }

            if (sourceOffset + dataLength > source.StorageLength)
            {
                throw new BufferCopyException("There isn't enough data in the source buffer to copy " + nameof(dataLength) + " elements");
            }

            if (destOffset + dataLength > dest.StorageLength)
            {
                throw new BufferCopyException("There isn't enough data in the dest buffer to copy " + nameof(dataLength) + " elements");
            }

            uint elementSize = source.ElementSize;
            int  sourceStart = (int)(source.StorageOffsetInBytes + sourceOffset * elementSize);
            int  destStart   = (int)(dest.StorageOffsetInBytes + destOffset * elementSize);

            if (source.Buffer == dest.Buffer)
            {
                // We're copying from and to the same buffer? Let's ensure the sections don't overlap then
                int dataLengthBytes = (int)(dataLength * elementSize);
                if (sourceStart < destStart + dataLengthBytes && sourceStart + dataLengthBytes > destStart)
                {
                    throw new BufferCopyException("When copying to and from the same " + nameof(BufferObject) + ", the ranges must not overlap");
                }
            }

            // Everything looks fine, let's perform the copy operation!
            g.CopyReadBuffer  = source.Buffer;
            g.CopyWriteBuffer = dest.Buffer;
            source.Buffer.GL.CopyBufferSubData(CopyBufferSubDataTarget.CopyReadBuffer, CopyBufferSubDataTarget.CopyWriteBuffer, sourceStart, destStart, dataLength * elementSize);
        }
Example #2
0
        /// <summary>
        /// Copies all the data from a source <see cref="DataBufferSubset{T}"/> to a destination <see cref="DataBufferSubset{T}"/>.
        /// </summary>
        /// <param name="source">The <see cref="DataBufferSubset{T}"/> to copy data from.</param>
        /// <param name="dest">The <see cref="DataBufferSubset{T}"/> to write data to.</param>
        public static void CopyBuffers <T>(DataBufferSubset <T> source, DataBufferSubset <T> dest) where T : unmanaged
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            CopyBuffers(source, 0, dest, 0, source.StorageLength);
        }
Example #3
0
 private static VertexAttribSource[] MakeAttribList(DataBufferSubset bufferSubset, ReadOnlySpan <VertexAttribDescription> attribDescriptions)
 {
     VertexAttribSource[] sources = new VertexAttribSource[attribDescriptions.Length];
     for (int i = 0; i < sources.Length; i++)
     {
         sources[i] = new VertexAttribSource(bufferSubset, attribDescriptions[i]);
     }
     return(sources);
 }
        /// <summary>
        /// Creates a <see cref="VertexAttribSource"/> that represents padding. This means that the created
        /// <see cref="VertexAttribSource"/> will not indicate a buffer to read data from or use a vertex
        /// attribute index, it will just leave an ignored space between other attributes.
        /// </summary>
        /// <param name="bufferSubset">The <see cref="BufferObjectSubset"/> where the padding will be added.</param>
        /// <param name="paddingBytes">The amount of space to leave empty, measured in bytes.</param>
        public VertexAttribSource(DataBufferSubset bufferSubset, uint paddingBytes)
        {
            if (bufferSubset == null)
            {
                throw new ArgumentNullException(nameof(bufferSubset));
            }

            if (bufferSubset.BufferTarget != BufferTargetARB.ArrayBuffer)
            {
                throw new ArgumentException("The specified BufferObjectSubset must be usable as vertex attrib data. Try using a VertexDataBufferSubset", nameof(bufferSubset));
            }

            BufferSubset      = bufferSubset;
            AttribDescription = new VertexAttribDescription(paddingBytes);
        }
Example #5
0
        /// <summary>
        /// Creates a <see cref="VertexAttribSource"/> with a given <see cref="BufferObjectSubset"/>
        /// and the given <see cref="VertexAttribDescription"/>.
        /// </summary>
        /// <param name="bufferSubset">The <see cref="BufferObjectSubset"/> where the vertex attrib data is located. Must be a subset usable for vertex data.</param>
        /// <param name="attribDesc">The <see cref="VertexAttribDescription"/> describing the vertex attribute.</param>
        public VertexAttribSource(DataBufferSubset bufferSubset, VertexAttribDescription attribDesc)
        {
            if (bufferSubset == null)
            {
                throw new ArgumentNullException(nameof(bufferSubset));
            }

            if (bufferSubset.BufferTarget != BufferTarget.ArrayBuffer)
            {
                throw new ArgumentException("The specified " + nameof(BufferObjectSubset) + " must be usable as vertex attrib data. Try using a VertexDataBufferSubset", nameof(bufferSubset));
            }

            BufferSubset      = bufferSubset;
            AttribDescription = attribDesc;
        }
 /// <summary>
 /// Creates a <see cref="VertexAttribSource"/> with a given <see cref="BufferObjectSubset"/> and specifies
 /// a vertex attribute where the data format in the shader and the buffer don't match and need conversion.
 /// </summary>
 /// <param name="bufferSubset">The <see cref="BufferObjectSubset"/> where the vertex attrib data is located. Must be a subset usable for vertex data.</param>
 /// <param name="attribType">The type of attribute declared in the shader.</param>
 /// <param name="normalized">Whether the data needs to be normalized (uint/ushort/byte -> float between 0 and 1, or int/short/sbyte -> float between -1 and 1).</param>
 /// <param name="dataBaseType">The base type of the data found on the buffer. If normalized is true, this must be an integer type.</param>
 /// <param name="attribDivisor">The divisor that defines how reading this attribute advances on instanced rendering.</param>
 public VertexAttribSource(DataBufferSubset bufferSubset, AttributeType attribType, bool normalized, VertexAttribPointerType dataBaseType, uint attribDivisor = 0)
     : this(bufferSubset, new VertexAttribDescription(attribType, normalized, dataBaseType, attribDivisor))
 {
 }
 /// <summary>
 /// Creates a <see cref="VertexAttribSource"/> with a given <see cref="BufferObjectSubset"/> and specifies a
 /// vertex attribute where the data format in the shader and the buffer match and don't need conversion.
 /// </summary>
 /// <param name="bufferSubset">The <see cref="BufferObjectSubset"/> where the vertex attrib data is located. Must be a subset usable for vertex data.</param>
 /// <param name="attribType">The type of attribute declared in the shader.</param>
 /// <param name="attribDivisor">The divisor that defines how reading this attribute advances on instanced rendering.</param>
 public VertexAttribSource(DataBufferSubset bufferSubset, AttributeType attribType, uint attribDivisor = 0)
     : this(bufferSubset, new VertexAttribDescription(attribType, attribDivisor))
 {
 }
 /// <summary>
 /// Creates a <see cref="VertexAttribSource"/> that specifies padding for the amount
 /// of bytes used by a specified <see cref="AttributeType"/>.
 /// </summary>
 /// <param name="bufferSubset">The buffer subset in which the padding will be applied.</param>
 /// <param name="attribType">The type of the attribute, for calculating paddign.</param>
 /// <remarks>
 /// Padding indicators ignore padding based on type that occurs when using compensation
 /// for struct padding (which is the default behavior in <see cref="VertexArray"/>).
 /// </remarks>
 public static VertexAttribSource CreatePadding(DataBufferSubset bufferSubset, AttributeType attribType)
 {
     return(new VertexAttribSource(bufferSubset, VertexAttribDescription.CreatePadding(attribType)));
 }
 /// <summary>
 /// Creates a <see cref="VertexAttribSource"/> that specifies padding for an
 /// amount of bytes calculated based on the baseType and size parameters.
 /// </summary>
 /// <param name="bufferSubset">The buffer subset in which the padding will be applied.</param>
 /// <param name="baseType">The base type of the attribute.</param>
 /// <param name="size">The size of the attribute.</param>
 public static VertexAttribSource CreatePadding(DataBufferSubset bufferSubset, VertexAttribPointerType baseType, uint size)
 {
     return(new VertexAttribSource(bufferSubset, VertexAttribDescription.CreatePadding(baseType, size)));
 }
Example #10
0
 /// <summary>
 /// Creates a <see cref="VertexArray"/> in which all the vertex attributes come interleaved from the same data buffer.
 /// </summary>
 /// <param name="graphicsDevice">The <see cref="GraphicsDevice"/> this resource will use.</param>
 /// <param name="bufferSubset">The data buffer that stores all the vertex attributes.</param>
 /// <param name="attribDescriptions">The descriptions of the vertex attributes.</param>
 /// <param name="indexBuffer">An index buffer to attach to the vertex array, null if none is desired.</param>
 /// <param name="compensateStructPadding">Whether to compensate for struct padding. Default is true.</param>
 /// <param name="paddingPackValue">The struct packing value for compensating for padding. Default is 4.</param>
 public VertexArray(GraphicsDevice graphicsDevice, DataBufferSubset bufferSubset, ReadOnlySpan <VertexAttribDescription> attribDescriptions, IndexBufferSubset indexBuffer = null, bool compensateStructPadding = true, uint paddingPackValue = 4)
     : this(graphicsDevice, MakeAttribList(bufferSubset, attribDescriptions), indexBuffer, compensateStructPadding, paddingPackValue)
 {
 }
Example #11
0
        /// <summary>
        /// Creates a <see cref="VertexArray"/> for the specified vertex type, where all of the vertex attributes come interleaved from the same buffer subset.
        /// </summary>
        /// <typeparam name="T">The type of vertex to use.</typeparam>
        /// <param name="graphicsDevice">The <see cref="GraphicsDevice"/> this resource will use.</param>
        /// <param name="dataBuffer">The buffer from which all attributes come from.</param>
        /// <param name="indexBuffer">An index buffer to attach to the vertex array, null if none is desired.</param>
        /// <param name="compensateStructPadding">Whether to compensate for struct padding. Default is true.</param>
        /// <param name="paddingPackValue">The struct packing value for compensating for padding. Default is 4.</param>
        public static VertexArray CreateSingleBuffer <T>(GraphicsDevice graphicsDevice, DataBufferSubset dataBuffer, IndexBufferSubset indexBuffer = null, bool compensateStructPadding = true, uint paddingPackValue = 4) where T : unmanaged, IVertex
        {
            T   t           = default;
            int attribCount = t.AttribDescriptionCount;
            Span <VertexAttribDescription> attribDescriptions = attribCount > 32 ?
                                                                new VertexAttribDescription[attribCount] : stackalloc VertexAttribDescription[attribCount];

            t.WriteAttribDescriptions(attribDescriptions);

            return(new VertexArray(graphicsDevice, dataBuffer, attribDescriptions, indexBuffer, compensateStructPadding, paddingPackValue));
        }