wgpu 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 512271e2d60995dd34229880d73287b135c827e69d99b7a757de1a145c4f20e3
4
- data.tar.gz: d8ea4fe71b901767d8a53dce17dc58841de03cfb3fe933688eba07b871d64337
3
+ metadata.gz: bd711bce02ed7be442c0f636460bf55f23df6e9b26cb7a6f07ed1b48b99ca78b
4
+ data.tar.gz: f6ffe9530b72876da7b91805ab22b9a20dd065857bfc7fe99c66a79823fb4c75
5
5
  SHA512:
6
- metadata.gz: 99320911c5862fa7efe153f225bd295ff47bd471a2dfb295482cca10f66e1f728e1dfe72d0ec7925a0643f7c74b641e3aa1fc31d4575b470781635f92a3645bc
7
- data.tar.gz: 74888fd58146595b8f6cf73f2ce1c426b60e05be15416c4ba84cc1b914bd0d9ad2ea51b4f7d5c94d469b9bb4f243f6119f18bbdb1458c6605b75b469ea9062de
6
+ metadata.gz: 3430e9a25cdc932eb8441903b9f5f5aa83ebdafd34d56311ac8f794240a983b9adb6745fef484293dc968fb76b7e1f5da7813faa5a63b46b46126bb817e1b2eb
7
+ data.tar.gz: 75b6031fc4e7654541e6e8596434f8c1e3c4b24d89a16d5b946a29a40ba8da0b6082e395d8ac0a47928e7bc56b2e1e473a350051d78b9a9e6edc4945d293deed
@@ -2,13 +2,12 @@
2
2
 
3
3
  module WGPU
4
4
  class Adapter
5
- attr_reader :handle
5
+ attr_reader :handle, :instance
6
6
 
7
- CALLBACK_MODE_WAIT_ANY_ONLY = 1
8
-
9
- def self.from_handle(handle)
7
+ def self.from_handle(handle, instance: nil)
10
8
  adapter = allocate
11
9
  adapter.instance_variable_set(:@handle, handle)
10
+ adapter.instance_variable_set(:@instance, instance)
12
11
  adapter
13
12
  end
14
13
 
@@ -17,13 +16,14 @@ module WGPU
17
16
  status_holder = { value: nil, message: nil }
18
17
 
19
18
  callback = FFI::Function.new(
20
- :void, [:uint32, :pointer, Native::StringView.by_value, :pointer]
21
- ) do |status, adapter, message, _userdata|
19
+ :void, [:uint32, :pointer, Native::StringView.by_value, :pointer, :pointer]
20
+ ) do |status, adapter, message, _userdata1, _userdata2|
22
21
  status_holder[:value] = Native::RequestAdapterStatus[status]
23
22
  if message[:data] && !message[:data].null? && message[:length] > 0
24
23
  status_holder[:message] = message[:data].read_string(message[:length])
25
24
  end
26
25
  adapter_ptr.write_pointer(adapter)
26
+ status_holder[:done] = true
27
27
  end
28
28
 
29
29
  options = Native::RequestAdapterOptions.new
@@ -36,11 +36,14 @@ module WGPU
36
36
 
37
37
  callback_info = Native::RequestAdapterCallbackInfo.new
38
38
  callback_info[:next_in_chain] = nil
39
- callback_info[:mode] = CALLBACK_MODE_WAIT_ANY_ONLY
39
+ callback_info[:mode] = AsyncWaiter.callback_mode(instance: instance)
40
40
  callback_info[:callback] = callback
41
- callback_info[:userdata] = nil
41
+ callback_info[:userdata1] = nil
42
+ callback_info[:userdata2] = nil
42
43
 
43
- Native.wgpuInstanceRequestAdapter(instance.handle, options, callback_info)
44
+ status_holder[:done] = false
45
+ future = Native.wgpuInstanceRequestAdapter(instance.handle, options, callback_info)
46
+ AsyncWaiter.wait(status_holder: status_holder, instance: instance, future: future)
44
47
 
45
48
  handle = adapter_ptr.read_pointer
46
49
  if handle.null? || status_holder[:value] != :success
@@ -48,11 +51,12 @@ module WGPU
48
51
  raise AdapterError, "Failed to request adapter: #{msg}"
49
52
  end
50
53
 
51
- new(handle)
54
+ new(handle, instance: instance)
52
55
  end
53
56
 
54
- def initialize(handle)
57
+ def initialize(handle, instance: nil)
55
58
  @handle = handle
59
+ @instance = instance
56
60
  end
57
61
 
58
62
  def request_device(label: nil, required_features: [], required_limits: nil)
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WGPU
4
+ module AsyncWaiter
5
+ POLL_INTERVAL_SECONDS = 0.001
6
+ CALLBACK_MODE_FALLBACK = {
7
+ allow_process_events: 2,
8
+ allow_spontaneous: 3
9
+ }.freeze
10
+
11
+ module_function
12
+
13
+ def callback_mode(instance:)
14
+ if instance
15
+ callback_mode_value(:allow_process_events)
16
+ else
17
+ callback_mode_value(:allow_spontaneous)
18
+ end
19
+ end
20
+
21
+ def wait(status_holder:, instance: nil, device: nil, future: nil)
22
+ wait_info = build_wait_info(future) if instance && Native.future_api?
23
+
24
+ until status_holder[:done]
25
+ if instance && wait_info
26
+ wait_with_wait_any(instance, wait_info)
27
+ elsif instance
28
+ instance.process_events
29
+ elsif device && Native.device_poll_available?
30
+ Native.wgpuDevicePoll(device.handle, 0, nil)
31
+ end
32
+ sleep(POLL_INTERVAL_SECONDS) unless status_holder[:done]
33
+ end
34
+ end
35
+
36
+ def callback_mode_value(name)
37
+ Native::CallbackMode[name] || CALLBACK_MODE_FALLBACK.fetch(name)
38
+ end
39
+ private_class_method :callback_mode_value
40
+
41
+ def build_wait_info(future)
42
+ return nil unless future.respond_to?(:[])
43
+
44
+ id = future[:id].to_i
45
+ return nil if id.zero?
46
+
47
+ wait_info = Native::FutureWaitInfo.new
48
+ wait_info[:future] = future
49
+ wait_info[:completed] = 0
50
+ wait_info
51
+ rescue StandardError
52
+ nil
53
+ end
54
+ private_class_method :build_wait_info
55
+
56
+ def wait_with_wait_any(instance, wait_info)
57
+ status = Native.wgpuInstanceWaitAny(instance.handle, 1, wait_info.to_ptr, 0)
58
+ return if [:success, :timed_out].include?(status)
59
+
60
+ raise Error, "wgpuInstanceWaitAny failed: #{status.inspect}"
61
+ end
62
+ private_class_method :wait_with_wait_any
63
+ end
64
+ end
@@ -4,21 +4,21 @@ module WGPU
4
4
  class Device
5
5
  attr_reader :handle, :queue, :adapter
6
6
 
7
- CALLBACK_MODE_WAIT_ANY_ONLY = 1
8
7
  LIMIT_FIELDS = Native::Limits.members.freeze
9
8
 
10
9
  def self.request(adapter, label: nil, required_features: [], required_limits: nil)
11
10
  device_ptr = FFI::MemoryPointer.new(:pointer)
12
- status_holder = { value: nil, message: nil }
11
+ status_holder = { done: false, value: nil, message: nil }
13
12
 
14
13
  callback = FFI::Function.new(
15
- :void, [:uint32, :pointer, Native::StringView.by_value, :pointer]
16
- ) do |status, device, message, _userdata|
14
+ :void, [:uint32, :pointer, Native::StringView.by_value, :pointer, :pointer]
15
+ ) do |status, device, message, _userdata1, _userdata2|
17
16
  status_holder[:value] = Native::RequestDeviceStatus[status]
18
17
  if message[:data] && !message[:data].null? && message[:length] > 0
19
18
  status_holder[:message] = message[:data].read_string(message[:length])
20
19
  end
21
20
  device_ptr.write_pointer(device)
21
+ status_holder[:done] = true
22
22
  end
23
23
 
24
24
  queue_desc = Native::QueueDescriptor.new
@@ -30,12 +30,14 @@ module WGPU
30
30
  device_lost_info[:next_in_chain] = nil
31
31
  device_lost_info[:mode] = 0
32
32
  device_lost_info[:callback] = nil
33
- device_lost_info[:userdata] = nil
33
+ device_lost_info[:userdata1] = nil
34
+ device_lost_info[:userdata2] = nil
34
35
 
35
36
  error_info = Native::UncapturedErrorCallbackInfo.new
36
37
  error_info[:next_in_chain] = nil
37
38
  error_info[:callback] = nil
38
- error_info[:userdata] = nil
39
+ error_info[:userdata1] = nil
40
+ error_info[:userdata2] = nil
39
41
 
40
42
  desc = Native::DeviceDescriptor.new
41
43
  desc[:next_in_chain] = nil
@@ -67,11 +69,13 @@ module WGPU
67
69
 
68
70
  callback_info = Native::RequestDeviceCallbackInfo.new
69
71
  callback_info[:next_in_chain] = nil
70
- callback_info[:mode] = CALLBACK_MODE_WAIT_ANY_ONLY
72
+ callback_info[:mode] = AsyncWaiter.callback_mode(instance: adapter.instance)
71
73
  callback_info[:callback] = callback
72
- callback_info[:userdata] = nil
74
+ callback_info[:userdata1] = nil
75
+ callback_info[:userdata2] = nil
73
76
 
74
- Native.wgpuAdapterRequestDevice(adapter.handle, desc, callback_info)
77
+ future = Native.wgpuAdapterRequestDevice(adapter.handle, desc, callback_info)
78
+ AsyncWaiter.wait(status_holder: status_holder, instance: adapter.instance, future: future)
75
79
 
76
80
  handle = device_ptr.read_pointer
77
81
  if handle.null? || status_holder[:value] != :success
@@ -235,7 +239,12 @@ module WGPU
235
239
  end
236
240
 
237
241
  def poll(wait: false)
238
- Native.wgpuDevicePoll(@handle, wait ? 1 : 0, nil)
242
+ if Native.device_poll_available?
243
+ Native.wgpuDevicePoll(@handle, wait ? 1 : 0, nil)
244
+ else
245
+ @adapter&.instance&.process_events
246
+ 0
247
+ end
239
248
  end
240
249
 
241
250
  def push_error_scope(filter = :validation)
@@ -243,11 +252,13 @@ module WGPU
243
252
  end
244
253
 
245
254
  def pop_error_scope
246
- error_holder = { type: nil, message: nil }
255
+ error_holder = { done: false, status: nil, type: nil, message: nil }
247
256
 
248
257
  callback = FFI::Function.new(
249
258
  :void, [:uint32, :uint32, Native::StringView.by_value, :pointer, :pointer]
250
- ) do |_status, error_type, message, _userdata1, _userdata2|
259
+ ) do |status, error_type, message, _userdata1, _userdata2|
260
+ error_holder[:done] = true
261
+ error_holder[:status] = Native::PopErrorScopeStatus[status]
251
262
  error_holder[:type] = Native::ErrorType[error_type]
252
263
  if message[:data] && !message[:data].null? && message[:length] > 0
253
264
  error_holder[:message] = message[:data].read_string(message[:length])
@@ -256,12 +267,13 @@ module WGPU
256
267
 
257
268
  callback_info = Native::PopErrorScopeCallbackInfo.new
258
269
  callback_info[:next_in_chain] = nil
259
- callback_info[:mode] = 1
270
+ callback_info[:mode] = AsyncWaiter.callback_mode(instance: @adapter&.instance)
260
271
  callback_info[:callback] = callback
261
272
  callback_info[:userdata1] = nil
262
273
  callback_info[:userdata2] = nil
263
274
 
264
- Native.wgpuDevicePopErrorScope(@handle, callback_info)
275
+ future = Native.wgpuDevicePopErrorScope(@handle, callback_info)
276
+ AsyncWaiter.wait(status_holder: error_holder, instance: @adapter&.instance, device: self, future: future)
265
277
 
266
278
  error_holder
267
279
  end
@@ -53,7 +53,7 @@ module WGPU
53
53
  Native.wgpuInstanceEnumerateAdapters(@handle, options, adapters_ptr)
54
54
 
55
55
  adapters_ptr.read_array_of_pointer(count).map do |ptr|
56
- Adapter.from_handle(ptr)
56
+ Adapter.from_handle(ptr, instance: self)
57
57
  end
58
58
  end
59
59
 
@@ -133,6 +133,7 @@ module WGPU
133
133
 
134
134
  def on_submitted_work_done(device: nil)
135
135
  device ||= @device
136
+ instance = device&.adapter&.instance
136
137
  status_holder = { done: false, status: nil }
137
138
 
138
139
  callback = FFI::Function.new(
@@ -144,21 +145,13 @@ module WGPU
144
145
 
145
146
  callback_info = Native::QueueWorkDoneCallbackInfo.new
146
147
  callback_info[:next_in_chain] = nil
147
- callback_info[:mode] = 1
148
+ callback_info[:mode] = AsyncWaiter.callback_mode(instance: instance)
148
149
  callback_info[:callback] = callback
149
150
  callback_info[:userdata1] = nil
150
151
  callback_info[:userdata2] = nil
151
152
 
152
- Native.wgpuQueueOnSubmittedWorkDone(@handle, callback_info)
153
-
154
- if device
155
- until status_holder[:done]
156
- Native.wgpuDevicePoll(device.handle, 0, nil)
157
- sleep(0.001)
158
- end
159
- else
160
- sleep(0.001) until status_holder[:done]
161
- end
153
+ future = Native.wgpuQueueOnSubmittedWorkDone(@handle, callback_info)
154
+ AsyncWaiter.wait(status_holder: status_holder, instance: instance, device: device, future: future)
162
155
 
163
156
  status_holder[:status]
164
157
  end
@@ -3,19 +3,19 @@
3
3
  module WGPU
4
4
  module Native
5
5
  callback :request_adapter_callback,
6
- [RequestAdapterStatus, :pointer, StringView.by_value, :pointer], :void
6
+ [RequestAdapterStatus, :pointer, StringView.by_value, :pointer, :pointer], :void
7
7
 
8
8
  callback :request_device_callback,
9
- [RequestDeviceStatus, :pointer, StringView.by_value, :pointer], :void
9
+ [RequestDeviceStatus, :pointer, StringView.by_value, :pointer, :pointer], :void
10
10
 
11
11
  callback :buffer_map_callback,
12
- [MapAsyncStatus, :pointer], :void
12
+ [MapAsyncStatus, StringView.by_value, :pointer, :pointer], :void
13
13
 
14
- callback :error_callback,
15
- [:uint32, StringView.by_value, :pointer], :void
14
+ callback :uncaptured_error_callback,
15
+ [:pointer, ErrorType, StringView.by_value, :pointer, :pointer], :void
16
16
 
17
17
  callback :device_lost_callback,
18
- [:pointer, :uint32, StringView.by_value, :pointer], :void
18
+ [:pointer, :uint32, StringView.by_value, :pointer, :pointer], :void
19
19
 
20
20
  callback :pop_error_scope_callback,
21
21
  [PopErrorScopeStatus, ErrorType, StringView.by_value, :pointer, :pointer], :void
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WGPU
4
+ module Native
5
+ class << self
6
+ def future_api?
7
+ respond_to?(:wgpuInstanceWaitAny)
8
+ end
9
+
10
+ def device_poll_available?
11
+ respond_to?(:wgpuDevicePoll)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -50,13 +50,15 @@ module WGPU
50
50
  :success, 0x00000001,
51
51
  :instance_dropped, 0x00000002,
52
52
  :unavailable, 0x00000003,
53
- :error, 0x00000004
53
+ :error, 0x00000004,
54
+ :unknown, 0x00000005
54
55
  )
55
56
 
56
57
  RequestDeviceStatus = enum(
57
58
  :success, 0x00000001,
58
59
  :instance_dropped, 0x00000002,
59
- :error, 0x00000003
60
+ :error, 0x00000003,
61
+ :unknown, 0x00000004
60
62
  )
61
63
 
62
64
  BufferMapState = enum(
@@ -65,11 +67,18 @@ module WGPU
65
67
  :mapped, 0x00000003
66
68
  )
67
69
 
70
+ CallbackMode = enum(
71
+ :wait_any_only, 0x00000001,
72
+ :allow_process_events, 0x00000002,
73
+ :allow_spontaneous, 0x00000003
74
+ )
75
+
68
76
  MapAsyncStatus = enum(
69
77
  :success, 0x00000001,
70
78
  :instance_dropped, 0x00000002,
71
79
  :error, 0x00000003,
72
- :aborted, 0x00000004
80
+ :aborted, 0x00000004,
81
+ :unknown, 0x00000005
73
82
  )
74
83
 
75
84
  BufferUsage = {
@@ -482,8 +491,16 @@ module WGPU
482
491
 
483
492
  PopErrorScopeStatus = enum(
484
493
  :success, 0x00000001,
485
- :callback_cancelled, 0x00000002,
486
- :error, 0x00000003
494
+ :instance_dropped, 0x00000002,
495
+ :empty_stack, 0x00000003
496
+ )
497
+
498
+ WaitStatus = enum(
499
+ :success, 0x00000001,
500
+ :timed_out, 0x00000002,
501
+ :unsupported_timeout, 0x00000003,
502
+ :unsupported_count, 0x00000004,
503
+ :unsupported_mixed_sources, 0x00000005
487
504
  )
488
505
 
489
506
  QueueWorkDoneStatus = enum(
@@ -9,7 +9,7 @@ module WGPU
9
9
  [:pointer], :void
10
10
 
11
11
  attach_function :wgpuInstanceRequestAdapter,
12
- [:pointer, RequestAdapterOptions.by_ref, RequestAdapterCallbackInfo.by_value], :pointer
12
+ [:pointer, RequestAdapterOptions.by_ref, RequestAdapterCallbackInfo.by_value], Future.by_value
13
13
 
14
14
  attach_function :wgpuInstanceEnumerateAdapters,
15
15
  [:pointer, :pointer, :pointer], :size_t
@@ -17,6 +17,12 @@ module WGPU
17
17
  attach_function :wgpuInstanceProcessEvents,
18
18
  [:pointer], :void
19
19
 
20
+ begin
21
+ attach_function :wgpuInstanceWaitAny,
22
+ [:pointer, :size_t, :pointer, :uint64], WaitStatus
23
+ rescue FFI::NotFoundError
24
+ end
25
+
20
26
  attach_function :wgpuAdapterRelease,
21
27
  [:pointer], :void
22
28
 
@@ -24,7 +30,7 @@ module WGPU
24
30
  [:pointer, AdapterInfo.by_ref], :void
25
31
 
26
32
  attach_function :wgpuAdapterRequestDevice,
27
- [:pointer, DeviceDescriptor.by_ref, RequestDeviceCallbackInfo.by_value], :pointer
33
+ [:pointer, DeviceDescriptor.by_ref, RequestDeviceCallbackInfo.by_value], Future.by_value
28
34
 
29
35
  attach_function :wgpuAdapterGetFeatures,
30
36
  [:pointer, :pointer], :void
@@ -71,8 +77,11 @@ module WGPU
71
77
  attach_function :wgpuDeviceCreateCommandEncoder,
72
78
  [:pointer, CommandEncoderDescriptor.by_ref], :pointer
73
79
 
74
- attach_function :wgpuDevicePoll,
75
- [:pointer, :uint32, :pointer], :uint32
80
+ begin
81
+ attach_function :wgpuDevicePoll,
82
+ [:pointer, :uint32, :pointer], :uint32
83
+ rescue FFI::NotFoundError
84
+ end
76
85
 
77
86
  attach_function :wgpuQueueRelease,
78
87
  [:pointer], :void
@@ -81,7 +90,7 @@ module WGPU
81
90
  [:pointer, :size_t, :pointer], :void
82
91
 
83
92
  attach_function :wgpuQueueOnSubmittedWorkDone,
84
- [:pointer, QueueWorkDoneCallbackInfo.by_value], :pointer
93
+ [:pointer, QueueWorkDoneCallbackInfo.by_value], Future.by_value
85
94
 
86
95
  attach_function :wgpuQueueWriteBuffer,
87
96
  [:pointer, :pointer, :uint64, :pointer, :size_t], :void
@@ -96,7 +105,7 @@ module WGPU
96
105
  [:pointer], :void
97
106
 
98
107
  attach_function :wgpuBufferMapAsync,
99
- [:pointer, :uint64, :size_t, :size_t, BufferMapCallbackInfo.by_value], :pointer
108
+ [:pointer, :uint64, :size_t, :size_t, BufferMapCallbackInfo.by_value], Future.by_value
100
109
 
101
110
  attach_function :wgpuBufferUnmap,
102
111
  [:pointer], :void
@@ -120,7 +129,7 @@ module WGPU
120
129
  [:pointer], :void
121
130
 
122
131
  attach_function :wgpuShaderModuleGetCompilationInfo,
123
- [:pointer, CompilationInfoCallbackInfo.by_value], :pointer
132
+ [:pointer, CompilationInfoCallbackInfo.by_value], Future.by_value
124
133
 
125
134
  attach_function :wgpuCommandEncoderRelease,
126
135
  [:pointer], :void
@@ -363,7 +372,7 @@ module WGPU
363
372
  [:pointer, ErrorFilter], :void
364
373
 
365
374
  attach_function :wgpuDevicePopErrorScope,
366
- [:pointer, PopErrorScopeCallbackInfo.by_value], :pointer
375
+ [:pointer, PopErrorScopeCallbackInfo.by_value], Future.by_value
367
376
 
368
377
  attach_function :wgpuComputePipelineGetBindGroupLayout,
369
378
  [:pointer, :uint32], :pointer
@@ -59,3 +59,4 @@ require_relative "enums"
59
59
  require_relative "structs"
60
60
  require_relative "callbacks"
61
61
  require_relative "functions"
62
+ require_relative "capabilities"
@@ -17,6 +17,15 @@ module WGPU
17
17
  :s_type, SType
18
18
  end
19
19
 
20
+ class Future < FFI::Struct
21
+ layout :id, :uint64
22
+ end
23
+
24
+ class FutureWaitInfo < FFI::Struct
25
+ layout :future, Future.by_value,
26
+ :completed, :uint32
27
+ end
28
+
20
29
  class InstanceCapabilities < FFI::Struct
21
30
  layout :next_in_chain, :pointer,
22
31
  :timed_wait_any_enable, :uint32,
@@ -58,13 +67,15 @@ module WGPU
58
67
  layout :next_in_chain, :pointer,
59
68
  :mode, :uint32,
60
69
  :callback, :pointer,
61
- :userdata, :pointer
70
+ :userdata1, :pointer,
71
+ :userdata2, :pointer
62
72
  end
63
73
 
64
74
  class UncapturedErrorCallbackInfo < FFI::Struct
65
75
  layout :next_in_chain, :pointer,
66
76
  :callback, :pointer,
67
- :userdata, :pointer
77
+ :userdata1, :pointer,
78
+ :userdata2, :pointer
68
79
  end
69
80
 
70
81
  class PopErrorScopeCallbackInfo < FFI::Struct
@@ -355,21 +366,24 @@ module WGPU
355
366
  layout :next_in_chain, :pointer,
356
367
  :mode, :uint32,
357
368
  :callback, :pointer,
358
- :userdata, :pointer
369
+ :userdata1, :pointer,
370
+ :userdata2, :pointer
359
371
  end
360
372
 
361
373
  class RequestDeviceCallbackInfo < FFI::Struct
362
374
  layout :next_in_chain, :pointer,
363
375
  :mode, :uint32,
364
376
  :callback, :pointer,
365
- :userdata, :pointer
377
+ :userdata1, :pointer,
378
+ :userdata2, :pointer
366
379
  end
367
380
 
368
381
  class BufferMapCallbackInfo < FFI::Struct
369
382
  layout :next_in_chain, :pointer,
370
383
  :mode, :uint32,
371
384
  :callback, :pointer,
372
- :userdata, :pointer
385
+ :userdata1, :pointer,
386
+ :userdata2, :pointer
373
387
  end
374
388
 
375
389
  class TextureViewDescriptor < FFI::Struct
@@ -35,6 +35,7 @@ module WGPU
35
35
 
36
36
  def get_compilation_info
37
37
  result_holder = { done: false, status: nil, messages: [] }
38
+ instance = @device.adapter&.instance
38
39
 
39
40
  callback = FFI::Function.new(
40
41
  :void, [:uint32, :pointer, :pointer, :pointer]
@@ -69,17 +70,13 @@ module WGPU
69
70
 
70
71
  callback_info = Native::CompilationInfoCallbackInfo.new
71
72
  callback_info[:next_in_chain] = nil
72
- callback_info[:mode] = 1
73
+ callback_info[:mode] = AsyncWaiter.callback_mode(instance: instance)
73
74
  callback_info[:callback] = callback
74
75
  callback_info[:userdata1] = nil
75
76
  callback_info[:userdata2] = nil
76
77
 
77
- Native.wgpuShaderModuleGetCompilationInfo(@handle, callback_info)
78
-
79
- until result_holder[:done]
80
- Native.wgpuDevicePoll(@device.handle, 0, nil)
81
- sleep(0.001)
82
- end
78
+ future = Native.wgpuShaderModuleGetCompilationInfo(@handle, callback_info)
79
+ AsyncWaiter.wait(status_holder: result_holder, instance: instance, device: @device, future: future)
83
80
 
84
81
  {
85
82
  status: result_holder[:status],
@@ -60,17 +60,17 @@ module WGPU
60
60
  end
61
61
 
62
62
  def map_sync(mode, offset: 0, size: nil)
63
- status_holder, callback = begin_map_request(mode, offset: offset, size: size)
64
- wait_for_map(status_holder)
63
+ status_holder, callback, future = begin_map_request(mode, offset: offset, size: size)
64
+ wait_for_map(status_holder, future)
65
65
  finalize_map(status_holder)
66
66
  ensure
67
67
  @map_callbacks.delete(callback) if callback
68
68
  end
69
69
 
70
70
  def map_async(mode, offset: 0, size: nil)
71
- status_holder, callback = begin_map_request(mode, offset: offset, size: size)
71
+ status_holder, callback, future = begin_map_request(mode, offset: offset, size: size)
72
72
  AsyncTask.new do
73
- wait_for_map(status_holder)
73
+ wait_for_map(status_holder, future)
74
74
  finalize_map(status_holder)
75
75
  ensure
76
76
  @map_callbacks.delete(callback)
@@ -137,29 +137,35 @@ module WGPU
137
137
  else raise ArgumentError, "Invalid map mode: #{mode}"
138
138
  end
139
139
 
140
- status_holder = { done: false, status: nil }
141
- callback = FFI::Function.new(:void, [:uint32, :pointer]) do |status, _userdata|
140
+ status_holder = { done: false, status: nil, message: nil }
141
+ callback = FFI::Function.new(:void, [:uint32, Native::StringView.by_value, :pointer, :pointer]) do |status, message, _userdata1, _userdata2|
142
142
  status_holder[:done] = true
143
143
  status_holder[:status] = Native::MapAsyncStatus[status]
144
+ if message[:data] && !message[:data].null? && message[:length] > 0
145
+ status_holder[:message] = message[:data].read_string(message[:length])
146
+ end
144
147
  end
145
148
  @map_callbacks << callback
146
149
 
147
150
  callback_info = Native::BufferMapCallbackInfo.new
148
151
  callback_info[:next_in_chain] = nil
149
- callback_info[:mode] = 1
152
+ callback_info[:mode] = AsyncWaiter.callback_mode(instance: @device.adapter&.instance)
150
153
  callback_info[:callback] = callback
151
- callback_info[:userdata] = nil
154
+ callback_info[:userdata1] = nil
155
+ callback_info[:userdata2] = nil
152
156
 
153
- Native.wgpuBufferMapAsync(@handle, mode_flag, offset, size, callback_info)
157
+ future = Native.wgpuBufferMapAsync(@handle, mode_flag, offset, size, callback_info)
154
158
 
155
- [status_holder, callback]
159
+ [status_holder, callback, future]
156
160
  end
157
161
 
158
- def wait_for_map(status_holder)
159
- until status_holder[:done]
160
- Native.wgpuDevicePoll(@device.handle, 0, nil)
161
- sleep(0.001)
162
- end
162
+ def wait_for_map(status_holder, future)
163
+ AsyncWaiter.wait(
164
+ status_holder: status_holder,
165
+ instance: @device.adapter&.instance,
166
+ device: @device,
167
+ future: future
168
+ )
163
169
  end
164
170
 
165
171
  def finalize_map(status_holder)
@@ -167,7 +173,9 @@ module WGPU
167
173
  @mapped = true
168
174
  true
169
175
  else
170
- raise BufferError, "Failed to map buffer: #{status_holder[:status]}"
176
+ detail = status_holder[:message]
177
+ base = "Failed to map buffer: #{status_holder[:status]}"
178
+ raise BufferError, detail && !detail.empty? ? "#{base} (#{detail})" : base
171
179
  end
172
180
  end
173
181
 
data/lib/wgpu/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WGPU
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/wgpu.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "wgpu/version"
4
4
  require_relative "wgpu/error"
5
5
  require_relative "wgpu/native/loader"
6
6
  require_relative "wgpu/async_task"
7
+ require_relative "wgpu/core/async_waiter"
7
8
 
8
9
  require_relative "wgpu/resources/buffer"
9
10
  require_relative "wgpu/resources/texture"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wgpu
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yudai Takada
@@ -74,6 +74,7 @@ files:
74
74
  - lib/wgpu/commands/render_bundle_encoder.rb
75
75
  - lib/wgpu/commands/render_pass.rb
76
76
  - lib/wgpu/core/adapter.rb
77
+ - lib/wgpu/core/async_waiter.rb
77
78
  - lib/wgpu/core/canvas_context.rb
78
79
  - lib/wgpu/core/device.rb
79
80
  - lib/wgpu/core/instance.rb
@@ -81,6 +82,7 @@ files:
81
82
  - lib/wgpu/core/surface.rb
82
83
  - lib/wgpu/error.rb
83
84
  - lib/wgpu/native/callbacks.rb
85
+ - lib/wgpu/native/capabilities.rb
84
86
  - lib/wgpu/native/enums.rb
85
87
  - lib/wgpu/native/functions.rb
86
88
  - lib/wgpu/native/loader.rb