From 9b28e4331c8e249655a67ef63afbfa4e262719f4 Mon Sep 17 00:00:00 2001 From: Bailey Hayes Date: Tue, 10 Mar 2026 15:25:10 -0400 Subject: [PATCH 1/2] Version as rc.1 and add publish pipeline - Add release pipeline (prepare-release + publish-release workflows) modeled after wasi-otel, adapted for wasi-gfx's multi-package structure (graphics-context, webgpu, surface, frame-buffer) - Migrate from vendored `deps/` directories to `wkg.toml` + `wkg.lock` for dependency management - Add `.gitignore` for build artifacts (`.wasm` files) - **prepare-release**: Auto-increments `0.2.0-rc.N` version from git tags, bumps all `wasi:graphics-context`, `wasi:webgpu`, `wasi:surface`, `wasi:frame-buffer` version references across `.wit` files, and opens a release PR - **publish-release**: Extracts version from `graphics-context/graphics-context.wit`, creates git tag + GitHub release, builds all 4 WIT packages with `wkg wit build`, publishes to GHCR (`ghcr.io/webassembly/wasi/{graphics-context,webgpu,surface,frame- buffer}`), attests build provenance, and uploads `.wasm` artifacts to the release --- .github/workflows/prepare-release.yml | 63 +++++ .github/workflows/publish-release.yml | 160 +++++++++++ .gitignore | 1 + .../graphics-context/graphics-context.wit | 18 -- frame-buffer/frame-buffer.wit | 4 +- frame-buffer/wkg.lock | 4 + frame-buffer/wkg.toml | 2 + graphics-context/graphics-context.wit | 2 +- graphics-context/wkg.lock | 4 + .../graphics-context/graphics-context.wit | 18 -- surface/deps/io/error.wit | 34 --- surface/deps/io/poll.wit | 41 --- surface/deps/io/streams.wit | 262 ------------------ surface/deps/io/world.wit | 6 - surface/surface.wit | 4 +- surface/wkg.lock | 12 + surface/wkg.toml | 2 + .../graphics-context/graphics-context.wit | 18 -- webgpu/deps/io/error.wit | 34 --- webgpu/deps/io/poll.wit | 41 --- webgpu/deps/io/streams.wit | 262 ------------------ webgpu/deps/io/world.wit | 6 - webgpu/imports.wit | 2 +- webgpu/webgpu.wit | 4 +- webgpu/wkg.lock | 12 + webgpu/wkg.toml | 2 + 26 files changed, 270 insertions(+), 748 deletions(-) create mode 100644 .github/workflows/prepare-release.yml create mode 100644 .github/workflows/publish-release.yml create mode 100644 .gitignore delete mode 100644 frame-buffer/deps/graphics-context/graphics-context.wit create mode 100644 frame-buffer/wkg.lock create mode 100644 frame-buffer/wkg.toml create mode 100644 graphics-context/wkg.lock delete mode 100644 surface/deps/graphics-context/graphics-context.wit delete mode 100644 surface/deps/io/error.wit delete mode 100644 surface/deps/io/poll.wit delete mode 100644 surface/deps/io/streams.wit delete mode 100644 surface/deps/io/world.wit create mode 100644 surface/wkg.lock create mode 100644 surface/wkg.toml delete mode 100644 webgpu/deps/graphics-context/graphics-context.wit delete mode 100644 webgpu/deps/io/error.wit delete mode 100644 webgpu/deps/io/poll.wit delete mode 100644 webgpu/deps/io/streams.wit delete mode 100644 webgpu/deps/io/world.wit create mode 100644 webgpu/wkg.lock create mode 100644 webgpu/wkg.toml diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 0000000..3960c4d --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,63 @@ +name: Prepare Release + +on: + workflow_dispatch: + +jobs: + prepare: + name: Create Release PR + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - name: Determine next RC version + id: version + run: | + # Find highest RC number from existing tags + HIGHEST_RC=0 + for tag in $(git tag -l 'v0.2.0-rc.*'); do + if [[ "$tag" =~ ^v0\.2\.0-rc\.([0-9]+)$ ]]; then + RC_NUM="${BASH_REMATCH[1]}" + if [ "$RC_NUM" -gt "$HIGHEST_RC" ]; then + HIGHEST_RC="$RC_NUM" + fi + fi + done + + NEXT_RC=$((HIGHEST_RC + 1)) + VERSION="0.2.0-rc.${NEXT_RC}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "Preparing version: $VERSION" + + - name: Bump package versions + run: | + VERSION="${{ steps.version.outputs.version }}" + + # Update version for all wasi-gfx packages (but not external deps like wasi:io) + for pkg in graphics-context webgpu surface frame-buffer; do + find . -name "*.wit" -not -path "*/generate/*" -exec sed -i \ + "s/\(wasi:${pkg}@\)[^;, }]*/\1${VERSION}/g" {} + + done + + - name: Create Pull Request + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + with: + commit-message: "chore: bump version to ${{ steps.version.outputs.version }}" + branch: release/${{ steps.version.outputs.version }} + title: "Release ${{ steps.version.outputs.version }}" + body: | + Bumps package version to `${{ steps.version.outputs.version }}`. + + Once merged, manually run the **Publish Release** workflow to: + - Create git tag `v${{ steps.version.outputs.version }}` + - Create GitHub release + - Publish packages to GHCR: + - `ghcr.io/webassembly/wasi/graphics-context:${{ steps.version.outputs.version }}` + - `ghcr.io/webassembly/wasi/webgpu:${{ steps.version.outputs.version }}` + - `ghcr.io/webassembly/wasi/surface:${{ steps.version.outputs.version }}` + - `ghcr.io/webassembly/wasi/frame-buffer:${{ steps.version.outputs.version }}` diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..b072103 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,160 @@ +name: Publish Release + +on: + workflow_dispatch: + +jobs: + publish: + name: Publish Release + runs-on: ubuntu-latest + permissions: + id-token: write + packages: write + contents: write + attestations: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - name: Extract version from package + id: version + run: | + # Extract version from graphics-context (canonical source) + VERSION=$(sed -n 's/^package wasi:graphics-context@\([^;]*\);/\1/p' graphics-context/graphics-context.wit) + if [[ ! "$VERSION" =~ ^0\.2\.0-rc\.[0-9]+$ ]]; then + echo "Error: Version '$VERSION' is not a valid RC version" + exit 1 + fi + TAG="v${VERSION}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "Publishing version: $VERSION" + + - name: Check tag doesn't exist + run: | + if git tag -l "${{ steps.version.outputs.tag }}" | grep -q .; then + echo "Error: Tag ${{ steps.version.outputs.tag }} already exists" + exit 1 + fi + + - name: Create git tag + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.version }}" + git push origin "${{ steps.version.outputs.tag }}" + + - name: Create GitHub release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${{ steps.version.outputs.tag }}" \ + --title "${{ steps.version.outputs.version }}" \ + --prerelease \ + --generate-notes + + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@80aaafe04903087c333980fa2686259ddd34b2d9 # v1.16.6 + + - name: Install wkg + run: cargo binstall -y "wkg@0.15.0" + + - name: Login to GitHub Container Registry + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build WIT packages + run: | + for pkg in graphics-context webgpu surface frame-buffer; do + (cd "$pkg" && wkg wit build -d . -o "../wasi-${pkg}.wasm") + done + + - name: Publish graphics-context + id: publish-graphics-context + uses: bytecodealliance/wkg-github-action@10b3b04b9059ba46208cd7daf7d352af14bded0f # v5 + with: + oci-reference-without-tag: ghcr.io/webassembly/wasi/graphics-context + file: wasi-graphics-context.wasm + description: 'WASI Graphics Context' + source: https://github.com/WebAssembly/wasi-gfx + homepage: https://github.com/WebAssembly/wasi-gfx + version: ${{ steps.version.outputs.version }} + licenses: Apache-2.0 WITH LLVM-exception + + - name: Publish webgpu + id: publish-webgpu + uses: bytecodealliance/wkg-github-action@10b3b04b9059ba46208cd7daf7d352af14bded0f # v5 + with: + oci-reference-without-tag: ghcr.io/webassembly/wasi/webgpu + file: wasi-webgpu.wasm + description: 'WASI WebGPU' + source: https://github.com/WebAssembly/wasi-gfx + homepage: https://github.com/WebAssembly/wasi-gfx + version: ${{ steps.version.outputs.version }} + licenses: Apache-2.0 WITH LLVM-exception + + - name: Publish surface + id: publish-surface + uses: bytecodealliance/wkg-github-action@10b3b04b9059ba46208cd7daf7d352af14bded0f # v5 + with: + oci-reference-without-tag: ghcr.io/webassembly/wasi/surface + file: wasi-surface.wasm + description: 'WASI Surface' + source: https://github.com/WebAssembly/wasi-gfx + homepage: https://github.com/WebAssembly/wasi-gfx + version: ${{ steps.version.outputs.version }} + licenses: Apache-2.0 WITH LLVM-exception + + - name: Publish frame-buffer + id: publish-frame-buffer + uses: bytecodealliance/wkg-github-action@10b3b04b9059ba46208cd7daf7d352af14bded0f # v5 + with: + oci-reference-without-tag: ghcr.io/webassembly/wasi/frame-buffer + file: wasi-frame-buffer.wasm + description: 'WASI Frame Buffer' + source: https://github.com/WebAssembly/wasi-gfx + homepage: https://github.com/WebAssembly/wasi-gfx + version: ${{ steps.version.outputs.version }} + licenses: Apache-2.0 WITH LLVM-exception + + - name: Attest build provenance + uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + with: + subject-name: ghcr.io/webassembly/wasi/graphics-context + subject-digest: ${{ steps.publish-graphics-context.outputs.digest }} + push-to-registry: true + + - name: Attest build provenance (webgpu) + uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + with: + subject-name: ghcr.io/webassembly/wasi/webgpu + subject-digest: ${{ steps.publish-webgpu.outputs.digest }} + push-to-registry: true + + - name: Attest build provenance (surface) + uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + with: + subject-name: ghcr.io/webassembly/wasi/surface + subject-digest: ${{ steps.publish-surface.outputs.digest }} + push-to-registry: true + + - name: Attest build provenance (frame-buffer) + uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + with: + subject-name: ghcr.io/webassembly/wasi/frame-buffer + subject-digest: ${{ steps.publish-frame-buffer.outputs.digest }} + push-to-registry: true + + - name: Upload wasm files to release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload "${{ steps.version.outputs.tag }}" \ + wasi-graphics-context.wasm \ + wasi-webgpu.wasm \ + wasi-surface.wasm \ + wasi-frame-buffer.wasm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..19e1bce --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.wasm diff --git a/frame-buffer/deps/graphics-context/graphics-context.wit b/frame-buffer/deps/graphics-context/graphics-context.wit deleted file mode 100644 index 9ad8745..0000000 --- a/frame-buffer/deps/graphics-context/graphics-context.wit +++ /dev/null @@ -1,18 +0,0 @@ -package wasi:graphics-context@0.0.1; - -world imports { - import graphics-context; -} - -interface graphics-context { - resource context { - constructor(); - - get-current-buffer: func() -> abstract-buffer; - - // TODO: might want to remove this. - present: func(); - } - - resource abstract-buffer { } -} diff --git a/frame-buffer/frame-buffer.wit b/frame-buffer/frame-buffer.wit index 0696975..5ee0b77 100644 --- a/frame-buffer/frame-buffer.wit +++ b/frame-buffer/frame-buffer.wit @@ -1,11 +1,11 @@ -package wasi:frame-buffer@0.0.1; +package wasi:frame-buffer@0.2.0-rc.1; world imports { import frame-buffer; } interface frame-buffer { - use wasi:graphics-context/graphics-context@0.0.1.{context, abstract-buffer}; + use wasi:graphics-context/graphics-context@0.2.0-rc.1.{context, abstract-buffer}; resource device { constructor(); diff --git a/frame-buffer/wkg.lock b/frame-buffer/wkg.lock new file mode 100644 index 0000000..2ad4aa8 --- /dev/null +++ b/frame-buffer/wkg.lock @@ -0,0 +1,4 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 +packages = [] diff --git a/frame-buffer/wkg.toml b/frame-buffer/wkg.toml new file mode 100644 index 0000000..537e9f2 --- /dev/null +++ b/frame-buffer/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"wasi:graphics-context" = { path = "../graphics-context" } diff --git a/graphics-context/graphics-context.wit b/graphics-context/graphics-context.wit index 9ad8745..8204cca 100644 --- a/graphics-context/graphics-context.wit +++ b/graphics-context/graphics-context.wit @@ -1,4 +1,4 @@ -package wasi:graphics-context@0.0.1; +package wasi:graphics-context@0.2.0-rc.1; world imports { import graphics-context; diff --git a/graphics-context/wkg.lock b/graphics-context/wkg.lock new file mode 100644 index 0000000..2ad4aa8 --- /dev/null +++ b/graphics-context/wkg.lock @@ -0,0 +1,4 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 +packages = [] diff --git a/surface/deps/graphics-context/graphics-context.wit b/surface/deps/graphics-context/graphics-context.wit deleted file mode 100644 index 9ad8745..0000000 --- a/surface/deps/graphics-context/graphics-context.wit +++ /dev/null @@ -1,18 +0,0 @@ -package wasi:graphics-context@0.0.1; - -world imports { - import graphics-context; -} - -interface graphics-context { - resource context { - constructor(); - - get-current-buffer: func() -> abstract-buffer; - - // TODO: might want to remove this. - present: func(); - } - - resource abstract-buffer { } -} diff --git a/surface/deps/io/error.wit b/surface/deps/io/error.wit deleted file mode 100644 index 22e5b64..0000000 --- a/surface/deps/io/error.wit +++ /dev/null @@ -1,34 +0,0 @@ -package wasi:io@0.2.0; - - -interface error { - /// A resource which represents some error information. - /// - /// The only method provided by this resource is `to-debug-string`, - /// which provides some human-readable information about the error. - /// - /// In the `wasi:io` package, this resource is returned through the - /// `wasi:io/streams/stream-error` type. - /// - /// To provide more specific error information, other interfaces may - /// provide functions to further "downcast" this error into more specific - /// error information. For example, `error`s returned in streams derived - /// from filesystem types to be described using the filesystem's own - /// error-code type, using the function - /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter - /// `borrow` and returns - /// `option`. - /// - /// The set of functions which can "downcast" an `error` into a more - /// concrete type is open. - resource error { - /// Returns a string that is suitable to assist humans in debugging - /// this error. - /// - /// WARNING: The returned string should not be consumed mechanically! - /// It may change across platforms, hosts, or other implementation - /// details. Parsing this string is a major platform-compatibility - /// hazard. - to-debug-string: func() -> string; - } -} diff --git a/surface/deps/io/poll.wit b/surface/deps/io/poll.wit deleted file mode 100644 index ddc67f8..0000000 --- a/surface/deps/io/poll.wit +++ /dev/null @@ -1,41 +0,0 @@ -package wasi:io@0.2.0; - -/// A poll API intended to let users wait for I/O events on multiple handles -/// at once. -interface poll { - /// `pollable` represents a single I/O event which may be ready, or not. - resource pollable { - - /// Return the readiness of a pollable. This function never blocks. - /// - /// Returns `true` when the pollable is ready, and `false` otherwise. - ready: func() -> bool; - - /// `block` returns immediately if the pollable is ready, and otherwise - /// blocks until ready. - /// - /// This function is equivalent to calling `poll.poll` on a list - /// containing only this pollable. - block: func(); - } - - /// Poll for completion on a set of pollables. - /// - /// This function takes a list of pollables, which identify I/O sources of - /// interest, and waits until one or more of the events is ready for I/O. - /// - /// The result `list` contains one or more indices of handles in the - /// argument list that is ready for I/O. - /// - /// If the list contains more elements than can be indexed with a `u32` - /// value, this function traps. - /// - /// A timeout can be implemented by adding a pollable from the - /// wasi-clocks API to the list. - /// - /// This function does not return a `result`; polling in itself does not - /// do any I/O so it doesn't fail. If any of the I/O sources identified by - /// the pollables has an error, it is indicated by marking the source as - /// being reaedy for I/O. - poll: func(in: list>) -> list; -} diff --git a/surface/deps/io/streams.wit b/surface/deps/io/streams.wit deleted file mode 100644 index 6d2f871..0000000 --- a/surface/deps/io/streams.wit +++ /dev/null @@ -1,262 +0,0 @@ -package wasi:io@0.2.0; - -/// WASI I/O is an I/O abstraction API which is currently focused on providing -/// stream types. -/// -/// In the future, the component model is expected to add built-in stream types; -/// when it does, they are expected to subsume this API. -interface streams { - use error.{error}; - use poll.{pollable}; - - /// An error for input-stream and output-stream operations. - variant stream-error { - /// The last operation (a write or flush) failed before completion. - /// - /// More information is available in the `error` payload. - last-operation-failed(error), - /// The stream is closed: no more input will be accepted by the - /// stream. A closed output-stream will return this error on all - /// future operations. - closed - } - - /// An input bytestream. - /// - /// `input-stream`s are *non-blocking* to the extent practical on underlying - /// platforms. I/O operations always return promptly; if fewer bytes are - /// promptly available than requested, they return the number of bytes promptly - /// available, which could even be zero. To wait for data to be available, - /// use the `subscribe` function to obtain a `pollable` which can be polled - /// for using `wasi:io/poll`. - resource input-stream { - /// Perform a non-blocking read from the stream. - /// - /// When the source of a `read` is binary data, the bytes from the source - /// are returned verbatim. When the source of a `read` is known to the - /// implementation to be text, bytes containing the UTF-8 encoding of the - /// text are returned. - /// - /// This function returns a list of bytes containing the read data, - /// when successful. The returned list will contain up to `len` bytes; - /// it may return fewer than requested, but not more. The list is - /// empty when no bytes are available for reading at this time. The - /// pollable given by `subscribe` will be ready when more bytes are - /// available. - /// - /// This function fails with a `stream-error` when the operation - /// encounters an error, giving `last-operation-failed`, or when the - /// stream is closed, giving `closed`. - /// - /// When the caller gives a `len` of 0, it represents a request to - /// read 0 bytes. If the stream is still open, this call should - /// succeed and return an empty list, or otherwise fail with `closed`. - /// - /// The `len` parameter is a `u64`, which could represent a list of u8 which - /// is not possible to allocate in wasm32, or not desirable to allocate as - /// as a return value by the callee. The callee may return a list of bytes - /// less than `len` in size while more bytes are available for reading. - read: func( - /// The maximum number of bytes to read - len: u64 - ) -> result, stream-error>; - - /// Read bytes from a stream, after blocking until at least one byte can - /// be read. Except for blocking, behavior is identical to `read`. - blocking-read: func( - /// The maximum number of bytes to read - len: u64 - ) -> result, stream-error>; - - /// Skip bytes from a stream. Returns number of bytes skipped. - /// - /// Behaves identical to `read`, except instead of returning a list - /// of bytes, returns the number of bytes consumed from the stream. - skip: func( - /// The maximum number of bytes to skip. - len: u64, - ) -> result; - - /// Skip bytes from a stream, after blocking until at least one byte - /// can be skipped. Except for blocking behavior, identical to `skip`. - blocking-skip: func( - /// The maximum number of bytes to skip. - len: u64, - ) -> result; - - /// Create a `pollable` which will resolve once either the specified stream - /// has bytes available to read or the other end of the stream has been - /// closed. - /// The created `pollable` is a child resource of the `input-stream`. - /// Implementations may trap if the `input-stream` is dropped before - /// all derived `pollable`s created with this function are dropped. - subscribe: func() -> pollable; - } - - - /// An output bytestream. - /// - /// `output-stream`s are *non-blocking* to the extent practical on - /// underlying platforms. Except where specified otherwise, I/O operations also - /// always return promptly, after the number of bytes that can be written - /// promptly, which could even be zero. To wait for the stream to be ready to - /// accept data, the `subscribe` function to obtain a `pollable` which can be - /// polled for using `wasi:io/poll`. - resource output-stream { - /// Check readiness for writing. This function never blocks. - /// - /// Returns the number of bytes permitted for the next call to `write`, - /// or an error. Calling `write` with more bytes than this function has - /// permitted will trap. - /// - /// When this function returns 0 bytes, the `subscribe` pollable will - /// become ready when this function will report at least 1 byte, or an - /// error. - check-write: func() -> result; - - /// Perform a write. This function never blocks. - /// - /// When the destination of a `write` is binary data, the bytes from - /// `contents` are written verbatim. When the destination of a `write` is - /// known to the implementation to be text, the bytes of `contents` are - /// transcoded from UTF-8 into the encoding of the destination and then - /// written. - /// - /// Precondition: check-write gave permit of Ok(n) and contents has a - /// length of less than or equal to n. Otherwise, this function will trap. - /// - /// returns Err(closed) without writing if the stream has closed since - /// the last call to check-write provided a permit. - write: func( - contents: list - ) -> result<_, stream-error>; - - /// Perform a write of up to 4096 bytes, and then flush the stream. Block - /// until all of these operations are complete, or an error occurs. - /// - /// This is a convenience wrapper around the use of `check-write`, - /// `subscribe`, `write`, and `flush`, and is implemented with the - /// following pseudo-code: - /// - /// ```text - /// let pollable = this.subscribe(); - /// while !contents.is_empty() { - /// // Wait for the stream to become writable - /// pollable.block(); - /// let Ok(n) = this.check-write(); // eliding error handling - /// let len = min(n, contents.len()); - /// let (chunk, rest) = contents.split_at(len); - /// this.write(chunk ); // eliding error handling - /// contents = rest; - /// } - /// this.flush(); - /// // Wait for completion of `flush` - /// pollable.block(); - /// // Check for any errors that arose during `flush` - /// let _ = this.check-write(); // eliding error handling - /// ``` - blocking-write-and-flush: func( - contents: list - ) -> result<_, stream-error>; - - /// Request to flush buffered output. This function never blocks. - /// - /// This tells the output-stream that the caller intends any buffered - /// output to be flushed. the output which is expected to be flushed - /// is all that has been passed to `write` prior to this call. - /// - /// Upon calling this function, the `output-stream` will not accept any - /// writes (`check-write` will return `ok(0)`) until the flush has - /// completed. The `subscribe` pollable will become ready when the - /// flush has completed and the stream can accept more writes. - flush: func() -> result<_, stream-error>; - - /// Request to flush buffered output, and block until flush completes - /// and stream is ready for writing again. - blocking-flush: func() -> result<_, stream-error>; - - /// Create a `pollable` which will resolve once the output-stream - /// is ready for more writing, or an error has occured. When this - /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an - /// error. - /// - /// If the stream is closed, this pollable is always ready immediately. - /// - /// The created `pollable` is a child resource of the `output-stream`. - /// Implementations may trap if the `output-stream` is dropped before - /// all derived `pollable`s created with this function are dropped. - subscribe: func() -> pollable; - - /// Write zeroes to a stream. - /// - /// This should be used precisely like `write` with the exact same - /// preconditions (must use check-write first), but instead of - /// passing a list of bytes, you simply pass the number of zero-bytes - /// that should be written. - write-zeroes: func( - /// The number of zero-bytes to write - len: u64 - ) -> result<_, stream-error>; - - /// Perform a write of up to 4096 zeroes, and then flush the stream. - /// Block until all of these operations are complete, or an error - /// occurs. - /// - /// This is a convenience wrapper around the use of `check-write`, - /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with - /// the following pseudo-code: - /// - /// ```text - /// let pollable = this.subscribe(); - /// while num_zeroes != 0 { - /// // Wait for the stream to become writable - /// pollable.block(); - /// let Ok(n) = this.check-write(); // eliding error handling - /// let len = min(n, num_zeroes); - /// this.write-zeroes(len); // eliding error handling - /// num_zeroes -= len; - /// } - /// this.flush(); - /// // Wait for completion of `flush` - /// pollable.block(); - /// // Check for any errors that arose during `flush` - /// let _ = this.check-write(); // eliding error handling - /// ``` - blocking-write-zeroes-and-flush: func( - /// The number of zero-bytes to write - len: u64 - ) -> result<_, stream-error>; - - /// Read from one stream and write to another. - /// - /// The behavior of splice is equivelant to: - /// 1. calling `check-write` on the `output-stream` - /// 2. calling `read` on the `input-stream` with the smaller of the - /// `check-write` permitted length and the `len` provided to `splice` - /// 3. calling `write` on the `output-stream` with that read data. - /// - /// Any error reported by the call to `check-write`, `read`, or - /// `write` ends the splice and reports that error. - /// - /// This function returns the number of bytes transferred; it may be less - /// than `len`. - splice: func( - /// The stream to read from - src: borrow, - /// The number of bytes to splice - len: u64, - ) -> result; - - /// Read from one stream and write to another, with blocking. - /// - /// This is similar to `splice`, except that it blocks until the - /// `output-stream` is ready for writing, and the `input-stream` - /// is ready for reading, before performing the `splice`. - blocking-splice: func( - /// The stream to read from - src: borrow, - /// The number of bytes to splice - len: u64, - ) -> result; - } -} diff --git a/surface/deps/io/world.wit b/surface/deps/io/world.wit deleted file mode 100644 index 5f0b43f..0000000 --- a/surface/deps/io/world.wit +++ /dev/null @@ -1,6 +0,0 @@ -package wasi:io@0.2.0; - -world imports { - import streams; - import poll; -} diff --git a/surface/surface.wit b/surface/surface.wit index 9242c44..a8c6e1e 100644 --- a/surface/surface.wit +++ b/surface/surface.wit @@ -1,11 +1,11 @@ -package wasi:surface@0.0.1; +package wasi:surface@0.2.0-rc.1; world imports { import surface; } interface surface { - use wasi:graphics-context/graphics-context@0.0.1.{context}; + use wasi:graphics-context/graphics-context@0.2.0-rc.1.{context}; use wasi:io/poll@0.2.0.{pollable}; record create-desc { diff --git a/surface/wkg.lock b/surface/wkg.lock new file mode 100644 index 0000000..9565d95 --- /dev/null +++ b/surface/wkg.lock @@ -0,0 +1,12 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:io" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:c33b1dbf050f64229ff4decbf9a3d3420e0643a86f5f0cea29f81054820020a6" diff --git a/surface/wkg.toml b/surface/wkg.toml new file mode 100644 index 0000000..537e9f2 --- /dev/null +++ b/surface/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"wasi:graphics-context" = { path = "../graphics-context" } diff --git a/webgpu/deps/graphics-context/graphics-context.wit b/webgpu/deps/graphics-context/graphics-context.wit deleted file mode 100644 index 9ad8745..0000000 --- a/webgpu/deps/graphics-context/graphics-context.wit +++ /dev/null @@ -1,18 +0,0 @@ -package wasi:graphics-context@0.0.1; - -world imports { - import graphics-context; -} - -interface graphics-context { - resource context { - constructor(); - - get-current-buffer: func() -> abstract-buffer; - - // TODO: might want to remove this. - present: func(); - } - - resource abstract-buffer { } -} diff --git a/webgpu/deps/io/error.wit b/webgpu/deps/io/error.wit deleted file mode 100644 index 22e5b64..0000000 --- a/webgpu/deps/io/error.wit +++ /dev/null @@ -1,34 +0,0 @@ -package wasi:io@0.2.0; - - -interface error { - /// A resource which represents some error information. - /// - /// The only method provided by this resource is `to-debug-string`, - /// which provides some human-readable information about the error. - /// - /// In the `wasi:io` package, this resource is returned through the - /// `wasi:io/streams/stream-error` type. - /// - /// To provide more specific error information, other interfaces may - /// provide functions to further "downcast" this error into more specific - /// error information. For example, `error`s returned in streams derived - /// from filesystem types to be described using the filesystem's own - /// error-code type, using the function - /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter - /// `borrow` and returns - /// `option`. - /// - /// The set of functions which can "downcast" an `error` into a more - /// concrete type is open. - resource error { - /// Returns a string that is suitable to assist humans in debugging - /// this error. - /// - /// WARNING: The returned string should not be consumed mechanically! - /// It may change across platforms, hosts, or other implementation - /// details. Parsing this string is a major platform-compatibility - /// hazard. - to-debug-string: func() -> string; - } -} diff --git a/webgpu/deps/io/poll.wit b/webgpu/deps/io/poll.wit deleted file mode 100644 index ddc67f8..0000000 --- a/webgpu/deps/io/poll.wit +++ /dev/null @@ -1,41 +0,0 @@ -package wasi:io@0.2.0; - -/// A poll API intended to let users wait for I/O events on multiple handles -/// at once. -interface poll { - /// `pollable` represents a single I/O event which may be ready, or not. - resource pollable { - - /// Return the readiness of a pollable. This function never blocks. - /// - /// Returns `true` when the pollable is ready, and `false` otherwise. - ready: func() -> bool; - - /// `block` returns immediately if the pollable is ready, and otherwise - /// blocks until ready. - /// - /// This function is equivalent to calling `poll.poll` on a list - /// containing only this pollable. - block: func(); - } - - /// Poll for completion on a set of pollables. - /// - /// This function takes a list of pollables, which identify I/O sources of - /// interest, and waits until one or more of the events is ready for I/O. - /// - /// The result `list` contains one or more indices of handles in the - /// argument list that is ready for I/O. - /// - /// If the list contains more elements than can be indexed with a `u32` - /// value, this function traps. - /// - /// A timeout can be implemented by adding a pollable from the - /// wasi-clocks API to the list. - /// - /// This function does not return a `result`; polling in itself does not - /// do any I/O so it doesn't fail. If any of the I/O sources identified by - /// the pollables has an error, it is indicated by marking the source as - /// being reaedy for I/O. - poll: func(in: list>) -> list; -} diff --git a/webgpu/deps/io/streams.wit b/webgpu/deps/io/streams.wit deleted file mode 100644 index 6d2f871..0000000 --- a/webgpu/deps/io/streams.wit +++ /dev/null @@ -1,262 +0,0 @@ -package wasi:io@0.2.0; - -/// WASI I/O is an I/O abstraction API which is currently focused on providing -/// stream types. -/// -/// In the future, the component model is expected to add built-in stream types; -/// when it does, they are expected to subsume this API. -interface streams { - use error.{error}; - use poll.{pollable}; - - /// An error for input-stream and output-stream operations. - variant stream-error { - /// The last operation (a write or flush) failed before completion. - /// - /// More information is available in the `error` payload. - last-operation-failed(error), - /// The stream is closed: no more input will be accepted by the - /// stream. A closed output-stream will return this error on all - /// future operations. - closed - } - - /// An input bytestream. - /// - /// `input-stream`s are *non-blocking* to the extent practical on underlying - /// platforms. I/O operations always return promptly; if fewer bytes are - /// promptly available than requested, they return the number of bytes promptly - /// available, which could even be zero. To wait for data to be available, - /// use the `subscribe` function to obtain a `pollable` which can be polled - /// for using `wasi:io/poll`. - resource input-stream { - /// Perform a non-blocking read from the stream. - /// - /// When the source of a `read` is binary data, the bytes from the source - /// are returned verbatim. When the source of a `read` is known to the - /// implementation to be text, bytes containing the UTF-8 encoding of the - /// text are returned. - /// - /// This function returns a list of bytes containing the read data, - /// when successful. The returned list will contain up to `len` bytes; - /// it may return fewer than requested, but not more. The list is - /// empty when no bytes are available for reading at this time. The - /// pollable given by `subscribe` will be ready when more bytes are - /// available. - /// - /// This function fails with a `stream-error` when the operation - /// encounters an error, giving `last-operation-failed`, or when the - /// stream is closed, giving `closed`. - /// - /// When the caller gives a `len` of 0, it represents a request to - /// read 0 bytes. If the stream is still open, this call should - /// succeed and return an empty list, or otherwise fail with `closed`. - /// - /// The `len` parameter is a `u64`, which could represent a list of u8 which - /// is not possible to allocate in wasm32, or not desirable to allocate as - /// as a return value by the callee. The callee may return a list of bytes - /// less than `len` in size while more bytes are available for reading. - read: func( - /// The maximum number of bytes to read - len: u64 - ) -> result, stream-error>; - - /// Read bytes from a stream, after blocking until at least one byte can - /// be read. Except for blocking, behavior is identical to `read`. - blocking-read: func( - /// The maximum number of bytes to read - len: u64 - ) -> result, stream-error>; - - /// Skip bytes from a stream. Returns number of bytes skipped. - /// - /// Behaves identical to `read`, except instead of returning a list - /// of bytes, returns the number of bytes consumed from the stream. - skip: func( - /// The maximum number of bytes to skip. - len: u64, - ) -> result; - - /// Skip bytes from a stream, after blocking until at least one byte - /// can be skipped. Except for blocking behavior, identical to `skip`. - blocking-skip: func( - /// The maximum number of bytes to skip. - len: u64, - ) -> result; - - /// Create a `pollable` which will resolve once either the specified stream - /// has bytes available to read or the other end of the stream has been - /// closed. - /// The created `pollable` is a child resource of the `input-stream`. - /// Implementations may trap if the `input-stream` is dropped before - /// all derived `pollable`s created with this function are dropped. - subscribe: func() -> pollable; - } - - - /// An output bytestream. - /// - /// `output-stream`s are *non-blocking* to the extent practical on - /// underlying platforms. Except where specified otherwise, I/O operations also - /// always return promptly, after the number of bytes that can be written - /// promptly, which could even be zero. To wait for the stream to be ready to - /// accept data, the `subscribe` function to obtain a `pollable` which can be - /// polled for using `wasi:io/poll`. - resource output-stream { - /// Check readiness for writing. This function never blocks. - /// - /// Returns the number of bytes permitted for the next call to `write`, - /// or an error. Calling `write` with more bytes than this function has - /// permitted will trap. - /// - /// When this function returns 0 bytes, the `subscribe` pollable will - /// become ready when this function will report at least 1 byte, or an - /// error. - check-write: func() -> result; - - /// Perform a write. This function never blocks. - /// - /// When the destination of a `write` is binary data, the bytes from - /// `contents` are written verbatim. When the destination of a `write` is - /// known to the implementation to be text, the bytes of `contents` are - /// transcoded from UTF-8 into the encoding of the destination and then - /// written. - /// - /// Precondition: check-write gave permit of Ok(n) and contents has a - /// length of less than or equal to n. Otherwise, this function will trap. - /// - /// returns Err(closed) without writing if the stream has closed since - /// the last call to check-write provided a permit. - write: func( - contents: list - ) -> result<_, stream-error>; - - /// Perform a write of up to 4096 bytes, and then flush the stream. Block - /// until all of these operations are complete, or an error occurs. - /// - /// This is a convenience wrapper around the use of `check-write`, - /// `subscribe`, `write`, and `flush`, and is implemented with the - /// following pseudo-code: - /// - /// ```text - /// let pollable = this.subscribe(); - /// while !contents.is_empty() { - /// // Wait for the stream to become writable - /// pollable.block(); - /// let Ok(n) = this.check-write(); // eliding error handling - /// let len = min(n, contents.len()); - /// let (chunk, rest) = contents.split_at(len); - /// this.write(chunk ); // eliding error handling - /// contents = rest; - /// } - /// this.flush(); - /// // Wait for completion of `flush` - /// pollable.block(); - /// // Check for any errors that arose during `flush` - /// let _ = this.check-write(); // eliding error handling - /// ``` - blocking-write-and-flush: func( - contents: list - ) -> result<_, stream-error>; - - /// Request to flush buffered output. This function never blocks. - /// - /// This tells the output-stream that the caller intends any buffered - /// output to be flushed. the output which is expected to be flushed - /// is all that has been passed to `write` prior to this call. - /// - /// Upon calling this function, the `output-stream` will not accept any - /// writes (`check-write` will return `ok(0)`) until the flush has - /// completed. The `subscribe` pollable will become ready when the - /// flush has completed and the stream can accept more writes. - flush: func() -> result<_, stream-error>; - - /// Request to flush buffered output, and block until flush completes - /// and stream is ready for writing again. - blocking-flush: func() -> result<_, stream-error>; - - /// Create a `pollable` which will resolve once the output-stream - /// is ready for more writing, or an error has occured. When this - /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an - /// error. - /// - /// If the stream is closed, this pollable is always ready immediately. - /// - /// The created `pollable` is a child resource of the `output-stream`. - /// Implementations may trap if the `output-stream` is dropped before - /// all derived `pollable`s created with this function are dropped. - subscribe: func() -> pollable; - - /// Write zeroes to a stream. - /// - /// This should be used precisely like `write` with the exact same - /// preconditions (must use check-write first), but instead of - /// passing a list of bytes, you simply pass the number of zero-bytes - /// that should be written. - write-zeroes: func( - /// The number of zero-bytes to write - len: u64 - ) -> result<_, stream-error>; - - /// Perform a write of up to 4096 zeroes, and then flush the stream. - /// Block until all of these operations are complete, or an error - /// occurs. - /// - /// This is a convenience wrapper around the use of `check-write`, - /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with - /// the following pseudo-code: - /// - /// ```text - /// let pollable = this.subscribe(); - /// while num_zeroes != 0 { - /// // Wait for the stream to become writable - /// pollable.block(); - /// let Ok(n) = this.check-write(); // eliding error handling - /// let len = min(n, num_zeroes); - /// this.write-zeroes(len); // eliding error handling - /// num_zeroes -= len; - /// } - /// this.flush(); - /// // Wait for completion of `flush` - /// pollable.block(); - /// // Check for any errors that arose during `flush` - /// let _ = this.check-write(); // eliding error handling - /// ``` - blocking-write-zeroes-and-flush: func( - /// The number of zero-bytes to write - len: u64 - ) -> result<_, stream-error>; - - /// Read from one stream and write to another. - /// - /// The behavior of splice is equivelant to: - /// 1. calling `check-write` on the `output-stream` - /// 2. calling `read` on the `input-stream` with the smaller of the - /// `check-write` permitted length and the `len` provided to `splice` - /// 3. calling `write` on the `output-stream` with that read data. - /// - /// Any error reported by the call to `check-write`, `read`, or - /// `write` ends the splice and reports that error. - /// - /// This function returns the number of bytes transferred; it may be less - /// than `len`. - splice: func( - /// The stream to read from - src: borrow, - /// The number of bytes to splice - len: u64, - ) -> result; - - /// Read from one stream and write to another, with blocking. - /// - /// This is similar to `splice`, except that it blocks until the - /// `output-stream` is ready for writing, and the `input-stream` - /// is ready for reading, before performing the `splice`. - blocking-splice: func( - /// The stream to read from - src: borrow, - /// The number of bytes to splice - len: u64, - ) -> result; - } -} diff --git a/webgpu/deps/io/world.wit b/webgpu/deps/io/world.wit deleted file mode 100644 index 5f0b43f..0000000 --- a/webgpu/deps/io/world.wit +++ /dev/null @@ -1,6 +0,0 @@ -package wasi:io@0.2.0; - -world imports { - import streams; - import poll; -} diff --git a/webgpu/imports.wit b/webgpu/imports.wit index 774b702..f3dec18 100644 --- a/webgpu/imports.wit +++ b/webgpu/imports.wit @@ -1,4 +1,4 @@ -package wasi:webgpu@0.0.1; +package wasi:webgpu@0.2.0-rc.1; world imports { import webgpu; diff --git a/webgpu/webgpu.wit b/webgpu/webgpu.wit index b06a22e..1d929f3 100644 --- a/webgpu/webgpu.wit +++ b/webgpu/webgpu.wit @@ -1,8 +1,8 @@ -package wasi:webgpu@0.0.1; +package wasi:webgpu@0.2.0-rc.1; interface webgpu { use wasi:io/poll@0.2.0.{ pollable }; - use wasi:graphics-context/graphics-context@0.0.1.{ context, abstract-buffer }; + use wasi:graphics-context/graphics-context@0.2.0-rc.1.{ context, abstract-buffer }; resource gpu-supported-limits { max-texture-dimension1-d: func() -> u32; max-texture-dimension2-d: func() -> u32; diff --git a/webgpu/wkg.lock b/webgpu/wkg.lock new file mode 100644 index 0000000..9565d95 --- /dev/null +++ b/webgpu/wkg.lock @@ -0,0 +1,12 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:io" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:c33b1dbf050f64229ff4decbf9a3d3420e0643a86f5f0cea29f81054820020a6" diff --git a/webgpu/wkg.toml b/webgpu/wkg.toml new file mode 100644 index 0000000..537e9f2 --- /dev/null +++ b/webgpu/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"wasi:graphics-context" = { path = "../graphics-context" } From 74289a20af765cc99c5b37fcd022b7d8dc9b43ad Mon Sep 17 00:00:00 2001 From: Bailey Hayes Date: Tue, 10 Mar 2026 15:30:09 -0400 Subject: [PATCH 2/2] fix: update install-wit-deps.sh --- install-wit-deps.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/install-wit-deps.sh b/install-wit-deps.sh index 67baf7d..faae159 100755 --- a/install-wit-deps.sh +++ b/install-wit-deps.sh @@ -1,4 +1,3 @@ -wit-deps -m webgpu/deps.toml -l webgpu/deps.lock -d webgpu/deps update -wit-deps -m surface/deps.toml -l surface/deps.lock -d surface/deps update -wit-deps -m graphics-context/deps.toml -l graphics-context/deps.lock -d graphics-context/deps update -wit-deps -m frame-buffer/deps.toml -l frame-buffer/deps.lock -d frame-buffer/deps update +for pkg in graphics-context webgpu surface frame-buffer; do + (cd "$pkg" && wkg wit fetch -d .) +done