From 3f8c1ad5df853cb76f1bf65c7777fcbbbc65d3ba Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Mon, 20 Nov 2017 20:11:29 +0000 Subject: [PATCH] Don't allocate a full-sized array when creating a VertexBuffer. We can allocate a much smaller zeroed buffer and copy that multiple times in order to zero the memory. When creating large VertexBuffers, this caps our temporary allocation size significantly. --- OpenRA.Platforms.Default/VertexBuffer.cs | 27 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/OpenRA.Platforms.Default/VertexBuffer.cs b/OpenRA.Platforms.Default/VertexBuffer.cs index 8ad4d8acf2..08a48d8015 100644 --- a/OpenRA.Platforms.Default/VertexBuffer.cs +++ b/OpenRA.Platforms.Default/VertexBuffer.cs @@ -27,20 +27,32 @@ namespace OpenRA.Platforms.Default OpenGL.CheckGLError(); Bind(); - var ptr = GCHandle.Alloc(new T[size], GCHandleType.Pinned); + // Generates a buffer with uninitialized memory. + OpenGL.glBufferData(OpenGL.GL_ARRAY_BUFFER, + new IntPtr(VertexSize * size), + IntPtr.Zero, + OpenGL.GL_DYNAMIC_DRAW); + OpenGL.CheckGLError(); + + // We need to zero all the memory. Let's generate a smallish array and copy that over the whole buffer. + var zeroedArrayElementSize = Math.Min(size, 2048); + var ptr = GCHandle.Alloc(new T[zeroedArrayElementSize], GCHandleType.Pinned); try { - OpenGL.glBufferData(OpenGL.GL_ARRAY_BUFFER, - new IntPtr(VertexSize * size), - ptr.AddrOfPinnedObject(), - OpenGL.GL_DYNAMIC_DRAW); + for (var offset = 0; offset < size; offset += zeroedArrayElementSize) + { + var length = Math.Min(zeroedArrayElementSize, size - offset); + OpenGL.glBufferSubData(OpenGL.GL_ARRAY_BUFFER, + new IntPtr(VertexSize * offset), + new IntPtr(VertexSize * length), + ptr.AddrOfPinnedObject()); + OpenGL.CheckGLError(); + } } finally { ptr.Free(); } - - OpenGL.CheckGLError(); } public void SetData(T[] data, int length) @@ -108,6 +120,7 @@ namespace OpenRA.Platforms.Default return; disposed = true; OpenGL.glDeleteBuffers(1, ref buffer); + OpenGL.CheckGLError(); } } }