1
0
Fork 0
forked from wry/wry

vulkan: only use coherency functions for non-coherent memory

This commit is contained in:
Julian Orth 2024-09-06 19:47:34 +02:00
parent 1f169a0d7b
commit fe8238421f
2 changed files with 20 additions and 11 deletions

View file

@ -4,7 +4,7 @@ use {
utils::{numcell::NumCell, ptr_ext::MutPtrExt}, utils::{numcell::NumCell, ptr_ext::MutPtrExt},
}, },
ash::vk::{DeviceMemory, DeviceSize, MemoryRequirements}, ash::vk::{DeviceMemory, DeviceSize, MemoryRequirements},
gpu_alloc::{Config, GpuAllocator, MemoryBlock, Request, UsageFlags}, gpu_alloc::{Config, GpuAllocator, MemoryBlock, MemoryPropertyFlags, Request, UsageFlags},
gpu_alloc_ash::AshMemoryDevice, gpu_alloc_ash::AshMemoryDevice,
std::{ std::{
cell::{Cell, UnsafeCell}, cell::{Cell, UnsafeCell},
@ -25,6 +25,7 @@ pub struct VulkanAllocation {
pub(super) offset: DeviceSize, pub(super) offset: DeviceSize,
pub(super) mem: Option<*mut u8>, pub(super) mem: Option<*mut u8>,
pub(super) size: DeviceSize, pub(super) size: DeviceSize,
pub(super) coherency_mask: Option<u64>,
block: Cell<Option<MemoryBlock<DeviceMemory>>>, block: Cell<Option<MemoryBlock<DeviceMemory>>>,
} }
@ -111,6 +112,10 @@ impl VulkanAllocator {
offset: block.offset(), offset: block.offset(),
mem: ptr, mem: ptr,
size: block.size(), size: block.size(),
coherency_mask: match block.props().contains(MemoryPropertyFlags::HOST_COHERENT) {
true => None,
false => Some(self.non_coherent_atom_mask),
},
block: Cell::new(Some(block)), block: Cell::new(Some(block)),
}) })
} }

View file

@ -72,27 +72,31 @@ impl VulkanStagingBuffer {
F: FnOnce(*mut u8, usize) -> T, F: FnOnce(*mut u8, usize) -> T,
{ {
let t = f(self.allocation.mem.unwrap(), self.size as usize); let t = f(self.allocation.mem.unwrap(), self.size as usize);
let range = self.range(); if let Some(mask) = self.allocation.coherency_mask {
let res = unsafe { self.device.device.flush_mapped_memory_ranges(&[range]) }; let range = self.incoherent_range(mask);
res.map_err(VulkanError::FlushMemory).map(|_| t) let res = unsafe { self.device.device.flush_mapped_memory_ranges(&[range]) };
res.map_err(VulkanError::FlushMemory)?;
}
Ok(t)
} }
pub fn download<T, F>(&self, f: F) -> Result<T, VulkanError> pub fn download<T, F>(&self, f: F) -> Result<T, VulkanError>
where where
F: FnOnce(*const u8, usize) -> T, F: FnOnce(*const u8, usize) -> T,
{ {
let range = self.range(); if let Some(mask) = self.allocation.coherency_mask {
let res = unsafe { self.device.device.invalidate_mapped_memory_ranges(&[range]) }; let range = self.incoherent_range(mask);
res.map_err(VulkanError::FlushMemory)?; let res = unsafe { self.device.device.invalidate_mapped_memory_ranges(&[range]) };
res.map_err(VulkanError::FlushMemory)?;
}
Ok(f(self.allocation.mem.unwrap(), self.size as usize)) Ok(f(self.allocation.mem.unwrap(), self.size as usize))
} }
fn range(&self) -> MappedMemoryRange { fn incoherent_range(&self, mask: u64) -> MappedMemoryRange {
let atom_mask = self.allocation.allocator.non_coherent_atom_mask;
MappedMemoryRange::default() MappedMemoryRange::default()
.memory(self.allocation.memory) .memory(self.allocation.memory)
.offset(self.allocation.offset & !atom_mask) .offset(self.allocation.offset & !mask)
.size((self.allocation.size + atom_mask) & !atom_mask) .size((self.allocation.size + mask) & !mask)
} }
} }