hexga_wgpu 0.0.11-beta.53

wgpu wrapped for hexga
Documentation
use super::*;

#[derive(Clone, Debug, PartialEq, Hash)]
pub struct GpuVec<T>
{
    pub(crate) buffer: GpuBuffer<T>,
    pub(crate) len: usize,
    pub(crate) desc: GpuBufferDesc,
}
impl<T> GpuVec<T>
where
    T: BitAllUsed,
{
    pub fn update_part(&mut self, offset: usize, data: &[T])
    {
        self.try_update_part(offset, data)
            .expect("failed to update the gpu vec");
    }
    pub fn try_update_part(&mut self, offset: usize, data: &[T]) -> Result<(), ()>
    where
        T: BitAllUsed,
    {
        let elem_size = std::mem::size_of::<T>().max(1);
        let required_len = offset.checked_add(data.len()).ok_or(())?;

        if required_len > self.capacity()
        {
            let new_capacity = required_len.next_power_of_two();
            let new_byte_size = (new_capacity * elem_size) as wgpu::BufferAddress;

            let new_buffer = Gpu.wgpu.device.create_buffer(&wgpu::BufferDescriptor {
                label: None,
                size: new_byte_size,
                usage: self.desc.usages.into(),
                mapped_at_creation: false,
            });

            if self.len > 0
            {
                if !self.desc.usages.contains(BufferUsageFlags::CopySrc)
                    || !self.desc.usages.contains(BufferUsageFlags::CopyDst)
                {
                    return Err(());
                }

                let copy_byte_len = (self.len * elem_size) as wgpu::BufferAddress;

                let mut encoder = Gpu
                    .wgpu
                    .device
                    .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });

                encoder.copy_buffer_to_buffer(&self.buffer.wgpu, 0, &new_buffer, 0, copy_byte_len);

                Gpu.wgpu.queue.submit(Some(encoder.finish()));
            }

            self.buffer.wgpu = new_buffer;
        }

        let write_byte_offset = (offset * elem_size) as wgpu::BufferAddress;

        let write_bytes = bit::try_transmute_slice(data).map_err(|e| ())?;

        Gpu.wgpu
            .queue
            .write_buffer(&self.buffer.wgpu, write_byte_offset, write_bytes);

        if required_len > self.len
        {
            self.len = required_len;
        }

        Ok(())
    }
}

impl<T> Clear for GpuVec<T>
{
    fn clear(&mut self) { self.len = 0; }
}

pub trait ToGpuVec<T>
where
    T: BitAllUsed,
{
    fn to_gpu_vec(self, desc: GpuBufferDesc) -> GpuVec<T>;
}
impl<T> ToGpuVec<T> for &[T]
where
    T: BitAllUsed,
{
    fn to_gpu_vec(self, desc: GpuBufferDesc) -> GpuVec<T> { GpuVec::new(self, desc) }
}

impl<T> GpuBufferNew<T> for GpuVec<T>
where
    GpuBuffer<T>: GpuBufferNew<T>,
{
    fn new(value: &[T], desc: GpuBufferDesc) -> Self
    {
        let len = value.len();
        Self {
            buffer: GpuBuffer::new(value, desc),
            len,
            desc,
        }
    }

    fn with_capacity(capacity: usize, desc: GpuBufferDesc) -> Self
    {
        Self {
            buffer: GpuBuffer::with_capacity(capacity, desc),
            len: capacity,
            desc,
        }
    }
}
impl<T> GpuBufferByte for GpuVec<T>
where
    GpuBuffer<T>: GpuBufferByte,
{
    fn wgpu_bytes_len(&self) -> GpuBufferAddress
    {
        (self.len * std::mem::size_of::<T>()) as GpuBufferAddress
    }
    fn wgpu_bytes_capacity(&self) -> GpuBufferAddress { self.buffer.wgpu_bytes_capacity() }
}
impl<T> GpuAsUntypedSlice for GpuVec<T>
where
    GpuBuffer<T>: GpuBufferByte,
{
    fn untyped_slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuUntypedSlice<'_>
    {
        self.buffer.untyped_slice(bounds)
    }
    fn try_untyped_update<T2>(&mut self, values: &[T2]) -> Result<(), ()>
    where
        T2: BitAllUsed,
    {
        self.buffer.try_untyped_update(values)
    }
}
impl<T> GpuBufferRead<T> for GpuVec<T>
where
    wgpu::Buffer: GpuBufferRead<T>,
{
    fn read_in(&self, vec: &mut Vec<T>) -> GpuResult
    where
        T: BitZero + BitPattern,
    {
        self.buffer.read_in(vec)
    }

    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T>
    {
        self.buffer.slice(bounds)
    }
    fn try_update(&mut self, values: &[T]) -> Result<(), ()>
    where
        T: BitAllUsed,
    {
        self.try_update_part(0, values)
    }
}