Skip to content

Commit c761fd3

Browse files
[Rendering] Improve instancing buffer usage;
1 parent b36e465 commit c761fd3

File tree

4 files changed

+65
-47
lines changed

4 files changed

+65
-47
lines changed

Engine/Staple.Core/Rendering/Mesh/MeshRenderSystem.cs

Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ private struct InstanceInfo
2424
private class InstanceData
2525
{
2626
public ExpandableContainer<InstanceInfo> instanceInfos = new();
27-
public Matrix4x4[] transformMatrices = [];
2827
}
2928

3029
private readonly Dictionary<int, InstanceData> instanceCache = [];
3130

32-
private readonly Dictionary<int, VertexBuffer> instanceBuffers = [];
31+
private VertexBuffer instanceBuffer;
32+
private int instanceOffset;
33+
private int instanceCount;
34+
private Matrix4x4[] transformMatrices = [];
3335

3436
private readonly Lazy<VertexLayout> instanceLayout = new(() =>
3537
{
@@ -59,27 +61,6 @@ public void Prepare()
5961
}
6062
#endregion
6163

62-
private VertexBuffer GetInstanceBuffer(int count)
63-
{
64-
if (instanceBuffers.TryGetValue(count, out var buffer) && buffer.Disposed == false)
65-
{
66-
return buffer;
67-
}
68-
69-
buffer = VertexBuffer.Create(new Matrix4x4[count], instanceLayout.Value, RenderBufferFlags.GraphicsRead);
70-
71-
if((buffer?.Disposed ?? true))
72-
{
73-
instanceBuffers.Remove(count);
74-
75-
return null;
76-
}
77-
78-
instanceBuffers.AddOrSetKey(count, buffer);
79-
80-
return buffer;
81-
}
82-
8364
/// <summary>
8465
/// Renders a mesh
8566
/// </summary>
@@ -258,13 +239,7 @@ void Add(Material material, int submeshIndex)
258239
}
259240
}
260241

261-
foreach (var p in instanceCache)
262-
{
263-
if(p.Value.instanceInfos.Length != p.Value.transformMatrices.Length)
264-
{
265-
Array.Resize(ref p.Value.transformMatrices, p.Value.instanceInfos.Length);
266-
}
267-
}
242+
instanceOffset = 0;
268243
}
269244

270245
public void Submit()
@@ -275,6 +250,50 @@ public void Submit()
275250
enableDepth = true,
276251
};
277252

253+
if(instanceBuffer?.Disposed ?? true)
254+
{
255+
instanceBuffer = VertexBuffer.Create(new Matrix4x4[1], instanceLayout.Value, RenderBufferFlags.GraphicsRead);
256+
}
257+
258+
instanceCount = instanceOffset = 0;
259+
260+
foreach (var (_, contents) in instanceCache)
261+
{
262+
if (contents.instanceInfos.Length <= 1)
263+
{
264+
continue;
265+
}
266+
267+
instanceCount += contents.instanceInfos.Length;
268+
}
269+
270+
if (instanceCount > 0)
271+
{
272+
if(instanceCount > transformMatrices.Length)
273+
{
274+
Array.Resize(ref transformMatrices, instanceCount);
275+
}
276+
277+
foreach (var (_, contents) in instanceCache)
278+
{
279+
if (contents.instanceInfos.Length <= 1)
280+
{
281+
continue;
282+
}
283+
284+
for(var i = 0; i < contents.instanceInfos.Length; i++)
285+
{
286+
transformMatrices[instanceOffset++] = contents.instanceInfos.Contents[i].transform.Matrix;
287+
}
288+
}
289+
290+
instanceOffset = 0;
291+
292+
var span = new Span<Matrix4x4>(transformMatrices, 0, instanceCount);
293+
294+
instanceBuffer.Update(span);
295+
}
296+
278297
foreach (var (_, contents) in instanceCache)
279298
{
280299
if (contents.instanceInfos.Length == 0)
@@ -284,6 +303,9 @@ public void Submit()
284303

285304
renderState.ClearStorageBuffers();
286305

306+
renderState.instanceCount = 1;
307+
renderState.instanceOffset = 0;
308+
287309
var renderData = contents.instanceInfos.Contents[0];
288310

289311
var material = renderData.material;
@@ -324,25 +346,14 @@ public void Submit()
324346

325347
contents.instanceInfos.Contents[0].mesh.SetActive(ref renderState, contents.instanceInfos.Contents[0].submeshIndex);
326348

327-
for (var i = 0; i < contents.instanceInfos.Length; i++)
328-
{
329-
contents.transformMatrices[i] = contents.instanceInfos.Contents[i].transform.Matrix;
330-
}
331-
332-
var buffer = GetInstanceBuffer(contents.transformMatrices.Length);
333-
334-
if(buffer == null)
349+
if (instanceBuffer != null)
335350
{
336-
continue;
337-
}
338-
339-
buffer.Update(contents.transformMatrices);
351+
renderState.instanceOffset = instanceOffset;
352+
renderState.instanceCount = contents.instanceInfos.Length;
340353

341-
if (buffer != null)
342-
{
343-
renderState.instanceCount = contents.transformMatrices.Length;
354+
instanceOffset += renderState.instanceCount;
344355

345-
renderState.ApplyStorageBufferIfNeeded("StapleInstancingTransforms", buffer);
356+
renderState.ApplyStorageBufferIfNeeded("StapleInstancingTransforms", instanceBuffer);
346357

347358
RenderSystem.Submit(renderState, renderData.mesh.SubmeshTriangleCount(contents.instanceInfos.Contents[0].submeshIndex),
348359
contents.instanceInfos.Length);

Engine/Staple.Core/Rendering/RenderSystem/Backend/Impls/SDLGPU/SDLGPURendererBackend.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ internal struct StapleRenderData
3030
public Matrix4x4 world;
3131
public Matrix4x4 view;
3232
public Matrix4x4 projection;
33+
public int instanceOffset;
3334
}
3435

3536
[StructLayout(LayoutKind.Sequential, Pack = 0)]
@@ -1471,6 +1472,7 @@ state.indexBuffer is not SDLGPUIndexBuffer index ||
14711472
unsafe
14721473
{
14731474
viewData.renderData.world = state.world;
1475+
viewData.renderData.instanceOffset = state.instanceOffset > 0 ? state.instanceOffset : 0;
14741476

14751477
fixed (void* ptr = &viewData.renderData)
14761478
{
@@ -1636,6 +1638,7 @@ public void RenderTransient<T>(Span<T> vertices, VertexLayout layout, Span<ushor
16361638
unsafe
16371639
{
16381640
viewData.renderData.world = state.world;
1641+
viewData.renderData.instanceOffset = 0;
16391642

16401643
fixed (void* ptr = &viewData.renderData)
16411644
{
@@ -1802,6 +1805,7 @@ public void RenderTransient<T>(Span<T> vertices, VertexLayout layout, Span<uint>
18021805
unsafe
18031806
{
18041807
viewData.renderData.world = state.world;
1808+
viewData.renderData.instanceOffset = 0;
18051809

18061810
fixed (void* ptr = &viewData.renderData)
18071811
{

Engine/Staple.Core/Rendering/RenderSystem/Backend/RenderState.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal struct RenderState
2929
public Texture[] vertexTextures;
3030
public Texture[] fragmentTextures;
3131
public Matrix4x4 world;
32+
public int instanceOffset;
3233
public int instanceCount;
3334

3435
public readonly RenderState Clone()
@@ -56,6 +57,7 @@ public readonly RenderState Clone()
5657
vertexTextures = (Texture[])vertexTextures?.Clone(),
5758
wireframe = wireframe,
5859
world = world,
60+
instanceOffset = instanceOffset,
5961
instanceCount = instanceCount,
6062
};
6163
}

Tools/ShaderIncludes/Staple.slang

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public cbuffer StapleRenderData
1010
public float4x4 world;
1111
public float4x4 view;
1212
public float4x4 projection;
13+
public int instanceOffset;
1314
};
1415

1516
[[vk::binding(1, StapleUniformBufferSet)]]
@@ -49,6 +50,6 @@ public float4x4 StapleGetSkinningMatrix(float4x4 world, float4 indices, float4 w
4950
#ifdef INSTANCING
5051
public float4x4 StapleGetInstancedTransform(uint index)
5152
{
52-
return StapleInstancingTransforms[index];
53+
return StapleInstancingTransforms[index + instanceOffset];
5354
}
5455
#endif

0 commit comments

Comments
 (0)