dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 1 | # Tint Architecture |
| 2 | |
| 3 | ``` |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 4 | ┏━━━━━━━━┓ ┏━━━━━━┓ |
| 5 | ┃ SPIR━V ┃ ┃ WGSL ┃ |
| 6 | ┗━━━━┃━━━┛ ┗━━━┃━━┛ |
| 7 | ▼ ▼ |
| 8 | ┏━━━━━━━━━┃━━━━━━━━━━━━━━━━━━━━━━━━━━━┃━━━━━━━━┓ |
| 9 | ┃ ┃ Reader ┃ ┃ |
| 10 | ┃ ┃ ┃ ┃ |
| 11 | ┃ ┏━━━━━━━┻━━━━━━┓ ┏━━━━━━┻━━━━━━┓ ┃ |
| 12 | ┃ ┃ SPIRV-Reader ┃ ┃ WGSL-Reader ┃ ┃ |
| 13 | ┃ ┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━┛ ┃ |
| 14 | ┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛ |
| 15 | ▼ |
| 16 | ┏━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┓ |
| 17 | ┃ ProgramBuilder ┃ |
| 18 | ┃ (mutable) ┃ |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 19 | ┏━━━━━━━━━━━━►┫ ┏━━━━━┓ ┏━━━━━━━━━┓ ┃ |
| 20 | ┃ ┃ ┃ AST ┃ ┃ Symbols ┃ ┃ |
| 21 | ┃ ┃ ┗━━━━━┛ ┗━━━━━━━━━┛ ┃ |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 22 | ┃ ┗━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┛ |
| 23 | ┃ ▼ |
| 24 | ┃ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 25 | ▲ ┆ Resolve ▼ ┆ |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 26 | ┏━━━┻━━━┓ ┆ ┏━━━━━━━━┻━━━━━━━━┓ ┆ |
Ben Clayton | 5f0ea11 | 2021-03-09 10:54:37 +0000 | [diff] [blame] | 27 | ┃ Clone ┃ ┆ ┃ Resolver ┃ ┆ |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 28 | ┗━━━┳━━━┛ ┆ ┗━━━━━━━━━━━━━━━━━┛ ┆ |
| 29 | ▲ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ |
| 30 | ┃ ▼ |
| 31 | ┃ ┏━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━┓ |
| 32 | ┃ ┃ Program ┃ |
| 33 | ┃ ┃ (immutable) ┃ |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 34 | ┣━━━━━━◄┫ ┏━━━━━┓ ┏━━━━━━━━━━┓ ┏━━━━━━━━━┓ ┃ |
| 35 | ┃ ┃ ┃ AST ┃ ┃ Semantic ┃ ┃ Symbols ┃ ┃ |
| 36 | ┃ ┃ ┗━━━━━┛ ┗━━━━━━━━━━┛ ┗━━━━━━━━━┛ ┃ |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 37 | ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛ |
| 38 | ▲ ▼ |
Antonio Maiorano | d15391e | 2021-04-08 14:08:47 +0000 | [diff] [blame] | 39 | ┏━━━━━┻━━━━━┓ ┃ ┏━━━━━━━━━━━┓ |
| 40 | ┃ Transform ┃◄━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━►┃ Inspector ┃ |
| 41 | ┗━━━━━━━━━━━┛ ┃ ┗━━━━━━━━━━━┛ |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 42 | ▼ |
Ben Clayton | 5f60eb7 | 2022-02-15 14:02:47 +0000 | [diff] [blame] | 43 | ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ |
| 44 | ┃ Writers ┃ |
| 45 | ┃ ┃ |
| 46 | ┃ ┏━━━━━━━━━━━━━━┓┏━━━━━━━━━━━━━┓┏━━━━━━━━━━━━━┓┏━━━━━━━━━━━━━┓┏━━━━━━━━━━━━┓ ┃ |
| 47 | ┃ ┃ SPIRV-Writer ┃┃ WGSL-Writer ┃┃ HLSL-Writer ┃┃ GLSL-Writer ┃┃ MSL-Writer ┃ ┃ |
| 48 | ┃ ┗━━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━┛ ┃ |
| 49 | ┗━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━┛ |
| 50 | ▼ ▼ ▼ ▼ ▼ |
| 51 | ┏━━━━┻━━━┓ ┏━━━┻━━┓ ┏━━━┻━━┓ ┏━━━┻━━┓ ┏━━┻━━┓ |
| 52 | ┃ SPIR-V ┃ ┃ WGSL ┃ ┃ HLSL ┃ ┃ GLSL ┃ ┃ MSL ┃ |
| 53 | ┗━━━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━┛ ┗━━━━━┛ |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 54 | ``` |
| 55 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 56 | ## Reader |
| 57 | |
| 58 | Readers are responsible for parsing a shader program and populating a |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 59 | `ProgramBuilder` with the parsed AST and symbol information. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 60 | |
| 61 | The WGSL reader is a recursive descent parser. It closely follows the WGSL |
| 62 | grammar in the naming of the parse methods. |
| 63 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 64 | ## ProgramBuilder |
| 65 | |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 66 | A `ProgramBuilder` is the interface to construct an immutable `Program`. |
| 67 | There are a large number of helper methods for simplifying the creation of the |
| 68 | AST nodes. A `ProgramBuilder` can only be used once, and must be discarded after |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 69 | the `Program` is constructed. |
| 70 | |
Ben Clayton | 915ceca | 2023-07-29 13:12:58 +0000 | [diff] [blame] | 71 | A `Program` is built from the `ProgramBuilder` via a call to |
| 72 | `resolver::Resolve()`, which will perform validation and semantic analysis. |
| 73 | The returned program will contain the semantic information which can be obtained |
| 74 | by calling `Program::Sem()`. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 75 | |
| 76 | At any time before building the `Program`, `ProgramBuilder::IsValid()` may be |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 77 | called to ensure that no error diagnostics have been raised during the |
| 78 | construction of the AST. This includes parser syntax errors, but not semantic |
| 79 | validation which happens during the `Resolve` phase. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 80 | |
| 81 | If further changes to the `Program` are needed (say via a `Transform`) then a |
| 82 | new `ProgramBuilder` can be produced by cloning the `Program` into a new |
| 83 | `ProgramBuilder`. |
| 84 | |
| 85 | Unlike `Program`s, `ProgramBuilder`s are not part of the public Tint API. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 86 | |
| 87 | ## AST |
| 88 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 89 | The Abstract Syntax Tree is a directed acyclic graph of `ast::Node`s which |
| 90 | encode the syntactic structure of the WGSL program. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 91 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 92 | The root of the AST is the `ast::Module` class which holds each of the declared |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 93 | functions, variables and user declared types (type aliases and structures). |
David Neto | 6d6aed5 | 2020-10-08 21:18:45 +0000 | [diff] [blame] | 94 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 95 | Each `ast::Node` represents a **single** part of the program's source, and so |
| 96 | `ast::Node`s are not shared. |
David Neto | 6d6aed5 | 2020-10-08 21:18:45 +0000 | [diff] [blame] | 97 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 98 | The AST does not perform any verification of its content. For example, the |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 99 | `ast::Array` node has numeric size parameter, which is not validated to be |
| 100 | within the WGSL specification limits until validation of the `Resolver`. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 101 | |
| 102 | ## Semantic information |
| 103 | |
Antonio Maiorano | 5cd71b8 | 2021-04-16 19:07:51 +0000 | [diff] [blame] | 104 | Semantic information is held by `sem::Node`s which describe the program at |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 105 | a higher / more abstract level than the AST. This includes information such as |
Ben Clayton | b85e692 | 2022-02-02 23:07:11 +0000 | [diff] [blame] | 106 | the resolved type of each expression, the resolved overload of a builtin |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 107 | function call, and the module scoped variables used by each function. |
| 108 | |
Ben Clayton | 5f0ea11 | 2021-03-09 10:54:37 +0000 | [diff] [blame] | 109 | Semantic information is generated by the `Resolver` when the `Program` |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 110 | is built from a `ProgramBuilder`. |
| 111 | |
Antonio Maiorano | 5cd71b8 | 2021-04-16 19:07:51 +0000 | [diff] [blame] | 112 | The `sem::Info` class holds a map of `ast::Node`s to `sem::Node`s. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 113 | This map is **many-to-one** - i.e. while a AST node might have a single |
| 114 | corresponding semantic node, the reverse may not be true. For example: |
Antonio Maiorano | 5cd71b8 | 2021-04-16 19:07:51 +0000 | [diff] [blame] | 115 | many `ast::IdentifierExpression` nodes may map to a single `sem::Variable`, |
| 116 | and so the `sem::Variable` does not have a single corresponding |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 117 | `ast::Node`. |
| 118 | |
| 119 | Unlike `ast::Node`s, semantic nodes may not necessarily form a directed acyclic |
| 120 | graph, and the semantic graph may contain diamonds. |
| 121 | |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 122 | ## Types |
| 123 | |
| 124 | AST types are regular AST nodes, in that they uniquely represent a single part |
| 125 | of the parsed source code. Unlike semantic types, identical AST types are not |
| 126 | de-duplicated as they refer to the source usage of the type. |
| 127 | |
| 128 | Semantic types are constructed during the `Resolver` phase, and are held by |
| 129 | the `Program` or `ProgramBuilder`. |
| 130 | |
| 131 | Each `sem::Type` node **uniquely** represents a particular WGSL type within the |
| 132 | program, so you can compare `type::Type*` pointers to check for type |
| 133 | equivalence. For example, a `Program` will only hold one instance of the |
| 134 | `sem::I32` semantic type, no matter how many times an `i32` is mentioned in the |
| 135 | source program. |
| 136 | |
| 137 | WGSL type aliases resolve to their target semantic type. For example, given: |
| 138 | |
| 139 | ```wgsl |
| 140 | type MyI32 = i32; |
| 141 | const a : i32 = 1; |
| 142 | const b : MyI32 = 2; |
| 143 | ``` |
| 144 | |
| 145 | The **semantic** types for the variables `a` and `b` will both be the same |
| 146 | `sem::I32` node pointer. |
| 147 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 148 | ## Symbols |
| 149 | |
| 150 | Symbols represent a unique string identifier in the source program. These string |
| 151 | identifiers are transformed into symbols within the `Reader`s. |
| 152 | |
| 153 | During the Writer phase, symbols may be emitted as strings using a `Namer`. |
| 154 | A `Namer` may output the symbol in any form that preserves the uniqueness of |
| 155 | that symbol. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 156 | |
Ben Clayton | 5f0ea11 | 2021-03-09 10:54:37 +0000 | [diff] [blame] | 157 | ## Resolver |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 158 | |
Ben Clayton | 5f0ea11 | 2021-03-09 10:54:37 +0000 | [diff] [blame] | 159 | The `Resolver` will automatically run when a `Program` is built. |
| 160 | A `Resolver` creates the `Program`s semantic information by analyzing the |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 161 | `Program`s AST and type information. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 162 | |
Antonio Maiorano | d15391e | 2021-04-08 14:08:47 +0000 | [diff] [blame] | 163 | The `Resolver` will validate to make sure the generated `Program` is |
| 164 | semantically valid. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 165 | |
| 166 | ## Program |
| 167 | |
| 168 | A `Program` holds an immutable version of the information from the |
| 169 | `ProgramBuilder` along with semantic information generated by the |
Ben Clayton | 5f0ea11 | 2021-03-09 10:54:37 +0000 | [diff] [blame] | 170 | `Resolver`. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 171 | |
Ben Clayton | 8b0ceea | 2022-07-15 17:16:49 +0000 | [diff] [blame] | 172 | `Program::IsValid()` may be called to ensure the program is structurally correct |
| 173 | **and** semantically valid, and that the `Resolver` did not report any errors |
| 174 | during validation. |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 175 | |
| 176 | Unlike the `ProgramBuilder`, a `Program` is fully immutable, and is part of the |
| 177 | public Tint API. The immutable nature of `Program`s make these entirely safe |
| 178 | to share between multiple threads without the use of synchronization primitives. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 179 | |
dan sinclair | 66377ce | 2020-10-08 14:24:55 +0000 | [diff] [blame] | 180 | ## Inspector |
| 181 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 182 | The inspectors job is to go through the `Program` and pull out various pieces of |
dan sinclair | 66377ce | 2020-10-08 14:24:55 +0000 | [diff] [blame] | 183 | information. The information may be used to pass information into the downstream |
| 184 | compilers (things like specialization constants) or may be used to pass into |
| 185 | transforms to update the AST before generating the resulting code. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 186 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 187 | The input `Program` to the inspector must be valid (pass validation). |
| 188 | |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 189 | ## Transforms |
| 190 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 191 | There maybe various transforms we want to run over the `Program`. |
| 192 | This is for things like Vertex Pulling or Robust Buffer Access. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 193 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 194 | A transform operates by cloning the input `Program` into a new `ProgramBuilder`, |
| 195 | applying the required changes, and then finally building and returning a new |
Ben Clayton | 5f0ea11 | 2021-03-09 10:54:37 +0000 | [diff] [blame] | 196 | output `Program`. As the resolver is always run when a `Program` is built, |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 197 | Transforms will always emit a `Program` with semantic information. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 198 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 199 | The input `Program` to a transform must be valid (pass validation). |
| 200 | If the input `Program` of a transform is valid then the transform must guarantee |
| 201 | that the output program is also valid. |
dan sinclair | b684178 | 2020-09-21 16:00:11 +0000 | [diff] [blame] | 202 | |
| 203 | ## Writers |
| 204 | |
Ben Clayton | 00eb8df | 2021-02-23 16:08:09 +0000 | [diff] [blame] | 205 | A writer is responsible for writing the `Program` in the target shader language. |
| 206 | |
| 207 | The input `Program` to a writer must be valid (pass validation). |