1use crate::{context::VulkanoContext, window::WindowDescriptor};
2use foldhash::HashMap;
3use std::{sync::Arc, time::Duration};
4use vulkano::{
5 device::{Device, Queue},
6 format::Format,
7 image::{view::ImageView, Image, ImageCreateInfo, ImageType, ImageUsage},
8 memory::allocator::{AllocationCreateInfo, StandardMemoryAllocator},
9 swapchain::{self, PresentMode, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo},
10 sync::{self, GpuFuture},
11 Validated, VulkanError,
12};
13use winit::window::Window;
14
15pub const DEFAULT_IMAGE_FORMAT: Format = Format::R8G8B8A8_UNORM;
17
18pub struct VulkanoWindowRenderer {
26 window: Arc<Window>,
27 graphics_queue: Arc<Queue>,
28 compute_queue: Arc<Queue>,
29 swapchain: Arc<Swapchain>,
30 final_views: Vec<Arc<ImageView>>,
31 memory_allocator: Arc<StandardMemoryAllocator>,
32 additional_image_views: HashMap<usize, Arc<ImageView>>,
35 recreate_swapchain: bool,
36 previous_frame_end: Option<Box<dyn GpuFuture>>,
37 image_index: u32,
38 present_mode: PresentMode,
39}
40
41impl VulkanoWindowRenderer {
42 pub fn new(
46 vulkano_context: &VulkanoContext,
47 window: Window,
48 descriptor: &WindowDescriptor,
49 swapchain_create_info_modify: fn(&mut SwapchainCreateInfo),
50 ) -> VulkanoWindowRenderer {
51 let window = Arc::new(window);
52
53 let (swap_chain, final_views) = Self::create_swapchain(
55 vulkano_context.device().clone(),
56 &window,
57 descriptor,
58 swapchain_create_info_modify,
59 );
60
61 let previous_frame_end = Some(sync::now(vulkano_context.device().clone()).boxed());
62
63 VulkanoWindowRenderer {
64 window,
65 graphics_queue: vulkano_context.graphics_queue().clone(),
66 compute_queue: vulkano_context.compute_queue().clone(),
67 swapchain: swap_chain,
68 final_views,
69 memory_allocator: vulkano_context.memory_allocator().clone(),
70 additional_image_views: HashMap::default(),
71 recreate_swapchain: false,
72 previous_frame_end,
73 image_index: 0,
74 present_mode: descriptor.present_mode,
75 }
76 }
77
78 fn create_swapchain(
81 device: Arc<Device>,
82 window: &Arc<Window>,
83 window_descriptor: &WindowDescriptor,
84 swapchain_create_info_modify: fn(&mut SwapchainCreateInfo),
85 ) -> (Arc<Swapchain>, Vec<Arc<ImageView>>) {
86 let surface = Surface::from_window(device.instance().clone(), window.clone()).unwrap();
87 let surface_capabilities = device
88 .physical_device()
89 .surface_capabilities(&surface, Default::default())
90 .unwrap();
91 let image_format = device
92 .physical_device()
93 .surface_formats(&surface, Default::default())
94 .unwrap()[0]
95 .0;
96 let (swapchain, images) = Swapchain::new(device, surface, {
97 let mut create_info = SwapchainCreateInfo {
98 min_image_count: surface_capabilities.min_image_count.max(2),
99 image_format,
100 image_extent: window.inner_size().into(),
101 image_usage: ImageUsage::COLOR_ATTACHMENT,
102 composite_alpha: surface_capabilities
103 .supported_composite_alpha
104 .into_iter()
105 .next()
106 .unwrap(),
107 ..Default::default()
108 };
109 create_info.present_mode = window_descriptor.present_mode;
111 swapchain_create_info_modify(&mut create_info);
112 create_info
113 })
114 .unwrap();
115 let images = images
116 .into_iter()
117 .map(|image| ImageView::new_default(image).unwrap())
118 .collect::<Vec<_>>();
119
120 (swapchain, images)
121 }
122
123 #[inline]
125 pub fn set_present_mode(&mut self, present_mode: PresentMode) {
126 if self.present_mode != present_mode {
127 self.present_mode = present_mode;
128 self.recreate_swapchain = true;
129 }
130 }
131
132 #[inline]
134 pub fn swapchain_format(&self) -> Format {
135 self.final_views[self.image_index as usize].format()
136 }
137
138 #[inline]
140 pub fn image_index(&self) -> u32 {
141 self.image_index
142 }
143
144 #[inline]
146 pub fn graphics_queue(&self) -> Arc<Queue> {
147 self.graphics_queue.clone()
148 }
149
150 #[inline]
152 pub fn compute_queue(&self) -> Arc<Queue> {
153 self.compute_queue.clone()
154 }
155
156 #[inline]
158 pub fn surface(&self) -> Arc<Surface> {
159 self.swapchain.surface().clone()
160 }
161
162 #[inline]
164 pub fn window(&self) -> &Window {
165 &self.window
166 }
167
168 #[inline]
170 pub fn window_size(&self) -> [f32; 2] {
171 let size = self.window().inner_size();
172 [size.width as f32, size.height as f32]
173 }
174
175 #[inline]
177 pub fn swapchain_image_size(&self) -> [u32; 2] {
178 self.final_views[0].image().extent()[0..2]
179 .try_into()
180 .unwrap()
181 }
182
183 #[inline]
185 pub fn swapchain_image_view(&self) -> Arc<ImageView> {
186 self.final_views[self.image_index as usize].clone()
187 }
188
189 #[inline]
191 pub fn resolution(&self) -> [f32; 2] {
192 let size = self.window().inner_size();
193 let scale_factor = self.window().scale_factor();
194 [
195 (size.width as f64 / scale_factor) as f32,
196 (size.height as f64 / scale_factor) as f32,
197 ]
198 }
199
200 #[inline]
201 pub fn aspect_ratio(&self) -> f32 {
202 let dims = self.window_size();
203 dims[0] / dims[1]
204 }
205
206 #[inline]
208 #[must_use]
209 pub fn swapchain_image_views(&self) -> &[Arc<ImageView>] {
211 &self.final_views
214 }
215
216 #[inline]
219 pub fn resize(&mut self) {
220 self.recreate_swapchain = true;
221 }
222
223 #[inline]
225 pub fn add_additional_image_view(&mut self, key: usize, format: Format, usage: ImageUsage) {
226 let final_view_image = self.final_views[0].image();
227 let image = ImageView::new_default(
228 Image::new(
229 self.memory_allocator.clone(),
230 ImageCreateInfo {
231 image_type: ImageType::Dim2d,
232 format,
233 extent: final_view_image.extent(),
234 usage,
235 ..Default::default()
236 },
237 AllocationCreateInfo::default(),
238 )
239 .unwrap(),
240 )
241 .unwrap();
242 self.additional_image_views.insert(key, image);
243 }
244
245 #[inline]
247 pub fn get_additional_image_view(&mut self, key: usize) -> Arc<ImageView> {
248 self.additional_image_views.get(&key).unwrap().clone()
249 }
250
251 #[inline]
253 pub fn remove_additional_image_view(&mut self, key: usize) {
254 self.additional_image_views.remove(&key);
255 }
256
257 #[inline]
264 pub fn acquire(
265 &mut self,
266 timeout: Option<Duration>,
267 on_recreate_swapchain: impl FnOnce(&[Arc<ImageView>]),
268 ) -> Result<Box<dyn GpuFuture>, VulkanError> {
269 if self.recreate_swapchain {
272 self.recreate_swapchain_and_views();
273 on_recreate_swapchain(&self.final_views);
274 }
275
276 let (image_index, suboptimal, acquire_future) =
278 match swapchain::acquire_next_image(self.swapchain.clone(), timeout)
279 .map_err(Validated::unwrap)
280 {
281 Ok(r) => r,
282 Err(VulkanError::OutOfDate) => {
283 self.recreate_swapchain = true;
284 return Err(VulkanError::OutOfDate);
285 }
286 Err(e) => panic!("failed to acquire next image: {e}"),
287 };
288 if suboptimal {
289 self.recreate_swapchain = true;
290 }
291 self.image_index = image_index;
293
294 let future = self.previous_frame_end.take().unwrap().join(acquire_future);
295
296 Ok(future.boxed())
297 }
298
299 #[inline]
306 pub fn present(&mut self, after_future: Box<dyn GpuFuture>, wait_future: bool) {
307 let future = after_future
308 .then_swapchain_present(
309 self.graphics_queue.clone(),
310 SwapchainPresentInfo::swapchain_image_index(
311 self.swapchain.clone(),
312 self.image_index,
313 ),
314 )
315 .then_signal_fence_and_flush();
316 match future.map_err(Validated::unwrap) {
317 Ok(mut future) => {
318 if wait_future {
319 future.wait(None).unwrap_or_else(|e| println!("{e}"))
320 } else {
322 future.cleanup_finished();
323 }
324
325 self.previous_frame_end = Some(future.boxed());
326 }
327 Err(VulkanError::OutOfDate) => {
328 self.recreate_swapchain = true;
329 self.previous_frame_end =
330 Some(sync::now(self.graphics_queue.device().clone()).boxed());
331 }
332 Err(e) => {
333 println!("failed to flush future: {e}");
334 self.previous_frame_end =
335 Some(sync::now(self.graphics_queue.device().clone()).boxed());
336 }
337 }
338 }
339
340 fn recreate_swapchain_and_views(&mut self) {
342 let image_extent: [u32; 2] = self.window().inner_size().into();
343
344 if image_extent.contains(&0) {
345 return;
346 }
347
348 let (new_swapchain, new_images) = self
349 .swapchain
350 .recreate(SwapchainCreateInfo {
351 image_extent,
352 present_mode: self.present_mode,
354 ..self.swapchain.create_info()
355 })
356 .expect("failed to recreate swapchain");
357
358 self.swapchain = new_swapchain;
359 let new_images = new_images
360 .into_iter()
361 .map(|image| ImageView::new_default(image).unwrap())
362 .collect::<Vec<_>>();
363 self.final_views = new_images;
364 let resizable_views = self
366 .additional_image_views
367 .iter()
368 .map(|c| *c.0)
369 .collect::<Vec<usize>>();
370 for i in resizable_views {
371 let format = self.get_additional_image_view(i).format();
372 let usage = self.get_additional_image_view(i).usage();
373 self.remove_additional_image_view(i);
374 self.add_additional_image_view(i, format, usage);
375 }
376 self.recreate_swapchain = false;
377 }
378}