demo_vk/graphics/vulkan/swapchain/
mod.rs1mod settings;
2
3use {
4 crate::{
5 graphics::vulkan::{raii, VulkanContext},
6 unwrap_here,
7 },
8 anyhow::{anyhow, Context, Result},
9 ash::vk,
10 std::sync::Arc,
11};
12
13#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
14pub enum AcquireImageStatus {
15 ImageAcquired(u32),
16 SwapchainNeedsRebuild,
17}
18
19#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
20pub enum PresentImageStatus {
21 Queued,
22 SwapchainNeedsRebuild,
23}
24
25pub struct Swapchain {
27 swapchain: Arc<raii::Swapchain>,
28 extent: vk::Extent2D,
29 format: vk::SurfaceFormatKHR,
30 images: Vec<vk::Image>,
31 image_views: Vec<raii::ImageView>,
32 cxt: Arc<VulkanContext>,
33}
34
35impl Swapchain {
36 pub fn new(
38 cxt: Arc<VulkanContext>,
39 framebuffer_size: (u32, u32),
40 previous_swapchain: Option<vk::SwapchainKHR>,
41 ) -> Result<Self> {
42 let (swapchain, extent, format) = unwrap_here!(
43 "Create swapchain",
44 settings::create_swapchain(
45 &cxt,
46 framebuffer_size,
47 previous_swapchain,
48 )
49 );
50
51 let images = unwrap_here!("Get swapchain images", unsafe {
52 swapchain.ext.get_swapchain_images(swapchain.raw)
53 });
54 let mut image_views = vec![];
55 for (index, image) in images.iter().enumerate() {
56 let create_info = vk::ImageViewCreateInfo {
57 image: *image,
58 view_type: vk::ImageViewType::TYPE_2D,
59 format: format.format,
60 components: vk::ComponentMapping::default(),
61 subresource_range: vk::ImageSubresourceRange {
62 aspect_mask: vk::ImageAspectFlags::COLOR,
63 base_mip_level: 0,
64 level_count: 1,
65 base_array_layer: 0,
66 layer_count: 1,
67 },
68 ..Default::default()
69 };
70 let image_view = unwrap_here!(
71 format!("Create swapchain image view [{}]", index),
72 raii::ImageView::new(
73 format!("Swapchain Image [{}]", index),
74 cxt.device.clone(),
75 &create_info,
76 )
77 );
78 image_views.push(image_view);
79 }
80
81 Ok(Self {
82 swapchain,
83 extent,
84 format,
85 images,
86 image_views,
87 cxt,
88 })
89 }
90
91 pub fn raw(&self) -> vk::SwapchainKHR {
93 self.swapchain.raw
94 }
95
96 pub fn extent(&self) -> vk::Extent2D {
98 self.extent
99 }
100
101 pub fn scissor(&self) -> vk::Rect2D {
103 vk::Rect2D {
104 offset: vk::Offset2D { x: 0, y: 0 },
105 extent: self.extent,
106 }
107 }
108
109 pub fn viewport(&self) -> vk::Viewport {
110 vk::Viewport {
111 x: 0.0,
112 y: 0.0,
113 width: self.extent.width as f32,
114 height: self.extent.height as f32,
115 min_depth: 0.0,
116 max_depth: 1.0,
117 }
118 }
119
120 pub fn format(&self) -> vk::Format {
122 self.format.format
123 }
124
125 pub fn images(&self) -> &[vk::Image] {
127 &self.images
128 }
129
130 pub fn image_views(&self) -> &[raii::ImageView] {
134 &self.image_views
135 }
136
137 pub fn acquire_image(
143 &self,
144 image_ready_semaphore: vk::Semaphore,
145 ) -> Result<AcquireImageStatus> {
146 let result = unsafe {
147 self.swapchain.ext.acquire_next_image(
148 self.swapchain.raw,
149 u64::MAX,
150 image_ready_semaphore,
151 vk::Fence::null(),
152 )
153 };
154 match result {
155 Ok((index, false)) => Ok(AcquireImageStatus::ImageAcquired(index)),
156 Ok((_, true)) => {
157 Ok(AcquireImageStatus::SwapchainNeedsRebuild)
159 }
160 Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => {
161 Ok(AcquireImageStatus::SwapchainNeedsRebuild)
162 }
163 Err(err) => {
164 Err(anyhow!(err)).context("Unable to acquire swapchain image!")
165 }
166 }
167 }
168
169 pub fn present_image(
176 &self,
177 wait_semaphore: vk::Semaphore,
178 image_index: u32,
179 ) -> Result<PresentImageStatus> {
180 let present_info = vk::PresentInfoKHR {
181 wait_semaphore_count: 1,
182 p_wait_semaphores: &wait_semaphore,
183 swapchain_count: 1,
184 p_swapchains: &self.swapchain.raw,
185 p_image_indices: &image_index,
186 ..Default::default()
187 };
188 let result = unsafe {
189 self.swapchain
190 .ext
191 .queue_present(self.cxt.graphics_queue, &present_info)
192 };
193 match result {
194 Ok(false) => Ok(PresentImageStatus::Queued),
195 Ok(true) => Ok(PresentImageStatus::SwapchainNeedsRebuild),
196 Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => {
197 Ok(PresentImageStatus::SwapchainNeedsRebuild)
198 }
199 Err(err) => Err(err).context("Unable to present swapchain image!"),
200 }
201 }
202}
203
204impl std::fmt::Debug for Swapchain {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 f.debug_struct("Swapchain")
207 .field("swapchain", &self.swapchain)
208 .field("extent", &self.extent)
209 .field("format", &self.format)
210 .field("images", &self.images)
211 .field("image_views", &self.image_views)
212 .finish()
213 }
214}