@@ -25,6 +25,9 @@ use winit::{
2525 window:: WindowBuilder ,
2626} ;
2727
28+ // The maximum number of frames we allow to be in flight at any given time
29+ pub const MAX_FRAME_LATENCY : usize = 3 ;
30+
2831// Simple offset_of macro akin to C++ offsetof
2932#[ macro_export]
3033macro_rules! offset_of {
@@ -133,6 +136,7 @@ pub struct ExampleBase {
133136 pub debug_utils_loader : debug_utils:: Instance ,
134137 pub window : winit:: window:: Window ,
135138 pub event_loop : RefCell < EventLoop < ( ) > > ,
139+ pub frame_index : RefCell < usize > ,
136140 pub debug_call_back : vk:: DebugUtilsMessengerEXT ,
137141
138142 pub pdevice : vk:: PhysicalDevice ,
@@ -149,22 +153,22 @@ pub struct ExampleBase {
149153 pub present_image_views : Vec < vk:: ImageView > ,
150154
151155 pub pool : vk:: CommandPool ,
152- pub draw_command_buffer : vk:: CommandBuffer ,
156+ pub draw_command_buffers : [ vk:: CommandBuffer ; MAX_FRAME_LATENCY ] ,
153157 pub setup_command_buffer : vk:: CommandBuffer ,
154158 pub app_setup_command_buffer : vk:: CommandBuffer ,
155159
156160 pub depth_image : vk:: Image ,
157161 pub depth_image_view : vk:: ImageView ,
158162 pub depth_image_memory : vk:: DeviceMemory ,
159163
160- pub present_complete_semaphore : vk:: Semaphore ,
164+ pub present_complete_semaphores : [ vk:: Semaphore ; MAX_FRAME_LATENCY ] ,
161165 pub rendering_complete_semaphores : Vec < vk:: Semaphore > ,
162166
163- pub draw_commands_reuse_fence : vk:: Fence ,
167+ pub draw_commands_reuse_fences : [ vk:: Fence ; MAX_FRAME_LATENCY ] ,
164168}
165169
166170impl ExampleBase {
167- pub fn render_loop < F : Fn ( ) > ( & self , f : F ) -> Result < ( ) , impl Error > {
171+ pub fn render_loop < F : Fn ( usize ) > ( & self , f : F ) -> Result < ( ) , impl Error > {
168172 self . event_loop . borrow_mut ( ) . run_on_demand ( |event, elwp| {
169173 elwp. set_control_flow ( ControlFlow :: Poll ) ;
170174 match event {
@@ -185,19 +189,22 @@ impl ExampleBase {
185189 elwp. exit ( ) ;
186190 }
187191 Event :: AboutToWait => {
192+ let mut frame_index = self . frame_index . borrow_mut ( ) ;
193+
194+ // The fence from 3 frames ago, that will also be signaled this frame
195+ let draw_commands_reuse_fence =
196+ self . draw_commands_reuse_fences [ * frame_index % MAX_FRAME_LATENCY ] ;
188197 unsafe {
189- self . device . wait_for_fences (
190- & [ self . draw_commands_reuse_fence ] ,
191- true ,
192- u64:: MAX ,
193- )
198+ self . device
199+ . wait_for_fences ( & [ draw_commands_reuse_fence] , true , u64:: MAX )
194200 }
195201 . expect ( "Wait for fence failed." ) ;
196202
197- unsafe { self . device . reset_fences ( & [ self . draw_commands_reuse_fence ] ) }
203+ unsafe { self . device . reset_fences ( & [ draw_commands_reuse_fence] ) }
198204 . expect ( "Reset fences failed." ) ;
199205
200- f ( )
206+ f ( * frame_index) ;
207+ * frame_index += 1 ;
201208 }
202209 _ => ( ) ,
203210 }
@@ -404,7 +411,7 @@ impl ExampleBase {
404411 let pool = device. create_command_pool ( & pool_create_info, None ) . unwrap ( ) ;
405412
406413 let command_buffer_allocate_info = vk:: CommandBufferAllocateInfo :: default ( )
407- . command_buffer_count ( 3 )
414+ . command_buffer_count ( 5 )
408415 . command_pool ( pool)
409416 . level ( vk:: CommandBufferLevel :: PRIMARY ) ;
410417
@@ -413,7 +420,7 @@ impl ExampleBase {
413420 . unwrap ( ) ;
414421 let setup_command_buffer = command_buffers[ 0 ] ;
415422 let app_setup_command_buffer = command_buffers[ 1 ] ;
416- let draw_command_buffer = command_buffers[ 2 ] ;
423+ let draw_command_buffers = command_buffers[ 2 .. 5 ] . try_into ( ) . unwrap ( ) ;
417424
418425 let present_images = swapchain_loader. get_swapchain_images ( swapchain) . unwrap ( ) ;
419426 let present_image_views: Vec < vk:: ImageView > = present_images
@@ -472,13 +479,6 @@ impl ExampleBase {
472479 . bind_image_memory ( depth_image, depth_image_memory, 0 )
473480 . expect ( "Unable to bind depth image memory" ) ;
474481
475- let fence_create_info =
476- vk:: FenceCreateInfo :: default ( ) . flags ( vk:: FenceCreateFlags :: SIGNALED ) ;
477-
478- let draw_commands_reuse_fence = device
479- . create_fence ( & fence_create_info, None )
480- . expect ( "Create fence failed." ) ;
481-
482482 record_submit_commandbuffer (
483483 & device,
484484 setup_command_buffer,
@@ -532,9 +532,11 @@ impl ExampleBase {
532532
533533 let semaphore_create_info = vk:: SemaphoreCreateInfo :: default ( ) ;
534534
535- let present_complete_semaphore = device
536- . create_semaphore ( & semaphore_create_info, None )
537- . unwrap ( ) ;
535+ let present_complete_semaphores = std:: array:: from_fn ( |_| {
536+ device
537+ . create_semaphore ( & semaphore_create_info, None )
538+ . unwrap ( )
539+ } ) ;
538540 let rendering_complete_semaphores = ( 0 ..present_images. len ( ) )
539541 . map ( |_| {
540542 device
@@ -543,8 +545,18 @@ impl ExampleBase {
543545 } )
544546 . collect ( ) ;
545547
548+ let fence_create_info =
549+ vk:: FenceCreateInfo :: default ( ) . flags ( vk:: FenceCreateFlags :: SIGNALED ) ;
550+
551+ let draw_commands_reuse_fences = std:: array:: from_fn ( |_| {
552+ device
553+ . create_fence ( & fence_create_info, None )
554+ . expect ( "Create fence failed." )
555+ } ) ;
556+
546557 Ok ( Self {
547558 event_loop : RefCell :: new ( event_loop) ,
559+ frame_index : RefCell :: new ( 0 ) ,
548560 entry,
549561 instance,
550562 device,
@@ -561,14 +573,14 @@ impl ExampleBase {
561573 present_images,
562574 present_image_views,
563575 pool,
564- draw_command_buffer ,
576+ draw_command_buffers ,
565577 setup_command_buffer,
566578 app_setup_command_buffer,
567579 depth_image,
568580 depth_image_view,
569- present_complete_semaphore ,
581+ present_complete_semaphores ,
570582 rendering_complete_semaphores,
571- draw_commands_reuse_fence ,
583+ draw_commands_reuse_fences ,
572584 surface,
573585 debug_call_back,
574586 debug_utils_loader,
@@ -582,13 +594,15 @@ impl Drop for ExampleBase {
582594 fn drop ( & mut self ) {
583595 unsafe {
584596 self . device . device_wait_idle ( ) . unwrap ( ) ;
585- self . device
586- . destroy_semaphore ( self . present_complete_semaphore , None ) ;
597+ for & semaphore in & self . present_complete_semaphores {
598+ self . device . destroy_semaphore ( semaphore, None ) ;
599+ }
587600 for & semaphore in & self . rendering_complete_semaphores {
588601 self . device . destroy_semaphore ( semaphore, None ) ;
589602 }
590- self . device
591- . destroy_fence ( self . draw_commands_reuse_fence , None ) ;
603+ for & fence in & self . draw_commands_reuse_fences {
604+ self . device . destroy_fence ( fence, None ) ;
605+ }
592606 self . device . free_memory ( self . depth_image_memory , None ) ;
593607 self . device . destroy_image_view ( self . depth_image_view , None ) ;
594608 self . device . destroy_image ( self . depth_image , None ) ;
0 commit comments