/// <summary> /// Reads data from the index buffer into the array. /// </summary> /// <typeparam name="T">The type of data in the index buffer - int or short.</typeparam> /// <param name="data">Array to write the data to</param> /// <param name="startIndex">Starting index in the array at which to start writing to</param> /// <param name="elementCount">Number of indices to read</param> /// <param name="offsetInBytes">Offset from the start of the index buffer at which to start copying from</param> /// <remarks>See implementors for exceptions that may occur.</remarks> public override void GetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes) { if (_buffer == null || _buffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int numBytes = MemoryHelper.SizeOf <T>(); int ibSize = base.IndexCount * ((base.IndexFormat == IndexFormat.SixteenBits) ? 2 : 4); int dataSize = elementCount * numBytes; if (offsetInBytes < 0 || offsetInBytes > ibSize) { throw new ArgumentOutOfRangeException("offsetInBytes", "Byte offset is out of range."); } if ((offsetInBytes + dataSize) > ibSize) { throw new ArgumentOutOfRangeException("data", "Byte offset and the number of elements to read will cause a buffer overflow."); } CreateStaging(); try { //If we're reading from the entire VB just copy the whole thing if (offsetInBytes == 0 && startIndex == 0 && dataSize == ibSize) { _graphicsDevice.CopyResource(_buffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_buffer, 0, region, _staging, 0, offsetInBytes, 0, 0); } using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Read, D3D.MapFlags.None)) { ds.Position = offsetInBytes; ds.ReadRange <T>(data, startIndex, elementCount); _staging.Unmap(); } } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Buffer.", e); } }
/// <summary> /// Gets the data from the texture. /// </summary> /// <typeparam name="T">Type of data in the array.</typeparam> /// <param name="data">Array of data.</param> /// <param name="mipLevel">Mip map level to access.</param> /// <param name="subimage">Rectangle representing a sub-image of the 2D texture to read from, if null the whole image is read from.</param> /// <param name="startIndex">Starting index in the array to start writing to.</param> /// <param name="elementCount">Number of elements to read.</param> /// <exception cref="System.ArgumentException">Thrown if the format byte size of the type to read and the texture do not match, the subimage /// dimensions are invalid, or if the total size to read and the total size in the texture do not match</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error reading from the texture.</exception> public override void GetData <T>(T[] data, int mipLevel, Rectangle?subimage, int startIndex, int elementCount) { if (_texture2D == null || _texture2D.Disposed) { throw new ObjectDisposedException(GetType().Name); } if (mipLevel < 0 || mipLevel >= _mipCount) { throw new ArgumentOutOfRangeException("mipLevel", String.Format("Mip level is out of range. Must be between 0 and {0}.", _mipCount.ToString())); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int formatSize = D3D10Helper.FormatSize(base.Format); int elemSize = MemoryHelper.SizeOf <T>(); CheckSizes(formatSize, elemSize); //Calc subresource dimensions int width = (int)MathHelper.Max(1, base.Width >> mipLevel); int height = (int)MathHelper.Max(1, base.Height >> mipLevel); //Get the dimensions, if its null we copy the whole texture Rectangle rect; if (subimage.HasValue) { rect = subimage.Value; CheckRectangle(rect, ref width, ref height); } else { rect = new Rectangle(0, 0, width, height); } CheckTotalSize(base.Format, ref formatSize, ref width, ref height, elemSize, elementCount); //Create staging CreateStaging(); try { int row = rect.Y; int col = rect.X; //Do resource copy if (base.Format == SurfaceFormat.DXT1 || base.Format == SurfaceFormat.DXT3 || base.Format == SurfaceFormat.DXT5) { _graphicsDevice.CopyResource(_texture2D, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = col; region.Right = col + width; region.Top = row; region.Bottom = row + height; region.Front = 0; region.Back = 1; _graphicsDevice.CopySubresourceRegion(_texture2D, mipLevel, region, _staging, mipLevel, col, row, 0); } SDX.DataRectangle dataRect = _staging.Map(mipLevel, D3D.MapMode.Read, D3D.MapFlags.None); SDX.DataStream ds = dataRect.Data; int pitch = dataRect.Pitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Go row by row for (int i = row; i < height; i++) { //Set the position ds.Position = (i * pitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.ReadRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.ReadRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } _staging.Unmap(mipLevel); } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Texture2D.", e); } }
/// <summary> /// Gets the data from the texture. /// </summary> /// <typeparam name="T">Type of data in the array</typeparam> /// <param name="data">The array of data</param> /// <param name="mipLevel">Mip map level to read from</param> /// <param name="left">Right-most width position in the texture at which to acess. (0 or greater)</param> /// <param name="right">Right-most width position in the texture at which to acess. (width or less)</param> /// <param name="top">Top-most height position in the texture at which to acess. (0 or greater)</param> /// <param name="bottom">Bottom-most height position in the texture at which to acess. (height or less)</param> /// <param name="front">Front-most depth position in the texture at which to acess. (0 or greater)</param> /// <param name="back">Back-most depth position in the texture at which to acess. (depth or less)</param> /// <param name="startIndex">Starting index in the array to start reading from.</param> /// <param name="elementCount">Number of elements to write.</param> /// <exception cref="System.ArgumentException">Thrown if the format byte size of the type to read and the texture do not match, the subimage /// dimensions are invalid, or if the total size to read and the total size in the texture do not match</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error reading from the texture.</exception> public override void GetData <T>(T[] data, int mipLevel, int left, int right, int top, int bottom, int front, int back, int startIndex, int elementCount) { if (_texture3D == null || _texture3D.Disposed) { throw new ObjectDisposedException(GetType().Name); } if (mipLevel < 0 || mipLevel >= _mipCount) { throw new ArgumentOutOfRangeException("mipLevel", String.Format("Mip level is out of range. Must be between 0 and {0}.", _mipCount.ToString())); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int formatSize = D3D10Helper.FormatSize(base.Format); int elemSize = MemoryHelper.SizeOf <T>(); CheckSizes(formatSize, elemSize); //Calc subresource dimensions int width = (int)MathHelper.Max(1, base.Width >> mipLevel); int height = (int)MathHelper.Max(1, base.Height >> mipLevel); int depth = (int)MathHelper.Max(1, base.Depth >> mipLevel); //Ensure box dimensions CheckBox(left, right, top, bottom, front, back, ref width, ref height, ref depth); CheckTotalSize(base.Format, ref formatSize, ref width, ref height, ref depth, elemSize, elementCount); //Create staging CreateStaging(); try { int row = left; int col = top; int slice = front; //Do resource copy if (base.Format == SurfaceFormat.DXT1 || base.Format == SurfaceFormat.DXT3 || base.Format == SurfaceFormat.DXT5) { _graphicsDevice.CopyResource(_texture3D, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = col; region.Right = right; region.Top = row; region.Bottom = bottom; region.Front = slice; region.Back = back; _graphicsDevice.CopySubresourceRegion(_texture3D, mipLevel, region, _staging, mipLevel, col, row, slice); } SDX.DataBox dataBox = _staging.Map(mipLevel, D3D.MapMode.Read, D3D.MapFlags.None); SDX.DataStream ds = dataBox.Data; int rowPitch = dataBox.RowPitch; int slicePitch = dataBox.SlicePitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Go slice by slice for (int k = slice; k < back; k++) { //Go row by row for (int i = row; i < bottom; i++) { //Set the position ds.Position = (k * slicePitch) + (i * rowPitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.ReadRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.ReadRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } } _staging.Unmap(mipLevel); } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Texture3D.", e); } }
/// <summary> /// Gets the back buffer data. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="subimage">The rectangle representing the sub-image. Null value means to grab the whole back buffer.</param> /// <param name="data">The data.</param> /// <param name="startIndex">The starting index in the array.</param> /// <param name="elementCount">The number of eleemnts to read</param> public override void GetBackBufferData <T>(Rectangle?subimage, T[] data, int startIndex, int elementCount) { if (_backBuffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); //Calc subresource dimensions int width = _presentParams.BackBufferWidth; int height = _presentParams.BackBufferHeight; //Get the dimensions, if its null we copy the whole texture Rectangle rect; if (subimage.HasValue) { rect = subimage.Value; CheckRectangle(rect, width, height); } else { rect = new Rectangle(0, 0, width, height); } if (elementCount > rect.Width * rect.Height) { throw new ArgumentOutOfRangeException("elementCount", "Number of elements to read is larger than contained in the specified subimage."); } //Create staging CreateStaging(); try { int row = rect.Y; int col = rect.X; int rectWidth = rect.Width; int rectHeight = rect.Height; //Do resource copy if (row == 0 && col == 0 && rectWidth == width && rectHeight == height) { _graphicsDevice.CopyResource(_backBuffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = col; region.Right = col + rectWidth; region.Top = row; region.Bottom = row + rectHeight; region.Front = 0; region.Back = 1; _graphicsDevice.CopySubresourceRegion(_backBuffer, 0, region, _staging, 0, col, row, 0); } SDX.DataRectangle dataRect = _staging.Map(0, D3D.MapMode.Read, D3D.MapFlags.None); SDX.DataStream ds = dataRect.Data; int elemSize = MemoryHelper.SizeOf <T>(); int formatSize = D3D10Helper.FormatSize(_presentParams.BackBufferFormat); int pitch = dataRect.Pitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(rectWidth * (formatSize / elemSize)); //Go row by row for (int i = row; i < height; i++) { //Set the position ds.Position = (i * pitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.ReadRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.ReadRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } _staging.Unmap(0); } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Texture2D.", e); } }
/// <summary> /// Gets the data from the texture. /// </summary> /// <typeparam name="T">Type of data in the array.</typeparam> /// <param name="data">Array of data</param> /// <param name="mipLevel">Mip map level to access</param> /// <param name="left">The left-most position in the 1D texture at which to access.</param> /// <param name="right">The right-most position in the 1D texture at which to acess.</param> /// <param name="startIndex">Starting index in the array to start writing to.</param> /// <param name="elementCount">Number of elements to read.</param> public override void GetData <T>(T[] data, int mipLevel, int left, int right, int startIndex, int elementCount) { if (_texture1D.Disposed) { throw new ObjectDisposedException(GetType().Name); } if (mipLevel < 0 || mipLevel >= _mipCount) { throw new ArgumentOutOfRangeException("mipLevel", String.Format("Mip level is out of range. Must be between 0 and {0}.", _mipCount.ToString())); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); SurfaceFormat format = base.Format; int formatSize = D3D10Helper.FormatSize(format); int elemSize = MemoryHelper.SizeOf <T>(); CheckSizes(formatSize, elemSize); //Calc subresource dimensions int width = (int)MathHelper.Max(1, base.Width >> mipLevel); //Check the line CheckLine(ref width, left, right); //Check the total size - fixes up the proper sizes if we're using a compression format CheckTotalSize(format, ref formatSize, ref width, elemSize, elementCount); //Create staging CreateStaging(); try { //Copy from the texture to staging if (format == SurfaceFormat.DXT1 || format == SurfaceFormat.DXT3 || format == SurfaceFormat.DXT5) { _graphicsDevice.CopyResource(_texture1D, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = left; region.Right = right; region.Top = 0; region.Bottom = 1; region.Front = 0; region.Back = 1; _graphicsDevice.CopySubresourceRegion(_texture1D, mipLevel, region, _staging, mipLevel, left, 0, 0); } SDX.DataStream ds = _staging.Map(mipLevel, D3D.MapMode.Read, D3D.MapFlags.None); //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Read data ds.Position = left * formatSize; ds.ReadRange <T>(data, startIndex, actWidth); _staging.Unmap(mipLevel); } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Texture2D.", e); } }
/// <summary> /// Gets the data from the vertex buffer and copies it into specified array. /// </summary> /// <typeparam name="T">The type of data in the vertex buffer.</typeparam> /// <param name="data">Array to copy contents to from the vertex buffer into</param> /// <param name="startIndex">Index of the element in the array at each to start writing to</param> /// <param name="elementCount">Number of elements to copy</param> /// <param name="offsetInBytes">Offset in bytes from the beginning of the vertex buffer to the data.</param> /// <param name="vertexStride">Size of an element in bytes</param> /// <exception cref="System.ObjectDisposedException">Thrown if Dispose() has been called.</exception> /// <exception cref="System.InvalidOperationException">Thrown if the write options are incompatible with the resource usage of the buffer.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the data's vertex stride is too small, the offset in bytes is out of range, /// or the byte offset and number of elements to read will cause overflow.</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error reading from the buffer.</exception> public override void GetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, int vertexStride) { if (_buffer == null || _buffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Check if array bounds are out of range D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); VertexDeclaration vertexDecl = base.VertexDeclaration; int vertexCount = base.VertexCount; int vbSize = vertexCount * vertexDecl.VertexStride; int elemSize = MemoryHelper.SizeOf <T>(); int dataSize = elementCount * elemSize; int vertexStep = vertexStride; if (vertexStride != 0) { vertexStep -= elemSize; if (vertexStep < 0) { throw new ArgumentException("vertexStride", "Vertex stride is too small for requested data size."); } //If we get this far, we need to make sure the actual bytes we're going to look at matches up, //since we can grab specific parts of a vertex and not the whole thing if (elementCount > 1) { dataSize = ((elementCount - 1) * vertexStep) + dataSize; } } //Prevent overflow out of range errors if ((offsetInBytes < 0) || (offsetInBytes > vbSize)) { throw new ArgumentOutOfRangeException("offsetInBytes", "Byte offset is out of range."); } if ((offsetInBytes + dataSize) > vbSize) { throw new ArgumentOutOfRangeException("data", "Byte offset and elements to read will cause in buffer overflow."); } //Create scratch buffer, if it hasn't been created already CreateStaging(); try { //If we're reading from the entire VB just copy the whole thing if (offsetInBytes == 0 && startIndex == 0 && vertexCount == data.Length) { _graphicsDevice.CopyResource(_buffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_buffer, 0, region, _staging, 0, offsetInBytes, 0, 0); } using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Read, D3D.MapFlags.None)) { //If the step is zero, that means we're dealing with the entire vertex and not a subset of it if (vertexStep == 0) { ds.Position = offsetInBytes; ds.ReadRange <T>(data, startIndex, elementCount); } else { ds.Position = offsetInBytes; int count = elementCount - 1; int index = startIndex; data[index++] = ds.Read <T>(); while (count > 0) { ds.Position += vertexStep; data[index] = ds.Read <T>(); count--; index++; } } _staging.Unmap(); } } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Buffer.", e); } }