Update docs/arch.md with new design
Change-Id: I8deb4416ac2f1e14f8b863b80a20c23550ed05e6 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40383 Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
767df5f03b
commit
00eb8dfa8b
241
docs/arch.md
241
docs/arch.md
|
@ -1,107 +1,206 @@
|
||||||
# Tint Architecture
|
# Tint Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
+--------+ +------+
|
┏━━━━━━━━┓ ┏━━━━━━┓
|
||||||
| SPIR-V | | WGSL |
|
┃ SPIR━V ┃ ┃ WGSL ┃
|
||||||
+----|---+ +---|--+
|
┗━━━━┃━━━┛ ┗━━━┃━━┛
|
||||||
| |
|
▼ ▼
|
||||||
+---------|---------------------------|--------+
|
┏━━━━━━━━━┃━━━━━━━━━━━━━━━━━━━━━━━━━━━┃━━━━━━━━┓
|
||||||
| | Reader | |
|
┃ ┃ Reader ┃ ┃
|
||||||
| | | |
|
┃ ┃ ┃ ┃
|
||||||
| +-------|------+ +------|------+ |
|
┃ ┏━━━━━━━┻━━━━━━┓ ┏━━━━━━┻━━━━━━┓ ┃
|
||||||
| | SPIRV-Reader | | WGSL-Reader | |
|
┃ ┃ SPIRV-Reader ┃ ┃ WGSL-Reader ┃ ┃
|
||||||
| +--------------+ +-------------+ |
|
┃ ┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━┛ ┃
|
||||||
+-----------------------|----------------------+
|
┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛
|
||||||
|
|
▼
|
||||||
+--|--+ +---------+
|
┏━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┓
|
||||||
| AST |------| IsValid |
|
┃ ProgramBuilder ┃
|
||||||
+--|--+ +---------+
|
┃ (mutable) ┃
|
||||||
|
|
┏━━━━━━━━━━━━►┫ ┏━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━┓ ┃
|
||||||
+--------|--------+
|
┃ ┃ ┃ AST ┃ ┃ Types ┃ ┃ Symbols ┃ ┃
|
||||||
| Type Determiner |
|
┃ ┃ ┗━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━┛ ┃
|
||||||
+--------|--------+
|
┃ ┗━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┛
|
||||||
|
|
┃ ▼
|
||||||
+-----|-----+
|
┃ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
|
||||||
| Validator |
|
▲ ┆ Build ▼ ┆
|
||||||
+-----|-----+
|
┏━━━┻━━━┓ ┆ ┏━━━━━━━━┻━━━━━━━━┓ ┆
|
||||||
|
|
┃ Clone ┃ ┆ ┃ Type Determiner ┃ ┆
|
||||||
+-----|-----+
|
┗━━━┳━━━┛ ┆ ┗━━━━━━━━━━━━━━━━━┛ ┆
|
||||||
| Inspector |
|
▲ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
|
||||||
+-----|-----+
|
┃ ▼
|
||||||
|
|
┃ ┏━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━┓
|
||||||
+------|-----+
|
┃ ┃ Program ┃
|
||||||
| Transforms |
|
┃ ┃ (immutable) ┃
|
||||||
+------|-----+
|
┣━━━━━━◄┫ ┏━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━━┓ ┏━━━━━━━━━┓ ┃
|
||||||
|
|
┃ ┃ ┃ AST ┃ ┃ Types ┃ ┃ Semantic ┃ ┃ Symbols ┃ ┃
|
||||||
+-------------------------------------|------------------------------------+
|
┃ ┃ ┗━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━━┛ ┗━━━━━━━━━┛ ┃
|
||||||
| Writer |
|
┃ ┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛
|
||||||
| |
|
▲ ▼
|
||||||
| +--------------+ +-------------+ +-------------+ +------------+ |
|
┏━━━━━┻━━━━━┓ ┏━━━━━┻━━━━━┓ ┏━━━━━━━━━━━┓
|
||||||
| | SPIRV-Writer | | WGSL-Writer | | HLSL-Writer | | MSL-Writer | |
|
┃ Transform ┃◄━━━━━━━━━━━━━━━━━◄┃ Validator ┣━━━━━━►┃ Inspector ┃
|
||||||
| +-------|------+ +------|------+ +------|------+ +------|-----+ |
|
┗━━━━━━━━━━━┛ ┗━━━━━┳━━━━━┛ ┗━━━━━━━━━━━┛
|
||||||
+---------|------------------|------------------|------------------|-------+
|
▼
|
||||||
| | | |
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||||
+----|---+ +---|--+ +---|--+ +--|--+
|
┃ Writer ┃
|
||||||
| SPIR-V | | WGSL | | HLSL | | MSL |
|
┃ ┃
|
||||||
+--------+ +------+ +------+ +-----+
|
┃ ┏━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓ ┃
|
||||||
|
┃ ┃ SPIRV-Writer ┃ ┃ WGSL-Writer ┃ ┃ HLSL-Writer ┃ ┃ MSL-Writer ┃ ┃
|
||||||
|
┃ ┗━━━━━━━┳━━━━━━┛ ┗━━━━━━┳━━━━━━┛ ┗━━━━━━┳━━━━━━┛ ┗━━━━━━┳━━━━━┛ ┃
|
||||||
|
┗━━━━━━━━━┃━━━━━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━━━━━┃━━━━━━━┛
|
||||||
|
▼ ▼ ▼ ▼
|
||||||
|
┏━━━━┻━━━┓ ┏━━━┻━━┓ ┏━━━┻━━┓ ┏━━┻━━┓
|
||||||
|
┃ SPIR-V ┃ ┃ WGSL ┃ ┃ HLSL ┃ ┃ MSL ┃
|
||||||
|
┗━━━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━┛ ┗━━━━━┛
|
||||||
```
|
```
|
||||||
|
|
||||||
## WGSL Reader
|
## Reader
|
||||||
|
|
||||||
|
Readers are responsible for parsing a shader program and populating a
|
||||||
|
`ProgramBuilder` with the parsed AST, type and symbol information.
|
||||||
|
|
||||||
The WGSL reader is a recursive descent parser. It closely follows the WGSL
|
The WGSL reader is a recursive descent parser. It closely follows the WGSL
|
||||||
grammar in the naming of the parse methods.
|
grammar in the naming of the parse methods.
|
||||||
|
|
||||||
|
## ProgramBuilder
|
||||||
|
|
||||||
|
A `ProgramBuilder` is the primary interface to construct an immutable `Program`.
|
||||||
|
There are a number of methods exposed which make creating of the `Program`
|
||||||
|
simpler. A `ProgramBuilder` can only be used once, and must be discarded after
|
||||||
|
the `Program` is constructed.
|
||||||
|
|
||||||
|
A `Program` is built from the `ProgramBuilder` by `std::move()`ing the
|
||||||
|
`ProgramBuilder` to a new `Program` object. When built, type determination is
|
||||||
|
run so the produced `Program` will contain all the needed semantic information.
|
||||||
|
|
||||||
|
At any time before building the `Program`, `ProgramBuilder::IsValid()` may be
|
||||||
|
called to ensure the AST is **structurally** correct. This checks that things
|
||||||
|
like `if` statements have a condition and body attached.
|
||||||
|
|
||||||
|
If further changes to the `Program` are needed (say via a `Transform`) then a
|
||||||
|
new `ProgramBuilder` can be produced by cloning the `Program` into a new
|
||||||
|
`ProgramBuilder`.
|
||||||
|
|
||||||
|
Unlike `Program`s, `ProgramBuilder`s are not part of the public Tint API.
|
||||||
|
|
||||||
## AST
|
## AST
|
||||||
|
|
||||||
The Abstract Syntax Tree is a directed acyclic graph of nodes encoding
|
The Abstract Syntax Tree is a directed acyclic graph of `ast::Node`s which
|
||||||
the structure of the WGSL program.
|
encode the syntactic structure of the WGSL program.
|
||||||
|
|
||||||
Many AST nodes have numeric parameters. For example, the ast::StrideDecoration
|
The root of the AST is the `ast::Module` class which holds each of the declared
|
||||||
node has numeric stride parameter, which is a count of the number of bytes from
|
functions, variables and user defined types (type aliases and structures).
|
||||||
the start of one array element to the start of the next. The AST node itself
|
|
||||||
does not constrain the set of stride values that you can set, aside from storing
|
|
||||||
it as an unsigned integer.
|
|
||||||
|
|
||||||
After creating the AST for the whole WGSL program, Tint will run an `IsValid`
|
Each `ast::Node` represents a **single** part of the program's source, and so
|
||||||
method which verifies that the produced AST is structurally correct. This
|
`ast::Node`s are not shared.
|
||||||
means that things like `if` statements have a condition and body attached.
|
|
||||||
|
|
||||||
A later phase of processing, Validation, will check properties such as whether
|
The AST does not perform any verification of its content. For example, the
|
||||||
array strides satisfy all the requirements in the WGSL specification.
|
`ast::StrideDecoration` node has numeric stride parameter, which is a count of
|
||||||
|
the number of bytes from the start of one array element to the start of the
|
||||||
|
next. The AST node itself does not constrain the set of stride values that you
|
||||||
|
can set, aside from storing it as an unsigned integer.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
Types are constructed during the Reader and Type Determination phases, and are
|
||||||
|
held by the `Program` or `ProgramBuilder`. AST and semantic nodes can both
|
||||||
|
reference types.
|
||||||
|
|
||||||
|
Each `type::Type` node **uniquely** represents a particular spelling of a WGSL
|
||||||
|
type within the program, so you can compare `type::Type*` pointers to check for
|
||||||
|
equivalence of type expressions.
|
||||||
|
For example, there is only one `type::Type` node for the `i32` type, no matter
|
||||||
|
how many times it is mentioned in the source program.
|
||||||
|
However, if `MyI32` is a type alias for `i32`, then they will have two different
|
||||||
|
type nodes.
|
||||||
|
|
||||||
|
## Semantic information
|
||||||
|
|
||||||
|
Semantic information is held by `semantic::Node`s which describe the program at
|
||||||
|
a higher / more abstract level than the AST. This includes information such as
|
||||||
|
the resolved type of each expression, the resolved overload of an intrinsic
|
||||||
|
function call, and the module scoped variables used by each function.
|
||||||
|
|
||||||
|
Semantic information is generated by the `TypeDeterminer` when the `Program`
|
||||||
|
is built from a `ProgramBuilder`.
|
||||||
|
|
||||||
|
The `semantic::Info` class holds a map of `ast::Node`s to `semantic::Node`s.
|
||||||
|
This map is **many-to-one** - i.e. while a AST node might have a single
|
||||||
|
corresponding semantic node, the reverse may not be true. For example:
|
||||||
|
many `ast::IdentifierExpression` nodes may map to a single `semantic::Variable`,
|
||||||
|
and so the `semantic::Variable` does not have a single corresponding
|
||||||
|
`ast::Node`.
|
||||||
|
|
||||||
|
Unlike `ast::Node`s, semantic nodes may not necessarily form a directed acyclic
|
||||||
|
graph, and the semantic graph may contain diamonds.
|
||||||
|
|
||||||
|
## Symbols
|
||||||
|
|
||||||
|
Symbols represent a unique string identifier in the source program. These string
|
||||||
|
identifiers are transformed into symbols within the `Reader`s.
|
||||||
|
|
||||||
|
During the Writer phase, symbols may be emitted as strings using a `Namer`.
|
||||||
|
A `Namer` may output the symbol in any form that preserves the uniqueness of
|
||||||
|
that symbol.
|
||||||
|
|
||||||
## Type Determiner
|
## Type Determiner
|
||||||
|
|
||||||
The type determination stage assigns a result type to each node in the AST. It
|
The `TypeDeterminer` will automatically run when a `Program` is built.
|
||||||
will do the minimal amount of validation required in order to always be
|
A `TypeDeterminer` creates the `Program`s semantic information by analyzing the
|
||||||
accessing valid nodes, but that doesn't mean the overall AST is valid. (e.g. a
|
`Program`s AST and type information.
|
||||||
4 component vector type constructor with 5 components will pass type
|
|
||||||
determination but is invalid.)
|
|
||||||
|
|
||||||
|
The `TypeDeterminer` will do the minimal amount of validation required in order
|
||||||
|
to always be accessing valid nodes, reporting any errors found in the
|
||||||
|
`Program`'s diagnostics. Even if the `TypeDeterminer` doesn't generate any
|
||||||
|
errors doesn't mean the generated `Program` is semantically valid. Use the
|
||||||
|
`Validator` to check for a `Program`'s final validity.
|
||||||
|
|
||||||
|
## Program
|
||||||
|
|
||||||
|
A `Program` holds an immutable version of the information from the
|
||||||
|
`ProgramBuilder` along with semantic information generated by the
|
||||||
|
`TypeDeterminer`.
|
||||||
|
|
||||||
|
Like `ProgramBuilder`, `Program::IsValid()` may be called to ensure the AST is
|
||||||
|
structurally correct and that the `TypeDeterminer` did not report any errors.
|
||||||
|
`Program::IsValid()` does not perform semantic validation, use the `Validator`
|
||||||
|
to check for a `Program`'s final validity.
|
||||||
|
|
||||||
|
Unlike the `ProgramBuilder`, a `Program` is fully immutable, and is part of the
|
||||||
|
public Tint API. The immutable nature of `Program`s make these entirely safe
|
||||||
|
to share between multiple threads without the use of synchronization primitives.
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
|
|
||||||
After the validation step the AST should be a known valid WGSL program.
|
The `Validator` checks a `Program` for static validity as specified by the WGSL
|
||||||
|
language, and reports any validation errors found. Attempting to pass a
|
||||||
|
`Program` that does not pass validation on to later stages will result in
|
||||||
|
undefined behavior.
|
||||||
|
|
||||||
## Inspector
|
## Inspector
|
||||||
|
|
||||||
The inspectors job is to go through the AST and pull out various pieces of
|
The inspectors job is to go through the `Program` and pull out various pieces of
|
||||||
information. The information may be used to pass information into the downstream
|
information. The information may be used to pass information into the downstream
|
||||||
compilers (things like specialization constants) or may be used to pass into
|
compilers (things like specialization constants) or may be used to pass into
|
||||||
transforms to update the AST before generating the resulting code.
|
transforms to update the AST before generating the resulting code.
|
||||||
|
|
||||||
|
The input `Program` to the inspector must be valid (pass validation).
|
||||||
|
|
||||||
## Transforms
|
## Transforms
|
||||||
|
|
||||||
There maybe various transforms we want to run over the AST. This is for things
|
There maybe various transforms we want to run over the `Program`.
|
||||||
like Vertex Pulling or Robust Buffer Access. These transforms will modify the
|
This is for things like Vertex Pulling or Robust Buffer Access.
|
||||||
AST and must produce valid AST after their execution.
|
|
||||||
|
|
||||||
Currently the transforms are run individually but we should consider adding
|
A transform operates by cloning the input `Program` into a new `ProgramBuilder`,
|
||||||
a transform manager to maintain and execute the list of transforms.
|
applying the required changes, and then finally building and returning a new
|
||||||
|
output `Program`. As type determination is always run when a `Program` is built,
|
||||||
|
Transforms will always emit a `Program` with semantic information.
|
||||||
|
|
||||||
|
The input `Program` to a transform must be valid (pass validation).
|
||||||
|
If the input `Program` of a transform is valid then the transform must guarantee
|
||||||
|
that the output program is also valid.
|
||||||
|
|
||||||
## Writers
|
## Writers
|
||||||
|
|
||||||
The writers should be thread safe, we maybe generating the HLSL and MLS output
|
A writer is responsible for writing the `Program` in the target shader language.
|
||||||
at the same time on different threads. (The writer portion is the only one
|
|
||||||
that needs to be thread safe.)
|
The input `Program` to a writer must be valid (pass validation).
|
||||||
|
|
Loading…
Reference in New Issue