@@ -21,8 +21,8 @@ use std::{
2121 thread,
2222} ;
2323use utils:: {
24- get_base_device_limits_from_adapter_limits, make_slice, str_into_string_view,
25- string_view_into_label, string_view_into_str, texture_format_has_depth,
24+ get_base_device_limits_from_adapter_limits, make_slice, make_slice_mut , str_into_string_view,
25+ string_view_into_label, string_view_into_str, texture_format_has_depth, FutureRegistry ,
2626} ;
2727use wgc:: {
2828 command:: { bundle_ffi, ComputePass , RenderPass } ,
@@ -46,6 +46,7 @@ pub mod native {
4646
4747pub struct Context {
4848 global : wgc:: global:: Global ,
49+ futures : parking_lot:: RwLock < FutureRegistry > ,
4950}
5051
5152pub struct WGPUAdapterImpl {
@@ -673,6 +674,7 @@ pub unsafe extern "C" fn wgpuCreateInstance(
673674 Arc :: into_raw ( Arc :: new ( WGPUInstanceImpl {
674675 context : Arc :: new ( Context {
675676 global : wgc:: global:: Global :: new ( "wgpu" , & instance_desc) ,
677+ futures : Default :: default ( ) ,
676678 } ) ,
677679 } ) )
678680}
@@ -865,7 +867,8 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice(
865867 }
866868 } ;
867869
868- NULL_FUTURE
870+ // `context.global.adapter_request_device` resolves immediately
871+ context. futures . write ( ) . completed_future ( ) . into ( )
869872}
870873
871874#[ no_mangle]
@@ -998,6 +1001,9 @@ pub unsafe extern "C" fn wgpuBufferMapAsync(
9981001 let callback = callback_info. callback . expect ( "invalid callback" ) ;
9991002 let userdata = new_userdata ! ( callback_info) ;
10001003
1004+ let id = context. futures . write ( ) . incomplete_future ( ) ;
1005+ let dup_id = id. clone ( ) ;
1006+ let ctx = context. clone ( ) ;
10011007 let operation = wgc:: resource:: BufferMapOperation {
10021008 host : match mode as native:: WGPUMapMode {
10031009 native:: WGPUMapMode_Write => wgc:: device:: HostMap :: Write ,
@@ -1025,6 +1031,7 @@ pub unsafe extern "C" fn wgpuBufferMapAsync(
10251031 userdata. get_1 ( ) ,
10261032 userdata. get_2 ( ) ,
10271033 ) ;
1034+ ctx. futures . write ( ) . complete ( dup_id) ;
10281035 } ) ) ,
10291036 } ;
10301037
@@ -1037,8 +1044,7 @@ pub unsafe extern "C" fn wgpuBufferMapAsync(
10371044 handle_error ( error_sink, cause, None , "wgpuBufferMapAsync" ) ;
10381045 } ;
10391046
1040- // TODO: Properly handle futures.
1041- NULL_FUTURE
1047+ id. into ( )
10421048}
10431049
10441050#[ no_mangle]
@@ -2637,7 +2643,7 @@ pub unsafe extern "C" fn wgpuDevicePopErrorScope(
26372643 }
26382644 } ;
26392645
2640- NULL_FUTURE
2646+ device . context . futures . write ( ) . completed_future ( ) . into ( )
26412647}
26422648
26432649#[ no_mangle]
@@ -2746,6 +2752,7 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter(
27462752 let context = & instance. context ;
27472753 let callback = callback_info. callback . expect ( "invalid callback" ) ;
27482754
2755+ let id = context. futures . write ( ) . completed_future ( ) ;
27492756 let ( desc, inputs) = match options {
27502757 Some ( options) => (
27512758 wgt:: RequestAdapterOptions {
@@ -2776,7 +2783,7 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter(
27762783 callback_info. userdata1 ,
27772784 callback_info. userdata2 ,
27782785 ) ;
2779- return NULL_FUTURE ;
2786+ return id . into ( ) ;
27802787 }
27812788 backend_type => panic ! ( "invalid backend type: 0x{backend_type:08X}" ) ,
27822789 } ,
@@ -2819,7 +2826,7 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter(
28192826 }
28202827 } ;
28212828
2822- NULL_FUTURE
2829+ id . into ( )
28232830}
28242831
28252832#[ no_mangle]
@@ -2940,20 +2947,23 @@ pub unsafe extern "C" fn wgpuQueueOnSubmittedWorkDone(
29402947 let callback = callback_info. callback . expect ( "invalid callback" ) ;
29412948 let userdata = new_userdata ! ( callback_info) ;
29422949
2950+ let id = context. futures . write ( ) . incomplete_future ( ) ;
2951+ let dup_id = id. clone ( ) ;
2952+ let ctx = context. clone ( ) ;
29432953 let closure: wgc:: device:: queue:: SubmittedWorkDoneClosure = Box :: new ( move || {
29442954 callback (
29452955 native:: WGPUQueueWorkDoneStatus_Success ,
29462956 userdata. get_1 ( ) ,
29472957 userdata. get_2 ( ) ,
29482958 ) ;
2959+ ctx. futures . write ( ) . complete ( dup_id) ;
29492960 } ) ;
29502961
29512962 context
29522963 . global
29532964 . queue_on_submitted_work_done ( queue_id, closure) ;
29542965
2955- // TODO: Properly handle futures.
2956- NULL_FUTURE
2966+ id. into ( )
29572967}
29582968
29592969#[ no_mangle]
@@ -4742,3 +4752,46 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderWriteTimestamp(
47424752 ) ,
47434753 }
47444754}
4755+
4756+ #[ no_mangle]
4757+ pub unsafe extern "C" fn wgpuInstanceWaitAny (
4758+ instance : native:: WGPUInstance ,
4759+ future_count : usize ,
4760+ futures : * mut native:: WGPUFutureWaitInfo ,
4761+ timeout_ns : u64 ,
4762+ ) -> native:: WGPUWaitStatus {
4763+ let instance = instance. as_ref ( ) . expect ( "invalid instance" ) ;
4764+ let context = & instance. context ;
4765+ let futures = make_slice_mut ( futures, future_count) ;
4766+
4767+ for future in futures. iter ( ) {
4768+ assert_ne ! (
4769+ future. future. id, NULL_FUTURE . id,
4770+ "null future should never be used"
4771+ ) ;
4772+ }
4773+
4774+ let start = std:: time:: Instant :: now ( ) ;
4775+ loop {
4776+ let mut success = false ;
4777+ let registry = context. futures . read ( ) ;
4778+ for future in futures. iter_mut ( ) {
4779+ future. completed = if registry. is_completed ( future. future . into ( ) ) {
4780+ success = true ;
4781+ true as native:: WGPUBool
4782+ } else {
4783+ false as native:: WGPUBool
4784+ }
4785+ }
4786+ drop ( registry) ;
4787+
4788+ if success {
4789+ return native:: WGPUWaitStatus_Success ;
4790+ }
4791+
4792+ let now = std:: time:: Instant :: now ( ) ;
4793+ if now - start >= std:: time:: Duration :: from_nanos ( timeout_ns) {
4794+ return native:: WGPUWaitStatus_TimedOut ;
4795+ }
4796+ }
4797+ }
0 commit comments