nexg 0.1.1

Nexg is a pure-rust library that makes coding Vulkan functionality easier and more Rust-like.
Documentation
use crate::mem::DeviceMemory;
use crate::{Destroy, Device, DeviceConnecter, Instance, NxError, NxResult};
use ash::vk::{BufferCreateInfo, BufferUsageFlags, MappedMemoryRange, MemoryMapFlags, SharingMode};
use std::ffi::c_void;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BufferUsage {
    Vertex,
    Index,
    Uniform,
}

impl From<BufferUsage> for BufferUsageFlags {
    fn from(value: BufferUsage) -> Self {
        match value {
            BufferUsage::Vertex => BufferUsageFlags::VERTEX_BUFFER,
            BufferUsage::Index => BufferUsageFlags::INDEX_BUFFER,
            BufferUsage::Uniform => BufferUsageFlags::UNIFORM_BUFFER,
        }
    }
}

pub struct BufferDescriptor {
    size: usize,
    usage: BufferUsage,
}

impl BufferDescriptor {
    pub fn empty() -> Self {
        Self {
            size: 0,
            usage: BufferUsage::Vertex,
        }
    }

    pub fn size(mut self, size: usize) -> Self {
        self.size = size;
        self
    }

    pub fn usage(mut self, usage: BufferUsage) -> Self {
        self.usage = usage;
        self
    }
}

pub struct Buffer {
    pub(crate) buffer: ash::vk::Buffer,
    memory: DeviceMemory,
    size: usize,
}

impl Buffer {
    pub fn new(
        instance: &Instance,
        connecter: DeviceConnecter,
        device: &Device,
        descriptor: &BufferDescriptor,
    ) -> NxResult<Self> {
        let create_info = BufferCreateInfo::builder()
            .size(descriptor.size as u64)
            .usage(descriptor.usage.into())
            .sharing_mode(SharingMode::EXCLUSIVE)
            .build();
        let buffer = unsafe { device.device.create_buffer(&create_info, None) }.unwrap();
        let mem_props = connecter.get_memory_properties(instance);
        let mem_req = unsafe { device.device.get_buffer_memory_requirements(buffer) };
        let memory =
            match DeviceMemory::alloc_buffer_memory(&device.device, buffer, mem_props, mem_req) {
                Ok(x) => x,
                Err(e) => return Err(e),
            };

        Ok(Self {
            buffer,
            memory,
            size: descriptor.size,
        })
    }

    pub fn size(&self, device: &Device) -> u64 {
        self.memory.size(device)
    }

    pub fn write(&self, device: &Device, data: *const c_void) -> NxResult<()> {
        let mapped_memory = match unsafe {
            device.device.map_memory(
                self.memory.memory,
                0,
                self.size as u64,
                MemoryMapFlags::empty(),
            )
        } {
            Ok(x) => x,
            Err(e) => match e {
                ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => Err(NxError::OutOfDeviceMemory),
                ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => Err(NxError::OutOfHostMemory),
                ash::vk::Result::ERROR_MEMORY_MAP_FAILED => Err(NxError::MemoryMapFailed),
                _ => Err(NxError::Unknown),
            }?,
        };

        mem_copy(mapped_memory, data, self.size);
        let flush_memory_range = MappedMemoryRange::builder()
            .memory(self.memory.memory)
            .offset(0)
            .size(self.size as u64)
            .build();
        unsafe {
            device
                .device
                .flush_mapped_memory_ranges(&[flush_memory_range])
                .unwrap();
        }

        Ok(())
    }

    pub fn lock(&self, device: &Device) {
        unsafe {
            device.device.unmap_memory(self.memory.memory);
        }
    }
}

impl Destroy for Buffer {
    fn instance(&self, _: &Instance) {}

    fn device(&self, device: &Device) {
        unsafe {
            device.device.destroy_buffer(self.buffer, None);
            device.destroy(&self.memory);
        }
    }
}

pub(crate) fn mem_copy<T>(dst: *mut T, src: *const T, count: usize) {
    unsafe {
        std::ptr::copy_nonoverlapping(src, dst, count);
    }
}