Significantly reduce allocation of GCHandles, replace with inlined fixed statement in GL class.

This commit is contained in:
UnknownShadow200 2015-08-03 20:08:04 +10:00
parent dd2eb1105a
commit 281e815125
5 changed files with 52 additions and 31 deletions

View file

@ -306,11 +306,16 @@ namespace ClassicalSharp.GraphicsAPI {
device.SetVertexFormat( formatMapping[(int)VertexFormat.Pos3fTex2fCol4b] );
batchStride = VertexPos3fTex2fCol4b.Size;
}
public override void DrawIndexedVbBatch( DrawMode mode, int vb, int ib, int indicesCount,
int startVertex, int startIndex ) {
device.SetIndices( iBuffers[ib] );
public override void BindVb( int vb ) {
device.SetStreamSource( 0, vBuffers[vb], 0, batchStride );
}
public override void BindIb( int ib ) {
device.SetIndices( iBuffers[ib] );
}
public override void DrawIndexedVb( DrawMode mode, int indicesCount, int startVertex, int startIndex ) {
device.DrawIndexedPrimitives( modeMappings[(int)mode], startVertex, startVertex,
indicesCount / 6 * 4, startIndex, NumPrimitives( indicesCount, mode ) );
}

View file

@ -110,6 +110,8 @@ namespace ClassicalSharp.GraphicsAPI {
public abstract int InitIb( ushort[] indices, int indicesCount );
public abstract int InitIb( IntPtr indices, int indicesCount );
public abstract bool IsValidVb( int vb );
public abstract bool IsValidIb( int ib );

View file

@ -184,45 +184,47 @@ namespace ClassicalSharp.GraphicsAPI {
#region Vertex buffers
Action setupBatchFunc;
Action setupBatchFuncTex2f, setupBatchFuncCol4b, setupBatchFuncTex2fCol4b;
Action setupBatchFuncTex2f, setupBatchFuncCol4b, setupBatchFuncTex2fCol4b;
public unsafe override int CreateDynamicVb( VertexFormat format, int maxVertices ) {
int id = 0;
GL.GenBuffersARB( 1, &id );
int id = GenAndBind( BufferTarget.ArrayBuffer );
int sizeInBytes = maxVertices * strideSizes[(int)format];
GL.BindBufferARB( BufferTarget.ArrayBuffer, id );
GL.BufferDataARB( BufferTarget.ArrayBuffer, new IntPtr( sizeInBytes ), IntPtr.Zero, BufferUsageHint.DynamicDraw );
return id;
}
public unsafe override int InitVb<T>( T[] vertices, VertexFormat format, int count ) {
int id = 0;
GL.GenBuffersARB( 1, &id );
int id = GenAndBind( BufferTarget.ArrayBuffer );
int sizeInBytes = count * strideSizes[(int)format];
GL.BindBufferARB( BufferTarget.ArrayBuffer, id );
GCHandle handle = GCHandle.Alloc( vertices, GCHandleType.Pinned );
GL.BufferDataARB( BufferTarget.ArrayBuffer, new IntPtr( sizeInBytes ), handle.AddrOfPinnedObject(), BufferUsageHint.StaticDraw );
handle.Free();
GL.BufferDataARB( BufferTarget.ArrayBuffer, new IntPtr( sizeInBytes ), vertices, BufferUsageHint.StaticDraw );
return id;
}
public unsafe override int InitIb( ushort[] indices, int indicesCount ) {
int id = GenAndBind( BufferTarget.ElementArrayBuffer );
int sizeInBytes = indicesCount * sizeof( ushort );
GL.BufferDataARB( BufferTarget.ElementArrayBuffer, new IntPtr( sizeInBytes ), indices, BufferUsageHint.StaticDraw );
return id;
}
public unsafe override int InitIb( IntPtr indices, int indicesCount ) {
int id = GenAndBind( BufferTarget.ElementArrayBuffer );
int sizeInBytes = indicesCount * sizeof( ushort );
GL.BufferDataARB( BufferTarget.ElementArrayBuffer, new IntPtr( sizeInBytes ), indices, BufferUsageHint.StaticDraw );
return id;
}
unsafe static int GenAndBind( BufferTarget target ) {
int id = 0;
GL.GenBuffersARB( 1, &id );
int sizeInBytes = indicesCount * sizeof( ushort );
GL.BindBufferARB( BufferTarget.ElementArrayBuffer, id );
fixed( ushort* ptr = indices ) {
GL.BufferDataARB( BufferTarget.ElementArrayBuffer, new IntPtr( sizeInBytes ), (IntPtr)ptr, BufferUsageHint.StaticDraw );
}
GL.BindBufferARB( target, id );
return id;
}
public override void DrawDynamicVb<T>( DrawMode mode, int id, T[] vertices, VertexFormat format, int count ) {
int sizeInBytes = count * strideSizes[(int)format];
GL.BindBufferARB( BufferTarget.ArrayBuffer, id );
GCHandle handle = GCHandle.Alloc( vertices, GCHandleType.Pinned );
GL.BufferSubDataARB( BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr( sizeInBytes ), handle.AddrOfPinnedObject() );
handle.Free();
GL.BufferSubDataARB( BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr( sizeInBytes ), vertices );
BeginVbBatch( format );
setupBatchFunc();
@ -317,20 +319,21 @@ namespace ClassicalSharp.GraphicsAPI {
GL.BindBufferARB( BufferTarget.ElementArrayBuffer, 0 );
}
IntPtr zero = new IntPtr( 0 ), twelve = new IntPtr( 12 ), sixteen = new IntPtr( 16 );
void SetupVbPos3fTex2f() {
GL.VertexPointer( 3, PointerType.Float, 20, new IntPtr( 0 ) );
GL.TexCoordPointer( 2, PointerType.Float, 20, new IntPtr( 12 ) );
GL.VertexPointer( 3, PointerType.Float, VertexPos3fTex2f.Size, zero );
GL.TexCoordPointer( 2, PointerType.Float, VertexPos3fTex2f.Size, twelve );
}
void SetupVbPos3fCol4b() {
GL.VertexPointer( 3, PointerType.Float, 16, new IntPtr( 0 ) );
GL.ColorPointer( 4, PointerType.UnsignedByte, 16, new IntPtr( 12 ) );
GL.VertexPointer( 3, PointerType.Float, VertexPos3fCol4b.Size, zero );
GL.ColorPointer( 4, PointerType.UnsignedByte, VertexPos3fCol4b.Size, twelve );
}
void SetupVbPos3fTex2fCol4b() {
GL.VertexPointer( 3, PointerType.Float, 24, new IntPtr( 0 ) );
GL.ColorPointer( 4, PointerType.UnsignedByte, 24, new IntPtr( 12 ) );
GL.TexCoordPointer( 2, PointerType.Float, 24, new IntPtr( 16 ) );
GL.VertexPointer( 3, PointerType.Float, VertexPos3fTex2fCol4b.Size, zero );
GL.ColorPointer( 4, PointerType.UnsignedByte, VertexPos3fTex2fCol4b.Size, twelve );
GL.TexCoordPointer( 2, PointerType.Float, VertexPos3fTex2fCol4b.Size, sixteen );
}
#endregion
@ -378,8 +381,8 @@ namespace ClassicalSharp.GraphicsAPI {
game.SwapBuffers();
}
public override void SetVSync( Game game, bool value ) {
game.VSync = value;
public override void SetVSync( Game game, bool value ) {
game.VSync = value;
}
public unsafe override void PrintApiSpecificInfo() {

View file

@ -38,6 +38,11 @@ namespace OpenTK.Graphics.OpenGL {
Interop.Calli( (int)target, size, data, (int)usage, BufferDataARBAddress );
} static IntPtr BufferDataARBAddress;
public static void BufferDataARB<T>( BufferTarget target, IntPtr size, T[] data, BufferUsageHint usage ) where T : struct {
IntPtr dataPtr = Interop.Fixed( ref data[0] );
Interop.Calli( (int)target, size, dataPtr, (int)usage, BufferDataARBAddress );
}
public static void BufferSubData( BufferTarget target, IntPtr offset, IntPtr size, IntPtr data ) {
Interop.Calli( (int)target, offset, size, data, BufferSubDataAddress );
} static IntPtr BufferSubDataAddress;
@ -45,6 +50,11 @@ namespace OpenTK.Graphics.OpenGL {
public static void BufferSubDataARB( BufferTarget target, IntPtr offset, IntPtr size, IntPtr data ) {
Interop.Calli( (int)target, offset, size, data, BufferSubDataARBAddress );
} static IntPtr BufferSubDataARBAddress;
public static void BufferSubDataARB<T>( BufferTarget target, IntPtr offset, IntPtr size, T[] data ) where T : struct {
IntPtr dataPtr = Interop.Fixed( ref data[0] );
Interop.Calli( (int)target, offset, size, dataPtr, BufferSubDataARBAddress );
}
public static void Clear( ClearBufferMask mask ) {
Interop.Calli( (int)mask, ClearAddress );

View file

@ -5,6 +5,7 @@ namespace OpenTK.Graphics.OpenGL {
internal static unsafe class Interop {
static Exception rewriteEx = new NotImplementedException( "You need to run InteropPatcher on this dll." );
public static IntPtr Fixed<T>( ref T data ) { throw rewriteEx; }
public static void Calli( IntPtr address ) { throw rewriteEx; }
public static int Calli_Int32( IntPtr address ) { throw rewriteEx; }
public static void Calli( int arg0, IntPtr address ) { throw rewriteEx; }