diff --git a/OpenRA.Game/Graphics/PlatformInterfaces.cs b/OpenRA.Game/Graphics/PlatformInterfaces.cs index c740b744da..c5d32db3e5 100644 --- a/OpenRA.Game/Graphics/PlatformInterfaces.cs +++ b/OpenRA.Game/Graphics/PlatformInterfaces.cs @@ -84,6 +84,7 @@ namespace OpenRA public interface IGraphicsContext : IDisposable { IVertexBuffer CreateVertexBuffer(int size); + Vertex[] CreateVertices(int size); ITexture CreateTexture(); IFrameBuffer CreateFrameBuffer(Size s); IFrameBuffer CreateFrameBuffer(Size s, Color clearColor); @@ -105,6 +106,11 @@ namespace OpenRA { void Bind(); void SetData(T[] vertices, int length); + + /// + /// Upon return `vertices` may reference another array object of at least the same size - containing random values. + /// + void SetData(ref T[] vertices, int length); void SetData(T[] vertices, int offset, int start, int length); } diff --git a/OpenRA.Game/Graphics/SpriteRenderer.cs b/OpenRA.Game/Graphics/SpriteRenderer.cs index 02b222566a..5ed582fa03 100644 --- a/OpenRA.Game/Graphics/SpriteRenderer.cs +++ b/OpenRA.Game/Graphics/SpriteRenderer.cs @@ -23,7 +23,7 @@ namespace OpenRA.Graphics readonly Renderer renderer; readonly IShader shader; - readonly Vertex[] vertices; + Vertex[] vertices; readonly Sheet[] sheets = new Sheet[SheetCount]; BlendMode currentBlend = BlendMode.Alpha; @@ -34,7 +34,7 @@ namespace OpenRA.Graphics { this.renderer = renderer; this.shader = shader; - vertices = new Vertex[renderer.TempBufferSize]; + vertices = renderer.Context.CreateVertices(renderer.TempBufferSize); } public void Flush() @@ -49,7 +49,9 @@ namespace OpenRA.Graphics renderer.Context.SetBlendMode(currentBlend); shader.PrepareRender(); - renderer.DrawBatch(vertices, nv, PrimitiveType.TriangleList); + + // PERF: The renderer may choose to replace vertices with a different temporary buffer. + renderer.DrawBatch(ref vertices, nv, PrimitiveType.TriangleList); renderer.Context.SetBlendMode(BlendMode.None); nv = 0; diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index 7f086198fc..5ecc6cd02a 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -333,6 +333,12 @@ namespace OpenRA DrawBatch(tempBuffer, 0, numVertices, type); } + public void DrawBatch(ref Vertex[] vertices, int numVertices, PrimitiveType type) + { + tempBuffer.SetData(ref vertices, numVertices); + DrawBatch(tempBuffer, 0, numVertices, type); + } + public void DrawBatch(IVertexBuffer vertices, int firstVertex, int numVertices, PrimitiveType type) where T : struct diff --git a/OpenRA.Platforms.Default/Sdl2GraphicsContext.cs b/OpenRA.Platforms.Default/Sdl2GraphicsContext.cs index 942f52d4bf..ec95eadc73 100644 --- a/OpenRA.Platforms.Default/Sdl2GraphicsContext.cs +++ b/OpenRA.Platforms.Default/Sdl2GraphicsContext.cs @@ -67,6 +67,12 @@ namespace OpenRA.Platforms.Default return new VertexBuffer(size); } + public Vertex[] CreateVertices(int size) + { + VerifyThreadAffinity(); + return new Vertex[size]; + } + public ITexture CreateTexture() { VerifyThreadAffinity(); diff --git a/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs b/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs index 81a9047556..b2fe4aa96c 100644 --- a/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs +++ b/OpenRA.Platforms.Default/ThreadedGraphicsContext.cs @@ -404,6 +404,11 @@ namespace OpenRA.Platforms.Default return Send(getCreateVertexBuffer, length); } + public Vertex[] CreateVertices(int size) + { + return GetVertices(size); + } + public void DisableDepthBuffer() { Post(doDisableDepthBuffer); @@ -526,6 +531,16 @@ namespace OpenRA.Platforms.Default device.Post(setData1, (buffer, length)); } + /// + /// PERF: The vertices array is passed without copying to the render thread. Upon return `vertices` may reference another + /// array object of at least the same size - containing random values. + /// + public void SetData(ref Vertex[] vertices, int length) + { + device.Post(setData1, (vertices, length)); + vertices = device.GetVertices(vertices.Length); + } + public void SetData(Vertex[] vertices, int offset, int start, int length) { if (length <= device.BatchSize) diff --git a/OpenRA.Platforms.Default/VertexBuffer.cs b/OpenRA.Platforms.Default/VertexBuffer.cs index af4f91aa47..4ffa5d4b2a 100644 --- a/OpenRA.Platforms.Default/VertexBuffer.cs +++ b/OpenRA.Platforms.Default/VertexBuffer.cs @@ -60,6 +60,11 @@ namespace OpenRA.Platforms.Default SetData(data, 0, 0, length); } + public void SetData(ref T[] data, int length) + { + SetData(data, 0, 0, length); + } + public void SetData(T[] data, int offset, int start, int length) { Bind();