1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
6 use std::fmt::{self, Debug, Display};
7 use std::ops::{Deref, DerefMut};
10 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Enum)]
12 pub enum DeviceMemoryType {
16 impl DeviceMemoryType {
17 pub fn from_index(index: u32) -> Option<Self> {
18 for (enumerant, _) in EnumMap::<Self, ()>::from(|_| {}).iter() {
19 if enumerant as u32 == index {
20 return Some(enumerant);
25 pub fn heap(self) -> DeviceMemoryHeap {
27 DeviceMemoryType::Main => DeviceMemoryHeap::Main,
30 pub fn flags(self) -> api::VkMemoryPropertyFlags {
32 DeviceMemoryType::Main => {
33 api::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
34 | api::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
35 | api::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
36 | api::VK_MEMORY_PROPERTY_HOST_CACHED_BIT
40 pub fn to_bits(self) -> u32 {
45 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
46 pub struct DeviceMemoryTypes(EnumMap<DeviceMemoryType, bool>);
48 impl Default for DeviceMemoryTypes {
49 fn default() -> Self {
50 DeviceMemoryTypes(enum_map! {_ => false})
54 impl DeviceMemoryTypes {
56 pub fn to_bits(self) -> u32 {
58 for (enumerant, value) in self.iter() {
60 retval |= enumerant.to_bits();
67 impl From<EnumMap<DeviceMemoryType, bool>> for DeviceMemoryTypes {
68 fn from(v: EnumMap<DeviceMemoryType, bool>) -> Self {
73 impl From<DeviceMemoryType> for DeviceMemoryTypes {
74 fn from(v: DeviceMemoryType) -> Self {
75 DeviceMemoryTypes(EnumMap::from(|i| i == v))
79 impl Deref for DeviceMemoryTypes {
80 type Target = EnumMap<DeviceMemoryType, bool>;
81 fn deref(&self) -> &Self::Target {
86 impl DerefMut for DeviceMemoryTypes {
87 fn deref_mut(&mut self) -> &mut Self::Target {
92 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Enum)]
94 pub enum DeviceMemoryHeap {
98 impl DeviceMemoryHeap {
99 pub fn flags(self) -> api::VkMemoryHeapFlags {
101 DeviceMemoryHeap::Main => api::VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
105 pub fn to_bits(self) -> u32 {
109 pub fn from_index(index: u32) -> Option<Self> {
110 for (enumerant, _) in EnumMap::<Self, ()>::from(|_| {}).iter() {
111 if enumerant as u32 == index {
112 return Some(enumerant);
119 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
120 pub struct DeviceMemoryHeaps(EnumMap<DeviceMemoryHeap, bool>);
122 impl Default for DeviceMemoryHeaps {
123 fn default() -> Self {
124 DeviceMemoryHeaps(enum_map! {_ => false})
128 impl DeviceMemoryHeaps {
130 pub fn to_bits(self) -> u32 {
132 for (enumerant, value) in self.iter() {
134 retval |= enumerant.to_bits();
141 impl From<EnumMap<DeviceMemoryHeap, bool>> for DeviceMemoryHeaps {
142 fn from(v: EnumMap<DeviceMemoryHeap, bool>) -> Self {
147 impl From<DeviceMemoryHeap> for DeviceMemoryHeaps {
148 fn from(v: DeviceMemoryHeap) -> Self {
149 DeviceMemoryHeaps(EnumMap::from(|i| i == v))
153 impl Deref for DeviceMemoryHeaps {
154 type Target = EnumMap<DeviceMemoryHeap, bool>;
155 fn deref(&self) -> &Self::Target {
160 impl DerefMut for DeviceMemoryHeaps {
161 fn deref_mut(&mut self) -> &mut Self::Target {
166 #[derive(Copy, Clone, Debug)]
167 pub struct DeviceMemoryLayout {
169 pub alignment: usize,
172 impl DeviceMemoryLayout {
173 pub fn calculate(required_size: usize, required_alignment: usize) -> Self {
174 assert!(required_alignment.is_power_of_two());
175 assert_ne!(required_size, 0);
177 size: (required_size + required_alignment - 1) & !(required_alignment - 1),
178 alignment: required_alignment,
183 pub trait DeviceMemoryAllocation: 'static + Send + Sync + Debug {
184 unsafe fn get(&self) -> NonNull<u8>;
185 fn layout(&self) -> DeviceMemoryLayout;
186 fn size(&self) -> usize {
192 pub struct DefaultDeviceMemoryAllocation {
194 layout: alloc::Layout,
198 pub struct DefaultDeviceMemoryAllocationFailure;
200 impl Display for DefaultDeviceMemoryAllocationFailure {
201 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202 f.write_str("device memory allocation failed with default allocator")
206 impl DefaultDeviceMemoryAllocation {
207 pub fn new(layout: DeviceMemoryLayout) -> Result<Self, DefaultDeviceMemoryAllocationFailure> {
209 let layout = alloc::Layout::from_size_align(layout.size, layout.alignment).unwrap();
211 memory: NonNull::new(alloc::alloc(layout))
212 .ok_or(DefaultDeviceMemoryAllocationFailure)?,
219 unsafe impl Send for DefaultDeviceMemoryAllocation {}
221 unsafe impl Sync for DefaultDeviceMemoryAllocation {}
223 impl DeviceMemoryAllocation for DefaultDeviceMemoryAllocation {
224 unsafe fn get(&self) -> NonNull<u8> {
227 fn layout(&self) -> DeviceMemoryLayout {
229 size: self.layout.size(),
230 alignment: self.layout.align(),
235 impl Drop for DefaultDeviceMemoryAllocation {
238 alloc::dealloc(self.memory.as_ptr(), self.layout);
244 pub enum DeviceMemory {
245 Default(DefaultDeviceMemoryAllocation),
247 Special(Box<dyn DeviceMemoryAllocation>),
251 pub fn allocate_from_default_heap(
252 layout: DeviceMemoryLayout,
253 ) -> Result<Self, DefaultDeviceMemoryAllocationFailure> {
254 Ok(DeviceMemory::Default(DefaultDeviceMemoryAllocation::new(
260 impl DeviceMemoryAllocation for DeviceMemory {
261 unsafe fn get(&self) -> NonNull<u8> {
263 DeviceMemory::Default(memory) => memory.get(),
264 DeviceMemory::Special(memory) => memory.as_ref().get(),
267 fn layout(&self) -> DeviceMemoryLayout {
269 DeviceMemory::Default(memory) => memory.layout(),
270 DeviceMemory::Special(memory) => memory.as_ref().layout(),