#[allow(unused_imports)] use log::{debug, error, info, trace, warn}; use std::mem::ManuallyDrop; use crate::renderer::gpu::Gpu; //--Attachement implementation---------------------------------------------------------------------- #[derive(Debug)] pub struct Attachement { buffer: ManuallyDrop, memory: ManuallyDrop, size: u64, } impl Attachement where B: gfx_hal::Backend, { pub fn drop(mut self, gpu: &mut Gpu) { use std::ptr::read; use gfx_hal::device::Device; debug!("Dropping Attachement..."); unsafe { gpu.device() .free_memory(ManuallyDrop::into_inner(read(&mut self.memory))); gpu.device() .destroy_buffer(ManuallyDrop::into_inner(read(&mut self.buffer))); } } pub fn new(gpu: &mut Gpu) -> Result, &'static str> { use std::mem::size_of; use gfx_hal::{ device::Device, adapter::PhysicalDevice, buffer::Usage, }; debug!("Creating attachement..."); let mut buffer = unsafe { gpu.device() .create_buffer((size_of::()*2*3) as u64, Usage::VERTEX) .map_err(|_| "Could not create buffer")? }; trace!("Creating underlying attachement memory..."); let (memory, size) = { use gfx_hal::{ memory::Properties, MemoryTypeId, }; let requirements = unsafe { gpu.device().get_buffer_requirements(&buffer) }; let memory_type = gpu.adapter() .physical_device .memory_properties() .memory_types .iter() .enumerate() .find(|&(id, memory_type)| { requirements.type_mask & (1 << id) != 0 && memory_type.properties.contains(Properties::CPU_VISIBLE)}) .map(|(id, _)| MemoryTypeId(id)) .ok_or("Could not find a suitable memory type to allocate attachement memory")?; ( unsafe { gpu.device() .allocate_memory(memory_type, requirements.size) .map_err(|_| "Could not allocate buffer memory...")? }, requirements.size, )}; trace!("Binding memory to buffer..."); unsafe { gpu.device() .bind_buffer_memory(&memory, 0, &mut buffer) .map_err(|__| "Could not bind memory to buffer")?; } Ok( Attachement { buffer: ManuallyDrop::new(buffer), memory: ManuallyDrop::new(memory), size, }) } pub fn get_buffer(&self) -> &B::Buffer { //manual deref for ManuallyDrop to not cause troubles &self.buffer } pub fn write_buffer(&self, gpu: &Gpu, data: Vec) -> Result<(), &'static str> { use gfx_hal::{ device::Device, memory::Segment, }; trace!("writing data to buffer..."); unsafe { let mapped_memory = gpu.device() .map_memory(&self.memory, Segment::ALL) .map_err(|_| "Could not map buffer memory")?; //debug!("before : {}", std::ptr::read(mapped_memory as *mut f32)); std::ptr::copy_nonoverlapping(data.as_ptr() as *const u8, mapped_memory, self.size as usize); //debug!("after : {}", std::ptr::read(mapped_memory as *mut f32)); //manual deref for ManuallyDrop to not cause troubles let memory_ref: &B::Memory = &self.memory; gpu.device() .flush_mapped_memory_ranges(std::iter::once((memory_ref, Segment::ALL))) .map_err(|_| "Could not flush mapped buffer memory")?; gpu.device().unmap_memory(&self.memory); } Ok(()) } }