diff --git a/aurora/lib/aurora.cpp b/aurora/lib/aurora.cpp index 020ed36fa..fcaf9f907 100644 --- a/aurora/lib/aurora.cpp +++ b/aurora/lib/aurora.cpp @@ -293,6 +293,7 @@ void app_run(std::unique_ptr app, Icon icon, int argc, char** argv) .label = "Redraw encoder", }; auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor); + gfx::end_frame(encoder); { const std::array attachments{ wgpu::RenderPassColorAttachment{ @@ -324,7 +325,7 @@ void app_run(std::unique_ptr app, Icon icon, int argc, char** argv) .depthStencilAttachment = &depthStencilAttachment, }; auto pass = encoder.BeginRenderPass(&renderPassDescriptor); - gfx::end_frame(pass); + gfx::render(pass); pass.End(); } { diff --git a/aurora/lib/gfx/common.cpp b/aurora/lib/gfx/common.cpp index ac9767876..5746b3000 100644 --- a/aurora/lib/gfx/common.cpp +++ b/aurora/lib/gfx/common.cpp @@ -24,6 +24,8 @@ constexpr uint64_t VertexBufferSize = 5242880; // 5mb constexpr uint64_t IndexBufferSize = 2097152; // 2mb constexpr uint64_t StorageBufferSize = 134217728; // 128mb +constexpr uint64_t StagingBufferSize = UniformBufferSize + VertexBufferSize + IndexBufferSize + StorageBufferSize; + struct ShaderState { movie_player::State moviePlayer; colored_quad::State coloredQuad; @@ -209,6 +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 ShaderState g_state; static PipelineRef g_currentPipeline; @@ -389,15 +392,21 @@ void initialize() { const auto createBuffer = [](wgpu::Buffer& out, wgpu::BufferUsage usage, uint64_t size, const char* label) { const wgpu::BufferDescriptor descriptor{ .label = label, - .usage = usage | wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapWrite, + .usage = usage, .size = size, }; out = g_device.CreateBuffer(&descriptor); }; - createBuffer(g_uniformBuffer, wgpu::BufferUsage::Uniform, UniformBufferSize, "Shared Uniform Buffer"); - createBuffer(g_vertexBuffer, wgpu::BufferUsage::Vertex, VertexBufferSize, "Shared Vertex Buffer"); - createBuffer(g_indexBuffer, wgpu::BufferUsage::Index, IndexBufferSize, "Shared Index Buffer"); - createBuffer(g_storageBuffer, wgpu::BufferUsage::Storage, StorageBufferSize, "Shared Storage Buffer"); + createBuffer(g_uniformBuffer, wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst, UniformBufferSize, + "Shared Uniform Buffer"); + createBuffer(g_vertexBuffer, wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst, VertexBufferSize, + "Shared Vertex Buffer"); + createBuffer(g_indexBuffer, wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst, IndexBufferSize, + "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"); g_state.moviePlayer = movie_player::construct_state(); g_state.coloredQuad = colored_quad::construct_state(); @@ -420,61 +429,55 @@ void shutdown() { g_uniformBuffer = {}; g_indexBuffer = {}; g_storageBuffer = {}; + g_stagingBuffer = {}; g_state = {}; } void begin_frame() { - int mappedBuffers = 0, totalBuffers = 0; - const auto mapBuffer = [&](ByteBuffer& buf, wgpu::Buffer& out, uint64_t size) { - struct MapCallbackData { - ByteBuffer& buf; - wgpu::Buffer& out; - uint64_t size; - int& mappedBuffers; - }; - auto* data = new MapCallbackData{ - .buf = buf, - .out = out, - .size = size, - .mappedBuffers = mappedBuffers, - }; - out.MapAsync( - wgpu::MapMode::Write, 0, size, - [](WGPUBufferMapAsyncStatus status, void* userdata) { - if (status != WGPUBufferMapAsyncStatus_Success) { - Log.report(logvisor::Fatal, FMT_STRING("Buffer mapping failed: {}"), status); - unreachable(); - } - auto* data = static_cast(userdata); - data->buf = ByteBuffer{static_cast(data->out.GetMappedRange(0, data->size)), data->size}; - ++data->mappedBuffers; - delete data; - }, - data); - ++totalBuffers; + 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; }; - mapBuffer(g_verts, g_vertexBuffer, VertexBufferSize); - mapBuffer(g_uniforms, g_uniformBuffer, UniformBufferSize); - mapBuffer(g_indices, g_indexBuffer, IndexBufferSize); - mapBuffer(g_storage, g_storageBuffer, StorageBufferSize); - while (mappedBuffers < totalBuffers) { + g_stagingBuffer.MapAsync( + wgpu::MapMode::Write, 0, StagingBufferSize, + [](WGPUBufferMapAsyncStatus status, void* userdata) { + if (status != WGPUBufferMapAsyncStatus_Success) { + Log.report(logvisor::Fatal, FMT_STRING("Buffer mapping failed: {}"), status); + unreachable(); + } + *static_cast(userdata) = true; + }, + &bufferMapped); + while (!bufferMapped) { g_device.Tick(); } + mapBuffer(g_verts, VertexBufferSize); + mapBuffer(g_uniforms, UniformBufferSize); + mapBuffer(g_indices, IndexBufferSize); + mapBuffer(g_storage, StorageBufferSize); } -void end_frame(const wgpu::RenderPassEncoder& pass) { - const auto writeBuffer = [](ByteBuffer& buf, wgpu::Buffer& out, std::string_view label) { - const auto size = buf.size(); - // Log.report(logvisor::Info, FMT_STRING("{} buffer usage: {}"), label, size); - buf.clear(); - out.Unmap(); +void end_frame(const wgpu::CommandEncoder& cmd) { + uint64_t bufferOffset = 0; + 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); + buf.clear(); + } + bufferOffset += size; }; - writeBuffer(g_verts, g_vertexBuffer, "Vertex"); - writeBuffer(g_uniforms, g_uniformBuffer, "Uniform"); - writeBuffer(g_indices, g_indexBuffer, "Index"); - writeBuffer(g_storage, g_storageBuffer, "Storage"); + g_stagingBuffer.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"); +} +void render(const wgpu::RenderPassEncoder& pass) { g_currentPipeline = UINT64_MAX; for (const auto& cmd : g_commands) { diff --git a/aurora/lib/gfx/common.hpp b/aurora/lib/gfx/common.hpp index 0e6323248..c21c6c699 100644 --- a/aurora/lib/gfx/common.hpp +++ b/aurora/lib/gfx/common.hpp @@ -172,7 +172,8 @@ void initialize(); void shutdown(); void begin_frame(); -void end_frame(const wgpu::RenderPassEncoder& pass); +void end_frame(const wgpu::CommandEncoder& cmd); +void render(const wgpu::RenderPassEncoder& pass); Range push_verts(const uint8_t* data, size_t length); template