Learn Wgpu
Home
  • Dependencies and the window
  • The Surface
  • The Pipeline
  • Buffers and Indices
  • Textures and bind groups
  • Uniform buffers and a 3d camera
  • Instancing
  • The Depth Buffer
  • Model Loading
  • Working with Lights
  • Normal Mapping
  • A Better Camera
  • High Dynamic Range Rendering
  • Intro to Compute Pipelines
  • Sorting on the GPU
  • Foreword
  • Mipmapping
  • Stencil Buffers
  • Wgpu without a window
  • Creating gifs
  • Pong
  • Memory Layout in WGSL
  • Update to Wgpu 29.0
  • Update to Vuepress v2
  • Version 28.0 and stencil showcase
  • Update to 27.0!
  • Update to wgpu 26.0.1 and started compute pipeline guide
  • Update to Winit 0.30!
  • Version 25.0!
  • Version 24.0
  • First Major Version! (22.0)
  • Update to 0.18 and HDR tutorial
  • Update to 0.17
  • Update to 0.16
  • Update to 0.15!
  • Update to 0.14!
  • Update to 0.13!
  • Update to 0.12!
  • News (Pre 0.12)
Home
  • Dependencies and the window
  • The Surface
  • The Pipeline
  • Buffers and Indices
  • Textures and bind groups
  • Uniform buffers and a 3d camera
  • Instancing
  • The Depth Buffer
  • Model Loading
  • Working with Lights
  • Normal Mapping
  • A Better Camera
  • High Dynamic Range Rendering
  • Intro to Compute Pipelines
  • Sorting on the GPU
  • Foreword
  • Mipmapping
  • Stencil Buffers
  • Wgpu without a window
  • Creating gifs
  • Pong
  • Memory Layout in WGSL
  • Update to Wgpu 29.0
  • Update to Vuepress v2
  • Version 28.0 and stencil showcase
  • Update to 27.0!
  • Update to wgpu 26.0.1 and started compute pipeline guide
  • Update to Winit 0.30!
  • Version 25.0!
  • Version 24.0
  • First Major Version! (22.0)
  • Update to 0.18 and HDR tutorial
  • Update to 0.17
  • Update to 0.16
  • Update to 0.15!
  • Update to 0.14!
  • Update to 0.13!
  • Update to 0.12!
  • News (Pre 0.12)
  • Update to 0.13!

Update to 0.13!

WGPU Change Log

The change log above contains most of the details about what has changed about WGPU and therefore the tutorial. I will make a special mention about how to use map_async() as that has changed. Previously map_async returned a promise that you had to await before you could access a buffers contents. It now expects a 'static callback that takes the Result of the mapping attempt as a parameter. This means that if we want to save a buffers context to an image instead of doing the following:


{
    let buffer_slice = output_buffer.slice(..);

    let mapping = buffer_slice.map_async(wgpu::MapMode::Read);
    device.poll(wgpu::PollType::wait_indefinitely())?;
    mapping.await.unwrap();

    let data = buffer_slice.get_mapped_range();

    use image::{ImageBuffer, Rgba};
    let buffer =
        ImageBuffer::<Rgba<u8>, _>::from_raw(texture_size, texture_size, data).unwrap();
    buffer.save("image.png").unwrap();
}
output_buffer.unmap();

We would do the following:

{
    let buffer_slice = output_buffer.slice(..);

    let (tx, rx) = futures_intrusive::channel::shared::oneshot_channel();
    buffer_slice.map_async(wgpu::MapMode::Read, move |result| {
        tx.send(result).unwrap();
    });
    device.poll(wgpu::PollType::wait_indefinitely())?;
    rx.receive().await.unwrap().unwrap();

    let data = buffer_slice.get_mapped_range();

    use image::{ImageBuffer, Rgba};
    let buffer =
        ImageBuffer::<Rgba<u8>, _>::from_raw(texture_size, texture_size, data).unwrap();
    buffer.save("image.png").unwrap();

}
output_buffer.unmap();

You can explore the reasoning for the change to map_async in this PR.

Another thing to note is that presentation modes need to match what the surface supports. You can get a list of supported modes from Surface::get_surface_modes().

As always, let me know if I missed anything in the migration process. You can open an issue/submit a PR on the Learn Wgpu repo!

Last Updated: 3/25/26, 3:47 AM
Contributors: Ben Hansen