mod index;
mod staging;
mod vertex;
#[allow(clippy::wildcard_imports)]
pub(super) use {index::*, staging::*, vertex::*};
use {
anyhow::Result,
ash::vk
};
use super::{
commands::CommandPool,
devices::{Device, PhysicalDevice},
images::Image,
setup::Instance,
VulkanDrop
};
use crate::fatal;
#[derive(Hash)]
pub struct Buffer {
pub raw: vk::Buffer,
pub memory: vk::DeviceMemory
}
impl Buffer {
pub fn new(
instance: &Instance,
physical_device: &PhysicalDevice,
device: &Device,
size: vk::DeviceSize,
usage: vk::BufferUsageFlags,
properties: vk::MemoryPropertyFlags
) -> Result<Self> {
let raw = {
let create_info = vk::BufferCreateInfo::builder()
.size(size)
.usage(usage)
.sharing_mode(vk::SharingMode::EXCLUSIVE);
unsafe { device.raw.create_buffer(&create_info, None) }?
};
let memory = {
let memory_requirements = unsafe { device.raw.get_buffer_memory_requirements(raw) };
let memory_properties = unsafe { instance.raw.get_physical_device_memory_properties(physical_device.raw) };
let memory_type_index = {
let mut found = false;
let mut result = 0;
for i in 0..memory_properties.memory_type_count {
let req = (memory_requirements.memory_type_bits & (1 << i)) != 0;
let mem = (memory_properties.memory_types[i as usize].property_flags & properties) == properties;
if req && mem {
found = true;
result = i;
break;
}
}
if !found {
fatal!("Failed to find a suitable memory type");
}
result
};
let allocate_info = vk::MemoryAllocateInfo::builder()
.allocation_size(memory_requirements.size)
.memory_type_index(memory_type_index);
unsafe { device.raw.allocate_memory(&allocate_info, None) }?
};
unsafe { device.raw.bind_buffer_memory(raw, memory, 0) }?;
Ok(Self { raw, memory })
}
pub fn copy(
device: &Device,
command_pool: &CommandPool,
src_buffer: &Self,
dst_buffer: &Self,
size: vk::DeviceSize
) -> Result<()> {
let command_buffer = command_pool.begin_single_time_commands(device)?;
{
let copy_region = vk::BufferCopy::builder().size(size);
unsafe { device.raw.cmd_copy_buffer(command_buffer, src_buffer.raw, dst_buffer.raw, &[*copy_region]); }
}
command_pool.end_single_time_commands(device, command_buffer)?;
Ok(())
}
#[allow(dead_code)]
pub fn copy_to_image(
&self,
device: &Device,
command_pool: &CommandPool,
image: &Image,
width: u32,
height: u32
) -> Result<()> {
let command_buffer = command_pool.begin_single_time_commands(device)?;
let subresource_range = vk::ImageSubresourceLayers::builder()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.mip_level(0)
.base_array_layer(0)
.layer_count(1)
.build();
let region = vk::BufferImageCopy::builder()
.buffer_offset(0)
.buffer_row_length(0)
.buffer_image_height(0)
.image_subresource(subresource_range)
.image_offset(vk::Offset3D { x: 0, y: 0, z: 0 })
.image_extent(vk::Extent3D { width, height, depth: 1 });
unsafe {
device.raw.cmd_copy_buffer_to_image(
command_buffer,
self.raw,
image.raw,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[*region]
);
}
command_pool.end_single_time_commands(device, command_buffer)?;
Ok(())
}
}
impl VulkanDrop for Buffer {
fn drop(&self, device: &Device) {
unsafe {
device.raw.destroy_buffer(self.raw, None);
device.raw.free_memory(self.memory, None);
}
}
}