wgpu 1.2.0 → 1.2.1
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 +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +18 -2
- data/docs/README.md +2 -2
- data/docs/api_coverage.md +23 -15
- data/docs/async.md +10 -0
- data/docs/command_encoding.md +25 -0
- data/docs/getting_started_compute.md +1 -0
- data/docs/pipeline_descriptors.md +7 -2
- data/docs/releasing.md +11 -1
- data/docs/resource_lifetime.md +16 -2
- data/docs/texture_readback.md +27 -0
- data/docs/troubleshooting.md +5 -0
- data/docs/upgrading_wgpu_native.md +16 -5
- data/lib/wgpu/async_task.rb +19 -0
- data/lib/wgpu/commands/command_buffer.rb +14 -1
- data/lib/wgpu/commands/command_encoder.rb +58 -1
- data/lib/wgpu/commands/compute_pass.rb +43 -0
- data/lib/wgpu/commands/render_bundle.rb +9 -1
- data/lib/wgpu/commands/render_bundle_encoder.rb +55 -1
- data/lib/wgpu/commands/render_pass.rb +102 -0
- data/lib/wgpu/core/adapter.rb +91 -12
- data/lib/wgpu/core/async_waiter.rb +15 -0
- data/lib/wgpu/core/canvas_context.rb +32 -0
- data/lib/wgpu/core/device.rb +296 -46
- data/lib/wgpu/core/instance.rb +20 -0
- data/lib/wgpu/core/queue.rb +139 -24
- data/lib/wgpu/core/surface.rb +49 -1
- data/lib/wgpu/data_types.rb +16 -0
- data/lib/wgpu/descriptor_helpers.rb +65 -0
- data/lib/wgpu/error.rb +15 -0
- data/lib/wgpu/native/abi_verifier.rb +37 -3
- data/lib/wgpu/native/callbacks.rb +6 -0
- data/lib/wgpu/native/capabilities.rb +16 -2
- data/lib/wgpu/native/distribution.rb +63 -0
- data/lib/wgpu/native/enum_helper.rb +17 -0
- data/lib/wgpu/native/enums.rb +8 -0
- data/lib/wgpu/native/fixtures/webgpu-v27.0.4.0-enums.h +848 -0
- data/lib/wgpu/native/functions.rb +11 -0
- data/lib/wgpu/native/installer.rb +48 -17
- data/lib/wgpu/native/loader.rb +22 -0
- data/lib/wgpu/native/structs.rb +18 -1
- data/lib/wgpu/native_resource.rb +174 -3
- data/lib/wgpu/pipeline/bind_group.rb +9 -0
- data/lib/wgpu/pipeline/bind_group_layout.rb +17 -4
- data/lib/wgpu/pipeline/compute_pipeline.rb +20 -32
- data/lib/wgpu/pipeline/pipeline_layout.rb +8 -0
- data/lib/wgpu/pipeline/render_pipeline.rb +27 -42
- data/lib/wgpu/pipeline/shader_module.rb +54 -29
- data/lib/wgpu/resources/buffer.rb +258 -31
- data/lib/wgpu/resources/query_set.rb +12 -0
- data/lib/wgpu/resources/sampler.rb +7 -0
- data/lib/wgpu/resources/texture.rb +45 -6
- data/lib/wgpu/resources/texture_view.rb +24 -4
- data/lib/wgpu/texture_format.rb +14 -0
- data/lib/wgpu/version.rb +1 -1
- data/lib/wgpu/window.rb +26 -0
- data/sig/wgpu.rbs +84 -5
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c118a2950771b2f34f06fcf4642634e57e8b1de07c26681b81aa94d6a1faaf93
|
|
4
|
+
data.tar.gz: b4f4cc4e97846d21e74144194f97ede7cb2704725cb5887a885345ceedd1c8f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5fad367a0475a31c846fa57151a01d6fda7aed9a5592f6167237117da8967df7269a7ac0233059a174be0803794dc844ee4660cd1383ce3fa858009620100036
|
|
7
|
+
data.tar.gz: 967d67b899a1ca01e5e805407677772aeaec152d72ede7b31746a8baef6d5fa04544863f7d8e70a4bb2804506ccf8fdd58036c5d5a99c49cfe338be73d667504
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 1.2.1 - 2026-07-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add reusable staging buffers to `Queue#read_buffer` and
|
|
15
|
+
`Queue#read_texture`, together with a padded texture-readback example and
|
|
16
|
+
guide.
|
|
17
|
+
- Support WGSL override constants and omitted entry points across compute,
|
|
18
|
+
vertex, and fragment pipeline stages.
|
|
19
|
+
- Add a pinned wgpu-native v27.0.4.0 header fixture, ABI update tooling, and
|
|
20
|
+
cross-platform native artifact verification.
|
|
21
|
+
- Complete RBS and YARD coverage for the public API and expand acceptance
|
|
22
|
+
coverage for typed buffers, descriptors, errors, timeouts, resource
|
|
23
|
+
lifetimes, and GPU examples.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Centralize native capability metadata and validate enum, callback, struct,
|
|
28
|
+
and function ABI expectations against the pinned wgpu-native release.
|
|
29
|
+
- Make compute and rendering examples verify their results, and enforce
|
|
30
|
+
documentation coverage, SDL3-free installation, release checks, and strict
|
|
31
|
+
lavapipe GPU coverage in CI.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Retain callbacks, user data, devices, and instances through dependent
|
|
36
|
+
resource and pending-operation lifetimes, preventing use-after-free crashes
|
|
37
|
+
after release, garbage collection, or timeout.
|
|
38
|
+
- Reject out-of-bounds mapped ranges and prevent late buffer, queue, shader,
|
|
39
|
+
and error-scope callbacks from corrupting completed operation state.
|
|
40
|
+
- Preserve row padding and clean up temporary resources during buffer and
|
|
41
|
+
texture readback, including repeated reads with caller-owned staging buffers.
|
|
42
|
+
- Recover rendering loops from timed-out, outdated, and lost surface frames,
|
|
43
|
+
report fatal acquisition states explicitly, and release every acquired
|
|
44
|
+
texture and view.
|
|
45
|
+
- Track adopted native handles in leak diagnostics and keep release operations
|
|
46
|
+
idempotent across wrapper types.
|
|
47
|
+
- Correct the isolated core-gem dependency path and make Windows native
|
|
48
|
+
artifact checks independent of shell quoting.
|
|
49
|
+
|
|
10
50
|
## 1.2.0 - 2026-07-23
|
|
11
51
|
|
|
12
52
|
### Added
|
data/README.md
CHANGED
|
@@ -53,6 +53,7 @@ export WGPU_LIB_PATH=/path/to/libwgpu_native.so
|
|
|
53
53
|
|
|
54
54
|
### Basic Setup
|
|
55
55
|
|
|
56
|
+
<!-- wgpu-example: run; expect: Using: -->
|
|
56
57
|
```ruby
|
|
57
58
|
require 'wgpu'
|
|
58
59
|
|
|
@@ -62,10 +63,15 @@ device = adapter.request_device
|
|
|
62
63
|
queue = device.queue
|
|
63
64
|
|
|
64
65
|
puts "Using: #{adapter.info[:device]} (#{adapter.info[:backend_type]})"
|
|
66
|
+
|
|
67
|
+
device.release
|
|
68
|
+
adapter.release
|
|
69
|
+
instance.release
|
|
65
70
|
```
|
|
66
71
|
|
|
67
72
|
### Compute Shader Example
|
|
68
73
|
|
|
74
|
+
<!-- wgpu-example: run; expect: [0.0, 2.0, 4.0 -->
|
|
69
75
|
```ruby
|
|
70
76
|
require 'wgpu'
|
|
71
77
|
|
|
@@ -118,14 +124,23 @@ pass.set_pipeline(pipeline)
|
|
|
118
124
|
pass.set_bind_group(0, bind_group)
|
|
119
125
|
pass.dispatch_workgroups(input_data.size / 64)
|
|
120
126
|
pass.end_pass
|
|
121
|
-
|
|
127
|
+
command_buffer = encoder.finish
|
|
128
|
+
queue.submit(command_buffer)
|
|
122
129
|
|
|
123
130
|
# Read results
|
|
124
|
-
result = queue.read_buffer(buffer
|
|
131
|
+
result = queue.read_buffer(buffer)
|
|
125
132
|
output_data = result.unpack("f*")
|
|
126
133
|
|
|
127
134
|
puts output_data[0, 10].inspect
|
|
128
135
|
# => [0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0]
|
|
136
|
+
|
|
137
|
+
[
|
|
138
|
+
command_buffer, pass, encoder, pipeline, pipeline_layout,
|
|
139
|
+
bind_group, bind_group_layout, shader, buffer
|
|
140
|
+
].each(&:release)
|
|
141
|
+
device.release
|
|
142
|
+
adapter.release
|
|
143
|
+
instance.release
|
|
129
144
|
```
|
|
130
145
|
|
|
131
146
|
## Examples
|
|
@@ -147,6 +162,7 @@ Headless validation examples:
|
|
|
147
162
|
- `13_error_handling.rb` - Typed, labeled validation errors
|
|
148
163
|
- `14_async_map.rb` - Async mapping through a forced GC cycle
|
|
149
164
|
- `15_timestamp_query.rb` - Feature-gated timestamp query resolution
|
|
165
|
+
- `16_texture_readback.rb` - Aligned readback of a 65-pixel-wide texture with reusable staging
|
|
150
166
|
|
|
151
167
|
Rendering examples (SDL3):
|
|
152
168
|
- `07_triangle.rb` - Basic triangle rendering
|
data/docs/README.md
CHANGED
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
- [Upgrading wgpu-native](upgrading_wgpu_native.md)
|
|
18
18
|
- [Releasing](releasing.md)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
signatures live in `sig/wgpu.rbs` and validate with
|
|
20
|
+
The published [API reference](https://www.rubydoc.info/gems/wgpu) is generated
|
|
21
|
+
with `bundle exec yard doc`. Static API signatures live in `sig/wgpu.rbs` and validate with
|
|
22
22
|
`bundle exec rbs -I sig validate`.
|
data/docs/api_coverage.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# WebGPU API coverage
|
|
2
2
|
|
|
3
|
-
This page records the public Ruby API implemented by wgpu-ruby 1.
|
|
3
|
+
This page records the public Ruby API implemented by wgpu-ruby 1.2 and its
|
|
4
4
|
relationship to the WebGPU object model. It is a baseline, not a claim that
|
|
5
5
|
every WebGPU feature is implemented.
|
|
6
6
|
|
|
@@ -33,12 +33,12 @@ Legend:
|
|
|
33
33
|
| `GPUCompilationMessage` | `WGPU::CompilationMessage` | ✅ | Message, type, line, column, offset, and length are typed fields. |
|
|
34
34
|
| `GPUComputePassEncoder` | `WGPU::ComputePass` | ✅ | |
|
|
35
35
|
| `GPUComputePipeline` | `WGPU::ComputePipeline` | ✅ | Auto layout and override constants are accepted. |
|
|
36
|
-
| `GPUDevice` | `WGPU::Device` | ◐ | Resource creation, error scopes, polling, features,
|
|
37
|
-
| `GPUDeviceLostInfo` |
|
|
38
|
-
| `GPUError` |
|
|
36
|
+
| `GPUDevice` | `WGPU::Device` | ◐ | Resource creation, error scopes, polling, features, limits, device-lost notification, and uncaptured-error subscriptions are exposed. |
|
|
37
|
+
| `GPUDeviceLostInfo` | callback `reason` and `message` | ◐ | `Device#on_device_lost` exposes the native reason and message without a separate wrapper object. |
|
|
38
|
+
| `GPUError` | `WGPU::GPUError` | ✅ | Typed value object with `type`, `message`, `to_h`, and exception conversion. |
|
|
39
39
|
| `GPUExternalTexture` | — | ❌ | Browser video/external-texture import is not exposed. |
|
|
40
|
-
| `GPUInternalError` |
|
|
41
|
-
| `GPUOutOfMemoryError` |
|
|
40
|
+
| `GPUInternalError` | `WGPU::InternalError` | ◐ | Represented as a Ruby exception converted from `GPUError`. |
|
|
41
|
+
| `GPUOutOfMemoryError` | `WGPU::OutOfMemoryError` | ◐ | Represented as a Ruby exception converted from `GPUError`. |
|
|
42
42
|
| `GPUPipelineError` | `WGPU::PipelineError` | ◐ | Ruby exception exists; native pipeline error data is not a value object. |
|
|
43
43
|
| `GPUPipelineLayout` | `WGPU::PipelineLayout` | ✅ | |
|
|
44
44
|
| `GPUQuerySet` | `WGPU::QuerySet` | ✅ | |
|
|
@@ -53,10 +53,10 @@ Legend:
|
|
|
53
53
|
| `GPUSupportedLimits` | `Hash` | ◐ | Represented as a Ruby hash. |
|
|
54
54
|
| `GPUTexture` | `WGPU::Texture` | ✅ | |
|
|
55
55
|
| `GPUTextureView` | `WGPU::TextureView` | ✅ | |
|
|
56
|
-
| `GPUUncapturedErrorEvent` |
|
|
57
|
-
| `GPUValidationError` |
|
|
56
|
+
| `GPUUncapturedErrorEvent` | `Device#on_uncaptured_error` | ◐ | The callback receives `WGPU::GPUError`; there is no DOM event wrapper. |
|
|
57
|
+
| `GPUValidationError` | `WGPU::ValidationError` | ◐ | Validation errors are translated during resource creation and typed error-scope handling. |
|
|
58
58
|
| `WGSLLanguageFeatures` | — | ❌ | |
|
|
59
|
-
| `GPUObjectBase` |
|
|
59
|
+
| `GPUObjectBase` | `WGPU::NativeResource` | ✅ | All native wrappers share `handle`, `label`, `released?`, `use`, `inspect`, idempotent release, and use-after-release guards. |
|
|
60
60
|
| `GPUPipelineBase` | `#get_bind_group_layout` | ✅ | Implemented by compute and render pipelines. |
|
|
61
61
|
| `GPUCommandsMixin` | `WGPU::CommandEncoder` | ✅ | |
|
|
62
62
|
| `GPUDebugCommandsMixin` | encoder/pass debug methods | ✅ | |
|
|
@@ -76,19 +76,22 @@ and DOM canvas ownership) are not implemented.
|
|
|
76
76
|
|
|
77
77
|
Constructors are omitted where objects are normally returned by another
|
|
78
78
|
wrapper. `handle` readers are listed once here as a common escape hatch for
|
|
79
|
-
native interoperation.
|
|
79
|
+
native interoperation. Every native wrapper also has the common
|
|
80
|
+
`label`, `released?`, `use`, `inspect`, and idempotent `release` methods from
|
|
81
|
+
`WGPU::NativeResource`.
|
|
80
82
|
|
|
81
83
|
| Ruby class | Public class methods | Public instance methods |
|
|
82
84
|
|---|---|---|
|
|
85
|
+
| `WGPU` | — | module methods `log_level`, `log_level=`, `on_log` |
|
|
83
86
|
| `WGPU::Instance` | — | `request_adapter`, `request_adapter_async`, `enumerate_adapters`, `enumerate_adapters_async`, `process_events`, `get_canvas_context`, `release`, `handle` |
|
|
84
87
|
| `WGPU::Adapter` | `request`, `from_handle` | `request_device`, `request_device_async`, `info`, `name`, `vendor`, `adapter_type`, `backend_type`, `features`, `has_feature?`, `limits`, `summary`, `release`, `handle`, `instance` |
|
|
85
|
-
| `WGPU::Device` | `request` | `queue`, `adapter`, `adapter_info`, `features`, `has_feature?`, `limits`, all `create_*` methods, `push_error_scope`, `pop_error_scope`, `pop_error_scope_async`, `with_error_scope`, `poll`, `destroy`, `release`, `handle` |
|
|
88
|
+
| `WGPU::Device` | `request` | `queue`, `adapter`, `adapter_info`, `features`, `has_feature?`, `limits`, all `create_*` methods, `push_error_scope`, `pop_error_scope`, `pop_error_scope_async`, `pop_error_scope_typed`, `with_error_scope`, `on_uncaptured_error`, `on_device_lost`, `poll`, `destroy`, `release`, `handle` |
|
|
86
89
|
| `WGPU::Queue` | — | `submit`, `write_buffer`, `write_texture`, `read_buffer`, `read_texture`, `on_submitted_work_done`, `on_submitted_work_done_async`, `release`, `handle` |
|
|
87
90
|
| `WGPU::Surface` | `from_metal_layer`, `from_windows_hwnd`, `from_xlib_window`, `from_wayland_surface` | `configure`, `unconfigure`, `current_texture`, `get_current_texture`, `present`, `get_configuration`, `get_preferred_format`, `capabilities`, `release`, `handle` |
|
|
88
91
|
| `WGPU::CanvasContext` | — | `configure`, `unconfigure`, `get_current_texture`, `present`, `get_configuration`, `get_preferred_format`, `set_physical_size`, `physical_size`, `release` |
|
|
89
|
-
| `WGPU::Buffer` | — | `write`, `mapped_range`, `get_mapped_range`, `unmap`, `map_sync`, `map_async`, `read_mapped_data`, `read_mapped`, `write_mapped`, `
|
|
90
|
-
| `WGPU::BufferMappedRange` | — | `
|
|
91
|
-
| `WGPU::Texture` | `from_handle` | `create_view`, `width`, `height`, `depth_or_array_layers`, `size`, `mip_level_count`, `sample_count`, `dimension`, `format`, `usage`, `destroy`, `release`, `handle` |
|
|
92
|
+
| `WGPU::Buffer` | — | `write`, `mapped_range`, `get_mapped_range`, `unmap`, `map_sync`, `map_async`, `read_mapped_data`, `read_mapped`, `write_mapped`, typed `read_mapped_*` methods, `read_mapped_values`, `map_state`, `size`, `usage`, `destroy`, `release`, `handle` |
|
|
93
|
+
| `WGPU::BufferMappedRange` | — | `read`, `write`, `read_bytes`, `write_bytes`, and typed `read_*` / `write_*` methods |
|
|
94
|
+
| `WGPU::Texture` | `from_handle` | `create_view`, `width`, `height`, `depth_or_array_layers`, `size`, `mip_level_count`, `sample_count`, `dimension`, `format`, `usage`, `surface_status`, `destroy`, `release`, `handle` |
|
|
92
95
|
| `WGPU::TextureView` | `from_handle` | `texture`, `size`, `release`, `handle` |
|
|
93
96
|
| `WGPU::Sampler` | — | `release`, `handle` |
|
|
94
97
|
| `WGPU::QuerySet` | — | `count`, `type`, `destroy`, `release`, `handle` |
|
|
@@ -105,6 +108,10 @@ native interoperation.
|
|
|
105
108
|
| `WGPU::RenderBundleEncoder` | — | pipeline/bind-group/buffer setup, draw/debug methods, `finish`, `release`, `handle` |
|
|
106
109
|
| `WGPU::RenderBundle` | — | `release`, `handle` |
|
|
107
110
|
| `WGPU::AsyncTask` | — | `wait`, `value`, `then`, `complete?`, `pending?`, `error` |
|
|
111
|
+
| `WGPU::GPUError` | `from_hash` | `type`, `message`, `exception_class`, `raise!`, `to_h` |
|
|
112
|
+
| `WGPU::CompilationMessage` | — | `type`, `message`, `line_num`/`line`, `line_pos`/`column`, `offset`, `length`, `to_s` |
|
|
113
|
+
| `WGPU::DataTypes` | `pack`, `unpack`, `byte_size`, `to_pointer`, `validate_alignment!` | — |
|
|
114
|
+
| `WGPU::TextureFormat` | `block_size`, `block_dimensions`, `bytes_per_row`, `aligned_bytes_per_row`, `block_info` | — |
|
|
108
115
|
| `WGPU::Window::SDLWindow` | — | `create_surface`, event/key helpers, `drawable_size`, `close` |
|
|
109
116
|
|
|
110
117
|
## Examples as executable specifications
|
|
@@ -123,9 +130,10 @@ native interoperation.
|
|
|
123
130
|
| `10_textured_quad.rb` | Texture sampling | texture upload/view, sampler, texture bind group, draw |
|
|
124
131
|
| `11_rotating_cube.rb` | Depth-tested 3D rendering | vertex/index/uniform/depth resources, pipeline, per-frame uniform write, draw |
|
|
125
132
|
| `12_headless_render.rb` | Offscreen triangle and readback | render-to-texture, block render pass, aligned texture readback, pixel assertions |
|
|
126
|
-
| `13_error_handling.rb` | Typed and labeled validation error | `
|
|
133
|
+
| `13_error_handling.rb` | Typed and labeled validation error | `ArgumentError`, operation/label context |
|
|
127
134
|
| `14_async_map.rb` | Async map and callback retention | `map_async`, `AsyncTask`, typed mapped reads, GC stress |
|
|
128
135
|
| `15_timestamp_query.rb` | Feature-gated GPU timestamps | timestamp pass writes, query resolution, u64 readback |
|
|
136
|
+
| `16_texture_readback.rb` | Non-aligned-width texture readback | texture row alignment helpers, caller-owned reusable staging |
|
|
129
137
|
|
|
130
138
|
When a public API changes, the corresponding example is part of the acceptance
|
|
131
139
|
test surface. Compute and headless examples are automated in GPU CI; SDL
|
data/docs/async.md
CHANGED
|
@@ -19,11 +19,21 @@ That release also exports `wgpuBufferGetMapState` as an unimplemented panic
|
|
|
19
19
|
stub. `Buffer#map_state` is maintained by wgpu-ruby as `:unmapped`,
|
|
20
20
|
`:pending`, or `:mapped` while map operations run.
|
|
21
21
|
|
|
22
|
+
The exported `wgpuDeviceCreateComputePipelineAsync` and
|
|
23
|
+
`wgpuDeviceCreateRenderPipelineAsync` functions are also panic stubs in
|
|
24
|
+
wgpu-native v27. Pipeline `*_async` methods therefore retain the safe Ruby
|
|
25
|
+
Thread implementation until those native entry points are implemented.
|
|
26
|
+
|
|
22
27
|
Synchronous adapter/device requests, `Buffer#map_sync`,
|
|
23
28
|
`Device#pop_error_scope`, and `Queue#on_submitted_work_done` accept
|
|
24
29
|
`timeout:` in seconds. The default `nil` preserves the prior unbounded wait.
|
|
25
30
|
Expiry raises `WGPU::TimeoutError`.
|
|
26
31
|
|
|
32
|
+
`Device.request` can time out only when its adapter is associated with an
|
|
33
|
+
`Instance`. When adopting a native adapter, pass `instance:` to
|
|
34
|
+
`Adapter.from_handle`; without an instance there is no safe event-progress
|
|
35
|
+
boundary for cleaning up a device that completes after timeout.
|
|
36
|
+
|
|
27
37
|
`*_async` methods return `WGPU::AsyncTask`, a convenience wrapper backed by a
|
|
28
38
|
Ruby Thread. Concurrent operations on the same WebGPU object are not
|
|
29
39
|
guaranteed safe. Prefer synchronous operations or external serialization when
|
data/docs/command_encoding.md
CHANGED
|
@@ -22,3 +22,28 @@ call `end_pass` (or `end`) and `release` yourself.
|
|
|
22
22
|
Only one pass may be active on a command encoder. `CommandEncoder#finish`
|
|
23
23
|
raises `WGPU::CommandError` while a pass is still active instead of handing
|
|
24
24
|
invalid state to wgpu-native. Calling `end_pass` more than once is harmless.
|
|
25
|
+
|
|
26
|
+
## Queries and debug markers
|
|
27
|
+
|
|
28
|
+
Pass descriptors accept `timestamp_writes:` with a query set and beginning/end
|
|
29
|
+
indices. Render passes additionally accept `occlusion_query_set:` and expose
|
|
30
|
+
`begin_occlusion_query` / `end_occlusion_query`. Copy completed query values
|
|
31
|
+
into a buffer with `CommandEncoder#resolve_query_set`; timestamp queries
|
|
32
|
+
require the adapter's `:timestamp_query` feature and a device requested with
|
|
33
|
+
that feature.
|
|
34
|
+
|
|
35
|
+
[`examples/15_timestamp_query.rb`](../examples/15_timestamp_query.rb) shows the
|
|
36
|
+
complete feature-gated timestamp flow, including query resolution and typed
|
|
37
|
+
`u64` readback.
|
|
38
|
+
|
|
39
|
+
Command encoders, compute/render passes, and render bundle encoders expose
|
|
40
|
+
`push_debug_group`, `pop_debug_group`, and `insert_debug_marker`. Labels are
|
|
41
|
+
forwarded directly to wgpu-native for capture/debugging tools:
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
encoder.push_debug_group("upload and dispatch")
|
|
45
|
+
encoder.insert_debug_marker("resources ready")
|
|
46
|
+
encoder.pop_debug_group
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Debug groups must be balanced before the encoder or pass is finished.
|
|
@@ -5,13 +5,13 @@ WebGPU pipeline descriptors. Passing `layout: :auto`, `"auto"`, or `nil` request
|
|
|
5
5
|
automatic layout inference. A layout object continues to select an explicit
|
|
6
6
|
pipeline layout.
|
|
7
7
|
|
|
8
|
-
## Default
|
|
8
|
+
## Default pipeline state
|
|
9
9
|
|
|
10
10
|
The wrapper applies the following WebGPU defaults when a field is omitted:
|
|
11
11
|
|
|
12
12
|
| State | Field | Default |
|
|
13
13
|
|---|---|---|
|
|
14
|
-
| Vertex | `entry_point` | `
|
|
14
|
+
| Vertex/fragment/compute | `entry_point` | omitted (`nil`) |
|
|
15
15
|
| Vertex buffer | `step_mode` | `:vertex` |
|
|
16
16
|
| Primitive | `topology` | `:triangle_list` |
|
|
17
17
|
| Primitive | `strip_index_format` | `:undefined` |
|
|
@@ -33,6 +33,11 @@ The wrapper applies the following WebGPU defaults when a field is omitted:
|
|
|
33
33
|
depth/stencil state requires `format`. Unknown descriptor keys produce a warning
|
|
34
34
|
so misspellings are visible while preserving v1.x compatibility.
|
|
35
35
|
|
|
36
|
+
When `entry_point` is omitted, the wrapper passes WebGPU's nullable string
|
|
37
|
+
sentinel to wgpu-native. Native pipeline creation then selects the sole matching
|
|
38
|
+
entry point in that shader stage. Specify `entry_point:` when a stage contains
|
|
39
|
+
multiple matching entry points.
|
|
40
|
+
|
|
36
41
|
Both vertex/fragment and compute stages accept `constants:`, a Hash mapping WGSL
|
|
37
42
|
override names to numeric values. The descriptor keeps all FFI strings and
|
|
38
43
|
arrays alive until native pipeline creation completes.
|
data/docs/releasing.md
CHANGED
|
@@ -3,7 +3,17 @@
|
|
|
3
3
|
The release workflow uses RubyGems Trusted Publishing and runs for `v*` tags.
|
|
4
4
|
Before the first automated release, configure a trusted publisher for the
|
|
5
5
|
`ydah/wgpu-ruby` repository, workflow `release.yml`, and GitHub environment
|
|
6
|
-
`release` on RubyGems.org.
|
|
6
|
+
`release` on RubyGems.org. The trusted publisher and protected environment are
|
|
7
|
+
repository/RubyGems.org settings, so they cannot be configured or verified from
|
|
8
|
+
this repository alone.
|
|
9
|
+
|
|
10
|
+
## Dry run
|
|
11
|
+
|
|
12
|
+
Run the **Push gem** workflow manually from the GitHub Actions page before
|
|
13
|
+
tagging a release. A `workflow_dispatch` run executes the same native build,
|
|
14
|
+
ABI verification, CPU and GPU specs, examples, RuboCop, RBS, YARD, coverage,
|
|
15
|
+
and gem build checks as a tag run. It skips both the tag/version comparison and
|
|
16
|
+
the RubyGems publishing action, so it cannot publish a gem.
|
|
7
17
|
|
|
8
18
|
Release checklist:
|
|
9
19
|
|
data/docs/resource_lifetime.md
CHANGED
|
@@ -17,6 +17,10 @@ Ruby finalizers.
|
|
|
17
17
|
- Every native wrapper supports `use { |resource| ... }`. It returns the block
|
|
18
18
|
result and releases the wrapper in `ensure`, including when the block raises.
|
|
19
19
|
This is Ruby convenience API rather than a WebGPU operation.
|
|
20
|
+
- Device callbacks share a lifetime across the device and every derived native
|
|
21
|
+
wrapper. Releasing a device before a child does not free callback closures
|
|
22
|
+
that wgpu-native may still reach; they are freed after the final child
|
|
23
|
+
wrapper and pending callback operation complete.
|
|
20
24
|
|
|
21
25
|
For short-lived resources:
|
|
22
26
|
|
|
@@ -81,10 +85,20 @@ does not itself release the command buffer or its referenced Ruby wrappers.
|
|
|
81
85
|
## Internal staging resources
|
|
82
86
|
|
|
83
87
|
`Queue#read_buffer` and `Queue#read_texture` create a temporary staging buffer,
|
|
84
|
-
submit a copy, map and read it, then unmap and release it.
|
|
85
|
-
|
|
88
|
+
submit a copy, map and read it, then unmap and release it. Cleanup independently
|
|
89
|
+
attempts to unmap and release the command buffer, encoder, and internal staging
|
|
90
|
+
buffer on every exit path, even when an earlier cleanup operation raises.
|
|
86
91
|
Applications should not attempt to retain or release this internal buffer.
|
|
87
92
|
|
|
93
|
+
For repeated readbacks, pass a caller-owned `staging:` buffer created by the
|
|
94
|
+
same device. It must be unmapped, have `:map_read` and `:copy_dst` usage, and be
|
|
95
|
+
large enough for the requested byte range (`read_buffer`) or padded copy
|
|
96
|
+
footprint (`read_texture`). The queue unmaps it after each read but never
|
|
97
|
+
releases it, so it can be reused and the caller remains responsible for its
|
|
98
|
+
eventual release. A device-owned queue uses its owning device automatically;
|
|
99
|
+
only queues constructed without an owner require the explicit `device:`
|
|
100
|
+
keyword.
|
|
101
|
+
|
|
88
102
|
## Leak diagnostics
|
|
89
103
|
|
|
90
104
|
Set `WGPU_DEBUG_LEAKS=1` before requiring the gem, or set
|
data/docs/texture_readback.md
CHANGED
|
@@ -17,3 +17,30 @@ depth/stencil copies require an explicit `aspect:`.
|
|
|
17
17
|
256-byte copy alignment and large enough for the requested width and format.
|
|
18
18
|
Use `aligned_bytes_per_row` when the tight row is not already aligned. Automatic
|
|
19
19
|
padding and mipmap generation are intentionally outside this low-level binding.
|
|
20
|
+
|
|
21
|
+
For example, an `rgba8_unorm` row that is 65 pixels wide contains 260 bytes,
|
|
22
|
+
but its smallest valid readback stride is 512 bytes:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
width = 65
|
|
26
|
+
height = 2
|
|
27
|
+
bytes_per_row = WGPU::TextureFormat.aligned_bytes_per_row(width, :rgba8_unorm)
|
|
28
|
+
# => 512
|
|
29
|
+
|
|
30
|
+
pixels = queue.read_texture(
|
|
31
|
+
source: { texture: texture },
|
|
32
|
+
data_layout: { bytes_per_row: bytes_per_row, rows_per_image: height },
|
|
33
|
+
size: { width: width, height: height }
|
|
34
|
+
)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The returned string includes row padding and has
|
|
38
|
+
`bytes_per_row * rows_per_image * depth_or_array_layers` bytes. Read only the
|
|
39
|
+
tight bytes of each row when processing pixels.
|
|
40
|
+
|
|
41
|
+
Both `Queue#read_texture` and `Queue#read_buffer` accept an optional `staging:`
|
|
42
|
+
buffer for repeated readbacks. It must be unmapped, belong to the same device,
|
|
43
|
+
be large enough for the full returned string, and include both `:map_read` and
|
|
44
|
+
`:copy_dst` usage. The helper unmaps caller-provided staging after each read but
|
|
45
|
+
does not release it, so the caller can reuse it and remains responsible for
|
|
46
|
+
releasing it. The queue uses its owning device when `device:` is omitted.
|
data/docs/troubleshooting.md
CHANGED
|
@@ -27,6 +27,11 @@ Pass `timeout:` to adapter/device requests, `Buffer#map_sync`,
|
|
|
27
27
|
`WGPU::TimeoutError`. In an event loop, regularly call
|
|
28
28
|
`Instance#process_events` or `Device#poll`.
|
|
29
29
|
|
|
30
|
+
For a native adapter wrapped with `Adapter.from_handle`, provide its
|
|
31
|
+
`instance:` before using `Device.request(timeout: ...)`. Timeout is rejected
|
|
32
|
+
without that instance because a late native completion cannot be cleaned up
|
|
33
|
+
safely.
|
|
34
|
+
|
|
30
35
|
## Texture readback rejects bytes_per_row
|
|
31
36
|
|
|
32
37
|
Buffer/texture copy rows must be 256-byte aligned. Calculate the value with
|
|
@@ -9,11 +9,23 @@ Use this checklist for each pinned wgpu-native update.
|
|
|
9
9
|
remains.
|
|
10
10
|
4. Run `bundle exec rake wgpu:clean wgpu:install` on a disposable cache, then
|
|
11
11
|
test an existing legacy cache separately.
|
|
12
|
-
5.
|
|
13
|
-
|
|
12
|
+
5. Regenerate the repository enum fixture from the installed release header:
|
|
13
|
+
|
|
14
|
+
```console
|
|
15
|
+
bundle exec ruby script/update_abi_fixture.rb \
|
|
16
|
+
"$WGPU_CACHE_DIR/<version>/include/webgpu/webgpu.h"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The generated comment records the source SHA-256. For the current
|
|
20
|
+
`v27.0.4.0` release, `include/webgpu/webgpu.h` is
|
|
21
|
+
`a6fccf7f9f2fa674d1adfe4f6ea89784a876395b2307bfc2b06f2e77cf6cf356`.
|
|
22
|
+
Review every enum addition, removal, and value change, then run
|
|
23
|
+
`bundle exec rake wgpu:verify_abi`.
|
|
14
24
|
6. Compare structs, field offsets, callback signatures, and exported functions.
|
|
15
|
-
Add ABI specs for changed layouts.
|
|
16
|
-
|
|
25
|
+
Add ABI specs for changed layouts. Check `include/webgpu/wgpu.h` for native
|
|
26
|
+
extensions as well. `wgpuGetVersion` encodes `vMAJOR.MINOR.PATCH.BUILD` in
|
|
27
|
+
four bytes; the verifier compares it with `Distribution::VERSION`. Mark
|
|
28
|
+
functions optional only when the Ruby API has a valid capability fallback.
|
|
17
29
|
7. Run `bundle exec rspec --tag '~gpu'`, RuboCop, RBS validation, and YARD.
|
|
18
30
|
8. Run every `:gpu` spec and `rake examples:ci` with lavapipe. Run rendering
|
|
19
31
|
examples on at least one real surface backend.
|
|
@@ -23,4 +35,3 @@ Use this checklist for each pinned wgpu-native update.
|
|
|
23
35
|
|
|
24
36
|
For a dry run, use a temporary `WGPU_CACHE_DIR` and restore the version/artifact
|
|
25
37
|
edits afterward. Never replace the shared user cache as part of verification.
|
|
26
|
-
|
data/lib/wgpu/async_task.rb
CHANGED
|
@@ -4,6 +4,8 @@ require "timeout"
|
|
|
4
4
|
|
|
5
5
|
module WGPU
|
|
6
6
|
class AsyncTask
|
|
7
|
+
# Starts a background task that evaluates the given block.
|
|
8
|
+
# @raise [ArgumentError] if no block is supplied
|
|
7
9
|
def initialize(&block)
|
|
8
10
|
raise ArgumentError, "block is required" unless block
|
|
9
11
|
|
|
@@ -18,12 +20,20 @@ module WGPU
|
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
|
|
23
|
+
# Waits until the task finishes.
|
|
24
|
+
# @param timeout [Numeric, nil] maximum number of seconds to wait
|
|
25
|
+
# @return [AsyncTask] this task
|
|
26
|
+
# @raise [Timeout::Error] if the task does not finish in time
|
|
21
27
|
def wait(timeout: nil)
|
|
22
28
|
joined = timeout ? @thread.join(timeout) : @thread.join
|
|
23
29
|
raise Timeout::Error, "async task timeout" unless joined
|
|
24
30
|
self
|
|
25
31
|
end
|
|
26
32
|
|
|
33
|
+
# Waits for and returns the task result.
|
|
34
|
+
# @param timeout [Numeric, nil] maximum number of seconds to wait
|
|
35
|
+
# @return [Object] block result
|
|
36
|
+
# @raise [StandardError] re-raises an exception raised by the block
|
|
27
37
|
def value(timeout: nil)
|
|
28
38
|
wait(timeout: timeout)
|
|
29
39
|
raise @error if @error
|
|
@@ -31,20 +41,29 @@ module WGPU
|
|
|
31
41
|
@value
|
|
32
42
|
end
|
|
33
43
|
|
|
44
|
+
# Creates a task that transforms this task's result.
|
|
45
|
+
# @yieldparam value [Object] completed task result
|
|
46
|
+
# @return [AsyncTask] chained task
|
|
34
47
|
def then(&block)
|
|
35
48
|
AsyncTask.new do
|
|
36
49
|
block.call(value)
|
|
37
50
|
end
|
|
38
51
|
end
|
|
39
52
|
|
|
53
|
+
# Reports whether the task has finished.
|
|
54
|
+
# @return [Boolean]
|
|
40
55
|
def complete?
|
|
41
56
|
!@thread.alive?
|
|
42
57
|
end
|
|
43
58
|
|
|
59
|
+
# Reports whether the task is still running.
|
|
60
|
+
# @return [Boolean]
|
|
44
61
|
def pending?
|
|
45
62
|
@thread.alive?
|
|
46
63
|
end
|
|
47
64
|
|
|
65
|
+
# Returns the exception raised by the task, if any.
|
|
66
|
+
# @return [StandardError, nil]
|
|
48
67
|
def error
|
|
49
68
|
value
|
|
50
69
|
nil
|
|
@@ -4,21 +4,34 @@ module WGPU
|
|
|
4
4
|
class CommandBuffer
|
|
5
5
|
attr_reader :handle
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# Wraps an encoded native command buffer.
|
|
8
|
+
# @param handle [FFI::Pointer] native command buffer handle
|
|
9
|
+
# @param device [Device, nil] device whose callbacks the command buffer may use
|
|
10
|
+
def initialize(handle, device: nil)
|
|
8
11
|
@handle = handle
|
|
12
|
+
@device = device
|
|
9
13
|
@submitted = false
|
|
10
14
|
end
|
|
11
15
|
|
|
16
|
+
# Reports whether this command buffer has been submitted.
|
|
17
|
+
# @return [Boolean]
|
|
12
18
|
def submitted?
|
|
13
19
|
@submitted
|
|
14
20
|
end
|
|
15
21
|
|
|
22
|
+
# Marks this command buffer as submitted.
|
|
23
|
+
# @raise [CommandError] if it was already submitted
|
|
24
|
+
# @return [void]
|
|
16
25
|
def mark_submitted!
|
|
17
26
|
raise CommandError, "Command buffer has already been submitted" if @submitted
|
|
18
27
|
|
|
19
28
|
@submitted = true
|
|
20
29
|
end
|
|
21
30
|
|
|
31
|
+
# Releases the native command buffer handle.
|
|
32
|
+
#
|
|
33
|
+
# Calling this method more than once has no effect.
|
|
34
|
+
# @return [void]
|
|
22
35
|
def release
|
|
23
36
|
return if @handle.null?
|
|
24
37
|
Native.wgpuCommandBufferRelease(@handle)
|