vulkan: move gpu-alloc-ash to core
This commit is contained in:
parent
fce250d233
commit
4b3d3a50cd
4 changed files with 3 additions and 7 deletions
199
src/vulkan_core/gpu_alloc_ash.rs
Normal file
199
src/vulkan_core/gpu_alloc_ash.rs
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
// Author: Zakarum <zakarumych@ya.ru>
|
||||
// https://github.com/zakarumych/gpu-alloc
|
||||
|
||||
use {
|
||||
ash::{
|
||||
Device, Instance,
|
||||
vk::{
|
||||
self, PhysicalDeviceFeatures2, PhysicalDeviceProperties2,
|
||||
PhysicalDeviceVulkan11Properties,
|
||||
},
|
||||
},
|
||||
gpu_alloc_types::{
|
||||
AllocationFlags, DeviceMapError, DeviceProperties, MappedMemoryRange, MemoryDevice,
|
||||
MemoryHeap, MemoryPropertyFlags, MemoryType, OutOfMemory,
|
||||
},
|
||||
smallvec::SmallVec,
|
||||
std::{mem, ptr::NonNull},
|
||||
};
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct AshMemoryDevice {
|
||||
device: Device,
|
||||
}
|
||||
|
||||
impl AshMemoryDevice {
|
||||
pub fn wrap(device: &Device) -> &Self {
|
||||
unsafe { mem::transmute::<&Device, &Self>(device) }
|
||||
}
|
||||
}
|
||||
|
||||
impl MemoryDevice<vk::DeviceMemory> for AshMemoryDevice {
|
||||
unsafe fn allocate_memory(
|
||||
&self,
|
||||
size: u64,
|
||||
memory_type: u32,
|
||||
flags: AllocationFlags,
|
||||
) -> Result<vk::DeviceMemory, OutOfMemory> {
|
||||
assert!((flags & !AllocationFlags::DEVICE_ADDRESS).is_empty());
|
||||
let mut info = vk::MemoryAllocateInfo::default()
|
||||
.allocation_size(size)
|
||||
.memory_type_index(memory_type);
|
||||
let mut info_flags;
|
||||
if flags.contains(AllocationFlags::DEVICE_ADDRESS) {
|
||||
info_flags = vk::MemoryAllocateFlagsInfo::default()
|
||||
.flags(vk::MemoryAllocateFlags::DEVICE_ADDRESS);
|
||||
info = info.push_next(&mut info_flags);
|
||||
}
|
||||
let res = unsafe { self.device.allocate_memory(&info, None) };
|
||||
match res {
|
||||
Ok(memory) => Ok(memory),
|
||||
Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(OutOfMemory::OutOfDeviceMemory),
|
||||
Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(OutOfMemory::OutOfHostMemory),
|
||||
Err(vk::Result::ERROR_TOO_MANY_OBJECTS) => panic!("Too many objects"),
|
||||
Err(err) => panic!("Unexpected Vulkan error: `{}`", err),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn deallocate_memory(&self, memory: vk::DeviceMemory) {
|
||||
unsafe {
|
||||
self.device.free_memory(memory, None);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn map_memory(
|
||||
&self,
|
||||
memory: &mut vk::DeviceMemory,
|
||||
offset: u64,
|
||||
size: u64,
|
||||
) -> Result<NonNull<u8>, DeviceMapError> {
|
||||
let res = unsafe {
|
||||
self.device
|
||||
.map_memory(*memory, offset, size, vk::MemoryMapFlags::empty())
|
||||
};
|
||||
match res {
|
||||
Ok(ptr) => {
|
||||
Ok(NonNull::new(ptr as *mut u8)
|
||||
.expect("Pointer to memory mapping must not be null"))
|
||||
}
|
||||
Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(DeviceMapError::OutOfDeviceMemory),
|
||||
Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(DeviceMapError::OutOfHostMemory),
|
||||
Err(vk::Result::ERROR_MEMORY_MAP_FAILED) => Err(DeviceMapError::MapFailed),
|
||||
Err(err) => panic!("Unexpected Vulkan error: `{}`", err),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unmap_memory(&self, memory: &mut vk::DeviceMemory) {
|
||||
unsafe {
|
||||
self.device.unmap_memory(*memory);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn invalidate_memory_ranges(
|
||||
&self,
|
||||
ranges: &[MappedMemoryRange<'_, vk::DeviceMemory>],
|
||||
) -> Result<(), OutOfMemory> {
|
||||
unsafe {
|
||||
self.device
|
||||
.invalidate_mapped_memory_ranges(&map_ranges(ranges))
|
||||
.map_err(|err| match err {
|
||||
vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => OutOfMemory::OutOfDeviceMemory,
|
||||
vk::Result::ERROR_OUT_OF_HOST_MEMORY => OutOfMemory::OutOfHostMemory,
|
||||
err => panic!("Unexpected Vulkan error: `{}`", err),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn flush_memory_ranges(
|
||||
&self,
|
||||
ranges: &[MappedMemoryRange<'_, vk::DeviceMemory>],
|
||||
) -> Result<(), OutOfMemory> {
|
||||
unsafe {
|
||||
self.device
|
||||
.flush_mapped_memory_ranges(&map_ranges(ranges))
|
||||
.map_err(|err| match err {
|
||||
vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => OutOfMemory::OutOfDeviceMemory,
|
||||
vk::Result::ERROR_OUT_OF_HOST_MEMORY => OutOfMemory::OutOfHostMemory,
|
||||
err => panic!("Unexpected Vulkan error: `{}`", err),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn device_properties(
|
||||
instance: &Instance,
|
||||
physical_device: vk::PhysicalDevice,
|
||||
) -> Result<DeviceProperties<'static>, vk::Result> {
|
||||
let mut properties_11 = PhysicalDeviceVulkan11Properties::default();
|
||||
let mut properties = PhysicalDeviceProperties2::default().push_next(&mut properties_11);
|
||||
unsafe {
|
||||
instance.get_physical_device_properties2(physical_device, &mut properties);
|
||||
};
|
||||
let limits = properties.properties.limits;
|
||||
let memory_properties =
|
||||
unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
||||
let buffer_device_address = {
|
||||
let mut bda_features = vk::PhysicalDeviceBufferDeviceAddressFeatures::default();
|
||||
let mut features = PhysicalDeviceFeatures2::default().push_next(&mut bda_features);
|
||||
unsafe {
|
||||
instance.get_physical_device_features2(physical_device, &mut features);
|
||||
}
|
||||
bda_features.buffer_device_address != 0
|
||||
};
|
||||
Ok(DeviceProperties {
|
||||
max_memory_allocation_count: limits.max_memory_allocation_count,
|
||||
max_memory_allocation_size: properties_11.max_memory_allocation_size,
|
||||
non_coherent_atom_size: limits.non_coherent_atom_size,
|
||||
memory_types: memory_properties.memory_types
|
||||
[..memory_properties.memory_type_count as usize]
|
||||
.iter()
|
||||
.map(|memory_type| MemoryType {
|
||||
props: memory_properties_from_ash(memory_type.property_flags),
|
||||
heap: memory_type.heap_index,
|
||||
})
|
||||
.collect(),
|
||||
memory_heaps: memory_properties.memory_heaps
|
||||
[..memory_properties.memory_heap_count as usize]
|
||||
.iter()
|
||||
.map(|&memory_heap| MemoryHeap {
|
||||
size: memory_heap.size,
|
||||
})
|
||||
.collect(),
|
||||
buffer_device_address,
|
||||
})
|
||||
}
|
||||
|
||||
fn memory_properties_from_ash(props: vk::MemoryPropertyFlags) -> MemoryPropertyFlags {
|
||||
let mut result = MemoryPropertyFlags::empty();
|
||||
if props.contains(vk::MemoryPropertyFlags::DEVICE_LOCAL) {
|
||||
result |= MemoryPropertyFlags::DEVICE_LOCAL;
|
||||
}
|
||||
if props.contains(vk::MemoryPropertyFlags::HOST_VISIBLE) {
|
||||
result |= MemoryPropertyFlags::HOST_VISIBLE;
|
||||
}
|
||||
if props.contains(vk::MemoryPropertyFlags::HOST_COHERENT) {
|
||||
result |= MemoryPropertyFlags::HOST_COHERENT;
|
||||
}
|
||||
if props.contains(vk::MemoryPropertyFlags::HOST_CACHED) {
|
||||
result |= MemoryPropertyFlags::HOST_CACHED;
|
||||
}
|
||||
if props.contains(vk::MemoryPropertyFlags::LAZILY_ALLOCATED) {
|
||||
result |= MemoryPropertyFlags::LAZILY_ALLOCATED;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn map_ranges(
|
||||
ranges: &[MappedMemoryRange<'_, vk::DeviceMemory>],
|
||||
) -> SmallVec<[vk::MappedMemoryRange<'static>; 4]> {
|
||||
ranges
|
||||
.iter()
|
||||
.map(|range| {
|
||||
vk::MappedMemoryRange::default()
|
||||
.memory(*range.memory)
|
||||
.offset(range.offset)
|
||||
.size(range.size)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue