use crate::prelude::*; use anyhow::Result; use vma_rs::prelude::*; use std::marker::PhantomData; use std::sync::Arc; #[derive(Debug, Clone, PartialEq, Hash, Eq)] pub enum MemoryUsage { GpuOnly, CpuOnly, CpuToGpu, GpuToCpu, } impl MemoryUsage { pub fn into_vma(usage: Option) -> VmaMemoryUsage { match usage { Some(usage) => usage.into(), None => VMA_MEMORY_USAGE_UNKNOWN, } } } impl Into for MemoryUsage { fn into(self) -> VmaMemoryUsage { match self { Self::GpuOnly => VMA_MEMORY_USAGE_GPU_ONLY, Self::CpuOnly => VMA_MEMORY_USAGE_CPU_ONLY, Self::CpuToGpu => VMA_MEMORY_USAGE_CPU_TO_GPU, Self::GpuToCpu => VMA_MEMORY_USAGE_GPU_TO_CPU, } } } #[derive(Debug)] pub struct Memory { device: Arc, allocation: Allocation, data_type: PhantomData, } impl Memory { pub(crate) fn forced_requirements( device: &Arc, memory_requirements: VkMemoryRequirements, buffer: VkBuffer, memory_usage: VmaMemoryUsage, ) -> Result>> { let mut memory = Self::create_and_bind(device, memory_requirements, memory_usage, ())?; if let Some(mut_memory) = Arc::get_mut(&mut memory) { mut_memory.allocation.bind_buffer_memory(buffer)?; } Ok(memory) } pub(crate) fn buffer_memory( device: &Arc, buffer: VkBuffer, memory_usage: VmaMemoryUsage, ) -> Result>> { let memory_requirements = device.buffer_memory_requirements(buffer); Self::create_and_bind(device, memory_requirements, memory_usage, buffer) } pub(crate) fn image_memory( device: &Arc, image: VkImage, memory_usage: VmaMemoryUsage, ) -> Result>> { let memory_requirements = device.image_memory_requirements(image); Self::create_and_bind(device, memory_requirements, memory_usage, image) } pub(crate) fn vk_handle(&self) -> VkDeviceMemory { self.allocation.device_memory() } } trait MemoryBinder { fn create_and_bind( device: &Arc, memory_requirements: VkMemoryRequirements, memory_usage: VmaMemoryUsage, argument: T, ) -> Result>>; } impl MemoryBinder<(), K> for Memory { fn create_and_bind( device: &Arc, memory_requirements: VkMemoryRequirements, memory_usage: VmaMemoryUsage, _: (), ) -> Result>> { let allocation = device .allocator() .allocate() .set_usage(memory_usage) .set_memory_type_bits(memory_requirements.memoryTypeBits.into()) .build(&memory_requirements)?; Ok(Arc::new(Memory { device: device.clone(), allocation, data_type: PhantomData, })) } } impl MemoryBinder for Memory { fn create_and_bind( device: &Arc, memory_requirements: VkMemoryRequirements, memory_usage: VmaMemoryUsage, image: VkImage, ) -> Result>> { let allocation = device .allocator() .allocate() .set_usage(memory_usage) .set_memory_type_bits(memory_requirements.memoryTypeBits.into()) .build(image)?; Ok(Arc::new(Memory { device: device.clone(), allocation, data_type: PhantomData, })) } } impl MemoryBinder for Memory { fn create_and_bind( device: &Arc, memory_requirements: VkMemoryRequirements, memory_usage: VmaMemoryUsage, buffer: VkBuffer, ) -> Result>> { let allocation = device .allocator() .allocate() .set_usage(memory_usage) .set_memory_type_bits(memory_requirements.memoryTypeBits.into()) .build(buffer)?; Ok(Arc::new(Memory { device: device.clone(), allocation, data_type: PhantomData, })) } } impl VulkanDevice for Memory { fn device(&self) -> &Arc { &self.device } } impl Memory { pub fn map(&self, length: VkDeviceSize) -> Result> { self.allocation.map(length) } }