Don't always map memory (#699)

This commit is contained in:
tomaka 2017-07-30 09:03:24 +02:00 committed by GitHub
parent beb1ddc200
commit 5e78de73e2
10 changed files with 63 additions and 36 deletions

View File

@ -46,6 +46,7 @@ use memory::Content;
use memory::CpuAccess as MemCpuAccess;
use memory::DeviceMemoryAllocError;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
@ -226,7 +227,8 @@ impl<T: ?Sized> CpuAccessibleBuffer<T> {
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Linear)?;
AllocLayout::Linear,
MappingRequirement::Map)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
debug_assert!(mem.mapped_memory().is_some());
buffer.bind_memory(mem.memory(), mem.offset())?;

View File

@ -34,6 +34,7 @@ use device::DeviceOwned;
use device::Queue;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPool;
@ -352,7 +353,8 @@ impl<T, A> CpuBufferPool<T, A>
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Linear)?;
AllocLayout::Linear,
MappingRequirement::Map)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
debug_assert!(mem.mapped_memory().is_some());
buffer.bind_memory(mem.memory(), mem.offset())?;

View File

@ -31,6 +31,7 @@ use device::DeviceOwned;
use device::Queue;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
@ -144,7 +145,8 @@ impl<T: ?Sized> DeviceLocalBuffer<T> {
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Linear)?;
AllocLayout::Linear,
MappingRequirement::DoNotMap)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
buffer.bind_memory(mem.memory(), mem.offset())?;

View File

@ -43,6 +43,7 @@ use device::DeviceOwned;
use device::Queue;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
@ -268,7 +269,8 @@ impl<T: ?Sized> ImmutableBuffer<T> {
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Linear)?;
AllocLayout::Linear,
MappingRequirement::DoNotMap)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
buffer.bind_memory(mem.memory(), mem.offset())?;

View File

@ -32,6 +32,7 @@ use image::traits::ImageClearValue;
use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
@ -228,7 +229,8 @@ impl<F> AttachmentImage<F> {
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Optimal)?;
AllocLayout::Optimal,
MappingRequirement::DoNotMap)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
unsafe {
image.bind_memory(mem.memory(), mem.offset())?;

View File

@ -39,6 +39,7 @@ use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
@ -153,7 +154,8 @@ impl<F> ImmutableImage<F> {
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Optimal)?;
AllocLayout::Optimal,
MappingRequirement::DoNotMap)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
unsafe {
image.bind_memory(mem.memory(), mem.offset())?;

View File

@ -31,6 +31,7 @@ use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPool;
@ -131,7 +132,8 @@ impl<F> StorageImage<F> {
mem_ty,
mem_reqs.size,
mem_reqs.alignment,
AllocLayout::Optimal)?;
AllocLayout::Optimal,
MappingRequirement::DoNotMap)?;
debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
unsafe {
image.bind_memory(mem.memory(), mem.offset())?;

View File

@ -34,6 +34,7 @@ impl StdHostVisibleMemoryTypePool {
/// # Panic
///
/// - Panics if the `device` and `memory_type` don't belong to the same physical device.
/// - Panics if the memory type is not host-visible.
///
#[inline]
pub fn new(device: Arc<Device>, memory_type: MemoryType) -> Arc<StdHostVisibleMemoryTypePool> {
@ -41,6 +42,7 @@ impl StdHostVisibleMemoryTypePool {
&**memory_type.physical_device().instance() as *const Instance);
assert_eq!(device.physical_device().index(),
memory_type.physical_device().index());
assert!(memory_type.is_host_visible());
Arc::new(StdHostVisibleMemoryTypePool {
device: device.clone(),

View File

@ -40,11 +40,12 @@ pub unsafe trait MemoryPool {
///
/// - Panics if `memory_type` doesn't belong to the same physical device as the device which
/// was used to create this pool.
/// - Panics if the memory type is not host-visible and `map` is `MappingRequirement::Map`.
/// - Panics if `size` is 0.
/// - Panics if `alignment` is 0.
///
fn alloc(&self, ty: MemoryType, size: usize, alignment: usize, layout: AllocLayout)
-> Result<Self::Alloc, DeviceMemoryAllocError>;
fn alloc(&self, ty: MemoryType, size: usize, alignment: usize, layout: AllocLayout,
map: MappingRequirement) -> Result<Self::Alloc, DeviceMemoryAllocError>;
}
/// Object that represents a single allocation. Its destructor should free the chunk.
@ -61,6 +62,15 @@ pub unsafe trait MemoryPoolAlloc {
fn offset(&self) -> usize;
}
/// Whether an allocation should map the memory or not.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MappingRequirement {
/// Should map.
Map,
/// Shouldn't map.
DoNotMap,
}
/// Layout of the object being allocated.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum AllocLayout {

View File

@ -20,6 +20,7 @@ use memory::DeviceMemory;
use memory::MappedDeviceMemory;
use memory::DeviceMemoryAllocError;
use memory::pool::AllocLayout;
use memory::pool::MappingRequirement;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdHostVisibleMemoryTypePool;
@ -32,7 +33,7 @@ pub struct StdMemoryPool {
device: Arc<Device>,
// For each memory type index, stores the associated pool.
pools: Mutex<HashMap<(u32, AllocLayout), Pool, BuildHasherDefault<FnvHasher>>>,
pools: Mutex<HashMap<(u32, AllocLayout, MappingRequirement), Pool, BuildHasherDefault<FnvHasher>>>,
}
impl StdMemoryPool {
@ -52,11 +53,14 @@ impl StdMemoryPool {
unsafe impl MemoryPool for Arc<StdMemoryPool> {
type Alloc = StdMemoryPoolAlloc;
fn alloc(&self, memory_type: MemoryType, size: usize, alignment: usize, layout: AllocLayout)
-> Result<StdMemoryPoolAlloc, DeviceMemoryAllocError> {
fn alloc(&self, memory_type: MemoryType, size: usize, alignment: usize, layout: AllocLayout,
map: MappingRequirement) -> Result<StdMemoryPoolAlloc, DeviceMemoryAllocError> {
let mut pools = self.pools.lock().unwrap();
match pools.entry((memory_type.id(), layout)) {
let memory_type_host_visible = memory_type.is_host_visible();
assert!(memory_type_host_visible || map == MappingRequirement::DoNotMap);
match pools.entry((memory_type.id(), layout, map)) {
Entry::Occupied(entry) => {
match entry.get() {
&Pool::HostVisible(ref pool) => {
@ -79,29 +83,26 @@ unsafe impl MemoryPool for Arc<StdMemoryPool> {
},
Entry::Vacant(entry) => {
match memory_type.is_host_visible() {
true => {
let pool = StdHostVisibleMemoryTypePool::new(self.device.clone(),
memory_type);
entry.insert(Pool::HostVisible(pool.clone()));
let alloc = StdHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?;
let inner = StdMemoryPoolAllocInner::HostVisible(alloc);
Ok(StdMemoryPoolAlloc {
inner: inner,
pool: self.clone(),
})
},
false => {
let pool = StdNonHostVisibleMemoryTypePool::new(self.device.clone(),
memory_type);
entry.insert(Pool::NonHostVisible(pool.clone()));
let alloc = StdNonHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?;
let inner = StdMemoryPoolAllocInner::NonHostVisible(alloc);
Ok(StdMemoryPoolAlloc {
inner: inner,
pool: self.clone(),
})
},
if memory_type_host_visible {
let pool = StdHostVisibleMemoryTypePool::new(self.device.clone(),
memory_type);
entry.insert(Pool::HostVisible(pool.clone()));
let alloc = StdHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?;
let inner = StdMemoryPoolAllocInner::HostVisible(alloc);
Ok(StdMemoryPoolAlloc {
inner: inner,
pool: self.clone(),
})
} else {
let pool = StdNonHostVisibleMemoryTypePool::new(self.device.clone(),
memory_type);
entry.insert(Pool::NonHostVisible(pool.clone()));
let alloc = StdNonHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?;
let inner = StdMemoryPoolAllocInner::NonHostVisible(alloc);
Ok(StdMemoryPoolAlloc {
inner: inner,
pool: self.clone(),
})
}
},
}