demo_vk/graphics/vulkan/swapchain/
mod.rs1mod settings;
2
3use {
4 crate::{
5 graphics::vulkan::{raii, VulkanContext},
6 trace,
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) = settings::create_swapchain(
43 &cxt,
44 framebuffer_size,
45 previous_swapchain,
46 )
47 .with_context(trace!("Unable to initialize swapchain!"))?;
48
49 let images =
50 unsafe { swapchain.ext.get_swapchain_images(swapchain.raw)? };
51 let mut image_views = vec![];
52 for (index, image) in images.iter().enumerate() {
53 let create_info = vk::ImageViewCreateInfo {
54 image: *image,
55 view_type: vk::ImageViewType::TYPE_2D,
56 format: format.format,
57 components: vk::ComponentMapping::default(),
58 subresource_range: vk::ImageSubresourceRange {
59 aspect_mask: vk::ImageAspectFlags::COLOR,
60 base_mip_level: 0,
61 level_count: 1,
62 base_array_layer: 0,
63 layer_count: 1,
64 },
65 ..Default::default()
66 };
67 let image_view = raii::ImageView::new(
68 format!("Swapchain Image [{}]", index),
69 cxt.device.clone(),
70 &create_info,
71 )?;
72 image_views.push(image_view);
73 }
74
75 Ok(Self {
76 swapchain,
77 extent,
78 format,
79 images,
80 image_views,
81 cxt,
82 })
83 }
84
85 pub fn raw(&self) -> vk::SwapchainKHR {
87 self.swapchain.raw
88 }
89
90 pub fn extent(&self) -> vk::Extent2D {
92 self.extent
93 }
94
95 pub fn scissor(&self) -> vk::Rect2D {
97 vk::Rect2D {
98 offset: vk::Offset2D { x: 0, y: 0 },
99 extent: self.extent,
100 }
101 }
102
103 pub fn viewport(&self) -> vk::Viewport {
104 vk::Viewport {
105 x: 0.0,
106 y: 0.0,
107 width: self.extent.width as f32,
108 height: self.extent.height as f32,
109 min_depth: 0.0,
110 max_depth: 1.0,
111 }
112 }
113
114 pub fn format(&self) -> vk::Format {
116 self.format.format
117 }
118
119 pub fn images(&self) -> &[vk::Image] {
121 &self.images
122 }
123
124 pub fn image_views(&self) -> &[raii::ImageView] {
128 &self.image_views
129 }
130
131 pub fn acquire_image(
137 &self,
138 image_ready_semaphore: vk::Semaphore,
139 ) -> Result<AcquireImageStatus> {
140 let result = unsafe {
141 self.swapchain.ext.acquire_next_image(
142 self.swapchain.raw,
143 u64::MAX,
144 image_ready_semaphore,
145 vk::Fence::null(),
146 )
147 };
148 match result {
149 Ok((index, false)) => Ok(AcquireImageStatus::ImageAcquired(index)),
150 Ok((_, true)) => {
151 Ok(AcquireImageStatus::SwapchainNeedsRebuild)
153 }
154 Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => {
155 Ok(AcquireImageStatus::SwapchainNeedsRebuild)
156 }
157 Err(err) => Err(anyhow!(err))
158 .with_context(trace!("Unable to acquire swapchain image!")),
159 }
160 }
161
162 pub fn present_image(
169 &self,
170 wait_semaphore: vk::Semaphore,
171 image_index: u32,
172 ) -> Result<PresentImageStatus> {
173 let present_info = vk::PresentInfoKHR {
174 wait_semaphore_count: 1,
175 p_wait_semaphores: &wait_semaphore,
176 swapchain_count: 1,
177 p_swapchains: &self.swapchain.raw,
178 p_image_indices: &image_index,
179 ..Default::default()
180 };
181 let result = unsafe {
182 self.swapchain
183 .ext
184 .queue_present(self.cxt.graphics_queue, &present_info)
185 };
186 match result {
187 Ok(false) => Ok(PresentImageStatus::Queued),
188 Ok(true) => Ok(PresentImageStatus::SwapchainNeedsRebuild),
189 Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => {
190 Ok(PresentImageStatus::SwapchainNeedsRebuild)
191 }
192 Err(err) => Err(err)
193 .with_context(trace!("Unable to present swapchain image!")),
194 }
195 }
196}
197
198impl std::fmt::Debug for Swapchain {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 f.debug_struct("Swapchain")
201 .field("swapchain", &self.swapchain)
202 .field("extent", &self.extent)
203 .field("format", &self.format)
204 .field("images", &self.images)
205 .field("image_views", &self.image_views)
206 .finish()
207 }
208}