Skip to content

Commit

Permalink
Transfer buffer improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Terria-K committed Oct 29, 2024
1 parent 5f97afd commit 1cbeb9c
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 51 deletions.
42 changes: 18 additions & 24 deletions Riateu/Core/Graphics/Batch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public class Batch : System.IDisposable
private const uint MaxTextures = 4096;
private const uint InitialMaxQueues = 4;
private GraphicsDevice device;
private unsafe BatchData* datas;

private bool rendered;
private bool flushed;
Expand All @@ -28,6 +27,10 @@ public class Batch : System.IDisposable
private TransferBuffer transferComputeBuffer;
private BatchQueue[] queues = new BatchQueue[InitialMaxQueues];

public StructuredBuffer<PositionTextureColorVertex> VertexBuffer => vertexBuffer;
public StructuredBuffer<uint> IndexBuffer => indexBuffer;
public StructuredBuffer<BatchData> ComputeBuffer => computeBuffer;

#if DEBUG
private bool DEBUG_begin;
private bool DEBUG_isFlushed;
Expand Down Expand Up @@ -72,22 +75,21 @@ public Batch(GraphicsDevice device, int width, int height)
Matrix = view * projection;
}

private static unsafe StructuredBuffer<uint> GenerateIndexArray(GraphicsDevice device, uint maxIndices)
private static StructuredBuffer<uint> GenerateIndexArray(GraphicsDevice device, uint maxIndices)
{
using TransferBuffer transferBuffer = TransferBuffer.Create<uint>(device, TransferBufferUsage.Upload, maxIndices);
StructuredBuffer<uint> indexBuffer = new StructuredBuffer<uint>(device, BufferUsageFlags.Index, maxIndices);

var mapPtr = transferBuffer.UnsafeMap(false);
uint* indexPtr = (uint*)mapPtr;
Span<uint> indexPtr = transferBuffer.Map<uint>(false);

for (uint i = 0, j = 0; i < maxIndices; i += 6, j += 4)
{
indexPtr[i] = j;
indexPtr[i + 1] = j + 1;
indexPtr[i + 2] = j + 2;
indexPtr[i + 3] = j + 2;
indexPtr[i + 4] = j + 1;
indexPtr[i + 5] = j + 3;
indexPtr[(int)i] = j;
indexPtr[(int)i + 1] = j + 1;
indexPtr[(int)i + 2] = j + 2;
indexPtr[(int)i + 3] = j + 2;
indexPtr[(int)i + 4] = j + 1;
indexPtr[(int)i + 5] = j + 3;
}
transferBuffer.Unmap();

Expand Down Expand Up @@ -166,11 +168,7 @@ public void Begin(Texture texture, Sampler sampler, Material material, Matrix4x4
Offset = vertexIndex,
Matrix = transform
};

unsafe {
var data = transferComputeBuffer.UnsafeMap(true);
datas = (BatchData*)data;
}
transferComputeBuffer.Map(true);
}

/// <summary>
Expand Down Expand Up @@ -290,10 +288,7 @@ internal void ResizeBuffer()
computeBuffer.Dispose();
computeBuffer = new StructuredBuffer<BatchData>(device, BufferUsageFlags.ComputeStorageRead, maxTextures);
currentMaxTexture = maxTextures;
unsafe {
var data = transferComputeBuffer.UnsafeMap(true);
datas = (BatchData*)data;
}
transferComputeBuffer.Map(true);
}

/// <summary>
Expand Down Expand Up @@ -416,7 +411,8 @@ public unsafe void Draw(TextureQuad quad, Vector2 position, Color color, Vector2
{
ResizeBuffer();
}
datas[vertexIndex] = new BatchData
var datas = transferComputeBuffer.MappedTouch<BatchData>();
datas[(int)vertexIndex] = new BatchData
{
Position = position,
Scale = scale,
Expand Down Expand Up @@ -470,9 +466,7 @@ public void Draw(SpriteFont font, string text, Vector2 position, Color color, Ve
_ => throw new NotImplementedException()
};

unsafe {
font.Draw(datas, ref vertexIndex, text, position, justify, color, scale, layerDepth);
}
font.Draw(transferComputeBuffer.MappedTouch<BatchData>(), ref vertexIndex, text, position, justify, color, scale, layerDepth);
}

#if DEBUG
Expand Down Expand Up @@ -518,7 +512,7 @@ private struct BatchQueue
}

[StructLayout(LayoutKind.Explicit, Size = 96)]
internal struct BatchData
public struct BatchData
{
[FieldOffset(0)]
public Vector2 Position;
Expand Down
4 changes: 2 additions & 2 deletions Riateu/Core/Graphics/ResourceUploader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ private void CopyToTransferBuffer()
bufferTransferBuffer = new TransferBuffer(Device, TransferBufferUsage.Upload, bufferDataSize);
}

var span = bufferTransferBuffer.Map(true);
var span = bufferTransferBuffer.Map(true, 0);
fixed (byte *ptr = span)
{
NativeMemory.Copy(bufferData, ptr, bufferDataSize);
Expand All @@ -212,7 +212,7 @@ private void CopyToTransferBuffer()
textureTransferBuffer = new TransferBuffer(Device, TransferBufferUsage.Upload, textureDataSize);
}

var span = textureTransferBuffer.Map(true);
var span = textureTransferBuffer.Map(true, 0);
fixed (byte *ptr = span)
{
NativeMemory.Copy(textureData, ptr, textureDataSize);
Expand Down
4 changes: 2 additions & 2 deletions Riateu/Core/Graphics/SpriteFont.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public SpriteFontCharacter GetCharacter(int c)
throw new Exception($"A character: '{(char)c}' is not available");
}

internal unsafe void Draw(Batch.BatchData* computeData, ref uint vertexIndex, ReadOnlySpan<char> text, Vector2 position, Vector2 justify, Color color, Vector2 scale, float layerDepth = 1f)
internal void Draw(Span<Batch.BatchData> computeData, ref uint vertexIndex, ReadOnlySpan<char> text, Vector2 position, Vector2 justify, Color color, Vector2 scale, float layerDepth = 1f)
{
if (text.IsEmpty)
return;
Expand Down Expand Up @@ -299,7 +299,7 @@ internal unsafe void Draw(Batch.BatchData* computeData, ref uint vertexIndex, Re

lastCodePoint = ch;

computeData[vertexIndex] = new Batch.BatchData
computeData[(int)vertexIndex] = new Batch.BatchData
{
Position = pos,
Scale = scale,
Expand Down
51 changes: 31 additions & 20 deletions Riateu/Core/Graphics/TransferBuffer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SDL3;

Expand All @@ -8,10 +9,8 @@ namespace Riateu.Graphics;
public class TransferBuffer : GraphicsResource
{
public uint Size { get; }
private IntPtr mappedPointer;

#if DEBUG
public bool IsMapped { get; private set; }
#endif

public TransferBuffer(GraphicsDevice device, TransferBufferUsage usage, uint size) : base(device)
{
Expand All @@ -29,42 +28,46 @@ public unsafe static TransferBuffer Create<T>(GraphicsDevice device, TransferBuf
return new TransferBuffer(device, usage, size * (uint)sizeof(T));
}

public unsafe byte* UnsafeMap(bool cycle)
public void Map(bool cycle)
{
if (mappedPointer != IntPtr.Zero)
{
return;
}
mappedPointer = (IntPtr)SDL.SDL_MapGPUTransferBuffer(Device.Handle, Handle, cycle);
}

public unsafe Span<byte> Map(bool cycle, uint offset = 0)
{
#if DEBUG
AssertNotMapped();
IsMapped = true;
#endif
var data = (byte*)SDL.SDL_MapGPUTransferBuffer(Device.Handle, Handle, cycle);
return data;
Map(cycle);
return new Span<byte>((void*)(mappedPointer + offset), (int)(Size - offset));
}

public unsafe Span<byte> Map(bool cycle)
public unsafe Span<T> Map<T>(bool cycle, uint offset = 0)
where T : unmanaged
{
#if DEBUG
AssertNotMapped();
IsMapped = true;
#endif
var data = (byte*)SDL.SDL_MapGPUTransferBuffer(Device.Handle, Handle, cycle);
return new Span<byte>(data, (int)Size);
Map(cycle);
return new Span<T>((void*)(mappedPointer + offset), (int)(Size - offset) / Unsafe.SizeOf<T>());
}

public unsafe Span<T> Map<T>(bool cycle)
public unsafe Span<T> MappedTouch<T>(uint offset = 0)
{
#if DEBUG
AssertNotMapped();
IsMapped = true;
AssertMapped();
#endif
var data = (byte*)SDL.SDL_MapGPUTransferBuffer(Device.Handle, Handle, cycle);
return new Span<T>(data, (int)Size);
return new Span<T>((void*)(mappedPointer + offset), (int)(Size - offset) / Unsafe.SizeOf<T>());
}

public void Unmap()
{
#if DEBUG
IsMapped = false;
#endif
SDL.SDL_UnmapGPUTransferBuffer(Device.Handle, Handle);
mappedPointer = IntPtr.Zero;
}

public unsafe uint SetTransferData<T>(Span<T> source, uint bufferOffsetInBytes, bool cycle)
Expand Down Expand Up @@ -124,9 +127,17 @@ protected override void HandleDispose(nint handle)
}

#if DEBUG
private void AssertMapped()
{
if (mappedPointer == IntPtr.Zero)
{
throw new Exception("Transfer buffer has not mapped yet.");
}
}

private void AssertNotMapped()
{
if (IsMapped)
if (mappedPointer != IntPtr.Zero)
{
throw new Exception("Transfer buffer is still mapping.");
}
Expand Down
6 changes: 3 additions & 3 deletions Riateu/Core/ImGui/ImGuiRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ public ImGuiRenderer(GraphicsDevice device, Window window, int width, int height
io.DisplayFramebufferScale = System.Numerics.Vector2.One;
imGuiShader = Resources.GetShader(device, Resources.ImGuiShader, "main", new ShaderCreateInfo {
ShaderStage = ShaderStage.Vertex,
ShaderFormat = GameContext.BackendShaderFormat,
ShaderFormat = GraphicsDevice.BackendShaderFormat,
UniformBufferCount = 1
});
imGuiSampler = new Sampler(device, SamplerCreateInfo.PointClamp);

var fragmentShader = Resources.GetShader(device, Resources.Texture, "main", new ShaderCreateInfo {
ShaderStage = ShaderStage.Fragment,
ShaderFormat = GameContext.BackendShaderFormat,
ShaderFormat = GraphicsDevice.BackendShaderFormat,
SamplerCount = 1
});

Expand Down Expand Up @@ -213,7 +213,7 @@ private unsafe void UpdateImGuiBuffers(ImDrawDataPtr drawDataPtr)
int indexSize = 0;
int indexOffset = drawDataPtr.TotalVtxCount * sizeof(Position2DTextureColorVertex);

var vertexIndexData = transferBuffer.Map(true);
var vertexIndexData = transferBuffer.Map(true, 0);
fixed (byte *ptr = vertexIndexData)
{
for (var n = 0; n < drawDataPtr.CmdListsCount; n += 1)
Expand Down

0 comments on commit 1cbeb9c

Please sign in to comment.