1
2use crate::prelude::*;
3use std::{
4 any::TypeId,
5 cmp::max,
6 ffi::c_void,
7 fmt::{self, Debug, Formatter},
8 mem::{MaybeUninit, size_of},
9 ops::Deref,
10 ptr::{copy, null},
11 sync::Arc,
12};
13use image::{
14 ImageBuffer,
15 Pixel,
16};
17
18#[derive(Debug, Clone, Copy)]
20pub struct TextureRegion {
21 pub offset: VkOffset3D,
22 pub extent: VkExtent3D,
23}
24
25#[derive(Debug, Clone, Copy)]
27pub enum VulkanTextureType {
28 T1d(u32),
30
31 T2d(VkExtent2D),
33
34 T3d(VkExtent3D),
36
37 Cube(u32),
39
40 DepthStencil(VkExtent2D),
42}
43
44impl VulkanTextureType {
45 pub fn is_cube(&self) -> bool {
47 matches!(self, Self::Cube(_))
48 }
49
50 pub fn is_depth_stencil(&self) -> bool {
52 matches!(self, Self::DepthStencil(_))
53 }
54
55 pub fn get_image_type(&self) -> VkImageType {
57 match self {
58 Self::T1d(_) => {
59 VkImageType::VK_IMAGE_TYPE_1D
60 }
61 Self::T2d(_) => {
62 VkImageType::VK_IMAGE_TYPE_2D
63 }
64 Self::T3d(_) => {
65 VkImageType::VK_IMAGE_TYPE_3D
66 }
67 Self::Cube(_) => {
68 VkImageType::VK_IMAGE_TYPE_2D
69 }
70 Self::DepthStencil(_) => {
71 VkImageType::VK_IMAGE_TYPE_2D
72 }
73 }
74 }
75
76 pub fn get_extent(&self) -> VkExtent3D {
78 match self {
79 Self::T1d(size) => {
80 VkExtent3D {
81 width: *size,
82 height: 1,
83 depth: 1,
84 }
85 }
86 Self::T2d(size) => {
87 VkExtent3D {
88 width: size.width,
89 height: size.height,
90 depth: 1,
91 }
92 }
93 Self::T3d(size) => {
94 VkExtent3D {
95 width: size.width,
96 height: size.height,
97 depth: size.depth,
98 }
99 }
100 Self::Cube(size) => {
101 VkExtent3D {
102 width: *size,
103 height: *size,
104 depth: 1,
105 }
106 }
107 Self::DepthStencil(size) => {
108 VkExtent3D {
109 width: size.width,
110 height: size.height,
111 depth: 1,
112 }
113 }
114 }
115 }
116}
117
118unsafe impl Send for VulkanTextureType {}
119
120pub struct VulkanTexture {
122 pub device: Arc<VulkanDevice>,
124
125 pub(crate) image: VkImage,
127
128 pub(crate) image_view: VkImageView,
130
131 pub(crate) type_size: VulkanTextureType,
133
134 pub(crate) format: VkFormat,
136
137 pub(crate) memory: Option<VulkanMemory>,
139
140 pub staging_buffer: Option<StagingBuffer>,
142
143 mipmap_levels: u32,
145}
146
147impl VulkanTexture {
148 pub fn new(device: Arc<VulkanDevice>, type_size: VulkanTextureType, with_mipmap: bool, format: VkFormat, usage: VkImageUsageFlags) -> Result<Self, VulkanError> {
150 let vkcore = device.vkcore.clone();
151 let vkdevice = device.get_vk_device();
152 let extent = type_size.get_extent();
153 let dim = type_size.get_image_type();
154 let is_cube = type_size.is_cube();
155 let mipmap_levels = if with_mipmap {
156 let mut levels = 0u32;
157 let mut size = max(max(extent.width, extent.height), extent.depth);
158 while size > 0 {
159 size >>= 1;
160 levels += 1;
161 }
162 levels
163 } else {
164 1
165 };
166 let image_ci = VkImageCreateInfo {
167 sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
168 pNext: null(),
169 flags: if is_cube {VkImageCreateFlagBits::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT as VkImageCreateFlags} else {0},
170 imageType: dim,
171 format,
172 extent,
173 mipLevels: mipmap_levels,
174 arrayLayers: 1,
175 samples: VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT,
176 tiling: VkImageTiling::VK_IMAGE_TILING_OPTIMAL,
177 usage,
178 sharingMode: VkSharingMode::VK_SHARING_MODE_EXCLUSIVE,
179 queueFamilyIndexCount: 0,
180 pQueueFamilyIndices: null(),
181 initialLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
182 };
183 let mut image: VkImage = null();
184 vkcore.vkCreateImage(vkdevice, &image_ci, null(), &mut image)?;
185 let image = ResourceGuard::new(image, |&i|vkcore.clone().vkDestroyImage(vkdevice, i, null()).unwrap());
186 let mut mem_reqs: VkMemoryRequirements = unsafe {MaybeUninit::zeroed().assume_init()};
187 vkcore.vkGetImageMemoryRequirements(vkdevice, *image, &mut mem_reqs)?;
188 let memory = VulkanMemory::new(device.clone(), &mem_reqs, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT as u32)?;
189 memory.bind_vk_image(*image)?;
190 let mut ret = Self::new_from_existing_image(device, *image, type_size, format)?;
191 ret.memory = Some(memory);
192 ret.mipmap_levels = mipmap_levels;
193 image.release();
194 Ok(ret)
195 }
196
197 pub(crate) fn new_from_existing_image(device: Arc<VulkanDevice>, image: VkImage, type_size: VulkanTextureType, format: VkFormat) -> Result<Self, VulkanError> {
199 let vkcore = device.vkcore.clone();
200 let vkdevice = device.get_vk_device();
201 let image_view_ci = VkImageViewCreateInfo {
202 sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
203 pNext: null(),
204 flags: 0,
205 image,
206 viewType: if type_size.is_cube() {
207 VkImageViewType::VK_IMAGE_VIEW_TYPE_CUBE
208 } else {
209 match type_size.get_image_type() {
210 VkImageType::VK_IMAGE_TYPE_1D => VkImageViewType::VK_IMAGE_VIEW_TYPE_1D,
211 VkImageType::VK_IMAGE_TYPE_2D => VkImageViewType::VK_IMAGE_VIEW_TYPE_2D,
212 VkImageType::VK_IMAGE_TYPE_3D => VkImageViewType::VK_IMAGE_VIEW_TYPE_3D,
213 _ => panic!("Bad image type"),
214 }
215 },
216 format,
217 components: VkComponentMapping {
218 r: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
219 g: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
220 b: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
221 a: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
222 },
223 subresourceRange: VkImageSubresourceRange {
224 aspectMask: if type_size.is_depth_stencil() {
225 VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT as VkImageAspectFlags |
226 VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT as VkImageAspectFlags
227 } else {
228 VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags
229 },
230 baseMipLevel: 0,
231 levelCount: 1,
232 baseArrayLayer: 0,
233 layerCount: 1,
234 },
235 };
236 let mut image_view: VkImageView = null();
237 vkcore.vkCreateImageView(vkdevice, &image_view_ci, null(), &mut image_view)?;
238 Ok(Self {
239 device,
240 image,
241 image_view,
242 type_size,
243 format,
244 memory: None,
245 staging_buffer: None,
246 mipmap_levels: 1,
247 })
248 }
249
250 pub fn new_from_image<P, Container>(device: Arc<VulkanDevice>, cmdbuf: VkCommandBuffer, image: &ImageBuffer<P, Container>, channel_is_normalized: bool, with_mipmap: bool, usage: VkImageUsageFlags) -> Result<Self, VulkanError>
252 where
253 P: Pixel,
254 Container: Deref<Target = [P::Subpixel]>,
255 <P as Pixel>::Subpixel: 'static {
256 let (width, height) = image.dimensions();
257 let extent = VkExtent2D {
258 width,
259 height,
260 };
261 let is_signed;
262 let is_float;
263 let bits;
264 if TypeId::of::<P::Subpixel>() == TypeId::of::<i8>() {
265 is_signed = true;
266 is_float = false;
267 bits = 8;
268 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<u8>() {
269 is_signed = false;
270 is_float = false;
271 bits = 8;
272 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<i16>() {
273 is_signed = true;
274 is_float = false;
275 bits = 16;
276 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<u16>() {
277 is_signed = false;
278 is_float = false;
279 bits = 16;
280 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<i32>() {
281 is_signed = true;
282 is_float = false;
283 bits = 32;
284 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<u32>() {
285 is_signed = false;
286 is_float = false;
287 bits = 32;
288 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<f32>() {
289 is_signed = true;
290 is_float = true;
291 bits = 32;
292 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<i64>() {
293 is_signed = true;
294 is_float = false;
295 bits = 64;
296 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<u64>() {
297 is_signed = false;
298 is_float = false;
299 bits = 64;
300 } else if TypeId::of::<P::Subpixel>() == TypeId::of::<f64>() {
301 is_signed = true;
302 is_float = true;
303 bits = 64;
304 } else {
305 return Err(VulkanError::ImagePixelFormatNotSupported);
306 }
307 let format = match (P::CHANNEL_COUNT, bits, is_signed, channel_is_normalized, is_float) {
308 (1, 8, true, false, false) => VkFormat::VK_FORMAT_R8_SINT,
309 (1, 8, true, true, false) => VkFormat::VK_FORMAT_R8_SNORM,
310 (1, 8, false, false, false) => VkFormat::VK_FORMAT_R8_UINT,
311 (1, 8, false, true, false) => VkFormat::VK_FORMAT_R8_UNORM,
312 (2, 8, true, false, false) => VkFormat::VK_FORMAT_R8G8_SINT,
313 (2, 8, true, true, false) => VkFormat::VK_FORMAT_R8G8_SNORM,
314 (2, 8, false, false, false) => VkFormat::VK_FORMAT_R8G8_UINT,
315 (2, 8, false, true, false) => VkFormat::VK_FORMAT_R8G8_UNORM,
316 (3, 8, true, false, false) => VkFormat::VK_FORMAT_R8G8B8_SINT,
317 (3, 8, true, true, false) => VkFormat::VK_FORMAT_R8G8B8_SNORM,
318 (3, 8, false, false, false) => VkFormat::VK_FORMAT_R8G8B8_UINT,
319 (3, 8, false, true, false) => VkFormat::VK_FORMAT_R8G8B8_UNORM,
320 (4, 8, true, false, false) => VkFormat::VK_FORMAT_R8G8B8A8_SINT,
321 (4, 8, true, true, false) => VkFormat::VK_FORMAT_R8G8B8A8_SNORM,
322 (4, 8, false, false, false) => VkFormat::VK_FORMAT_R8G8B8A8_UINT,
323 (4, 8, false, true, false) => VkFormat::VK_FORMAT_R8G8B8A8_UNORM,
324 (1, 16, true, false, false) => VkFormat::VK_FORMAT_R16_SINT,
325 (1, 16, true, true, false) => VkFormat::VK_FORMAT_R16_SNORM,
326 (1, 16, false, false, false) => VkFormat::VK_FORMAT_R16_UINT,
327 (1, 16, false, true, false) => VkFormat::VK_FORMAT_R16_UNORM,
328 (2, 16, true, false, false) => VkFormat::VK_FORMAT_R16G16_SINT,
329 (2, 16, true, true, false) => VkFormat::VK_FORMAT_R16G16_SNORM,
330 (2, 16, false, false, false) => VkFormat::VK_FORMAT_R16G16_UINT,
331 (2, 16, false, true, false) => VkFormat::VK_FORMAT_R16G16_UNORM,
332 (3, 16, true, false, false) => VkFormat::VK_FORMAT_R16G16B16_SINT,
333 (3, 16, true, true, false) => VkFormat::VK_FORMAT_R16G16B16_SNORM,
334 (3, 16, false, false, false) => VkFormat::VK_FORMAT_R16G16B16_UINT,
335 (3, 16, false, true, false) => VkFormat::VK_FORMAT_R16G16B16_UNORM,
336 (4, 16, true, false, false) => VkFormat::VK_FORMAT_R16G16B16A16_SINT,
337 (4, 16, true, true, false) => VkFormat::VK_FORMAT_R16G16B16A16_SNORM,
338 (4, 16, false, false, false) => VkFormat::VK_FORMAT_R16G16B16A16_UINT,
339 (4, 16, false, true, false) => VkFormat::VK_FORMAT_R16G16B16A16_UNORM,
340 (1, 32, true, false, false) => VkFormat::VK_FORMAT_R32_SINT,
341 (1, 32, false, false, false) => VkFormat::VK_FORMAT_R32_UINT,
342 (2, 32, true, false, false) => VkFormat::VK_FORMAT_R32G32_SINT,
343 (2, 32, false, false, false) => VkFormat::VK_FORMAT_R32G32_UINT,
344 (3, 32, true, false, false) => VkFormat::VK_FORMAT_R32G32B32_SINT,
345 (3, 32, false, false, false) => VkFormat::VK_FORMAT_R32G32B32_UINT,
346 (4, 32, true, false, false) => VkFormat::VK_FORMAT_R32G32B32A32_SINT,
347 (4, 32, false, false, false) => VkFormat::VK_FORMAT_R32G32B32A32_UINT,
348 (1, 64, true, false, false) => VkFormat::VK_FORMAT_R64_SINT,
349 (1, 64, false, false, false) => VkFormat::VK_FORMAT_R64_UINT,
350 (2, 64, true, false, false) => VkFormat::VK_FORMAT_R64G64_SINT,
351 (2, 64, false, false, false) => VkFormat::VK_FORMAT_R64G64_UINT,
352 (3, 64, true, false, false) => VkFormat::VK_FORMAT_R64G64B64_SINT,
353 (3, 64, false, false, false) => VkFormat::VK_FORMAT_R64G64B64_UINT,
354 (4, 64, true, false, false) => VkFormat::VK_FORMAT_R64G64B64A64_SINT,
355 (4, 64, false, false, false) => VkFormat::VK_FORMAT_R64G64B64A64_UINT,
356 (1, 32, true, false, true) => VkFormat::VK_FORMAT_R32_SFLOAT,
357 (2, 32, true, false, true) => VkFormat::VK_FORMAT_R32G32_SFLOAT,
358 (3, 32, true, false, true) => VkFormat::VK_FORMAT_R32G32B32_SFLOAT,
359 (4, 32, true, false, true) => VkFormat::VK_FORMAT_R32G32B32A32_SFLOAT,
360 (1, 64, true, false, true) => VkFormat::VK_FORMAT_R64_SFLOAT,
361 (2, 64, true, false, true) => VkFormat::VK_FORMAT_R64G64_SFLOAT,
362 (3, 64, true, false, true) => VkFormat::VK_FORMAT_R64G64B64_SFLOAT,
363 (4, 64, true, false, true) => VkFormat::VK_FORMAT_R64G64B64A64_SFLOAT,
364 _ => return Err(VulkanError::ImagePixelFormatNotSupported),
365 };
366 let mut ret = Self::new(device, VulkanTextureType::T2d(extent), with_mipmap, format, usage)?;
367 unsafe {ret.set_staging_data_from_compact_pixels(0, image.as_ptr() as *const c_void, (bits / 8 * P::CHANNEL_COUNT) as usize * width as usize, height)?};
368 let offset = VkOffset3D {
369 x: 0,
370 y: 0,
371 z: 0,
372 };
373 let update_extent = VkExtent3D {
374 width,
375 height,
376 depth: 1,
377 };
378 ret.upload_staging_buffer(cmdbuf, &offset, &update_extent)?;
379 Ok(ret)
380 }
381
382 pub fn get_size(&self) -> Result<VkDeviceSize, VulkanError> {
384 let mut mem_reqs: VkMemoryRequirements = unsafe {MaybeUninit::zeroed().assume_init()};
385 self.device.vkcore.vkGetImageMemoryRequirements(self.device.get_vk_device(), self.image, &mut mem_reqs)?;
386 Ok(mem_reqs.size)
387 }
388
389 pub fn get_pitch(&self) -> Result<usize, VulkanError> {
391 let subresource = VkImageSubresource {
392 aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
393 mipLevel: 0,
394 arrayLayer: 0,
395 };
396 let mut layout = unsafe {MaybeUninit::zeroed().assume_init()};
397 self.device.vkcore.vkGetImageSubresourceLayout(self.device.get_vk_device(), self.image, &subresource, &mut layout)?;
398 Ok(layout.rowPitch as usize)
399 }
400
401 pub fn get_mipmap_levels(&self) -> u32 {
403 self.mipmap_levels
404 }
405
406 pub fn ensure_staging_buffer(&mut self) -> Result<(), VulkanError> {
408 if self.staging_buffer.is_none() {
409 self.staging_buffer = Some(StagingBuffer::new(self.device.clone(), self.get_size()?)?);
410 }
411 Ok(())
412 }
413
414 pub fn get_staging_buffer_address(&mut self) -> Result<*mut c_void, VulkanError> {
416 self.ensure_staging_buffer()?;
417 Ok(self.staging_buffer.as_ref().unwrap().address)
418 }
419
420 pub fn discard_staging_buffer(&mut self) {
422 self.staging_buffer = None;
423 }
424
425 pub fn set_staging_data(&mut self, data: *const c_void, offset: VkDeviceSize, size: usize) -> Result<(), VulkanError> {
427 self.ensure_staging_buffer()?;
428 self.staging_buffer.as_mut().unwrap().set_data(data, offset, size)?;
429 Ok(())
430 }
431
432 pub unsafe fn set_staging_data_from_compact_pixels(&mut self, offset: usize, src_ptr: *const c_void, src_stride: usize, num_rows: u32) -> Result<(), VulkanError> {
441 let pitch = self.get_pitch()?;
442 let target_address = (self.get_staging_buffer_address()? as *mut u8).wrapping_add(offset);
443 let source_address = src_ptr as *const u8;
444 if pitch == src_stride {
445 unsafe {copy(source_address, target_address, src_stride * num_rows as usize)};
446 } else {
447 for y in 0..num_rows {
448 let src_offset = y as usize * src_stride;
449 let dst_offset = y as usize * pitch;
450 unsafe {copy(source_address.wrapping_add(src_offset), target_address.wrapping_add(dst_offset), src_stride)};
451 }
452 }
453 Ok(())
454 }
455
456 pub fn set_staging_data_from_image<P, Container>(&mut self, image: &ImageBuffer<P, Container>, z_layer: u32) -> Result<(), VulkanError>
458 where
459 P: Pixel,
460 Container: Deref<Target = [P::Subpixel]> {
461 let (width, height) = image.dimensions();
462 let extent = self.type_size.get_extent();
463 let layer_size = self.get_size()? as usize / extent.depth as usize;
464 let row_byte_count = size_of::<P>() * width as usize;
465 let image_size = row_byte_count * height as usize;
466 if width != extent.width || height != extent.height {
467 return Err(VulkanError::ImageTypeSizeNotMatch(format!("The size of the texture is {extent:?}, but the size of the image is {width}x_{height}. The size doesn't match.")));
468 }
469 if layer_size != image_size {
470 return Err(VulkanError::ImageTypeSizeNotMatch(format!("The layer size of the texture is {layer_size}, but the size of the image is {image_size}. The size doesn't match.")));
471 }
472 if z_layer >= extent.depth {
473 panic!("The given `z_layer` is {z_layer}, but the depth of the texture is {}, the `z_layer` is out of bound", extent.depth);
474 }
475 let layer_offset = z_layer as usize * image_size;
476 let image_address = image.as_ptr() as *const c_void;
477 let texture_pitch = layer_size / height as usize;
478 if row_byte_count == texture_pitch {
479 self.set_staging_data(image_address, layer_offset as u64, image_size)
480 } else {
481 unsafe {self.set_staging_data_from_compact_pixels(layer_offset, image_address, row_byte_count, height)}
482 }
483 }
484
485 pub fn upload_staging_buffer(&self, cmdbuf: VkCommandBuffer, offset: &VkOffset3D, extent: &VkExtent3D) -> Result<(), VulkanError> {
487 if let Some(ref staging_buffer) = self.staging_buffer {
488 let copy_region = VkBufferImageCopy {
489 bufferOffset: 0,
490 bufferRowLength: 0,
491 bufferImageHeight: 0,
492 imageSubresource: VkImageSubresourceLayers {
493 aspectMask: if self.is_depth_stencil() {
494 VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT as VkImageAspectFlags |
495 VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT as VkImageAspectFlags
496 } else {
497 VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags
498 },
499 mipLevel: 0,
500 baseArrayLayer: 0,
501 layerCount: 1,
502 },
503 imageOffset: *offset,
504 imageExtent: *extent,
505 };
506
507 self.device.vkcore.vkCmdCopyBufferToImage(cmdbuf, staging_buffer.get_vk_buffer(), self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region)?;
508 Ok(())
509 } else {
510 Err(VulkanError::NoStagingBuffer)
511 }
512 }
513
514 pub fn upload_staging_buffer_multi(&self, cmdbuf: VkCommandBuffer, regions: &[TextureRegion]) -> Result<(), VulkanError> {
516 if let Some(ref staging_buffer) = self.staging_buffer {
517 let copy_regions: Vec<VkBufferImageCopy> = regions.iter().map(|r| VkBufferImageCopy {
518 bufferOffset: 0,
519 bufferRowLength: 0,
520 bufferImageHeight: 0,
521 imageSubresource: VkImageSubresourceLayers {
522 aspectMask: if self.is_depth_stencil() {
523 VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT as VkImageAspectFlags |
524 VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT as VkImageAspectFlags
525 } else {
526 VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags
527 },
528 mipLevel: 0,
529 baseArrayLayer: 0,
530 layerCount: 1,
531 },
532 imageOffset: r.offset,
533 imageExtent: r.extent,
534 }).collect();
535
536 self.device.vkcore.vkCmdCopyBufferToImage(cmdbuf, staging_buffer.get_vk_buffer(), self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy_regions.len() as u32, copy_regions.as_ptr())?;
537 Ok(())
538 } else {
539 Err(VulkanError::NoStagingBuffer)
540 }
541 }
542
543 pub(crate) fn get_vk_image(&self) -> VkImage {
545 self.image
546 }
547
548 pub(crate) fn get_vk_image_view(&self) -> VkImageView {
550 self.image_view
551 }
552
553 pub fn get_type_size(&self) -> VulkanTextureType {
555 self.type_size
556 }
557
558 pub fn is_cube(&self) -> bool {
560 self.type_size.is_cube()
561 }
562
563 pub fn is_depth_stencil(&self) -> bool {
565 self.type_size.is_depth_stencil()
566 }
567
568 pub fn get_image_type(&self) -> VkImageType {
570 self.type_size.get_image_type()
571 }
572
573 pub fn get_extent(&self) -> VkExtent3D {
575 self.type_size.get_extent()
576 }
577
578 pub fn generate_mipmaps(&mut self, cmdbuf: VkCommandBuffer, filter: VkFilter) -> Result<(), VulkanError> {
580 let mut barrier = VkImageMemoryBarrier {
581 sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
582 pNext: null(),
583 srcAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags,
584 dstAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags,
585 oldLayout: VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
586 newLayout: VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
587 srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
588 dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
589 image: self.image,
590 subresourceRange: VkImageSubresourceRange {
591 aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
592 baseMipLevel: 0,
593 levelCount: 1,
594 baseArrayLayer: 0,
595 layerCount: 1,
596 },
597 };
598
599 let extent = self.type_size.get_extent();
600
601 let mut mip_width = extent.width;
602 let mut mip_height = extent.height;
603 let mut mip_depth = extent.depth;
604
605 for i in 1..self.mipmap_levels {
606 barrier.subresourceRange.baseMipLevel = i - 1;
607 barrier.oldLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
608 barrier.newLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
609 barrier.srcAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags;
610 barrier.dstAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags;
611
612 self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
613 VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
614 VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
615 0,
616 0, null(),
617 0, null(),
618 1, &barrier
619 )?;
620
621 let next_mip_width = max(mip_width / 2, 1);
622 let next_mip_height = max(mip_height / 2, 1);
623 let next_mip_depth = max(mip_depth / 2, 1);
624
625 let blit = VkImageBlit {
626 srcSubresource: VkImageSubresourceLayers {
627 aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
628 mipLevel: i - 1,
629 baseArrayLayer: 0,
630 layerCount: 1,
631 },
632 srcOffsets: [
633 VkOffset3D {
634 x: 0,
635 y: 0,
636 z: 0,
637 },
638 VkOffset3D {
639 x: mip_width as i32,
640 y: mip_height as i32,
641 z: mip_depth as i32,
642 },
643 ],
644 dstSubresource: VkImageSubresourceLayers {
645 aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
646 mipLevel: i,
647 baseArrayLayer: 0,
648 layerCount: 1,
649 },
650 dstOffsets: [
651 VkOffset3D {
652 x: 0,
653 y: 0,
654 z: 0,
655 },
656 VkOffset3D {
657 x: next_mip_width as i32,
658 y: next_mip_height as i32,
659 z: next_mip_depth as i32,
660 },
661 ],
662 };
663
664 self.device.vkcore.vkCmdBlitImage(cmdbuf,
665 self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
666 self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
667 1, &blit,
668 filter
669 )?;
670
671 barrier.oldLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
672 barrier.newLayout = VkImageLayout::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
673 barrier.srcAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags;
674 barrier.dstAccessMask = VkAccessFlagBits::VK_ACCESS_SHADER_READ_BIT as VkAccessFlags;
675
676 self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
677 VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
678 VkPipelineStageFlagBits::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT as VkPipelineStageFlags,
679 0,
680 0, null(),
681 0, null(),
682 1, &barrier
683 )?;
684
685 mip_width = next_mip_width;
686 mip_height = next_mip_height;
687 mip_depth = next_mip_depth;
688 }
689
690 barrier.subresourceRange.baseMipLevel = self.mipmap_levels - 1;
691 barrier.oldLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
692 barrier.newLayout = VkImageLayout::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
693 barrier.srcAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags;
694 barrier.dstAccessMask = VkAccessFlagBits::VK_ACCESS_SHADER_READ_BIT as VkAccessFlags;
695
696 self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
697 VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
698 VkPipelineStageFlagBits::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT as VkPipelineStageFlags,
699 0,
700 0, null(),
701 0, null(),
702 1, &barrier
703 )?;
704 Ok(())
705 }
706}
707
708unsafe impl Send for VulkanTexture {}
709unsafe impl Sync for VulkanTexture {}
710
711impl Debug for VulkanTexture {
712 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
713 f.debug_struct("VulkanTexture")
714 .field("image", &self.image)
715 .field("image_view", &self.image_view)
716 .field("type_size", &self.type_size)
717 .field("format", &self.format)
718 .field("memory", &self.memory)
719 .field("staging_buffer", &self.staging_buffer)
720 .finish()
721 }
722}
723
724impl Drop for VulkanTexture {
725 fn drop(&mut self) {
726 let vkcore = self.device.vkcore.clone();
727 let vkdevice = self.device.get_vk_device();
728 proceed_run(vkcore.vkDestroyImageView(vkdevice, self.image_view, null()));
729
730 if self.memory.is_some() {
732 proceed_run(vkcore.vkDestroyImage(vkdevice, self.image, null()));
733 }
734 }
735}