use {
crate::{
graphics::vulkan::{raii, Allocator, Block},
trace,
},
anyhow::{Context, Result},
ash::vk,
std::sync::Arc,
};
#[derive(Debug)]
pub struct OwnedBlock {
block: Block,
allocator: Arc<Allocator>,
}
impl OwnedBlock {
pub fn allocate_image(
allocator: Arc<Allocator>,
image_create_info: &vk::ImageCreateInfo,
flags: vk::MemoryPropertyFlags,
) -> Result<(Self, raii::Image)> {
let image = raii::Image::new(
allocator.logical_device.clone(),
image_create_info,
)
.with_context(trace!("Unable to create image!"))?;
let (requirements, dedicated) = {
let mut dedicated = vk::MemoryDedicatedRequirements::default();
let requirements = unsafe {
let mut out = vk::MemoryRequirements2::default()
.push_next(&mut dedicated);
allocator.logical_device.get_image_memory_requirements2(
&vk::ImageMemoryRequirementsInfo2 {
image: image.raw,
..Default::default()
},
&mut out,
);
out.memory_requirements
};
(
requirements,
dedicated.prefers_dedicated_allocation == vk::TRUE
|| dedicated.requires_dedicated_allocation == vk::TRUE,
)
};
let block = allocator
.allocate_memory(&requirements, flags, dedicated)
.with_context(trace!("Unable to allocate memory for image!"))?;
unsafe {
allocator
.logical_device
.bind_image_memory(image.raw, block.memory(), block.offset())
.with_context(trace!("Unable to bind image memory!"))?;
};
Ok((Self { block, allocator }, image))
}
pub fn allocate_buffer(
allocator: Arc<Allocator>,
buffer_create_info: &vk::BufferCreateInfo,
flags: vk::MemoryPropertyFlags,
) -> Result<(OwnedBlock, raii::Buffer)> {
let buffer = raii::Buffer::new(
allocator.logical_device.clone(),
buffer_create_info,
)
.with_context(trace!("Unable to create buffer!"))?;
let (requirements, dedicated) = {
let mut dedicated = vk::MemoryDedicatedRequirements::default();
let requirements = unsafe {
let mut out = vk::MemoryRequirements2::default()
.push_next(&mut dedicated);
allocator.logical_device.get_buffer_memory_requirements2(
&vk::BufferMemoryRequirementsInfo2 {
buffer: buffer.raw,
..Default::default()
},
&mut out,
);
out.memory_requirements
};
(
requirements,
dedicated.prefers_dedicated_allocation == vk::TRUE
|| dedicated.requires_dedicated_allocation == vk::TRUE,
)
};
let block = allocator
.allocate_memory(&requirements, flags, dedicated)
.with_context(trace!("Unable to allocate memory for buffer!"))?;
unsafe {
allocator
.logical_device
.bind_buffer_memory(buffer.raw, block.memory(), block.offset())
.with_context(trace!("Unable to bind buffer to memory!"))?;
};
Ok((Self { block, allocator }, buffer))
}
}
impl std::ops::Deref for OwnedBlock {
type Target = Block;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl Drop for OwnedBlock {
fn drop(&mut self) {
self.allocator.free(&self.block);
}
}