wgpu_canvas 5.0.5

A 2D WGPU renderer API for drawing text, shapes, and images with Rust.
Documentation
use wgpu::{COPY_BUFFER_ALIGNMENT, BufferDescriptor, BufferAddress, BufferUsages, Buffer, Device, Queue,};

pub struct DynamicBufferDescriptor<'a> {
    pub label: Option<&'a str>,
    pub usage: BufferUsages,
}

pub struct DynamicBuffer {
    buffer: Buffer,
    size: BufferAddress,
    label: Option<String>
}

impl DynamicBuffer {
    pub fn new(device: &Device, descriptor: &DynamicBufferDescriptor) -> Self {
        let size = 4096;
        DynamicBuffer{
            buffer: device.create_buffer(&BufferDescriptor{
                label: descriptor.label,
                size,
                usage: descriptor.usage,
                mapped_at_creation: false
            }),
            size,
            label: descriptor.label.map(|s| s.to_string())
        }
    }

    pub fn write_buffer(&mut self, device: &Device, queue: &Queue, contents: &[u8]) {
        let pad: usize = contents.len() % 4;
        let contents = if pad != 0 {
            &[contents, &vec![0u8; pad]].concat()
        } else {contents};

        if self.size >= contents.len() as u64 {
            queue.write_buffer(&self.buffer, 0, contents);
        } else {
            let size = Self::next_copy_buffer_size(contents.len() as u64);
            self.buffer = device.create_buffer(&BufferDescriptor {
                label: self.label.as_deref(),
                size,
                usage: self.buffer.usage(),
                mapped_at_creation: true,
            });
            self.buffer.slice(..).get_mapped_range_mut()[..contents.len()].copy_from_slice(contents);
            self.buffer.unmap();
            self.size = size;
        }
    }

    fn next_copy_buffer_size(size: u64) -> u64 {
        let align_mask = COPY_BUFFER_ALIGNMENT - 1;
        ((size.next_power_of_two() + align_mask) & !align_mask).max(COPY_BUFFER_ALIGNMENT)
    }
}

impl AsRef<Buffer> for DynamicBuffer {
    fn as_ref(&self) -> &Buffer {
        &self.buffer
    }
}