You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.4KB

  1. use crate::render::{
  2. Conf, Device, OwnedImage, PhysicalDevice, Queue, Surface,
  3. };
  4. use ash::vk;
  5. use std::rc::Rc;
  6. pub struct Swapchain {
  7. handle: vk::SwapchainKHR,
  8. pub device: Rc<Device>,
  9. pub surface: Rc<Surface>,
  10. pub format: vk::Format,
  11. pub extent: vk::Extent2D,
  12. }
  13. impl Swapchain {
  14. pub fn create(
  15. device: Rc<Device>,
  16. phys_device: &PhysicalDevice,
  17. surface: Rc<Surface>,
  18. conf: &Conf,
  19. queue_graphics: &Queue,
  20. queue_surface: &Queue,
  21. ) -> Result<Rc<Self>, vk::Result> {
  22. let capabilities = unsafe {
  23. device.instance.surface_ext.get_physical_device_surface_capabilities(
  24. **phys_device,
  25. **surface,
  26. )?
  27. };
  28. let formats = unsafe {
  29. device
  30. .instance
  31. .surface_ext
  32. .get_physical_device_surface_formats(**phys_device, **surface)?
  33. };
  34. let modes = unsafe {
  35. device.instance.surface_ext.get_physical_device_surface_present_modes(
  36. **phys_device,
  37. **surface,
  38. )?
  39. };
  40. let extent = if capabilities.current_extent.width != u32::max_value() {
  41. capabilities.current_extent
  42. } else {
  43. vk::Extent2D {
  44. width: capabilities
  45. .min_image_extent
  46. .width
  47. .max(capabilities.max_image_extent.width),
  48. height: capabilities
  49. .min_image_extent
  50. .height
  51. .max(capabilities.max_image_extent.height),
  52. }
  53. };
  54. let format = *formats
  55. .iter()
  56. .find(|format| {
  57. format.format == vk::Format::B8G8R8A8_UNORM &&
  58. format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
  59. })
  60. .unwrap_or_else(|| &formats[0]);
  61. let mode = *modes
  62. .iter()
  63. .find(|&&mode| mode == conf.swap_mode.into())
  64. .unwrap_or_else(|| &vk::PresentModeKHR::FIFO);
  65. let min_image_count = capabilities.min_image_count + 1;
  66. let min_image_count =
  67. if capabilities.max_image_count > 0 &&
  68. min_image_count > capabilities.max_image_count
  69. {
  70. capabilities.max_image_count
  71. } else {
  72. min_image_count
  73. };
  74. let queue_family_indices = [queue_graphics.index, queue_surface.index];
  75. let create_info = vk::SwapchainCreateInfoKHR {
  76. min_image_count,
  77. present_mode: mode,
  78. image_extent: extent,
  79. surface: **surface,
  80. image_format: format.format,
  81. image_color_space: format.color_space,
  82. image_array_layers: 1,
  83. image_usage: vk::ImageUsageFlags::COLOR_ATTACHMENT,
  84. image_sharing_mode: if queue_graphics.index != queue_surface.index {
  85. vk::SharingMode::CONCURRENT
  86. } else {
  87. vk::SharingMode::EXCLUSIVE
  88. },
  89. queue_family_index_count: queue_family_indices.len() as u32,
  90. p_queue_family_indices: queue_family_indices.as_ptr(),
  91. pre_transform: capabilities.current_transform,
  92. composite_alpha: vk::CompositeAlphaFlagsKHR::OPAQUE,
  93. clipped: vk::TRUE,
  94. ..Default::default()
  95. };
  96. let handle =
  97. unsafe { device.swapchain_ext.create_swapchain(&create_info, None)? };
  98. Ok(Rc::new(Self {
  99. handle,
  100. device,
  101. surface,
  102. extent,
  103. format: format.format,
  104. }))
  105. }
  106. pub fn get_images(
  107. this: Rc<Self>,
  108. ) -> Result<Vec<Rc<OwnedImage>>, vk::Result> {
  109. let images = unsafe {
  110. this.device.swapchain_ext.get_swapchain_images(this.handle)?
  111. };
  112. Ok(images
  113. .iter()
  114. .map(|&image| OwnedImage::own(this.clone(), image))
  115. .collect())
  116. }
  117. }
  118. impl Drop for Swapchain {
  119. fn drop(&mut self) {
  120. unsafe {
  121. self.device.swapchain_ext.destroy_swapchain(self.handle, None);
  122. }
  123. }
  124. }
  125. impl std::ops::Deref for Swapchain {
  126. type Target = vk::SwapchainKHR;
  127. fn deref(&self) -> &Self::Target {
  128. &self.handle
  129. }
  130. }
  131. // EOF