Combine IndexBuffer and VertexBuffer, simplify methods of setting data, use inlined fixed instead of GCHandles.

This commit is contained in:
UnknownShadow200 2015-08-16 06:43:37 +10:00
parent cfeabc612a
commit 54afbcdb65
4 changed files with 68 additions and 85 deletions

View File

@ -21,8 +21,8 @@ namespace ClassicalSharp.GraphicsAPI {
const int texBufferSize = 512, iBufferSize = 256, vBufferSize = 2048;
D3D.Texture[] textures = new D3D.Texture[texBufferSize];
VertexBuffer[] vBuffers = new VertexBuffer[vBufferSize];
IndexBuffer[] iBuffers = new IndexBuffer[iBufferSize];
DataBuffer[] vBuffers = new DataBuffer[vBufferSize];
DataBuffer[] iBuffers = new DataBuffer[iBufferSize];
MatrixStack viewStack, projStack, texStack;
MatrixStack curStack;
PrimitiveType[] modeMappings = {
@ -165,10 +165,7 @@ namespace ClassicalSharp.GraphicsAPI {
public override int CreateTexture( int width, int height, IntPtr scan0 ) {
D3D.Texture texture = device.CreateTexture( width, height, 0, Usage.None, Format.A8R8G8B8, Pool.Managed );
LockedRectangle vbData = texture.LockRectangle( 0, LockFlags.None );
IntPtr dest = vbData.DataPointer;
memcpy( scan0, dest, width * height * 4 );
texture.UnlockRectangle( 0 );
texture.SetData( scan0, width * height * 4, 0, LockFlags.None );
return GetOrExpand( ref textures, texture, texBufferSize );
}
@ -230,50 +227,33 @@ namespace ClassicalSharp.GraphicsAPI {
};
public override int CreateVb<T>( T[] vertices, VertexFormat format, int count ) {
GCHandle handle = GCHandle.Alloc( vertices, GCHandleType.Pinned );
VertexBuffer buffer = CreateVertexBuffer( handle.AddrOfPinnedObject(), count, format );
handle.Free();
int size = count * strideSizes[(int)format];
DataBuffer buffer = device.CreateVertexBuffer( size, Usage.None, formatMapping[(int)format], Pool.Managed );
buffer.SetData( vertices, size, LockFlags.None );
return GetOrExpand( ref vBuffers, buffer, vBufferSize );
}
public override int CreateVb( IntPtr vertices, VertexFormat format, int count ) {
VertexBuffer buffer = CreateVertexBuffer( vertices, count, format );
int size = count * strideSizes[(int)format];
DataBuffer buffer = device.CreateVertexBuffer( size, Usage.None, formatMapping[(int)format], Pool.Managed );
buffer.SetData( vertices, size, LockFlags.None );
return GetOrExpand( ref vBuffers, buffer, vBufferSize );
}
public unsafe override int CreateIb( ushort[] indices, int indicesCount ) {
IndexBuffer buffer;
fixed( ushort* src = indices )
buffer = CreateIndexBuffer( (IntPtr)src, indicesCount );
int size = indicesCount * sizeof( ushort );
DataBuffer buffer = device.CreateIndexBuffer( size, Usage.None, Format.Index16, Pool.Managed );
buffer.SetData( indices, size, LockFlags.None );
return GetOrExpand( ref iBuffers, buffer, iBufferSize );
}
public override int CreateIb( IntPtr indices, int indicesCount ) {
IndexBuffer buffer = CreateIndexBuffer( indices, indicesCount );
int size = indicesCount * sizeof( ushort );
DataBuffer buffer = device.CreateIndexBuffer( size, Usage.None, Format.Index16, Pool.Managed );
buffer.SetData( indices, size, LockFlags.None );
return GetOrExpand( ref iBuffers, buffer, iBufferSize );
}
unsafe VertexBuffer CreateVertexBuffer( IntPtr src, int count, VertexFormat format ) {
int size = count * strideSizes[(int)format];
VertexBuffer buffer = device.CreateVertexBuffer( size, Usage.None, formatMapping[(int)format], Pool.Managed );
IntPtr vbData = buffer.Lock( 0, size, LockFlags.None );
memcpy( src, vbData, size );
buffer.Unlock();
return buffer;
}
unsafe IndexBuffer CreateIndexBuffer( IntPtr src, int count ) {
int size = count * sizeof( ushort );
IndexBuffer buffer = device.CreateIndexBuffer( size, Usage.None, Format.Index16, Pool.Managed );
IntPtr vbData = buffer.Lock( 0, size, LockFlags.None );
memcpy( src, vbData, size );
buffer.Unlock();
return buffer;
}
public override void DeleteVb( int vb ) {
Delete( vBuffers, vb );
}
@ -474,29 +454,7 @@ namespace ClassicalSharp.GraphicsAPI {
args.Windowed = true;
return args;
}
unsafe void memcpy( IntPtr srcPtr, IntPtr dstPtr, int bytes ) {
byte* srcByte, dstByte;
if( memcpy64Bit ) {
long* srcLong = (long*)srcPtr, dstLong = (long*)dstPtr;
while( bytes >= 8 ) {
*dstLong++ = *srcLong++;
bytes -= 8;
}
srcByte = (byte*)srcLong; dstByte = (byte*)dstLong;
} else {
int* srcInt = (int*)srcPtr, dstInt = (int*)dstPtr;
while( bytes >= 4 ) {
*dstInt++ = *srcInt++;
bytes -= 4;
}
srcByte = (byte*)srcInt; dstByte = (byte*)dstInt;
}
for( int i = 0; i < bytes; i++ ) {
*dstByte++ = *srcByte++;
}
}
static int GetOrExpand<T>( ref T[] array, T value, int expSize ) {
// Find first free slot
for( int i = 1; i < array.Length; i++ ) {

View File

@ -80,18 +80,18 @@ namespace SharpDX.Direct3D9
return new Texture( pOut );
}
public VertexBuffer CreateVertexBuffer(int length, Usage usage, VertexFormat vertexFormat, Pool pool) {
public DataBuffer CreateVertexBuffer(int length, Usage usage, VertexFormat vertexFormat, Pool pool) {
IntPtr pOut = IntPtr.Zero;
int res = Interop.Calli(comPointer, length, (int)usage, (int)vertexFormat, (int)pool, (IntPtr)(void*)&pOut, IntPtr.Zero,(*(IntPtr**)comPointer)[26]);
if( res < 0 ) { throw new SharpDXException( res ); }
return new VertexBuffer( pOut );
return new DataBuffer( pOut );
}
public IndexBuffer CreateIndexBuffer(int length, Usage usage, Format format, Pool pool) {
public DataBuffer CreateIndexBuffer(int length, Usage usage, Format format, Pool pool) {
IntPtr pOut = IntPtr.Zero;
int res = Interop.Calli(comPointer, length, (int)usage, (int)format, (int)pool, (IntPtr)(void*)&pOut, IntPtr.Zero,(*(IntPtr**)comPointer)[27]);
if( res < 0 ) { throw new SharpDXException( res ); }
return new IndexBuffer( pOut );
return new DataBuffer( pOut );
}
public void GetRenderTargetData(Surface renderTarget, Surface destSurface) {
@ -189,12 +189,12 @@ namespace SharpDX.Direct3D9
if( res < 0 ) { throw new SharpDXException( res ); }
}
public void SetStreamSource(int streamNumber, VertexBuffer streamData, int offsetInBytes, int stride) {
public void SetStreamSource(int streamNumber, DataBuffer streamData, int offsetInBytes, int stride) {
int res = Interop.Calli(comPointer, streamNumber,(streamData == null)?IntPtr.Zero:streamData.comPointer,offsetInBytes, stride,(*(IntPtr**)comPointer)[100]);
if( res < 0 ) { throw new SharpDXException( res ); }
}
public void SetIndices(IndexBuffer indexData) {
public void SetIndices(DataBuffer indexData) {
int res = Interop.Calli(comPointer,(indexData == null)?IntPtr.Zero:indexData.comPointer,(*(IntPtr**)comPointer)[104]);
if( res < 0 ) { throw new SharpDXException( res ); }
}

View File

@ -34,6 +34,7 @@ namespace SharpDX.Direct3D9 {
Adapters = new List<AdapterInformation>( count );
for( int i = 0; i < count; i++ )
Adapters.Add( new AdapterInformation( this, i ) );
memcpy64Bit = IntPtr.Size == 8;
}
public List<AdapterInformation> Adapters;
@ -103,5 +104,29 @@ namespace SharpDX.Direct3D9 {
if( res < 0 ) { throw new SharpDXException( res ); }
return new Device( devicePtr );
}
// TODO: Place this in a utilities class.
static bool memcpy64Bit;
internal static unsafe void memcpy( IntPtr srcPtr, IntPtr dstPtr, int bytes ) {
byte* srcByte, dstByte;
if( memcpy64Bit ) {
long* srcLong = (long*)srcPtr, dstLong = (long*)dstPtr;
while( bytes >= 8 ) {
*dstLong++ = *srcLong++;
bytes -= 8;
}
srcByte = (byte*)srcLong; dstByte = (byte*)dstLong;
} else {
int* srcInt = (int*)srcPtr, dstInt = (int*)dstPtr;
while( bytes >= 4 ) {
*dstInt++ = *srcInt++;
bytes -= 4;
}
srcByte = (byte*)srcInt; dstByte = (byte*)dstInt;
}
for( int i = 0; i < bytes; i++ ) {
*dstByte++ = *srcByte++;
}
}
}
}

View File

@ -42,9 +42,9 @@ namespace SharpDX.Direct3D9 {
}
[InteropPatch]
public unsafe class IndexBuffer : Resource {
public unsafe class DataBuffer : Resource { // Either 'VertexBuffer' or 'IndexBuffer
public IndexBuffer(IntPtr nativePtr) : base(nativePtr) {
public DataBuffer(IntPtr nativePtr) : base(nativePtr) {
}
public IntPtr Lock( int offsetToLock, int sizeToLock, LockFlags flags ) {
@ -54,6 +54,19 @@ namespace SharpDX.Direct3D9 {
return pOut;
}
public void SetData( IntPtr data, int bytes, LockFlags flags ) {
IntPtr dst = Lock( 0, bytes, flags );
Direct3D.memcpy( data, dst, bytes );
Unlock();
}
public void SetData<T>( T[] data, int bytes, LockFlags flags ) where T : struct {
IntPtr src = Interop.Fixed( ref data[0] );
IntPtr dst = Lock( 0, bytes, flags );
Direct3D.memcpy( src, dst, bytes );
Unlock();
}
public void Unlock() {
int res = Interop.Calli(comPointer, (*(IntPtr**)comPointer)[12]);
if( res < 0 ) { throw new SharpDXException( res ); }
@ -92,28 +105,15 @@ namespace SharpDX.Direct3D9 {
return lockedRect;
}
public void SetData( IntPtr data, int bytes, int level, LockFlags flags ) {
LockedRectangle rect = LockRectangle( level, flags );
Direct3D.memcpy( data, rect.DataPointer, bytes );
UnlockRectangle( level );
}
public void UnlockRectangle(int level) {
int res = Interop.Calli(comPointer, level,(*(IntPtr**)comPointer)[20]);
if( res < 0 ) { throw new SharpDXException( res ); }
}
}
[InteropPatch]
public unsafe class VertexBuffer : Resource {
public VertexBuffer(IntPtr nativePtr) : base(nativePtr) {
}
public IntPtr Lock( int offsetToLock, int sizeToLock, LockFlags flags ) {
IntPtr pOut;
int res = Interop.Calli(comPointer, offsetToLock, sizeToLock, (IntPtr)(void*)&pOut, (int)flags, (*(IntPtr**)comPointer)[11]);
if( res < 0 ) { throw new SharpDXException( res ); }
return pOut;
}
public void Unlock() {
int res = Interop.Calli(comPointer,(*(IntPtr**)comPointer)[12]);
if( res < 0 ) { throw new SharpDXException( res ); }
}
}
}