Remove Vertex from PlatformInterfaces

This commit is contained in:
Gustas
2023-09-13 10:44:08 +03:00
committed by Matthias Mailänder
parent d77fd5c13e
commit 0a90c2a95e
7 changed files with 67 additions and 41 deletions

View File

@@ -10,7 +10,6 @@
#endregion
using System;
using OpenRA.Graphics;
using OpenRA.Primitives;
namespace OpenRA
@@ -83,9 +82,9 @@ namespace OpenRA
public interface IGraphicsContext : IDisposable
{
IVertexBuffer<Vertex> CreateVertexBuffer(int size);
IVertexBuffer<T> CreateVertexBuffer<T>(int size) where T : struct;
T[] CreateVertices<T>(int size) where T : struct;
IIndexBuffer CreateIndexBuffer(uint[] indices);
Vertex[] CreateVertices(int size);
ITexture CreateTexture();
IFrameBuffer CreateFrameBuffer(Size s);
IFrameBuffer CreateFrameBuffer(Size s, Color clearColor);
@@ -104,7 +103,7 @@ namespace OpenRA
string GLVersion { get; }
}
public interface IVertexBuffer<T> : IDisposable
public interface IVertexBuffer<T> : IDisposable where T : struct
{
void Bind();
void SetData(T[] vertices, int length);

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Graphics
{
this.renderer = renderer;
this.shader = shader;
vertices = renderer.Context.CreateVertices(renderer.TempVertexBufferSize);
vertices = renderer.Context.CreateVertices<Vertex>(renderer.TempVertexBufferSize);
}
public void Flush()

View File

@@ -51,7 +51,7 @@ namespace OpenRA.Graphics
vertexRowStride = 4 * map.MapSize.X;
vertices = new Vertex[vertexRowStride * map.MapSize.Y];
vertexBuffer = Game.Renderer.Context.CreateVertexBuffer(vertices.Length);
vertexBuffer = Game.Renderer.Context.CreateVertexBuffer<Vertex>(vertices.Length);
indexRowStride = 6 * map.MapSize.X;
lock (IndexBuffers)

View File

@@ -96,7 +96,7 @@ namespace OpenRA
RgbaSpriteRenderer = new RgbaSpriteRenderer(SpriteRenderer);
RgbaColorRenderer = new RgbaColorRenderer(SpriteRenderer);
tempVertexBuffer = Context.CreateVertexBuffer(TempVertexBufferSize);
tempVertexBuffer = Context.CreateVertexBuffer<Vertex>(TempVertexBufferSize);
quadIndexBuffer = Context.CreateIndexBuffer(Util.CreateQuadIndices(TempIndexBufferSize / 6));
}
@@ -382,9 +382,9 @@ namespace OpenRA
}
}
public IVertexBuffer<Vertex> CreateVertexBuffer(int length)
public IVertexBuffer<T> CreateVertexBuffer<T>(int length) where T : struct
{
return Context.CreateVertexBuffer(length);
return Context.CreateVertexBuffer<T>(length);
}
public void EnableScissor(Rectangle rect)

View File

@@ -195,7 +195,7 @@ namespace OpenRA.Mods.Cnc.Graphics
public void RefreshBuffer()
{
vertexBuffer?.Dispose();
vertexBuffer = Game.Renderer.CreateVertexBuffer(totalVertexCount);
vertexBuffer = Game.Renderer.CreateVertexBuffer<Vertex>(totalVertexCount);
vertexBuffer.SetData(vertices.SelectMany(v => v).ToArray(), totalVertexCount);
cachedVertexCount = totalVertexCount;
}

View File

@@ -10,7 +10,6 @@
#endregion
using System;
using OpenRA.Graphics;
using OpenRA.Primitives;
using SDL2;
@@ -62,10 +61,10 @@ namespace OpenRA.Platforms.Default
OpenGL.CheckGLError();
}
public IVertexBuffer<Vertex> CreateVertexBuffer(int size)
public IVertexBuffer<T> CreateVertexBuffer<T>(int size) where T : struct
{
VerifyThreadAffinity();
return new VertexBuffer<Vertex>(size);
return new VertexBuffer<T>(size);
}
public IIndexBuffer CreateIndexBuffer(uint[] indices)
@@ -74,10 +73,10 @@ namespace OpenRA.Platforms.Default
return new StaticIndexBuffer(indices);
}
public Vertex[] CreateVertices(int size)
public T[] CreateVertices<T>(int size) where T : struct
{
VerifyThreadAffinity();
return new Vertex[size];
return new T[size];
}
public ITexture CreateTexture()

View File

@@ -13,7 +13,6 @@ using System;
using System.Collections.Generic;
using System.Runtime.ExceptionServices;
using System.Threading;
using OpenRA.Graphics;
using OpenRA.Primitives;
namespace OpenRA.Platforms.Default
@@ -25,7 +24,7 @@ namespace OpenRA.Platforms.Default
sealed class ThreadedGraphicsContext : IGraphicsContext
{
// PERF: Maintain several object pools to reduce allocations.
readonly Stack<Vertex[]> verticesPool = new();
readonly Dictionary<Type, object> vertexBufferPools = new();
readonly Stack<Message> messagePool = new();
readonly Queue<Message> messages = new();
@@ -46,7 +45,7 @@ namespace OpenRA.Platforms.Default
Func<ITexture> getCreateTexture;
Func<object, IFrameBuffer> getCreateFrameBuffer;
Func<object, IShader> getCreateShader;
Func<object, IVertexBuffer<Vertex>> getCreateVertexBuffer;
Func<object, object> getCreateVertexBuffer;
Func<object, IIndexBuffer> getCreateIndexBuffer;
Action<object> doDrawPrimitives;
Action<object> doDrawElements;
@@ -97,7 +96,13 @@ namespace OpenRA.Platforms.Default
context.CreateFrameBuffer(t.Item1, (ITextureInternal)CreateTexture(), t.Item2));
};
getCreateShader = name => new ThreadedShader(this, context.CreateShader((string)name));
getCreateVertexBuffer = length => new ThreadedVertexBuffer(this, context.CreateVertexBuffer((int)length));
getCreateVertexBuffer =
tuple =>
{
(object t, var type) = ((int, Type))tuple;
var vertexBuffer = context.GetType().GetMethod(nameof(CreateVertexBuffer)).MakeGenericMethod(type).Invoke(context, new[] { t });
return typeof(ThreadedVertexBuffer<>).MakeGenericType(type).GetConstructors()[0].Invoke(new[] { this, vertexBuffer });
};
getCreateIndexBuffer = indices => new ThreadedIndexBuffer(this, context.CreateIndexBuffer((uint[])indices));
doDrawPrimitives =
tuple =>
@@ -150,20 +155,31 @@ namespace OpenRA.Platforms.Default
}
}
internal Vertex[] GetVertices(int size)
internal T[] GetVertices<T>(int size)
{
lock (verticesPool)
if (size <= VertexBatchSize && verticesPool.Count > 0)
return verticesPool.Pop();
lock (vertexBufferPools)
{
Stack<T[]> pool;
if (!vertexBufferPools.TryGetValue(typeof(T), out var poolObject))
{
pool = new Stack<T[]>();
vertexBufferPools.Add(typeof(T), pool);
}
else
pool = (Stack<T[]>)poolObject;
return new Vertex[size < VertexBatchSize ? VertexBatchSize : size];
if (size <= VertexBatchSize && pool.Count > 0)
return pool.Pop();
}
internal void ReturnVertices(Vertex[] vertices)
return new T[size < VertexBatchSize ? VertexBatchSize : size];
}
internal void ReturnVertices<T>(T[] vertices)
{
if (vertices.Length == VertexBatchSize)
lock (verticesPool)
verticesPool.Push(vertices);
lock (vertexBufferPools)
((Stack<T[]>)vertexBufferPools[typeof(T)]).Push(vertices);
}
sealed class Message
@@ -410,9 +426,9 @@ namespace OpenRA.Platforms.Default
return Send(getCreateTexture);
}
public IVertexBuffer<Vertex> CreateVertexBuffer(int length)
public IVertexBuffer<T> CreateVertexBuffer<T>(int size) where T : struct
{
return Send(getCreateVertexBuffer, length);
return (IVertexBuffer<T>)Send(getCreateVertexBuffer, (size, typeof(T)));
}
public IIndexBuffer CreateIndexBuffer(uint[] indices)
@@ -420,9 +436,9 @@ namespace OpenRA.Platforms.Default
return Send(getCreateIndexBuffer, indices);
}
public Vertex[] CreateVertices(int size)
public T[] CreateVertices<T>(int size) where T : struct
{
return GetVertices(size);
return GetVertices<T>(size);
}
public void DisableDepthBuffer()
@@ -521,7 +537,7 @@ namespace OpenRA.Platforms.Default
}
}
sealed class ThreadedVertexBuffer : IVertexBuffer<Vertex>
sealed class ThreadedVertexBuffer<T> : IVertexBuffer<T> where T : struct
{
readonly ThreadedGraphicsContext device;
readonly Action bind;
@@ -530,12 +546,24 @@ namespace OpenRA.Platforms.Default
readonly Func<object, object> setData3;
readonly Action dispose;
public ThreadedVertexBuffer(ThreadedGraphicsContext device, IVertexBuffer<Vertex> vertexBuffer)
public ThreadedVertexBuffer(ThreadedGraphicsContext device, IVertexBuffer<T> vertexBuffer)
{
this.device = device;
bind = vertexBuffer.Bind;
setData1 = tuple => { var t = ((Vertex[], int))tuple; vertexBuffer.SetData(t.Item1, t.Item2); device.ReturnVertices(t.Item1); };
setData2 = tuple => { var t = ((Vertex[], int, int, int))tuple; vertexBuffer.SetData(t.Item1, t.Item2, t.Item3, t.Item4); device.ReturnVertices(t.Item1); };
setData1 = tuple =>
{
var t = ((T[], int))tuple;
vertexBuffer.SetData(t.Item1, t.Item2);
device.ReturnVertices(t.Item1);
};
setData2 = tuple =>
{
var t = ((T[], int, int, int))tuple;
vertexBuffer.SetData(t.Item1, t.Item2, t.Item3, t.Item4);
device.ReturnVertices(t.Item1);
};
setData3 = tuple => { setData2(tuple); return null; };
dispose = vertexBuffer.Dispose;
}
@@ -545,9 +573,9 @@ namespace OpenRA.Platforms.Default
device.Post(bind);
}
public void SetData(Vertex[] vertices, int length)
public void SetData(T[] vertices, int length)
{
var buffer = device.GetVertices(length);
var buffer = device.GetVertices<T>(length);
Array.Copy(vertices, buffer, length);
device.Post(setData1, (buffer, length));
}
@@ -556,18 +584,18 @@ namespace OpenRA.Platforms.Default
/// 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.
/// </summary>
public void SetData(ref Vertex[] vertices, int length)
public void SetData(ref T[] vertices, int length)
{
device.Post(setData1, (vertices, length));
vertices = device.GetVertices(vertices.Length);
vertices = device.GetVertices<T>(vertices.Length);
}
public void SetData(Vertex[] vertices, int offset, int start, int length)
public void SetData(T[] vertices, int offset, int start, int length)
{
if (length <= device.VertexBatchSize)
{
// If we are able to use a buffer without allocation, post a message to avoid blocking.
var buffer = device.GetVertices(length);
var buffer = device.GetVertices<T>(length);
Array.Copy(vertices, offset, buffer, 0, length);
device.Post(setData2, (buffer, 0, start, length));
}