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#[derive(Debug, Clone, Copy)]
27pub struct TextureRegion {
28 pub offset: VkOffset3D,
29 pub extent: VkExtent3D,
30}
31
32#[derive(Debug, Clone, Copy)]
34pub enum VulkanTextureType {
35 T1d(u32),
37
38 T2d(VkExtent2D),
40
41 T3d(VkExtent3D),
43
44 Cube(u32),
46
47 DepthStencil(VkExtent2D),
49}
50
51impl VulkanTextureType {
52 pub fn is_cube(&self) -> bool {
54 matches!(self, Self::Cube(_))
55 }
56
57 pub fn is_depth_stencil(&self) -> bool {
59 matches!(self, Self::DepthStencil(_))
60 }
61
62 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 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
127pub struct VulkanTexture {
129 pub device: Arc<VulkanDevice>,
131
132 pub(crate) image: VkImage,
134
135 pub(crate) image_view: VkImageView,
137
138 pub image_format_props: Option<VkImageFormatProperties>,
140
141 pub(crate) type_size: VulkanTextureType,
143
144 pub(crate) format: VkFormat,
146
147 pub(crate) memory: Option<VulkanMemory>,
149
150 pub staging_buffer: RwLock<Option<StagingBuffer>>,
152
153 mipmap_levels: u32,
155
156 mipmap_filter: VkFilter,
158
159 ready_to_sample: AtomicBool,
161}
162
163impl VulkanTexture {
164 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 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 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 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 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 pub fn get_mipmap_levels(&self) -> u32 {
475 self.mipmap_levels
476 }
477
478 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 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 pub fn discard_staging_buffer(&self) {
495 let mut staging_buffer = self.staging_buffer.write().unwrap();
496 *staging_buffer = None;
497 }
498
499 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 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 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, ©_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 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 pub(crate) fn get_vk_image(&self) -> VkImage {
654 self.image
655 }
656
657 pub(crate) fn get_vk_image_view(&self) -> VkImageView {
659 self.image_view
660 }
661
662 pub fn get_type_size(&self) -> VulkanTextureType {
664 self.type_size
665 }
666
667 pub fn is_cube(&self) -> bool {
669 self.type_size.is_cube()
670 }
671
672 pub fn is_depth_stencil(&self) -> bool {
674 self.type_size.is_depth_stencil()
675 }
676
677 pub fn get_image_type(&self) -> VkImageType {
679 self.type_size.get_image_type()
680 }
681
682 pub fn get_extent(&self) -> VkExtent3D {
684 self.type_size.get_extent()
685 }
686
687 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 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 if self.memory.is_some() {
875 proceed_run(vkcore.vkDestroyImage(vkdevice, self.image, null()));
876 }
877 }
878}