/// <summary>
        /// Creates a new instance of <see cref="VertexBufferImplementation"/>.
        /// </summary>
        /// <param name="vertexDeclaration">The vertex declaration that describes the data.</param>
        /// <param name="usage">The resource usage specifying the type of memory the buffer should use.</param>
        /// <param name="data">Array of databuffers to initialize the vertex buffer with, each databuffer corresponds to a single vertex element.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if data or vertex declaration is null.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the declaration's vertex stride is not
        /// the same as the data's vertex stride, or the number of data buffers do not match the number of declaraed vertex elements, or the
        /// data buffers are not all the same length.</exception>
        protected VertexBufferImplementation(VertexDeclaration vertexDeclaration, ResourceUsage usage, params DataBuffer[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data", "Data cannot be null.");
            }

            if (vertexDeclaration == null)
            {
                throw new ArgumentNullException("vertexDeclaration", "Vertex declaration cannot be null.");
            }

            _vertexDecl  = vertexDeclaration;
            _bufferUsage = usage;

            //Verify if the incoming vertex streams match right with the supplied vertex declaration
            VertexElement[] elems = _vertexDecl.VertexElements;
            if (elems.Length != data.Length)
            {
                throw new ArgumentOutOfRangeException("data", "Number of vertex streams do not match up the number of declared vertex elements.");
            }

            //Get the vertex count from the first data...we'll check if the data sizes are the same later
            _vertexCount = data[0].SizeInBytes / data[0].ElementSizeInBytes;

            int totalSizeInBytes = 0;
            int vertexStride     = 0;

            for (int i = 0; i < data.Length; i++)
            {
                DataBuffer    db           = data[i];
                VertexElement element      = elems[i];
                int           vSizeInBytes = db.ElementSizeInBytes;
                int           vCount       = db.SizeInBytes / vSizeInBytes;

                if (vCount != _vertexCount)
                {
                    throw new ArgumentOutOfRangeException("data", "Vertex count mismatch, buffers must be of same length.");
                }
                if (vSizeInBytes != VertexDeclaration.GetVertexElementSize(element.Format))
                {
                    throw new ArgumentOutOfRangeException("data", "Supplied vertex buffer element size mismatch with actual vertex element size.");
                }

                totalSizeInBytes += db.SizeInBytes;
                vertexStride     += vSizeInBytes;
                db.Position       = 0;
            }

            if (totalSizeInBytes != _vertexDecl.VertexStride * _vertexCount)
            {
                throw new ArgumentOutOfRangeException("data", "Vertex data must match the size declared for this vertex buffer!");
            }
        }
Beispiel #2
0
        public D3D.InputLayout GetOrCreateLayout(VertexBufferBinding[] vbuffers, int numBuffers)
        {
            //Take care of the trivial cases
            if (numBuffers == 1)
            {
                return(GetOrCreateLayout(vbuffers[0]));
            }
            else if (numBuffers == 0)
            {
                throw new TeslaException("Error creating input layout - cannot draw!");
            }

            //Clear semantic index array
            ClearSemanticIndices();

            //Make sure we aren't trying to do too much
            if (numBuffers >= vbuffers.Length)
            {
                throw new ArgumentOutOfRangeException("numBuffers", "Number of vertex declarations to merge is greater than number of vertex buffers given.");
            }

            //Do we have an input layout that matches?
            int key = GenerateKey(vbuffers, numBuffers);

            D3D.InputLayout layout;
            if (!_layoutMap.TryGetValue(key, out layout))
            {
                //If not, need to loop over each vertex buffer and create a layout from each declaration
                try {
                    D3D.InputElement[] elements = new D3D.InputElement[GetVertexElementCount(vbuffers, numBuffers)];
                    int index = 0;
                    for (int i = 0; i < numBuffers; i++)
                    {
                        VertexBufferBinding binding = vbuffers[i];
                        VertexDeclaration   decl    = binding.VertexBuffer.VertexDeclaration;
                        int offset = 0; //Every new stream, reset offset
                        for (int j = 0; j < decl.ElementCount; j++)
                        {
                            VertexElement element = decl[j];
                            element.SemanticIndex = IncrementSemanticIndex(element.SemanticName);
                            element.Offset        = offset;
                            elements[index++]     = GenerateInputElement(element, i, binding.InstanceFrequency);
                            offset += VertexDeclaration.GetVertexElementSize(element.Format);
                        }
                    }
                    layout = new D3D.InputLayout(_device, _sig, elements);
                } catch (Exception e) {
                    throw new TeslaException("Error setting vertex declaration, it does not match the shader's input signature. Either there is an invalid element, or the declaration does not have enough elements.", e);
                }
                //If we're good, add it to the map
                _layoutMap.Add(key, layout);
            }
            return(layout);
        }
        /// <summary>
        /// Convienence method that takes an array of data buffers, each representing a vertex element (in the order
        /// declared by the vertex declaration), and writes all of the data to the vertex buffer. The buffers must match
        /// the vertex declaration as well as the byte sizes of each element and all be of the same length.
        /// </summary>
        /// <param name="data">Array of databuffers representing the vertex data.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if data is null.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the number of buffers do not match the number
        /// of vertex elements, or if the number of vertices in each buffer does not match the vertex count,
        /// or if there is a byte size mismatch of any kind.</exception>
        public override void SetInterleavedData(params DataBuffer[] data)
        {
            if (_buffer == null || _buffer.Disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            if (data == null || data.Length == 0)
            {
                throw new ArgumentNullException("data", "Data cannot be null.");
            }

            VertexDeclaration vertexDecl = base.VertexDeclaration;
            int vertexCount = base.VertexCount;

            //Verify if the incoming vertex streams match right with the supplied vertex declaration
            VertexElement[] elems = vertexDecl.VertexElements;
            if (elems.Length != data.Length)
            {
                throw new ArgumentOutOfRangeException("data", "Number of vertex streams do not match up the number of declared vertex elements.");
            }

            int totalSizeInBytes = 0;
            int vertexStride     = 0;

            for (int i = 0; i < data.Length; i++)
            {
                DataBuffer    db           = data[i];
                VertexElement element      = elems[i];
                int           vSizeInBytes = db.ElementSizeInBytes;
                int           vCount       = db.SizeInBytes / vSizeInBytes;

                if (vCount != vertexCount)
                {
                    throw new ArgumentOutOfRangeException("data", "Vertex count mismatch, buffers must be of same length.");
                }
                if (vSizeInBytes != VertexDeclaration.GetVertexElementSize(element.Format))
                {
                    throw new ArgumentOutOfRangeException("data", "Supplied vertex buffer element size mismatch with actual vertex element size.");
                }

                totalSizeInBytes += db.SizeInBytes;
                vertexStride     += vSizeInBytes;
                db.Position       = 0;
            }

            if (totalSizeInBytes != vertexDecl.VertexStride * vertexCount)
            {
                throw new ArgumentOutOfRangeException("data", "Vertex data must match the size of the vertex buffer in bytes!");
            }

            CreateStaging();

            try {
                using (SDX.DataStream interleaved = _staging.Map(D3D.MapMode.Write, D3D.MapFlags.None)) {
                    byte[] vertex = new byte[vertexStride];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        int startIndex = 0;
                        for (int j = 0; j < data.Length; j++)
                        {
                            DataBuffer db          = data[j];
                            int        elementSize = db.ElementSizeInBytes;
                            db.Get(vertex, startIndex, elementSize);
                            startIndex += elementSize;
                        }
                        interleaved.Write(vertex, 0, vertexStride);
                    }
                    _staging.Unmap();
                    //Copy entire resource
                    _graphicsDevice.CopyResource(_staging, _buffer);
                }
            } catch (Exception e) {
                throw new TeslaException("Error writing to D3D10 Buffer.", e);
            }
        }
        /// <summary>
        /// Convienence method that takes an array of data buffers, each representing a vertex element (in the order
        /// declared by the vertex declaration), and writes all of the data to the vertex buffer. The buffers must match
        /// the vertex declaration as well as the byte sizes of each element and all be of the same length.
        /// </summary>
        /// <param name="data">Array of databuffers representing the vertex data.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if data is null.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the number of buffers do not match the number
        /// of vertex elements, or if the number of vertices in each buffer does not match the vertex count,
        /// or if there is a byte size mismatch of any kind.</exception>
        public override void SetInterleavedData(params DataBuffer[] data)
        {
            if (data == null || data.Length == 0)
            {
                throw new ArgumentNullException("data", "Data cannot be null.");
            }

            VertexDeclaration vertexDecl = base.VertexDeclaration;
            int vertexCount = base.VertexCount;

            //Verify if the incoming vertex streams match right with the supplied vertex declaration
            VertexElement[] elems = vertexDecl.VertexElements;
            if (elems.Length != data.Length)
            {
                throw new ArgumentOutOfRangeException("data", "Number of vertex streams do not match up the number of declared vertex elements.");
            }

            int totalSizeInBytes = 0;
            int vertexStride     = 0;

            for (int i = 0; i < data.Length; i++)
            {
                DataBuffer    db           = data[i];
                VertexElement element      = elems[i];
                int           vSizeInBytes = db.ElementSizeInBytes;
                int           vCount       = db.SizeInBytes / vSizeInBytes;

                if (vCount != vertexCount)
                {
                    throw new ArgumentOutOfRangeException("data", "Vertex count mismatch, buffers must be of same length.");
                }
                if (vSizeInBytes != VertexDeclaration.GetVertexElementSize(element.Format))
                {
                    throw new ArgumentOutOfRangeException("data", "Supplied vertex buffer element size mismatch with actual vertex element size.");
                }

                totalSizeInBytes += db.SizeInBytes;
                vertexStride     += vSizeInBytes;
                db.Position       = 0;
            }

            if (totalSizeInBytes != vertexDecl.VertexStride * vertexCount)
            {
                throw new ArgumentOutOfRangeException("data", "Vertex data must match the size of the vertex buffer in bytes!");
            }

            DataBuffer <byte> interleaved = new DataBuffer <byte>(vertexCount * vertexDecl.VertexStride);

            byte[] vertex = new byte[vertexStride];
            for (int i = 0; i < vertexCount; i++)
            {
                int startIndex = 0;
                for (int j = 0; j < data.Length; j++)
                {
                    DataBuffer db          = data[j];
                    int        elementSize = db.ElementSizeInBytes;
                    db.Get(vertex, startIndex, elementSize);
                    startIndex += elementSize;
                }
                interleaved.Set(vertex, 0, vertexStride);
            }
            _vertexBuffer.SetData <byte>(interleaved.Buffer);
        }