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; const int texBufferSize = 512, iBufferSize = 256, vBufferSize = 2048;
D3D.Texture[] textures = new D3D.Texture[texBufferSize]; D3D.Texture[] textures = new D3D.Texture[texBufferSize];
VertexBuffer[] vBuffers = new VertexBuffer[vBufferSize]; DataBuffer[] vBuffers = new DataBuffer[vBufferSize];
IndexBuffer[] iBuffers = new IndexBuffer[iBufferSize]; DataBuffer[] iBuffers = new DataBuffer[iBufferSize];
MatrixStack viewStack, projStack, texStack; MatrixStack viewStack, projStack, texStack;
MatrixStack curStack; MatrixStack curStack;
PrimitiveType[] modeMappings = { PrimitiveType[] modeMappings = {
@ -165,10 +165,7 @@ namespace ClassicalSharp.GraphicsAPI {
public override int CreateTexture( int width, int height, IntPtr scan0 ) { public override int CreateTexture( int width, int height, IntPtr scan0 ) {
D3D.Texture texture = device.CreateTexture( width, height, 0, Usage.None, Format.A8R8G8B8, Pool.Managed ); D3D.Texture texture = device.CreateTexture( width, height, 0, Usage.None, Format.A8R8G8B8, Pool.Managed );
LockedRectangle vbData = texture.LockRectangle( 0, LockFlags.None ); texture.SetData( scan0, width * height * 4, 0, LockFlags.None );
IntPtr dest = vbData.DataPointer;
memcpy( scan0, dest, width * height * 4 );
texture.UnlockRectangle( 0 );
return GetOrExpand( ref textures, texture, texBufferSize ); return GetOrExpand( ref textures, texture, texBufferSize );
} }
@ -230,50 +227,33 @@ namespace ClassicalSharp.GraphicsAPI {
}; };
public override int CreateVb<T>( T[] vertices, VertexFormat format, int count ) { public override int CreateVb<T>( T[] vertices, VertexFormat format, int count ) {
GCHandle handle = GCHandle.Alloc( vertices, GCHandleType.Pinned ); int size = count * strideSizes[(int)format];
VertexBuffer buffer = CreateVertexBuffer( handle.AddrOfPinnedObject(), count, format ); DataBuffer buffer = device.CreateVertexBuffer( size, Usage.None, formatMapping[(int)format], Pool.Managed );
handle.Free(); buffer.SetData( vertices, size, LockFlags.None );
return GetOrExpand( ref vBuffers, buffer, vBufferSize ); return GetOrExpand( ref vBuffers, buffer, vBufferSize );
} }
public override int CreateVb( IntPtr vertices, VertexFormat format, int count ) { 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 ); return GetOrExpand( ref vBuffers, buffer, vBufferSize );
} }
public unsafe override int CreateIb( ushort[] indices, int indicesCount ) { public unsafe override int CreateIb( ushort[] indices, int indicesCount ) {
IndexBuffer buffer; int size = indicesCount * sizeof( ushort );
fixed( ushort* src = indices ) DataBuffer buffer = device.CreateIndexBuffer( size, Usage.None, Format.Index16, Pool.Managed );
buffer = CreateIndexBuffer( (IntPtr)src, indicesCount ); buffer.SetData( indices, size, LockFlags.None );
return GetOrExpand( ref iBuffers, buffer, iBufferSize ); return GetOrExpand( ref iBuffers, buffer, iBufferSize );
} }
public override int CreateIb( IntPtr indices, int indicesCount ) { 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 ); 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 ) { public override void DeleteVb( int vb ) {
Delete( vBuffers, vb ); Delete( vBuffers, vb );
} }
@ -475,28 +455,6 @@ namespace ClassicalSharp.GraphicsAPI {
return args; 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 ) { static int GetOrExpand<T>( ref T[] array, T value, int expSize ) {
// Find first free slot // Find first free slot
for( int i = 1; i < array.Length; i++ ) { for( int i = 1; i < array.Length; i++ ) {

View File

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

View File

@ -34,6 +34,7 @@ namespace SharpDX.Direct3D9 {
Adapters = new List<AdapterInformation>( count ); Adapters = new List<AdapterInformation>( count );
for( int i = 0; i < count; i++ ) for( int i = 0; i < count; i++ )
Adapters.Add( new AdapterInformation( this, i ) ); Adapters.Add( new AdapterInformation( this, i ) );
memcpy64Bit = IntPtr.Size == 8;
} }
public List<AdapterInformation> Adapters; public List<AdapterInformation> Adapters;
@ -103,5 +104,29 @@ namespace SharpDX.Direct3D9 {
if( res < 0 ) { throw new SharpDXException( res ); } if( res < 0 ) { throw new SharpDXException( res ); }
return new Device( devicePtr ); 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] [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 ) { public IntPtr Lock( int offsetToLock, int sizeToLock, LockFlags flags ) {
@ -54,6 +54,19 @@ namespace SharpDX.Direct3D9 {
return pOut; 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() { public void Unlock() {
int res = Interop.Calli(comPointer, (*(IntPtr**)comPointer)[12]); int res = Interop.Calli(comPointer, (*(IntPtr**)comPointer)[12]);
if( res < 0 ) { throw new SharpDXException( res ); } if( res < 0 ) { throw new SharpDXException( res ); }
@ -92,28 +105,15 @@ namespace SharpDX.Direct3D9 {
return lockedRect; 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) { public void UnlockRectangle(int level) {
int res = Interop.Calli(comPointer, level,(*(IntPtr**)comPointer)[20]); int res = Interop.Calli(comPointer, level,(*(IntPtr**)comPointer)[20]);
if( res < 0 ) { throw new SharpDXException( res ); } 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 ); }
}
}
} }