vkobject_rs/
texture.rs

1
2use crate::prelude::*;
3use std::{
4	any::TypeId,
5	cmp::max,
6	ffi::{c_void, OsStr},
7	fmt::{self, Debug, Formatter},
8	fs::read,
9	io::Cursor,
10	mem::{MaybeUninit, size_of},
11	ops::Deref,
12	path::{Path, PathBuf},
13	ptr::null,
14	sync::{
15		Arc,
16		RwLock,
17		atomic::{AtomicBool, Ordering},
18	},
19};
20use image::{
21	ImageBuffer,
22	Pixel,
23};
24
25/// The offset and extent of a piece of the texture
26#[derive(Debug, Clone, Copy)]
27pub struct TextureRegion {
28	pub offset: VkOffset3D,
29	pub extent: VkExtent3D,
30}
31
32/// The texture type and size
33#[derive(Debug, Clone, Copy)]
34pub enum VulkanTextureType {
35	/// 1D texture
36	T1d(u32),
37
38	/// 2D texture
39	T2d(VkExtent2D),
40
41	/// 3D texture (a.k.a. volume texture)
42	T3d(VkExtent3D),
43
44	/// Cubemap texture with 6 faces
45	Cube(u32),
46
47	/// The texture dedicated for a depth stencil buffer
48	DepthStencil(VkExtent2D),
49}
50
51impl VulkanTextureType {
52	/// Get if the image is cubemap
53	pub fn is_cube(&self) -> bool {
54		matches!(self, Self::Cube(_))
55	}
56
57	/// Get if the image is depth stencil
58	pub fn is_depth_stencil(&self) -> bool {
59		matches!(self, Self::DepthStencil(_))
60	}
61
62	/// Get the `VkImageType`
63	pub fn get_image_type(&self) -> VkImageType {
64		match self {
65			Self::T1d(_) => {
66				VkImageType::VK_IMAGE_TYPE_1D
67			}
68			Self::T2d(_) => {
69				VkImageType::VK_IMAGE_TYPE_2D
70			}
71			Self::T3d(_) => {
72				VkImageType::VK_IMAGE_TYPE_3D
73			}
74			Self::Cube(_) => {
75				VkImageType::VK_IMAGE_TYPE_2D
76			}
77			Self::DepthStencil(_) => {
78				VkImageType::VK_IMAGE_TYPE_2D
79			}
80		}
81	}
82
83	/// Get the `VkExtent3D`
84	pub fn get_extent(&self) -> VkExtent3D {
85		match self {
86			Self::T1d(size) => {
87				VkExtent3D {
88					width: *size,
89					height: 1,
90					depth: 1,
91				}
92			}
93			Self::T2d(size) => {
94				VkExtent3D {
95					width: size.width,
96					height: size.height,
97					depth: 1,
98				}
99			}
100			Self::T3d(size) => {
101				VkExtent3D {
102					width: size.width,
103					height: size.height,
104					depth: size.depth,
105				}
106			}
107			Self::Cube(size) => {
108				VkExtent3D {
109					width: *size,
110					height: *size,
111					depth: 1,
112				}
113			}
114			Self::DepthStencil(size) => {
115				VkExtent3D {
116					width: size.width,
117					height: size.height,
118					depth: 1,
119				}
120			}
121		}
122	}
123}
124
125unsafe impl Send for VulkanTextureType {}
126
127/// The wrapper for the Vulkan texture images
128pub struct VulkanTexture {
129	/// The device holds all of the resource
130	pub device: Arc<VulkanDevice>,
131
132	/// The texture image
133	pub(crate) image: VkImage,
134
135	/// The image view
136	pub(crate) image_view: VkImageView,
137
138	/// The image format properties
139	pub image_format_props: Option<VkImageFormatProperties>,
140
141	/// The type and size of the texture
142	pub(crate) type_size: VulkanTextureType,
143
144	/// The format of the texture
145	pub(crate) format: VkFormat,
146
147	/// The memory holds the image data
148	pub(crate) memory: Option<VulkanMemory>,
149
150	/// The staging buffer for the texture
151	pub staging_buffer: RwLock<Option<StagingBuffer>>,
152
153	/// The mipmap levels
154	mipmap_levels: u32,
155
156	/// The mipmap filter
157	mipmap_filter: VkFilter,
158
159	/// Is this texture ready to sample by shaders?
160	ready_to_sample: AtomicBool,
161}
162
163impl VulkanTexture {
164	/// Create the `VulkanTexture`
165	pub fn new(device: Arc<VulkanDevice>, type_size: VulkanTextureType, with_mipmap: Option<VkFilter>, format: VkFormat, usage: VkImageUsageFlags) -> Result<Self, VulkanError> {
166		let vkcore = device.vkcore.clone();
167		let vkdevice = device.get_vk_device();
168		let vkphysicaldevice = device.get_vk_physical_device();
169		let extent = type_size.get_extent();
170		let dim = type_size.get_image_type();
171		let is_cube = type_size.is_cube();
172		let mipmap_levels = if with_mipmap.is_some() {
173			let mut levels = 0u32;
174			let mut size = max(max(extent.width, extent.height), extent.depth);
175			while size > 0 {
176				size >>= 1;
177				levels += 1;
178			}
179			levels
180		} else {
181			1
182		};
183		let image_ci = VkImageCreateInfo {
184			sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
185			pNext: null(),
186			flags: if is_cube {VkImageCreateFlagBits::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT as VkImageCreateFlags} else {0},
187			imageType: dim,
188			format,
189			extent,
190			mipLevels: mipmap_levels,
191			arrayLayers: 1,
192			samples: VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT,
193			tiling: VkImageTiling::VK_IMAGE_TILING_OPTIMAL,
194			usage: usage | VkImageUsageFlagBits::combine(&[
195				VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
196				VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_DST_BIT
197			]),
198			sharingMode: VkSharingMode::VK_SHARING_MODE_EXCLUSIVE,
199			queueFamilyIndexCount: 0,
200			pQueueFamilyIndices: null(),
201			initialLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
202		};
203		let mut image_format_props: VkImageFormatProperties = unsafe {MaybeUninit::zeroed().assume_init()};
204		vkcore.vkGetPhysicalDeviceImageFormatProperties(vkphysicaldevice, format, dim, image_ci.tiling, image_ci.usage, image_ci.flags, &mut image_format_props)?;
205		let mut image: VkImage = null();
206		vkcore.vkCreateImage(vkdevice, &image_ci, null(), &mut image)?;
207		let image = ResourceGuard::new(image, |&i|vkcore.clone().vkDestroyImage(vkdevice, i, null()).unwrap());
208		let mut mem_reqs: VkMemoryRequirements = unsafe {MaybeUninit::zeroed().assume_init()};
209		vkcore.vkGetImageMemoryRequirements(vkdevice, *image, &mut mem_reqs)?;
210		let memory = VulkanMemory::new(device.clone(), &mem_reqs, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT as u32)?;
211		memory.bind_vk_image(*image)?;
212		let mut ret = Self::new_from_existing_image(device, *image, type_size, mipmap_levels, format)?;
213		ret.memory = Some(memory);
214		ret.mipmap_filter = with_mipmap.unwrap_or(VkFilter::VK_FILTER_LINEAR);
215		image.release();
216		ret.image_format_props = Some(image_format_props);
217		Ok(ret)
218	}
219
220	/// Create the `VulkanTexture` from a image that's not owned (e.g. from a swapchain image)
221	pub(crate) fn new_from_existing_image(device: Arc<VulkanDevice>, image: VkImage, type_size: VulkanTextureType, mipmap_levels: u32, format: VkFormat) -> Result<Self, VulkanError> {
222		let vkcore = device.vkcore.clone();
223		let vkdevice = device.get_vk_device();
224		let image_view_ci = VkImageViewCreateInfo {
225			sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
226			pNext: null(),
227			flags: 0,
228			image,
229			viewType: if type_size.is_cube() {
230				VkImageViewType::VK_IMAGE_VIEW_TYPE_CUBE
231			} else {
232				match type_size.get_image_type() {
233					VkImageType::VK_IMAGE_TYPE_1D => VkImageViewType::VK_IMAGE_VIEW_TYPE_1D,
234					VkImageType::VK_IMAGE_TYPE_2D => VkImageViewType::VK_IMAGE_VIEW_TYPE_2D,
235					VkImageType::VK_IMAGE_TYPE_3D => VkImageViewType::VK_IMAGE_VIEW_TYPE_3D,
236					_ => panic!("Bad image type"),
237				}
238			},
239			format,
240			components: VkComponentMapping {
241				r: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
242				g: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
243				b: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
244				a: VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY,
245			},
246			subresourceRange: VkImageSubresourceRange {
247				aspectMask: if type_size.is_depth_stencil() {
248					VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT as VkImageAspectFlags |
249					VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT as VkImageAspectFlags
250				} else {
251					VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags
252				},
253				baseMipLevel: 0,
254				levelCount: mipmap_levels,
255				baseArrayLayer: 0,
256				layerCount: 1,
257			},
258		};
259		let mut image_view: VkImageView = null();
260		vkcore.vkCreateImageView(vkdevice, &image_view_ci, null(), &mut image_view)?;
261		Ok(Self {
262			device,
263			image,
264			image_view,
265			image_format_props: None,
266			type_size,
267			format,
268			memory: None,
269			staging_buffer: RwLock::new(None),
270			mipmap_levels,
271			mipmap_filter: VkFilter::VK_FILTER_LINEAR,
272			ready_to_sample: AtomicBool::new(false),
273		})
274	}
275
276	/// Create a texture from image right away
277	pub fn new_from_image<P, Container>(device: Arc<VulkanDevice>, cmdbuf: VkCommandBuffer, image: &ImageBuffer<P, Container>, channel_is_normalized: bool, with_mipmap: Option<VkFilter>, usage: VkImageUsageFlags) -> Result<Self, VulkanError>
278	where
279		P: Pixel,
280		Container: Deref<Target = [P::Subpixel]>,
281		<P as Pixel>::Subpixel: 'static {
282		let (width, height) = image.dimensions();
283		let extent = VkExtent2D {
284			width,
285			height,
286		};
287		let is_signed;
288		let is_float;
289		let bits;
290		if TypeId::of::<P::Subpixel>() == TypeId::of::<i8>() {
291			is_signed = true;
292			is_float = false;
293			bits = 8;
294		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<u8>() {
295			is_signed = false;
296			is_float = false;
297			bits = 8;
298		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<i16>() {
299			is_signed = true;
300			is_float = false;
301			bits = 16;
302		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<u16>() {
303			is_signed = false;
304			is_float = false;
305			bits = 16;
306		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<i32>() {
307			is_signed = true;
308			is_float = false;
309			bits = 32;
310		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<u32>() {
311			is_signed = false;
312			is_float = false;
313			bits = 32;
314		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<f32>() {
315			is_signed = true;
316			is_float = true;
317			bits = 32;
318		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<i64>() {
319			is_signed = true;
320			is_float = false;
321			bits = 64;
322		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<u64>() {
323			is_signed = false;
324			is_float = false;
325			bits = 64;
326		} else if TypeId::of::<P::Subpixel>() == TypeId::of::<f64>() {
327			is_signed = true;
328			is_float = true;
329			bits = 64;
330		} else {
331			return Err(VulkanError::ImagePixelFormatNotSupported);
332		}
333		let format = match (P::CHANNEL_COUNT, bits, is_signed, channel_is_normalized, is_float) {
334			(1, 8, true,  false, false) => VkFormat::VK_FORMAT_R8_SINT,
335			(1, 8, true,  true,  false) => VkFormat::VK_FORMAT_R8_SNORM,
336			(1, 8, false, false, false) => VkFormat::VK_FORMAT_R8_UINT,
337			(1, 8, false, true,  false) => VkFormat::VK_FORMAT_R8_UNORM,
338			(2, 8, true,  false, false) => VkFormat::VK_FORMAT_R8G8_SINT,
339			(2, 8, true,  true,  false) => VkFormat::VK_FORMAT_R8G8_SNORM,
340			(2, 8, false, false, false) => VkFormat::VK_FORMAT_R8G8_UINT,
341			(2, 8, false, true,  false) => VkFormat::VK_FORMAT_R8G8_UNORM,
342			(3, 8, true,  false, false) => VkFormat::VK_FORMAT_R8G8B8_SINT,
343			(3, 8, true,  true,  false) => VkFormat::VK_FORMAT_R8G8B8_SNORM,
344			(3, 8, false, false, false) => VkFormat::VK_FORMAT_R8G8B8_UINT,
345			(3, 8, false, true,  false) => VkFormat::VK_FORMAT_R8G8B8_UNORM,
346			(4, 8, true,  false, false) => VkFormat::VK_FORMAT_R8G8B8A8_SINT,
347			(4, 8, true,  true,  false) => VkFormat::VK_FORMAT_R8G8B8A8_SNORM,
348			(4, 8, false, false, false) => VkFormat::VK_FORMAT_R8G8B8A8_UINT,
349			(4, 8, false, true,  false) => VkFormat::VK_FORMAT_R8G8B8A8_UNORM,
350			(1, 16, true,  false, false) => VkFormat::VK_FORMAT_R16_SINT,
351			(1, 16, true,  true,  false) => VkFormat::VK_FORMAT_R16_SNORM,
352			(1, 16, false, false, false) => VkFormat::VK_FORMAT_R16_UINT,
353			(1, 16, false, true,  false) => VkFormat::VK_FORMAT_R16_UNORM,
354			(2, 16, true,  false, false) => VkFormat::VK_FORMAT_R16G16_SINT,
355			(2, 16, true,  true,  false) => VkFormat::VK_FORMAT_R16G16_SNORM,
356			(2, 16, false, false, false) => VkFormat::VK_FORMAT_R16G16_UINT,
357			(2, 16, false, true,  false) => VkFormat::VK_FORMAT_R16G16_UNORM,
358			(3, 16, true,  false, false) => VkFormat::VK_FORMAT_R16G16B16_SINT,
359			(3, 16, true,  true,  false) => VkFormat::VK_FORMAT_R16G16B16_SNORM,
360			(3, 16, false, false, false) => VkFormat::VK_FORMAT_R16G16B16_UINT,
361			(3, 16, false, true,  false) => VkFormat::VK_FORMAT_R16G16B16_UNORM,
362			(4, 16, true,  false, false) => VkFormat::VK_FORMAT_R16G16B16A16_SINT,
363			(4, 16, true,  true,  false) => VkFormat::VK_FORMAT_R16G16B16A16_SNORM,
364			(4, 16, false, false, false) => VkFormat::VK_FORMAT_R16G16B16A16_UINT,
365			(4, 16, false, true,  false) => VkFormat::VK_FORMAT_R16G16B16A16_UNORM,
366			(1, 32, true,  false, false) => VkFormat::VK_FORMAT_R32_SINT,
367			(1, 32, false, false, false) => VkFormat::VK_FORMAT_R32_UINT,
368			(2, 32, true,  false, false) => VkFormat::VK_FORMAT_R32G32_SINT,
369			(2, 32, false, false, false) => VkFormat::VK_FORMAT_R32G32_UINT,
370			(3, 32, true,  false, false) => VkFormat::VK_FORMAT_R32G32B32_SINT,
371			(3, 32, false, false, false) => VkFormat::VK_FORMAT_R32G32B32_UINT,
372			(4, 32, true,  false, false) => VkFormat::VK_FORMAT_R32G32B32A32_SINT,
373			(4, 32, false, false, false) => VkFormat::VK_FORMAT_R32G32B32A32_UINT,
374			(1, 64, true,  false, false) => VkFormat::VK_FORMAT_R64_SINT,
375			(1, 64, false, false, false) => VkFormat::VK_FORMAT_R64_UINT,
376			(2, 64, true,  false, false) => VkFormat::VK_FORMAT_R64G64_SINT,
377			(2, 64, false, false, false) => VkFormat::VK_FORMAT_R64G64_UINT,
378			(3, 64, true,  false, false) => VkFormat::VK_FORMAT_R64G64B64_SINT,
379			(3, 64, false, false, false) => VkFormat::VK_FORMAT_R64G64B64_UINT,
380			(4, 64, true,  false, false) => VkFormat::VK_FORMAT_R64G64B64A64_SINT,
381			(4, 64, false, false, false) => VkFormat::VK_FORMAT_R64G64B64A64_UINT,
382			(1, 32, true, _, true) => VkFormat::VK_FORMAT_R32_SFLOAT,
383			(2, 32, true, _, true) => VkFormat::VK_FORMAT_R32G32_SFLOAT,
384			(3, 32, true, _, true) => VkFormat::VK_FORMAT_R32G32B32_SFLOAT,
385			(4, 32, true, _, true) => VkFormat::VK_FORMAT_R32G32B32A32_SFLOAT,
386			(1, 64, true, _, true) => VkFormat::VK_FORMAT_R64_SFLOAT,
387			(2, 64, true, _, true) => VkFormat::VK_FORMAT_R64G64_SFLOAT,
388			(3, 64, true, _, true) => VkFormat::VK_FORMAT_R64G64B64_SFLOAT,
389			(4, 64, true, _, true) => VkFormat::VK_FORMAT_R64G64B64A64_SFLOAT,
390			_ => return Err(VulkanError::ImagePixelFormatNotSupported),
391		};
392		let ret = Self::new(device, VulkanTextureType::T2d(extent), with_mipmap, format, usage)?;
393		ret.set_staging_data(image.as_ptr() as *const c_void, 0, (bits / 8 * P::CHANNEL_COUNT) as usize * width as usize * height as usize)?;
394		let offset = VkOffset3D {
395			x: 0,
396			y: 0,
397			z: 0,
398		};
399		let update_extent = VkExtent3D {
400			width,
401			height,
402			depth: 1,
403		};
404		ret.upload_staging_buffer(cmdbuf, &offset, &update_extent)?;
405		Ok(ret)
406	}
407
408	/// Create a texture from image loaded from file path right away
409	pub fn new_from_path<P: AsRef<Path>>(device: Arc<VulkanDevice>, cmdbuf: VkCommandBuffer, path: P, channel_is_normalized: bool, with_mipmap: Option<VkFilter>, usage: VkImageUsageFlags) -> Result<Self, VulkanError> {
410		use image::imageops::flip_vertical;
411		let image_data = read(&path)?;
412		let pb = PathBuf::from(path.as_ref());
413		let image = if pb.extension().and_then(OsStr::to_str).map(|s| {let s = s.to_lowercase(); s != "jpg" && s != "jpeg"}).unwrap_or(true) {
414			use image::DynamicImage;
415			let img = image::ImageReader::new(Cursor::new(&image_data)).with_guessed_format()?.decode()?;
416			match img {
417				DynamicImage::ImageLuma8(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
418				DynamicImage::ImageLumaA8(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
419				DynamicImage::ImageLuma16(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
420				DynamicImage::ImageLumaA16(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
421				DynamicImage::ImageRgba8(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
422				DynamicImage::ImageRgba16(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
423				DynamicImage::ImageRgba32F(img) => Self::new_from_image(device, cmdbuf, &flip_vertical(&img), channel_is_normalized, with_mipmap, usage),
424				DynamicImage::ImageRgb8(img) => {
425					use image::{Rgba, RgbaImage};
426					let img = flip_vertical(&img);
427					let rgba_img: RgbaImage = ImageBuffer::from_fn(img.width(), img.height(), |x, y| {
428						let pixel = img.get_pixel(x, y);
429						Rgba([pixel[0], pixel[1], pixel[2], 255])
430					});
431					Self::new_from_image(device, cmdbuf, &rgba_img, channel_is_normalized, with_mipmap, usage)
432				}
433				DynamicImage::ImageRgb16(img) => {
434					use image::Rgba;
435					type Rgba16Image = ImageBuffer<Rgba<u16>, Vec<u16>>;
436					let img = flip_vertical(&img);
437					let rgba_img: Rgba16Image = ImageBuffer::from_fn(img.width(), img.height(), |x, y| {
438						let pixel = img.get_pixel(x, y);
439						Rgba([pixel[0], pixel[1], pixel[2], 65535])
440					});
441					Self::new_from_image(device, cmdbuf, &rgba_img, channel_is_normalized, with_mipmap, usage)
442				}
443				DynamicImage::ImageRgb32F(img) => {
444					use image::{Rgba, Rgba32FImage};
445					let img = flip_vertical(&img);
446					let rgba_img: Rgba32FImage = ImageBuffer::from_fn(img.width(), img.height(), |x, y| {
447						let pixel = img.get_pixel(x, y);
448						Rgba([pixel[0], pixel[1], pixel[2], 1.0])
449					});
450					Self::new_from_image(device, cmdbuf, &rgba_img, channel_is_normalized, with_mipmap, usage)
451				}
452				_ => Err(VulkanError::LoadImageFailed(format!("Unknown image type: {img:?}")))
453			}
454		} else {
455			use image::{Rgba, RgbaImage};
456			let img: image::RgbImage = flip_vertical(&turbojpeg::decompress_image(&image_data).unwrap());
457			let rgba_img: RgbaImage = ImageBuffer::from_fn(img.width(), img.height(), |x, y| {
458				let pixel = img.get_pixel(x, y);
459				Rgba([pixel[0], pixel[1], pixel[2], 255])
460			});
461			Self::new_from_image(device, cmdbuf, &rgba_img, channel_is_normalized, with_mipmap, usage)
462		}?;
463		Ok(image)
464	}
465
466	/// Get the size of the image
467	pub fn get_size(&self) -> Result<VkDeviceSize, VulkanError> {
468		let mut mem_reqs: VkMemoryRequirements = unsafe {MaybeUninit::zeroed().assume_init()};
469		self.device.vkcore.vkGetImageMemoryRequirements(self.device.get_vk_device(), self.image, &mut mem_reqs)?;
470		Ok(mem_reqs.size)
471	}
472
473	/// Get the mipmap levels
474	pub fn get_mipmap_levels(&self) -> u32 {
475		self.mipmap_levels
476	}
477
478	/// Create the staging buffer if it not exists
479	pub fn ensure_staging_buffer(&self) -> Result<(), VulkanError> {
480		let mut staging_buffer = self.staging_buffer.write().unwrap();
481		if staging_buffer.is_none() {
482			*staging_buffer = Some(StagingBuffer::new(self.device.clone(), self.get_size()?)?);
483		}
484		Ok(())
485	}
486
487	/// Get the data pointer of the staging buffer
488	pub fn get_staging_buffer_address(&self) -> Result<*mut c_void, VulkanError> {
489		self.ensure_staging_buffer()?;
490		Ok(self.staging_buffer.read().unwrap().as_ref().unwrap().address)
491	}
492
493	/// Discard the staging buffer to save memory
494	pub fn discard_staging_buffer(&self) {
495		let mut staging_buffer = self.staging_buffer.write().unwrap();
496		*staging_buffer = None;
497	}
498
499	/// Update new data to the staging buffer
500	pub fn set_staging_data(&self, data: *const c_void, offset: VkDeviceSize, size: usize) -> Result<(), VulkanError> {
501		self.ensure_staging_buffer()?;
502		self.staging_buffer.write().unwrap().as_mut().unwrap().set_data(data, offset, size)?;
503		Ok(())
504	}
505
506	/// Update new data to the staging buffer from a `RgbImage`
507	pub fn set_staging_data_from_image<P, Container>(&self, image: &ImageBuffer<P, Container>, z_layer: u32) -> Result<(), VulkanError>
508	where
509		P: Pixel,
510		Container: Deref<Target = [P::Subpixel]> {
511		let (width, height) = image.dimensions();
512		let extent = self.type_size.get_extent();
513		let row_byte_count = size_of::<P>() * width as usize;
514		let image_size = row_byte_count * height as usize;
515		if width != extent.width || height != extent.height {
516			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.")));
517		}
518		if z_layer >= extent.depth {
519			panic!("The given `z_layer` is {z_layer}, but the depth of the texture is {}, the `z_layer` is out of bound", extent.depth);
520		}
521		let layer_offset = z_layer as usize * image_size;
522		let image_address = image.as_ptr() as *const c_void;
523		self.set_staging_data(image_address, layer_offset as u64, image_size)
524	}
525
526	/// Upload the staging buffer data to the texture
527	pub fn upload_staging_buffer(&self, cmdbuf: VkCommandBuffer, offset: &VkOffset3D, extent: &VkExtent3D) -> Result<(), VulkanError> {
528		let staging_buffer_lock = self.staging_buffer.read().unwrap();
529		if let Some(ref staging_buffer) = *staging_buffer_lock {
530			let barrier = VkImageMemoryBarrier {
531				sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
532				pNext: null(),
533				srcAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags,
534				dstAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags,
535				oldLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
536				newLayout: VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
537				srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
538				dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
539				image: self.image,
540				subresourceRange: VkImageSubresourceRange {
541					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
542					baseMipLevel: 0,
543					levelCount: 1,
544					baseArrayLayer: 0,
545					layerCount: 1,
546				},
547			};
548
549			self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
550				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
551				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
552				0,
553				0, null(),
554				0, null(),
555				1, &barrier
556			)?;
557
558			self.ready_to_sample.store(false, Ordering::Relaxed);
559
560			let copy_region = VkBufferImageCopy {
561				bufferOffset: 0,
562				bufferRowLength: 0,
563				bufferImageHeight: 0,
564				imageSubresource: VkImageSubresourceLayers {
565					aspectMask: if self.is_depth_stencil() {
566						VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT as VkImageAspectFlags |
567						VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT as VkImageAspectFlags
568					} else {
569						VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags
570					},
571					mipLevel: 0,
572					baseArrayLayer: 0,
573					layerCount: 1,
574				},
575				imageOffset: *offset,
576				imageExtent: *extent,
577			};
578
579			self.device.vkcore.vkCmdCopyBufferToImage(cmdbuf, staging_buffer.get_vk_buffer(), self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region)?;
580			if self.mipmap_levels > 1 {
581				self.generate_mipmaps(cmdbuf)?;
582			}
583			Ok(())
584		} else {
585			Err(VulkanError::NoStagingBuffer)
586		}
587	}
588
589	/// Upload the staging buffer data to the texture
590	pub fn upload_staging_buffer_multi(&self, cmdbuf: VkCommandBuffer, regions: &[TextureRegion]) -> Result<(), VulkanError> {
591		let staging_buffer_lock = self.staging_buffer.read().unwrap();
592		if let Some(ref staging_buffer) = *staging_buffer_lock {
593			let barrier = VkImageMemoryBarrier {
594				sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
595				pNext: null(),
596				srcAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags,
597				dstAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags,
598				oldLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
599				newLayout: VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
600				srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
601				dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
602				image: self.image,
603				subresourceRange: VkImageSubresourceRange {
604					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
605					baseMipLevel: 0,
606					levelCount: 1,
607					baseArrayLayer: 0,
608					layerCount: 1,
609				},
610			};
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			self.ready_to_sample.store(false, Ordering::Relaxed);
622
623			let copy_regions: Vec<VkBufferImageCopy> = regions.iter().map(|r| VkBufferImageCopy {
624				bufferOffset: 0,
625				bufferRowLength: 0,
626				bufferImageHeight: 0,
627				imageSubresource: VkImageSubresourceLayers {
628					aspectMask: if self.is_depth_stencil() {
629						VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT as VkImageAspectFlags |
630						VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT as VkImageAspectFlags
631					} else {
632						VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags
633					},
634					mipLevel: 0,
635					baseArrayLayer: 0,
636					layerCount: 1,
637				},
638				imageOffset: r.offset,
639				imageExtent: r.extent,
640			}).collect();
641
642			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())?;
643			if self.mipmap_levels > 1 {
644				self.generate_mipmaps(cmdbuf)?;
645			}
646			Ok(())
647		} else {
648			Err(VulkanError::NoStagingBuffer)
649		}
650	}
651
652	/// Get the `VkImage`
653	pub(crate) fn get_vk_image(&self) -> VkImage {
654		self.image
655	}
656
657	/// Get the `VkImageView`
658	pub(crate) fn get_vk_image_view(&self) -> VkImageView {
659		self.image_view
660	}
661
662	/// Get the type and size of the texture
663	pub fn get_type_size(&self) -> VulkanTextureType {
664		self.type_size
665	}
666
667	/// Get if the image is cubemap
668	pub fn is_cube(&self) -> bool {
669		self.type_size.is_cube()
670	}
671
672	/// Get if the image is depth stencil
673	pub fn is_depth_stencil(&self) -> bool {
674		self.type_size.is_depth_stencil()
675	}
676
677	/// Get the `VkImageType`
678	pub fn get_image_type(&self) -> VkImageType {
679		self.type_size.get_image_type()
680	}
681
682	/// Get the extent of the image
683	pub fn get_extent(&self) -> VkExtent3D {
684		self.type_size.get_extent()
685	}
686
687	/// Generate mipmaps for the texture
688	pub fn generate_mipmaps(&self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
689		let extent = self.type_size.get_extent();
690
691		let mut mip_width = extent.width;
692		let mut mip_height = extent.height;
693		let mut mip_depth = extent.depth;
694
695		for i in 1..self.mipmap_levels {
696			let barrier_base = VkImageMemoryBarrier {
697				sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
698				pNext: null(),
699				srcAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags,
700				dstAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags,
701				oldLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
702				newLayout: VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
703				srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
704				dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
705				image: self.image,
706				subresourceRange: VkImageSubresourceRange {
707					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
708					baseMipLevel: i - 1,
709					levelCount: 1,
710					baseArrayLayer: 0,
711					layerCount: 1,
712				},
713			};
714
715			let barrier_curr = VkImageMemoryBarrier {
716				sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
717				pNext: null(),
718				srcAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT as VkAccessFlags,
719				dstAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags,
720				oldLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
721				newLayout: VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
722				srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
723				dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
724				image: self.image,
725				subresourceRange: VkImageSubresourceRange {
726					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
727					baseMipLevel: i,
728					levelCount: 1,
729					baseArrayLayer: 0,
730					layerCount: 1,
731				},
732			};
733
734			self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
735				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
736				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
737				0,
738				0, null(),
739				0, null(),
740				1, &barrier_base
741			)?;
742
743			self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
744				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
745				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
746				0,
747				0, null(),
748				0, null(),
749				1, &barrier_curr
750			)?;
751
752			let next_mip_width = max(mip_width / 2, 1);
753			let next_mip_height = max(mip_height / 2, 1);
754			let next_mip_depth = max(mip_depth / 2, 1);
755
756			let blit = VkImageBlit {
757				srcSubresource: VkImageSubresourceLayers {
758					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
759					mipLevel: i - 1,
760					baseArrayLayer: 0,
761					layerCount: 1,
762				},
763				srcOffsets: [
764					VkOffset3D {
765						x: 0,
766						y: 0,
767						z: 0,
768					},
769					VkOffset3D {
770						x: mip_width as i32,
771						y: mip_height as i32,
772						z: mip_depth as i32,
773					},
774				],
775				dstSubresource: VkImageSubresourceLayers {
776					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
777					mipLevel: i,
778					baseArrayLayer: 0,
779					layerCount: 1,
780				},
781				dstOffsets: [
782					VkOffset3D {
783						x: 0,
784						y: 0,
785						z: 0,
786					},
787					VkOffset3D {
788						x: next_mip_width as i32,
789						y: next_mip_height as i32,
790						z: next_mip_depth as i32,
791					},
792				],
793			};
794
795			self.device.vkcore.vkCmdBlitImage(cmdbuf,
796				self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
797				self.image, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
798				1, &blit,
799				self.mipmap_filter
800			)?;
801
802			mip_width = next_mip_width;
803			mip_height = next_mip_height;
804			mip_depth = next_mip_depth;
805		}
806
807		self.ready_to_sample.store(false, Ordering::Relaxed);
808		Ok(())
809	}
810
811	/// Make this texture ready to be sampled by shaders
812	pub fn prepare_for_sample(&self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
813		if !self.ready_to_sample.load(Ordering::Relaxed) {
814			let barrier = VkImageMemoryBarrier {
815				sType: VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
816				pNext: null(),
817				srcAccessMask: VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT as VkAccessFlags,
818				dstAccessMask: VkAccessFlagBits::VK_ACCESS_SHADER_READ_BIT as VkAccessFlags,
819				oldLayout: VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,
820				newLayout: VkImageLayout::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
821				srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
822				dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED,
823				image: self.image,
824				subresourceRange: VkImageSubresourceRange {
825					aspectMask: VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT as VkImageAspectFlags,
826					baseMipLevel: 0,
827					levelCount: self.mipmap_levels,
828					baseArrayLayer: 0,
829					layerCount: 1,
830				},
831			};
832
833			self.device.vkcore.vkCmdPipelineBarrier(cmdbuf,
834				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT as VkPipelineStageFlags,
835				VkPipelineStageFlagBits::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT as VkPipelineStageFlags,
836				0,
837				0, null(),
838				0, null(),
839				1, &barrier
840			)?;
841			self.ready_to_sample.store(true, Ordering::Relaxed);
842		}
843		Ok(())
844	}
845}
846
847unsafe impl Send for VulkanTexture {}
848unsafe impl Sync for VulkanTexture {}
849
850impl Debug for VulkanTexture {
851	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
852		f.debug_struct("VulkanTexture")
853		.field("image", &self.image)
854		.field("image_view", &self.image_view)
855		.field("image_format_props", &self.image_format_props)
856		.field("type_size", &self.type_size)
857		.field("format", &self.format)
858		.field("memory", &self.memory)
859		.field("staging_buffer", &self.staging_buffer)
860		.field("mipmap_levels", &self.mipmap_levels)
861		.field("mipmap_filter", &self.mipmap_filter)
862		.field("ready_to_sample", &self.ready_to_sample)
863		.finish()
864	}
865}
866
867impl Drop for VulkanTexture {
868	fn drop(&mut self) {
869		let vkcore = self.device.vkcore.clone();
870		let vkdevice = self.device.get_vk_device();
871		proceed_run(vkcore.vkDestroyImageView(vkdevice, self.image_view, null()));
872
873		// Only destroy the image if it was owned by the struct.
874		if self.memory.is_some() {
875			proceed_run(vkcore.vkDestroyImage(vkdevice, self.image, null()));
876		}
877	}
878}