@@ -33,7 +33,6 @@ use skia_safe::{
3333use std:: {
3434 ffi:: { CStr , CString } ,
3535 sync:: Arc ,
36- u64,
3736} ;
3837
3938use crate :: window_renderer:: SkiaBackend ;
@@ -53,6 +52,8 @@ pub(crate) struct VulkanBackend {
5352 swapchain_format : Format ,
5453 swapchain_extent : Extent2D ,
5554 swapchain_image_index : u32 ,
55+ swapchain_suboptimal : bool ,
56+ swapchain_size : ( u32 , u32 ) ,
5657 gr_context : DirectContext ,
5758 image_available_semaphore : Semaphore ,
5859 render_finished_semaphore : Semaphore ,
@@ -88,6 +89,8 @@ impl VulkanBackend {
8889 let ( device, queue) = create_logical_device ( & instance, physical_device, queue_family_index) ;
8990 let device = Arc :: new ( device) ;
9091
92+ let swapchain_size = ( width, height) ;
93+
9194 let ( swapchain, swapchain_fns, swapchain_images, swapchain_format, swapchain_extent) =
9295 create_swapchain (
9396 & instance,
@@ -96,8 +99,7 @@ impl VulkanBackend {
9699 & surface_fns,
97100 surface,
98101 queue_family_index,
99- width,
100- height,
102+ swapchain_size,
101103 None ,
102104 ) ;
103105
@@ -151,6 +153,8 @@ impl VulkanBackend {
151153 swapchain_format,
152154 swapchain_extent,
153155 swapchain_image_index : 0 ,
156+ swapchain_suboptimal : false ,
157+ swapchain_size,
154158 gr_context,
155159 image_available_semaphore,
156160 render_finished_semaphore,
@@ -159,6 +163,36 @@ impl VulkanBackend {
159163 cmd_buf,
160164 }
161165 }
166+
167+ fn recreate_swapchain ( & mut self ) {
168+ unsafe {
169+ self . device . device_wait_idle ( ) . unwrap ( ) ;
170+ }
171+
172+ let old_swapchain = self . swapchain ;
173+
174+ let ( swapchain, swapchain_fns, swapchain_images, swapchain_format, swapchain_extent) =
175+ create_swapchain (
176+ & self . instance ,
177+ & self . device ,
178+ self . physical_device ,
179+ & self . surface_fns ,
180+ self . surface ,
181+ self . queue_family_index ,
182+ self . swapchain_size ,
183+ Some ( old_swapchain) ,
184+ ) ;
185+ self . swapchain = swapchain;
186+ self . swapchain_fns = swapchain_fns;
187+ self . swapchain_images = swapchain_images;
188+ self . swapchain_format = swapchain_format;
189+ self . swapchain_extent = swapchain_extent;
190+ self . swapchain_suboptimal = false ;
191+
192+ unsafe {
193+ self . swapchain_fns . destroy_swapchain ( old_swapchain, None ) ;
194+ }
195+ }
162196}
163197
164198impl Drop for VulkanBackend {
@@ -189,31 +223,8 @@ impl Drop for VulkanBackend {
189223
190224impl SkiaBackend for VulkanBackend {
191225 fn set_size ( & mut self , width : u32 , height : u32 ) {
192- unsafe {
193- self . device . device_wait_idle ( ) . unwrap ( ) ;
194-
195- let old_swapchain = self . swapchain ;
196-
197- let ( swapchain, swapchain_fns, swapchain_images, swapchain_format, swapchain_extent) =
198- create_swapchain (
199- & self . instance ,
200- & self . device ,
201- self . physical_device ,
202- & self . surface_fns ,
203- self . surface ,
204- self . queue_family_index ,
205- width,
206- height,
207- Some ( old_swapchain) ,
208- ) ;
209- self . swapchain = swapchain;
210- self . swapchain_fns = swapchain_fns;
211- self . swapchain_images = swapchain_images;
212- self . swapchain_format = swapchain_format;
213- self . swapchain_extent = swapchain_extent;
214-
215- self . swapchain_fns . destroy_swapchain ( old_swapchain, None ) ;
216- }
226+ self . swapchain_size = ( width, height) ;
227+ self . recreate_swapchain ( ) ;
217228 }
218229
219230 fn prepare ( & mut self ) -> Option < Surface > {
@@ -224,7 +235,7 @@ impl SkiaBackend for VulkanBackend {
224235
225236 self . device . reset_fences ( & [ self . in_flight_fence ] ) . unwrap ( ) ;
226237
227- let ( image_index, _ ) = self
238+ let ( image_index, suboptimal ) = self
228239 . swapchain_fns
229240 . acquire_next_image (
230241 self . swapchain ,
@@ -235,6 +246,7 @@ impl SkiaBackend for VulkanBackend {
235246 . unwrap ( ) ;
236247
237248 self . swapchain_image_index = image_index;
249+ self . swapchain_suboptimal = suboptimal;
238250
239251 let image = self . swapchain_images [ image_index as usize ] ;
240252
@@ -334,13 +346,15 @@ impl SkiaBackend for VulkanBackend {
334346 . swapchains ( & swapchains)
335347 . image_indices ( & image_indices) ;
336348
337- unsafe {
338- self . swapchain_fns
339- . queue_present ( self . queue , & present_info)
340- . unwrap ( ) ;
341- } ;
349+ let result = unsafe { self . swapchain_fns . queue_present ( self . queue , & present_info) } ;
342350
343351 drop ( surface) ;
352+
353+ if self . swapchain_suboptimal
354+ || matches ! ( result, Err ( ash:: vk:: Result :: ERROR_OUT_OF_DATE_KHR ) )
355+ {
356+ self . recreate_swapchain ( ) ;
357+ }
344358 }
345359}
346360
@@ -453,8 +467,7 @@ fn create_swapchain(
453467 surface_fns : & InstanceSurfaceFns ,
454468 surface : SurfaceKHR ,
455469 queue_family_index : u32 ,
456- width : u32 ,
457- height : u32 ,
470+ size : ( u32 , u32 ) ,
458471 old_swapchain : Option < SwapchainKHR > ,
459472) -> (
460473 SwapchainKHR ,
@@ -494,7 +507,21 @@ fn create_swapchain(
494507 . find ( |& m| m == PresentModeKHR :: MAILBOX )
495508 . unwrap_or ( PresentModeKHR :: FIFO ) ;
496509
497- let extent = Extent2D { width, height } ;
510+ let extent = if surface_caps. current_extent . width == u32:: MAX {
511+ Extent2D {
512+ width : size
513+ . 0
514+ . max ( surface_caps. min_image_extent . width )
515+ . min ( surface_caps. max_image_extent . width ) ,
516+ height : size
517+ . 1
518+ . max ( surface_caps. min_image_extent . height )
519+ . min ( surface_caps. max_image_extent . height ) ,
520+ }
521+ } else {
522+ surface_caps. current_extent
523+ } ;
524+
498525 let image_count = surface_caps. min_image_count . max ( 2 ) ;
499526
500527 let create_info = SwapchainCreateInfoKHR :: default ( )
@@ -518,7 +545,7 @@ fn create_swapchain(
518545 . clipped ( true )
519546 . old_swapchain ( old_swapchain. unwrap_or ( SwapchainKHR :: null ( ) ) ) ;
520547
521- let swapchain_fns = DeviceSwapchainFns :: new ( & instance, & device) ;
548+ let swapchain_fns = DeviceSwapchainFns :: new ( instance, device) ;
522549 let swapchain = unsafe { swapchain_fns. create_swapchain ( & create_info, None ) . unwrap ( ) } ;
523550 let images = unsafe { swapchain_fns. get_swapchain_images ( swapchain) . unwrap ( ) } ;
524551
0 commit comments