fix: no GPU allocation path maps, however small the buffer

The previous commit converted the allocations that scale with the
drawing and deliberately left the small fixed-size ones -- uniforms, the
viewcube's static geometry, per-image and per-wipeout quads -- reasoning
that an allocation failure was not a realistic outcome for a few dozen
bytes.

That reasoning was wrong, and the log says so precisely. On the
reproducer the vertex buffers degraded exactly as intended:

  [gpu] uncaptured ... Out of Memory
  [gpu] uncaptured ... In Queue::write_buffer
          Buffer with 'block_wire.vertices' label is invalid
  ... errors #4 #8 #16 #32 #64 #128, session kept alive

and then the process died here:

  thread 'main' panicked at wgpu_core.rs:2253:
  Error in Buffer::get_mapped_range: Validation Error
  Caused by: Buffer with 'block_wire.const' label is invalid

'block_wire.const' is a single uniform struct. Once the device is out of
memory every allocation fails, including a 32-byte one, and
create_buffer_init maps it and panics. Size was never the relevant
property -- whether the path maps is.

So every remaining allocation goes through gpu_upload too: block-wire
const, the viewcube's seven buffers, the blit and clip-boundary buffers,
image instances/params/vertices, mesh material params and surface and the
empty index stub, the texture-hatch uniform, and all five wipeout
buffers. `grep -r create_buffer_init src` now finds only a comment, and
no mapped_at_creation:true remains outside gpu_upload's own docs.

`queue` is threaded through the last holdouts: upload_wipeouts,
upload_clip_boundary, MeshBatchStubs::new and
create_material_bind_group_from_resources.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
PanosandClaude Opus 5 committed 2026-09-04 16:21:08 +03:00
1 parent 0d11421dea
commit 6747d7125e
8 files changed
+181 -129

No files matched your search

+12 -6
View File
@@ -676,7 +676,6 @@ impl BlockWireGpu {
color_override: Option<[f32; 4]>,
const_bgl: &wgpu::BindGroupLayout,
) -> Vec<Self> {
use wgpu::util::DeviceExt;
let mut slots: rustc_hash::FxHashMap<(u64, bool), usize> =
rustc_hash::FxHashMap::default();
@@ -751,11 +750,18 @@ impl BlockWireGpu {
)
})
.collect();
let const_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("block_wire.const"),
contents: bytemuck::bytes_of(&constant),
usage: wgpu::BufferUsages::UNIFORM,
});
// Tiny, but size is irrelevant here: once the device is out of
// memory every allocation fails, including a one-struct uniform,
// and create_buffer_init would map the invalid buffer and panic.
// This is the allocation that killed the process after the vertex
// buffers had already degraded gracefully.
let const_buffer = super::gpu_upload::upload_buffer(
device,
queue,
"block_wire.const",
std::slice::from_ref(&constant),
wgpu::BufferUsages::UNIFORM,
);
let const_bind_group = std::sync::Arc::new(device.create_bind_group(
&wgpu::BindGroupDescriptor {
label: Some("block_wire.const.bg"),