-
Notifications
You must be signed in to change notification settings - Fork 0
[Batch 5] Double-buffer upload pipeline #388
Copy link
Copy link
Open
Labels
batch-5Batch 5: Final PushBatch 5: Final PushbugSomething isn't workingSomething isn't workingdocumentationImprovements or additions to documentationImprovements or additions to documentationengineenhancementNew feature or requestNew feature or requestperf/renderingRendering pipeline performanceRendering pipeline performancequestionFurther information is requestedFurther information is requested
Description
Summary
Implement a double-buffered staging + upload pipeline that overlaps mesh uploads with rendering. Chunk mesh data is written to one staging buffer while the GPU reads from the previous frame's buffer, eliminating upload stalls.
Depends on: #384 (dedicated transfer queue + staging ring)
Current State (after #384)
The transfer queue and staging ring exist, but uploads are submitted one-at-a-time and may still cause synchronization points. The main thread submits uploads, waits for completion, then renders. At high chunk throughput (128+ chunks loading simultaneously), upload bandwidth is limited.
Target Architecture
Double-Buffer Strategy
Frame N:
Staging Buffer A: GPU is copying from this → megabuffer (previous frame's uploads)
Staging Buffer B: CPU is writing new mesh data into this
Frame N+1:
Swap: A becomes write target, B becomes GPU read source
GPU copies B → megabuffer while CPU writes A
Upload Pipeline
- Collect: Worker threads produce mesh vertex data
- Stage: Main thread allocates from staging buffer B (current write buffer), copies data
- Submit: End of frame: submit transfer commands for buffer B → megabuffer
- Swap: Next frame: buffer B becomes GPU source, buffer A becomes CPU write target
- Fence: Previous frame's transfer must complete before staging buffer A is reused
Per-Chunk Flow
Worker thread: Build mesh → pending_solid/pending_cutout/pending_fluid arrays
Main thread (beginFrame):
- Check previous frame's transfer fence
- If complete: swap staging buffers, reclaim space
Main thread (update):
- For each pending upload:
- Allocate from current staging buffer
- Copy vertex data
- Record copy command (staging → megabuffer offset)
Main thread (endFrame):
- Submit accumulated transfer commands
- Signal fence
Implementation Plan
Step 1: Double-buffered staging
- Two
StagingRinginstances (or one ring split in half) write_stagingandgpu_stagingpointers, swapped each frame- Frame N writes to
write_staging, GPU reads fromgpu_staging - After swap:
gpu_stagingis the just-written buffer,write_stagingis the just-completed buffer
Step 2: Batch upload submission
- Accumulate multiple chunk uploads per frame
- Single
vkQueueSubmitwith all copy commands batched - One fence per frame (not per chunk)
vkCmdCopyBufferfor each chunk: staging offset → megabuffer offset
Step 3: Integration with WorldStreamer
WorldStreamercurrently hasmax_uploads_per_framelimit- With double-buffer pipeline, this limit can be raised significantly
- Upload queue: FIFO of chunks with completed meshes awaiting upload
- Main thread drains the queue into staging buffer
Step 4: Backpressure
- If staging buffer is >80% full: pause new uploads (backpressure to streamer)
- If GPU is consistently behind on transfers: log warning, reduce upload rate
- Monitor: show staging buffer utilization in debug overlay
Files to Modify
src/engine/graphics/vulkan/transfer_queue.zig— double-buffer logicsrc/world/world_streamer.zig— upload queue integrationsrc/world/chunk_mesh.zig— pending upload handlingsrc/engine/ui/timing_overlay.zig— staging buffer utilization stat
Testing
- No frame stalls during heavy chunk streaming (128+ chunks)
- Upload throughput scales with available staging buffer size
- Backpressure prevents staging overflow
- All chunk passes (solid/cutout/fluid) upload correctly
- LOD mesh uploads use same pipeline
- Timing overlay shows upload metrics
Roadmap: docs/PERFORMANCE_ROADMAP.md — Batch 5, Issue 3B-2
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
batch-5Batch 5: Final PushBatch 5: Final PushbugSomething isn't workingSomething isn't workingdocumentationImprovements or additions to documentationImprovements or additions to documentationengineenhancementNew feature or requestNew feature or requestperf/renderingRendering pipeline performanceRendering pipeline performancequestionFurther information is requestedFurther information is requested