MCPcopy Create free account
hub / github.com/Bloom-Engine/engine / read_atlas

Function read_atlas

tools/imposter-baker/src/render.rs:384–437  ·  view source on GitHub ↗

Copy texture to a CPU-mappable buffer, handling wgpu's 256-byte row-pitch alignment, and return the unpadded pixel bytes.

(
    device: &wgpu::Device,
    queue: &wgpu::Queue,
    tex: &wgpu::Texture,
    width: u32,
    height: u32,
    bytes_per_pixel: u32,
)

Source from the content-addressed store, hash-verified

382/// Copy texture to a CPU-mappable buffer, handling wgpu's 256-byte
383/// row-pitch alignment, and return the unpadded pixel bytes.
384async fn read_atlas(
385 device: &wgpu::Device,
386 queue: &wgpu::Queue,
387 tex: &wgpu::Texture,
388 width: u32,
389 height: u32,
390 bytes_per_pixel: u32,
391) -> Result<Vec<u8>, String> {
392 let unpadded_bpr = width * bytes_per_pixel;
393 let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
394 let padded_bpr = ((unpadded_bpr + align - 1) / align) * align;
395 let buf_size = (padded_bpr * height) as u64;
396
397 let buf = device.create_buffer(&wgpu::BufferDescriptor {
398 label: Some("readback"),
399 size: buf_size,
400 usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
401 mapped_at_creation: false,
402 });
403
404 let mut enc = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("readback-enc") });
405 enc.copy_texture_to_buffer(
406 wgpu::TexelCopyTextureInfo { texture: tex, mip_level: 0, origin: wgpu::Origin3d::ZERO, aspect: wgpu::TextureAspect::All },
407 wgpu::TexelCopyBufferInfo {
408 buffer: &buf,
409 layout: wgpu::TexelCopyBufferLayout {
410 offset: 0,
411 bytes_per_row: Some(padded_bpr),
412 rows_per_image: Some(height),
413 },
414 },
415 wgpu::Extent3d { width, height, depth_or_array_layers: 1 },
416 );
417 queue.submit(Some(enc.finish()));
418
419 let slice = buf.slice(..);
420 let (tx, rx) = std::sync::mpsc::channel();
421 slice.map_async(wgpu::MapMode::Read, move |r| { let _ = tx.send(r); });
422 let _ = device.poll(wgpu::PollType::Wait { submission_index: None, timeout: None });
423 rx.recv()
424 .map_err(|e| format!("map_async send: {e}"))?
425 .map_err(|e| format!("map_async: {e}"))?;
426
427 let view = slice.get_mapped_range();
428 // Strip per-row padding.
429 let mut out = Vec::with_capacity((unpadded_bpr * height) as usize);
430 for row in 0..height {
431 let src = (row * padded_bpr) as usize;
432 out.extend_from_slice(&view[src..src + unpadded_bpr as usize]);
433 }
434 drop(view);
435 buf.unmap();
436 Ok(out)
437}
438
439// ────────────────────────────────────────────────────────────────────
440// Tiny matrix helpers (column-major, row-vector × matrix multiplication

Callers 1

bake_asyncFunction · 0.85

Calls 1

sliceMethod · 0.80

Tested by

no test coverage detected