1use crate::{
2 AllocationAccess, AllocatorAccess, Device, DeviceOwned, ImageAccess, ImageDimensions,
3 MemoryAllocation, MemoryAllocator, PhysicalDevice,
4};
5use ash::{
6 prelude::VkResult,
7 vk::{self, Handle},
8};
9use bort_vma::{Alloc, AllocationCreateInfo};
10use std::sync::Arc;
11
12pub struct Image {
15 handle: vk::Image,
16 image_properties: ImageProperties,
17 memory_allocation: MemoryAllocation,
18}
19
20impl Image {
21 pub fn new(
22 alloc_access: Arc<dyn AllocatorAccess>,
23 image_properties: ImageProperties,
24 allocation_info: AllocationCreateInfo,
25 ) -> VkResult<Self> {
26 let (handle, vma_allocation) = unsafe {
27 alloc_access
28 .vma_allocator()
29 .create_image(&image_properties.create_info_builder(), &allocation_info)
30 }?;
31
32 let memory_allocation = MemoryAllocation::from_vma_allocation(vma_allocation, alloc_access);
33
34 Ok(Self {
35 handle,
36 image_properties,
37 memory_allocation,
38 })
39 }
40
41 pub unsafe fn new_from_create_info(
42 alloc_access: Arc<dyn AllocatorAccess>,
43 image_create_info_builder: vk::ImageCreateInfoBuilder,
44 allocation_info: AllocationCreateInfo,
45 ) -> VkResult<Self> {
46 let image_properties =
47 ImageProperties::from_create_info_builder(&image_create_info_builder);
48
49 let (handle, vma_allocation) = unsafe {
50 alloc_access
51 .vma_allocator()
52 .create_image(&image_create_info_builder, &allocation_info)
53 }?;
54
55 let memory_allocation = MemoryAllocation::from_vma_allocation(vma_allocation, alloc_access);
56
57 Ok(Self {
58 handle,
59 image_properties,
60 memory_allocation,
61 })
62 }
63
64 pub fn new_tranient(
66 memory_allocator: Arc<MemoryAllocator>,
67 dimensions: ImageDimensions,
68 format: vk::Format,
69 additional_usage: vk::ImageUsageFlags,
70 ) -> VkResult<Self> {
71 let (image_properties, allocation_info) =
72 transient_image_info(dimensions, format, additional_usage);
73
74 Self::new(memory_allocator, image_properties, allocation_info)
75 }
76
77 #[inline]
80 pub fn properties(&self) -> &ImageProperties {
81 &self.image_properties
82 }
83
84 #[inline]
85 pub fn allocator_access(&self) -> &Arc<dyn AllocatorAccess> {
86 &self.memory_allocation.allocator_access()
87 }
88
89 #[inline]
90 pub fn memory_allocation(&self) -> &MemoryAllocation {
91 &self.memory_allocation
92 }
93}
94
95impl ImageAccess for Image {
96 #[inline]
97 fn handle(&self) -> vk::Image {
98 self.handle
99 }
100
101 #[inline]
102 fn dimensions(&self) -> ImageDimensions {
103 self.image_properties.dimensions
104 }
105}
106
107impl AllocationAccess for Image {
108 fn memory_allocation_mut(&mut self) -> &mut MemoryAllocation {
109 &mut self.memory_allocation
110 }
111}
112
113impl DeviceOwned for Image {
114 #[inline]
115 fn device(&self) -> &Arc<Device> {
116 &self.memory_allocation.device()
117 }
118
119 #[inline]
120 fn handle_raw(&self) -> u64 {
121 self.handle.as_raw()
122 }
123}
124
125impl Drop for Image {
126 fn drop(&mut self) {
127 unsafe {
128 self.allocator_access()
129 .clone()
130 .vma_allocator()
131 .destroy_image(self.handle, self.memory_allocation.inner_mut());
132 }
133 }
134}
135
136pub fn transient_image_info(
140 dimensions: ImageDimensions,
141 format: vk::Format,
142 additional_usage: vk::ImageUsageFlags,
143) -> (ImageProperties, AllocationCreateInfo) {
144 let image_properties = ImageProperties::new_default(
145 format,
146 dimensions,
147 vk::ImageUsageFlags::TRANSIENT_ATTACHMENT | additional_usage,
148 );
149
150 let allocation_info = AllocationCreateInfo {
151 required_flags: vk::MemoryPropertyFlags::DEVICE_LOCAL,
153 preferred_flags: vk::MemoryPropertyFlags::LAZILY_ALLOCATED,
154 ..AllocationCreateInfo::default()
155 };
156
157 (image_properties, allocation_info)
158}
159
160#[derive(Debug, Clone)]
164pub struct ImageProperties {
165 pub flags: vk::ImageCreateFlags,
166 pub format: vk::Format,
167 pub dimensions: ImageDimensions,
168 pub mip_levels: u32,
169 pub samples: vk::SampleCountFlags,
170 pub tiling: vk::ImageTiling,
171 pub usage: vk::ImageUsageFlags,
172 pub sharing_mode: vk::SharingMode,
173 pub queue_family_indices: Vec<u32>,
174 pub initial_layout: vk::ImageLayout,
175}
176
177impl Default for ImageProperties {
178 fn default() -> Self {
179 Self {
180 mip_levels: 1,
181 samples: vk::SampleCountFlags::TYPE_1,
182 tiling: vk::ImageTiling::OPTIMAL,
183 sharing_mode: vk::SharingMode::EXCLUSIVE,
184 queue_family_indices: Vec::new(),
185 initial_layout: vk::ImageLayout::UNDEFINED,
186 flags: vk::ImageCreateFlags::empty(),
187
188 format: vk::Format::default(),
190 dimensions: ImageDimensions::default(),
191 usage: vk::ImageUsageFlags::empty(),
192 }
193 }
194}
195
196impl ImageProperties {
197 pub fn subresource_range(&self) -> vk::ImageSubresourceRange {
198 let aspect_mask = aspect_mask_from_format(self.format);
199 vk::ImageSubresourceRange {
200 aspect_mask,
201 base_mip_level: 0,
202 level_count: self.mip_levels,
203 base_array_layer: 0,
204 layer_count: self.dimensions.array_layers(),
205 }
206 }
207
208 #[inline]
209 pub fn new_default(
210 format: vk::Format,
211 dimensions: ImageDimensions,
212 usage: vk::ImageUsageFlags,
213 ) -> Self {
214 Self {
215 format,
216 dimensions,
217 usage,
218 ..Self::default()
219 }
220 }
221
222 pub fn create_info_builder(&self) -> vk::ImageCreateInfoBuilder {
223 vk::ImageCreateInfo::builder()
224 .flags(self.flags)
225 .image_type(self.dimensions.image_type())
226 .format(self.format)
227 .extent(self.dimensions.extent_3d())
228 .mip_levels(self.mip_levels)
229 .array_layers(self.dimensions.array_layers())
230 .samples(self.samples)
231 .tiling(self.tiling)
232 .usage(self.usage)
233 .sharing_mode(self.sharing_mode)
234 .initial_layout(self.initial_layout)
235 .queue_family_indices(&self.queue_family_indices)
236 }
237
238 fn from_create_info_builder(value: &vk::ImageCreateInfoBuilder) -> Self {
239 let dimensions =
240 ImageDimensions::new_from_extent_and_layers(value.extent, value.array_layers);
241
242 let mut queue_family_indices = Vec::<u32>::new();
243 for i in 0..value.queue_family_index_count {
244 let queue_family_index = unsafe { *value.p_queue_family_indices.offset(i as isize) };
245 queue_family_indices.push(queue_family_index);
246 }
247
248 Self {
249 mip_levels: value.mip_levels,
250 samples: value.samples,
251 tiling: value.tiling,
252 sharing_mode: value.sharing_mode,
253 queue_family_indices,
254 initial_layout: value.initial_layout,
255 flags: value.flags,
256 format: value.format,
257 dimensions,
258 usage: value.usage,
259 }
260 }
261}
262
263pub fn guaranteed_depth_stencil_format(physical_device: &PhysicalDevice) -> vk::Format {
273 let d24_s8_props = unsafe {
274 physical_device
275 .instance()
276 .inner()
277 .get_physical_device_format_properties(
278 physical_device.handle(),
279 vk::Format::D24_UNORM_S8_UINT,
280 )
281 };
282
283 if d24_s8_props
284 .optimal_tiling_features
285 .contains(vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT)
286 {
287 return vk::Format::D24_UNORM_S8_UINT;
288 } else {
289 return vk::Format::D32_SFLOAT_S8_UINT;
290 }
291}
292
293pub fn guaranteed_pure_depth_format(physical_device: &PhysicalDevice) -> vk::Format {
301 let d32_props = unsafe {
302 physical_device
303 .instance()
304 .inner()
305 .get_physical_device_format_properties(physical_device.handle(), vk::Format::D32_SFLOAT)
306 };
307
308 if d32_props
309 .optimal_tiling_features
310 .contains(vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT)
311 {
312 return vk::Format::D32_SFLOAT;
313 } else {
314 return vk::Format::X8_D24_UNORM_PACK32;
315 }
316}
317
318pub fn extent_2d_from_width_height(dimensions: [u32; 2]) -> vk::Extent2D {
319 vk::Extent2D {
320 width: dimensions[0],
321 height: dimensions[1],
322 }
323}
324
325pub fn aspect_mask_from_format(format: vk::Format) -> vk::ImageAspectFlags {
327 let mut aspect = vk::ImageAspectFlags::empty();
328
329 if !matches!(
330 format,
331 vk::Format::D16_UNORM
332 | vk::Format::X8_D24_UNORM_PACK32
333 | vk::Format::D32_SFLOAT
334 | vk::Format::S8_UINT
335 | vk::Format::D16_UNORM_S8_UINT
336 | vk::Format::D24_UNORM_S8_UINT
337 | vk::Format::D32_SFLOAT_S8_UINT
338 ) {
339 aspect |= vk::ImageAspectFlags::COLOR;
340 }
341
342 if matches!(
343 format,
344 vk::Format::D16_UNORM
345 | vk::Format::X8_D24_UNORM_PACK32
346 | vk::Format::D32_SFLOAT
347 | vk::Format::D16_UNORM_S8_UINT
348 | vk::Format::D24_UNORM_S8_UINT
349 | vk::Format::D32_SFLOAT_S8_UINT
350 ) {
351 aspect |= vk::ImageAspectFlags::DEPTH;
352 }
353
354 if matches!(
355 format,
356 vk::Format::S8_UINT
357 | vk::Format::D16_UNORM_S8_UINT
358 | vk::Format::D24_UNORM_S8_UINT
359 | vk::Format::D32_SFLOAT_S8_UINT
360 ) {
361 aspect |= vk::ImageAspectFlags::STENCIL;
362 }
363
364 aspect
365}