From 54afbcdb651d297006b9611a16fbd0f5ba39aad9 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 16 Aug 2015 06:43:37 +1000 Subject: [PATCH] Combine IndexBuffer and VertexBuffer, simplify methods of setting data, use inlined fixed instead of GCHandles. --- ClassicalSharp/GraphicsAPI/Direct3D9Api.cs | 74 +++++----------------- SharpDX/SharpDX.Direct3D/Device.cs | 12 ++-- SharpDX/SharpDX.Direct3D/Direct3D.cs | 25 ++++++++ SharpDX/SharpDX.Direct3D/Resources.cs | 42 ++++++------ 4 files changed, 68 insertions(+), 85 deletions(-) diff --git a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs index 753829f66..51ef91bc4 100644 --- a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs +++ b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs @@ -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[] 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( ref T[] array, T value, int expSize ) { // Find first free slot for( int i = 1; i < array.Length; i++ ) { diff --git a/SharpDX/SharpDX.Direct3D/Device.cs b/SharpDX/SharpDX.Direct3D/Device.cs index 4eb96fd80..8a962e054 100644 --- a/SharpDX/SharpDX.Direct3D/Device.cs +++ b/SharpDX/SharpDX.Direct3D/Device.cs @@ -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 ); } } diff --git a/SharpDX/SharpDX.Direct3D/Direct3D.cs b/SharpDX/SharpDX.Direct3D/Direct3D.cs index 00aadad84..68c3f2992 100644 --- a/SharpDX/SharpDX.Direct3D/Direct3D.cs +++ b/SharpDX/SharpDX.Direct3D/Direct3D.cs @@ -34,6 +34,7 @@ namespace SharpDX.Direct3D9 { Adapters = new List( count ); for( int i = 0; i < count; i++ ) Adapters.Add( new AdapterInformation( this, i ) ); + memcpy64Bit = IntPtr.Size == 8; } public List 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++; + } + } } } diff --git a/SharpDX/SharpDX.Direct3D/Resources.cs b/SharpDX/SharpDX.Direct3D/Resources.cs index 58a17ccd4..596cdfd8c 100644 --- a/SharpDX/SharpDX.Direct3D/Resources.cs +++ b/SharpDX/SharpDX.Direct3D/Resources.cs @@ -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[] 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 ); } - } - } }