wgpu 1.1.0 → 1.2.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 +4 -4
- data/CHANGELOG.md +48 -0
- data/README.md +26 -3
- data/docs/README.md +22 -0
- data/docs/api_coverage.md +132 -0
- data/docs/async.md +31 -0
- data/docs/bind_groups.md +25 -0
- data/docs/buffer_data.md +37 -0
- data/docs/command_encoding.md +24 -0
- data/docs/errors.md +40 -0
- data/docs/getting_started_compute.md +61 -0
- data/docs/getting_started_rendering.md +62 -0
- data/docs/installation.md +94 -0
- data/docs/pipeline_descriptors.md +38 -0
- data/docs/releasing.md +22 -0
- data/docs/resource_lifetime.md +94 -0
- data/docs/shaders.md +32 -0
- data/docs/texture_readback.md +19 -0
- data/docs/troubleshooting.md +48 -0
- data/docs/upgrading_wgpu_native.md +26 -0
- data/ext/wgpu/extconf.rb +10 -142
- data/lib/wgpu/commands/command_buffer.rb +11 -0
- data/lib/wgpu/commands/command_encoder.rb +65 -8
- data/lib/wgpu/commands/compute_pass.rb +10 -0
- data/lib/wgpu/commands/render_bundle_encoder.rb +10 -3
- data/lib/wgpu/commands/render_pass.rb +34 -8
- data/lib/wgpu/core/adapter.rb +36 -11
- data/lib/wgpu/core/async_waiter.rb +32 -4
- data/lib/wgpu/core/canvas_context.rb +0 -2
- data/lib/wgpu/core/device.rb +138 -42
- data/lib/wgpu/core/instance.rb +8 -4
- data/lib/wgpu/core/queue.rb +80 -49
- data/lib/wgpu/core/surface.rb +16 -17
- data/lib/wgpu/data_types.rb +67 -0
- data/lib/wgpu/descriptor_helpers.rb +39 -0
- data/lib/wgpu/error.rb +55 -0
- data/lib/wgpu/logging.rb +63 -0
- data/lib/wgpu/native/abi_verifier.rb +109 -0
- data/lib/wgpu/native/callbacks.rb +4 -1
- data/lib/wgpu/native/capabilities.rb +18 -2
- data/lib/wgpu/native/distribution.rb +113 -0
- data/lib/wgpu/native/enum_helper.rb +63 -0
- data/lib/wgpu/native/enums.rb +60 -8
- data/lib/wgpu/native/functions.rb +10 -10
- data/lib/wgpu/native/installer.rb +192 -0
- data/lib/wgpu/native/loader.rb +39 -21
- data/lib/wgpu/native_resource.rb +171 -0
- data/lib/wgpu/pipeline/bind_group.rb +12 -0
- data/lib/wgpu/pipeline/bind_group_layout.rb +91 -37
- data/lib/wgpu/pipeline/compute_pipeline.rb +28 -26
- data/lib/wgpu/pipeline/render_pipeline.rb +180 -68
- data/lib/wgpu/pipeline/shader_module.rb +50 -8
- data/lib/wgpu/resources/buffer.rb +148 -73
- data/lib/wgpu/resources/query_set.rb +14 -12
- data/lib/wgpu/resources/sampler.rb +36 -20
- data/lib/wgpu/resources/texture.rb +44 -42
- data/lib/wgpu/resources/texture_view.rb +11 -3
- data/lib/wgpu/texture_format.rb +82 -0
- data/lib/wgpu/version.rb +1 -1
- data/lib/wgpu/window.rb +8 -1
- data/lib/wgpu.rb +32 -0
- data/sig/wgpu.rbs +381 -0
- metadata +31 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 65be5bedee12b2389a8bf8fd8ec2dcb883d739852178dda17cae6b682a26663e
|
|
4
|
+
data.tar.gz: 584a76214478803361befac5011bb22df20034f4b9e18731be6685b69877eabd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cde23ae0101bf4e385adb161faca1221069ba15b275c066bcc1770aaab5f88e957bcaa7f8fcd06e1e711730fa75908fbee31e31140a06ba53c8acc55f4b634ed
|
|
7
|
+
data.tar.gz: d2d974230e674a282ca23a790eb16155730f2b5d9e97d0bc4df3c08822e862e0b17874c9c41b80155a5297bbda427c53ac35e77a7b455050ddb8c2da02031498
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
## 1.2.0 - 2026-07-23
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add typed buffer data, texture layout, shader diagnostics, GPU errors, and
|
|
15
|
+
synchronous timeout APIs.
|
|
16
|
+
- Add ensure-safe command pass blocks, auto pipeline layouts, resource guards,
|
|
17
|
+
leak diagnostics, and callback keepalive.
|
|
18
|
+
- Add checksum-verified wgpu-native installation and ABI verification.
|
|
19
|
+
- Add headless rendering pixel verification, 3D/array texture round-trips,
|
|
20
|
+
async/error/timestamp examples, and GPU CI coverage.
|
|
21
|
+
- Add block-scoped resource cleanup, native diagnostic logging, RBS
|
|
22
|
+
signatures, YARD documentation, and Trusted Publishing release automation.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Make the SDL3 Ruby gem optional for compute-only users.
|
|
27
|
+
- Validate descriptor shapes, enum values, buffer alignment, and texture
|
|
28
|
+
readback layout before native calls.
|
|
29
|
+
- Treat command buffers as consumed after submission and expose typed surface
|
|
30
|
+
acquisition status.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- Correct `CompareFunction` values and add missing v27 surface status and
|
|
35
|
+
vertex format enum entries discovered by header verification.
|
|
36
|
+
- Guard exported-but-unimplemented v27 functions before they can abort Ruby,
|
|
37
|
+
expose native extension feature names, and avoid v27 query-set double
|
|
38
|
+
removal after `destroy`.
|
|
39
|
+
|
|
40
|
+
## 1.1.0 - 2026-02-16
|
|
41
|
+
|
|
42
|
+
- Align bindings with wgpu v27 async ABI.
|
|
43
|
+
- Add shared async waiting for adapter/device.
|
|
44
|
+
- Migrate buffer/queue/shader async completion paths.
|
|
45
|
+
|
|
46
|
+
## 1.0.0 - 2026-02-15
|
|
47
|
+
|
|
48
|
+
- Initial release
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Ruby bindings for [WebGPU](https://www.w3.org/TR/webgpu/) via [wgpu-native](http
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- WebGPU object bindings using Ruby-FFI, with an explicit [API coverage matrix](docs/api_coverage.md)
|
|
8
8
|
- GPU compute shaders (GPGPU)
|
|
9
9
|
- Cross-platform support (macOS, Linux, Windows)
|
|
10
10
|
- Automatic wgpu-native library download on gem install
|
|
@@ -12,7 +12,7 @@ Ruby bindings for [WebGPU](https://www.w3.org/TR/webgpu/) via [wgpu-native](http
|
|
|
12
12
|
## Requirements
|
|
13
13
|
|
|
14
14
|
- Ruby 3.2+
|
|
15
|
-
- Supported platforms:
|
|
15
|
+
- Supported platforms (64-bit only):
|
|
16
16
|
- macOS (x86_64, arm64)
|
|
17
17
|
- Linux (x86_64, aarch64)
|
|
18
18
|
- Windows (x86_64)
|
|
@@ -38,6 +38,8 @@ gem install wgpu
|
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
The wgpu-native library is automatically downloaded from GitHub Releases during installation.
|
|
41
|
+
See [Installation and native artifacts](docs/installation.md) for supported
|
|
42
|
+
artifacts, cache behavior, manual installation, and troubleshooting.
|
|
41
43
|
|
|
42
44
|
### Custom wgpu-native Build
|
|
43
45
|
|
|
@@ -128,7 +130,8 @@ puts output_data[0, 10].inspect
|
|
|
128
130
|
|
|
129
131
|
## Examples
|
|
130
132
|
|
|
131
|
-
See the `examples/`
|
|
133
|
+
See the [`examples/` guide](examples/README.md) for prerequisites, expected
|
|
134
|
+
results, and more complete examples:
|
|
132
135
|
|
|
133
136
|
Compute examples:
|
|
134
137
|
- `01_adapter_info.rb` - Query GPU adapter information
|
|
@@ -138,6 +141,13 @@ Compute examples:
|
|
|
138
141
|
- `05_image_blur.rb` - Image processing with box filter
|
|
139
142
|
- `06_parallel_reduction.rb` - Parallel sum reduction
|
|
140
143
|
|
|
144
|
+
Headless validation examples:
|
|
145
|
+
|
|
146
|
+
- `12_headless_render.rb` - Offscreen triangle and pixel verification
|
|
147
|
+
- `13_error_handling.rb` - Typed, labeled validation errors
|
|
148
|
+
- `14_async_map.rb` - Async mapping through a forced GC cycle
|
|
149
|
+
- `15_timestamp_query.rb` - Feature-gated timestamp query resolution
|
|
150
|
+
|
|
141
151
|
Rendering examples (SDL3):
|
|
142
152
|
- `07_triangle.rb` - Basic triangle rendering
|
|
143
153
|
- `08_colored_quad.rb` - Indexed colored quad rendering
|
|
@@ -156,8 +166,14 @@ Rendering examples require SDL3 on your system:
|
|
|
156
166
|
```bash
|
|
157
167
|
# macOS
|
|
158
168
|
brew install sdl3
|
|
169
|
+
|
|
170
|
+
# Gemfile
|
|
171
|
+
gem "sdl3", "~> 1.0"
|
|
159
172
|
```
|
|
160
173
|
|
|
174
|
+
The core `wgpu` gem does not depend on SDL3. Only code that explicitly requires
|
|
175
|
+
`wgpu/window` needs the optional Ruby gem and system library.
|
|
176
|
+
|
|
161
177
|
## API Overview
|
|
162
178
|
|
|
163
179
|
### Core Objects
|
|
@@ -207,6 +223,13 @@ bundle install
|
|
|
207
223
|
bundle exec rake spec
|
|
208
224
|
```
|
|
209
225
|
|
|
226
|
+
See [Resource lifetime](docs/resource_lifetime.md) before building long-running
|
|
227
|
+
applications, and use the [API coverage matrix](docs/api_coverage.md) to check
|
|
228
|
+
the current relationship to the WebGPU specification. The
|
|
229
|
+
[documentation index](docs/README.md) links the compute/rendering guides,
|
|
230
|
+
buffer/texture rules, async and error handling, troubleshooting, and release
|
|
231
|
+
operations.
|
|
232
|
+
|
|
210
233
|
## Contributing
|
|
211
234
|
|
|
212
235
|
Bug reports and pull requests are welcome on GitHub at https://github.com/ydah/wgpu-ruby.
|
data/docs/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
- [Getting started: compute](getting_started_compute.md)
|
|
4
|
+
- [Getting started: rendering](getting_started_rendering.md)
|
|
5
|
+
- [API coverage](api_coverage.md)
|
|
6
|
+
- [Installation and native artifacts](installation.md)
|
|
7
|
+
- [Resource lifetime](resource_lifetime.md)
|
|
8
|
+
- [Async operations and polling](async.md)
|
|
9
|
+
- [GPU errors](errors.md)
|
|
10
|
+
- [Buffer data](buffer_data.md)
|
|
11
|
+
- [Texture readback](texture_readback.md)
|
|
12
|
+
- [Shaders and diagnostics](shaders.md)
|
|
13
|
+
- [Bind groups and layouts](bind_groups.md)
|
|
14
|
+
- [Pipeline descriptors](pipeline_descriptors.md)
|
|
15
|
+
- [Command encoding](command_encoding.md)
|
|
16
|
+
- [Troubleshooting](troubleshooting.md)
|
|
17
|
+
- [Upgrading wgpu-native](upgrading_wgpu_native.md)
|
|
18
|
+
- [Releasing](releasing.md)
|
|
19
|
+
|
|
20
|
+
Generated API documentation is built with `bundle exec yard doc`. Static API
|
|
21
|
+
signatures live in `sig/wgpu.rbs` and validate with
|
|
22
|
+
`bundle exec rbs -I sig validate`.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# WebGPU API coverage
|
|
2
|
+
|
|
3
|
+
This page records the public Ruby API implemented by wgpu-ruby 1.1 and its
|
|
4
|
+
relationship to the WebGPU object model. It is a baseline, not a claim that
|
|
5
|
+
every WebGPU feature is implemented.
|
|
6
|
+
|
|
7
|
+
The WebGPU names below follow the
|
|
8
|
+
[WebGPU Editor's Draft](https://gpuweb.github.io/gpuweb/). Browser-only APIs
|
|
9
|
+
such as DOM canvas discovery and external image import are intentionally
|
|
10
|
+
called out instead of being hidden by a general "complete" claim.
|
|
11
|
+
|
|
12
|
+
Legend:
|
|
13
|
+
|
|
14
|
+
- ✅: a public Ruby wrapper exists for the interface's core operations
|
|
15
|
+
- ◐: some operations or the returned data shape are implemented
|
|
16
|
+
- ❌: no public wrapper exists
|
|
17
|
+
- N/A: browser integration that does not map directly to a native Ruby binding
|
|
18
|
+
|
|
19
|
+
## Object and supporting-interface coverage
|
|
20
|
+
|
|
21
|
+
| WebGPU interface | Ruby API | Status | Notes |
|
|
22
|
+
|---|---|:---:|---|
|
|
23
|
+
| `GPU` | `WGPU::Instance` | ◐ | Native entry point; adapter requests and event processing are exposed. Browser canvas-format and WGSL-language-feature queries are not. |
|
|
24
|
+
| `GPUAdapter` | `WGPU::Adapter` | ✅ | Adapter info, features, limits, and device requests are exposed. |
|
|
25
|
+
| `GPUAdapterInfo` | `Hash` from `Adapter#info` | ◐ | Returned as a Ruby hash rather than a value object. |
|
|
26
|
+
| `GPUBindGroup` | `WGPU::BindGroup` | ✅ | |
|
|
27
|
+
| `GPUBindGroupLayout` | `WGPU::BindGroupLayout` | ✅ | |
|
|
28
|
+
| `GPUBuffer` | `WGPU::Buffer` | ✅ | Mapping, destruction, and Ruby data helpers are included. |
|
|
29
|
+
| `GPUCanvasContext` | `WGPU::CanvasContext` | ◐ | Native-window presentation wrapper; no DOM `canvas` attribute. |
|
|
30
|
+
| `GPUCommandBuffer` | `WGPU::CommandBuffer` | ✅ | |
|
|
31
|
+
| `GPUCommandEncoder` | `WGPU::CommandEncoder` | ✅ | Buffer/texture copies, query resolution, timestamps, and debug markers are exposed. |
|
|
32
|
+
| `GPUCompilationInfo` | `ShaderModule#get_compilation_info` + `CompilationMessage` | ◐ | Typed diagnostics are ready, but pinned wgpu-native v27 exports only a panic stub; calls fail safely in Ruby. |
|
|
33
|
+
| `GPUCompilationMessage` | `WGPU::CompilationMessage` | ✅ | Message, type, line, column, offset, and length are typed fields. |
|
|
34
|
+
| `GPUComputePassEncoder` | `WGPU::ComputePass` | ✅ | |
|
|
35
|
+
| `GPUComputePipeline` | `WGPU::ComputePipeline` | ✅ | Auto layout and override constants are accepted. |
|
|
36
|
+
| `GPUDevice` | `WGPU::Device` | ◐ | Resource creation, error scopes, polling, features, and limits are exposed; device-lost and uncaptured-error subscriptions are not. |
|
|
37
|
+
| `GPUDeviceLostInfo` | — | ❌ | |
|
|
38
|
+
| `GPUError` | error hashes and `WGPU::Error` subclasses | ◐ | There is no common `GPUError` value object yet. |
|
|
39
|
+
| `GPUExternalTexture` | — | ❌ | Browser video/external-texture import is not exposed. |
|
|
40
|
+
| `GPUInternalError` | — | ❌ | |
|
|
41
|
+
| `GPUOutOfMemoryError` | — | ❌ | |
|
|
42
|
+
| `GPUPipelineError` | `WGPU::PipelineError` | ◐ | Ruby exception exists; native pipeline error data is not a value object. |
|
|
43
|
+
| `GPUPipelineLayout` | `WGPU::PipelineLayout` | ✅ | |
|
|
44
|
+
| `GPUQuerySet` | `WGPU::QuerySet` | ✅ | |
|
|
45
|
+
| `GPUQueue` | `WGPU::Queue` | ◐ | Submission, writes, work-done notification, and readback helpers are exposed; browser `copyExternalImageToTexture` is not. |
|
|
46
|
+
| `GPURenderBundle` | `WGPU::RenderBundle` | ✅ | |
|
|
47
|
+
| `GPURenderBundleEncoder` | `WGPU::RenderBundleEncoder` | ✅ | |
|
|
48
|
+
| `GPURenderPassEncoder` | `WGPU::RenderPass` | ✅ | |
|
|
49
|
+
| `GPURenderPipeline` | `WGPU::RenderPipeline` | ✅ | Auto layout and override constants are accepted. |
|
|
50
|
+
| `GPUSampler` | `WGPU::Sampler` | ✅ | |
|
|
51
|
+
| `GPUShaderModule` | `WGPU::ShaderModule` | ✅ | WGSL and wgpu-native SPIR-V/GLSL extensions are supported. |
|
|
52
|
+
| `GPUSupportedFeatures` | `Array<Symbol>` | ◐ | Represented as a Ruby array. |
|
|
53
|
+
| `GPUSupportedLimits` | `Hash` | ◐ | Represented as a Ruby hash. |
|
|
54
|
+
| `GPUTexture` | `WGPU::Texture` | ✅ | |
|
|
55
|
+
| `GPUTextureView` | `WGPU::TextureView` | ✅ | |
|
|
56
|
+
| `GPUUncapturedErrorEvent` | — | ❌ | |
|
|
57
|
+
| `GPUValidationError` | class-specific Ruby exceptions | ◐ | Validation errors are translated during resource creation. |
|
|
58
|
+
| `WGSLLanguageFeatures` | — | ❌ | |
|
|
59
|
+
| `GPUObjectBase` | `#handle`, labels on descriptors | ◐ | Common released-state behavior is not yet centralized. |
|
|
60
|
+
| `GPUPipelineBase` | `#get_bind_group_layout` | ✅ | Implemented by compute and render pipelines. |
|
|
61
|
+
| `GPUCommandsMixin` | `WGPU::CommandEncoder` | ✅ | |
|
|
62
|
+
| `GPUDebugCommandsMixin` | encoder/pass debug methods | ✅ | |
|
|
63
|
+
| `GPUBindingCommandsMixin` | pass/bundle binding methods | ✅ | |
|
|
64
|
+
| `GPURenderCommandsMixin` | render pass/bundle draw methods | ✅ | |
|
|
65
|
+
| `NavigatorGPU` | — | N/A | Browser-only discovery API. |
|
|
66
|
+
|
|
67
|
+
Descriptor dictionaries are represented as Ruby keyword arguments and nested
|
|
68
|
+
hashes, then converted to the matching `WGPU*Descriptor` FFI structs. The
|
|
69
|
+
implemented object APIs cover buffer, texture/view, sampler, bind group/layout,
|
|
70
|
+
pipeline layout, shader module, compute/render pipeline, command/pass/bundle,
|
|
71
|
+
query set, surface, and device/adapter/instance descriptors. Browser-only
|
|
72
|
+
descriptors (`GPUExternalTextureDescriptor`, external image copy descriptors,
|
|
73
|
+
and DOM canvas ownership) are not implemented.
|
|
74
|
+
|
|
75
|
+
## Public Ruby API
|
|
76
|
+
|
|
77
|
+
Constructors are omitted where objects are normally returned by another
|
|
78
|
+
wrapper. `handle` readers are listed once here as a common escape hatch for
|
|
79
|
+
native interoperation.
|
|
80
|
+
|
|
81
|
+
| Ruby class | Public class methods | Public instance methods |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `WGPU::Instance` | — | `request_adapter`, `request_adapter_async`, `enumerate_adapters`, `enumerate_adapters_async`, `process_events`, `get_canvas_context`, `release`, `handle` |
|
|
84
|
+
| `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` |
|
|
86
|
+
| `WGPU::Queue` | — | `submit`, `write_buffer`, `write_texture`, `read_buffer`, `read_texture`, `on_submitted_work_done`, `on_submitted_work_done_async`, `release`, `handle` |
|
|
87
|
+
| `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
|
+
| `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`, `read_mapped_floats`, `map_state`, `size`, `usage`, `destroy`, `release`, `handle` |
|
|
90
|
+
| `WGPU::BufferMappedRange` | — | `read_bytes`, `write_bytes`, `read_floats`, `write_floats` |
|
|
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::TextureView` | `from_handle` | `texture`, `size`, `release`, `handle` |
|
|
93
|
+
| `WGPU::Sampler` | — | `release`, `handle` |
|
|
94
|
+
| `WGPU::QuerySet` | — | `count`, `type`, `destroy`, `release`, `handle` |
|
|
95
|
+
| `WGPU::ShaderModule` | — | `get_compilation_info`, `get_compilation_info_async`, `release`, `handle` |
|
|
96
|
+
| `WGPU::BindGroupLayout` | `from_handle` | `release`, `handle` |
|
|
97
|
+
| `WGPU::BindGroup` | — | `release`, `handle` |
|
|
98
|
+
| `WGPU::PipelineLayout` | — | `release`, `handle` |
|
|
99
|
+
| `WGPU::ComputePipeline` | — | `get_bind_group_layout`, `release`, `handle` |
|
|
100
|
+
| `WGPU::RenderPipeline` | — | `get_bind_group_layout`, `release`, `handle` |
|
|
101
|
+
| `WGPU::CommandEncoder` | — | `begin_compute_pass`, `begin_render_pass`, copy/clear/query/debug methods, `finish`, `release`, `handle` |
|
|
102
|
+
| `WGPU::CommandBuffer` | — | `release`, `handle` |
|
|
103
|
+
| `WGPU::ComputePass` | — | pipeline/bind-group setup, dispatch/debug methods, `end_pass`, `end`, `release`, `handle` |
|
|
104
|
+
| `WGPU::RenderPass` | — | pipeline/bind-group/buffer setup, draw/state/query/debug methods, `end_pass`, `end`, `release`, `handle` |
|
|
105
|
+
| `WGPU::RenderBundleEncoder` | — | pipeline/bind-group/buffer setup, draw/debug methods, `finish`, `release`, `handle` |
|
|
106
|
+
| `WGPU::RenderBundle` | — | `release`, `handle` |
|
|
107
|
+
| `WGPU::AsyncTask` | — | `wait`, `value`, `then`, `complete?`, `pending?`, `error` |
|
|
108
|
+
| `WGPU::Window::SDLWindow` | — | `create_surface`, event/key helpers, `drawable_size`, `close` |
|
|
109
|
+
|
|
110
|
+
## Examples as executable specifications
|
|
111
|
+
|
|
112
|
+
| Example | Purpose | Principal wgpu-ruby APIs exercised |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `01_adapter_info.rb` | Adapter discovery and reporting | `Instance#enumerate_adapters`, `#request_adapter`, adapter info/features/limits |
|
|
115
|
+
| `02_compute_basic.rb` | Minimal storage-buffer compute | buffer mapping, bind groups/layouts, compute pipeline/pass, submit, readback |
|
|
116
|
+
| `03_buffer_operations.rb` | Buffer write, copy, map, and read | `create_buffer_with_data`, `Queue#write_buffer`, buffer copy, `map_sync` |
|
|
117
|
+
| `04_matrix_multiply.rb` | Multi-buffer compute | typed byte upload, storage/uniform bindings, workgroup dispatch, readback |
|
|
118
|
+
| `05_image_blur.rb` | 2D compute workload | multiple storage buffers, 2D dispatch, readback |
|
|
119
|
+
| `06_parallel_reduction.rb` | Iterative compute reduction | repeated dispatch/submission, `Queue#write_buffer`, readback |
|
|
120
|
+
| `07_triangle.rb` | Basic surface rendering | SDL surface setup, render pipeline/pass, draw, present |
|
|
121
|
+
| `08_colored_quad.rb` | Indexed vertex rendering | vertex/index buffers, render pipeline/pass, indexed draw |
|
|
122
|
+
| `09_clear_color.rb` | Per-frame clear and presentation | current texture/view, render pass clear, submit, present |
|
|
123
|
+
| `10_textured_quad.rb` | Texture sampling | texture upload/view, sampler, texture bind group, draw |
|
|
124
|
+
| `11_rotating_cube.rb` | Depth-tested 3D rendering | vertex/index/uniform/depth resources, pipeline, per-frame uniform write, draw |
|
|
125
|
+
| `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 | `BufferError`, operation/label context |
|
|
127
|
+
| `14_async_map.rb` | Async map and callback retention | `map_async`, `AsyncTask`, typed mapped reads, GC stress |
|
|
128
|
+
| `15_timestamp_query.rb` | Feature-gated GPU timestamps | timestamp pass writes, query resolution, u64 readback |
|
|
129
|
+
|
|
130
|
+
When a public API changes, the corresponding example is part of the acceptance
|
|
131
|
+
test surface. Compute and headless examples are automated in GPU CI; SDL
|
|
132
|
+
window examples remain manual integration checks.
|
data/docs/async.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Async operations and polling
|
|
2
|
+
|
|
3
|
+
wgpu-native v27 returns futures for adapter/device requests, buffer mapping,
|
|
4
|
+
error scopes, compilation info, and queue completion. wgpu-ruby keeps callback
|
|
5
|
+
objects alive until each operation finishes and selects the best available
|
|
6
|
+
progress mechanism:
|
|
7
|
+
|
|
8
|
+
1. zero-time `wgpuInstanceWaitAny` polling;
|
|
9
|
+
2. `Instance#process_events`;
|
|
10
|
+
3. `Device#poll`;
|
|
11
|
+
4. a short Ruby sleep when native polling cannot block.
|
|
12
|
+
|
|
13
|
+
wgpu-native v27 aborts when its unsupported timed-WaitAny instance feature is
|
|
14
|
+
requested, so wgpu-ruby deliberately leaves that feature disabled. The Ruby
|
|
15
|
+
poll interval defaults to 1 ms and can be adjusted with
|
|
16
|
+
`WGPU::AsyncWaiter.poll_interval=`.
|
|
17
|
+
|
|
18
|
+
That release also exports `wgpuBufferGetMapState` as an unimplemented panic
|
|
19
|
+
stub. `Buffer#map_state` is maintained by wgpu-ruby as `:unmapped`,
|
|
20
|
+
`:pending`, or `:mapped` while map operations run.
|
|
21
|
+
|
|
22
|
+
Synchronous adapter/device requests, `Buffer#map_sync`,
|
|
23
|
+
`Device#pop_error_scope`, and `Queue#on_submitted_work_done` accept
|
|
24
|
+
`timeout:` in seconds. The default `nil` preserves the prior unbounded wait.
|
|
25
|
+
Expiry raises `WGPU::TimeoutError`.
|
|
26
|
+
|
|
27
|
+
`*_async` methods return `WGPU::AsyncTask`, a convenience wrapper backed by a
|
|
28
|
+
Ruby Thread. Concurrent operations on the same WebGPU object are not
|
|
29
|
+
guaranteed safe. Prefer synchronous operations or external serialization when
|
|
30
|
+
ordering matters. Rendering event loops should call `instance.process_events`
|
|
31
|
+
or `device.poll` regularly.
|
data/docs/bind_groups.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Bind groups and pipeline layouts
|
|
2
|
+
|
|
3
|
+
Each bind group layout entry requires `binding:`, `visibility:`, and exactly one
|
|
4
|
+
resource variant:
|
|
5
|
+
|
|
6
|
+
| Variant | Keys | Defaults |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `buffer:` | `type`, `has_dynamic_offset`, `min_binding_size` | `:storage`, `false`, `0` |
|
|
9
|
+
| `sampler:` | `type` | `:filtering` |
|
|
10
|
+
| `texture:` | `sample_type`, `view_dimension`, `multisampled` | `:float`, `:d2`, `false` |
|
|
11
|
+
| `storage_texture:` | `format` (required), `access`, `view_dimension` | `:write_only`, `:d2` |
|
|
12
|
+
|
|
13
|
+
`visibility:` accepts one shader-stage Symbol, an integer bitmask, or an Array
|
|
14
|
+
such as `%i[vertex fragment]`. Unknown keys warn; missing required keys and
|
|
15
|
+
conflicting resource variants raise `ArgumentError` before FFI.
|
|
16
|
+
|
|
17
|
+
A bind group entry requires `binding:` and exactly one of `buffer:`,
|
|
18
|
+
`sampler:`, or `texture_view:`. Buffer entries may also include `offset:` and
|
|
19
|
+
`size:`.
|
|
20
|
+
|
|
21
|
+
Compute and render pipelines accept `layout: :auto` (also `"auto"` or `nil`).
|
|
22
|
+
Call `pipeline.get_bind_group_layout(index)` to obtain an inferred layout.
|
|
23
|
+
That returned wrapper owns a native reference; the caller must release it.
|
|
24
|
+
`examples/02_compute_basic.rb` demonstrates this path. Explicit
|
|
25
|
+
`PipelineLayout` objects remain fully supported.
|
data/docs/buffer_data.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Buffer data
|
|
2
|
+
|
|
3
|
+
Ruby Arrays passed to buffer APIs use 32-bit floats by default, preserving the
|
|
4
|
+
original wgpu-ruby behavior. Pass `type:` to use another WebGPU scalar
|
|
5
|
+
representation:
|
|
6
|
+
|
|
7
|
+
| `type:` | Encoding | Bytes |
|
|
8
|
+
|---|---|---:|
|
|
9
|
+
| `:f32` | IEEE 754 float | 4 |
|
|
10
|
+
| `:f64` | IEEE 754 double | 8 |
|
|
11
|
+
| `:u32` | unsigned integer | 4 |
|
|
12
|
+
| `:i32` | signed integer | 4 |
|
|
13
|
+
| `:u16` | unsigned integer | 2 |
|
|
14
|
+
| `:u8` | unsigned integer | 1 |
|
|
15
|
+
|
|
16
|
+
The keyword is accepted by `Device#create_buffer_with_data`, `Buffer#write`,
|
|
17
|
+
`Buffer#write_mapped`, `Queue#write_buffer`, and `Queue#write_texture`.
|
|
18
|
+
Strings remain raw bytes and `FFI::Pointer` values remain unconverted.
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
buffer = device.create_buffer_with_data(
|
|
22
|
+
data: [1, 2, 3, 4],
|
|
23
|
+
type: :u32,
|
|
24
|
+
usage: %i[storage copy_src]
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
queue.write_buffer(buffer, 0, [10, 20], type: :u32)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`BufferMappedRange#read` and `#write` expose the same `type:` keyword. The
|
|
31
|
+
existing `read_floats` / `write_floats` methods remain aliases for the `:f32`
|
|
32
|
+
path. Typed convenience pairs are also available for float64, uint32, int32,
|
|
33
|
+
uint16, and uint8.
|
|
34
|
+
|
|
35
|
+
WebGPU alignment errors are reported before entering FFI: queue write offsets
|
|
36
|
+
and sizes must be multiples of 4 bytes; mapped offsets must be multiples of 8
|
|
37
|
+
bytes and mapped sizes multiples of 4 bytes.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Command encoding
|
|
2
|
+
|
|
3
|
+
Compute and render passes support both the original explicit form and an
|
|
4
|
+
ensure-safe block form:
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
encoder.begin_compute_pass do |pass|
|
|
8
|
+
pass.set_pipeline(pipeline)
|
|
9
|
+
pass.dispatch_workgroups(4)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
encoder.begin_render_pass(color_attachments: attachments) do |pass|
|
|
13
|
+
pass.set_pipeline(pipeline)
|
|
14
|
+
pass.draw(3)
|
|
15
|
+
end
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The block form always ends and releases the pass, including when the block
|
|
19
|
+
raises, and returns the block's value. The explicit form remains compatible:
|
|
20
|
+
call `end_pass` (or `end`) and `release` yourself.
|
|
21
|
+
|
|
22
|
+
Only one pass may be active on a command encoder. `CommandEncoder#finish`
|
|
23
|
+
raises `WGPU::CommandError` while a pass is still active instead of handing
|
|
24
|
+
invalid state to wgpu-native. Calling `end_pass` more than once is harmless.
|
data/docs/errors.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# GPU errors
|
|
2
|
+
|
|
3
|
+
`Device#pop_error_scope` keeps its v1.x Hash return value. New code may call
|
|
4
|
+
`pop_error_scope_typed`, which returns a `WGPU::GPUError` or `nil` for
|
|
5
|
+
`:no_error`.
|
|
6
|
+
|
|
7
|
+
`GPUError` has `type` and `message` readers, `to_h`, and `raise!`. `raise!`
|
|
8
|
+
maps WebGPU error types to `ValidationError`, `OutOfMemoryError`,
|
|
9
|
+
`InternalError`, or `DeviceLostError`.
|
|
10
|
+
|
|
11
|
+
Device-level callbacks can be installed after device creation:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
device.on_uncaptured_error do |error|
|
|
15
|
+
warn "#{error.type}: #{error.message}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
device.on_device_lost do |reason, message|
|
|
19
|
+
warn "#{reason}: #{message}"
|
|
20
|
+
end
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
wgpu-ruby installs native dispatch callbacks when requesting the device and
|
|
24
|
+
keeps them alive until release. User handlers can therefore be replaced without
|
|
25
|
+
recreating the native device. Without a handler, uncaptured errors and
|
|
26
|
+
unexpected device loss are written as warnings. Exceptions raised by a user
|
|
27
|
+
handler are caught at the FFI boundary and reported as warnings rather than
|
|
28
|
+
escaping through native callback code.
|
|
29
|
+
|
|
30
|
+
wgpu-native's process-wide diagnostic log can be routed into an application:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
WGPU.on_log do |level, message|
|
|
34
|
+
MyLogger.public_send(level == :warn ? :warn : :debug, message)
|
|
35
|
+
end
|
|
36
|
+
WGPU.log_level = :info
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The callback is retained for the process lifetime (or until replaced), so a
|
|
40
|
+
Ruby GC cycle cannot invalidate the native callback pointer.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Getting started: compute
|
|
2
|
+
|
|
3
|
+
Compute workloads need Ruby 3.2+, the `wgpu` gem, and a supported GPU driver.
|
|
4
|
+
They do not need SDL3.
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
require "wgpu"
|
|
8
|
+
|
|
9
|
+
instance = WGPU::Instance.new
|
|
10
|
+
adapter = instance.request_adapter(timeout: 10)
|
|
11
|
+
device = adapter.request_device(timeout: 10)
|
|
12
|
+
|
|
13
|
+
shader = device.create_shader_module(
|
|
14
|
+
code: <<~WGSL,
|
|
15
|
+
@group(0) @binding(0) var<storage, read_write> values: array<u32>;
|
|
16
|
+
|
|
17
|
+
@compute @workgroup_size(4)
|
|
18
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
19
|
+
values[id.x] *= 2u;
|
|
20
|
+
}
|
|
21
|
+
WGSL
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
buffer = device.create_buffer_with_data(
|
|
25
|
+
data: [1, 2, 3, 4],
|
|
26
|
+
type: :u32,
|
|
27
|
+
usage: %i[storage copy_src copy_dst]
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
pipeline = device.create_compute_pipeline(
|
|
31
|
+
layout: :auto,
|
|
32
|
+
compute: { module: shader }
|
|
33
|
+
)
|
|
34
|
+
layout = pipeline.get_bind_group_layout(0)
|
|
35
|
+
group = device.create_bind_group(
|
|
36
|
+
layout: layout,
|
|
37
|
+
entries: [{ binding: 0, buffer: buffer }]
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
encoder = device.create_command_encoder
|
|
41
|
+
encoder.begin_compute_pass do |pass|
|
|
42
|
+
pass.set_pipeline(pipeline)
|
|
43
|
+
pass.set_bind_group(0, group)
|
|
44
|
+
pass.dispatch_workgroups(1)
|
|
45
|
+
end
|
|
46
|
+
command_buffer = encoder.finish
|
|
47
|
+
device.queue.submit(command_buffer)
|
|
48
|
+
|
|
49
|
+
bytes = device.queue.read_buffer(buffer)
|
|
50
|
+
puts WGPU::DataTypes.unpack(bytes, type: :u32).inspect
|
|
51
|
+
|
|
52
|
+
[command_buffer, encoder, group, layout, pipeline, buffer, shader].each(&:release)
|
|
53
|
+
device.release
|
|
54
|
+
adapter.release
|
|
55
|
+
instance.release
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The full executable version is
|
|
59
|
+
[`examples/02_compute_basic.rb`](../examples/02_compute_basic.rb). For
|
|
60
|
+
production code, put resource release in `ensure` blocks and register
|
|
61
|
+
`Device#on_uncaptured_error` during startup.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Getting started: rendering
|
|
2
|
+
|
|
3
|
+
Rendering adds a window-system integration. The bundled helper uses SDL3, but
|
|
4
|
+
surfaces themselves are independent of SDL and may be created from native
|
|
5
|
+
Metal, Win32, Xlib, or Wayland handles.
|
|
6
|
+
|
|
7
|
+
Add the optional dependency:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem "wgpu"
|
|
11
|
+
gem "sdl3", "~> 1.0"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Install the SDL3 system library, then load the helper explicitly:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
require "wgpu"
|
|
18
|
+
require "wgpu/window"
|
|
19
|
+
|
|
20
|
+
window = WGPU::Window::SDLWindow.new(
|
|
21
|
+
title: "WebGPU",
|
|
22
|
+
width: 800,
|
|
23
|
+
height: 600
|
|
24
|
+
)
|
|
25
|
+
instance = WGPU::Instance.new
|
|
26
|
+
surface = window.create_surface(instance)
|
|
27
|
+
adapter = instance.request_adapter(compatible_surface: surface)
|
|
28
|
+
device = adapter.request_device
|
|
29
|
+
|
|
30
|
+
format = surface.capabilities(adapter).fetch(:formats).first
|
|
31
|
+
width, height = window.drawable_size
|
|
32
|
+
surface.configure(
|
|
33
|
+
device: device,
|
|
34
|
+
format: format,
|
|
35
|
+
width: width,
|
|
36
|
+
height: height,
|
|
37
|
+
present_mode: :fifo
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For every frame, acquire `surface.current_texture`, create a view, encode and
|
|
42
|
+
submit a render pass, call `surface.present`, and release frame-local objects.
|
|
43
|
+
The returned texture exposes `surface_status` as `:success_optimal` or
|
|
44
|
+
`:success_suboptimal`. Acquisition failures raise
|
|
45
|
+
`WGPU::SurfaceAcquisitionError`; inspect its `status` reader for `:timeout`,
|
|
46
|
+
`:outdated`, `:lost`, `:out_of_memory`, or `:device_lost`. Reconfigure on
|
|
47
|
+
`:outdated`/`:lost` after re-reading the drawable size.
|
|
48
|
+
When `drawable_size` changes, configure the surface again with positive pixel
|
|
49
|
+
dimensions. Do not render while a minimized window reports zero dimensions.
|
|
50
|
+
|
|
51
|
+
`Surface` is the low-level native-window API. `CanvasContext` owns and
|
|
52
|
+
delegates to a surface while retaining the familiar configure/acquire/present
|
|
53
|
+
shape. Integrations other than SDL3 can pass an `FFI::Pointer` obtained from
|
|
54
|
+
their window toolkit to `Surface.from_metal_layer`,
|
|
55
|
+
`Surface.from_windows_hwnd`, `Surface.from_xlib_window`, or
|
|
56
|
+
`Surface.from_wayland_surface`. The application must keep the corresponding
|
|
57
|
+
native window/display/layer alive longer than the surface; wgpu-ruby does not
|
|
58
|
+
take ownership of those platform objects.
|
|
59
|
+
|
|
60
|
+
[`examples/09_clear_color.rb`](../examples/09_clear_color.rb) is the smallest
|
|
61
|
+
resizable render loop. The other rendering examples cover vertex/index
|
|
62
|
+
buffers, textures, bind groups, depth testing, and uniform updates.
|