All pastes #2113341 Raw Edit

DirectX 11 buffer upload/downloa

public text v1 · immutable
#2113341 ·published 2012-02-08 21:01 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX;
using SlimDX.DXGI;
using D3D = SlimDX.Direct3D11;
using Exocortex.Diagnostics.Profiling;

namespace Exocortex.Rendering
{
	public class BufferHelper
	{
		static private D3D.BufferDescription CreateBufferDescription(BufferType bufferType, int elementCount, Type elementType )
		{
			int sizeOfT = System.Runtime.InteropServices.Marshal.SizeOf(elementType);
			switch (bufferType)
			{
				case BufferType.Vertex:
					return new D3D.BufferDescription(
				elementCount * sizeOfT,
				D3D.ResourceUsage.Default,
				D3D.BindFlags.VertexBuffer,
				D3D.CpuAccessFlags.None,
				D3D.ResourceOptionFlags.None,
				0);

				case BufferType.Index:
					return new D3D.BufferDescription(
				elementCount * sizeOfT,
				D3D.ResourceUsage.Default,
				D3D.BindFlags.IndexBuffer,
				D3D.CpuAccessFlags.None,
				D3D.ResourceOptionFlags.None,
				0);

				case BufferType.Compute:
					return new D3D.BufferDescription(
				elementCount * sizeOfT,
				D3D.ResourceUsage.Default,
				D3D.BindFlags.UnorderedAccess | D3D.BindFlags.ShaderResource,
				D3D.CpuAccessFlags.None,
				D3D.ResourceOptionFlags.StructuredBuffer,
				sizeOfT);

				default:
					throw new InvalidOperationException();
			}
		}

		static private BufferType GetBufferType(D3D.BufferDescription bufferDescription)
		{
			if (bufferDescription.BindFlags == (D3D.BindFlags.VertexBuffer))
			{
				return BufferType.Vertex;
			}
			if (bufferDescription.BindFlags == (D3D.BindFlags.IndexBuffer))
			{
				return BufferType.Index;
			}
			if (bufferDescription.BindFlags == (D3D.BindFlags.UnorderedAccess | D3D.BindFlags.ShaderResource))
			{
				return BufferType.Compute;
			}
			throw new ArgumentOutOfRangeException("bufferDescription.BindFlags", bufferDescription.BindFlags, "value not handled");
		}

		static private CodeTimer s_ctCreateBufferA = CodeTimer.Request(typeof(BufferHelper), "CreateBufferA");
		
		static public D3D.Buffer CreateBuffer(D3D.Device device, BufferType bufferType, int elementCount, Type elementType)
		{
			Debug2.Assert(device != null);
			using (s_ctCreateBufferA.TimeSection())
			{
				int sizeOfT = System.Runtime.InteropServices.Marshal.SizeOf(elementType);

				D3D.BufferDescription bufferDescription = CreateBufferDescription(bufferType, elementCount, elementType);

				return new D3D.Buffer(device, bufferDescription);
			}
		}

		static private CodeTimer s_ctCreateBufferB = CodeTimer.Request(typeof(BufferHelper), "CreateBufferB");
	
		static public D3D.Buffer CreateBuffer(D3D.Device device, BufferType bufferType, Array elementData, Type elementType, Type bufferElementType )
		{
			Debug2.Assert(device != null);
			Debug2.Assert(elementData != null);
			using (s_ctCreateBufferB.TimeSection())
			{

				int sizeOfT = System.Runtime.InteropServices.Marshal.SizeOf(bufferElementType);
				int sizeOfV = System.Runtime.InteropServices.Marshal.SizeOf(elementType);
				int vElementCount = elementData.Length;
				int bufferSizeInBytes = sizeOfV * vElementCount;
				int tElementCount = bufferSizeInBytes / sizeOfT;
				Debug2.Assert((bufferSizeInBytes % sizeOfT) == 0);

				D3D.BufferDescription bufferDescription = CreateBufferDescription(bufferType, tElementCount, bufferElementType);

				using (DataStream dataStream = new DataStream(elementData, true, false))
				{
					D3D.Buffer buffer = new D3D.Buffer(device, dataStream, bufferDescription);
					Debug2.Assert(buffer.Description.StructureByteStride == bufferDescription.StructureByteStride);
					return buffer;
				}
			}
		}

		static public void CopyBuffer(D3D.Buffer sourceBuffer, D3D.Buffer destinationBuffer)
		{
			Debug2.Assert(sourceBuffer != null);
			Debug2.Assert(destinationBuffer != null);
			Debug2.Assert(sourceBuffer.Device == destinationBuffer.Device );
			Debug2.Assert(sourceBuffer.Description.SizeInBytes == destinationBuffer.Description.SizeInBytes);
			Debug2.Assert(sourceBuffer.Description.StructureByteStride == destinationBuffer.Description.StructureByteStride);

			D3D.Device device = sourceBuffer.Device;
			device.ImmediateContext.CopyResource(sourceBuffer, destinationBuffer);
		}

		static public T[] ReadData<T>(D3D.Buffer buffer) where T : struct
		{
			Debug2.Assert(buffer != null);
			int sizeOfT = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
			Debug2.Assert(buffer.Description.StructureByteStride == sizeOfT);
			int elementCount = buffer.Description.SizeInBytes / sizeOfT;

			T[] elementData = new T[elementCount];

			ReadData<T>(buffer, elementData);
			return elementData;
		}

		static public void ReadData<T>(D3D.Buffer buffer, T[] elementData ) where T : struct
		{
			Debug2.Assert(buffer != null);
			Debug2.Assert(elementData != null);
			int sizeOfT = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
			//Debug2.Assert(buffer.Description.StructureByteStride == sizeOfT);
			int elementCount = buffer.Description.SizeInBytes / sizeOfT;

			Debug2.Assert(elementData.Length == elementCount );

			D3D.BufferDescription bufferDescription = new D3D.BufferDescription(
						elementCount * sizeOfT,
						D3D.ResourceUsage.Staging,
						D3D.BindFlags.None,
						D3D.CpuAccessFlags.Read,
						D3D.ResourceOptionFlags.StructuredBuffer,
						sizeOfT);
		
			D3D.Device device = buffer.Device;

			using (D3D.Buffer stagingBuffer = new D3D.Buffer(device, bufferDescription))
			{
				device.ImmediateContext.CopyResource(buffer, stagingBuffer);
				DataBox dataBox = device.ImmediateContext.MapSubresource(stagingBuffer, 0, stagingBuffer.Description.SizeInBytes, D3D.MapMode.Read, D3D.MapFlags.None);
				dataBox.Data.ReadRange<T>(elementData, 0, elementCount );
				device.ImmediateContext.UnmapSubresource(stagingBuffer, 0);
			}
		}

		public static void WriteData<T,V>(V[] data, D3D.Buffer buffer) where T : struct where V : struct
		{
			Debug2.Assert(data != null);
			Debug2.Assert(buffer != null);

			D3D.Device device = buffer.Device;

			BufferType bufferType = GetBufferType(buffer.Description);
			using (D3D.Buffer dataBuffer = CreateBuffer(device, bufferType, data, typeof(V), typeof(T)))
			{
				Debug2.Assert(dataBuffer.Description.SizeInBytes == buffer.Description.SizeInBytes);

				device.ImmediateContext.CopyResource(dataBuffer, buffer);
			}
		}


		public static D3D.ShaderResourceView CreateShaderResourceView(D3D.Buffer buffer)
		{
			return new D3D.ShaderResourceView(buffer.Device, buffer);
		}

		public static D3D.UnorderedAccessView CreateUnorderedAccessView(D3D.Buffer buffer)
		{
			Debug2.Assert(GetBufferType(buffer.Description) == BufferType.Compute);
			return new D3D.UnorderedAccessView(buffer.Device, buffer);
		}

	}
}