From a7fb23b5995e7d65a6bce100cf9b403617b281ec Mon Sep 17 00:00:00 2001 From: Konstantin Koch Date: Sun, 18 Jan 2015 15:50:00 +0000 Subject: [PATCH] Implemented GetData and SetData for Metro Rendersystem too. Together with commit 32081, this implements patch 15996. --- .../IndexBuffer_Metro.cs | 245 ++++++++++------- .../VertexBuffer_Metro.cs | 256 ++++++++++-------- 2 files changed, 291 insertions(+), 210 deletions(-) diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/IndexBuffer_Metro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/IndexBuffer_Metro.cs index ad746f39..ee0bab19 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/IndexBuffer_Metro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/IndexBuffer_Metro.cs @@ -1,8 +1,9 @@ using System; using ANX.Framework.Graphics; using ANX.Framework.NonXNA.RenderSystem; -using Dx11 = SharpDX.Direct3D11; +using Dx = SharpDX.Direct3D11; using System.IO; +using SharpDX; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. @@ -10,121 +11,161 @@ using System.IO; namespace ANX.RenderSystem.Windows.Metro { - public class IndexBuffer_Metro : INativeIndexBuffer, IDisposable - { - #region Private - private int indexSizeInBytes; - #endregion + public class IndexBuffer_Metro : INativeIndexBuffer, IDisposable + { + #region Private + private int indexSizeInBytes; + #endregion - #region Public - public Dx11.Buffer NativeBuffer - { - get; - private set; - } - #endregion + #region Public + public Dx.Buffer NativeBuffer + { + get; + private set; + } + #endregion - #region Constructor - public IndexBuffer_Metro(GraphicsDevice graphics, IndexElementSize size, - int indexCount, BufferUsage usage) - { - indexSizeInBytes = size == IndexElementSize.SixteenBits ? 2 : 4; - - GraphicsDeviceWindowsMetro gdMetro = graphics.NativeDevice as GraphicsDeviceWindowsMetro; - var device = gdMetro.NativeDevice.NativeDevice; + #region Constructor + public IndexBuffer_Metro(GraphicsDevice graphics, IndexElementSize size, + int indexCount, BufferUsage usage) + { + indexSizeInBytes = size == IndexElementSize.SixteenBits ? 2 : 4; + + GraphicsDeviceWindowsMetro gdMetro = graphics.NativeDevice as GraphicsDeviceWindowsMetro; + var device = gdMetro.NativeDevice.NativeDevice; - InitializeBuffer(device, indexCount, usage); - } + InitializeBuffer(device, indexCount, usage); + } - internal IndexBuffer_Metro(Dx11.Device device, IndexElementSize size, - int indexCount, BufferUsage usage) - { - indexSizeInBytes = size == IndexElementSize.SixteenBits ? 2 : 4; - InitializeBuffer(device, indexCount, usage); - } - #endregion + internal IndexBuffer_Metro(Dx.Device device, IndexElementSize size, + int indexCount, BufferUsage usage) + { + indexSizeInBytes = size == IndexElementSize.SixteenBits ? 2 : 4; + InitializeBuffer(device, indexCount, usage); + } + #endregion - #region InitializeBuffer - private void InitializeBuffer(Dx11.Device device, - int indexCount, BufferUsage usage) - { - var description = new Dx11.BufferDescription() - { - Usage = FormatConverter.Translate(usage), - SizeInBytes = indexSizeInBytes * indexCount, - BindFlags = Dx11.BindFlags.IndexBuffer, - CpuAccessFlags = Dx11.CpuAccessFlags.Write, - OptionFlags = Dx11.ResourceOptionFlags.None - }; + #region InitializeBuffer + private void InitializeBuffer(Dx.Device device, + int indexCount, BufferUsage usage) + { + var description = new Dx.BufferDescription() + { + Usage = FormatConverter.Translate(usage), + SizeInBytes = indexSizeInBytes * indexCount, + BindFlags = Dx.BindFlags.IndexBuffer, + CpuAccessFlags = Dx.CpuAccessFlags.Write, + OptionFlags = Dx.ResourceOptionFlags.None + }; - NativeBuffer = new Dx11.Buffer(device, description); - } - #endregion + NativeBuffer = new Dx.Buffer(device, description); + } + #endregion - #region SetData - public void SetData(GraphicsDevice graphicsDevice, T[] data) where T : struct - { - SetData(graphicsDevice, data, 0, data.Length); - } + #region SetData + public void SetData(GraphicsDevice graphicsDevice, T[] data) where T : struct + { + SetData(graphicsDevice, data, 0, data.Length); + } - public void SetData(GraphicsDevice graphicsDevice, T[] data, int startIndex, - int elementCount) where T : struct - { - SetData(graphicsDevice, 0, data, startIndex, elementCount); - } + public void SetData(GraphicsDevice graphicsDevice, T[] data, int startIndex, + int elementCount) where T : struct + { + SetData(graphicsDevice, 0, data, startIndex, elementCount); + } - public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, T[] data, - int startIndex, int elementCount) where T : struct - { - GraphicsDeviceWindowsMetro gdMetro = graphicsDevice.NativeDevice as GraphicsDeviceWindowsMetro; - var device = gdMetro.NativeDevice; + public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, T[] data, + int startIndex, int elementCount) where T : struct + { + GraphicsDeviceWindowsMetro gdMetro = graphicsDevice.NativeDevice as GraphicsDeviceWindowsMetro; + var device = gdMetro.NativeDevice; - //TODO: check offsetInBytes parameter for bounds etc. + //TODO: check offsetInBytes parameter for bounds etc. - SharpDX.DataStream stream = device.MapSubresource(NativeBuffer); + SharpDX.DataStream stream = device.MapSubresource(NativeBuffer); - if (offsetInBytes > 0) - stream.Seek(offsetInBytes, SeekOrigin.Current); + if (offsetInBytes > 0) + stream.Seek(offsetInBytes, SeekOrigin.Current); - if (startIndex > 0 || elementCount < data.Length) - for (int i = startIndex; i < startIndex + elementCount; i++) - stream.Write(data[i]); - else - for (int i = 0; i < data.Length; i++) - stream.Write(data[i]); - - device.UnmapSubresource(NativeBuffer, 0); - } - #endregion - - #region GetData (TODO) - public void GetData(int offsetInBytes, T[] data, int startIndex, - int elementCount) where T : struct - { - throw new NotImplementedException(); - } + if (startIndex > 0 || elementCount < data.Length) + for (int i = startIndex; i < startIndex + elementCount; i++) + stream.Write(data[i]); + else + for (int i = 0; i < data.Length; i++) + stream.Write(data[i]); - public void GetData(T[] data) where T : struct - { - throw new NotImplementedException(); - } + device.UnmapSubresource(NativeBuffer, 0); + } + #endregion + + #region GetData + public void GetData(S[] data) where S : struct + { + GetData(0, data, 0, data.Length); + } - public void GetData(T[] data, int startIndex, int elementCount) - where T : struct - { - throw new NotImplementedException(); - } - #endregion + public void GetData(S[] data, int startIndex, int elementCount) where S : struct + { + GetData(0, data, 0, data.Length); + } - #region Dispose - public void Dispose() - { - if (NativeBuffer != null) - { - NativeBuffer.Dispose(); - NativeBuffer = null; - } - } - #endregion - } + public void GetData(int offsetInBytes, S[] data, int startIndex, int elementCount) where S : struct + { + Dx.Buffer stagingBuffer = CreateStagingBuffer(indexSizeInBytes * elementCount); + CopySubresource(NativeBuffer, stagingBuffer); + + using (var stream = MapBufferRead(stagingBuffer)) + { + if (offsetInBytes > 0) + stream.Seek(offsetInBytes, SeekOrigin.Current); + + stream.ReadRange(data, startIndex, elementCount); + UnmapBuffer(stagingBuffer); + } + } + #endregion + + private SharpDX.DataStream MapBufferRead(Dx.Buffer buffer) + { + Dx.DeviceContext context = buffer.Device.ImmediateContext; + DataStream stream; + context.MapSubresource(buffer, Dx.MapMode.Read, Dx.MapFlags.None, out stream); + return stream; + } + + private void UnmapBuffer(Dx.Buffer buffer) + { + Dx.DeviceContext context = buffer.Device.ImmediateContext; + context.UnmapSubresource(buffer, 0); + } + + private void CopySubresource(Dx.Buffer source, Dx.Buffer destination) + { + this.NativeBuffer.Device.ImmediateContext.CopyResource(source, destination); + } + + private Dx.Buffer CreateStagingBuffer(int sizeInBytes) + { + var description = new Dx.BufferDescription() + { + Usage = Dx.ResourceUsage.Staging, + SizeInBytes = sizeInBytes, + CpuAccessFlags = Dx.CpuAccessFlags.Read, + OptionFlags = Dx.ResourceOptionFlags.None, + }; + + return new Dx.Buffer(NativeBuffer.Device, description); + } + + #region Dispose + public void Dispose() + { + if (NativeBuffer != null) + { + NativeBuffer.Dispose(); + NativeBuffer = null; + } + } + #endregion + } } diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/VertexBuffer_Metro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/VertexBuffer_Metro.cs index 74acf700..72a7eef5 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/VertexBuffer_Metro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/VertexBuffer_Metro.cs @@ -2,7 +2,8 @@ using System; using System.IO; using ANX.Framework.Graphics; using ANX.Framework.NonXNA.RenderSystem; -using Dx11 = SharpDX.Direct3D11; +using Dx = SharpDX.Direct3D11; +using System.Runtime.InteropServices; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. @@ -10,129 +11,168 @@ using Dx11 = SharpDX.Direct3D11; namespace ANX.RenderSystem.Windows.Metro { - public class VertexBuffer_Metro : INativeVertexBuffer, IDisposable - { - #region Private - private int vertexStride; - #endregion + public class VertexBuffer_Metro : INativeVertexBuffer, IDisposable + { + #region Private + private int vertexStride; + #endregion - #region Public - public Dx11.Buffer NativeBuffer - { - get; - private set; - } - #endregion + #region Public + public Dx.Buffer NativeBuffer + { + get; + private set; + } + #endregion - #region Constructor - public VertexBuffer_Metro(GraphicsDevice graphics, VertexDeclaration vertexDeclaration, - int vertexCount, BufferUsage usage) - { - GraphicsDeviceWindowsMetro gdMetro = graphics.NativeDevice as GraphicsDeviceWindowsMetro; - var device = gdMetro.NativeDevice.NativeDevice; + #region Constructor + public VertexBuffer_Metro(GraphicsDevice graphics, VertexDeclaration vertexDeclaration, + int vertexCount, BufferUsage usage) + { + GraphicsDeviceWindowsMetro gdMetro = graphics.NativeDevice as GraphicsDeviceWindowsMetro; + var device = gdMetro.NativeDevice.NativeDevice; - vertexStride = vertexDeclaration.VertexStride; - InitializeBuffer(device, vertexCount, usage); - } + vertexStride = vertexDeclaration.VertexStride; + InitializeBuffer(device, vertexCount, usage); + } - internal VertexBuffer_Metro(Dx11.Device device, VertexDeclaration vertexDeclaration, - int vertexCount, BufferUsage usage) - { - vertexStride = vertexDeclaration.VertexStride; - InitializeBuffer(device, vertexCount, usage); - } - #endregion + internal VertexBuffer_Metro(Dx.Device device, VertexDeclaration vertexDeclaration, + int vertexCount, BufferUsage usage) + { + vertexStride = vertexDeclaration.VertexStride; + InitializeBuffer(device, vertexCount, usage); + } + #endregion - #region InitializeBuffer - private void InitializeBuffer(Dx11.Device device, int vertexCount, - BufferUsage usage) - { - if (device != null) - { - var description = new Dx11.BufferDescription() - { - Usage = FormatConverter.Translate(usage), - SizeInBytes = vertexStride * vertexCount, - BindFlags = Dx11.BindFlags.VertexBuffer, - CpuAccessFlags = Dx11.CpuAccessFlags.Write, - OptionFlags = Dx11.ResourceOptionFlags.None - }; + #region InitializeBuffer + private void InitializeBuffer(Dx.Device device, int vertexCount, + BufferUsage usage) + { + if (device != null) + { + var description = new Dx.BufferDescription() + { + Usage = FormatConverter.Translate(usage), + SizeInBytes = vertexStride * vertexCount, + BindFlags = Dx.BindFlags.VertexBuffer, + CpuAccessFlags = Dx.CpuAccessFlags.Write, + OptionFlags = Dx.ResourceOptionFlags.None + }; - NativeBuffer = new Dx11.Buffer(device, description); - } - } - #endregion + NativeBuffer = new Dx.Buffer(device, description); + } + } + #endregion - #region SetData - public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, - T[] data, int startIndex, int elementCount) where T : struct - { - SetData(graphicsDevice, offsetInBytes, data, startIndex, elementCount, vertexStride); - } + #region SetData + public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, + T[] data, int startIndex, int elementCount) where T : struct + { + SetData(graphicsDevice, offsetInBytes, data, startIndex, elementCount, vertexStride); + } - public void SetData(GraphicsDevice graphicsDevice, T[] data) where T : struct - { - SetData(graphicsDevice, data, 0, data.Length); - } + public void SetData(GraphicsDevice graphicsDevice, T[] data) where T : struct + { + SetData(graphicsDevice, data, 0, data.Length); + } - public void SetData(GraphicsDevice graphicsDevice, T[] data, int startIndex, - int elementCount) where T : struct - { - SetData(graphicsDevice, 0, data, startIndex, elementCount); - } + public void SetData(GraphicsDevice graphicsDevice, T[] data, int startIndex, + int elementCount) where T : struct + { + SetData(graphicsDevice, 0, data, startIndex, elementCount); + } - public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, T[] data, - int startIndex, int elementCount, int vertexStride) where T : struct - { - GraphicsDeviceWindowsMetro gdMetro = graphicsDevice.NativeDevice as GraphicsDeviceWindowsMetro; - var device = gdMetro.NativeDevice; + public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, T[] data, + int startIndex, int elementCount, int vertexStride) where T : struct + { + if (offsetInBytes + elementCount * Marshal.SizeOf(typeof(T)) > NativeBuffer.Description.SizeInBytes) + throw new ArgumentOutOfRangeException(string.Format("The offset by \"{0}\" plus the byte length described by \"{1}\" is over the bounds of the buffer.", "offsetInBytes", "elementCount")); - //TODO: check offsetInBytes parameter for bounds etc. + if (startIndex + elementCount > data.Length) + throw new ArgumentOutOfRangeException(string.Format("The parameters {0} + {1} must be smaller than {2}.", "startIndex", "elementCount", "data.Length")); - SharpDX.DataStream stream = device.MapSubresource(NativeBuffer); + GraphicsDeviceWindowsMetro gdMetro = graphicsDevice.NativeDevice as GraphicsDeviceWindowsMetro; + var device = gdMetro.NativeDevice; - if (offsetInBytes > 0) - stream.Seek(offsetInBytes, SeekOrigin.Current); + SharpDX.DataStream stream = device.MapSubresource(NativeBuffer); - if (startIndex > 0 || elementCount < data.Length) - for (int i = startIndex; i < startIndex + elementCount; i++) - stream.Write(data[i]); - else - for (int i = 0; i < data.Length; i++) - stream.Write(data[i]); - - device.UnmapSubresource(NativeBuffer, 0); - } - #endregion + if (offsetInBytes > 0) + stream.Seek(offsetInBytes, SeekOrigin.Current); - #region GetData (TODO) - public void GetData(int offsetInBytes, T[] data, int startIndex, - int elementCount, int vertexStride) where T : struct - { - throw new NotImplementedException(); - } + for (int i = startIndex; i < startIndex + elementCount; i++) + stream.Write(data[i]); - public void GetData(T[] data) where T : struct - { - throw new NotImplementedException(); - } + device.UnmapSubresource(NativeBuffer, 0); + } + #endregion - public void GetData(T[] data, int startIndex, int elementCount) - where T : struct - { - throw new NotImplementedException(); - } - #endregion + #region GetData + public void GetData(T[] data) where T : struct + { + GetData(data, 0, data.Length); + } - #region Dispose - public void Dispose() - { - if (NativeBuffer != null) - { - NativeBuffer.Dispose(); - NativeBuffer = null; - } - } - #endregion - } + public void GetData(T[] data, int startIndex, int elementCount) where T : struct + { + GetData(0, data, startIndex, elementCount, vertexStride); + } + + public void GetData(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) + where T : struct + { + Dx.Buffer stagingBuffer = CreateStagingBuffer(elementCount * vertexStride); + CopySubresource(NativeBuffer, stagingBuffer); + + using (var stream = MapBufferRead(stagingBuffer)) + { + if (offsetInBytes > 0) + stream.Seek(offsetInBytes, SeekOrigin.Current); + + stream.ReadRange(data, startIndex, elementCount); + UnmapBuffer(stagingBuffer); + } + } + #endregion + + private SharpDX.DataStream MapBufferRead(Dx.Resource buffer) + { + SharpDX.DataStream stream; + buffer.Device.ImmediateContext.MapSubresource(buffer, 0, Dx.MapMode.Read, Dx.MapFlags.None, out stream); + return stream; + } + + private void CopySubresource(Dx.Buffer source, Dx.Buffer destination) + { + this.NativeBuffer.Device.ImmediateContext.CopyResource(source, destination); + } + + private void UnmapBuffer(Dx.Resource buffer) + { + buffer.Device.ImmediateContext.UnmapSubresource(buffer, 0); + } + + private Dx.Buffer CreateStagingBuffer(int sizeInBytes) + { + var description = new Dx.BufferDescription() + { + Usage = Dx.ResourceUsage.Staging, + SizeInBytes = sizeInBytes, + CpuAccessFlags = Dx.CpuAccessFlags.Read, + OptionFlags = Dx.ResourceOptionFlags.None, + }; + + return new Dx.Buffer(NativeBuffer.Device, description); + } + + #region Dispose + public void Dispose() + { + if (NativeBuffer != null) + { + NativeBuffer.Dispose(); + NativeBuffer = null; + } + } + #endregion + } }