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
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Installation and native artifacts
|
|
2
|
+
|
|
3
|
+
wgpu-ruby is a Ruby-FFI binding. Gem installation downloads a prebuilt
|
|
4
|
+
wgpu-native library; it does not compile a C extension.
|
|
5
|
+
|
|
6
|
+
## Supported runtime
|
|
7
|
+
|
|
8
|
+
- Ruby 3.2 or newer
|
|
9
|
+
- 64-bit macOS x86_64/arm64
|
|
10
|
+
- 64-bit Linux glibc x86_64/aarch64
|
|
11
|
+
- 64-bit Windows x86_64 with the MSVC wgpu-native artifact
|
|
12
|
+
|
|
13
|
+
Linux musl/Alpine and 32-bit runtimes do not have prebuilt artifacts. They may
|
|
14
|
+
still work with a compatible custom library supplied through `WGPU_LIB_PATH`.
|
|
15
|
+
|
|
16
|
+
## Pinned release and artifacts
|
|
17
|
+
|
|
18
|
+
The binding targets wgpu-native `v27.0.4.0` from:
|
|
19
|
+
|
|
20
|
+
`https://github.com/gfx-rs/wgpu-native/releases/download/v27.0.4.0/`
|
|
21
|
+
|
|
22
|
+
| Ruby platform | Archive | Library |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| `x86_64-linux` | `wgpu-linux-x86_64-release.zip` | `libwgpu_native.so` |
|
|
25
|
+
| `aarch64-linux` | `wgpu-linux-aarch64-release.zip` | `libwgpu_native.so` |
|
|
26
|
+
| `x86_64-darwin` | `wgpu-macos-x86_64-release.zip` | `libwgpu_native.dylib` |
|
|
27
|
+
| `arm64-darwin` | `wgpu-macos-aarch64-release.zip` | `libwgpu_native.dylib` |
|
|
28
|
+
| Windows `mingw`/`mswin` | `wgpu-windows-x86_64-msvc-release.zip` | `wgpu_native.dll` |
|
|
29
|
+
|
|
30
|
+
## Resolution order
|
|
31
|
+
|
|
32
|
+
1. If `WGPU_LIB_PATH` is set, installation skips the download and runtime
|
|
33
|
+
loading uses that exact file.
|
|
34
|
+
2. Otherwise the runtime uses the first configured cache location:
|
|
35
|
+
`WGPU_CACHE_DIR`, `XDG_CACHE_HOME`, then the operating-system default.
|
|
36
|
+
3. The legacy `~/.cache/wgpu-ruby/v27.0.4.0/lib/` location is also searched so
|
|
37
|
+
an existing installation does not require another download.
|
|
38
|
+
4. If the cached library is absent, reinstall the gem or run
|
|
39
|
+
`bundle exec ruby ext/wgpu/extconf.rb` from a source checkout.
|
|
40
|
+
|
|
41
|
+
Download uses `curl` when available, then Ruby `Net::HTTP`. Extraction uses
|
|
42
|
+
`rubyzip`, then PowerShell `Expand-Archive` on Windows, then `unzip`.
|
|
43
|
+
|
|
44
|
+
## Manual installation
|
|
45
|
+
|
|
46
|
+
1. Download the archive for the target above.
|
|
47
|
+
2. Extract it and locate the library in the archive's `lib` directory.
|
|
48
|
+
3. Set `WGPU_LIB_PATH` to the absolute library path before starting Ruby:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
export WGPU_LIB_PATH=/opt/wgpu-native/lib/libwgpu_native.so
|
|
52
|
+
bundle exec ruby -Ilib -e 'require "wgpu"; puts WGPU::Native.library_path'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
PowerShell:
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
$env:WGPU_LIB_PATH = "C:\wgpu-native\lib\wgpu_native.dll"
|
|
59
|
+
bundle exec ruby -Ilib -e 'require "wgpu"; puts WGPU::Native.library_path'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The library must match the process architecture and the v27 ABI expected by
|
|
63
|
+
this gem.
|
|
64
|
+
|
|
65
|
+
## Environment variables
|
|
66
|
+
|
|
67
|
+
| Variable | Meaning |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `WGPU_LIB_PATH` | Absolute path to a custom wgpu-native shared library; highest priority. |
|
|
70
|
+
| `WGPU_CACHE_DIR` | wgpu-ruby cache root override. The version directory is created directly beneath it. |
|
|
71
|
+
| `XDG_CACHE_HOME` | Cache base on Unix when `WGPU_CACHE_DIR` is unset. |
|
|
72
|
+
| `WGPU_SKIP_GPU_TESTS=1` | Skip tests that require an adapter. This is a test setting, not a runtime backend selector. |
|
|
73
|
+
|
|
74
|
+
Default cache paths are:
|
|
75
|
+
|
|
76
|
+
| Platform | Versioned cache directory |
|
|
77
|
+
|---|---|
|
|
78
|
+
| macOS | `~/Library/Caches/wgpu-ruby/v27.0.4.0/` |
|
|
79
|
+
| Linux/other Unix | `~/.cache/wgpu-ruby/v27.0.4.0/` |
|
|
80
|
+
| Windows | `%LOCALAPPDATA%\wgpu-ruby\v27.0.4.0\` |
|
|
81
|
+
|
|
82
|
+
Every downloaded archive is checked against the SHA-256 digest recorded in
|
|
83
|
+
`lib/wgpu/native/distribution.rb` before extraction. A mismatch deletes the
|
|
84
|
+
archive and stops installation.
|
|
85
|
+
|
|
86
|
+
## Troubleshooting
|
|
87
|
+
|
|
88
|
+
- **Library not found:** rerun the install hook or set `WGPU_LIB_PATH`.
|
|
89
|
+
- **Unsupported platform:** build wgpu-native for the host and use
|
|
90
|
+
`WGPU_LIB_PATH`.
|
|
91
|
+
- **Linux cannot create an adapter:** install a Vulkan driver. Mesa lavapipe
|
|
92
|
+
(`mesa-vulkan-drivers`) is sufficient for software-based tests.
|
|
93
|
+
- **Rendering examples fail to load SDL3:** install the SDL3 system library and
|
|
94
|
+
the `sdl3` Ruby gem. Compute APIs do not load `wgpu/window`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Pipeline descriptors
|
|
2
|
+
|
|
3
|
+
`WGPU::ComputePipeline` and `WGPU::RenderPipeline` accept Ruby Hashes that mirror
|
|
4
|
+
WebGPU pipeline descriptors. Passing `layout: :auto`, `"auto"`, or `nil` requests
|
|
5
|
+
automatic layout inference. A layout object continues to select an explicit
|
|
6
|
+
pipeline layout.
|
|
7
|
+
|
|
8
|
+
## Default render state
|
|
9
|
+
|
|
10
|
+
The wrapper applies the following WebGPU defaults when a field is omitted:
|
|
11
|
+
|
|
12
|
+
| State | Field | Default |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Vertex | `entry_point` | `"main"` |
|
|
15
|
+
| Vertex buffer | `step_mode` | `:vertex` |
|
|
16
|
+
| Primitive | `topology` | `:triangle_list` |
|
|
17
|
+
| Primitive | `strip_index_format` | `:undefined` |
|
|
18
|
+
| Primitive | `front_face` | `:ccw` |
|
|
19
|
+
| Primitive | `cull_mode` | `:none` |
|
|
20
|
+
| Primitive | `unclipped_depth` | `false` |
|
|
21
|
+
| Multisample | `count` | `1` |
|
|
22
|
+
| Multisample | `mask` | `0xFFFFFFFF` |
|
|
23
|
+
| Multisample | `alpha_to_coverage_enabled` | `false` |
|
|
24
|
+
| Depth/stencil | `depth_compare` | `:always` |
|
|
25
|
+
| Stencil face | operations | `:keep` |
|
|
26
|
+
| Color target | `write_mask` | `:all` |
|
|
27
|
+
| Blend component | `operation` | `:add` |
|
|
28
|
+
| Blend component | `src_factor` | `:one` |
|
|
29
|
+
| Blend component | `dst_factor` | `:zero` |
|
|
30
|
+
|
|
31
|
+
`vertex[:module]`, each vertex attribute's `format`, `offset`, and
|
|
32
|
+
`shader_location`, and each color target's `format` are required. A
|
|
33
|
+
depth/stencil state requires `format`. Unknown descriptor keys produce a warning
|
|
34
|
+
so misspellings are visible while preserving v1.x compatibility.
|
|
35
|
+
|
|
36
|
+
Both vertex/fragment and compute stages accept `constants:`, a Hash mapping WGSL
|
|
37
|
+
override names to numeric values. The descriptor keeps all FFI strings and
|
|
38
|
+
arrays alive until native pipeline creation completes.
|
data/docs/releasing.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
The release workflow uses RubyGems Trusted Publishing and runs for `v*` tags.
|
|
4
|
+
Before the first automated release, configure a trusted publisher for the
|
|
5
|
+
`ydah/wgpu-ruby` repository, workflow `release.yml`, and GitHub environment
|
|
6
|
+
`release` on RubyGems.org.
|
|
7
|
+
|
|
8
|
+
Release checklist:
|
|
9
|
+
|
|
10
|
+
1. Complete the [wgpu-native upgrade checklist](upgrading_wgpu_native.md) when
|
|
11
|
+
the native version changes.
|
|
12
|
+
2. Update `WGPU::VERSION` and move Unreleased changelog entries under the new
|
|
13
|
+
version/date heading.
|
|
14
|
+
3. Run the complete local verification documented in the project README.
|
|
15
|
+
4. Build and inspect the gem: `gem build wgpu.gemspec`.
|
|
16
|
+
5. Merge the release commit, create an annotated `vX.Y.Z` tag, and push it.
|
|
17
|
+
6. Confirm CI and the protected `release` environment. The workflow rejects a
|
|
18
|
+
tag that does not equal `v#{WGPU::VERSION}`.
|
|
19
|
+
7. Verify the published gem and generated documentation on RubyGems.org.
|
|
20
|
+
|
|
21
|
+
The workflow requests only `contents: write` and `id-token: write`; it stores no
|
|
22
|
+
long-lived RubyGems API key.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Resource lifetime
|
|
2
|
+
|
|
3
|
+
wgpu-ruby follows wgpu-native's explicit reference-counted handle model.
|
|
4
|
+
Callers own every wrapper returned to them and must call `release` when it is no
|
|
5
|
+
longer needed. The library does not automatically release native handles from
|
|
6
|
+
Ruby finalizers.
|
|
7
|
+
|
|
8
|
+
## `release` and `destroy`
|
|
9
|
+
|
|
10
|
+
- `release` gives up the wrapper's native reference. It sets the stored handle
|
|
11
|
+
to `FFI::Pointer::NULL`; calling `release` again is harmless.
|
|
12
|
+
- `destroy` immediately invalidates the underlying GPU resource contents but
|
|
13
|
+
does not give up the wrapper's reference. Call `release` after `destroy`.
|
|
14
|
+
- Calling another public native operation after `release` raises
|
|
15
|
+
`WGPU::ResourceError` before FFI is entered. `handle`, `released?`, `label`,
|
|
16
|
+
`inspect`, and repeated `release` remain available.
|
|
17
|
+
- Every native wrapper supports `use { |resource| ... }`. It returns the block
|
|
18
|
+
result and releases the wrapper in `ensure`, including when the block raises.
|
|
19
|
+
This is Ruby convenience API rather than a WebGPU operation.
|
|
20
|
+
|
|
21
|
+
For short-lived resources:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
bytes = device.create_buffer(
|
|
25
|
+
size: 256,
|
|
26
|
+
usage: %i[map_read copy_dst]
|
|
27
|
+
).use do |buffer|
|
|
28
|
+
# Work with buffer; it is released on every exit path.
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Wrapper matrix
|
|
33
|
+
|
|
34
|
+
The table covers all 23 native wrapper classes. `BufferMappedRange`,
|
|
35
|
+
`AsyncTask`, and `Window::SDLWindow` are not independent wgpu-native
|
|
36
|
+
reference-counted handles.
|
|
37
|
+
|
|
38
|
+
| Wrapper | `release` | `destroy` | Ownership note |
|
|
39
|
+
|---|:---:|:---:|---|
|
|
40
|
+
| `Instance` | ✅ | — | Release after all adapters/surfaces derived from it. |
|
|
41
|
+
| `Adapter` | ✅ | — | Returned by instance discovery/request. |
|
|
42
|
+
| `Device` | ✅ | ✅ | `release` also releases the cached queue wrapper first. |
|
|
43
|
+
| `Queue` | ✅ | — | Normally owned through `Device#queue`; device release cascades to it. |
|
|
44
|
+
| `Surface` | ✅ | — | Release after unconfiguring and after current texture work completes. |
|
|
45
|
+
| `CanvasContext` | ✅ | — | Releases its internally created surface. |
|
|
46
|
+
| `Buffer` | ✅ | ✅ | Destroy contents when early reclamation is desired, then release. |
|
|
47
|
+
| `Texture` | ✅ | ✅ | Texture views should be released before their texture. |
|
|
48
|
+
| `TextureView` | ✅ | — | `Texture#from_handle`/view wrappers are caller-owned. |
|
|
49
|
+
| `Sampler` | ✅ | — | |
|
|
50
|
+
| `QuerySet` | ✅ | ✅ | Destroy query storage, then release. The wrapper suppresses v27's aborting native double-removal path. |
|
|
51
|
+
| `ShaderModule` | ✅ | — | |
|
|
52
|
+
| `BindGroupLayout` | ✅ | — | Layouts returned by `get_bind_group_layout` are caller-owned. |
|
|
53
|
+
| `BindGroup` | ✅ | — | |
|
|
54
|
+
| `PipelineLayout` | ✅ | — | |
|
|
55
|
+
| `ComputePipeline` | ✅ | — | |
|
|
56
|
+
| `RenderPipeline` | ✅ | — | |
|
|
57
|
+
| `CommandEncoder` | ✅ | — | Finish before release. |
|
|
58
|
+
| `CommandBuffer` | ✅ | — | Release after submission is no longer needed. |
|
|
59
|
+
| `ComputePass` | ✅ | — | End the pass before finishing its encoder. |
|
|
60
|
+
| `RenderPass` | ✅ | — | End the pass before finishing its encoder. |
|
|
61
|
+
| `RenderBundleEncoder` | ✅ | — | Finish before release. |
|
|
62
|
+
| `RenderBundle` | ✅ | — | |
|
|
63
|
+
|
|
64
|
+
## Recommended release order
|
|
65
|
+
|
|
66
|
+
Release in the reverse order of creation:
|
|
67
|
+
|
|
68
|
+
1. End active compute/render passes.
|
|
69
|
+
2. Finish encoders and submit command buffers.
|
|
70
|
+
3. Release pass encoders, command buffers, and command encoders.
|
|
71
|
+
4. Release bind groups, pipelines/layouts, shader modules, samplers, texture
|
|
72
|
+
views, buffers, textures, and query sets.
|
|
73
|
+
5. Unconfigure and release surfaces/canvas contexts.
|
|
74
|
+
6. Release the device (which releases its queue), then adapter and instance.
|
|
75
|
+
|
|
76
|
+
Explicitly synchronize work when the application needs resources to remain
|
|
77
|
+
alive until completion. A `CommandBuffer` is consumed by its first successful
|
|
78
|
+
`Queue#submit`; submitting it again raises `WGPU::CommandError`. Submission
|
|
79
|
+
does not itself release the command buffer or its referenced Ruby wrappers.
|
|
80
|
+
|
|
81
|
+
## Internal staging resources
|
|
82
|
+
|
|
83
|
+
`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. In the baseline
|
|
85
|
+
implementation cleanup runs from `ensure`, including exceptional paths.
|
|
86
|
+
Applications should not attempt to retain or release this internal buffer.
|
|
87
|
+
|
|
88
|
+
## Leak diagnostics
|
|
89
|
+
|
|
90
|
+
Set `WGPU_DEBUG_LEAKS=1` before requiring the gem, or set
|
|
91
|
+
`WGPU.debug_leaks = true` before creating resources, to enable warnings.
|
|
92
|
+
Unreleased resources are reported with their wrapper class and label during GC
|
|
93
|
+
or process exit. The detector never releases a native handle; it is diagnostic
|
|
94
|
+
only and is disabled by default.
|
data/docs/shaders.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Shader modules and diagnostics
|
|
2
|
+
|
|
3
|
+
WGSL remains the default input:
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
shader = device.create_shader_module(code: wgsl, label: "simulation")
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Pass `validate: true` to request compilation information immediately when the
|
|
10
|
+
loaded wgpu-native version implements that API. Error messages are raised as
|
|
11
|
+
`WGPU::ShaderError` with the shader label and line/column diagnostics. Without
|
|
12
|
+
this option, creation follows the original lazy validation behavior.
|
|
13
|
+
|
|
14
|
+
`ShaderModule#get_compilation_info` returns a Hash with `status:` and
|
|
15
|
+
`messages:`. Each message is a `WGPU::CompilationMessage` with `type`,
|
|
16
|
+
`message`, `line_num`/`line`, `line_pos`/`column`, `offset`, and `length`.
|
|
17
|
+
|
|
18
|
+
wgpu-native v27.0.4.0 exports the compilation-info function as an
|
|
19
|
+
unimplemented panic stub. wgpu-ruby detects that version and raises
|
|
20
|
+
`WGPU::ShaderError` before crossing the native boundary. This guard avoids a
|
|
21
|
+
process abort; diagnostics can be enabled when a future pinned wgpu-native
|
|
22
|
+
release implements the function.
|
|
23
|
+
|
|
24
|
+
wgpu-native's SPIR-V extension is available explicitly:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
shader = device.create_shader_module(spirv: binary_bytes, label: "compute")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
SPIR-V input must contain a whole number of 32-bit words. It is a
|
|
31
|
+
wgpu-native extension rather than portable WebGPU API and should be avoided
|
|
32
|
+
when browser portability matters.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Texture readback
|
|
2
|
+
|
|
3
|
+
`WGPU::TextureFormat` exposes WebGPU texel-block calculations:
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
tight = WGPU::TextureFormat.bytes_per_row(width, :rgba8_unorm)
|
|
7
|
+
stride = WGPU::TextureFormat.aligned_bytes_per_row(width, :rgba8_unorm)
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
`block_size` returns the bytes in one texel block, while `block_dimensions`
|
|
11
|
+
returns its width and height. Compressed BC, ETC2/EAC, and ASTC formats use
|
|
12
|
+
their real block dimensions. Formats whose depth representation is
|
|
13
|
+
implementation-defined do not claim a portable copy footprint. Combined
|
|
14
|
+
depth/stencil copies require an explicit `aspect:`.
|
|
15
|
+
|
|
16
|
+
`Queue#read_texture` validates that `bytes_per_row` is a multiple of WebGPU's
|
|
17
|
+
256-byte copy alignment and large enough for the requested width and format.
|
|
18
|
+
Use `aligned_bytes_per_row` when the tight row is not already aligned. Automatic
|
|
19
|
+
padding and mipmap generation are intentionally outside this low-level binding.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Native library is not found
|
|
4
|
+
|
|
5
|
+
Run `bundle exec rake wgpu:install`. The error lists every searched cache path.
|
|
6
|
+
For a custom build, set `WGPU_LIB_PATH` to the shared library file, not its
|
|
7
|
+
directory. See [installation](installation.md).
|
|
8
|
+
|
|
9
|
+
## Download or checksum fails
|
|
10
|
+
|
|
11
|
+
The installer deletes an archive whose SHA-256 differs from the pinned release
|
|
12
|
+
metadata. Retry on a trusted network. Do not bypass the checksum; download the
|
|
13
|
+
matching artifact manually and set `WGPU_LIB_PATH` if GitHub Releases is
|
|
14
|
+
unavailable.
|
|
15
|
+
|
|
16
|
+
## No adapter is available
|
|
17
|
+
|
|
18
|
+
Update the platform GPU driver. On headless Linux, install Vulkan loader and
|
|
19
|
+
Mesa lavapipe, set `VK_ICD_FILENAMES` to the lavapipe ICD JSON, and inspect
|
|
20
|
+
`vulkaninfo --summary`. `WGPU_BACKEND=vulkan` can make backend selection
|
|
21
|
+
explicit.
|
|
22
|
+
|
|
23
|
+
## A synchronous operation hangs
|
|
24
|
+
|
|
25
|
+
Pass `timeout:` to adapter/device requests, `Buffer#map_sync`,
|
|
26
|
+
`Device#pop_error_scope`, or `Queue#on_submitted_work_done`. A timeout raises
|
|
27
|
+
`WGPU::TimeoutError`. In an event loop, regularly call
|
|
28
|
+
`Instance#process_events` or `Device#poll`.
|
|
29
|
+
|
|
30
|
+
## Texture readback rejects bytes_per_row
|
|
31
|
+
|
|
32
|
+
Buffer/texture copy rows must be 256-byte aligned. Calculate the value with
|
|
33
|
+
`WGPU::TextureFormat.aligned_bytes_per_row(width, format)` and account for
|
|
34
|
+
padding when decoding each row.
|
|
35
|
+
|
|
36
|
+
## SDL3 cannot be loaded
|
|
37
|
+
|
|
38
|
+
Compute code should only `require "wgpu"`. Rendering code must separately add
|
|
39
|
+
the `sdl3` Ruby gem, install the SDL3 system library, and then require
|
|
40
|
+
`wgpu/window`.
|
|
41
|
+
|
|
42
|
+
## Diagnosing validation and shader errors
|
|
43
|
+
|
|
44
|
+
Use `device.on_uncaptured_error`, scoped errors, and labels. Compilation-info
|
|
45
|
+
validation is guarded on pinned wgpu-native v27 because its exported function
|
|
46
|
+
is a panic stub; see [Shaders and diagnostics](shaders.md). Set
|
|
47
|
+
`WGPU_DEBUG_LEAKS=1` in development to warn about wrappers that reach GC or
|
|
48
|
+
process exit without `release`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Upgrading wgpu-native
|
|
2
|
+
|
|
3
|
+
Use this checklist for each pinned wgpu-native update.
|
|
4
|
+
|
|
5
|
+
1. Update only `WGPU::Native::Distribution::VERSION`.
|
|
6
|
+
2. Obtain the five release artifact names and SHA-256 digests from the official
|
|
7
|
+
wgpu-native GitHub release. Update `ARTIFACTS`.
|
|
8
|
+
3. Run `rg` for the old version and confirm no second version definition
|
|
9
|
+
remains.
|
|
10
|
+
4. Run `bundle exec rake wgpu:clean wgpu:install` on a disposable cache, then
|
|
11
|
+
test an existing legacy cache separately.
|
|
12
|
+
5. Run `bundle exec rake wgpu:verify_abi`. Review every enum addition, removal,
|
|
13
|
+
and value change against the checksum-pinned `webgpu.h`.
|
|
14
|
+
6. Compare structs, field offsets, callback signatures, and exported functions.
|
|
15
|
+
Add ABI specs for changed layouts. Mark functions optional only when the Ruby
|
|
16
|
+
API has a valid capability fallback.
|
|
17
|
+
7. Run `bundle exec rspec --tag '~gpu'`, RuboCop, RBS validation, and YARD.
|
|
18
|
+
8. Run every `:gpu` spec and `rake examples:ci` with lavapipe. Run rendering
|
|
19
|
+
examples on at least one real surface backend.
|
|
20
|
+
9. Build the gem and install it into a clean environment without SDL3.
|
|
21
|
+
10. Record ABI/API changes, platform artifacts, and migration notes in
|
|
22
|
+
`CHANGELOG.md`.
|
|
23
|
+
|
|
24
|
+
For a dry run, use a temporary `WGPU_CACHE_DIR` and restore the version/artifact
|
|
25
|
+
edits afterward. Never replace the shared user cache as part of verification.
|
|
26
|
+
|
data/ext/wgpu/extconf.rb
CHANGED
|
@@ -1,151 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
require "uri"
|
|
3
|
+
lib_dir = File.expand_path("../../lib", __dir__)
|
|
4
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
GITHUB_RELEASE_URL = "https://github.com/gfx-rs/wgpu-native/releases/download/#{WGPU_VERSION}"
|
|
6
|
+
require "wgpu/native/installer"
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/arm64-darwin/ => { file: "wgpu-macos-aarch64-release.zip", lib: "libwgpu_native.dylib" },
|
|
15
|
-
/mingw|mswin/ => { file: "wgpu-windows-x86_64-msvc-release.zip", lib: "wgpu_native.dll" }
|
|
16
|
-
}.freeze
|
|
17
|
-
|
|
18
|
-
def detect_platform
|
|
19
|
-
PLATFORM_MAP.each do |pattern, info|
|
|
20
|
-
return info if RUBY_PLATFORM =~ pattern
|
|
21
|
-
end
|
|
22
|
-
abort "Unsupported platform: #{RUBY_PLATFORM}\nSupported: #{PLATFORM_MAP.keys.map(&:inspect).join(", ")}"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def cache_dir
|
|
26
|
-
File.join(Dir.home, ".cache", "wgpu-ruby", WGPU_VERSION)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def windows?
|
|
30
|
-
RUBY_PLATFORM =~ /mingw|mswin/
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def curl_available?
|
|
34
|
-
if windows?
|
|
35
|
-
system("where curl >nul 2>&1")
|
|
8
|
+
begin
|
|
9
|
+
installer = WGPU::Native::Installer.new
|
|
10
|
+
if ENV["WGPU_LIB_PATH"]
|
|
11
|
+
puts "Using custom wgpu-native from WGPU_LIB_PATH: #{installer.install}"
|
|
36
12
|
else
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def download_with_curl(url, dest)
|
|
42
|
-
system("curl", "-fsSL", "-o", dest, url)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def download_with_ruby(url, dest, redirects = 5)
|
|
46
|
-
raise "Too many redirects" if redirects == 0
|
|
47
|
-
|
|
48
|
-
uri = URI.parse(url)
|
|
49
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
|
50
|
-
http.use_ssl = (uri.scheme == "https")
|
|
51
|
-
http.open_timeout = 10
|
|
52
|
-
http.read_timeout = 120
|
|
53
|
-
|
|
54
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
|
55
|
-
|
|
56
|
-
http.request(request) do |response|
|
|
57
|
-
case response
|
|
58
|
-
when Net::HTTPRedirection
|
|
59
|
-
download_with_ruby(response["location"], dest, redirects - 1)
|
|
60
|
-
when Net::HTTPSuccess
|
|
61
|
-
File.open(dest, "wb") do |file|
|
|
62
|
-
response.read_body { |chunk| file.write(chunk) }
|
|
63
|
-
end
|
|
64
|
-
else
|
|
65
|
-
return false
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
true
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def download_file(url, dest)
|
|
72
|
-
return if curl_available? && download_with_curl(url, dest)
|
|
73
|
-
return if download_with_ruby(url, dest)
|
|
74
|
-
|
|
75
|
-
abort "Download failed: #{url}"
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def extract_with_rubyzip(zip_path, dest_dir)
|
|
79
|
-
require "zip"
|
|
80
|
-
Zip::File.open(zip_path) do |zip_file|
|
|
81
|
-
zip_file.each do |entry|
|
|
82
|
-
dest_path = File.join(dest_dir, entry.name)
|
|
83
|
-
FileUtils.mkdir_p(File.dirname(dest_path))
|
|
84
|
-
entry.extract(dest_path) { true }
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
true
|
|
88
|
-
rescue LoadError
|
|
89
|
-
false
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def extract_with_powershell(zip_path, dest_dir)
|
|
93
|
-
return false unless windows?
|
|
94
|
-
|
|
95
|
-
system("powershell", "-Command", "Expand-Archive -Force -Path '#{zip_path}' -DestinationPath '#{dest_dir}'")
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def extract_with_unzip(zip_path, dest_dir)
|
|
99
|
-
system("unzip", "-o", "-q", zip_path, "-d", dest_dir)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def extract_zip(zip_path, dest_dir)
|
|
103
|
-
return if extract_with_rubyzip(zip_path, dest_dir)
|
|
104
|
-
return if windows? && extract_with_powershell(zip_path, dest_dir)
|
|
105
|
-
return if extract_with_unzip(zip_path, dest_dir)
|
|
106
|
-
|
|
107
|
-
abort "Failed to extract zip. Please install 'rubyzip' gem."
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def lib_dir
|
|
111
|
-
File.join(cache_dir, "lib")
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def download_wgpu_native
|
|
115
|
-
platform = detect_platform
|
|
116
|
-
lib_path = File.join(lib_dir, platform[:lib])
|
|
117
|
-
|
|
118
|
-
if File.exist?(lib_path)
|
|
119
|
-
puts "wgpu-native already cached at #{lib_path}"
|
|
120
|
-
return lib_path
|
|
13
|
+
installer.install
|
|
121
14
|
end
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
url = "#{GITHUB_RELEASE_URL}/#{platform[:file]}"
|
|
126
|
-
zip_path = File.join(cache_dir, platform[:file])
|
|
127
|
-
|
|
128
|
-
puts "Downloading wgpu-native #{WGPU_VERSION} from GitHub..."
|
|
129
|
-
puts " URL: #{url}"
|
|
130
|
-
download_file(url, zip_path)
|
|
131
|
-
|
|
132
|
-
puts "Extracting to #{cache_dir}..."
|
|
133
|
-
extract_zip(zip_path, cache_dir)
|
|
134
|
-
|
|
135
|
-
FileUtils.rm_f(zip_path)
|
|
136
|
-
|
|
137
|
-
unless File.exist?(lib_path)
|
|
138
|
-
abort "Failed to find #{platform[:lib]} after extraction"
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
puts "wgpu-native installed successfully!"
|
|
142
|
-
lib_path
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
if ENV["WGPU_LIB_PATH"]
|
|
146
|
-
puts "Using custom wgpu-native from WGPU_LIB_PATH: #{ENV["WGPU_LIB_PATH"]}"
|
|
147
|
-
else
|
|
148
|
-
download_wgpu_native
|
|
15
|
+
rescue WGPU::Native::InstallError => error
|
|
16
|
+
abort error.message
|
|
149
17
|
end
|
|
150
18
|
|
|
151
19
|
File.write("Makefile", <<~MAKEFILE)
|
|
@@ -6,6 +6,17 @@ module WGPU
|
|
|
6
6
|
|
|
7
7
|
def initialize(handle)
|
|
8
8
|
@handle = handle
|
|
9
|
+
@submitted = false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def submitted?
|
|
13
|
+
@submitted
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def mark_submitted!
|
|
17
|
+
raise CommandError, "Command buffer has already been submitted" if @submitted
|
|
18
|
+
|
|
19
|
+
@submitted = true
|
|
9
20
|
end
|
|
10
21
|
|
|
11
22
|
def release
|