rendered paste bodyusing 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);
}
}
}