use super::super::traits::{GpuAllocator, GpuBuffer, GpuAllocError, BufferUsage, MemoryType, GpuAllocStats};
use super::buffer::VulkanBuffer;
use std::sync::Arc;
pub struct VulkanAllocator {
device: Arc<ash::Device>,
physical_device: ash::vk::PhysicalDevice,
memory_properties: ash::vk::PhysicalDeviceMemoryProperties,
stats: GpuAllocStats,
}
impl VulkanAllocator {
pub fn new(device: Arc<ash::Device>, physical_device: ash::vk::PhysicalDevice, instance: &ash::Instance) -> Self {
let memory_properties = unsafe { instance.get_physical_device_memory_properties(physical_device) };
Self {
device,
physical_device,
memory_properties,
stats: GpuAllocStats::default(),
}
}
fn get_memory_heap_size(&self, memory_type: MemoryType) -> u64 {
for (i, mem_type) in self.memory_properties.memory_types.iter().enumerate() {
let properties = mem_type.property_flags;
let matches = match memory_type {
MemoryType::DeviceLocal => properties.contains(ash::vk::MemoryPropertyFlags::DEVICE_LOCAL),
MemoryType::HostVisible => properties.contains(ash::vk::MemoryPropertyFlags::HOST_VISIBLE),
MemoryType::HostCoherent => properties.contains(ash::vk::MemoryPropertyFlags::HOST_COHERENT),
MemoryType::HostCached => properties.contains(ash::vk::MemoryPropertyFlags::HOST_CACHED),
MemoryType::Lazy => properties.contains(ash::vk::MemoryPropertyFlags::LAZILY_ALLOCATED),
};
if matches {
let heap_index = mem_type.heap_index;
return self.memory_properties.memory_heaps[heap_index as usize].size;
}
}
0
}
}
impl GpuAllocator for VulkanAllocator {
fn allocate_buffer(
&mut self,
size: usize,
usage: BufferUsage,
memory_type: MemoryType,
) -> Result<Box<dyn GpuBuffer>, GpuAllocError> {
self.stats.allocation_count += 1;
let buffer = VulkanBuffer::new(
self.device.clone(),
size,
usage,
memory_type,
&self.memory_properties,
)?;
self.stats.allocated_bytes += size;
if self.stats.allocated_bytes > self.stats.peak_usage {
self.stats.peak_usage = self.stats.allocated_bytes;
}
Ok(Box::new(buffer))
}
fn free_buffer(&mut self, _buffer: Box<dyn GpuBuffer>) {
}
fn total_allocated(&self) -> usize {
self.stats.allocated_bytes
}
fn available_memory(&self) -> usize {
self.get_memory_heap_size(MemoryType::DeviceLocal) as usize
}
fn supports_mapping(&self) -> bool {
true }
fn alignment_for(&self, usage: BufferUsage) -> usize {
if usage.bits & (BufferUsage::UNIFORM_BUFFER.bits | BufferUsage::STORAGE_BUFFER.bits) != 0 {
256 } else {
16 }
}
}