From 1cbeb9c3607c5ffa5e18fb8b3c267feeb4c13b97 Mon Sep 17 00:00:00 2001 From: Terria-K Date: Tue, 29 Oct 2024 22:14:16 +0800 Subject: [PATCH] Transfer buffer improvements --- Riateu/Core/Graphics/Batch.cs | 42 +++++++++---------- Riateu/Core/Graphics/ResourceUploader.cs | 4 +- Riateu/Core/Graphics/SpriteFont.cs | 4 +- Riateu/Core/Graphics/TransferBuffer.cs | 51 ++++++++++++++---------- Riateu/Core/ImGui/ImGuiRenderer.cs | 6 +-- 5 files changed, 56 insertions(+), 51 deletions(-) diff --git a/Riateu/Core/Graphics/Batch.cs b/Riateu/Core/Graphics/Batch.cs index f586aa3..e273aff 100755 --- a/Riateu/Core/Graphics/Batch.cs +++ b/Riateu/Core/Graphics/Batch.cs @@ -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; @@ -28,6 +27,10 @@ public class Batch : System.IDisposable private TransferBuffer transferComputeBuffer; private BatchQueue[] queues = new BatchQueue[InitialMaxQueues]; + public StructuredBuffer VertexBuffer => vertexBuffer; + public StructuredBuffer IndexBuffer => indexBuffer; + public StructuredBuffer ComputeBuffer => computeBuffer; + #if DEBUG private bool DEBUG_begin; private bool DEBUG_isFlushed; @@ -72,22 +75,21 @@ public Batch(GraphicsDevice device, int width, int height) Matrix = view * projection; } - private static unsafe StructuredBuffer GenerateIndexArray(GraphicsDevice device, uint maxIndices) + private static StructuredBuffer GenerateIndexArray(GraphicsDevice device, uint maxIndices) { using TransferBuffer transferBuffer = TransferBuffer.Create(device, TransferBufferUsage.Upload, maxIndices); StructuredBuffer indexBuffer = new StructuredBuffer(device, BufferUsageFlags.Index, maxIndices); - var mapPtr = transferBuffer.UnsafeMap(false); - uint* indexPtr = (uint*)mapPtr; + Span indexPtr = transferBuffer.Map(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(); @@ -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); } /// @@ -290,10 +288,7 @@ internal void ResizeBuffer() computeBuffer.Dispose(); computeBuffer = new StructuredBuffer(device, BufferUsageFlags.ComputeStorageRead, maxTextures); currentMaxTexture = maxTextures; - unsafe { - var data = transferComputeBuffer.UnsafeMap(true); - datas = (BatchData*)data; - } + transferComputeBuffer.Map(true); } /// @@ -416,7 +411,8 @@ public unsafe void Draw(TextureQuad quad, Vector2 position, Color color, Vector2 { ResizeBuffer(); } - datas[vertexIndex] = new BatchData + var datas = transferComputeBuffer.MappedTouch(); + datas[(int)vertexIndex] = new BatchData { Position = position, Scale = scale, @@ -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(), ref vertexIndex, text, position, justify, color, scale, layerDepth); } #if DEBUG @@ -518,7 +512,7 @@ private struct BatchQueue } [StructLayout(LayoutKind.Explicit, Size = 96)] - internal struct BatchData + public struct BatchData { [FieldOffset(0)] public Vector2 Position; diff --git a/Riateu/Core/Graphics/ResourceUploader.cs b/Riateu/Core/Graphics/ResourceUploader.cs index cf4a93b..e488295 100644 --- a/Riateu/Core/Graphics/ResourceUploader.cs +++ b/Riateu/Core/Graphics/ResourceUploader.cs @@ -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); @@ -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); diff --git a/Riateu/Core/Graphics/SpriteFont.cs b/Riateu/Core/Graphics/SpriteFont.cs index 105ea60..c7ae211 100644 --- a/Riateu/Core/Graphics/SpriteFont.cs +++ b/Riateu/Core/Graphics/SpriteFont.cs @@ -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 text, Vector2 position, Vector2 justify, Color color, Vector2 scale, float layerDepth = 1f) + internal void Draw(Span computeData, ref uint vertexIndex, ReadOnlySpan text, Vector2 position, Vector2 justify, Color color, Vector2 scale, float layerDepth = 1f) { if (text.IsEmpty) return; @@ -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, diff --git a/Riateu/Core/Graphics/TransferBuffer.cs b/Riateu/Core/Graphics/TransferBuffer.cs index 933daf7..7606d90 100644 --- a/Riateu/Core/Graphics/TransferBuffer.cs +++ b/Riateu/Core/Graphics/TransferBuffer.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SDL3; @@ -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) { @@ -29,42 +28,46 @@ public unsafe static TransferBuffer Create(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 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((void*)(mappedPointer + offset), (int)(Size - offset)); } - public unsafe Span Map(bool cycle) + public unsafe Span Map(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(data, (int)Size); + Map(cycle); + return new Span((void*)(mappedPointer + offset), (int)(Size - offset) / Unsafe.SizeOf()); } - public unsafe Span Map(bool cycle) + public unsafe Span MappedTouch(uint offset = 0) { #if DEBUG - AssertNotMapped(); - IsMapped = true; + AssertMapped(); #endif - var data = (byte*)SDL.SDL_MapGPUTransferBuffer(Device.Handle, Handle, cycle); - return new Span(data, (int)Size); + return new Span((void*)(mappedPointer + offset), (int)(Size - offset) / Unsafe.SizeOf()); } public void Unmap() { -#if DEBUG - IsMapped = false; -#endif SDL.SDL_UnmapGPUTransferBuffer(Device.Handle, Handle); + mappedPointer = IntPtr.Zero; } public unsafe uint SetTransferData(Span source, uint bufferOffsetInBytes, bool cycle) @@ -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."); } diff --git a/Riateu/Core/ImGui/ImGuiRenderer.cs b/Riateu/Core/ImGui/ImGuiRenderer.cs index 27cb3ce..717bd8a 100644 --- a/Riateu/Core/ImGui/ImGuiRenderer.cs +++ b/Riateu/Core/ImGui/ImGuiRenderer.cs @@ -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 }); @@ -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)