aurora: Use staging buffer for mapping

This commit is contained in:
Luke Street 2022-03-15 23:04:43 -04:00
parent efd14dcaf2
commit c01152e23a
3 changed files with 55 additions and 50 deletions

View File

@ -293,6 +293,7 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
.label = "Redraw encoder", .label = "Redraw encoder",
}; };
auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor); auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor);
gfx::end_frame(encoder);
{ {
const std::array attachments{ const std::array attachments{
wgpu::RenderPassColorAttachment{ wgpu::RenderPassColorAttachment{
@ -324,7 +325,7 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
.depthStencilAttachment = &depthStencilAttachment, .depthStencilAttachment = &depthStencilAttachment,
}; };
auto pass = encoder.BeginRenderPass(&renderPassDescriptor); auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
gfx::end_frame(pass); gfx::render(pass);
pass.End(); pass.End();
} }
{ {

View File

@ -24,6 +24,8 @@ constexpr uint64_t VertexBufferSize = 5242880; // 5mb
constexpr uint64_t IndexBufferSize = 2097152; // 2mb constexpr uint64_t IndexBufferSize = 2097152; // 2mb
constexpr uint64_t StorageBufferSize = 134217728; // 128mb constexpr uint64_t StorageBufferSize = 134217728; // 128mb
constexpr uint64_t StagingBufferSize = UniformBufferSize + VertexBufferSize + IndexBufferSize + StorageBufferSize;
struct ShaderState { struct ShaderState {
movie_player::State moviePlayer; movie_player::State moviePlayer;
colored_quad::State coloredQuad; colored_quad::State coloredQuad;
@ -209,6 +211,7 @@ wgpu::Buffer g_uniformBuffer;
wgpu::Buffer g_indexBuffer; wgpu::Buffer g_indexBuffer;
wgpu::Buffer g_storageBuffer; wgpu::Buffer g_storageBuffer;
size_t g_staticStorageLastSize = 0; size_t g_staticStorageLastSize = 0;
static wgpu::Buffer g_stagingBuffer;
static ShaderState g_state; static ShaderState g_state;
static PipelineRef g_currentPipeline; 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 auto createBuffer = [](wgpu::Buffer& out, wgpu::BufferUsage usage, uint64_t size, const char* label) {
const wgpu::BufferDescriptor descriptor{ const wgpu::BufferDescriptor descriptor{
.label = label, .label = label,
.usage = usage | wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapWrite, .usage = usage,
.size = size, .size = size,
}; };
out = g_device.CreateBuffer(&descriptor); out = g_device.CreateBuffer(&descriptor);
}; };
createBuffer(g_uniformBuffer, wgpu::BufferUsage::Uniform, UniformBufferSize, "Shared Uniform Buffer"); createBuffer(g_uniformBuffer, wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst, UniformBufferSize,
createBuffer(g_vertexBuffer, wgpu::BufferUsage::Vertex, VertexBufferSize, "Shared Vertex Buffer"); "Shared Uniform Buffer");
createBuffer(g_indexBuffer, wgpu::BufferUsage::Index, IndexBufferSize, "Shared Index Buffer"); createBuffer(g_vertexBuffer, wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst, VertexBufferSize,
createBuffer(g_storageBuffer, wgpu::BufferUsage::Storage, StorageBufferSize, "Shared Storage Buffer"); "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.moviePlayer = movie_player::construct_state();
g_state.coloredQuad = colored_quad::construct_state(); g_state.coloredQuad = colored_quad::construct_state();
@ -420,61 +429,55 @@ void shutdown() {
g_uniformBuffer = {}; g_uniformBuffer = {};
g_indexBuffer = {}; g_indexBuffer = {};
g_storageBuffer = {}; g_storageBuffer = {};
g_stagingBuffer = {};
g_state = {}; g_state = {};
} }
void begin_frame() { void begin_frame() {
int mappedBuffers = 0, totalBuffers = 0; bool bufferMapped = false;
const auto mapBuffer = [&](ByteBuffer& buf, wgpu::Buffer& out, uint64_t size) { size_t bufferOffset = 0;
struct MapCallbackData { const auto mapBuffer = [&](ByteBuffer& buf, uint64_t size) {
ByteBuffer& buf; buf = ByteBuffer{static_cast<u8*>(g_stagingBuffer.GetMappedRange(bufferOffset, size)), size};
wgpu::Buffer& out; bufferOffset += size;
uint64_t size;
int& mappedBuffers;
}; };
auto* data = new MapCallbackData{ g_stagingBuffer.MapAsync(
.buf = buf, wgpu::MapMode::Write, 0, StagingBufferSize,
.out = out,
.size = size,
.mappedBuffers = mappedBuffers,
};
out.MapAsync(
wgpu::MapMode::Write, 0, size,
[](WGPUBufferMapAsyncStatus status, void* userdata) { [](WGPUBufferMapAsyncStatus status, void* userdata) {
if (status != WGPUBufferMapAsyncStatus_Success) { if (status != WGPUBufferMapAsyncStatus_Success) {
Log.report(logvisor::Fatal, FMT_STRING("Buffer mapping failed: {}"), status); Log.report(logvisor::Fatal, FMT_STRING("Buffer mapping failed: {}"), status);
unreachable(); unreachable();
} }
auto* data = static_cast<MapCallbackData*>(userdata); *static_cast<bool*>(userdata) = true;
data->buf = ByteBuffer{static_cast<uint8_t*>(data->out.GetMappedRange(0, data->size)), data->size};
++data->mappedBuffers;
delete data;
}, },
data); &bufferMapped);
++totalBuffers; while (!bufferMapped) {
};
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_device.Tick(); 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) { void end_frame(const wgpu::CommandEncoder& cmd) {
const auto writeBuffer = [](ByteBuffer& buf, wgpu::Buffer& out, std::string_view label) { uint64_t bufferOffset = 0;
const auto size = buf.size(); const auto writeBuffer = [&](ByteBuffer& buf, wgpu::Buffer& out, uint64_t size, std::string_view label) {
// Log.report(logvisor::Info, FMT_STRING("{} buffer usage: {}"), label, size); 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(); buf.clear();
out.Unmap(); }
bufferOffset += size;
}; };
writeBuffer(g_verts, g_vertexBuffer, "Vertex"); g_stagingBuffer.Unmap();
writeBuffer(g_uniforms, g_uniformBuffer, "Uniform"); writeBuffer(g_verts, g_vertexBuffer, VertexBufferSize, "Vertex");
writeBuffer(g_indices, g_indexBuffer, "Index"); writeBuffer(g_uniforms, g_uniformBuffer, UniformBufferSize, "Uniform");
writeBuffer(g_storage, g_storageBuffer, "Storage"); writeBuffer(g_indices, g_indexBuffer, IndexBufferSize, "Index");
writeBuffer(g_storage, g_storageBuffer, StorageBufferSize, "Storage");
}
void render(const wgpu::RenderPassEncoder& pass) {
g_currentPipeline = UINT64_MAX; g_currentPipeline = UINT64_MAX;
for (const auto& cmd : g_commands) { for (const auto& cmd : g_commands) {

View File

@ -172,7 +172,8 @@ void initialize();
void shutdown(); void shutdown();
void begin_frame(); 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); Range push_verts(const uint8_t* data, size_t length);
template <typename T> template <typename T>