/// <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!"); } }
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); }