@@ -464,6 +464,7 @@ pub struct Instance {
464464 flags : wgt:: InstanceFlags ,
465465 memory_budget_thresholds : wgt:: MemoryBudgetThresholds ,
466466 compiler_container : Arc < shader_compilation:: CompilerContainer > ,
467+ options : wgt:: Dx12BackendOptions ,
467468}
468469
469470impl Instance {
@@ -481,6 +482,7 @@ impl Instance {
481482 target : SurfaceTarget :: Visual ( visual. to_owned ( ) ) ,
482483 supports_allow_tearing : self . supports_allow_tearing ,
483484 swap_chain : RwLock :: new ( None ) ,
485+ options : self . options . clone ( ) ,
484486 }
485487 }
486488
@@ -498,6 +500,7 @@ impl Instance {
498500 target : SurfaceTarget :: SurfaceHandle ( surface_handle) ,
499501 supports_allow_tearing : self . supports_allow_tearing ,
500502 swap_chain : RwLock :: new ( None ) ,
503+ options : self . options . clone ( ) ,
501504 }
502505 }
503506
@@ -514,6 +517,7 @@ impl Instance {
514517 target : SurfaceTarget :: SwapChainPanel ( swap_chain_panel. to_owned ( ) ) ,
515518 supports_allow_tearing : self . supports_allow_tearing ,
516519 swap_chain : RwLock :: new ( None ) ,
520+ options : self . options . clone ( ) ,
517521 }
518522 }
519523}
@@ -528,7 +532,7 @@ struct SwapChain {
528532 // when the swapchain is destroyed
529533 resources : Vec < Direct3D12 :: ID3D12Resource > ,
530534 /// Handle is freed in [`Self::release_resources()`]
531- waitable : Foundation :: HANDLE ,
535+ waitable : Option < Foundation :: HANDLE > ,
532536 acquired_count : usize ,
533537 present_mode : wgt:: PresentMode ,
534538 format : wgt:: TextureFormat ,
@@ -550,6 +554,7 @@ pub struct Surface {
550554 target : SurfaceTarget ,
551555 supports_allow_tearing : bool ,
552556 swap_chain : RwLock < Option < SwapChain > > ,
557+ options : wgt:: Dx12BackendOptions ,
553558}
554559
555560unsafe impl Send for Surface { }
@@ -559,6 +564,12 @@ impl Surface {
559564 pub fn swap_chain ( & self ) -> Option < Dxgi :: IDXGISwapChain3 > {
560565 Some ( self . swap_chain . read ( ) . as_ref ( ) ?. raw . clone ( ) )
561566 }
567+
568+ /// Returns the waitable handle associated with this swap chain, if any.
569+ /// Handle is only valid while the swap chain is alive.
570+ pub unsafe fn waitable_handle ( & self ) -> Option < Foundation :: HANDLE > {
571+ self . swap_chain . read ( ) . as_ref ( ) ?. waitable
572+ }
562573}
563574
564575#[ derive( Debug , Clone , Copy ) ]
@@ -601,6 +612,7 @@ pub struct Adapter {
601612 workarounds : Workarounds ,
602613 memory_budget_thresholds : wgt:: MemoryBudgetThresholds ,
603614 compiler_container : Arc < shader_compilation:: CompilerContainer > ,
615+ options : wgt:: Dx12BackendOptions ,
604616}
605617
606618unsafe impl Send for Adapter { }
@@ -659,6 +671,7 @@ pub struct Device {
659671 idler : Idler ,
660672 features : wgt:: Features ,
661673 shared : Arc < DeviceShared > ,
674+ options : wgt:: Dx12BackendOptions ,
662675 // CPU only pools
663676 rtv_pool : Arc < Mutex < descriptor:: CpuPool > > ,
664677 dsv_pool : Mutex < descriptor:: CpuPool > ,
@@ -1178,7 +1191,9 @@ impl crate::DynAccelerationStructure for AccelerationStructure {}
11781191
11791192impl SwapChain {
11801193 unsafe fn release_resources ( mut self ) -> Dxgi :: IDXGISwapChain3 {
1181- unsafe { Foundation :: HANDLE :: free ( & mut self . waitable ) } ;
1194+ if let Some ( mut waitable) = self . waitable . take ( ) {
1195+ unsafe { Foundation :: HANDLE :: free ( & mut waitable) } ;
1196+ }
11821197 self . raw
11831198 }
11841199
@@ -1190,14 +1205,21 @@ impl SwapChain {
11901205 Some ( duration) => duration. as_millis ( ) as u32 ,
11911206 None => Threading :: INFINITE ,
11921207 } ;
1193- match unsafe { Threading :: WaitForSingleObject ( self . waitable , timeout_ms) } {
1194- Foundation :: WAIT_ABANDONED | Foundation :: WAIT_FAILED => Err ( crate :: SurfaceError :: Lost ) ,
1195- Foundation :: WAIT_OBJECT_0 => Ok ( true ) ,
1196- Foundation :: WAIT_TIMEOUT => Ok ( false ) ,
1197- other => {
1198- log:: error!( "Unexpected wait status: 0x{other:x?}" ) ;
1199- Err ( crate :: SurfaceError :: Lost )
1208+
1209+ if let Some ( waitable) = self . waitable {
1210+ match unsafe { Threading :: WaitForSingleObject ( waitable, timeout_ms) } {
1211+ Foundation :: WAIT_ABANDONED | Foundation :: WAIT_FAILED => {
1212+ Err ( crate :: SurfaceError :: Lost )
1213+ }
1214+ Foundation :: WAIT_OBJECT_0 => Ok ( true ) ,
1215+ Foundation :: WAIT_TIMEOUT => Ok ( false ) ,
1216+ other => {
1217+ log:: error!( "Unexpected wait status: 0x{other:x?}" ) ;
1218+ Err ( crate :: SurfaceError :: Lost )
1219+ }
12001220 }
1221+ } else {
1222+ Ok ( true )
12011223 }
12021224 }
12031225}
@@ -1365,7 +1387,14 @@ impl crate::Surface for Surface {
13651387
13661388 unsafe { swap_chain. SetMaximumFrameLatency ( config. maximum_frame_latency ) }
13671389 . into_device_result ( "SetMaximumFrameLatency" ) ?;
1368- let waitable = unsafe { swap_chain. GetFrameLatencyWaitableObject ( ) } ;
1390+
1391+ let waitable = match device. options . latency_waitable_object {
1392+ wgt:: Dx12UseFrameLatencyWaitableObject :: None => None ,
1393+ wgt:: Dx12UseFrameLatencyWaitableObject :: Wait
1394+ | wgt:: Dx12UseFrameLatencyWaitableObject :: DontWait => {
1395+ Some ( unsafe { swap_chain. GetFrameLatencyWaitableObject ( ) } )
1396+ }
1397+ } ;
13691398
13701399 let mut resources = Vec :: with_capacity ( swap_chain_buffer as usize ) ;
13711400 for i in 0 ..swap_chain_buffer {
@@ -1412,7 +1441,13 @@ impl crate::Surface for Surface {
14121441 let mut swapchain = self . swap_chain . write ( ) ;
14131442 let sc = swapchain. as_mut ( ) . unwrap ( ) ;
14141443
1415- unsafe { sc. wait ( timeout) } ?;
1444+ match self . options . latency_waitable_object {
1445+ wgt:: Dx12UseFrameLatencyWaitableObject :: None
1446+ | wgt:: Dx12UseFrameLatencyWaitableObject :: DontWait => { }
1447+ wgt:: Dx12UseFrameLatencyWaitableObject :: Wait => {
1448+ unsafe { sc. wait ( timeout) } ?;
1449+ }
1450+ }
14161451
14171452 let base_index = unsafe { sc. raw . GetCurrentBackBufferIndex ( ) } as usize ;
14181453 let index = ( base_index + sc. acquired_count ) % sc. resources . len ( ) ;
0 commit comments