├── .github └── workflows │ └── main.yml ├── .gitmodules ├── LICENSE.md ├── README.md ├── build-docs.sh ├── frame-buffer ├── deps.lock ├── deps.toml ├── deps │ └── graphics-context │ │ └── graphics-context.wit ├── frame-buffer.wit └── imports.md ├── graphics-context ├── deps.lock ├── deps.toml ├── graphics-context.wit └── imports.md ├── install-wit-deps.sh ├── surface ├── deps.lock ├── deps.toml ├── deps │ ├── graphics-context │ │ └── graphics-context.wit │ └── io │ │ ├── error.wit │ │ ├── poll.wit │ │ ├── streams.wit │ │ └── world.wit ├── imports.md └── surface.wit ├── test ├── README.md └── ensure-parses │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs └── webgpu ├── deps.lock ├── deps.toml ├── deps ├── graphics-context │ └── graphics-context.wit └── io │ ├── error.wit │ ├── poll.wit │ ├── streams.wit │ └── world.wit ├── generate ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── generate.sh ├── src │ └── main.rs └── webgpu-transforms.json ├── imports.md ├── imports.wit └── webgpu.wit /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [main] 5 | pull_request: 6 | branches: [main] 7 | 8 | jobs: 9 | abi-up-to-date: 10 | name: Check ABI files are up-to-date 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: WebAssembly/wit-abi-up-to-date@v22 15 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "webgpu/generate/webgpu-spec"] 2 | path = webgpu/generate/webgpu-spec 3 | url = https://github.com/gpuweb/gpuweb.git 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2019-2023 the Contributors to the WASI Specification, published 2 | by the [WebAssembly Community Group][cg] under the 3 | [W3C Community Contributor License Agreement (CLA)][cla]. A human-readable 4 | [summary][summary] is available. 5 | 6 | [cg]: https://www.w3.org/community/webassembly/ 7 | [cla]: https://www.w3.org/community/about/agreements/cla/ 8 | [summary]: https://www.w3.org/community/about/agreements/cla-deed/ 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WASI-GFX 2 | 3 | A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) API. 4 | 5 | ### Current Phase 6 | 7 | Phase 2 8 | 9 | ### Champions 10 | 11 | - Mendy Berger 12 | - Sean Isom 13 | 14 | ### Portability Criteria 15 | 16 | Linux, Window, MacOS, Android, Web. 17 | 18 | ## Table of Contents [if the explainer is longer than one printed page] 19 | 20 | - [Introduction](#introduction) 21 | - [Goals [or Motivating Use Cases, or Scenarios]](#goals-or-motivating-use-cases-or-scenarios) 22 | - [Non-goals](#non-goals) 23 | - [API walk-through](#api-walk-through) 24 | - [Use case 1](#use-case-1) 25 | - [Use case 2](#use-case-2) 26 | - [Detailed design discussion](#detailed-design-discussion) 27 | - [[Tricky design choice 1]](#tricky-design-choice-1) 28 | - [[Tricky design choice 2]](#tricky-design-choice-2) 29 | - [Considered alternatives](#considered-alternatives) 30 | - [[Alternative 1]](#alternative-1) 31 | - [[Alternative 2]](#alternative-2) 32 | - [Stakeholder Interest & Feedback](#stakeholder-interest--feedback) 33 | - [References & acknowledgements](#references--acknowledgements) 34 | 35 | ### Introduction 36 | 37 | This proposal is a collection of multiple packages. 38 | 39 | | Package | Description | 40 | | ------------------------| ---------------------------------------------------------------------------------- | 41 | | `wasi:webgpu` | WebGPU package for interacting with GPUs | 42 | | `wasi:frame-buffer` | A CPU based graphics API | 43 | | `wasi:surface` | A surface | 44 | | `wasi:graphics-context` | A small interface connecting the graphics APIs (webgpu or frame-buffer) to surface | 45 | 46 | 47 | ### Goals [or Motivating Use Cases, or Scenarios] 48 | 49 | - Bring some of the benefits that Wasm provides to CPU code, over to GPU code. 50 | - Enable secure GPU compute. 51 | - Enable wasm-based UI applications. 52 | - Enable wasm-based graphics even in environments with no GPUs. 53 | - Enable wasm-based AI for cases not covered by wasi-nn. 54 | 55 | ### Non-goals 56 | 57 | - A full windowing API. 58 | - VR/AR (subject to change, if we find contributors with expertise in the field). 59 | 60 | ### API walk-through 61 | 62 | The full API documentation can be found in [imports.md](imports.md). 63 | 64 | #### `wasi:webgpu` 65 | 66 | `wasi:webgpu` is based on the official [webgpu spec](https://www.w3.org/TR/webgpu/). 67 | 68 | `wasi:webgpu` does deviate sometimes from the webgpu spec, namely, in cases where the spec makes assumptions about running in a web or JS environment. Wherever `wasi:webgpu` deviates from the spec, a clear explanation should be documented. 69 | 70 | #### `wasi:surface` 71 | 72 | `wasi:surface` is a basic surface API. It lets you create a surface you can draw to (similar to canvas on web). You can also get basic user events from the surface, like pointer and keyboard events. 73 | 74 | `wasi:surface` supports the following event types: 75 | - Pointer: For mouse/touch/pencil/etc. 76 | - Key: For keyboard events. 77 | - Resize: Surface was resized. 78 | - Frame: Fires on each frame. (similar to [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) on the web) 79 | 80 | Other user input, such as scroll wheel, clipboard, drag-over, device motion, device orientation, gamepad input, etc., are all useful in many applications, but since they're a bit less common, they're out of scope for now. However, they might be added eventually. 81 | 82 | #### `wasi:frame-buffer` 83 | 84 | A simple frame buffer API for CPU-based rendering. 85 | 86 | This might be especially useful in embedded. 87 | 88 | #### `wasi:graphics-context` 89 | 90 | `wasi:graphics-context` is the point of connection between a graphics API (`wasi:webgpu`, `wasi:frame-buffer`, future graphics API) to a windowing system (`wasi:surface`, future windowing system). See diagram. 91 | 92 | ![image](https://github.com/user-attachments/assets/55bcc436-7bcd-4f02-9090-888106b889ef) 93 | 94 | `wasi:graphics-context` has a method to get the next frame as an `abstract-buffer`. Abstract buffer's contents can't be read. Instead, the graphics API in use can turn the `abstract-buffer` into something it can make use of. E.g. webgpu is able to turn the buffer into a `GPUTexture`. The runtime can easily, in the background, represent the `abstract-buffer` as a `GPUTexture`, and the conversion would just be a no-op. 95 | 96 | #### [Use case 1] 97 | 98 | [Provide example code snippets and diagrams explaining how the API would be used to solve the given problem] 99 | 100 | #### [Use case 2] 101 | 102 | [etc.] 103 | 104 | ### Detailed design discussion 105 | 106 | [This section should mostly refer to the .wit.md file that specifies the API. This section is for any discussion of the choices made in the API which don't make sense to document in the spec file itself.] 107 | 108 | #### [Tricky design choice #1] 109 | 110 | [Talk through the tradeoffs in coming to the specific design point you want to make.] 111 | 112 | ``` 113 | // Illustrated with example code. 114 | ``` 115 | 116 | [This may be an open question, in which case you should link to any active discussion threads.] 117 | 118 | #### [Tricky design choice 2] 119 | 120 | [etc.] 121 | 122 | ### Considered alternatives 123 | 124 | [This section is not required if you already covered considered alternatives in the design discussion above.] 125 | 126 | #### [Alternative 1] 127 | 128 | [Describe an alternative which was considered, and why you decided against it.] 129 | 130 | #### [Alternative 2] 131 | 132 | [etc.] 133 | 134 | ### Stakeholder Interest & Feedback 135 | 136 | TODO before entering Phase 3. 137 | 138 | [This should include a list of implementers who have expressed interest in implementing the proposal] 139 | 140 | ### References & acknowledgements 141 | 142 | Many thanks for valuable feedback and advice from: 143 | 144 | - [Person 1] 145 | - [Person 2] 146 | - [etc.] 147 | -------------------------------------------------------------------------------- /build-docs.sh: -------------------------------------------------------------------------------- 1 | wit-bindgen markdown --html-in-md ./graphics-context --out-dir ./graphics-context 2 | wit-bindgen markdown --html-in-md ./surface --out-dir ./surface 3 | wit-bindgen markdown --html-in-md ./webgpu --out-dir ./webgpu 4 | wit-bindgen markdown --html-in-md ./frame-buffer --out-dir ./frame-buffer 5 | -------------------------------------------------------------------------------- /frame-buffer/deps.lock: -------------------------------------------------------------------------------- 1 | [graphics-context] 2 | path = "../graphics-context" 3 | sha256 = "b138ab44463c5bb074207687c88d59dfca9c6bc7a5dad482dba626094cccbc3f" 4 | sha512 = "b9cef19d2cf0a0f3d0a58c94cf4483d051acfb5622e379bf0abcc6aa34c14d92210c56554387b932f08aba3c9c1e9e9cadb554e9dd0cf464b20c7d31c806515e" 5 | -------------------------------------------------------------------------------- /frame-buffer/deps.toml: -------------------------------------------------------------------------------- 1 | [graphics-context] 2 | path = "../graphics-context" 3 | -------------------------------------------------------------------------------- /frame-buffer/deps/graphics-context/graphics-context.wit: -------------------------------------------------------------------------------- 1 | package wasi:graphics-context@0.0.1; 2 | 3 | world imports { 4 | import graphics-context; 5 | } 6 | 7 | interface graphics-context { 8 | resource context { 9 | constructor(); 10 | 11 | get-current-buffer: func() -> abstract-buffer; 12 | 13 | // TODO: might want to remove this. 14 | present: func(); 15 | } 16 | 17 | resource abstract-buffer { } 18 | } 19 | -------------------------------------------------------------------------------- /frame-buffer/frame-buffer.wit: -------------------------------------------------------------------------------- 1 | package wasi:frame-buffer@0.0.1; 2 | 3 | world imports { 4 | import frame-buffer; 5 | } 6 | 7 | interface frame-buffer { 8 | use wasi:graphics-context/graphics-context@0.0.1.{context, abstract-buffer}; 9 | 10 | resource device { 11 | constructor(); 12 | 13 | connect-graphics-context: func(context: borrow); 14 | } 15 | 16 | resource buffer { 17 | from-graphics-buffer: static func(buffer: abstract-buffer) -> buffer; 18 | 19 | // TODO: This should be replcated with something that doesn't require a copy. 20 | get: func() -> list; 21 | set: func(val: list); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frame-buffer/imports.md: -------------------------------------------------------------------------------- 1 |

World imports

2 | 10 |

Import interface wasi:graphics-context/graphics-context

11 |
12 |

Types

13 |

resource context

14 |

resource abstract-buffer

15 |
16 |

Functions

17 |

[constructor]context: func

18 |
Return values
19 | 22 |

[method]context.get-current-buffer: func

23 |
Params
24 | 27 |
Return values
28 | 31 |

[method]context.present: func

32 |

TODO: might want to remove this.

33 |
Params
34 | 37 |

Import interface wasi:frame-buffer/frame-buffer

38 |
39 |

Types

40 |

type context

41 |

context

42 |

43 | #### `type abstract-buffer` 44 | [`abstract-buffer`](#abstract_buffer) 45 |

46 | #### `resource device` 47 |

resource buffer

48 |
49 |

Functions

50 |

[constructor]device: func

51 |
Return values
52 | 55 |

[method]device.connect-graphics-context: func

56 |
Params
57 | 61 |

[static]buffer.from-graphics-buffer: func

62 |
Params
63 | 66 |
Return values
67 | 70 |

[method]buffer.get: func

71 |

TODO: This should be replcated with something that doesn't require a copy.

72 |
Params
73 |
    74 |
  • self: borrow<buffer>
  • 75 |
76 |
Return values
77 |
    78 |
  • list<u8>
  • 79 |
80 |

[method]buffer.set: func

81 |
Params
82 |
    83 |
  • self: borrow<buffer>
  • 84 |
  • val: list<u8>
  • 85 |
86 | -------------------------------------------------------------------------------- /graphics-context/deps.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebAssembly/wasi-gfx/6c0d2244daf997cae7aed19cb1c2b38df011a41c/graphics-context/deps.lock -------------------------------------------------------------------------------- /graphics-context/deps.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebAssembly/wasi-gfx/6c0d2244daf997cae7aed19cb1c2b38df011a41c/graphics-context/deps.toml -------------------------------------------------------------------------------- /graphics-context/graphics-context.wit: -------------------------------------------------------------------------------- 1 | package wasi:graphics-context@0.0.1; 2 | 3 | world imports { 4 | import graphics-context; 5 | } 6 | 7 | interface graphics-context { 8 | resource context { 9 | constructor(); 10 | 11 | get-current-buffer: func() -> abstract-buffer; 12 | 13 | // TODO: might want to remove this. 14 | present: func(); 15 | } 16 | 17 | resource abstract-buffer { } 18 | } 19 | -------------------------------------------------------------------------------- /graphics-context/imports.md: -------------------------------------------------------------------------------- 1 |

World imports

2 | 9 |

Import interface wasi:graphics-context/graphics-context

10 |
11 |

Types

12 |

resource context

13 |

resource abstract-buffer

14 |
15 |

Functions

16 |

[constructor]context: func

17 |
Return values
18 | 21 |

[method]context.get-current-buffer: func

22 |
Params
23 | 26 |
Return values
27 | 30 |

[method]context.present: func

31 |

TODO: might want to remove this.

32 |
Params
33 | 36 | -------------------------------------------------------------------------------- /install-wit-deps.sh: -------------------------------------------------------------------------------- 1 | wit-deps -m webgpu/deps.toml -l webgpu/deps.lock -d webgpu/deps update 2 | wit-deps -m surface/deps.toml -l surface/deps.lock -d surface/deps update 3 | wit-deps -m graphics-context/deps.toml -l graphics-context/deps.lock -d graphics-context/deps update 4 | wit-deps -m frame-buffer/deps.toml -l frame-buffer/deps.lock -d frame-buffer/deps update 5 | -------------------------------------------------------------------------------- /surface/deps.lock: -------------------------------------------------------------------------------- 1 | [graphics-context] 2 | path = "../graphics-context" 3 | sha256 = "b138ab44463c5bb074207687c88d59dfca9c6bc7a5dad482dba626094cccbc3f" 4 | sha512 = "b9cef19d2cf0a0f3d0a58c94cf4483d051acfb5622e379bf0abcc6aa34c14d92210c56554387b932f08aba3c9c1e9e9cadb554e9dd0cf464b20c7d31c806515e" 5 | 6 | [io] 7 | url = "https://github.com/WebAssembly/wasi-io/archive/fef02cddb4ac28dcde97bf11a4c7b856833a948f.tar.gz" 8 | sha256 = "7210e5653539a15478f894d4da24cc69d61924cbcba21d2804d69314a88e5a4c" 9 | sha512 = "49184a1b0945a889abd52d25271172ed3dc2db6968fcdddb1bab7ee0081f4a3eeee0977ad2291126a37631c0d86eeea75d822fa8af224c422134500bf9f0f2bb" 10 | -------------------------------------------------------------------------------- /surface/deps.toml: -------------------------------------------------------------------------------- 1 | io = "https://github.com/WebAssembly/wasi-io/archive/fef02cddb4ac28dcde97bf11a4c7b856833a948f.tar.gz" 2 | 3 | [graphics-context] 4 | path = "../graphics-context" 5 | -------------------------------------------------------------------------------- /surface/deps/graphics-context/graphics-context.wit: -------------------------------------------------------------------------------- 1 | package wasi:graphics-context@0.0.1; 2 | 3 | world imports { 4 | import graphics-context; 5 | } 6 | 7 | interface graphics-context { 8 | resource context { 9 | constructor(); 10 | 11 | get-current-buffer: func() -> abstract-buffer; 12 | 13 | // TODO: might want to remove this. 14 | present: func(); 15 | } 16 | 17 | resource abstract-buffer { } 18 | } 19 | -------------------------------------------------------------------------------- /surface/deps/io/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// provide functions to further "downcast" this error into more specific 15 | /// error information. For example, `error`s returned in streams derived 16 | /// from filesystem types to be described using the filesystem's own 17 | /// error-code type, using the function 18 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter 19 | /// `borrow` and returns 20 | /// `option`. 21 | /// 22 | /// The set of functions which can "downcast" an `error` into a more 23 | /// concrete type is open. 24 | resource error { 25 | /// Returns a string that is suitable to assist humans in debugging 26 | /// this error. 27 | /// 28 | /// WARNING: The returned string should not be consumed mechanically! 29 | /// It may change across platforms, hosts, or other implementation 30 | /// details. Parsing this string is a major platform-compatibility 31 | /// hazard. 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /surface/deps/io/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | interface poll { 6 | /// `pollable` represents a single I/O event which may be ready, or not. 7 | resource pollable { 8 | 9 | /// Return the readiness of a pollable. This function never blocks. 10 | /// 11 | /// Returns `true` when the pollable is ready, and `false` otherwise. 12 | ready: func() -> bool; 13 | 14 | /// `block` returns immediately if the pollable is ready, and otherwise 15 | /// blocks until ready. 16 | /// 17 | /// This function is equivalent to calling `poll.poll` on a list 18 | /// containing only this pollable. 19 | block: func(); 20 | } 21 | 22 | /// Poll for completion on a set of pollables. 23 | /// 24 | /// This function takes a list of pollables, which identify I/O sources of 25 | /// interest, and waits until one or more of the events is ready for I/O. 26 | /// 27 | /// The result `list` contains one or more indices of handles in the 28 | /// argument list that is ready for I/O. 29 | /// 30 | /// If the list contains more elements than can be indexed with a `u32` 31 | /// value, this function traps. 32 | /// 33 | /// A timeout can be implemented by adding a pollable from the 34 | /// wasi-clocks API to the list. 35 | /// 36 | /// This function does not return a `result`; polling in itself does not 37 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 38 | /// the pollables has an error, it is indicated by marking the source as 39 | /// being reaedy for I/O. 40 | poll: func(in: list>) -> list; 41 | } 42 | -------------------------------------------------------------------------------- /surface/deps/io/streams.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | /// WASI I/O is an I/O abstraction API which is currently focused on providing 4 | /// stream types. 5 | /// 6 | /// In the future, the component model is expected to add built-in stream types; 7 | /// when it does, they are expected to subsume this API. 8 | interface streams { 9 | use error.{error}; 10 | use poll.{pollable}; 11 | 12 | /// An error for input-stream and output-stream operations. 13 | variant stream-error { 14 | /// The last operation (a write or flush) failed before completion. 15 | /// 16 | /// More information is available in the `error` payload. 17 | last-operation-failed(error), 18 | /// The stream is closed: no more input will be accepted by the 19 | /// stream. A closed output-stream will return this error on all 20 | /// future operations. 21 | closed 22 | } 23 | 24 | /// An input bytestream. 25 | /// 26 | /// `input-stream`s are *non-blocking* to the extent practical on underlying 27 | /// platforms. I/O operations always return promptly; if fewer bytes are 28 | /// promptly available than requested, they return the number of bytes promptly 29 | /// available, which could even be zero. To wait for data to be available, 30 | /// use the `subscribe` function to obtain a `pollable` which can be polled 31 | /// for using `wasi:io/poll`. 32 | resource input-stream { 33 | /// Perform a non-blocking read from the stream. 34 | /// 35 | /// When the source of a `read` is binary data, the bytes from the source 36 | /// are returned verbatim. When the source of a `read` is known to the 37 | /// implementation to be text, bytes containing the UTF-8 encoding of the 38 | /// text are returned. 39 | /// 40 | /// This function returns a list of bytes containing the read data, 41 | /// when successful. The returned list will contain up to `len` bytes; 42 | /// it may return fewer than requested, but not more. The list is 43 | /// empty when no bytes are available for reading at this time. The 44 | /// pollable given by `subscribe` will be ready when more bytes are 45 | /// available. 46 | /// 47 | /// This function fails with a `stream-error` when the operation 48 | /// encounters an error, giving `last-operation-failed`, or when the 49 | /// stream is closed, giving `closed`. 50 | /// 51 | /// When the caller gives a `len` of 0, it represents a request to 52 | /// read 0 bytes. If the stream is still open, this call should 53 | /// succeed and return an empty list, or otherwise fail with `closed`. 54 | /// 55 | /// The `len` parameter is a `u64`, which could represent a list of u8 which 56 | /// is not possible to allocate in wasm32, or not desirable to allocate as 57 | /// as a return value by the callee. The callee may return a list of bytes 58 | /// less than `len` in size while more bytes are available for reading. 59 | read: func( 60 | /// The maximum number of bytes to read 61 | len: u64 62 | ) -> result, stream-error>; 63 | 64 | /// Read bytes from a stream, after blocking until at least one byte can 65 | /// be read. Except for blocking, behavior is identical to `read`. 66 | blocking-read: func( 67 | /// The maximum number of bytes to read 68 | len: u64 69 | ) -> result, stream-error>; 70 | 71 | /// Skip bytes from a stream. Returns number of bytes skipped. 72 | /// 73 | /// Behaves identical to `read`, except instead of returning a list 74 | /// of bytes, returns the number of bytes consumed from the stream. 75 | skip: func( 76 | /// The maximum number of bytes to skip. 77 | len: u64, 78 | ) -> result; 79 | 80 | /// Skip bytes from a stream, after blocking until at least one byte 81 | /// can be skipped. Except for blocking behavior, identical to `skip`. 82 | blocking-skip: func( 83 | /// The maximum number of bytes to skip. 84 | len: u64, 85 | ) -> result; 86 | 87 | /// Create a `pollable` which will resolve once either the specified stream 88 | /// has bytes available to read or the other end of the stream has been 89 | /// closed. 90 | /// The created `pollable` is a child resource of the `input-stream`. 91 | /// Implementations may trap if the `input-stream` is dropped before 92 | /// all derived `pollable`s created with this function are dropped. 93 | subscribe: func() -> pollable; 94 | } 95 | 96 | 97 | /// An output bytestream. 98 | /// 99 | /// `output-stream`s are *non-blocking* to the extent practical on 100 | /// underlying platforms. Except where specified otherwise, I/O operations also 101 | /// always return promptly, after the number of bytes that can be written 102 | /// promptly, which could even be zero. To wait for the stream to be ready to 103 | /// accept data, the `subscribe` function to obtain a `pollable` which can be 104 | /// polled for using `wasi:io/poll`. 105 | resource output-stream { 106 | /// Check readiness for writing. This function never blocks. 107 | /// 108 | /// Returns the number of bytes permitted for the next call to `write`, 109 | /// or an error. Calling `write` with more bytes than this function has 110 | /// permitted will trap. 111 | /// 112 | /// When this function returns 0 bytes, the `subscribe` pollable will 113 | /// become ready when this function will report at least 1 byte, or an 114 | /// error. 115 | check-write: func() -> result; 116 | 117 | /// Perform a write. This function never blocks. 118 | /// 119 | /// When the destination of a `write` is binary data, the bytes from 120 | /// `contents` are written verbatim. When the destination of a `write` is 121 | /// known to the implementation to be text, the bytes of `contents` are 122 | /// transcoded from UTF-8 into the encoding of the destination and then 123 | /// written. 124 | /// 125 | /// Precondition: check-write gave permit of Ok(n) and contents has a 126 | /// length of less than or equal to n. Otherwise, this function will trap. 127 | /// 128 | /// returns Err(closed) without writing if the stream has closed since 129 | /// the last call to check-write provided a permit. 130 | write: func( 131 | contents: list 132 | ) -> result<_, stream-error>; 133 | 134 | /// Perform a write of up to 4096 bytes, and then flush the stream. Block 135 | /// until all of these operations are complete, or an error occurs. 136 | /// 137 | /// This is a convenience wrapper around the use of `check-write`, 138 | /// `subscribe`, `write`, and `flush`, and is implemented with the 139 | /// following pseudo-code: 140 | /// 141 | /// ```text 142 | /// let pollable = this.subscribe(); 143 | /// while !contents.is_empty() { 144 | /// // Wait for the stream to become writable 145 | /// pollable.block(); 146 | /// let Ok(n) = this.check-write(); // eliding error handling 147 | /// let len = min(n, contents.len()); 148 | /// let (chunk, rest) = contents.split_at(len); 149 | /// this.write(chunk ); // eliding error handling 150 | /// contents = rest; 151 | /// } 152 | /// this.flush(); 153 | /// // Wait for completion of `flush` 154 | /// pollable.block(); 155 | /// // Check for any errors that arose during `flush` 156 | /// let _ = this.check-write(); // eliding error handling 157 | /// ``` 158 | blocking-write-and-flush: func( 159 | contents: list 160 | ) -> result<_, stream-error>; 161 | 162 | /// Request to flush buffered output. This function never blocks. 163 | /// 164 | /// This tells the output-stream that the caller intends any buffered 165 | /// output to be flushed. the output which is expected to be flushed 166 | /// is all that has been passed to `write` prior to this call. 167 | /// 168 | /// Upon calling this function, the `output-stream` will not accept any 169 | /// writes (`check-write` will return `ok(0)`) until the flush has 170 | /// completed. The `subscribe` pollable will become ready when the 171 | /// flush has completed and the stream can accept more writes. 172 | flush: func() -> result<_, stream-error>; 173 | 174 | /// Request to flush buffered output, and block until flush completes 175 | /// and stream is ready for writing again. 176 | blocking-flush: func() -> result<_, stream-error>; 177 | 178 | /// Create a `pollable` which will resolve once the output-stream 179 | /// is ready for more writing, or an error has occured. When this 180 | /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an 181 | /// error. 182 | /// 183 | /// If the stream is closed, this pollable is always ready immediately. 184 | /// 185 | /// The created `pollable` is a child resource of the `output-stream`. 186 | /// Implementations may trap if the `output-stream` is dropped before 187 | /// all derived `pollable`s created with this function are dropped. 188 | subscribe: func() -> pollable; 189 | 190 | /// Write zeroes to a stream. 191 | /// 192 | /// This should be used precisely like `write` with the exact same 193 | /// preconditions (must use check-write first), but instead of 194 | /// passing a list of bytes, you simply pass the number of zero-bytes 195 | /// that should be written. 196 | write-zeroes: func( 197 | /// The number of zero-bytes to write 198 | len: u64 199 | ) -> result<_, stream-error>; 200 | 201 | /// Perform a write of up to 4096 zeroes, and then flush the stream. 202 | /// Block until all of these operations are complete, or an error 203 | /// occurs. 204 | /// 205 | /// This is a convenience wrapper around the use of `check-write`, 206 | /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with 207 | /// the following pseudo-code: 208 | /// 209 | /// ```text 210 | /// let pollable = this.subscribe(); 211 | /// while num_zeroes != 0 { 212 | /// // Wait for the stream to become writable 213 | /// pollable.block(); 214 | /// let Ok(n) = this.check-write(); // eliding error handling 215 | /// let len = min(n, num_zeroes); 216 | /// this.write-zeroes(len); // eliding error handling 217 | /// num_zeroes -= len; 218 | /// } 219 | /// this.flush(); 220 | /// // Wait for completion of `flush` 221 | /// pollable.block(); 222 | /// // Check for any errors that arose during `flush` 223 | /// let _ = this.check-write(); // eliding error handling 224 | /// ``` 225 | blocking-write-zeroes-and-flush: func( 226 | /// The number of zero-bytes to write 227 | len: u64 228 | ) -> result<_, stream-error>; 229 | 230 | /// Read from one stream and write to another. 231 | /// 232 | /// The behavior of splice is equivelant to: 233 | /// 1. calling `check-write` on the `output-stream` 234 | /// 2. calling `read` on the `input-stream` with the smaller of the 235 | /// `check-write` permitted length and the `len` provided to `splice` 236 | /// 3. calling `write` on the `output-stream` with that read data. 237 | /// 238 | /// Any error reported by the call to `check-write`, `read`, or 239 | /// `write` ends the splice and reports that error. 240 | /// 241 | /// This function returns the number of bytes transferred; it may be less 242 | /// than `len`. 243 | splice: func( 244 | /// The stream to read from 245 | src: borrow, 246 | /// The number of bytes to splice 247 | len: u64, 248 | ) -> result; 249 | 250 | /// Read from one stream and write to another, with blocking. 251 | /// 252 | /// This is similar to `splice`, except that it blocks until the 253 | /// `output-stream` is ready for writing, and the `input-stream` 254 | /// is ready for reading, before performing the `splice`. 255 | blocking-splice: func( 256 | /// The stream to read from 257 | src: borrow, 258 | /// The number of bytes to splice 259 | len: u64, 260 | ) -> result; 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /surface/deps/io/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | world imports { 4 | import streams; 5 | import poll; 6 | } 7 | -------------------------------------------------------------------------------- /surface/imports.md: -------------------------------------------------------------------------------- 1 |

World imports

2 | 11 |

Import interface wasi:graphics-context/graphics-context

12 |
13 |

Types

14 |

resource context

15 |

resource abstract-buffer

16 |
17 |

Functions

18 |

[constructor]context: func

19 |
Return values
20 | 23 |

[method]context.get-current-buffer: func

24 |
Params
25 | 28 |
Return values
29 | 32 |

[method]context.present: func

33 |

TODO: might want to remove this.

34 |
Params
35 | 38 |

Import interface wasi:io/poll@0.2.0

39 |

A poll API intended to let users wait for I/O events on multiple handles 40 | at once.

41 |
42 |

Types

43 |

resource pollable

44 |

pollable represents a single I/O event which may be ready, or not.

45 |

Functions

46 |

[method]pollable.ready: func

47 |

Return the readiness of a pollable. This function never blocks.

48 |

Returns true when the pollable is ready, and false otherwise.

49 |
Params
50 | 53 |
Return values
54 |
    55 |
  • bool
  • 56 |
57 |

[method]pollable.block: func

58 |

block returns immediately if the pollable is ready, and otherwise 59 | blocks until ready.

60 |

This function is equivalent to calling poll.poll on a list 61 | containing only this pollable.

62 |
Params
63 | 66 |

poll: func

67 |

Poll for completion on a set of pollables.

68 |

This function takes a list of pollables, which identify I/O sources of 69 | interest, and waits until one or more of the events is ready for I/O.

70 |

The result list<u32> contains one or more indices of handles in the 71 | argument list that is ready for I/O.

72 |

If the list contains more elements than can be indexed with a u32 73 | value, this function traps.

74 |

A timeout can be implemented by adding a pollable from the 75 | wasi-clocks API to the list.

76 |

This function does not return a result; polling in itself does not 77 | do any I/O so it doesn't fail. If any of the I/O sources identified by 78 | the pollables has an error, it is indicated by marking the source as 79 | being reaedy for I/O.

80 |
Params
81 | 84 |
Return values
85 |
    86 |
  • list<u32>
  • 87 |
88 |

Import interface wasi:surface/surface

89 |
90 |

Types

91 |

type context

92 |

context

93 |

94 | #### `type pollable` 95 | [`pollable`](#pollable) 96 |

97 | #### `record create-desc` 98 |

Record Fields
99 |
    100 |
  • height: option<u32>
  • 101 |
  • width: option<u32>
  • 102 |
103 |

resource surface

104 |

record resize-event

105 |
Record Fields
106 |
    107 |
  • height: u32
  • 108 |
  • width: u32
  • 109 |
110 |

record frame-event

111 |
Record Fields
112 |
    113 |
  • nothing: bool

    TODO: This field doesn't mean anything. 114 | Can't have empty record. Would like to have a way around this. 115 |

  • 116 |
117 |

record pointer-event

118 |
Record Fields
119 |
    120 |
  • x: f64
  • 121 |
  • y: f64
  • 122 |
123 |

enum key

124 |

corresponds with https://w3c.github.io/uievents-code/#code-value-tables 125 | Unidentified is not included, use option<key> instead.

126 |
Enum Cases
127 |
    128 |
  • backquote
  • 129 |
  • backslash
  • 130 |
  • bracket-left
  • 131 |
  • bracket-right
  • 132 |
  • comma
  • 133 |
  • digit0
  • 134 |
  • digit1
  • 135 |
  • digit2
  • 136 |
  • digit3
  • 137 |
  • digit4
  • 138 |
  • digit5
  • 139 |
  • digit6
  • 140 |
  • digit7
  • 141 |
  • digit8
  • 142 |
  • digit9
  • 143 |
  • equal
  • 144 |
  • intl-backslash
  • 145 |
  • intl-ro
  • 146 |
  • intl-yen
  • 147 |
  • key-a
  • 148 |
  • key-b
  • 149 |
  • key-c
  • 150 |
  • key-d
  • 151 |
  • key-e
  • 152 |
  • key-f
  • 153 |
  • key-g
  • 154 |
  • key-h
  • 155 |
  • key-i
  • 156 |
  • key-j
  • 157 |
  • key-k
  • 158 |
  • key-l
  • 159 |
  • key-m
  • 160 |
  • key-n
  • 161 |
  • key-o
  • 162 |
  • key-p
  • 163 |
  • key-q
  • 164 |
  • key-r
  • 165 |
  • key-s
  • 166 |
  • key-t
  • 167 |
  • key-u
  • 168 |
  • key-v
  • 169 |
  • key-w
  • 170 |
  • key-x
  • 171 |
  • key-y
  • 172 |
  • key-z
  • 173 |
  • minus
  • 174 |
  • period
  • 175 |
  • quote
  • 176 |
  • semicolon
  • 177 |
  • slash
  • 178 |
  • alt-left
  • 179 |
  • alt-right
  • 180 |
  • backspace
  • 181 |
  • caps-lock
  • 182 |
  • context-menu
  • 183 |
  • control-left
  • 184 |
  • control-right
  • 185 |
  • enter
  • 186 |
  • meta-left
  • 187 |
  • meta-right
  • 188 |
  • shift-left
  • 189 |
  • shift-right
  • 190 |
  • space
  • 191 |
  • tab
  • 192 |
  • convert
  • 193 |
  • kana-mode
  • 194 |
  • lang1
  • 195 |
  • lang2
  • 196 |
  • lang3
  • 197 |
  • lang4
  • 198 |
  • lang5
  • 199 |
  • non-convert
  • 200 |
  • delete
  • 201 |
  • end
  • 202 |
  • help
  • 203 |
  • home
  • 204 |
  • insert
  • 205 |
  • page-down
  • 206 |
  • page-up
  • 207 |
  • arrow-down
  • 208 |
  • arrow-left
  • 209 |
  • arrow-right
  • 210 |
  • arrow-up
  • 211 |
  • num-lock
  • 212 |
  • numpad0
  • 213 |
  • numpad1
  • 214 |
  • numpad2
  • 215 |
  • numpad3
  • 216 |
  • numpad4
  • 217 |
  • numpad5
  • 218 |
  • numpad6
  • 219 |
  • numpad7
  • 220 |
  • numpad8
  • 221 |
  • numpad9
  • 222 |
  • numpad-add
  • 223 |
  • numpad-backspace
  • 224 |
  • numpad-clear
  • 225 |
  • numpad-clear-entry
  • 226 |
  • numpad-comma
  • 227 |
  • numpad-decimal
  • 228 |
  • numpad-divide
  • 229 |
  • numpad-enter
  • 230 |
  • numpad-equal
  • 231 |
  • numpad-hash
  • 232 |
  • numpad-memory-add
  • 233 |
  • numpad-memory-clear
  • 234 |
  • numpad-memory-recall
  • 235 |
  • numpad-memory-store
  • 236 |
  • numpad-memory-subtract
  • 237 |
  • numpad-multiply
  • 238 |
  • numpad-paren-left
  • 239 |
  • numpad-paren-right
  • 240 |
  • numpad-star
  • 241 |
  • numpad-subtract
  • 242 |
  • escape
  • 243 |
  • f1
  • 244 |
  • f2
  • 245 |
  • f3
  • 246 |
  • f4
  • 247 |
  • f5
  • 248 |
  • f6
  • 249 |
  • f7
  • 250 |
  • f8
  • 251 |
  • f9
  • 252 |
  • f10
  • 253 |
  • f11
  • 254 |
  • f12
  • 255 |
  • fn
  • 256 |
  • fn-lock
  • 257 |
  • print-screen
  • 258 |
  • scroll-lock
  • 259 |
  • pause
  • 260 |
  • browser-back
  • 261 |
  • browser-favorites
  • 262 |
  • browser-forward
  • 263 |
  • browser-home
  • 264 |
  • browser-refresh
  • 265 |
  • browser-search
  • 266 |
  • browser-stop
  • 267 |
  • eject
  • 268 |
  • launch-app1
  • 269 |
  • launch-app2
  • 270 |
  • launch-mail
  • 271 |
  • media-play-pause
  • 272 |
  • media-select
  • 273 |
  • media-stop
  • 274 |
  • media-track-next
  • 275 |
  • media-track-previous
  • 276 |
  • power
  • 277 |
  • sleep
  • 278 |
  • audio-volume-down
  • 279 |
  • audio-volume-mute
  • 280 |
  • audio-volume-up
  • 281 |
  • wake-up
  • 282 |
  • hyper
  • 283 |
  • super
  • 284 |
  • turbo
  • 285 |
  • abort
  • 286 |
  • resume
  • 287 |
  • suspend
  • 288 |
  • again
  • 289 |
  • copy
  • 290 |
  • cut
  • 291 |
  • find
  • 292 |
  • open
  • 293 |
  • paste
  • 294 |
  • props
  • 295 |
  • select
  • 296 |
  • undo
  • 297 |
  • hiragana
  • 298 |
  • katakana
  • 299 |
300 |

record key-event

301 |
Record Fields
302 |
    303 |
  • key: option<key>
  • 304 |
  • text: option<string>
  • 305 |
  • alt-key: bool
  • 306 |
  • ctrl-key: bool
  • 307 |
  • meta-key: bool
  • 308 |
  • shift-key: bool
  • 309 |
310 |
311 |

Functions

312 |

[constructor]surface: func

313 |
Params
314 | 317 |
Return values
318 | 321 |

[method]surface.connect-graphics-context: func

322 |
Params
323 | 327 |

[method]surface.height: func

328 |
Params
329 |
    330 |
  • self: borrow<surface>
  • 331 |
332 |
Return values
333 |
    334 |
  • u32
  • 335 |
336 |

[method]surface.width: func

337 |
Params
338 |
    339 |
  • self: borrow<surface>
  • 340 |
341 |
Return values
342 |
    343 |
  • u32
  • 344 |
345 |

[method]surface.request-set-size: func

346 |
Params
347 |
    348 |
  • self: borrow<surface>
  • 349 |
  • height: option<u32>
  • 350 |
  • width: option<u32>
  • 351 |
352 |

[method]surface.subscribe-resize: func

353 |
Params
354 |
    355 |
  • self: borrow<surface>
  • 356 |
357 |
Return values
358 | 361 |

[method]surface.get-resize: func

362 |
Params
363 |
    364 |
  • self: borrow<surface>
  • 365 |
366 |
Return values
367 | 370 |

[method]surface.subscribe-frame: func

371 |
Params
372 |
    373 |
  • self: borrow<surface>
  • 374 |
375 |
Return values
376 | 379 |

[method]surface.get-frame: func

380 |
Params
381 |
    382 |
  • self: borrow<surface>
  • 383 |
384 |
Return values
385 | 388 |

[method]surface.subscribe-pointer-up: func

389 |
Params
390 |
    391 |
  • self: borrow<surface>
  • 392 |
393 |
Return values
394 | 397 |

[method]surface.get-pointer-up: func

398 |
Params
399 |
    400 |
  • self: borrow<surface>
  • 401 |
402 |
Return values
403 | 406 |

[method]surface.subscribe-pointer-down: func

407 |
Params
408 |
    409 |
  • self: borrow<surface>
  • 410 |
411 |
Return values
412 | 415 |

[method]surface.get-pointer-down: func

416 |
Params
417 |
    418 |
  • self: borrow<surface>
  • 419 |
420 |
Return values
421 | 424 |

[method]surface.subscribe-pointer-move: func

425 |
Params
426 |
    427 |
  • self: borrow<surface>
  • 428 |
429 |
Return values
430 | 433 |

[method]surface.get-pointer-move: func

434 |
Params
435 |
    436 |
  • self: borrow<surface>
  • 437 |
438 |
Return values
439 | 442 |

[method]surface.subscribe-key-up: func

443 |
Params
444 |
    445 |
  • self: borrow<surface>
  • 446 |
447 |
Return values
448 | 451 |

[method]surface.get-key-up: func

452 |
Params
453 |
    454 |
  • self: borrow<surface>
  • 455 |
456 |
Return values
457 | 460 |

[method]surface.subscribe-key-down: func

461 |
Params
462 |
    463 |
  • self: borrow<surface>
  • 464 |
465 |
Return values
466 | 469 |

[method]surface.get-key-down: func

470 |
Params
471 |
    472 |
  • self: borrow<surface>
  • 473 |
474 |
Return values
475 | 478 | -------------------------------------------------------------------------------- /surface/surface.wit: -------------------------------------------------------------------------------- 1 | package wasi:surface@0.0.1; 2 | 3 | world imports { 4 | import surface; 5 | } 6 | 7 | interface surface { 8 | use wasi:graphics-context/graphics-context@0.0.1.{context}; 9 | use wasi:io/poll@0.2.0.{pollable}; 10 | 11 | record create-desc { 12 | height: option, 13 | width: option, 14 | } 15 | 16 | resource surface { 17 | constructor(desc: create-desc); 18 | 19 | connect-graphics-context: func(context: borrow); 20 | 21 | height: func() -> u32; 22 | width: func() -> u32; 23 | 24 | request-set-size: func(height: option, width: option); 25 | 26 | subscribe-resize: func() -> pollable; 27 | get-resize: func() -> option; 28 | 29 | subscribe-frame: func() -> pollable; 30 | get-frame: func() -> option; 31 | 32 | subscribe-pointer-up: func() -> pollable; 33 | get-pointer-up: func() -> option; 34 | 35 | subscribe-pointer-down: func() -> pollable; 36 | get-pointer-down: func() -> option; 37 | 38 | subscribe-pointer-move: func() -> pollable; 39 | get-pointer-move: func() -> option; 40 | 41 | subscribe-key-up: func() -> pollable; 42 | get-key-up: func() -> option; 43 | 44 | subscribe-key-down: func() -> pollable; 45 | get-key-down: func() -> option; 46 | } 47 | 48 | record resize-event { 49 | height: u32, 50 | width: u32, 51 | } 52 | 53 | record frame-event { 54 | /// TODO: This field doesn't mean anything. 55 | /// Can't have empty record. Would like to have a way around this. 56 | nothing: bool, 57 | } 58 | 59 | record pointer-event { 60 | x: f64, 61 | y: f64, 62 | } 63 | 64 | record key-event { 65 | key: option, 66 | text: option, 67 | alt-key: bool, 68 | ctrl-key: bool, 69 | meta-key: bool, 70 | shift-key: bool, 71 | } 72 | 73 | // corresponds with https://w3c.github.io/uievents-code/#code-value-tables 74 | // `Unidentified` is not included, use `option` instead. 75 | enum key { 76 | backquote, 77 | backslash, 78 | bracket-left, 79 | bracket-right, 80 | comma, 81 | digit0, 82 | digit1, 83 | digit2, 84 | digit3, 85 | digit4, 86 | digit5, 87 | digit6, 88 | digit7, 89 | digit8, 90 | digit9, 91 | equal, 92 | intl-backslash, 93 | intl-ro, 94 | intl-yen, 95 | key-a, 96 | key-b, 97 | key-c, 98 | key-d, 99 | key-e, 100 | key-f, 101 | key-g, 102 | key-h, 103 | key-i, 104 | key-j, 105 | key-k, 106 | key-l, 107 | key-m, 108 | key-n, 109 | key-o, 110 | key-p, 111 | key-q, 112 | key-r, 113 | key-s, 114 | key-t, 115 | key-u, 116 | key-v, 117 | key-w, 118 | key-x, 119 | key-y, 120 | key-z, 121 | minus, 122 | period, 123 | quote, 124 | semicolon, 125 | slash, 126 | alt-left, 127 | alt-right, 128 | backspace, 129 | caps-lock, 130 | context-menu, 131 | control-left, 132 | control-right, 133 | enter, 134 | meta-left, 135 | meta-right, 136 | shift-left, 137 | shift-right, 138 | space, 139 | tab, 140 | convert, 141 | kana-mode, 142 | lang1, 143 | lang2, 144 | lang3, 145 | lang4, 146 | lang5, 147 | non-convert, 148 | delete, 149 | end, 150 | help, 151 | home, 152 | insert, 153 | page-down, 154 | page-up, 155 | arrow-down, 156 | arrow-left, 157 | arrow-right, 158 | arrow-up, 159 | num-lock, 160 | numpad0, 161 | numpad1, 162 | numpad2, 163 | numpad3, 164 | numpad4, 165 | numpad5, 166 | numpad6, 167 | numpad7, 168 | numpad8, 169 | numpad9, 170 | numpad-add, 171 | numpad-backspace, 172 | numpad-clear, 173 | numpad-clear-entry, 174 | numpad-comma, 175 | numpad-decimal, 176 | numpad-divide, 177 | numpad-enter, 178 | numpad-equal, 179 | numpad-hash, 180 | numpad-memory-add, 181 | numpad-memory-clear, 182 | numpad-memory-recall, 183 | numpad-memory-store, 184 | numpad-memory-subtract, 185 | numpad-multiply, 186 | numpad-paren-left, 187 | numpad-paren-right, 188 | numpad-star, 189 | numpad-subtract, 190 | escape, 191 | f1, 192 | f2, 193 | f3, 194 | f4, 195 | f5, 196 | f6, 197 | f7, 198 | f8, 199 | f9, 200 | f10, 201 | f11, 202 | f12, 203 | fn, 204 | fn-lock, 205 | print-screen, 206 | scroll-lock, 207 | pause, 208 | browser-back, 209 | browser-favorites, 210 | browser-forward, 211 | browser-home, 212 | browser-refresh, 213 | browser-search, 214 | browser-stop, 215 | eject, 216 | launch-app1, 217 | launch-app2, 218 | launch-mail, 219 | media-play-pause, 220 | media-select, 221 | media-stop, 222 | media-track-next, 223 | media-track-previous, 224 | power, 225 | sleep, 226 | audio-volume-down, 227 | audio-volume-mute, 228 | audio-volume-up, 229 | wake-up, 230 | hyper, 231 | super, 232 | turbo, 233 | abort, 234 | resume, 235 | suspend, 236 | again, 237 | copy, 238 | cut, 239 | find, 240 | open, 241 | paste, 242 | props, 243 | select, 244 | undo, 245 | hiragana, 246 | katakana, 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Testing guidelines 2 | 3 | TK fill in testing guidelines 4 | 5 | ## Installing the tools 6 | 7 | TK fill in instructions 8 | 9 | ## Running the tests 10 | 11 | TK fill in instructions 12 | -------------------------------------------------------------------------------- /test/ensure-parses/.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /test/ensure-parses/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.97" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "2.9.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 16 | 17 | [[package]] 18 | name = "ensure-parses" 19 | version = "0.1.0" 20 | dependencies = [ 21 | "wit-parser", 22 | ] 23 | 24 | [[package]] 25 | name = "equivalent" 26 | version = "1.0.2" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 29 | 30 | [[package]] 31 | name = "hashbrown" 32 | version = "0.15.2" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 35 | 36 | [[package]] 37 | name = "id-arena" 38 | version = "2.2.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" 41 | 42 | [[package]] 43 | name = "indexmap" 44 | version = "2.8.0" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" 47 | dependencies = [ 48 | "equivalent", 49 | "hashbrown", 50 | "serde", 51 | ] 52 | 53 | [[package]] 54 | name = "itoa" 55 | version = "1.0.15" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 58 | 59 | [[package]] 60 | name = "log" 61 | version = "0.4.27" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 64 | 65 | [[package]] 66 | name = "memchr" 67 | version = "2.7.4" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 70 | 71 | [[package]] 72 | name = "proc-macro2" 73 | version = "1.0.94" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 76 | dependencies = [ 77 | "unicode-ident", 78 | ] 79 | 80 | [[package]] 81 | name = "quote" 82 | version = "1.0.40" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 85 | dependencies = [ 86 | "proc-macro2", 87 | ] 88 | 89 | [[package]] 90 | name = "ryu" 91 | version = "1.0.20" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 94 | 95 | [[package]] 96 | name = "semver" 97 | version = "1.0.26" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 100 | 101 | [[package]] 102 | name = "serde" 103 | version = "1.0.219" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 106 | dependencies = [ 107 | "serde_derive", 108 | ] 109 | 110 | [[package]] 111 | name = "serde_derive" 112 | version = "1.0.219" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 115 | dependencies = [ 116 | "proc-macro2", 117 | "quote", 118 | "syn", 119 | ] 120 | 121 | [[package]] 122 | name = "serde_json" 123 | version = "1.0.140" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 126 | dependencies = [ 127 | "itoa", 128 | "memchr", 129 | "ryu", 130 | "serde", 131 | ] 132 | 133 | [[package]] 134 | name = "syn" 135 | version = "2.0.100" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 138 | dependencies = [ 139 | "proc-macro2", 140 | "quote", 141 | "unicode-ident", 142 | ] 143 | 144 | [[package]] 145 | name = "unicode-ident" 146 | version = "1.0.18" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 149 | 150 | [[package]] 151 | name = "unicode-xid" 152 | version = "0.2.6" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 155 | 156 | [[package]] 157 | name = "wasmparser" 158 | version = "0.227.1" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2" 161 | dependencies = [ 162 | "bitflags", 163 | "indexmap", 164 | "semver", 165 | ] 166 | 167 | [[package]] 168 | name = "wit-parser" 169 | version = "0.227.1" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11" 172 | dependencies = [ 173 | "anyhow", 174 | "id-arena", 175 | "indexmap", 176 | "log", 177 | "semver", 178 | "serde", 179 | "serde_derive", 180 | "serde_json", 181 | "unicode-xid", 182 | "wasmparser", 183 | ] 184 | -------------------------------------------------------------------------------- /test/ensure-parses/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ensure-parses" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | wit-parser = "0.227.1" 8 | -------------------------------------------------------------------------------- /test/ensure-parses/src/main.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn graphics_context() { 5 | assert_dir_parses("graphics-context"); 6 | } 7 | 8 | #[test] 9 | fn webgpu() { 10 | assert_dir_parses("webgpu"); 11 | } 12 | 13 | #[test] 14 | fn surface() { 15 | assert_dir_parses("surface"); 16 | } 17 | 18 | #[test] 19 | fn frame_buffer() { 20 | assert_dir_parses("frame-buffer"); 21 | } 22 | 23 | fn assert_dir_parses(path: &str) { 24 | let mut resolve = wit_parser::Resolve::new(); 25 | resolve 26 | .push_dir(&format!("../../{path}")) 27 | .expect(&format!("{path} failed to parse")); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /webgpu/deps.lock: -------------------------------------------------------------------------------- 1 | [graphics-context] 2 | path = "../graphics-context" 3 | sha256 = "b138ab44463c5bb074207687c88d59dfca9c6bc7a5dad482dba626094cccbc3f" 4 | sha512 = "b9cef19d2cf0a0f3d0a58c94cf4483d051acfb5622e379bf0abcc6aa34c14d92210c56554387b932f08aba3c9c1e9e9cadb554e9dd0cf464b20c7d31c806515e" 5 | 6 | [io] 7 | url = "https://github.com/WebAssembly/wasi-io/archive/fef02cddb4ac28dcde97bf11a4c7b856833a948f.tar.gz" 8 | sha256 = "7210e5653539a15478f894d4da24cc69d61924cbcba21d2804d69314a88e5a4c" 9 | sha512 = "49184a1b0945a889abd52d25271172ed3dc2db6968fcdddb1bab7ee0081f4a3eeee0977ad2291126a37631c0d86eeea75d822fa8af224c422134500bf9f0f2bb" 10 | -------------------------------------------------------------------------------- /webgpu/deps.toml: -------------------------------------------------------------------------------- 1 | io = "https://github.com/WebAssembly/wasi-io/archive/fef02cddb4ac28dcde97bf11a4c7b856833a948f.tar.gz" 2 | 3 | [graphics-context] 4 | path = "../graphics-context" 5 | -------------------------------------------------------------------------------- /webgpu/deps/graphics-context/graphics-context.wit: -------------------------------------------------------------------------------- 1 | package wasi:graphics-context@0.0.1; 2 | 3 | world imports { 4 | import graphics-context; 5 | } 6 | 7 | interface graphics-context { 8 | resource context { 9 | constructor(); 10 | 11 | get-current-buffer: func() -> abstract-buffer; 12 | 13 | // TODO: might want to remove this. 14 | present: func(); 15 | } 16 | 17 | resource abstract-buffer { } 18 | } 19 | -------------------------------------------------------------------------------- /webgpu/deps/io/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// provide functions to further "downcast" this error into more specific 15 | /// error information. For example, `error`s returned in streams derived 16 | /// from filesystem types to be described using the filesystem's own 17 | /// error-code type, using the function 18 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter 19 | /// `borrow` and returns 20 | /// `option`. 21 | /// 22 | /// The set of functions which can "downcast" an `error` into a more 23 | /// concrete type is open. 24 | resource error { 25 | /// Returns a string that is suitable to assist humans in debugging 26 | /// this error. 27 | /// 28 | /// WARNING: The returned string should not be consumed mechanically! 29 | /// It may change across platforms, hosts, or other implementation 30 | /// details. Parsing this string is a major platform-compatibility 31 | /// hazard. 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /webgpu/deps/io/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | interface poll { 6 | /// `pollable` represents a single I/O event which may be ready, or not. 7 | resource pollable { 8 | 9 | /// Return the readiness of a pollable. This function never blocks. 10 | /// 11 | /// Returns `true` when the pollable is ready, and `false` otherwise. 12 | ready: func() -> bool; 13 | 14 | /// `block` returns immediately if the pollable is ready, and otherwise 15 | /// blocks until ready. 16 | /// 17 | /// This function is equivalent to calling `poll.poll` on a list 18 | /// containing only this pollable. 19 | block: func(); 20 | } 21 | 22 | /// Poll for completion on a set of pollables. 23 | /// 24 | /// This function takes a list of pollables, which identify I/O sources of 25 | /// interest, and waits until one or more of the events is ready for I/O. 26 | /// 27 | /// The result `list` contains one or more indices of handles in the 28 | /// argument list that is ready for I/O. 29 | /// 30 | /// If the list contains more elements than can be indexed with a `u32` 31 | /// value, this function traps. 32 | /// 33 | /// A timeout can be implemented by adding a pollable from the 34 | /// wasi-clocks API to the list. 35 | /// 36 | /// This function does not return a `result`; polling in itself does not 37 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 38 | /// the pollables has an error, it is indicated by marking the source as 39 | /// being reaedy for I/O. 40 | poll: func(in: list>) -> list; 41 | } 42 | -------------------------------------------------------------------------------- /webgpu/deps/io/streams.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | /// WASI I/O is an I/O abstraction API which is currently focused on providing 4 | /// stream types. 5 | /// 6 | /// In the future, the component model is expected to add built-in stream types; 7 | /// when it does, they are expected to subsume this API. 8 | interface streams { 9 | use error.{error}; 10 | use poll.{pollable}; 11 | 12 | /// An error for input-stream and output-stream operations. 13 | variant stream-error { 14 | /// The last operation (a write or flush) failed before completion. 15 | /// 16 | /// More information is available in the `error` payload. 17 | last-operation-failed(error), 18 | /// The stream is closed: no more input will be accepted by the 19 | /// stream. A closed output-stream will return this error on all 20 | /// future operations. 21 | closed 22 | } 23 | 24 | /// An input bytestream. 25 | /// 26 | /// `input-stream`s are *non-blocking* to the extent practical on underlying 27 | /// platforms. I/O operations always return promptly; if fewer bytes are 28 | /// promptly available than requested, they return the number of bytes promptly 29 | /// available, which could even be zero. To wait for data to be available, 30 | /// use the `subscribe` function to obtain a `pollable` which can be polled 31 | /// for using `wasi:io/poll`. 32 | resource input-stream { 33 | /// Perform a non-blocking read from the stream. 34 | /// 35 | /// When the source of a `read` is binary data, the bytes from the source 36 | /// are returned verbatim. When the source of a `read` is known to the 37 | /// implementation to be text, bytes containing the UTF-8 encoding of the 38 | /// text are returned. 39 | /// 40 | /// This function returns a list of bytes containing the read data, 41 | /// when successful. The returned list will contain up to `len` bytes; 42 | /// it may return fewer than requested, but not more. The list is 43 | /// empty when no bytes are available for reading at this time. The 44 | /// pollable given by `subscribe` will be ready when more bytes are 45 | /// available. 46 | /// 47 | /// This function fails with a `stream-error` when the operation 48 | /// encounters an error, giving `last-operation-failed`, or when the 49 | /// stream is closed, giving `closed`. 50 | /// 51 | /// When the caller gives a `len` of 0, it represents a request to 52 | /// read 0 bytes. If the stream is still open, this call should 53 | /// succeed and return an empty list, or otherwise fail with `closed`. 54 | /// 55 | /// The `len` parameter is a `u64`, which could represent a list of u8 which 56 | /// is not possible to allocate in wasm32, or not desirable to allocate as 57 | /// as a return value by the callee. The callee may return a list of bytes 58 | /// less than `len` in size while more bytes are available for reading. 59 | read: func( 60 | /// The maximum number of bytes to read 61 | len: u64 62 | ) -> result, stream-error>; 63 | 64 | /// Read bytes from a stream, after blocking until at least one byte can 65 | /// be read. Except for blocking, behavior is identical to `read`. 66 | blocking-read: func( 67 | /// The maximum number of bytes to read 68 | len: u64 69 | ) -> result, stream-error>; 70 | 71 | /// Skip bytes from a stream. Returns number of bytes skipped. 72 | /// 73 | /// Behaves identical to `read`, except instead of returning a list 74 | /// of bytes, returns the number of bytes consumed from the stream. 75 | skip: func( 76 | /// The maximum number of bytes to skip. 77 | len: u64, 78 | ) -> result; 79 | 80 | /// Skip bytes from a stream, after blocking until at least one byte 81 | /// can be skipped. Except for blocking behavior, identical to `skip`. 82 | blocking-skip: func( 83 | /// The maximum number of bytes to skip. 84 | len: u64, 85 | ) -> result; 86 | 87 | /// Create a `pollable` which will resolve once either the specified stream 88 | /// has bytes available to read or the other end of the stream has been 89 | /// closed. 90 | /// The created `pollable` is a child resource of the `input-stream`. 91 | /// Implementations may trap if the `input-stream` is dropped before 92 | /// all derived `pollable`s created with this function are dropped. 93 | subscribe: func() -> pollable; 94 | } 95 | 96 | 97 | /// An output bytestream. 98 | /// 99 | /// `output-stream`s are *non-blocking* to the extent practical on 100 | /// underlying platforms. Except where specified otherwise, I/O operations also 101 | /// always return promptly, after the number of bytes that can be written 102 | /// promptly, which could even be zero. To wait for the stream to be ready to 103 | /// accept data, the `subscribe` function to obtain a `pollable` which can be 104 | /// polled for using `wasi:io/poll`. 105 | resource output-stream { 106 | /// Check readiness for writing. This function never blocks. 107 | /// 108 | /// Returns the number of bytes permitted for the next call to `write`, 109 | /// or an error. Calling `write` with more bytes than this function has 110 | /// permitted will trap. 111 | /// 112 | /// When this function returns 0 bytes, the `subscribe` pollable will 113 | /// become ready when this function will report at least 1 byte, or an 114 | /// error. 115 | check-write: func() -> result; 116 | 117 | /// Perform a write. This function never blocks. 118 | /// 119 | /// When the destination of a `write` is binary data, the bytes from 120 | /// `contents` are written verbatim. When the destination of a `write` is 121 | /// known to the implementation to be text, the bytes of `contents` are 122 | /// transcoded from UTF-8 into the encoding of the destination and then 123 | /// written. 124 | /// 125 | /// Precondition: check-write gave permit of Ok(n) and contents has a 126 | /// length of less than or equal to n. Otherwise, this function will trap. 127 | /// 128 | /// returns Err(closed) without writing if the stream has closed since 129 | /// the last call to check-write provided a permit. 130 | write: func( 131 | contents: list 132 | ) -> result<_, stream-error>; 133 | 134 | /// Perform a write of up to 4096 bytes, and then flush the stream. Block 135 | /// until all of these operations are complete, or an error occurs. 136 | /// 137 | /// This is a convenience wrapper around the use of `check-write`, 138 | /// `subscribe`, `write`, and `flush`, and is implemented with the 139 | /// following pseudo-code: 140 | /// 141 | /// ```text 142 | /// let pollable = this.subscribe(); 143 | /// while !contents.is_empty() { 144 | /// // Wait for the stream to become writable 145 | /// pollable.block(); 146 | /// let Ok(n) = this.check-write(); // eliding error handling 147 | /// let len = min(n, contents.len()); 148 | /// let (chunk, rest) = contents.split_at(len); 149 | /// this.write(chunk ); // eliding error handling 150 | /// contents = rest; 151 | /// } 152 | /// this.flush(); 153 | /// // Wait for completion of `flush` 154 | /// pollable.block(); 155 | /// // Check for any errors that arose during `flush` 156 | /// let _ = this.check-write(); // eliding error handling 157 | /// ``` 158 | blocking-write-and-flush: func( 159 | contents: list 160 | ) -> result<_, stream-error>; 161 | 162 | /// Request to flush buffered output. This function never blocks. 163 | /// 164 | /// This tells the output-stream that the caller intends any buffered 165 | /// output to be flushed. the output which is expected to be flushed 166 | /// is all that has been passed to `write` prior to this call. 167 | /// 168 | /// Upon calling this function, the `output-stream` will not accept any 169 | /// writes (`check-write` will return `ok(0)`) until the flush has 170 | /// completed. The `subscribe` pollable will become ready when the 171 | /// flush has completed and the stream can accept more writes. 172 | flush: func() -> result<_, stream-error>; 173 | 174 | /// Request to flush buffered output, and block until flush completes 175 | /// and stream is ready for writing again. 176 | blocking-flush: func() -> result<_, stream-error>; 177 | 178 | /// Create a `pollable` which will resolve once the output-stream 179 | /// is ready for more writing, or an error has occured. When this 180 | /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an 181 | /// error. 182 | /// 183 | /// If the stream is closed, this pollable is always ready immediately. 184 | /// 185 | /// The created `pollable` is a child resource of the `output-stream`. 186 | /// Implementations may trap if the `output-stream` is dropped before 187 | /// all derived `pollable`s created with this function are dropped. 188 | subscribe: func() -> pollable; 189 | 190 | /// Write zeroes to a stream. 191 | /// 192 | /// This should be used precisely like `write` with the exact same 193 | /// preconditions (must use check-write first), but instead of 194 | /// passing a list of bytes, you simply pass the number of zero-bytes 195 | /// that should be written. 196 | write-zeroes: func( 197 | /// The number of zero-bytes to write 198 | len: u64 199 | ) -> result<_, stream-error>; 200 | 201 | /// Perform a write of up to 4096 zeroes, and then flush the stream. 202 | /// Block until all of these operations are complete, or an error 203 | /// occurs. 204 | /// 205 | /// This is a convenience wrapper around the use of `check-write`, 206 | /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with 207 | /// the following pseudo-code: 208 | /// 209 | /// ```text 210 | /// let pollable = this.subscribe(); 211 | /// while num_zeroes != 0 { 212 | /// // Wait for the stream to become writable 213 | /// pollable.block(); 214 | /// let Ok(n) = this.check-write(); // eliding error handling 215 | /// let len = min(n, num_zeroes); 216 | /// this.write-zeroes(len); // eliding error handling 217 | /// num_zeroes -= len; 218 | /// } 219 | /// this.flush(); 220 | /// // Wait for completion of `flush` 221 | /// pollable.block(); 222 | /// // Check for any errors that arose during `flush` 223 | /// let _ = this.check-write(); // eliding error handling 224 | /// ``` 225 | blocking-write-zeroes-and-flush: func( 226 | /// The number of zero-bytes to write 227 | len: u64 228 | ) -> result<_, stream-error>; 229 | 230 | /// Read from one stream and write to another. 231 | /// 232 | /// The behavior of splice is equivelant to: 233 | /// 1. calling `check-write` on the `output-stream` 234 | /// 2. calling `read` on the `input-stream` with the smaller of the 235 | /// `check-write` permitted length and the `len` provided to `splice` 236 | /// 3. calling `write` on the `output-stream` with that read data. 237 | /// 238 | /// Any error reported by the call to `check-write`, `read`, or 239 | /// `write` ends the splice and reports that error. 240 | /// 241 | /// This function returns the number of bytes transferred; it may be less 242 | /// than `len`. 243 | splice: func( 244 | /// The stream to read from 245 | src: borrow, 246 | /// The number of bytes to splice 247 | len: u64, 248 | ) -> result; 249 | 250 | /// Read from one stream and write to another, with blocking. 251 | /// 252 | /// This is similar to `splice`, except that it blocks until the 253 | /// `output-stream` is ready for writing, and the `input-stream` 254 | /// is ready for reading, before performing the `splice`. 255 | blocking-splice: func( 256 | /// The stream to read from 257 | src: borrow, 258 | /// The number of bytes to splice 259 | len: u64, 260 | ) -> result; 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /webgpu/deps/io/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | world imports { 4 | import streams; 5 | import poll; 6 | } 7 | -------------------------------------------------------------------------------- /webgpu/generate/.gitignore: -------------------------------------------------------------------------------- 1 | /target -------------------------------------------------------------------------------- /webgpu/generate/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "ahash" 7 | version = "0.8.11" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 10 | dependencies = [ 11 | "cfg-if", 12 | "once_cell", 13 | "version_check", 14 | "zerocopy", 15 | ] 16 | 17 | [[package]] 18 | name = "anyhow" 19 | version = "1.0.96" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" 22 | 23 | [[package]] 24 | name = "bitflags" 25 | version = "2.8.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 28 | 29 | [[package]] 30 | name = "cfg-if" 31 | version = "1.0.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 34 | 35 | [[package]] 36 | name = "diff" 37 | version = "0.1.13" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" 40 | 41 | [[package]] 42 | name = "either" 43 | version = "1.14.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" 46 | 47 | [[package]] 48 | name = "equivalent" 49 | version = "1.0.2" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 52 | 53 | [[package]] 54 | name = "generate" 55 | version = "0.1.0" 56 | dependencies = [ 57 | "semver", 58 | "serde_json", 59 | "webidl2wit", 60 | "weedle", 61 | "wit-encoder 0.220.1", 62 | "wit-parser 0.220.1", 63 | "wit-transforms", 64 | ] 65 | 66 | [[package]] 67 | name = "hashbrown" 68 | version = "0.14.5" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 71 | dependencies = [ 72 | "ahash", 73 | ] 74 | 75 | [[package]] 76 | name = "hashbrown" 77 | version = "0.15.2" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 80 | 81 | [[package]] 82 | name = "hashlink" 83 | version = "0.9.1" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" 86 | dependencies = [ 87 | "hashbrown 0.14.5", 88 | ] 89 | 90 | [[package]] 91 | name = "heck" 92 | version = "0.5.0" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 95 | 96 | [[package]] 97 | name = "id-arena" 98 | version = "2.2.1" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" 101 | 102 | [[package]] 103 | name = "indexmap" 104 | version = "2.7.1" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 107 | dependencies = [ 108 | "equivalent", 109 | "hashbrown 0.15.2", 110 | "serde", 111 | ] 112 | 113 | [[package]] 114 | name = "itertools" 115 | version = "0.13.0" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 118 | dependencies = [ 119 | "either", 120 | ] 121 | 122 | [[package]] 123 | name = "itoa" 124 | version = "1.0.14" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 127 | 128 | [[package]] 129 | name = "log" 130 | version = "0.4.26" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" 133 | 134 | [[package]] 135 | name = "memchr" 136 | version = "2.7.4" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 139 | 140 | [[package]] 141 | name = "nom" 142 | version = "5.1.3" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" 145 | dependencies = [ 146 | "memchr", 147 | "version_check", 148 | ] 149 | 150 | [[package]] 151 | name = "once_cell" 152 | version = "1.20.3" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" 155 | 156 | [[package]] 157 | name = "pretty_assertions" 158 | version = "1.4.1" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" 161 | dependencies = [ 162 | "diff", 163 | "yansi", 164 | ] 165 | 166 | [[package]] 167 | name = "proc-macro2" 168 | version = "1.0.93" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 171 | dependencies = [ 172 | "unicode-ident", 173 | ] 174 | 175 | [[package]] 176 | name = "quote" 177 | version = "1.0.38" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 180 | dependencies = [ 181 | "proc-macro2", 182 | ] 183 | 184 | [[package]] 185 | name = "ryu" 186 | version = "1.0.19" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 189 | 190 | [[package]] 191 | name = "semver" 192 | version = "1.0.26" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 195 | dependencies = [ 196 | "serde", 197 | ] 198 | 199 | [[package]] 200 | name = "serde" 201 | version = "1.0.218" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" 204 | dependencies = [ 205 | "serde_derive", 206 | ] 207 | 208 | [[package]] 209 | name = "serde_derive" 210 | version = "1.0.218" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" 213 | dependencies = [ 214 | "proc-macro2", 215 | "quote", 216 | "syn", 217 | ] 218 | 219 | [[package]] 220 | name = "serde_json" 221 | version = "1.0.139" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" 224 | dependencies = [ 225 | "itoa", 226 | "memchr", 227 | "ryu", 228 | "serde", 229 | ] 230 | 231 | [[package]] 232 | name = "syn" 233 | version = "2.0.98" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" 236 | dependencies = [ 237 | "proc-macro2", 238 | "quote", 239 | "unicode-ident", 240 | ] 241 | 242 | [[package]] 243 | name = "unicode-ident" 244 | version = "1.0.17" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" 247 | 248 | [[package]] 249 | name = "unicode-xid" 250 | version = "0.2.6" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 253 | 254 | [[package]] 255 | name = "version_check" 256 | version = "0.9.5" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 259 | 260 | [[package]] 261 | name = "wasmparser" 262 | version = "0.220.1" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "8d07b6a3b550fefa1a914b6d54fc175dd11c3392da11eee604e6ffc759805d25" 265 | dependencies = [ 266 | "bitflags", 267 | "indexmap", 268 | "semver", 269 | ] 270 | 271 | [[package]] 272 | name = "webidl2wit" 273 | version = "0.1.0" 274 | source = "git+https://github.com/wasi-gfx/webidl2wit?rev=582c5a959fb98073cfcc60514964b417b5394e36#582c5a959fb98073cfcc60514964b417b5394e36" 275 | dependencies = [ 276 | "anyhow", 277 | "hashlink", 278 | "heck", 279 | "itertools", 280 | "weedle", 281 | "wit-encoder 0.221.3", 282 | "wit-parser 0.221.3", 283 | ] 284 | 285 | [[package]] 286 | name = "weedle" 287 | version = "0.13.0" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "bfde6c0c0dc6d6c8b4f13afc35b46793e5a62890bcafa1a9d4c2c2301fa2f829" 290 | dependencies = [ 291 | "nom", 292 | ] 293 | 294 | [[package]] 295 | name = "wit-encoder" 296 | version = "0.220.1" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "441a19b678328555fc3a753ab3353a2ed06123ce47de85e44ab4b65e70df590f" 299 | dependencies = [ 300 | "id-arena", 301 | "pretty_assertions", 302 | "semver", 303 | "serde", 304 | "wit-parser 0.220.1", 305 | ] 306 | 307 | [[package]] 308 | name = "wit-encoder" 309 | version = "0.221.3" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "b8789b759ea209cb19b63467b145a34c6b5e3a40394d1c6cb6132e19a260694d" 312 | dependencies = [ 313 | "pretty_assertions", 314 | "semver", 315 | ] 316 | 317 | [[package]] 318 | name = "wit-parser" 319 | version = "0.220.1" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "ae2a7999ed18efe59be8de2db9cb2b7f84d88b27818c79353dfc53131840fe1a" 322 | dependencies = [ 323 | "anyhow", 324 | "id-arena", 325 | "indexmap", 326 | "log", 327 | "semver", 328 | "serde", 329 | "serde_derive", 330 | "serde_json", 331 | "unicode-xid", 332 | "wasmparser", 333 | ] 334 | 335 | [[package]] 336 | name = "wit-parser" 337 | version = "0.221.3" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "896112579ed56b4a538b07a3d16e562d101ff6265c46b515ce0c701eef16b2ac" 340 | dependencies = [ 341 | "anyhow", 342 | "id-arena", 343 | "indexmap", 344 | "log", 345 | "semver", 346 | "unicode-xid", 347 | ] 348 | 349 | [[package]] 350 | name = "wit-transforms" 351 | version = "0.1.0" 352 | source = "git+https://github.com/wasi-gfx/wit-transforms?rev=d05dfeeba5e3cd5f52ecfd4bbbc917ba8fa5786c#d05dfeeba5e3cd5f52ecfd4bbbc917ba8fa5786c" 353 | dependencies = [ 354 | "anyhow", 355 | "serde", 356 | "serde_json", 357 | "wit-encoder 0.220.1", 358 | ] 359 | 360 | [[package]] 361 | name = "yansi" 362 | version = "1.0.1" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" 365 | 366 | [[package]] 367 | name = "zerocopy" 368 | version = "0.7.35" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 371 | dependencies = [ 372 | "zerocopy-derive", 373 | ] 374 | 375 | [[package]] 376 | name = "zerocopy-derive" 377 | version = "0.7.35" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 380 | dependencies = [ 381 | "proc-macro2", 382 | "quote", 383 | "syn", 384 | ] 385 | -------------------------------------------------------------------------------- /webgpu/generate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generate" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | webidl2wit = { git = "https://github.com/wasi-gfx/webidl2wit", rev = "582c5a959fb98073cfcc60514964b417b5394e36" } 8 | weedle = "0.13.0" 9 | wit-transforms = { git = "https://github.com/wasi-gfx/wit-transforms", rev = "d05dfeeba5e3cd5f52ecfd4bbbc917ba8fa5786c" } 10 | wit-parser = "0.220.0" 11 | wit-encoder = "0.220.0" 12 | serde_json = "1.0.139" 13 | semver = "1.0.26" 14 | -------------------------------------------------------------------------------- /webgpu/generate/generate.sh: -------------------------------------------------------------------------------- 1 | cd ./webgpu-spec 2 | make -j 3 | cd .. 4 | 5 | cargo run 6 | -------------------------------------------------------------------------------- /webgpu/generate/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{fs, path::Path}; 2 | use webidl2wit::{ConversionOptions, ResourceInheritance}; 3 | 4 | fn main() { 5 | let webidl = fs::read_to_string(Path::new("./webgpu-spec/spec/webgpu.idl")).unwrap(); 6 | let webidl_ast = weedle::parse(&webidl).unwrap(); 7 | let wit_ast = webidl2wit::webidl_to_wit( 8 | webidl_ast, 9 | ConversionOptions { 10 | phantom_interface: vec![ 11 | "Navigator".into(), 12 | "WorkerNavigator".into(), 13 | "HTMLVideoElement".into(), 14 | "HTMLImageElement".into(), 15 | "VideoFrame".into(), 16 | "ImageBitmap".into(), 17 | "ImageData".into(), 18 | "EventTarget".into(), 19 | "DOMException".into(), 20 | "Event".into(), 21 | ], 22 | phantom_dictionaries: vec![ 23 | "EventInit".into(), 24 | "PredefinedColorSpace".into(), 25 | "HTMLCanvasElement".into(), 26 | "OffscreenCanvas".into(), 27 | ], 28 | resource_inheritance: ResourceInheritance::DuplicateMethods, 29 | package_name: webidl2wit::PackageName::new( 30 | "wasi", 31 | "webgpu", 32 | Some(semver::Version { 33 | major: 0, 34 | minor: 0, 35 | patch: 1, 36 | pre: Default::default(), 37 | build: Default::default(), 38 | }), 39 | ), 40 | interface_name: "webgpu".into(), 41 | ..Default::default() 42 | }, 43 | ) 44 | .unwrap(); 45 | let wit = wit_ast.to_string(); 46 | 47 | let mut resolve = wit_parser::Resolve::new(); 48 | // TODO: remove once we have streams 49 | resolve.push_file(format!("../deps/io/poll.wit")).unwrap(); 50 | 51 | resolve.push_str("", &wit).unwrap(); 52 | 53 | let mut packages = wit_encoder::packages_from_parsed(&resolve); 54 | 55 | // removes wasi:io/pollable 56 | // TODO: remove this once we get rid of pollable 57 | packages.remove(0); 58 | 59 | assert!(packages.len() == 1, "Should create exactly one package"); 60 | let mut package = packages.remove(0); 61 | assert!( 62 | package.items().len() == 1, 63 | "Package should contain exactly one interface" 64 | ); 65 | let item = package.items_mut().remove(0); 66 | let interface = match item { 67 | wit_encoder::PackageItem::Interface(interface) => interface, 68 | wit_encoder::PackageItem::World(_) => { 69 | panic!("Package should contain exactly one interface") 70 | } 71 | }; 72 | let transforms = serde_json::from_str(include_str!("../webgpu-transforms.json")).unwrap(); 73 | let interface = wit_transforms::transform(interface, transforms); 74 | package.item(wit_encoder::PackageItem::Interface(interface)); 75 | 76 | let output = package.to_string(); 77 | 78 | fs::write("../webgpu.wit", output).unwrap(); 79 | } 80 | -------------------------------------------------------------------------------- /webgpu/generate/webgpu-transforms.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "reason": "Remove navigators", 4 | "operations": [ 5 | { 6 | "operation": { 7 | "remove-type": "navigator" 8 | } 9 | }, 10 | { 11 | "operation": { 12 | "remove-type": "worker-navigator" 13 | } 14 | } 15 | ] 16 | }, 17 | { 18 | "reason": "Have a single color type", 19 | "operations": [ 20 | { 21 | "operation": { 22 | "remove-type": "gpu-color-dict-or-list-f64" 23 | } 24 | }, 25 | { 26 | "operation": { 27 | "remove-type": "gpu-color" 28 | } 29 | }, 30 | { 31 | "operation": { 32 | "rename-type": { 33 | "from": "gpu-color-dict", 34 | "to": "gpu-color" 35 | } 36 | } 37 | } 38 | ] 39 | }, 40 | { 41 | "reason": "Have a single origin 3D type", 42 | "operations": [ 43 | { 44 | "operation": { 45 | "remove-type": "gpu-origin3-d-dict-or-list-gpu-integer-coordinate" 46 | } 47 | }, 48 | { 49 | "operation": { 50 | "remove-type": "gpu-origin3-d" 51 | } 52 | }, 53 | { 54 | "operation": { 55 | "rename-type": { 56 | "from": "gpu-origin3-d-dict", 57 | "to": "gpu-origin3-d" 58 | } 59 | } 60 | } 61 | ] 62 | }, 63 | { 64 | "reason": "Have a single extent 3D type", 65 | "operations": [ 66 | { 67 | "operation": { 68 | "remove-type": "gpu-extent3-d-dict-or-list-gpu-integer-coordinate" 69 | } 70 | }, 71 | { 72 | "operation": { 73 | "remove-type": "gpu-extent3-d" 74 | } 75 | }, 76 | { 77 | "operation": { 78 | "rename-type": { 79 | "from": "gpu-extent3-d-dict", 80 | "to": "gpu-extent3-d" 81 | } 82 | } 83 | } 84 | ] 85 | }, 86 | { 87 | "reason": "Remove gpu-supported-limits.copy-external-image-to-texture as it's web related", 88 | "operations": [ 89 | { 90 | "operation": { 91 | "remove-func": { 92 | "resource": "gpu-queue", 93 | "func": "copy-external-image-to-texture" 94 | } 95 | } 96 | }, 97 | { 98 | "operation": { 99 | "remove-type": "gpu-copy-external-image-source" 100 | } 101 | }, 102 | { 103 | "operation": { 104 | "remove-type": "gpu-copy-external-image-source-info" 105 | } 106 | }, 107 | { 108 | "operation": { 109 | "remove-type": "gpu-copy-external-image-dest-info" 110 | } 111 | }, 112 | { 113 | "operation": { 114 | "remove-type": "html-canvas-element-or-html-image-element-or-html-video-element-or-image-bitmap-or-image-data-or-offscreen-canvas-or-video-frame" 115 | } 116 | }, 117 | { 118 | "operation": { 119 | "remove-type": "html-canvas-element" 120 | } 121 | }, 122 | { 123 | "operation": { 124 | "remove-type": "html-image-element" 125 | } 126 | }, 127 | { 128 | "operation": { 129 | "remove-type": "image-bitmap" 130 | } 131 | }, 132 | { 133 | "operation": { 134 | "remove-type": "image-data" 135 | } 136 | }, 137 | { 138 | "operation": { 139 | "remove-type": "offscreen-canvas" 140 | } 141 | }, 142 | { 143 | "operation": { 144 | "remove-type": "gpu-origin2-d-dict" 145 | } 146 | }, 147 | { 148 | "operation": { 149 | "remove-type": "gpu-origin2-d-dict-or-list-gpu-integer-coordinate" 150 | } 151 | }, 152 | { 153 | "operation": { 154 | "remove-type": "gpu-origin2-d" 155 | } 156 | }, 157 | { 158 | "operation": { 159 | "remove-func": { 160 | "resource": "gpu-canvas-context", 161 | "func": "canvas" 162 | } 163 | } 164 | }, 165 | { 166 | "operation": { 167 | "remove-type": "html-canvas-element-or-offscreen-canvas" 168 | } 169 | } 170 | ] 171 | }, 172 | { 173 | "reason": "Remove gpu-device.import-external-texture as it's web related", 174 | "operations": [ 175 | { 176 | "operation": { 177 | "remove-func": { 178 | "resource": "gpu-device", 179 | "func": "import-external-texture" 180 | } 181 | } 182 | }, 183 | { 184 | "operation": { 185 | "remove-type": "gpu-external-texture-descriptor" 186 | } 187 | }, 188 | { 189 | "operation": { 190 | "remove-type": "html-video-element-or-video-frame" 191 | } 192 | }, 193 | { 194 | "operation": { 195 | "remove-type": "html-video-element" 196 | } 197 | }, 198 | { 199 | "operation": { 200 | "remove-type": "video-frame" 201 | } 202 | }, 203 | { 204 | "operation": { 205 | "remove-record-field": { 206 | "record": "gpu-bind-group-layout-entry", 207 | "field": "external-texture" 208 | } 209 | } 210 | }, 211 | { 212 | "operation": { 213 | "remove-type": "gpu-external-texture-binding-layout" 214 | } 215 | }, 216 | { 217 | "operation": { 218 | "remove-type": "gpu-external-texture" 219 | } 220 | }, 221 | { 222 | "operation": { 223 | "remove-variant-case": { 224 | "variant": "gpu-buffer-binding-or-gpu-external-texture-or-gpu-sampler-or-gpu-texture-view", 225 | "case": "gpu-external-texture" 226 | } 227 | } 228 | }, 229 | { 230 | "operation": { 231 | "rename-type": { 232 | "from": "gpu-buffer-binding-or-gpu-external-texture-or-gpu-sampler-or-gpu-texture-view", 233 | "to": "gpu-buffer-binding-or-gpu-sampler-or-gpu-texture-view" 234 | } 235 | } 236 | }, 237 | { 238 | "operation": { 239 | "replace-refs": { 240 | "old": "gpu-buffer-binding-or-gpu-external-texture-or-gpu-sampler-or-gpu-texture-view", 241 | "new": "gpu-buffer-binding-or-gpu-sampler-or-gpu-texture-view" 242 | } 243 | } 244 | } 245 | ] 246 | }, 247 | { 248 | "reason": "Remove bases that are never used", 249 | "operations": [ 250 | { 251 | "operation": { 252 | "remove-type": "dom-exception" 253 | } 254 | }, 255 | { 256 | "operation": { 257 | "remove-type": "event-init" 258 | } 259 | }, 260 | { 261 | "operation": { 262 | "remove-type": "gpu-object-descriptor-base" 263 | } 264 | }, 265 | { 266 | "operation": { 267 | "remove-type": "gpu-pipeline-descriptor-base" 268 | } 269 | }, 270 | { 271 | "operation": { 272 | "remove-type": "event-target" 273 | } 274 | }, 275 | { 276 | "operation": { 277 | "remove-type": "event" 278 | } 279 | } 280 | ] 281 | }, 282 | { 283 | "reason": "Beautify gpu-*-binding.set-bind-group, no tuple params. Note: offset & length are not optional in JS, but seems to be JS specific reason for this https://github.com/gpuweb/gpuweb/pull/440#discussion_r342299860", 284 | "operations": [ 285 | { 286 | "vars": { 287 | "$_INDEX": { 288 | "find-type": { 289 | "variant-case": { 290 | "variant": "gpu-render-bundle-encoder-set-bind-group-params", 291 | "case": "index-bind-group-dynamic-offsets" 292 | }, 293 | "unwrap-t": [ 294 | { "tuple": 0 } 295 | ] 296 | } 297 | }, 298 | "$_BIND_GROUP": { 299 | "find-type": { 300 | "variant-case": { 301 | "variant": "gpu-render-bundle-encoder-set-bind-group-params", 302 | "case": "index-bind-group-dynamic-offsets" 303 | }, 304 | "unwrap-t": [ 305 | { "tuple": 1 } 306 | ] 307 | } 308 | }, 309 | "$_DYNAMIC_OFFSETS_DATA": { 310 | "find-type": { 311 | "variant-case": { 312 | "variant": "gpu-render-bundle-encoder-set-bind-group-params", 313 | "case": "index-bind-group-dynamic-offsets" 314 | }, 315 | "unwrap-t": [ 316 | { "tuple": 2 } 317 | ] 318 | } 319 | }, 320 | "$_DYNAMIC_OFFSETS_DATA_START": { 321 | "find-type": { 322 | "variant-case": { 323 | "variant": "gpu-render-bundle-encoder-set-bind-group-params", 324 | "case": "index-bind-group-dynamic-offsets-data-dynamic-offsets-data-start-dynamic-offsets-data-length" 325 | }, 326 | "unwrap-t": [ 327 | { "tuple": 3 } 328 | ] 329 | } 330 | }, 331 | "$_DYNAMIC_OFFSETS_DATA_LENGTH": { 332 | "find-type": { 333 | "variant-case": { 334 | "variant": "gpu-render-bundle-encoder-set-bind-group-params", 335 | "case": "index-bind-group-dynamic-offsets-data-dynamic-offsets-data-start-dynamic-offsets-data-length" 336 | }, 337 | "unwrap-t": [ 338 | { "tuple": 4 } 339 | ] 340 | } 341 | } 342 | }, 343 | "operation": { 344 | "retype-func-params": { 345 | "resource": "gpu-render-bundle-encoder", 346 | "func": "set-bind-group", 347 | "new-params": { 348 | "items": [ 349 | ["index", "$_INDEX"], 350 | ["bind-group", "$_BIND_GROUP"], 351 | ["dynamic-offsets-data", "$_DYNAMIC_OFFSETS_DATA"], 352 | ["dynamic-offsets-data-start", { "option": "$_DYNAMIC_OFFSETS_DATA_START" }], 353 | ["dynamic-offsets-data-length", { "option": "$_DYNAMIC_OFFSETS_DATA_LENGTH" }] 354 | ] 355 | } 356 | } 357 | } 358 | }, 359 | { 360 | "operation": { 361 | "remove-type": "gpu-render-bundle-encoder-set-bind-group-params" 362 | } 363 | }, 364 | { 365 | "vars": { 366 | "$_INDEX": { 367 | "find-type": { 368 | "variant-case": { 369 | "variant": "gpu-render-pass-encoder-set-bind-group-params", 370 | "case": "index-bind-group-dynamic-offsets" 371 | }, 372 | "unwrap-t": [ 373 | { "tuple": 0 } 374 | ] 375 | } 376 | }, 377 | "$_BIND_GROUP": { 378 | "find-type": { 379 | "variant-case": { 380 | "variant": "gpu-render-pass-encoder-set-bind-group-params", 381 | "case": "index-bind-group-dynamic-offsets" 382 | }, 383 | "unwrap-t": [ 384 | { "tuple": 1 } 385 | ] 386 | } 387 | }, 388 | "$_DYNAMIC_OFFSETS_DATA": { 389 | "find-type": { 390 | "variant-case": { 391 | "variant": "gpu-render-pass-encoder-set-bind-group-params", 392 | "case": "index-bind-group-dynamic-offsets" 393 | }, 394 | "unwrap-t": [ 395 | { "tuple": 2 } 396 | ] 397 | } 398 | }, 399 | "$_DYNAMIC_OFFSETS_DATA_START": { 400 | "find-type": { 401 | "variant-case": { 402 | "variant": "gpu-render-pass-encoder-set-bind-group-params", 403 | "case": "index-bind-group-dynamic-offsets-data-dynamic-offsets-data-start-dynamic-offsets-data-length" 404 | }, 405 | "unwrap-t": [ 406 | { "tuple": 3 } 407 | ] 408 | } 409 | }, 410 | "$_DYNAMIC_OFFSETS_DATA_LENGTH": { 411 | "find-type": { 412 | "variant-case": { 413 | "variant": "gpu-render-pass-encoder-set-bind-group-params", 414 | "case": "index-bind-group-dynamic-offsets-data-dynamic-offsets-data-start-dynamic-offsets-data-length" 415 | }, 416 | "unwrap-t": [ 417 | { "tuple": 4 } 418 | ] 419 | } 420 | } 421 | }, 422 | "operation": { 423 | "retype-func-params": { 424 | "resource": "gpu-render-pass-encoder", 425 | "func": "set-bind-group", 426 | "new-params": { 427 | "items": [ 428 | ["index", "$_INDEX"], 429 | ["bind-group", "$_BIND_GROUP"], 430 | ["dynamic-offsets-data", "$_DYNAMIC_OFFSETS_DATA"], 431 | ["dynamic-offsets-data-start", { "option": "$_DYNAMIC_OFFSETS_DATA_START" }], 432 | ["dynamic-offsets-data-length", { "option": "$_DYNAMIC_OFFSETS_DATA_LENGTH" }] 433 | ] 434 | } 435 | } 436 | } 437 | }, 438 | { 439 | "operation": { 440 | "remove-type": "gpu-render-pass-encoder-set-bind-group-params" 441 | } 442 | }, 443 | { 444 | "vars": { 445 | "$_INDEX": { 446 | "find-type": { 447 | "variant-case": { 448 | "variant": "gpu-compute-pass-encoder-set-bind-group-params", 449 | "case": "index-bind-group-dynamic-offsets" 450 | }, 451 | "unwrap-t": [ 452 | { "tuple": 0 } 453 | ] 454 | } 455 | }, 456 | "$_BIND_GROUP": { 457 | "find-type": { 458 | "variant-case": { 459 | "variant": "gpu-compute-pass-encoder-set-bind-group-params", 460 | "case": "index-bind-group-dynamic-offsets" 461 | }, 462 | "unwrap-t": [ 463 | { "tuple": 1 } 464 | ] 465 | } 466 | }, 467 | "$_DYNAMIC_OFFSETS_DATA": { 468 | "find-type": { 469 | "variant-case": { 470 | "variant": "gpu-compute-pass-encoder-set-bind-group-params", 471 | "case": "index-bind-group-dynamic-offsets" 472 | }, 473 | "unwrap-t": [ 474 | { "tuple": 2 } 475 | ] 476 | } 477 | }, 478 | "$_DYNAMIC_OFFSETS_DATA_START": { 479 | "find-type": { 480 | "variant-case": { 481 | "variant": "gpu-compute-pass-encoder-set-bind-group-params", 482 | "case": "index-bind-group-dynamic-offsets-data-dynamic-offsets-data-start-dynamic-offsets-data-length" 483 | }, 484 | "unwrap-t": [ 485 | { "tuple": 3 } 486 | ] 487 | } 488 | }, 489 | "$_DYNAMIC_OFFSETS_DATA_LENGTH": { 490 | "find-type": { 491 | "variant-case": { 492 | "variant": "gpu-compute-pass-encoder-set-bind-group-params", 493 | "case": "index-bind-group-dynamic-offsets-data-dynamic-offsets-data-start-dynamic-offsets-data-length" 494 | }, 495 | "unwrap-t": [ 496 | { "tuple": 4 } 497 | ] 498 | } 499 | } 500 | }, 501 | "operation": { 502 | "retype-func-params": { 503 | "resource": "gpu-compute-pass-encoder", 504 | "func": "set-bind-group", 505 | "new-params": { 506 | "items": [ 507 | ["index", "$_INDEX"], 508 | ["bind-group", "$_BIND_GROUP"], 509 | ["dynamic-offsets-data", "$_DYNAMIC_OFFSETS_DATA"], 510 | ["dynamic-offsets-data-start", { "option": "$_DYNAMIC_OFFSETS_DATA_START" }], 511 | ["dynamic-offsets-data-length", { "option": "$_DYNAMIC_OFFSETS_DATA_LENGTH" }] 512 | ] 513 | } 514 | } 515 | } 516 | }, 517 | { 518 | "operation": { 519 | "remove-type": "gpu-compute-pass-encoder-set-bind-group-params" 520 | } 521 | } 522 | ] 523 | }, 524 | { 525 | "reason": "Remove allow-shared-buffer-source as it's web related and temporarily replace it with list", 526 | "operations": [ 527 | { 528 | "operation": { 529 | "retype-func-param-type": { 530 | "resource": "gpu-queue", 531 | "func": "write-buffer", 532 | "param": "data", 533 | "new-type": { 534 | "list": "u8" 535 | } 536 | } 537 | } 538 | }, 539 | { 540 | "operation": { 541 | "rename-func": { 542 | "resource": "gpu-queue", 543 | "old-func-name": "write-buffer", 544 | "new-func-name": "write-buffer-with-copy" 545 | } 546 | } 547 | }, 548 | { 549 | "operation": { 550 | "retype-func-param-type": { 551 | "resource": "gpu-queue", 552 | "func": "write-texture", 553 | "param": "data", 554 | "new-type": { 555 | "list": "u8" 556 | } 557 | } 558 | } 559 | }, 560 | { 561 | "operation": { 562 | "rename-func": { 563 | "resource": "gpu-queue", 564 | "old-func-name": "write-texture", 565 | "new-func-name": "write-texture-with-copy" 566 | } 567 | } 568 | }, 569 | { 570 | "operation": { 571 | "remove-type": "array-buffer-view" 572 | } 573 | }, 574 | { 575 | "operation": { 576 | "remove-type": "allow-shared-buffer-source" 577 | } 578 | }, 579 | { 580 | "operation": { 581 | "remove-type": "data-view" 582 | } 583 | }, 584 | { 585 | "operation": { 586 | "remove-type": "uint8-array" 587 | } 588 | }, 589 | { 590 | "operation": { 591 | "remove-type": "uint8-array-constructor-options" 592 | } 593 | }, 594 | { 595 | "operation": { 596 | "remove-type": "uint8-array-set-src" 597 | } 598 | }, 599 | { 600 | "operation": { 601 | "remove-type": "uint8-clamped-array" 602 | } 603 | }, 604 | { 605 | "operation": { 606 | "remove-type": "uint8-clamped-array-constructor-options" 607 | } 608 | }, 609 | { 610 | "operation": { 611 | "remove-type": "uint8-clamped-array-set-src" 612 | } 613 | }, 614 | { 615 | "operation": { 616 | "remove-type": "uint16-array" 617 | } 618 | }, 619 | { 620 | "operation": { 621 | "remove-type": "uint16-array-constructor-options" 622 | } 623 | }, 624 | { 625 | "operation": { 626 | "remove-type": "uint16-array-set-src" 627 | } 628 | }, 629 | { 630 | "operation": { 631 | "remove-type": "uint32-array" 632 | } 633 | }, 634 | { 635 | "operation": { 636 | "remove-type": "uint32-array-constructor-options" 637 | } 638 | }, 639 | { 640 | "operation": { 641 | "remove-type": "uint32-array-set-src" 642 | } 643 | }, 644 | { 645 | "operation": { 646 | "remove-type": "int8-array" 647 | } 648 | }, 649 | { 650 | "operation": { 651 | "remove-type": "int8-array-constructor-options" 652 | } 653 | }, 654 | { 655 | "operation": { 656 | "remove-type": "int8-array-set-src" 657 | } 658 | }, 659 | { 660 | "operation": { 661 | "remove-type": "int16-array" 662 | } 663 | }, 664 | { 665 | "operation": { 666 | "remove-type": "int16-array-constructor-options" 667 | } 668 | }, 669 | { 670 | "operation": { 671 | "remove-type": "int16-array-set-src" 672 | } 673 | }, 674 | { 675 | "operation": { 676 | "remove-type": "int32-array" 677 | } 678 | }, 679 | { 680 | "operation": { 681 | "remove-type": "int32-array-constructor-options" 682 | } 683 | }, 684 | { 685 | "operation": { 686 | "remove-type": "int32-array-set-src" 687 | } 688 | }, 689 | { 690 | "operation": { 691 | "remove-type": "float32-array" 692 | } 693 | }, 694 | { 695 | "operation": { 696 | "remove-type": "float32-array-constructor-options" 697 | } 698 | }, 699 | { 700 | "operation": { 701 | "remove-type": "float32-array-set-src" 702 | } 703 | }, 704 | { 705 | "operation": { 706 | "remove-type": "float64-array" 707 | } 708 | }, 709 | { 710 | "operation": { 711 | "remove-type": "float64-array-constructor-options" 712 | } 713 | }, 714 | { 715 | "operation": { 716 | "remove-type": "float64-array-set-src" 717 | } 718 | } 719 | ] 720 | }, 721 | { 722 | "reason": "Change predefined-color-space to enum", 723 | "operations": [ 724 | { 725 | "operation": { 726 | "remove-type": "predefined-color-space" 727 | } 728 | }, 729 | { 730 | "operation": { 731 | "add-type": { 732 | "name": "predefined-color-space", 733 | "kind": { 734 | "enum": { 735 | "cases": [ 736 | { 737 | "name": "srgb" 738 | }, 739 | { 740 | "name": "display-p3" 741 | } 742 | ] 743 | } 744 | } 745 | } 746 | } 747 | } 748 | ] 749 | }, 750 | { 751 | "reason": "Remove prefixes of identifiers with leading digits", 752 | "operations": [ 753 | { 754 | "operation": { 755 | "rename-enum-case": { 756 | "enum": "gpu-texture-dimension", 757 | "old-case-name" : "x1d", 758 | "new-case-name" : "d1" 759 | } 760 | } 761 | }, 762 | { 763 | "operation": { 764 | "rename-enum-case": { 765 | "enum": "gpu-texture-dimension", 766 | "old-case-name" : "x2d", 767 | "new-case-name" : "d2" 768 | } 769 | } 770 | }, 771 | { 772 | "operation": { 773 | "rename-enum-case": { 774 | "enum": "gpu-texture-dimension", 775 | "old-case-name" : "x3d", 776 | "new-case-name" : "d3" 777 | } 778 | } 779 | }, 780 | { 781 | "operation": { 782 | "rename-enum-case": { 783 | "enum": "gpu-texture-view-dimension", 784 | "old-case-name" : "x1d", 785 | "new-case-name" : "d1" 786 | } 787 | } 788 | }, 789 | { 790 | "operation": { 791 | "rename-enum-case": { 792 | "enum": "gpu-texture-view-dimension", 793 | "old-case-name" : "x2d", 794 | "new-case-name" : "d2" 795 | } 796 | } 797 | }, 798 | { 799 | "operation": { 800 | "rename-enum-case": { 801 | "enum": "gpu-texture-view-dimension", 802 | "old-case-name" : "x2d-array", 803 | "new-case-name" : "d2-array" 804 | } 805 | } 806 | }, 807 | { 808 | "operation": { 809 | "rename-enum-case": { 810 | "enum": "gpu-texture-view-dimension", 811 | "old-case-name" : "x3d", 812 | "new-case-name" : "d3" 813 | } 814 | } 815 | } 816 | ] 817 | }, 818 | { 819 | "reason": "Simplify naming of gpu-binding-resource", 820 | "operations": [ 821 | { 822 | "operation": { 823 | "remove-type": "gpu-binding-resource" 824 | } 825 | }, 826 | { 827 | "operation": { 828 | "rename-type": { 829 | "from" : "gpu-buffer-binding-or-gpu-sampler-or-gpu-texture-view", 830 | "to" : "gpu-binding-resource" 831 | } 832 | } 833 | } 834 | ] 835 | }, 836 | { 837 | "reason": "Simplify naming of gpu-layout-mode, and merge gpu-auto-layout-mode cases into gpu-layout-mode", 838 | "operations": [ 839 | { 840 | "operation": { 841 | "rename-type": { 842 | "from" : "gpu-auto-layout-mode-or-gpu-pipeline-layout", 843 | "to" : "gpu-layout-mode" 844 | } 845 | } 846 | }, 847 | { 848 | "operation": { 849 | "replace-refs": { 850 | "old": "gpu-auto-layout-mode-or-gpu-pipeline-layout", 851 | "new": "gpu-layout-mode" 852 | } 853 | } 854 | }, 855 | { 856 | "operation": { 857 | "rename-variant-case": { 858 | "variant": "gpu-layout-mode", 859 | "old-case-name": "gpu-pipeline-layout", 860 | "new-case-name": "specific" 861 | } 862 | } 863 | }, 864 | { 865 | "vars": { 866 | "$_CASES": { 867 | "find-string-list": { 868 | "enum-cases": { 869 | "enum": "gpu-auto-layout-mode" 870 | }, 871 | "convert-to": "variant-cases" 872 | } 873 | } 874 | }, 875 | "operation": { 876 | "add-variant-cases": { 877 | "variant": "gpu-layout-mode", 878 | "cases": "$_CASES" 879 | } 880 | } 881 | }, 882 | { 883 | "operation": { 884 | "remove-variant-case": { 885 | "variant": "gpu-layout-mode", 886 | "case": "gpu-auto-layout-mode" 887 | } 888 | } 889 | }, 890 | { 891 | "operation": { 892 | "remove-type": "gpu-auto-layout-mode" 893 | } 894 | } 895 | ] 896 | }, 897 | { 898 | "reason": "Add get root function", 899 | "operations": [ 900 | { 901 | "operation": { 902 | "add-standalone-func": { 903 | "func": { 904 | "name": "get-gpu", 905 | "params": { 906 | "items": [] 907 | }, 908 | "results": { "anon": { "named": "gpu" } } 909 | } 910 | } 911 | } 912 | } 913 | ] 914 | }, 915 | { 916 | "reason": "Remove array-buffer and replace it temporarily with list", 917 | "operations": [ 918 | { 919 | "operation": { 920 | "remove-type": "array-buffer" 921 | } 922 | }, 923 | { 924 | "operation": { 925 | "remove-type": "array-buffer-constructor-options" 926 | } 927 | }, 928 | { 929 | "operation": { 930 | "retype-func-results": { 931 | "resource": "gpu-buffer", 932 | "func": "get-mapped-range", 933 | "new-results": { 934 | "anon": { 935 | "list": "u8" 936 | } 937 | } 938 | } 939 | } 940 | }, 941 | { 942 | "operation": { 943 | "rename-func": { 944 | "resource": "gpu-buffer", 945 | "old-func-name": "get-mapped-range", 946 | "new-func-name": "get-mapped-range-get-with-copy" 947 | } 948 | } 949 | }, 950 | { 951 | "operation": { 952 | "add-resource-func": { 953 | "resource": "gpu-buffer", 954 | "func": { 955 | "kind": { 956 | "method": ["get-mapped-range-set-with-copy", { "named": { "items": [] } }] 957 | }, 958 | "params": { 959 | "items": [ 960 | ["data", { "list": "u8" }], 961 | ["offset", { "option": { "named": "gpu-size64" } }], 962 | ["size", { "option": { "named": "gpu-size64" } }] 963 | ] 964 | } 965 | } 966 | } 967 | } 968 | } 969 | ] 970 | }, 971 | { 972 | "reason": "Add graphics-context connections", 973 | "operations": [ 974 | { 975 | "operation": { 976 | "add-use": { 977 | "use": { 978 | "target": "wasi:graphics-context/graphics-context@0.0.1", 979 | "use-names-list": [ 980 | [ "context", null ], 981 | [ "abstract-buffer", null ] 982 | ] 983 | } 984 | } 985 | } 986 | }, 987 | { 988 | "operation": { 989 | "add-resource-func": { 990 | "resource": "gpu-device", 991 | "func": { 992 | "kind": { 993 | "method": ["connect-graphics-context", { "named": { "items": [] } }] 994 | }, 995 | "params": { 996 | "items": [ 997 | ["context", { "borrow": "context" }] 998 | ] 999 | } 1000 | } 1001 | } 1002 | } 1003 | }, 1004 | { 1005 | "operation": { 1006 | "add-resource-func": { 1007 | "resource": "gpu-texture", 1008 | "func": { 1009 | "kind": { 1010 | "static": ["from-graphics-buffer", { "anon": { "named": "gpu-texture" } }] 1011 | }, 1012 | "params": { 1013 | "items": [ 1014 | ["buffer", { "named": "abstract-buffer" }] 1015 | ] 1016 | } 1017 | } 1018 | } 1019 | } 1020 | } 1021 | ] 1022 | }, 1023 | { 1024 | "reason": "GPURenderPassLayout is only used as the base of GPURenderBundleEncoderDescriptor. Since wit doesn't have inheritance the fields are duplicated in the child so no need for the parent.", 1025 | "operations": [ 1026 | { 1027 | "operation": { 1028 | "remove-type": "gpu-render-pass-layout" 1029 | } 1030 | } 1031 | ] 1032 | }, 1033 | { 1034 | "reason": "Errors have the message field raised to the top level type so that they don't have to be taken out of the inner error. Important if we allow new error types in the future that the developer has not yet handled. They also get a `kind` to enable detecting the error type. `kind` is a variant and not an enum so that they can have fields inside like `pipeline-error.reason`. Note: not changing gpu-error to a record even though errors added by us are records, because GPUError is an interface in the spec, and might one day gain interface like properties", 1035 | "operations": [ 1036 | { 1037 | "operation": { 1038 | "add-type": { 1039 | "name": "gpu-error-kind", 1040 | "kind": { 1041 | "variant": { 1042 | "cases": [ 1043 | { "name": "validation-error" }, 1044 | { "name": "out-of-memory-error" }, 1045 | { "name": "internal-error" } 1046 | ] 1047 | } 1048 | } 1049 | } 1050 | } 1051 | }, 1052 | { 1053 | "operation": { 1054 | "add-resource-func": { 1055 | "resource": "gpu-error", 1056 | "func": { 1057 | "kind": { 1058 | "method": [ 1059 | "kind", 1060 | { 1061 | "anon": { 1062 | "named": "gpu-error-kind" 1063 | } 1064 | } 1065 | ] 1066 | }, 1067 | "params": { 1068 | "items": [] 1069 | } 1070 | } 1071 | } 1072 | } 1073 | }, 1074 | { 1075 | "operation": { 1076 | "remove-type": "gpu-validation-error" 1077 | } 1078 | }, 1079 | { 1080 | "operation": { 1081 | "remove-type": "gpu-out-of-memory-error" 1082 | } 1083 | }, 1084 | { 1085 | "operation": { 1086 | "remove-type": "gpu-internal-error" 1087 | } 1088 | } 1089 | ] 1090 | }, 1091 | { 1092 | "reason": "Remove gpu-uncaptured-error-event constructor as it's not useful, it's only here because of web specific rules. https://github.com/gpuweb/gpuweb/pull/255#issuecomment-477308123 and https://w3ctag.github.io/design-principles/#constructors", 1093 | "operations": [ 1094 | { 1095 | "operation": { 1096 | "remove-func": { 1097 | "resource": "gpu-uncaptured-error-event", 1098 | "func": "constructor" 1099 | } 1100 | } 1101 | }, 1102 | { 1103 | "operation": { 1104 | "remove-type": "gpu-uncaptured-error-event-init" 1105 | } 1106 | } 1107 | ] 1108 | }, 1109 | { 1110 | "reason": "request-device can throw for various reasons. https://www.w3.org/TR/webgpu/#dom-gpuadapter-requestdevice", 1111 | "operations": [ 1112 | { 1113 | "operation": { 1114 | "add-type": { 1115 | "name": "request-device-error-kind", 1116 | "kind": { 1117 | "variant": { 1118 | "cases": [ 1119 | { 1120 | "name": "type-error" 1121 | }, 1122 | { 1123 | "name": "operation-error" 1124 | } 1125 | ] 1126 | } 1127 | } 1128 | } 1129 | } 1130 | }, 1131 | { 1132 | "operation": { 1133 | "add-type": { 1134 | "name": "request-device-error", 1135 | "kind": { 1136 | "record": { 1137 | "fields": [ 1138 | { 1139 | "name": "kind", 1140 | "type": { 1141 | "named": "request-device-error-kind" 1142 | } 1143 | }, 1144 | { 1145 | "name": "message", 1146 | "type": "string" 1147 | } 1148 | ] 1149 | } 1150 | } 1151 | } 1152 | } 1153 | }, 1154 | { 1155 | "vars": { 1156 | "$_SUCCESS": { 1157 | "find-type": { 1158 | "func-results-anon": { 1159 | "resource": "gpu-adapter", 1160 | "func": "request-device" 1161 | } 1162 | } 1163 | } 1164 | }, 1165 | "operation": { 1166 | "retype-func-results": { 1167 | "resource": "gpu-adapter", 1168 | "func": "request-device", 1169 | "new-results": { 1170 | "anon": { 1171 | "result": { 1172 | "ok": "$_SUCCESS", 1173 | "err": { 1174 | "named": "request-device-error" 1175 | } 1176 | } 1177 | } 1178 | } 1179 | } 1180 | } 1181 | } 1182 | ] 1183 | }, 1184 | { 1185 | "reason": "create-*-pipeline-async throws if pipeline creation fails. https://www.w3.org/TR/webgpu/#async-pipeline-creation", 1186 | "operations": [ 1187 | { 1188 | "operation": { 1189 | "add-type": { 1190 | "name": "create-pipeline-error-kind", 1191 | "kind": { 1192 | "variant": { 1193 | "cases": [ 1194 | { 1195 | "name": "gpu-pipeline-error", 1196 | "type": { 1197 | "named": "gpu-pipeline-error-reason" 1198 | } 1199 | } 1200 | ] 1201 | } 1202 | } 1203 | } 1204 | } 1205 | }, 1206 | { 1207 | "operation": { 1208 | "add-type": { 1209 | "name": "create-pipeline-error", 1210 | "kind": { 1211 | "record": { 1212 | "fields": [ 1213 | { 1214 | "name": "kind", 1215 | "type": { 1216 | "named": "create-pipeline-error-kind" 1217 | } 1218 | }, 1219 | { 1220 | "name": "message", 1221 | "type": "string" 1222 | } 1223 | ] 1224 | } 1225 | } 1226 | } 1227 | } 1228 | }, 1229 | { 1230 | "vars": { 1231 | "$_SUCCESS": { 1232 | "find-type": { 1233 | "func-results-anon": { 1234 | "resource": "gpu-device", 1235 | "func": "create-compute-pipeline-async" 1236 | } 1237 | } 1238 | } 1239 | }, 1240 | "operation": { 1241 | "retype-func-results": { 1242 | "resource": "gpu-device", 1243 | "func": "create-compute-pipeline-async", 1244 | "new-results": { 1245 | "anon": { 1246 | "result": { 1247 | "ok": "$_SUCCESS", 1248 | "err": { 1249 | "named": "create-pipeline-error" 1250 | } 1251 | } 1252 | } 1253 | } 1254 | } 1255 | } 1256 | }, 1257 | { 1258 | "vars": { 1259 | "$_SUCCESS": { 1260 | "find-type": { 1261 | "func-results-anon": { 1262 | "resource": "gpu-device", 1263 | "func": "create-render-pipeline-async" 1264 | } 1265 | } 1266 | } 1267 | }, 1268 | "operation": { 1269 | "retype-func-results": { 1270 | "resource": "gpu-device", 1271 | "func": "create-render-pipeline-async", 1272 | "new-results": { 1273 | "anon": { 1274 | "result": { 1275 | "ok": "$_SUCCESS", 1276 | "err": { 1277 | "named": "create-pipeline-error" 1278 | } 1279 | } 1280 | } 1281 | } 1282 | } 1283 | } 1284 | }, 1285 | { 1286 | "operation": { 1287 | "remove-type": "gpu-pipeline-error" 1288 | } 1289 | }, 1290 | { 1291 | "operation": { 1292 | "remove-type": "gpu-pipeline-error-init" 1293 | } 1294 | } 1295 | ] 1296 | }, 1297 | { 1298 | "reason": "create-query-set throws if descriptor.type is 'timestamp', but 'timestamp-query' is not enabled for this device. https://www.w3.org/TR/webgpu/#dom-gpudevice-createqueryset", 1299 | "operations": [ 1300 | { 1301 | "operation": { 1302 | "add-type": { 1303 | "name": "create-query-set-error-kind", 1304 | "kind": { 1305 | "variant": { 1306 | "cases": [ 1307 | { 1308 | "name": "type-error" 1309 | } 1310 | ] 1311 | } 1312 | } 1313 | } 1314 | } 1315 | }, 1316 | { 1317 | "operation": { 1318 | "add-type": { 1319 | "name": "create-query-set-error", 1320 | "kind": { 1321 | "record": { 1322 | "fields": [ 1323 | { 1324 | "name": "kind", 1325 | "type": { 1326 | "named": "create-query-set-error-kind" 1327 | } 1328 | }, 1329 | { 1330 | "name": "message", 1331 | "type": "string" 1332 | } 1333 | ] 1334 | } 1335 | } 1336 | } 1337 | } 1338 | }, 1339 | { 1340 | "vars": { 1341 | "$_SUCCESS": { 1342 | "find-type": { 1343 | "func-results-anon": { 1344 | "resource": "gpu-device", 1345 | "func": "create-query-set" 1346 | } 1347 | } 1348 | } 1349 | }, 1350 | "operation": { 1351 | "retype-func-results": { 1352 | "resource": "gpu-device", 1353 | "func": "create-query-set", 1354 | "new-results": { 1355 | "anon": { 1356 | "result": { 1357 | "ok": "$_SUCCESS", 1358 | "err": { 1359 | "named": "create-query-set-error" 1360 | } 1361 | } 1362 | } 1363 | } 1364 | } 1365 | } 1366 | } 1367 | ] 1368 | }, 1369 | { 1370 | "reason": "pop-error-scope throws if the error-scope stack is empty. https://www.w3.org/TR/webgpu/#dom-gpudevice-poperrorscope", 1371 | "operations": [ 1372 | { 1373 | "operation": { 1374 | "add-type": { 1375 | "name": "pop-error-scope-error-kind", 1376 | "kind": { 1377 | "variant": { 1378 | "cases": [ 1379 | { 1380 | "name": "operation-error" 1381 | } 1382 | ] 1383 | } 1384 | } 1385 | } 1386 | } 1387 | }, 1388 | { 1389 | "operation": { 1390 | "add-type": { 1391 | "name": "pop-error-scope-error", 1392 | "kind": { 1393 | "record": { 1394 | "fields": [ 1395 | { 1396 | "name": "kind", 1397 | "type": { 1398 | "named": "pop-error-scope-error-kind" 1399 | } 1400 | }, 1401 | { 1402 | "name": "message", 1403 | "type": "string" 1404 | } 1405 | ] 1406 | } 1407 | } 1408 | } 1409 | } 1410 | }, 1411 | { 1412 | "vars": { 1413 | "$_SUCCESS": { 1414 | "find-type": { 1415 | "func-results-anon": { 1416 | "resource": "gpu-device", 1417 | "func": "pop-error-scope" 1418 | } 1419 | } 1420 | } 1421 | }, 1422 | "operation": { 1423 | "retype-func-results": { 1424 | "resource": "gpu-device", 1425 | "func": "pop-error-scope", 1426 | "new-results": { 1427 | "anon": { 1428 | "result": { 1429 | "ok": "$_SUCCESS", 1430 | "err": { 1431 | "named": "pop-error-scope-error" 1432 | } 1433 | } 1434 | } 1435 | } 1436 | } 1437 | } 1438 | } 1439 | ] 1440 | }, 1441 | { 1442 | "reason": "map-async can throw for various reasons. https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapasync", 1443 | "operations": [ 1444 | { 1445 | "operation": { 1446 | "add-type": { 1447 | "name": "map-async-error-kind", 1448 | "kind": { 1449 | "variant": { 1450 | "cases": [ 1451 | { 1452 | "name": "operation-error" 1453 | }, 1454 | { 1455 | "name": "range-error" 1456 | }, 1457 | { 1458 | "name": "abort-error" 1459 | } 1460 | ] 1461 | } 1462 | } 1463 | } 1464 | } 1465 | }, 1466 | { 1467 | "operation": { 1468 | "add-type": { 1469 | "name": "map-async-error", 1470 | "kind": { 1471 | "record": { 1472 | "fields": [ 1473 | { 1474 | "name": "kind", 1475 | "type": { 1476 | "named": "map-async-error-kind" 1477 | } 1478 | }, 1479 | { 1480 | "name": "message", 1481 | "type": "string" 1482 | } 1483 | ] 1484 | } 1485 | } 1486 | } 1487 | } 1488 | }, 1489 | { 1490 | "operation": { 1491 | "retype-func-results": { 1492 | "resource": "gpu-buffer", 1493 | "func": "map-async", 1494 | "new-results": { 1495 | "anon": { 1496 | "result": { 1497 | "err": { 1498 | "named": "map-async-error" 1499 | } 1500 | } 1501 | } 1502 | } 1503 | } 1504 | } 1505 | } 1506 | ] 1507 | }, 1508 | { 1509 | "reason": "get-mapped-range can throw for various reasons. https://www.w3.org/TR/webgpu/#dom-gpubuffer-getmappedrange", 1510 | "operations": [ 1511 | { 1512 | "operation": { 1513 | "add-type": { 1514 | "name": "get-mapped-range-error-kind", 1515 | "kind": { 1516 | "variant": { 1517 | "cases": [ 1518 | { 1519 | "name": "operation-error" 1520 | }, 1521 | { 1522 | "name": "range-error" 1523 | }, 1524 | { 1525 | "name": "type-error" 1526 | } 1527 | ] 1528 | } 1529 | } 1530 | } 1531 | } 1532 | }, 1533 | { 1534 | "operation": { 1535 | "add-type": { 1536 | "name": "get-mapped-range-error", 1537 | "kind": { 1538 | "record": { 1539 | "fields": [ 1540 | { 1541 | "name": "kind", 1542 | "type": { 1543 | "named": "get-mapped-range-error-kind" 1544 | } 1545 | }, 1546 | { 1547 | "name": "message", 1548 | "type": "string" 1549 | } 1550 | ] 1551 | } 1552 | } 1553 | } 1554 | } 1555 | }, 1556 | { 1557 | "vars": { 1558 | "$_SUCCESS": { 1559 | "find-type": { 1560 | "func-results-anon": { 1561 | "resource": "gpu-buffer", 1562 | "func": "get-mapped-range-get-with-copy" 1563 | } 1564 | } 1565 | } 1566 | }, 1567 | "operation": { 1568 | "retype-func-results": { 1569 | "resource": "gpu-buffer", 1570 | "func": "get-mapped-range-get-with-copy", 1571 | "new-results": { 1572 | "anon": { 1573 | "result": { 1574 | "ok": "$_SUCCESS", 1575 | "err": { 1576 | "named": "get-mapped-range-error" 1577 | } 1578 | } 1579 | } 1580 | } 1581 | } 1582 | } 1583 | }, 1584 | { 1585 | "operation": { 1586 | "retype-func-results": { 1587 | "resource": "gpu-buffer", 1588 | "func": "get-mapped-range-set-with-copy", 1589 | "new-results": { 1590 | "anon": { 1591 | "result": { 1592 | "err": { 1593 | "named": "get-mapped-range-error" 1594 | } 1595 | } 1596 | } 1597 | } 1598 | } 1599 | } 1600 | } 1601 | ] 1602 | }, 1603 | { 1604 | "reason": "unmap throws if called while future returned by map-async is still pending. https://www.w3.org/TR/webgpu/#dom-gpubuffer-unmap", 1605 | "operations": [ 1606 | { 1607 | "operation": { 1608 | "add-type": { 1609 | "name": "unmap-error-kind", 1610 | "kind": { 1611 | "variant": { 1612 | "cases": [ 1613 | { 1614 | "name": "abort-error" 1615 | } 1616 | ] 1617 | } 1618 | } 1619 | } 1620 | } 1621 | }, 1622 | { 1623 | "operation": { 1624 | "add-type": { 1625 | "name": "unmap-error", 1626 | "kind": { 1627 | "record": { 1628 | "fields": [ 1629 | { 1630 | "name": "kind", 1631 | "type": { 1632 | "named": "unmap-error-kind" 1633 | } 1634 | }, 1635 | { 1636 | "name": "message", 1637 | "type": "string" 1638 | } 1639 | ] 1640 | } 1641 | } 1642 | } 1643 | } 1644 | }, 1645 | { 1646 | "operation": { 1647 | "retype-func-results": { 1648 | "resource": "gpu-buffer", 1649 | "func": "unmap", 1650 | "new-results": { 1651 | "anon": { 1652 | "result": { 1653 | "err": { 1654 | "named": "unmap-error" 1655 | } 1656 | } 1657 | } 1658 | } 1659 | } 1660 | } 1661 | } 1662 | ] 1663 | }, 1664 | { 1665 | "reason": "set-bind-group throws if dynamic-offsets-data-start/length don't fit in dynamic-offsets-data. https://www.w3.org/TR/webgpu/#dom-gpubindingcommandsmixin-setbindgroup-index-bindgroup-dynamicoffsetsdata-dynamicoffsetsdatastart-dynamicoffsetsdatalength", 1666 | "operations": [ 1667 | { 1668 | "operation": { 1669 | "add-type": { 1670 | "name": "set-bind-group-error-kind", 1671 | "kind": { 1672 | "variant": { 1673 | "cases": [ 1674 | { 1675 | "name": "range-error" 1676 | } 1677 | ] 1678 | } 1679 | } 1680 | } 1681 | } 1682 | }, 1683 | { 1684 | "operation": { 1685 | "add-type": { 1686 | "name": "set-bind-group-error", 1687 | "kind": { 1688 | "record": { 1689 | "fields": [ 1690 | { 1691 | "name": "kind", 1692 | "type": { 1693 | "named": "set-bind-group-error-kind" 1694 | } 1695 | }, 1696 | { 1697 | "name": "message", 1698 | "type": "string" 1699 | } 1700 | ] 1701 | } 1702 | } 1703 | } 1704 | } 1705 | }, 1706 | { 1707 | "operation": { 1708 | "retype-func-results": { 1709 | "resource": "gpu-compute-pass-encoder", 1710 | "func": "set-bind-group", 1711 | "new-results": { 1712 | "anon": { 1713 | "result": { 1714 | "err": { 1715 | "named": "set-bind-group-error" 1716 | } 1717 | } 1718 | } 1719 | } 1720 | } 1721 | } 1722 | }, 1723 | { 1724 | "operation": { 1725 | "retype-func-results": { 1726 | "resource": "gpu-render-pass-encoder", 1727 | "func": "set-bind-group", 1728 | "new-results": { 1729 | "anon": { 1730 | "result": { 1731 | "err": { 1732 | "named": "set-bind-group-error" 1733 | } 1734 | } 1735 | } 1736 | } 1737 | } 1738 | } 1739 | }, 1740 | { 1741 | "operation": { 1742 | "retype-func-results": { 1743 | "resource": "gpu-render-bundle-encoder", 1744 | "func": "set-bind-group", 1745 | "new-results": { 1746 | "anon": { 1747 | "result": { 1748 | "err": { 1749 | "named": "set-bind-group-error" 1750 | } 1751 | } 1752 | } 1753 | } 1754 | } 1755 | } 1756 | } 1757 | ] 1758 | }, 1759 | { 1760 | "reason": "write-buffer can throw for various reasons. https://www.w3.org/TR/webgpu/#dom-gpuqueue-writebuffer", 1761 | "operations": [ 1762 | { 1763 | "operation": { 1764 | "add-type": { 1765 | "name": "write-buffer-error-kind", 1766 | "kind": { 1767 | "variant": { 1768 | "cases": [ 1769 | { 1770 | "name": "operation-error" 1771 | } 1772 | ] 1773 | } 1774 | } 1775 | } 1776 | } 1777 | }, 1778 | { 1779 | "operation": { 1780 | "add-type": { 1781 | "name": "write-buffer-error", 1782 | "kind": { 1783 | "record": { 1784 | "fields": [ 1785 | { 1786 | "name": "kind", 1787 | "type": { 1788 | "named": "write-buffer-error-kind" 1789 | } 1790 | }, 1791 | { 1792 | "name": "message", 1793 | "type": "string" 1794 | } 1795 | ] 1796 | } 1797 | } 1798 | } 1799 | } 1800 | }, 1801 | { 1802 | "operation": { 1803 | "retype-func-results": { 1804 | "resource": "gpu-queue", 1805 | "func": "write-buffer-with-copy", 1806 | "new-results": { 1807 | "anon": { 1808 | "result": { 1809 | "err": { 1810 | "named": "write-buffer-error" 1811 | } 1812 | } 1813 | } 1814 | } 1815 | } 1816 | } 1817 | } 1818 | ] 1819 | } 1820 | ] 1821 | -------------------------------------------------------------------------------- /webgpu/imports.wit: -------------------------------------------------------------------------------- 1 | package wasi:webgpu@0.0.1; 2 | 3 | world imports { 4 | import webgpu; 5 | } 6 | -------------------------------------------------------------------------------- /webgpu/webgpu.wit: -------------------------------------------------------------------------------- 1 | package wasi:webgpu@0.0.1; 2 | 3 | interface webgpu { 4 | use wasi:io/poll@0.2.0.{ pollable }; 5 | use wasi:graphics-context/graphics-context@0.0.1.{ context, abstract-buffer }; 6 | resource gpu-supported-limits { 7 | max-texture-dimension1-d: func() -> u32; 8 | max-texture-dimension2-d: func() -> u32; 9 | max-texture-dimension3-d: func() -> u32; 10 | max-texture-array-layers: func() -> u32; 11 | max-bind-groups: func() -> u32; 12 | max-bind-groups-plus-vertex-buffers: func() -> u32; 13 | max-bindings-per-bind-group: func() -> u32; 14 | max-dynamic-uniform-buffers-per-pipeline-layout: func() -> u32; 15 | max-dynamic-storage-buffers-per-pipeline-layout: func() -> u32; 16 | max-sampled-textures-per-shader-stage: func() -> u32; 17 | max-samplers-per-shader-stage: func() -> u32; 18 | max-storage-buffers-per-shader-stage: func() -> u32; 19 | max-storage-textures-per-shader-stage: func() -> u32; 20 | max-uniform-buffers-per-shader-stage: func() -> u32; 21 | max-uniform-buffer-binding-size: func() -> u64; 22 | max-storage-buffer-binding-size: func() -> u64; 23 | min-uniform-buffer-offset-alignment: func() -> u32; 24 | min-storage-buffer-offset-alignment: func() -> u32; 25 | max-vertex-buffers: func() -> u32; 26 | max-buffer-size: func() -> u64; 27 | max-vertex-attributes: func() -> u32; 28 | max-vertex-buffer-array-stride: func() -> u32; 29 | max-inter-stage-shader-variables: func() -> u32; 30 | max-color-attachments: func() -> u32; 31 | max-color-attachment-bytes-per-sample: func() -> u32; 32 | max-compute-workgroup-storage-size: func() -> u32; 33 | max-compute-invocations-per-workgroup: func() -> u32; 34 | max-compute-workgroup-size-x: func() -> u32; 35 | max-compute-workgroup-size-y: func() -> u32; 36 | max-compute-workgroup-size-z: func() -> u32; 37 | max-compute-workgroups-per-dimension: func() -> u32; 38 | } 39 | resource gpu-supported-features { 40 | has: func(value: string) -> bool; 41 | } 42 | resource wgsl-language-features { 43 | has: func(value: string) -> bool; 44 | } 45 | resource gpu-adapter-info { 46 | vendor: func() -> string; 47 | architecture: func() -> string; 48 | device: func() -> string; 49 | description: func() -> string; 50 | subgroup-min-size: func() -> u32; 51 | subgroup-max-size: func() -> u32; 52 | } 53 | resource gpu { 54 | request-adapter: func(options: option) -> option; 55 | get-preferred-canvas-format: func() -> gpu-texture-format; 56 | wgsl-language-features: func() -> wgsl-language-features; 57 | } 58 | enum gpu-power-preference { 59 | low-power, 60 | high-performance, 61 | } 62 | record gpu-request-adapter-options { 63 | feature-level: option, 64 | power-preference: option, 65 | force-fallback-adapter: option, 66 | xr-compatible: option, 67 | } 68 | resource gpu-adapter { 69 | features: func() -> gpu-supported-features; 70 | limits: func() -> gpu-supported-limits; 71 | info: func() -> gpu-adapter-info; 72 | is-fallback-adapter: func() -> bool; 73 | request-device: func(descriptor: option) -> result; 74 | } 75 | resource record-option-gpu-size64 { 76 | constructor(); 77 | add: func(key: string, value: option); 78 | get: func(key: string) -> option>; 79 | has: func(key: string) -> bool; 80 | remove: func(key: string); 81 | keys: func() -> list; 82 | values: func() -> list>; 83 | entries: func() -> list>>; 84 | } 85 | enum gpu-feature-name { 86 | depth-clip-control, 87 | depth32float-stencil8, 88 | texture-compression-bc, 89 | texture-compression-bc-sliced3d, 90 | texture-compression-etc2, 91 | texture-compression-astc, 92 | texture-compression-astc-sliced3d, 93 | timestamp-query, 94 | indirect-first-instance, 95 | shader-f16, 96 | rg11b10ufloat-renderable, 97 | bgra8unorm-storage, 98 | float32-filterable, 99 | float32-blendable, 100 | clip-distances, 101 | dual-source-blending, 102 | subgroups, 103 | } 104 | resource gpu-device { 105 | features: func() -> gpu-supported-features; 106 | limits: func() -> gpu-supported-limits; 107 | adapter-info: func() -> gpu-adapter-info; 108 | queue: func() -> gpu-queue; 109 | destroy: func(); 110 | create-buffer: func(descriptor: gpu-buffer-descriptor) -> gpu-buffer; 111 | create-texture: func(descriptor: gpu-texture-descriptor) -> gpu-texture; 112 | create-sampler: func(descriptor: option) -> gpu-sampler; 113 | create-bind-group-layout: func(descriptor: gpu-bind-group-layout-descriptor) -> gpu-bind-group-layout; 114 | create-pipeline-layout: func(descriptor: gpu-pipeline-layout-descriptor) -> gpu-pipeline-layout; 115 | create-bind-group: func(descriptor: gpu-bind-group-descriptor) -> gpu-bind-group; 116 | create-shader-module: func(descriptor: gpu-shader-module-descriptor) -> gpu-shader-module; 117 | create-compute-pipeline: func(descriptor: gpu-compute-pipeline-descriptor) -> gpu-compute-pipeline; 118 | create-render-pipeline: func(descriptor: gpu-render-pipeline-descriptor) -> gpu-render-pipeline; 119 | create-compute-pipeline-async: func(descriptor: gpu-compute-pipeline-descriptor) -> result; 120 | create-render-pipeline-async: func(descriptor: gpu-render-pipeline-descriptor) -> result; 121 | create-command-encoder: func(descriptor: option) -> gpu-command-encoder; 122 | create-render-bundle-encoder: func(descriptor: gpu-render-bundle-encoder-descriptor) -> gpu-render-bundle-encoder; 123 | create-query-set: func(descriptor: gpu-query-set-descriptor) -> result; 124 | label: func() -> string; 125 | set-label: func(label: string); 126 | lost: func() -> gpu-device-lost-info; 127 | push-error-scope: func(filter: gpu-error-filter); 128 | pop-error-scope: func() -> result, pop-error-scope-error>; 129 | onuncapturederror-subscribe: func() -> pollable; 130 | connect-graphics-context: func(context: borrow); 131 | } 132 | resource gpu-buffer { 133 | size: func() -> gpu-size64-out; 134 | usage: func() -> gpu-flags-constant; 135 | map-state: func() -> gpu-buffer-map-state; 136 | map-async: func(mode: gpu-map-mode-flags, offset: option, size: option) -> result<_, map-async-error>; 137 | get-mapped-range-get-with-copy: func(offset: option, size: option) -> result, get-mapped-range-error>; 138 | unmap: func() -> result<_, unmap-error>; 139 | destroy: func(); 140 | label: func() -> string; 141 | set-label: func(label: string); 142 | get-mapped-range-set-with-copy: func(data: list, offset: option, size: option) -> result<_, get-mapped-range-error>; 143 | } 144 | enum gpu-buffer-map-state { 145 | unmapped, 146 | pending, 147 | mapped, 148 | } 149 | type gpu-buffer-usage-flags = u32; 150 | resource gpu-buffer-usage { 151 | MAP-READ: static func() -> gpu-flags-constant; 152 | MAP-WRITE: static func() -> gpu-flags-constant; 153 | COPY-SRC: static func() -> gpu-flags-constant; 154 | COPY-DST: static func() -> gpu-flags-constant; 155 | INDEX: static func() -> gpu-flags-constant; 156 | VERTEX: static func() -> gpu-flags-constant; 157 | UNIFORM: static func() -> gpu-flags-constant; 158 | STORAGE: static func() -> gpu-flags-constant; 159 | INDIRECT: static func() -> gpu-flags-constant; 160 | QUERY-RESOLVE: static func() -> gpu-flags-constant; 161 | } 162 | type gpu-map-mode-flags = u32; 163 | resource gpu-map-mode { 164 | READ: static func() -> gpu-flags-constant; 165 | WRITE: static func() -> gpu-flags-constant; 166 | } 167 | resource gpu-texture { 168 | create-view: func(descriptor: option) -> gpu-texture-view; 169 | destroy: func(); 170 | width: func() -> gpu-integer-coordinate-out; 171 | height: func() -> gpu-integer-coordinate-out; 172 | depth-or-array-layers: func() -> gpu-integer-coordinate-out; 173 | mip-level-count: func() -> gpu-integer-coordinate-out; 174 | sample-count: func() -> gpu-size32-out; 175 | dimension: func() -> gpu-texture-dimension; 176 | format: func() -> gpu-texture-format; 177 | usage: func() -> gpu-flags-constant; 178 | label: func() -> string; 179 | set-label: func(label: string); 180 | from-graphics-buffer: static func(buffer: abstract-buffer) -> gpu-texture; 181 | } 182 | enum gpu-texture-dimension { 183 | d1, 184 | d2, 185 | d3, 186 | } 187 | type gpu-texture-usage-flags = u32; 188 | resource gpu-texture-usage { 189 | COPY-SRC: static func() -> gpu-flags-constant; 190 | COPY-DST: static func() -> gpu-flags-constant; 191 | TEXTURE-BINDING: static func() -> gpu-flags-constant; 192 | STORAGE-BINDING: static func() -> gpu-flags-constant; 193 | RENDER-ATTACHMENT: static func() -> gpu-flags-constant; 194 | } 195 | resource gpu-texture-view { 196 | label: func() -> string; 197 | set-label: func(label: string); 198 | } 199 | enum gpu-texture-view-dimension { 200 | d1, 201 | d2, 202 | d2-array, 203 | cube, 204 | cube-array, 205 | d3, 206 | } 207 | enum gpu-texture-aspect { 208 | all, 209 | stencil-only, 210 | depth-only, 211 | } 212 | enum gpu-texture-format { 213 | r8unorm, 214 | r8snorm, 215 | r8uint, 216 | r8sint, 217 | r16uint, 218 | r16sint, 219 | r16float, 220 | rg8unorm, 221 | rg8snorm, 222 | rg8uint, 223 | rg8sint, 224 | r32uint, 225 | r32sint, 226 | r32float, 227 | rg16uint, 228 | rg16sint, 229 | rg16float, 230 | rgba8unorm, 231 | rgba8unorm-srgb, 232 | rgba8snorm, 233 | rgba8uint, 234 | rgba8sint, 235 | bgra8unorm, 236 | bgra8unorm-srgb, 237 | rgb9e5ufloat, 238 | rgb10a2uint, 239 | rgb10a2unorm, 240 | rg11b10ufloat, 241 | rg32uint, 242 | rg32sint, 243 | rg32float, 244 | rgba16uint, 245 | rgba16sint, 246 | rgba16float, 247 | rgba32uint, 248 | rgba32sint, 249 | rgba32float, 250 | stencil8, 251 | depth16unorm, 252 | depth24plus, 253 | depth24plus-stencil8, 254 | depth32float, 255 | depth32float-stencil8, 256 | bc1-rgba-unorm, 257 | bc1-rgba-unorm-srgb, 258 | bc2-rgba-unorm, 259 | bc2-rgba-unorm-srgb, 260 | bc3-rgba-unorm, 261 | bc3-rgba-unorm-srgb, 262 | bc4-r-unorm, 263 | bc4-r-snorm, 264 | bc5-rg-unorm, 265 | bc5-rg-snorm, 266 | bc6h-rgb-ufloat, 267 | bc6h-rgb-float, 268 | bc7-rgba-unorm, 269 | bc7-rgba-unorm-srgb, 270 | etc2-rgb8unorm, 271 | etc2-rgb8unorm-srgb, 272 | etc2-rgb8a1unorm, 273 | etc2-rgb8a1unorm-srgb, 274 | etc2-rgba8unorm, 275 | etc2-rgba8unorm-srgb, 276 | eac-r11unorm, 277 | eac-r11snorm, 278 | eac-rg11unorm, 279 | eac-rg11snorm, 280 | astc4x4-unorm, 281 | astc4x4-unorm-srgb, 282 | astc5x4-unorm, 283 | astc5x4-unorm-srgb, 284 | astc5x5-unorm, 285 | astc5x5-unorm-srgb, 286 | astc6x5-unorm, 287 | astc6x5-unorm-srgb, 288 | astc6x6-unorm, 289 | astc6x6-unorm-srgb, 290 | astc8x5-unorm, 291 | astc8x5-unorm-srgb, 292 | astc8x6-unorm, 293 | astc8x6-unorm-srgb, 294 | astc8x8-unorm, 295 | astc8x8-unorm-srgb, 296 | astc10x5-unorm, 297 | astc10x5-unorm-srgb, 298 | astc10x6-unorm, 299 | astc10x6-unorm-srgb, 300 | astc10x8-unorm, 301 | astc10x8-unorm-srgb, 302 | astc10x10-unorm, 303 | astc10x10-unorm-srgb, 304 | astc12x10-unorm, 305 | astc12x10-unorm-srgb, 306 | astc12x12-unorm, 307 | astc12x12-unorm-srgb, 308 | } 309 | resource gpu-sampler { 310 | label: func() -> string; 311 | set-label: func(label: string); 312 | } 313 | enum gpu-address-mode { 314 | clamp-to-edge, 315 | repeat, 316 | mirror-repeat, 317 | } 318 | enum gpu-filter-mode { 319 | nearest, 320 | linear, 321 | } 322 | enum gpu-mipmap-filter-mode { 323 | nearest, 324 | linear, 325 | } 326 | enum gpu-compare-function { 327 | never, 328 | less, 329 | equal, 330 | less-equal, 331 | greater, 332 | not-equal, 333 | greater-equal, 334 | always, 335 | } 336 | record gpu-sampler-descriptor { 337 | address-mode-u: option, 338 | address-mode-v: option, 339 | address-mode-w: option, 340 | mag-filter: option, 341 | min-filter: option, 342 | mipmap-filter: option, 343 | lod-min-clamp: option, 344 | lod-max-clamp: option, 345 | compare: option, 346 | max-anisotropy: option, 347 | label: option, 348 | } 349 | resource gpu-bind-group-layout { 350 | label: func() -> string; 351 | set-label: func(label: string); 352 | } 353 | type gpu-shader-stage-flags = u32; 354 | resource gpu-shader-stage { 355 | VERTEX: static func() -> gpu-flags-constant; 356 | FRAGMENT: static func() -> gpu-flags-constant; 357 | COMPUTE: static func() -> gpu-flags-constant; 358 | } 359 | enum gpu-buffer-binding-type { 360 | uniform, 361 | storage, 362 | read-only-storage, 363 | } 364 | enum gpu-sampler-binding-type { 365 | filtering, 366 | non-filtering, 367 | comparison, 368 | } 369 | record gpu-sampler-binding-layout { 370 | %type: option, 371 | } 372 | enum gpu-texture-sample-type { 373 | float, 374 | unfilterable-float, 375 | depth, 376 | sint, 377 | uint, 378 | } 379 | record gpu-texture-binding-layout { 380 | sample-type: option, 381 | view-dimension: option, 382 | multisampled: option, 383 | } 384 | enum gpu-storage-texture-access { 385 | write-only, 386 | read-only, 387 | read-write, 388 | } 389 | record gpu-storage-texture-binding-layout { 390 | access: option, 391 | format: gpu-texture-format, 392 | view-dimension: option, 393 | } 394 | resource gpu-bind-group { 395 | label: func() -> string; 396 | set-label: func(label: string); 397 | } 398 | resource gpu-pipeline-layout { 399 | label: func() -> string; 400 | set-label: func(label: string); 401 | } 402 | record gpu-pipeline-layout-descriptor { 403 | bind-group-layouts: list>>, 404 | label: option, 405 | } 406 | resource gpu-shader-module { 407 | get-compilation-info: func() -> gpu-compilation-info; 408 | label: func() -> string; 409 | set-label: func(label: string); 410 | } 411 | enum gpu-compilation-message-type { 412 | error, 413 | warning, 414 | info, 415 | } 416 | resource gpu-compilation-message { 417 | message: func() -> string; 418 | %type: func() -> gpu-compilation-message-type; 419 | line-num: func() -> u64; 420 | line-pos: func() -> u64; 421 | offset: func() -> u64; 422 | length: func() -> u64; 423 | } 424 | resource gpu-compilation-info { 425 | messages: func() -> list; 426 | } 427 | enum gpu-pipeline-error-reason { 428 | validation, 429 | internal, 430 | } 431 | variant gpu-layout-mode { 432 | specific(borrow), 433 | auto, 434 | } 435 | record gpu-shader-module-compilation-hint { 436 | entry-point: string, 437 | layout: option, 438 | } 439 | record gpu-shader-module-descriptor { 440 | code: string, 441 | compilation-hints: option>, 442 | label: option, 443 | } 444 | resource record-gpu-pipeline-constant-value { 445 | constructor(); 446 | add: func(key: string, value: gpu-pipeline-constant-value); 447 | get: func(key: string) -> option; 448 | has: func(key: string) -> bool; 449 | remove: func(key: string); 450 | keys: func() -> list; 451 | values: func() -> list; 452 | entries: func() -> list>; 453 | } 454 | record gpu-programmable-stage { 455 | module: borrow, 456 | entry-point: option, 457 | constants: option, 458 | } 459 | type gpu-pipeline-constant-value = f64; 460 | resource gpu-compute-pipeline { 461 | label: func() -> string; 462 | set-label: func(label: string); 463 | get-bind-group-layout: func(index: u32) -> gpu-bind-group-layout; 464 | } 465 | record gpu-compute-pipeline-descriptor { 466 | compute: gpu-programmable-stage, 467 | layout: gpu-layout-mode, 468 | label: option, 469 | } 470 | resource gpu-render-pipeline { 471 | label: func() -> string; 472 | set-label: func(label: string); 473 | get-bind-group-layout: func(index: u32) -> gpu-bind-group-layout; 474 | } 475 | enum gpu-primitive-topology { 476 | point-list, 477 | line-list, 478 | line-strip, 479 | triangle-list, 480 | triangle-strip, 481 | } 482 | enum gpu-front-face { 483 | ccw, 484 | cw, 485 | } 486 | enum gpu-cull-mode { 487 | none, 488 | front, 489 | back, 490 | } 491 | type gpu-color-write-flags = u32; 492 | resource gpu-color-write { 493 | RED: static func() -> gpu-flags-constant; 494 | GREEN: static func() -> gpu-flags-constant; 495 | BLUE: static func() -> gpu-flags-constant; 496 | ALPHA: static func() -> gpu-flags-constant; 497 | ALL: static func() -> gpu-flags-constant; 498 | } 499 | enum gpu-blend-factor { 500 | zero, 501 | one, 502 | src, 503 | one-minus-src, 504 | src-alpha, 505 | one-minus-src-alpha, 506 | dst, 507 | one-minus-dst, 508 | dst-alpha, 509 | one-minus-dst-alpha, 510 | src-alpha-saturated, 511 | constant, 512 | one-minus-constant, 513 | src1, 514 | one-minus-src1, 515 | src1-alpha, 516 | one-minus-src1-alpha, 517 | } 518 | enum gpu-blend-operation { 519 | add, 520 | subtract, 521 | reverse-subtract, 522 | min, 523 | max, 524 | } 525 | record gpu-blend-component { 526 | operation: option, 527 | src-factor: option, 528 | dst-factor: option, 529 | } 530 | record gpu-blend-state { 531 | color: gpu-blend-component, 532 | alpha: gpu-blend-component, 533 | } 534 | record gpu-color-target-state { 535 | format: gpu-texture-format, 536 | blend: option, 537 | write-mask: option, 538 | } 539 | record gpu-fragment-state { 540 | targets: list>, 541 | module: borrow, 542 | entry-point: option, 543 | constants: option, 544 | } 545 | enum gpu-stencil-operation { 546 | keep, 547 | zero, 548 | replace, 549 | invert, 550 | increment-clamp, 551 | decrement-clamp, 552 | increment-wrap, 553 | decrement-wrap, 554 | } 555 | record gpu-stencil-face-state { 556 | compare: option, 557 | fail-op: option, 558 | depth-fail-op: option, 559 | pass-op: option, 560 | } 561 | enum gpu-index-format { 562 | uint16, 563 | uint32, 564 | } 565 | record gpu-primitive-state { 566 | topology: option, 567 | strip-index-format: option, 568 | front-face: option, 569 | cull-mode: option, 570 | unclipped-depth: option, 571 | } 572 | enum gpu-vertex-format { 573 | uint8, 574 | uint8x2, 575 | uint8x4, 576 | sint8, 577 | sint8x2, 578 | sint8x4, 579 | unorm8, 580 | unorm8x2, 581 | unorm8x4, 582 | snorm8, 583 | snorm8x2, 584 | snorm8x4, 585 | uint16, 586 | uint16x2, 587 | uint16x4, 588 | sint16, 589 | sint16x2, 590 | sint16x4, 591 | unorm16, 592 | unorm16x2, 593 | unorm16x4, 594 | snorm16, 595 | snorm16x2, 596 | snorm16x4, 597 | float16, 598 | float16x2, 599 | float16x4, 600 | float32, 601 | float32x2, 602 | float32x3, 603 | float32x4, 604 | uint32, 605 | uint32x2, 606 | uint32x3, 607 | uint32x4, 608 | sint32, 609 | sint32x2, 610 | sint32x3, 611 | sint32x4, 612 | unorm1010102, 613 | unorm8x4-bgra, 614 | } 615 | enum gpu-vertex-step-mode { 616 | vertex, 617 | instance, 618 | } 619 | resource gpu-command-buffer { 620 | label: func() -> string; 621 | set-label: func(label: string); 622 | } 623 | record gpu-command-buffer-descriptor { 624 | label: option, 625 | } 626 | resource gpu-command-encoder { 627 | begin-render-pass: func(descriptor: gpu-render-pass-descriptor) -> gpu-render-pass-encoder; 628 | begin-compute-pass: func(descriptor: option) -> gpu-compute-pass-encoder; 629 | copy-buffer-to-buffer: func(source: borrow, source-offset: gpu-size64, destination: borrow, destination-offset: gpu-size64, size: gpu-size64); 630 | copy-buffer-to-texture: func(source: gpu-texel-copy-buffer-info, destination: gpu-texel-copy-texture-info, copy-size: gpu-extent3-d); 631 | copy-texture-to-buffer: func(source: gpu-texel-copy-texture-info, destination: gpu-texel-copy-buffer-info, copy-size: gpu-extent3-d); 632 | copy-texture-to-texture: func(source: gpu-texel-copy-texture-info, destination: gpu-texel-copy-texture-info, copy-size: gpu-extent3-d); 633 | clear-buffer: func(buffer: borrow, offset: option, size: option); 634 | resolve-query-set: func(query-set: borrow, first-query: gpu-size32, query-count: gpu-size32, destination: borrow, destination-offset: gpu-size64); 635 | finish: func(descriptor: option) -> gpu-command-buffer; 636 | label: func() -> string; 637 | set-label: func(label: string); 638 | push-debug-group: func(group-label: string); 639 | pop-debug-group: func(); 640 | insert-debug-marker: func(marker-label: string); 641 | } 642 | record gpu-command-encoder-descriptor { 643 | label: option, 644 | } 645 | resource gpu-compute-pass-encoder { 646 | set-pipeline: func(pipeline: borrow); 647 | dispatch-workgroups: func(workgroup-count-x: gpu-size32, workgroup-count-y: option, workgroup-count-z: option); 648 | dispatch-workgroups-indirect: func(indirect-buffer: borrow, indirect-offset: gpu-size64); 649 | end: func(); 650 | label: func() -> string; 651 | set-label: func(label: string); 652 | push-debug-group: func(group-label: string); 653 | pop-debug-group: func(); 654 | insert-debug-marker: func(marker-label: string); 655 | set-bind-group: func(index: gpu-index32, bind-group: option>, dynamic-offsets-data: option>, dynamic-offsets-data-start: option, dynamic-offsets-data-length: option) -> result<_, set-bind-group-error>; 656 | } 657 | resource gpu-render-pass-encoder { 658 | set-viewport: func(x: f32, y: f32, width: f32, height: f32, min-depth: f32, max-depth: f32); 659 | set-scissor-rect: func(x: gpu-integer-coordinate, y: gpu-integer-coordinate, width: gpu-integer-coordinate, height: gpu-integer-coordinate); 660 | set-blend-constant: func(color: gpu-color); 661 | set-stencil-reference: func(reference: gpu-stencil-value); 662 | begin-occlusion-query: func(query-index: gpu-size32); 663 | end-occlusion-query: func(); 664 | execute-bundles: func(bundles: list>); 665 | end: func(); 666 | label: func() -> string; 667 | set-label: func(label: string); 668 | push-debug-group: func(group-label: string); 669 | pop-debug-group: func(); 670 | insert-debug-marker: func(marker-label: string); 671 | set-bind-group: func(index: gpu-index32, bind-group: option>, dynamic-offsets-data: option>, dynamic-offsets-data-start: option, dynamic-offsets-data-length: option) -> result<_, set-bind-group-error>; 672 | set-pipeline: func(pipeline: borrow); 673 | set-index-buffer: func(buffer: borrow, index-format: gpu-index-format, offset: option, size: option); 674 | set-vertex-buffer: func(slot: gpu-index32, buffer: option>, offset: option, size: option); 675 | draw: func(vertex-count: gpu-size32, instance-count: option, first-vertex: option, first-instance: option); 676 | draw-indexed: func(index-count: gpu-size32, instance-count: option, first-index: option, base-vertex: option, first-instance: option); 677 | draw-indirect: func(indirect-buffer: borrow, indirect-offset: gpu-size64); 678 | draw-indexed-indirect: func(indirect-buffer: borrow, indirect-offset: gpu-size64); 679 | } 680 | enum gpu-load-op { 681 | load, 682 | clear, 683 | } 684 | enum gpu-store-op { 685 | store, 686 | discard, 687 | } 688 | resource gpu-render-bundle { 689 | label: func() -> string; 690 | set-label: func(label: string); 691 | } 692 | record gpu-render-bundle-descriptor { 693 | label: option, 694 | } 695 | resource gpu-render-bundle-encoder { 696 | finish: func(descriptor: option) -> gpu-render-bundle; 697 | label: func() -> string; 698 | set-label: func(label: string); 699 | push-debug-group: func(group-label: string); 700 | pop-debug-group: func(); 701 | insert-debug-marker: func(marker-label: string); 702 | set-bind-group: func(index: gpu-index32, bind-group: option>, dynamic-offsets-data: option>, dynamic-offsets-data-start: option, dynamic-offsets-data-length: option) -> result<_, set-bind-group-error>; 703 | set-pipeline: func(pipeline: borrow); 704 | set-index-buffer: func(buffer: borrow, index-format: gpu-index-format, offset: option, size: option); 705 | set-vertex-buffer: func(slot: gpu-index32, buffer: option>, offset: option, size: option); 706 | draw: func(vertex-count: gpu-size32, instance-count: option, first-vertex: option, first-instance: option); 707 | draw-indexed: func(index-count: gpu-size32, instance-count: option, first-index: option, base-vertex: option, first-instance: option); 708 | draw-indirect: func(indirect-buffer: borrow, indirect-offset: gpu-size64); 709 | draw-indexed-indirect: func(indirect-buffer: borrow, indirect-offset: gpu-size64); 710 | } 711 | record gpu-queue-descriptor { 712 | label: option, 713 | } 714 | record gpu-device-descriptor { 715 | required-features: option>, 716 | required-limits: option, 717 | default-queue: option, 718 | label: option, 719 | } 720 | resource gpu-queue { 721 | submit: func(command-buffers: list>); 722 | on-submitted-work-done: func(); 723 | write-buffer-with-copy: func(buffer: borrow, buffer-offset: gpu-size64, data: list, data-offset: option, size: option) -> result<_, write-buffer-error>; 724 | write-texture-with-copy: func(destination: gpu-texel-copy-texture-info, data: list, data-layout: gpu-texel-copy-buffer-layout, size: gpu-extent3-d); 725 | label: func() -> string; 726 | set-label: func(label: string); 727 | } 728 | resource gpu-query-set { 729 | destroy: func(); 730 | %type: func() -> gpu-query-type; 731 | count: func() -> gpu-size32-out; 732 | label: func() -> string; 733 | set-label: func(label: string); 734 | } 735 | enum gpu-query-type { 736 | occlusion, 737 | timestamp, 738 | } 739 | resource gpu-canvas-context { 740 | configure: func(configuration: gpu-canvas-configuration); 741 | unconfigure: func(); 742 | get-configuration: func() -> option; 743 | get-current-texture: func() -> gpu-texture; 744 | } 745 | enum gpu-canvas-alpha-mode { 746 | opaque, 747 | premultiplied, 748 | } 749 | enum gpu-canvas-tone-mapping-mode { 750 | standard, 751 | extended, 752 | } 753 | record gpu-canvas-tone-mapping { 754 | mode: option, 755 | } 756 | record gpu-canvas-configuration { 757 | device: borrow, 758 | format: gpu-texture-format, 759 | usage: option, 760 | view-formats: option>, 761 | color-space: option, 762 | tone-mapping: option, 763 | alpha-mode: option, 764 | } 765 | enum gpu-device-lost-reason { 766 | unknown, 767 | destroyed, 768 | } 769 | resource gpu-device-lost-info { 770 | reason: func() -> gpu-device-lost-reason; 771 | message: func() -> string; 772 | } 773 | resource gpu-error { 774 | message: func() -> string; 775 | kind: func() -> gpu-error-kind; 776 | } 777 | enum gpu-error-filter { 778 | validation, 779 | out-of-memory, 780 | internal, 781 | } 782 | resource gpu-uncaptured-error-event { 783 | error: func() -> gpu-error; 784 | } 785 | type gpu-buffer-dynamic-offset = u32; 786 | type gpu-stencil-value = u32; 787 | record gpu-render-pass-depth-stencil-attachment { 788 | view: borrow, 789 | depth-clear-value: option, 790 | depth-load-op: option, 791 | depth-store-op: option, 792 | depth-read-only: option, 793 | stencil-clear-value: option, 794 | stencil-load-op: option, 795 | stencil-store-op: option, 796 | stencil-read-only: option, 797 | } 798 | type gpu-sample-mask = u32; 799 | type gpu-depth-bias = s32; 800 | record gpu-depth-stencil-state { 801 | format: gpu-texture-format, 802 | depth-write-enabled: option, 803 | depth-compare: option, 804 | stencil-front: option, 805 | stencil-back: option, 806 | stencil-read-mask: option, 807 | stencil-write-mask: option, 808 | depth-bias: option, 809 | depth-bias-slope-scale: option, 810 | depth-bias-clamp: option, 811 | } 812 | type gpu-size64 = u64; 813 | record gpu-buffer-descriptor { 814 | size: gpu-size64, 815 | usage: gpu-buffer-usage-flags, 816 | mapped-at-creation: option, 817 | label: option, 818 | } 819 | record gpu-buffer-binding-layout { 820 | %type: option, 821 | has-dynamic-offset: option, 822 | min-binding-size: option, 823 | } 824 | record gpu-buffer-binding { 825 | buffer: borrow, 826 | offset: option, 827 | size: option, 828 | } 829 | variant gpu-binding-resource { 830 | gpu-buffer-binding(gpu-buffer-binding), 831 | gpu-sampler(borrow), 832 | gpu-texture-view(borrow), 833 | } 834 | type gpu-integer-coordinate = u32; 835 | record gpu-texture-view-descriptor { 836 | format: option, 837 | dimension: option, 838 | usage: option, 839 | aspect: option, 840 | base-mip-level: option, 841 | mip-level-count: option, 842 | base-array-layer: option, 843 | array-layer-count: option, 844 | label: option, 845 | } 846 | type gpu-index32 = u32; 847 | record gpu-bind-group-layout-entry { 848 | binding: gpu-index32, 849 | visibility: gpu-shader-stage-flags, 850 | buffer: option, 851 | sampler: option, 852 | texture: option, 853 | storage-texture: option, 854 | } 855 | record gpu-bind-group-layout-descriptor { 856 | entries: list, 857 | label: option, 858 | } 859 | record gpu-bind-group-entry { 860 | binding: gpu-index32, 861 | %resource: gpu-binding-resource, 862 | } 863 | record gpu-bind-group-descriptor { 864 | layout: borrow, 865 | entries: list, 866 | label: option, 867 | } 868 | record gpu-vertex-attribute { 869 | format: gpu-vertex-format, 870 | offset: gpu-size64, 871 | shader-location: gpu-index32, 872 | } 873 | record gpu-vertex-buffer-layout { 874 | array-stride: gpu-size64, 875 | step-mode: option, 876 | attributes: list, 877 | } 878 | record gpu-vertex-state { 879 | buffers: option>>, 880 | module: borrow, 881 | entry-point: option, 882 | constants: option, 883 | } 884 | type gpu-size32 = u32; 885 | record gpu-multisample-state { 886 | count: option, 887 | mask: option, 888 | alpha-to-coverage-enabled: option, 889 | } 890 | record gpu-render-pipeline-descriptor { 891 | vertex: gpu-vertex-state, 892 | primitive: option, 893 | depth-stencil: option, 894 | multisample: option, 895 | fragment: option, 896 | layout: gpu-layout-mode, 897 | label: option, 898 | } 899 | record gpu-texel-copy-buffer-layout { 900 | offset: option, 901 | bytes-per-row: option, 902 | rows-per-image: option, 903 | } 904 | record gpu-texel-copy-buffer-info { 905 | buffer: borrow, 906 | offset: option, 907 | bytes-per-row: option, 908 | rows-per-image: option, 909 | } 910 | record gpu-compute-pass-timestamp-writes { 911 | query-set: borrow, 912 | beginning-of-pass-write-index: option, 913 | end-of-pass-write-index: option, 914 | } 915 | record gpu-compute-pass-descriptor { 916 | timestamp-writes: option, 917 | label: option, 918 | } 919 | record gpu-render-pass-timestamp-writes { 920 | query-set: borrow, 921 | beginning-of-pass-write-index: option, 922 | end-of-pass-write-index: option, 923 | } 924 | record gpu-render-bundle-encoder-descriptor { 925 | depth-read-only: option, 926 | stencil-read-only: option, 927 | color-formats: list>, 928 | depth-stencil-format: option, 929 | sample-count: option, 930 | label: option, 931 | } 932 | record gpu-query-set-descriptor { 933 | %type: gpu-query-type, 934 | count: gpu-size32, 935 | label: option, 936 | } 937 | type gpu-signed-offset32 = s32; 938 | type gpu-size64-out = u64; 939 | type gpu-integer-coordinate-out = u32; 940 | type gpu-size32-out = u32; 941 | type gpu-flags-constant = u32; 942 | record gpu-color { 943 | r: f64, 944 | g: f64, 945 | b: f64, 946 | a: f64, 947 | } 948 | record gpu-render-pass-color-attachment { 949 | view: borrow, 950 | depth-slice: option, 951 | resolve-target: option>, 952 | clear-value: option, 953 | load-op: gpu-load-op, 954 | store-op: gpu-store-op, 955 | } 956 | record gpu-render-pass-descriptor { 957 | color-attachments: list>, 958 | depth-stencil-attachment: option, 959 | occlusion-query-set: option>, 960 | timestamp-writes: option, 961 | max-draw-count: option, 962 | label: option, 963 | } 964 | record gpu-origin3-d { 965 | x: option, 966 | y: option, 967 | z: option, 968 | } 969 | record gpu-texel-copy-texture-info { 970 | texture: borrow, 971 | mip-level: option, 972 | origin: option, 973 | aspect: option, 974 | } 975 | record gpu-extent3-d { 976 | width: gpu-integer-coordinate, 977 | height: option, 978 | depth-or-array-layers: option, 979 | } 980 | record gpu-texture-descriptor { 981 | size: gpu-extent3-d, 982 | mip-level-count: option, 983 | sample-count: option, 984 | dimension: option, 985 | format: gpu-texture-format, 986 | usage: gpu-texture-usage-flags, 987 | view-formats: option>, 988 | label: option, 989 | } 990 | record gpu-canvas-configuration-owned { 991 | device: gpu-device, 992 | format: gpu-texture-format, 993 | usage: option, 994 | view-formats: option>, 995 | color-space: option, 996 | tone-mapping: option, 997 | alpha-mode: option, 998 | } 999 | enum predefined-color-space { 1000 | srgb, 1001 | display-p3, 1002 | } 1003 | get-gpu: func() -> gpu; 1004 | variant gpu-error-kind { 1005 | validation-error, 1006 | out-of-memory-error, 1007 | internal-error, 1008 | } 1009 | variant request-device-error-kind { 1010 | type-error, 1011 | operation-error, 1012 | } 1013 | record request-device-error { 1014 | kind: request-device-error-kind, 1015 | message: string, 1016 | } 1017 | variant create-pipeline-error-kind { 1018 | gpu-pipeline-error(gpu-pipeline-error-reason), 1019 | } 1020 | record create-pipeline-error { 1021 | kind: create-pipeline-error-kind, 1022 | message: string, 1023 | } 1024 | variant create-query-set-error-kind { 1025 | type-error, 1026 | } 1027 | record create-query-set-error { 1028 | kind: create-query-set-error-kind, 1029 | message: string, 1030 | } 1031 | variant pop-error-scope-error-kind { 1032 | operation-error, 1033 | } 1034 | record pop-error-scope-error { 1035 | kind: pop-error-scope-error-kind, 1036 | message: string, 1037 | } 1038 | variant map-async-error-kind { 1039 | operation-error, 1040 | range-error, 1041 | abort-error, 1042 | } 1043 | record map-async-error { 1044 | kind: map-async-error-kind, 1045 | message: string, 1046 | } 1047 | variant get-mapped-range-error-kind { 1048 | operation-error, 1049 | range-error, 1050 | type-error, 1051 | } 1052 | record get-mapped-range-error { 1053 | kind: get-mapped-range-error-kind, 1054 | message: string, 1055 | } 1056 | variant unmap-error-kind { 1057 | abort-error, 1058 | } 1059 | record unmap-error { 1060 | kind: unmap-error-kind, 1061 | message: string, 1062 | } 1063 | variant set-bind-group-error-kind { 1064 | range-error, 1065 | } 1066 | record set-bind-group-error { 1067 | kind: set-bind-group-error-kind, 1068 | message: string, 1069 | } 1070 | variant write-buffer-error-kind { 1071 | operation-error, 1072 | } 1073 | record write-buffer-error { 1074 | kind: write-buffer-error-kind, 1075 | message: string, 1076 | } 1077 | } 1078 | --------------------------------------------------------------------------------