From 788f57cb52aa9b4e22ccf7786d036657797afaf0 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 16 Mar 2022 02:05:56 -0400 Subject: [PATCH] aurora: Use multiple staging buffers & map at end of frame --- aurora/lib/gfx/common.cpp | 43 +++++++++++++++++++++++++-------------- aurora/lib/gfx/common.hpp | 1 + 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/aurora/lib/gfx/common.cpp b/aurora/lib/gfx/common.cpp index 5746b3000..3ccdee423 100644 --- a/aurora/lib/gfx/common.cpp +++ b/aurora/lib/gfx/common.cpp @@ -211,7 +211,7 @@ wgpu::Buffer g_uniformBuffer; wgpu::Buffer g_indexBuffer; wgpu::Buffer g_storageBuffer; size_t g_staticStorageLastSize = 0; -static wgpu::Buffer g_stagingBuffer; +static std::array g_stagingBuffers; static ShaderState g_state; static PipelineRef g_currentPipeline; @@ -405,8 +405,11 @@ void initialize() { "Shared Index Buffer"); createBuffer(g_storageBuffer, wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst, StorageBufferSize, "Shared Storage Buffer"); - createBuffer(g_stagingBuffer, wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, StagingBufferSize, - "Staging Buffer"); + createBuffer(g_stagingBuffers[0], wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, StagingBufferSize, + "Staging Buffer 1"); + createBuffer(g_stagingBuffers[1], wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, StagingBufferSize, + "Staging Buffer 2"); + map_staging_buffer(); g_state.moviePlayer = movie_player::construct_state(); g_state.coloredQuad = colored_quad::construct_state(); @@ -429,31 +432,39 @@ void shutdown() { g_uniformBuffer = {}; g_indexBuffer = {}; g_storageBuffer = {}; - g_stagingBuffer = {}; + g_stagingBuffers.fill({}); g_state = {}; } -void begin_frame() { - bool bufferMapped = false; - size_t bufferOffset = 0; - const auto mapBuffer = [&](ByteBuffer& buf, uint64_t size) { - buf = ByteBuffer{static_cast(g_stagingBuffer.GetMappedRange(bufferOffset, size)), size}; - bufferOffset += size; - }; - g_stagingBuffer.MapAsync( +static size_t currentStagingBuffer = 0; +static bool bufferMapped = false; +void map_staging_buffer() { + bufferMapped = false; + g_stagingBuffers[currentStagingBuffer].MapAsync( wgpu::MapMode::Write, 0, StagingBufferSize, [](WGPUBufferMapAsyncStatus status, void* userdata) { - if (status != WGPUBufferMapAsyncStatus_Success) { + if (status == WGPUBufferMapAsyncStatus_DestroyedBeforeCallback) { + return; + } else if (status != WGPUBufferMapAsyncStatus_Success) { Log.report(logvisor::Fatal, FMT_STRING("Buffer mapping failed: {}"), status); unreachable(); } *static_cast(userdata) = true; }, &bufferMapped); +} + +void begin_frame() { while (!bufferMapped) { g_device.Tick(); } + size_t bufferOffset = 0; + auto& stagingBuf = g_stagingBuffers[currentStagingBuffer]; + const auto mapBuffer = [&](ByteBuffer& buf, uint64_t size) { + buf = ByteBuffer{static_cast(stagingBuf.GetMappedRange(bufferOffset, size)), size}; + bufferOffset += size; + }; mapBuffer(g_verts, VertexBufferSize); mapBuffer(g_uniforms, UniformBufferSize); mapBuffer(g_indices, IndexBufferSize); @@ -465,16 +476,18 @@ void end_frame(const wgpu::CommandEncoder& cmd) { const auto writeBuffer = [&](ByteBuffer& buf, wgpu::Buffer& out, uint64_t size, std::string_view label) { const auto writeSize = buf.size(); // Only need to copy this many bytes if (writeSize > 0) { - cmd.CopyBufferToBuffer(g_stagingBuffer, bufferOffset, out, 0, writeSize); + cmd.CopyBufferToBuffer(g_stagingBuffers[currentStagingBuffer], bufferOffset, out, 0, writeSize); buf.clear(); } bufferOffset += size; }; - g_stagingBuffer.Unmap(); + g_stagingBuffers[currentStagingBuffer].Unmap(); writeBuffer(g_verts, g_vertexBuffer, VertexBufferSize, "Vertex"); writeBuffer(g_uniforms, g_uniformBuffer, UniformBufferSize, "Uniform"); writeBuffer(g_indices, g_indexBuffer, IndexBufferSize, "Index"); writeBuffer(g_storage, g_storageBuffer, StorageBufferSize, "Storage"); + currentStagingBuffer = (currentStagingBuffer + 1) % g_stagingBuffers.size(); + map_staging_buffer(); } void render(const wgpu::RenderPassEncoder& pass) { diff --git a/aurora/lib/gfx/common.hpp b/aurora/lib/gfx/common.hpp index c21c6c699..e990ed0d2 100644 --- a/aurora/lib/gfx/common.hpp +++ b/aurora/lib/gfx/common.hpp @@ -174,6 +174,7 @@ void shutdown(); void begin_frame(); void end_frame(const wgpu::CommandEncoder& cmd); void render(const wgpu::RenderPassEncoder& pass); +void map_staging_buffer(); Range push_verts(const uint8_t* data, size_t length); template