Initialise VertexBuffers immediately

This commit is contained in:
Gustas
2025-02-22 16:04:23 +02:00
committed by Paul Chote
parent a2096b6768
commit 39aec39364
10 changed files with 63 additions and 18 deletions

View File

@@ -83,7 +83,8 @@ namespace OpenRA
public interface IGraphicsContext : IDisposable public interface IGraphicsContext : IDisposable
{ {
IVertexBuffer<T> CreateVertexBuffer<T>(int size) where T : struct; IVertexBuffer<T> CreateEmptyVertexBuffer<T>(int size) where T : struct;
IVertexBuffer<T> CreateVertexBuffer<T>(T[] data, bool dynamic = true) where T : struct;
T[] CreateVertices<T>(int size) where T : struct; T[] CreateVertices<T>(int size) where T : struct;
IIndexBuffer CreateIndexBuffer(uint[] indices); IIndexBuffer CreateIndexBuffer(uint[] indices);
ITexture CreateTexture(); ITexture CreateTexture();

View File

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

View File

@@ -107,7 +107,7 @@ namespace OpenRA
RgbaSpriteRenderer = new RgbaSpriteRenderer(SpriteRenderer); RgbaSpriteRenderer = new RgbaSpriteRenderer(SpriteRenderer);
RgbaColorRenderer = new RgbaColorRenderer(SpriteRenderer); RgbaColorRenderer = new RgbaColorRenderer(SpriteRenderer);
tempVertexBuffer = Context.CreateVertexBuffer<Vertex>(TempVertexBufferSize); tempVertexBuffer = Context.CreateEmptyVertexBuffer<Vertex>(TempVertexBufferSize);
quadIndexBuffer = Context.CreateIndexBuffer(Util.CreateQuadIndices(TempIndexBufferSize / 6)); quadIndexBuffer = Context.CreateIndexBuffer(Util.CreateQuadIndices(TempIndexBufferSize / 6));
worldBufferSnapshot = Context.CreateTexture(); worldBufferSnapshot = Context.CreateTexture();
} }
@@ -406,9 +406,9 @@ namespace OpenRA
return Context.CreateShader(bindings); return Context.CreateShader(bindings);
} }
public IVertexBuffer<T> CreateVertexBuffer<T>(int length) where T : struct public IVertexBuffer<T> CreateVertexBuffer<T>(T[] data, bool dynamic) where T : struct
{ {
return Context.CreateVertexBuffer<T>(length); return Context.CreateVertexBuffer(data, dynamic);
} }
public void EnableScissor(Rectangle rect) public void EnableScissor(Rectangle rect)

View File

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

View File

@@ -37,7 +37,6 @@ namespace OpenRA.Mods.Cnc.Traits
shader = renderer.CreateShader(new RenderPostProcessPassTexturedShaderBindings("vortex")); shader = renderer.CreateShader(new RenderPostProcessPassTexturedShaderBindings("vortex"));
vortexSheet = new Sheet(SheetType.BGRA, new Size(512, 512)); vortexSheet = new Sheet(SheetType.BGRA, new Size(512, 512));
vortexBuffer = renderer.CreateVertexBuffer<RenderPostProcessPassTexturedVertex>(288);
var vertices = new RenderPostProcessPassTexturedVertex[288]; var vertices = new RenderPostProcessPassTexturedVertex[288];
var data = vortexSheet.GetData(); var data = vortexSheet.GetData();
@@ -72,7 +71,7 @@ namespace OpenRA.Mods.Cnc.Traits
vertices[j++] = new RenderPostProcessPassTexturedVertex(-32, -32, tl.X, tl.Y); vertices[j++] = new RenderPostProcessPassTexturedVertex(-32, -32, tl.X, tl.Y);
} }
vortexBuffer.SetData(ref vertices, 288); vortexBuffer = renderer.CreateVertexBuffer(vertices, false);
vortexSheet.CommitBufferedData(); vortexSheet.CommitBufferedData();
} }

View File

@@ -36,8 +36,7 @@ namespace OpenRA.Mods.Common.Traits
new(-1, -1) new(-1, -1)
}; };
buffer = renderer.CreateVertexBuffer<RenderPostProcessPassVertex>(6); buffer = renderer.CreateVertexBuffer(vertices, false);
buffer.SetData(ref vertices, 6);
} }
PostProcessPassType IRenderPostProcessPass.Type => type; PostProcessPassType IRenderPostProcessPass.Type => type;

View File

@@ -42,7 +42,6 @@ namespace OpenRA.Mods.D2k.Traits
Info = info; Info = info;
renderer = Game.Renderer; renderer = Game.Renderer;
shader = renderer.CreateShader(new RenderPostProcessPassTexturedShaderBindings("sonic")); shader = renderer.CreateShader(new RenderPostProcessPassTexturedShaderBindings("sonic"));
buffer = renderer.CreateVertexBuffer<RenderPostProcessPassTexturedVertex>(6);
var r = 0.5f * info.Size; var r = 0.5f * info.Size;
shader.SetVec("Scale", r * (1f / info.Zoom - 1)); shader.SetVec("Scale", r * (1f / info.Zoom - 1));
@@ -56,7 +55,7 @@ namespace OpenRA.Mods.D2k.Traits
new(-r, -r, -1, -1) new(-r, -r, -1, -1)
}; };
buffer.SetData(ref vertices, 6); buffer = renderer.CreateVertexBuffer(vertices, false);
} }
public void Draw(float3 pos) public void Draw(float3 pos)

View File

@@ -49,12 +49,18 @@ namespace OpenRA.Platforms.Default
OpenGL.CheckGLError(); OpenGL.CheckGLError();
} }
public IVertexBuffer<T> CreateVertexBuffer<T>(int size) where T : struct public IVertexBuffer<T> CreateEmptyVertexBuffer<T>(int size) where T : struct
{ {
VerifyThreadAffinity(); VerifyThreadAffinity();
return new VertexBuffer<T>(size); return new VertexBuffer<T>(size);
} }
public IVertexBuffer<T> CreateVertexBuffer<T>(T[] data, bool dynamic = true) where T : struct
{
VerifyThreadAffinity();
return new VertexBuffer<T>(data, dynamic);
}
public IIndexBuffer CreateIndexBuffer(uint[] indices) public IIndexBuffer CreateIndexBuffer(uint[] indices)
{ {
VerifyThreadAffinity(); VerifyThreadAffinity();

View File

@@ -45,6 +45,7 @@ namespace OpenRA.Platforms.Default
Func<ITexture> getCreateTexture; Func<ITexture> getCreateTexture;
Func<object, IFrameBuffer> getCreateFrameBuffer; Func<object, IFrameBuffer> getCreateFrameBuffer;
Func<object, IShader> getCreateShader; Func<object, IShader> getCreateShader;
Func<object, object> getCreateEmptyVertexBuffer;
Func<object, object> getCreateVertexBuffer; Func<object, object> getCreateVertexBuffer;
Func<object, IIndexBuffer> getCreateIndexBuffer; Func<object, IIndexBuffer> getCreateIndexBuffer;
Action<object> doDrawPrimitives; Action<object> doDrawPrimitives;
@@ -96,11 +97,25 @@ namespace OpenRA.Platforms.Default
context.CreateFrameBuffer(t.Item1, (ITextureInternal)CreateTexture(), t.Item2)); context.CreateFrameBuffer(t.Item1, (ITextureInternal)CreateTexture(), t.Item2));
}; };
getCreateShader = bindings => new ThreadedShader(this, context.CreateShader((IShaderBindings)bindings)); getCreateShader = bindings => new ThreadedShader(this, context.CreateShader((IShaderBindings)bindings));
getCreateVertexBuffer = getCreateEmptyVertexBuffer =
tuple => tuple =>
{ {
(object t, var type) = ((int, Type))tuple; (object t, var type) = ((int, Type))tuple;
var vertexBuffer = context.GetType().GetMethod(nameof(CreateVertexBuffer)).MakeGenericMethod(type).Invoke(context, [t]); var vertexBuffer = context.GetType()
.GetMethod(nameof(CreateEmptyVertexBuffer))
.MakeGenericMethod(type)
.Invoke(context, [t]);
return typeof(ThreadedVertexBuffer<>).MakeGenericType(type).GetConstructors()[0].Invoke([this, vertexBuffer]);
};
getCreateVertexBuffer =
tuple =>
{
var (array, dynamic, type) = ((object, bool, Type))tuple;
var vertexBuffer = context.GetType()
.GetMethod(nameof(CreateVertexBuffer))
.MakeGenericMethod(type)
.Invoke(context, [array, dynamic]);
return typeof(ThreadedVertexBuffer<>).MakeGenericType(type).GetConstructors()[0].Invoke([this, vertexBuffer]); return typeof(ThreadedVertexBuffer<>).MakeGenericType(type).GetConstructors()[0].Invoke([this, vertexBuffer]);
}; };
getCreateIndexBuffer = indices => new ThreadedIndexBuffer(this, context.CreateIndexBuffer((uint[])indices)); getCreateIndexBuffer = indices => new ThreadedIndexBuffer(this, context.CreateIndexBuffer((uint[])indices));
@@ -426,9 +441,14 @@ namespace OpenRA.Platforms.Default
return Send(getCreateTexture); return Send(getCreateTexture);
} }
public IVertexBuffer<T> CreateVertexBuffer<T>(int size) where T : struct public IVertexBuffer<T> CreateEmptyVertexBuffer<T>(int size) where T : struct
{ {
return (IVertexBuffer<T>)Send(getCreateVertexBuffer, (size, typeof(T))); return (IVertexBuffer<T>)Send(getCreateEmptyVertexBuffer, (size, typeof(T)));
}
public IVertexBuffer<T> CreateVertexBuffer<T>(T[] data, bool dynamic = true) where T : struct
{
return (IVertexBuffer<T>)Send(getCreateVertexBuffer, ((object)data, dynamic, typeof(T)));
} }
public IIndexBuffer CreateIndexBuffer(uint[] indices) public IIndexBuffer CreateIndexBuffer(uint[] indices)

View File

@@ -55,6 +55,28 @@ namespace OpenRA.Platforms.Default
} }
} }
public VertexBuffer(T[] data, bool dynamic = true)
{
OpenGL.glGenBuffers(1, out buffer);
OpenGL.CheckGLError();
Bind();
var ptr = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
OpenGL.glBufferData(OpenGL.GL_ARRAY_BUFFER,
new IntPtr(VertexSize * data.Length),
ptr.AddrOfPinnedObject(),
dynamic ? OpenGL.GL_DYNAMIC_DRAW : OpenGL.GL_STATIC_DRAW);
}
finally
{
ptr.Free();
}
OpenGL.CheckGLError();
}
public void SetData(T[] data, int length) public void SetData(T[] data, int length)
{ {
SetData(data, 0, 0, length); SetData(data, 0, 0, length);