• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Tint Architecture
2
3```
4                   ┏━━━━━━━━┓                   ┏━━━━━━┓
5                   ┃ SPIR━V ┃                   ┃ WGSL ┃
6                   ┗━━━━┃━━━┛                   ┗━━━┃━━┛
7                        ▼                           ▼
8              ┏━━━━━━━━━┃━━━━━━━━━━━━━━━━━━━━━━━━━━━┃━━━━━━━━┓
9              ┃         ┃          Reader           ┃        ┃
10              ┃         ┃                           ┃        ┃
11              ┃ ┏━━━━━━━┻━━━━━━┓             ┏━━━━━━┻━━━━━━┓ ┃
12              ┃ ┃ SPIRV-Reader ┃             ┃ WGSL-Reader ┃ ┃
13              ┃ ┗━━━━━━━━━━━━━━┛             ┗━━━━━━━━━━━━━┛ ┃
14              ┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛
1516                    ┏━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┓
17                    ┃           ProgramBuilder          ┃
18                    ┃             (mutable)             ┃
19      ┏━━━━━━━━━━━━►┫   ┏━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━┓   ┃
20      ┃             ┃   ┃ AST ┃ ┃ Types ┃ ┃ Symbols ┃   ┃
21      ┃             ┃   ┗━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━┛   ┃
22      ┃             ┗━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┛
23      ┃                               ▼
24      ┃             ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
25      ▲             ┆ Build           ▼                ┆
26  ┏━━━┻━━━┓         ┆        ┏━━━━━━━━┻━━━━━━━━┓       ┆
27  ┃ Clone ┃         ┆        ┃    Resolver     ┃       ┆
28  ┗━━━┳━━━┛         ┆        ┗━━━━━━━━━━━━━━━━━┛       ┆
29      ▲             └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
30      ┃                               ▼
31      ┃       ┏━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━┓
32      ┃       ┃                    Program                   ┃
33      ┃       ┃                  (immutable)                 ┃
34      ┣━━━━━━◄┫  ┏━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━━┓ ┏━━━━━━━━━┓  ┃
35      ┃       ┃  ┃ AST ┃ ┃ Types ┃ ┃ Semantic ┃ ┃ Symbols ┃  ┃
36      ┃       ┃  ┗━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━━┛ ┗━━━━━━━━━┛  ┃
37      ┃       ┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛
38      ▲                               ▼
39┏━━━━━┻━━━━━┓                         ┃             ┏━━━━━━━━━━━┓
40┃ Transform ┃◄━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━►┃ Inspector ┃
41┗━━━━━━━━━━━┛                         ┃             ┗━━━━━━━━━━━┛
4243┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
44┃                                  Writer                                  ┃
45┃                                                                          ┃
46┃ ┏━━━━━━━━━━━━━━┓    ┏━━━━━━━━━━━━━┓    ┏━━━━━━━━━━━━━┓    ┏━━━━━━━━━━━━┓ ┃
47┃ ┃ SPIRV-Writer ┃    ┃ WGSL-Writer ┃    ┃ HLSL-Writer ┃    ┃ MSL-Writer ┃ ┃
48┃ ┗━━━━━━━┳━━━━━━┛    ┗━━━━━━┳━━━━━━┛    ┗━━━━━━┳━━━━━━┛    ┗━━━━━━┳━━━━━┛ ┃
49┗━━━━━━━━━┃━━━━━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━━━━━┃━━━━━━━┛
50          ▼                  ▼                  ▼                  ▼
51     ┏━━━━┻━━━┓          ┏━━━┻━━┓           ┏━━━┻━━┓            ┏━━┻━━┓
52     ┃ SPIR-V ┃          ┃ WGSL ┃           ┃ HLSL ┃            ┃ MSL ┃
53     ┗━━━━━━━━┛          ┗━━━━━━┛           ┗━━━━━━┛            ┗━━━━━┛
54```
55
56## Reader
57
58Readers are responsible for parsing a shader program and populating a
59`ProgramBuilder` with the parsed AST, type and symbol information.
60
61The WGSL reader is a recursive descent parser. It closely follows the WGSL
62grammar in the naming of the parse methods.
63
64## ProgramBuilder
65
66A `ProgramBuilder` is the primary interface to construct an immutable `Program`.
67There are a number of methods exposed which make creating of the `Program`
68simpler. A `ProgramBuilder` can only be used once, and must be discarded after
69the `Program` is constructed.
70
71A `Program` is built from the `ProgramBuilder` by `std::move()`ing the
72`ProgramBuilder` to a new `Program` object. When built, resolution is performed
73so the produced `Program` will contain all the needed semantic information.
74
75At any time before building the `Program`, `ProgramBuilder::IsValid()` may be
76called to ensure the AST is **structurally** correct. This checks that things
77like `if` statements have a condition and body attached.
78
79If further changes to the `Program` are needed (say via a `Transform`) then a
80new `ProgramBuilder` can be produced by cloning the `Program` into a new
81`ProgramBuilder`.
82
83Unlike `Program`s, `ProgramBuilder`s are not part of the public Tint API.
84
85## AST
86
87The Abstract Syntax Tree is a directed acyclic graph of `ast::Node`s which
88encode the syntactic structure of the WGSL program.
89
90The root of the AST is the `ast::Module` class which holds each of the declared
91functions, variables and user defined types (type aliases and structures).
92
93Each `ast::Node` represents a **single** part of the program's source, and so
94`ast::Node`s are not shared.
95
96The AST does not perform any verification of its content. For example, the
97`ast::StrideDecoration` node has numeric stride parameter, which is a count of
98the number of bytes from the start of one array element to the start of the
99next. The AST node itself does not constrain the set of stride values that you
100can set, aside from storing it as an unsigned integer.
101
102## Types
103
104Types are constructed during the Reader and resolution phases, and are
105held by the `Program` or `ProgramBuilder`. AST and semantic nodes can both
106reference types.
107
108Each `type::Type` node **uniquely** represents a particular spelling of a WGSL
109type within the program, so you can compare `type::Type*` pointers to check for
110equivalence of type expressions.
111For example, there is only one `type::Type` node for the `i32` type, no matter
112how many times it is mentioned in the source program.
113However, if `MyI32` is a type alias for `i32`, then they will have two different
114type nodes.
115
116## Semantic information
117
118Semantic information is held by `sem::Node`s which describe the program at
119a higher / more abstract level than the AST. This includes information such as
120the resolved type of each expression, the resolved overload of an intrinsic
121function call, and the module scoped variables used by each function.
122
123Semantic information is generated by the `Resolver` when the `Program`
124is built from a `ProgramBuilder`.
125
126The `sem::Info` class holds a map of `ast::Node`s to `sem::Node`s.
127This map is **many-to-one** - i.e. while a AST node might have a single
128corresponding semantic node, the reverse may not be true. For example:
129many `ast::IdentifierExpression` nodes may map to a single `sem::Variable`,
130and so the `sem::Variable` does not have a single corresponding
131`ast::Node`.
132
133Unlike `ast::Node`s, semantic nodes may not necessarily form a directed acyclic
134graph, and the semantic graph may contain diamonds.
135
136## Symbols
137
138Symbols represent a unique string identifier in the source program. These string
139identifiers are transformed into symbols within the `Reader`s.
140
141During the Writer phase, symbols may be emitted as strings using a `Namer`.
142A `Namer` may output the symbol in any form that preserves the uniqueness of
143that symbol.
144
145## Resolver
146
147The `Resolver` will automatically run when a `Program` is built.
148A `Resolver` creates the `Program`s semantic information by analyzing the
149`Program`s AST and type information.
150
151The `Resolver` will validate to make sure the generated `Program` is
152semantically valid.
153
154## Program
155
156A `Program` holds an immutable version of the information from the
157`ProgramBuilder` along with semantic information generated by the
158`Resolver`.
159
160Like `ProgramBuilder`, `Program::IsValid()` may be called to ensure the AST is
161structurally correct and semantically valid, and that the `Resolver` did not
162report any errors.
163
164Unlike the `ProgramBuilder`, a `Program` is fully immutable, and is part of the
165public Tint API. The immutable nature of `Program`s make these entirely safe
166to share between multiple threads without the use of synchronization primitives.
167
168## Inspector
169
170The inspectors job is to go through the `Program` and pull out various pieces of
171information. The information may be used to pass information into the downstream
172compilers (things like specialization constants) or may be used to pass into
173transforms to update the AST before generating the resulting code.
174
175The input `Program` to the inspector must be valid (pass validation).
176
177## Transforms
178
179There maybe various transforms we want to run over the `Program`.
180This is for things like Vertex Pulling or Robust Buffer Access.
181
182A transform operates by cloning the input `Program` into a new `ProgramBuilder`,
183applying the required changes, and then finally building and returning a new
184output `Program`. As the resolver is always run when a `Program` is built,
185Transforms will always emit a `Program` with semantic information.
186
187The input `Program` to a transform must be valid (pass validation).
188If the input `Program` of a transform is valid then the transform must guarantee
189that the output program is also valid.
190
191## Writers
192
193A writer is responsible for writing the `Program` in the target shader language.
194
195The input `Program` to a writer must be valid (pass validation).
196