vkobject_rs/
texture.rs

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/// The offset and extent of a piece of the texture
19#[derive(Debug, Clone, Copy)]
20pub struct TextureRegion {
21	pub offset: VkOffset3D,
22	pub extent: VkExtent3D,
23}
24
25/// The texture type and size
26#[derive(Debug, Clone, Copy)]
27pub enum VulkanTextureType {
28	/// 1D texture
29	T1d(u32),
30
31	/// 2D texture
32	T2d(VkExtent2D),
33
34	/// 3D texture (a.k.a. volume texture)
35	T3d(VkExtent3D),
36
37	/// Cubemap texture with 6 faces
38	Cube(u32),
39
40	/// The texture dedicated for a depth stencil buffer
41	DepthStencil(VkExtent2D),
42}
43
44impl VulkanTextureType {
45	/// Get if the image is cubemap
46	pub fn is_cube(&self) -> bool {
47		matches!(self, Self::Cube(_))
48	}
49
50	/// Get if the image is depth stencil
51	pub fn is_depth_stencil(&self) -> bool {
52		matches!(self, Self::DepthStencil(_))
53	}
54
55	/// Get the `VkImageType`
56	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	/// Get the `VkExtent3D`
77	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
120/// The wrapper for the Vulkan texture images
121pub struct VulkanTexture {
122	/// The device holds all of the resource
123	pub device: Arc<VulkanDevice>,
124
125	/// The texture image
126	pub(crate) image: VkImage,
127
128	/// The image view
129	pub(crate) image_view: VkImageView,
130
131	/// The type and size of the texture
132	pub(crate) type_size: VulkanTextureType,
133
134	/// The format of the texture
135	pub(crate) format: VkFormat,
136
137	/// The memory holds the image data
138	pub(crate) memory: Option<VulkanMemory>,
139
140	/// The staging buffer for the texture
141	pub staging_buffer: Option<StagingBuffer>,
142
143	/// The mipmap levels
144	mipmap_levels: u32,
145}
146
147impl VulkanTexture {
148	/// Create the `VulkanTexture`
149	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	/// Create the `VulkanTexture` from a image that's not owned (e.g. from a swapchain image)
198	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	/// Create a texture from image right away
251	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	/// Get the size of the image
383	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	/// Get the pitch, the bytes per row of the texture
390	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	/// Get the mipmap levels
402	pub fn get_mipmap_levels(&self) -> u32 {
403		self.mipmap_levels
404	}
405
406	/// Create the staging buffer if it not exists
407	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	/// Get the data pointer of the staging buffer
415	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	/// Discard the staging buffer to save memory
421	pub fn discard_staging_buffer(&mut self) {
422		self.staging_buffer = None;
423	}
424
425	/// Update new data to the staging buffer
426	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	/// Copy image data from a compactly packed pixels to the 32-bit aligned staging buffer
433	///
434	/// # Safety
435	///
436	/// This function is unsafe due to these factors:
437	/// * The purpose of `offset` is for modifying each layer of the 3D texture, and is unchecked.
438	/// * The `src_stride` is unchecked. The caller calculates the stride.
439	/// * The `num_rows` is unchecked.
440	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	/// Update new data to the staging buffer from a `RgbImage`
457	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	/// Upload the staging buffer data to the texture
486	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, &copy_region)?;
508			Ok(())
509		} else {
510			Err(VulkanError::NoStagingBuffer)
511		}
512	}
513
514	/// Upload the staging buffer data to the texture
515	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	/// Get the `VkImage`
544	pub(crate) fn get_vk_image(&self) -> VkImage {
545		self.image
546	}
547
548	/// Get the `VkImageView`
549	pub(crate) fn get_vk_image_view(&self) -> VkImageView {
550		self.image_view
551	}
552
553	/// Get the type and size of the texture
554	pub fn get_type_size(&self) -> VulkanTextureType {
555		self.type_size
556	}
557
558	/// Get if the image is cubemap
559	pub fn is_cube(&self) -> bool {
560		self.type_size.is_cube()
561	}
562
563	/// Get if the image is depth stencil
564	pub fn is_depth_stencil(&self) -> bool {
565		self.type_size.is_depth_stencil()
566	}
567
568	/// Get the `VkImageType`
569	pub fn get_image_type(&self) -> VkImageType {
570		self.type_size.get_image_type()
571	}
572
573	/// Get the extent of the image
574	pub fn get_extent(&self) -> VkExtent3D {
575		self.type_size.get_extent()
576	}
577
578	/// Generate mipmaps for the texture
579	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		// Only destroy the image if it was owned by the struct.
731		if self.memory.is_some() {
732			proceed_run(vkcore.vkDestroyImage(vkdevice, self.image, null()));
733		}
734	}
735}