mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-09 05:27:49 +00:00
tint->dawn: Shuffle source tree in preperation of merging repos
docs/ -> docs/tint/ fuzzers/ -> src/tint/fuzzers/ samples/ -> src/tint/cmd/ src/ -> src/tint/ test/ -> test/tint/ BUG=tint:1418,tint:1433 Change-Id: Id2aa79f989aef3245b80ef4aa37a27ff16cd700b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/80482 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
committed by
Tint LUCI CQ
parent
38f1e9c75c
commit
dbc13af287
195
docs/tint/arch.md
Normal file
195
docs/tint/arch.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# Tint Architecture
|
||||
|
||||
```
|
||||
┏━━━━━━━━┓ ┏━━━━━━┓
|
||||
┃ SPIR━V ┃ ┃ WGSL ┃
|
||||
┗━━━━┃━━━┛ ┗━━━┃━━┛
|
||||
▼ ▼
|
||||
┏━━━━━━━━━┃━━━━━━━━━━━━━━━━━━━━━━━━━━━┃━━━━━━━━┓
|
||||
┃ ┃ Reader ┃ ┃
|
||||
┃ ┃ ┃ ┃
|
||||
┃ ┏━━━━━━━┻━━━━━━┓ ┏━━━━━━┻━━━━━━┓ ┃
|
||||
┃ ┃ SPIRV-Reader ┃ ┃ WGSL-Reader ┃ ┃
|
||||
┃ ┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━┛ ┃
|
||||
┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
▼
|
||||
┏━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┓
|
||||
┃ ProgramBuilder ┃
|
||||
┃ (mutable) ┃
|
||||
┏━━━━━━━━━━━━►┫ ┏━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━┓ ┃
|
||||
┃ ┃ ┃ AST ┃ ┃ Types ┃ ┃ Symbols ┃ ┃
|
||||
┃ ┃ ┗━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━┛ ┃
|
||||
┃ ┗━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┛
|
||||
┃ ▼
|
||||
┃ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
|
||||
▲ ┆ Build ▼ ┆
|
||||
┏━━━┻━━━┓ ┆ ┏━━━━━━━━┻━━━━━━━━┓ ┆
|
||||
┃ Clone ┃ ┆ ┃ Resolver ┃ ┆
|
||||
┗━━━┳━━━┛ ┆ ┗━━━━━━━━━━━━━━━━━┛ ┆
|
||||
▲ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘
|
||||
┃ ▼
|
||||
┃ ┏━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ ┃ Program ┃
|
||||
┃ ┃ (immutable) ┃
|
||||
┣━━━━━━◄┫ ┏━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━━┓ ┏━━━━━━━━━┓ ┃
|
||||
┃ ┃ ┃ AST ┃ ┃ Types ┃ ┃ Semantic ┃ ┃ Symbols ┃ ┃
|
||||
┃ ┃ ┗━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━━┛ ┗━━━━━━━━━┛ ┃
|
||||
┃ ┗━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
▲ ▼
|
||||
┏━━━━━┻━━━━━┓ ┃ ┏━━━━━━━━━━━┓
|
||||
┃ Transform ┃◄━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━►┃ Inspector ┃
|
||||
┗━━━━━━━━━━━┛ ┃ ┗━━━━━━━━━━━┛
|
||||
▼
|
||||
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Writers ┃
|
||||
┃ ┃
|
||||
┃ ┏━━━━━━━━━━━━━━┓┏━━━━━━━━━━━━━┓┏━━━━━━━━━━━━━┓┏━━━━━━━━━━━━━┓┏━━━━━━━━━━━━┓ ┃
|
||||
┃ ┃ SPIRV-Writer ┃┃ WGSL-Writer ┃┃ HLSL-Writer ┃┃ GLSL-Writer ┃┃ MSL-Writer ┃ ┃
|
||||
┃ ┗━━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━━┛┗━━━━━━┳━━━━━┛ ┃
|
||||
┗━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━┛
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
┏━━━━┻━━━┓ ┏━━━┻━━┓ ┏━━━┻━━┓ ┏━━━┻━━┓ ┏━━┻━━┓
|
||||
┃ SPIR-V ┃ ┃ WGSL ┃ ┃ HLSL ┃ ┃ GLSL ┃ ┃ MSL ┃
|
||||
┗━━━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━┛ ┗━━━━━┛
|
||||
```
|
||||
|
||||
## 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
|
||||
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, resolution is performed
|
||||
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
|
||||
|
||||
The Abstract Syntax Tree is a directed acyclic graph of `ast::Node`s which
|
||||
encode the syntactic structure of the WGSL program.
|
||||
|
||||
The root of the AST is the `ast::Module` class which holds each of the declared
|
||||
functions, variables and user defined types (type aliases and structures).
|
||||
|
||||
Each `ast::Node` represents a **single** part of the program's source, and so
|
||||
`ast::Node`s are not shared.
|
||||
|
||||
The AST does not perform any verification of its content. For example, the
|
||||
`ast::StrideAttribute` 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 resolution 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 `sem::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 a builtin
|
||||
function call, and the module scoped variables used by each function.
|
||||
|
||||
Semantic information is generated by the `Resolver` when the `Program`
|
||||
is built from a `ProgramBuilder`.
|
||||
|
||||
The `sem::Info` class holds a map of `ast::Node`s to `sem::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 `sem::Variable`,
|
||||
and so the `sem::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.
|
||||
|
||||
## Resolver
|
||||
|
||||
The `Resolver` will automatically run when a `Program` is built.
|
||||
A `Resolver` creates the `Program`s semantic information by analyzing the
|
||||
`Program`s AST and type information.
|
||||
|
||||
The `Resolver` will validate to make sure the generated `Program` is
|
||||
semantically valid.
|
||||
|
||||
## Program
|
||||
|
||||
A `Program` holds an immutable version of the information from the
|
||||
`ProgramBuilder` along with semantic information generated by the
|
||||
`Resolver`.
|
||||
|
||||
Like `ProgramBuilder`, `Program::IsValid()` may be called to ensure the AST is
|
||||
structurally correct and semantically valid, and that the `Resolver` did not
|
||||
report any errors.
|
||||
|
||||
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.
|
||||
|
||||
## Inspector
|
||||
|
||||
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
|
||||
compilers (things like specialization constants) or may be used to pass into
|
||||
transforms to update the AST before generating the resulting code.
|
||||
|
||||
The input `Program` to the inspector must be valid (pass validation).
|
||||
|
||||
## Transforms
|
||||
|
||||
There maybe various transforms we want to run over the `Program`.
|
||||
This is for things like Vertex Pulling or Robust Buffer Access.
|
||||
|
||||
A transform operates by cloning the input `Program` into a new `ProgramBuilder`,
|
||||
applying the required changes, and then finally building and returning a new
|
||||
output `Program`. As the resolver 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
|
||||
|
||||
A writer is responsible for writing the `Program` in the target shader language.
|
||||
|
||||
The input `Program` to a writer must be valid (pass validation).
|
||||
119
docs/tint/compound_statements.md
Normal file
119
docs/tint/compound_statements.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Compound Statements
|
||||
|
||||
Compound statements are statements that can hold other statements.
|
||||
|
||||
This document maps the WGSL compound statements to their semantic tree representations.
|
||||
|
||||
## if statement
|
||||
|
||||
WGSL:
|
||||
```
|
||||
if (condition_a) {
|
||||
statement_a;
|
||||
} else if (condition_b) {
|
||||
statement_b;
|
||||
} else {
|
||||
statement_c;
|
||||
}
|
||||
```
|
||||
|
||||
Semantic tree:
|
||||
```
|
||||
sem::IfStatement {
|
||||
condition_a
|
||||
sem::BlockStatement {
|
||||
statement_a
|
||||
}
|
||||
sem::ElseStatement {
|
||||
condition_b
|
||||
sem::BlockStatement {
|
||||
statement_b
|
||||
}
|
||||
}
|
||||
sem::ElseStatement {
|
||||
sem::BlockStatement {
|
||||
statement_c
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## for loop
|
||||
|
||||
WGSL:
|
||||
```
|
||||
for (initializer; condition; continuing) {
|
||||
statement;
|
||||
}
|
||||
```
|
||||
|
||||
Semantic tree:
|
||||
```
|
||||
sem::ForLoopStatement {
|
||||
sem::Statement initializer
|
||||
sem::Expression condition
|
||||
sem::Statement continuing
|
||||
|
||||
sem::LoopBlockStatement {
|
||||
sem::Statement statement
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## loop
|
||||
|
||||
WGSL:
|
||||
```
|
||||
loop (condition) {
|
||||
statement_a;
|
||||
continuing {
|
||||
statement_b;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Semantic tree:
|
||||
```
|
||||
sem::LoopStatement {
|
||||
sem::Expression condition
|
||||
|
||||
sem::LoopBlockStatement {
|
||||
sem::Statement statement_a
|
||||
sem::LoopContinuingBlockStatement {
|
||||
sem::Statement statement_b
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## switch statement
|
||||
|
||||
WGSL:
|
||||
```
|
||||
switch (condition) {
|
||||
case literal_a, literal_b: {
|
||||
statement_a;
|
||||
}
|
||||
default {
|
||||
statement_b;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Semantic tree:
|
||||
```
|
||||
sem::SwitchStatement {
|
||||
sem::Expression condition
|
||||
sem::CaseStatement {
|
||||
sem::BlockStatement {
|
||||
sem::Statement statement_a
|
||||
}
|
||||
}
|
||||
sem::CaseStatement {
|
||||
sem::BlockStatement {
|
||||
sem::Statement statement_b
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
24
docs/tint/coverage-info.md
Normal file
24
docs/tint/coverage-info.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Generating and viewing Tint code-coverage
|
||||
|
||||
Requirements:
|
||||
|
||||
* Host running Linux or macOS
|
||||
* Clang toolchain on the `PATH` environment variable
|
||||
|
||||
## Building Tint with coverage generation enabled
|
||||
|
||||
Follow the steps [to build Tint with CMake](../README.md), but include the additional `-DTINT_EMIT_COVERAGE=1` CMake flag.
|
||||
|
||||
## Generate coverage information
|
||||
|
||||
Use the `<tint>/tools/tint-generate-coverage` script to run the tint executable or unit tests and generate the coverage information.
|
||||
|
||||
The script takes the executable to invoke as the first command line argument, followed by additional arguments to pass to the executable.
|
||||
|
||||
For example, to see the code coverage for all unit tests, run:
|
||||
`<tint>/tools/tint-generate-coverage <build>/tint_unittests --gtest_brief`
|
||||
|
||||
The script will emit two files at the root of the tint directory:
|
||||
|
||||
* `coverage.summary` - A text file giving a coverage summary for all Tint source files.
|
||||
* `lcov.info` - A binary coverage file that can be consumed with the [VSCode Coverage Gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) extension.
|
||||
126
docs/tint/diagnostics_guide.md
Normal file
126
docs/tint/diagnostics_guide.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Tint diagnostic style guide
|
||||
|
||||
This guide provides a set of best practices when writing code that emits
|
||||
diagnostic messages in Tint. These diagnostics are messages presented to the
|
||||
user in case of error or warning.
|
||||
|
||||
The goal of this document is to have our diagnostic messages be clear and
|
||||
understandable to our users, so that problems are easy to fix, and to try and
|
||||
keep a consistent style.
|
||||
|
||||
## Message style
|
||||
|
||||
* Start diagnostic messages with a lower-case letter
|
||||
* Try to keep the message to a single sentence, if possible
|
||||
* Do not end the message with punctuation (full stop, exclamation mark, etc)
|
||||
|
||||
**Don't:**
|
||||
|
||||
```
|
||||
shader.wgsl:7:1 error: Cannot take the address of expression.
|
||||
```
|
||||
|
||||
**Do:**
|
||||
|
||||
```
|
||||
shader.wgsl:7:1 error: cannot take the address of expression
|
||||
```
|
||||
|
||||
**Justification:**
|
||||
|
||||
Succinct messages are more important than grammatical correctness. \
|
||||
This style matches the style found in most other compilers.
|
||||
|
||||
## Prefer to use a `Source` location instead of quoting the code in the message
|
||||
|
||||
**Don't:**
|
||||
|
||||
```
|
||||
shader.wgsl:5:7 error: cannot multiply 'expr_a * expr_b' with types i32 and f32
|
||||
|
||||
var res : f32 = expr_a * expr_b
|
||||
^^^^^^^^^^^^^^^
|
||||
```
|
||||
|
||||
**Do:**
|
||||
|
||||
```
|
||||
shader.wgsl:5:7 error: cannot multiply types i32 and f32
|
||||
|
||||
var res : f32 = expr_a * expr_b
|
||||
^^^^^^^^^^^^^^^
|
||||
```
|
||||
|
||||
**Justification:**
|
||||
|
||||
The highlighted line provides even more contextual information than the quoted
|
||||
source, and duplicating this information doesn't provide any more help to the
|
||||
developer. \
|
||||
Quoting single word identifiers or keywords from the source is not discouraged.
|
||||
|
||||
## Use `note` diagnostics for providing additional links to relevant code
|
||||
|
||||
**Don't:**
|
||||
|
||||
```
|
||||
shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is non-host-shareable
|
||||
|
||||
cond : bool;
|
||||
^^^^
|
||||
```
|
||||
|
||||
**Do:**
|
||||
|
||||
```
|
||||
shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is non-host-shareable
|
||||
|
||||
cond : bool;
|
||||
^^^^
|
||||
|
||||
shader.wgsl:8:4 note: while instantiating variable 'StorageBuffer'
|
||||
|
||||
var<storage> sb : StorageBuffer;
|
||||
^^
|
||||
```
|
||||
|
||||
**Justification:**
|
||||
|
||||
To properly understand some diagnostics requires looking at more than a single
|
||||
line. \
|
||||
Multi-source links can greatly reduce the time it takes to properly
|
||||
understand a diagnostic message. \
|
||||
This is especially important for diagnostics raised from complex whole-program
|
||||
analysis, but can also greatly aid simple diagnostics like symbol collision errors.
|
||||
|
||||
## Use simple terminology
|
||||
|
||||
**Don't:**
|
||||
|
||||
```
|
||||
shader.wgsl:7:1 error: the originating variable of the left-hand side of an assignment expression must not be declared with read access control.
|
||||
```
|
||||
|
||||
**Do:**
|
||||
|
||||
```
|
||||
shader.wgsl:7:1 error: cannot assign to variable with read access control
|
||||
|
||||
x.y = 1;
|
||||
^^^^^^^
|
||||
|
||||
shader.wgsl:2:8 note: read access control declared here
|
||||
|
||||
var<storage, read> x : i32;
|
||||
^^^^
|
||||
```
|
||||
|
||||
**Justification:**
|
||||
|
||||
Diagnostics will be read by Web developers who may not be native English
|
||||
speakers and are unlikely to be familiar with WGSL specification terminology.
|
||||
Too much technical jargon can be intimidating and confusing. \
|
||||
Diagnostics should give enough information to explain what's wrong, and most
|
||||
importantly, give enough information so that a fix actionable.
|
||||
|
||||
**Caution:** Be careful to not over simplify. Use the specification terminology
|
||||
if there's potential ambiguity by not including it.
|
||||
35
docs/tint/end-to-end-tests.md
Normal file
35
docs/tint/end-to-end-tests.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Tint end-to-end tests
|
||||
|
||||
This repo contains a large number of end-to-end tests at `<tint>/test`.
|
||||
|
||||
## Test files
|
||||
|
||||
Test input files have either the `.wgsl`, `.spv` or `.spvasm` file extension.
|
||||
|
||||
Each test input file is tested against each of the Tint backends. There are `<number-of-input-files>` × `<number-of-tint-backends>` tests that are performed on an unfiltered end-to-end test run.
|
||||
|
||||
Each backend test can have an **expectation file**. This expectation file sits next to the input file, with a `<input-file>.expected.<format>` extension. For example the test `test/foo.wgsl` would have the HLSL expectation file `test/foo.wgsl.expected.hlsl`.
|
||||
|
||||
An expectation file contains the expected output of Tint, when passed the input file for the given backend.
|
||||
|
||||
If the first line of the expectation file starts `SKIP`, then the test will be skipped instead of failing the end-to-end test run. It is good practice to include after the `SKIP` a reason for why the test is being skipped, along with any additional details, such as compiler error messages.
|
||||
|
||||
## Running
|
||||
|
||||
To run the end-to-end tests use the `<tint>/test/test-all.sh` script, passing the path to the tint executable as the first command line argument.
|
||||
|
||||
You can pass `--help` to see the full list of command line flags.\
|
||||
The most commonly used flags are:
|
||||
|
||||
| flag | description |
|
||||
|----------------------|-------------|
|
||||
|`--filter` | Filters the testing to subset of the tests. The filter argument is a glob pattern that can include `*` for any substring of a file or directory, and `**` for any number of directories.<br>Example: `--filter 'expressions/**/i32.wgsl'` will test all the `i32.wgsl` expression tests.
|
||||
|`--format` | Filters the tests to the particular backend.<br>Example: `--format hlsl` will just test the HLSL backend.
|
||||
|`--generate-expected` | Generate expectation files for the tests that previously had no expectation file, or were marked as `SKIP` but now pass.
|
||||
|`--generate-skip` | Generate `SKIP` expectation files for tests that are not currently passing.
|
||||
|
||||
## Authoring guidelines
|
||||
|
||||
Each test should be as small as possible, and focused on the particular feature being tested.
|
||||
|
||||
Use sub-directories whenever possible to group similar tests, and try to keep the pattern of directories as consistent as possible between different tests. This helps filter tests using the `--filter` glob patterns.
|
||||
44
docs/tint/experimental_extensions.md
Normal file
44
docs/tint/experimental_extensions.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Experimental extensions
|
||||
|
||||
Sometimes a language feature proposed for WGSL requires experiementation
|
||||
to prove its worth. Tint needs to support these, in general to enable
|
||||
that experimentation.
|
||||
|
||||
The steps for doing so are:
|
||||
|
||||
1. Choose a name for the feature, to be used in an `enable` directive.
|
||||
An experimental extension should use prefix of `google_experimental_`
|
||||
Example:
|
||||
|
||||
enable google_experimental_f16;
|
||||
|
||||
2. Write down what the feature is supposed to mean.
|
||||
This informs the Tint implementation, and tells shader authors what
|
||||
has changed.
|
||||
Ideally, this will take the form of one of the following:
|
||||
|
||||
- A PR against the WGSL spec.
|
||||
|
||||
- A description of what the contents of that PR would be, committed
|
||||
as a document in this Tint repository.
|
||||
|
||||
3. File a tracking bug for adding the feature.
|
||||
Note: Should the Tint repo have a label for experimental features?
|
||||
|
||||
4. File a tracking bug for removing the feature or converting it to
|
||||
non-experimental.
|
||||
|
||||
5. Write a plan for removal of the experiment.
|
||||
- Ideally, this plan is committed to this repository, especially the
|
||||
description of public activities and commitments. However, we recognize
|
||||
that some internal goals or metrics may be sensitive, and can be hidden.
|
||||
- The plan is about process, not technical details. It should include:
|
||||
- Who is the point of contact for this feature? The point of contact
|
||||
is responsible when the feature causes an issue or gets in the way.
|
||||
- What is your target date for declaring the experiment a success or
|
||||
failure. In Chrome an experiment must be shipped or removed, in
|
||||
finite time.
|
||||
- What experience are you hoping to gain? Do you have target metrics?
|
||||
- What approvals, if any, do you need from W3C? What is your plan to
|
||||
present your case to W3C?
|
||||
- The bug tracking removal of the experiment.
|
||||
109
docs/tint/origin-trial-changes.md
Normal file
109
docs/tint/origin-trial-changes.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Tint changes during Origin Trial
|
||||
|
||||
## Changes for M101
|
||||
|
||||
### New Features
|
||||
|
||||
* Tint now supports unicode identifiers. [tint:1437](crbug.com/tint/1437)
|
||||
|
||||
## Changes for M100
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* The `@interpolate(flat)` attribute must now be specified on integral user-defined IO. [tint:1224](crbug.com/tint/1224)
|
||||
* The `ignore()` intrinsic has been removed. Use phoney-assignment instead: `ignore(expr);` -> `_ = expr;`.
|
||||
* `break` statements in `continuing` blocks are now correctly validated.
|
||||
|
||||
### New Features
|
||||
|
||||
* Module-scope declarations can now be declared in any order. [tint:1266](crbug.com/tint/1266)
|
||||
* The `override` keyword and `@id()` attribute for pipeline-overridable constants are now supported, replacing the `@override` attribute. [tint:1403](crbug.com/tint/1403)
|
||||
|
||||
## Changes for M99
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Obviously infinite loops (no condition, no break) are now a validation error.
|
||||
|
||||
### Deprecated Features
|
||||
|
||||
The following features have been deprecated and will be removed in M102:
|
||||
|
||||
* The `[[block]]` attribute has been deprecated. [tint:1324](https://crbug.com/tint/1324)
|
||||
* Attributes now use the `@decoration` syntax instead of the `[[decoration]]` syntax. [tint:1382](https://crbug.com/tint/1382)
|
||||
* `elseif` has been replaced with `else if`. [tint:1289](https://crbug.com/tint/1289)
|
||||
* The `[[stride]]` attribute has been deprecated. [tint:1381](https://crbug.com/tint/1381)
|
||||
|
||||
### New Features
|
||||
|
||||
* Vector and matrix element type can now be inferred from constructor argument types. [tint:1334](https://crbug.com/tint/1334)
|
||||
* Added builtins `degrees()` and `radians()` for converting between degrees and radians. [tint:1329](https://crbug.com/tint/1329)
|
||||
* `let` arrays and matrices can now be dynamically indexed. [tint:1352](https://crbug.com/tint/1352)
|
||||
* Storage and Uniform buffer types no longer have to be structures. [tint:1372](crbug.com/tint/1372)
|
||||
* A struct declaration does not have to be followed by a semicolon. [tint:1380](crbug.com/tint/1380)
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fixed an issue where for-loops that contain array or structure constructors in the loop initializer statements, condition expressions or continuing statements could fail to compile. [tint:1364](https://crbug.com/tint/1364)
|
||||
|
||||
## Changes for M98
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Taking the address of a vector component is no longer allowed.
|
||||
* Module-scope declarations can no longer alias a builtin name. [tint:1318](https://crbug.com/tint/1318)
|
||||
* It is now an error to call a function either directly or transitively, from a loop continuing block, that uses `discard`. [tint:1302](https://crbug.com/tint/1302)
|
||||
|
||||
### Deprecated Features
|
||||
|
||||
* The `isNan()`, `isInf()`, `isFinite()` and `isNormal()` builtins has been deprecated and will be removed in M101. [tint:1312](https://crbug.com/tint/1312)
|
||||
|
||||
### New Features
|
||||
|
||||
* New texture gather builtins: `textureGather()` and `textureGatherCompare()`. [tint:1330](https://crbug.com/tint/1330)
|
||||
* Shadowing is now fully supported. [tint:819](https://crbug.com/tint/819)
|
||||
* The `dot()` builtin now supports integer vector types.
|
||||
* Identifiers can now start with a single leading underscore. [tint:1292](https://crbug.com/tint/1292)
|
||||
* Control flow analysis has been improved, and functions no longer need to `return` if the statement is unreachable. [tint:1302](https://crbug.com/tint/1302)
|
||||
* Unreachable statements now produce a warning instead of an error, to allow WGSL code to be updated to the new analysis behavior. These warnings may become errors in the future [gpuweb#2378](https://github.com/gpuweb/gpuweb/issues/2378)
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fixed an issue where using a module-scoped `let` in a `workgroup_size` may result in a compilation error. [tint:1320](https://crbug.com/tint/1320)
|
||||
|
||||
## Changes for M97
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Deprecated `modf()` and `frexp()` builtin overloads that take a pointer second parameter have been removed.
|
||||
* Deprecated texture builtin functions that accepted a `read` access controlled storage texture have been removed.
|
||||
* Storage textures must now only use the `write` access control.
|
||||
|
||||
### Deprecated Features
|
||||
|
||||
* The `ignore()` builtin has been replaced with phony-assignment. [gpuweb#2127](https://github.com/gpuweb/gpuweb/pull/2127)
|
||||
|
||||
### New Features
|
||||
|
||||
* `any()` and `all()` now support a `bool` parameter. These simply return the passed argument. [tint:1253](https://crbug.com/tint/1253)
|
||||
* Call statements may now include functions that return a value (`ignore()` is no longer needed).
|
||||
* The `interpolate(flat)` attribute can now be specified on integral user-defined IO. It will eventually become an error to define integral user-defined IO without this attribute.
|
||||
* Matrix construction from scalar element values is now supported.
|
||||
|
||||
### Fixes
|
||||
|
||||
* Swizzling of `vec3` types in `storage` and `uniform` buffers has been fixed for Metal 1.x. [tint:1249](https://crbug.com/tint/1249)
|
||||
* Calling a function that returns an unused value no longer produces an FXC compilation error. [tint:1259](https://crbug.com/tint/1259)
|
||||
* `abs()` fixed for unsigned integers on SPIR-V backend
|
||||
|
||||
## Changes for M95
|
||||
|
||||
### New Features
|
||||
|
||||
* The size of an array can now be defined using a non-overridable module-scope constant
|
||||
* The `num_workgroups` builtin is now supported.
|
||||
|
||||
### Fixes
|
||||
|
||||
* Hex floats: now correctly errors when the magnitude is non-zero, and the exponent would cause overflow. [tint:1150](https://crbug.com/tint/1150), [tint:1166](https://crbug.com/tint/1166)
|
||||
* Identifiers beginning with an underscore are now correctly rejected. [tint:1179](https://crbug.com/tint/1179)
|
||||
267
docs/tint/spirv-input-output-variables.md
Normal file
267
docs/tint/spirv-input-output-variables.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# SPIR-V translation of shader input and output variables
|
||||
|
||||
WGSL [MR 1315](https://github.com/gpuweb/gpuweb/issues/1315) changed WGSL so
|
||||
that pipeline inputs and outputs are handled similar to HLSL:
|
||||
|
||||
- Shader pipeline inputs are the WGSL entry point function arguments.
|
||||
- Shader pipeline outputs are the WGSL entry point return value.
|
||||
|
||||
Note: In both cases, a struct may be used to pack multiple values together.
|
||||
In that case, I/O specific attributes appear on struct members at the struct declaration.
|
||||
|
||||
Resource variables, e.g. buffers, samplers, and textures, are still declared
|
||||
as variables at module scope.
|
||||
|
||||
## Vulkan SPIR-V today
|
||||
|
||||
SPIR-V for Vulkan models inputs and outputs as module-scope variables in
|
||||
the Input and Output storage classes, respectively.
|
||||
|
||||
The `OpEntryPoint` instruction has a list of module-scope variables that must
|
||||
be a superset of all the input and output variables that are statically
|
||||
accessed in the shader call tree.
|
||||
From SPIR-V 1.4 onward, all interface variables that might be statically accessed
|
||||
must appear on that list.
|
||||
So that includes all resource variables that might be statically accessed
|
||||
by the shader call tree.
|
||||
|
||||
## Translation scheme for SPIR-V to WGSL
|
||||
|
||||
A translation scheme from SPIR-V to WGSL is as follows:
|
||||
|
||||
Each SPIR-V entry point maps to a set of Private variables proxying the
|
||||
inputs and outputs, and two functions:
|
||||
|
||||
- An inner function with no arguments or return values, and whose body
|
||||
is the same as the original SPIR-V entry point.
|
||||
- Original input variables are mapped to pseudo-in Private variables
|
||||
with the same store types, but no other attributes or properties copied.
|
||||
In Vulkan, Input variables don't have initalizers.
|
||||
- Original output variables are mapped to pseudo-out Private variables
|
||||
with the same store types and optional initializer, but no other attributes
|
||||
or properties are copied.
|
||||
- A wrapper entry point function whose arguments correspond in type, location
|
||||
and builtin attributes the original input variables, and whose return type is
|
||||
a structure containing members correspond in type, location, and builtin
|
||||
attributes to the original output variables.
|
||||
The body of the wrapper function the following phases:
|
||||
- Copy formal parameter values into pseudo-in variables.
|
||||
- Insert a bitcast if the WGSL builtin variable has different signedness
|
||||
from the SPIR-V declared type.
|
||||
- Execute the inner function.
|
||||
- Copy pseudo-out variables into the return structure.
|
||||
- Insert a bitcast if the WGSL builtin variable has different signedness
|
||||
from the SPIR-V declared type.
|
||||
- Return the return structure.
|
||||
|
||||
- Replace uses of the the original input/output variables to the pseudo-in and
|
||||
pseudo-out variables, respectively.
|
||||
- Remap pointer-to-Input with pointer-to-Private
|
||||
- Remap pointer-to-Output with pointer-to-Private
|
||||
|
||||
We are not concerned with the cost of extra copying input/output values.
|
||||
First, the pipeline inputs/outputs tend to be small.
|
||||
Second, we expect the backend compiler in the driver will be able to see
|
||||
through the copying and optimize the result.
|
||||
|
||||
### Example
|
||||
|
||||
|
||||
```glsl
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec4 frag_colour;
|
||||
layout(location = 0) in vec4 the_colour;
|
||||
|
||||
void bar() {
|
||||
frag_colour = the_colour;
|
||||
}
|
||||
|
||||
void main() {
|
||||
bar();
|
||||
}
|
||||
```
|
||||
|
||||
Current translation, through SPIR-V, SPIR-V reader, WGSL writer:
|
||||
|
||||
```groovy
|
||||
@location(0) var<out> frag_colour : vec4<f32>;
|
||||
@location(0) var<in> the_colour : vec4<f32>;
|
||||
|
||||
fn bar_() -> void {
|
||||
const x_14 : vec4<f32> = the_colour;
|
||||
frag_colour = x_14;
|
||||
return;
|
||||
}
|
||||
|
||||
@stage(fragment)
|
||||
fn main() -> void {
|
||||
bar_();
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
Proposed translation, through SPIR-V, SPIR-V reader, WGSL writer:
|
||||
|
||||
```groovy
|
||||
// 'in' variables are now 'private'.
|
||||
var<private> frag_colour : vec4<f32>;
|
||||
var<private> the_colour : vec4<f32>;
|
||||
|
||||
fn bar_() -> void {
|
||||
// Accesses to the module-scope variables do not change.
|
||||
// This is a big simplifying advantage.
|
||||
const x_14 : vec4<f32> = the_colour;
|
||||
frag_colour = x_14;
|
||||
return;
|
||||
}
|
||||
|
||||
fn main_inner() -> void {
|
||||
bar_();
|
||||
return;
|
||||
}
|
||||
|
||||
// Declare a structure type to collect the return values.
|
||||
struct main_result_type {
|
||||
@location(0) frag_color : vec4<f32>;
|
||||
};
|
||||
|
||||
@stage(fragment)
|
||||
fn main(
|
||||
|
||||
// 'in' variables are entry point parameters
|
||||
@location(0) the_color_arg : vec4<f32>
|
||||
|
||||
) -> main_result_type {
|
||||
|
||||
// Save 'in' arguments to 'private' variables.
|
||||
the_color = the_color_arg;
|
||||
|
||||
// Initialize 'out' variables.
|
||||
// Use the zero value, since no initializer was specified.
|
||||
frag_color = vec4<f32>();
|
||||
|
||||
// Invoke the original entry point.
|
||||
main_inner();
|
||||
|
||||
// Collect outputs into a structure and return it.
|
||||
var result : main_outer_result_type;
|
||||
result.frag_color = frag_color;
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
Alternately, we could emit the body of the original entry point at
|
||||
the point of invocation.
|
||||
However that is more complex because the original entry point function
|
||||
may return from multiple locations, and we would like to have only
|
||||
a single exit path to construct and return the result value.
|
||||
|
||||
### Handling fragment discard
|
||||
|
||||
In SPIR-V `OpKill` causes immediate termination of the shader.
|
||||
Is the shader obligated to write its outputs when `OpKill` is executed?
|
||||
|
||||
The Vulkan fragment operations are as follows:
|
||||
(see [6. Fragment operations](https://www.khronos.org/registry/vulkan/specs/1.2/html/vkspec.html#fragops)).
|
||||
|
||||
* Scissor test
|
||||
* Sample mask test
|
||||
* Fragment shading
|
||||
* Multisample coverage
|
||||
* Depth bounds test
|
||||
* Stencil test
|
||||
* Depth test
|
||||
* Sample counting
|
||||
* Coverage reduction
|
||||
|
||||
After that, the fragment results are used to update output attachments, including
|
||||
colour, depth, and stencil attachments.
|
||||
|
||||
Vulkan says:
|
||||
|
||||
> If a fragment operation results in all bits of the coverage mask being 0,
|
||||
> the fragment is discarded, and no further operations are performed.
|
||||
> Fragments can also be programmatically discarded in a fragment shader by executing one of
|
||||
>
|
||||
> OpKill.
|
||||
|
||||
I interpret this to mean that the outputs of a discarded fragment are ignored.
|
||||
|
||||
Therefore, `OpKill` does not require us to modify the basic scheme from the previous
|
||||
section.
|
||||
|
||||
The `OpDemoteToHelperInvocationEXT`
|
||||
instruction is an alternative way to throw away a fragment, but which
|
||||
does not immediately terminate execution of the invocation.
|
||||
It is introduced in the [`SPV_EXT_demote_to_helper_invocation](http://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/EXT/SPV_EXT_demote_to_helper_invocation.html)
|
||||
extension. WGSL does not have this feature, but we expect it will be introduced by a
|
||||
future WGSL extension. The same analysis applies to demote-to-helper. When introduced,
|
||||
it will not affect translation of pipeline outputs.
|
||||
|
||||
### Handling depth-replacing mode
|
||||
|
||||
A Vulkan fragment shader must write to the fragment depth builtin if and only if it
|
||||
has a `DepthReplacing` execution mode. Otherwise behaviour is undefined.
|
||||
|
||||
We will ignore the case where the SPIR-V shader writes to the `FragDepth` builtin
|
||||
and then discards the fragment.
|
||||
This is justified because "no further operations" are performed by the pipeline
|
||||
after the fragment is discarded, and that includes writing to depth output attachments.
|
||||
|
||||
Assuming the shader is valid, no special translation is required.
|
||||
|
||||
### Handling output sample mask
|
||||
|
||||
By the same reasoning as for depth-replacing, it is ok to incidentally not write
|
||||
to the sample-mask builtin variable when the fragment is discarded.
|
||||
|
||||
### Handling clip distance and cull distance
|
||||
|
||||
Most builtin variables are scalars or vectors.
|
||||
However, the `ClipDistance` and `CullDistance` builtin variables are arrays of 32-bit float values.
|
||||
Each entry defines a clip half-plane (respectively cull half-plane)
|
||||
A Vulkan implementation must support array sizes of up to 8 elements.
|
||||
|
||||
How prevalent are shaders that use these features?
|
||||
These variables are supported when Vulkan features `shaderClipDistance` and `shaderCullDistance`
|
||||
are supported.
|
||||
According to gpuinfo.org as of this writing, those
|
||||
Vulkan features appear to be nearly universally supported on Windows devices (>99%),
|
||||
but by only 70% on Android.
|
||||
It appears that Qualcomm devices support them, but Mali devices do not (e.g. Mali-G77).
|
||||
|
||||
The proposed translation scheme forces a copy of each array from private
|
||||
variables into the return value of a vertex shader, or into a private
|
||||
variable of a fragment shader.
|
||||
In addition to the register pressure, there may be a performance degradation
|
||||
due to the bulk copying of data.
|
||||
|
||||
We think this is an acceptable tradeoff for the gain in usability and
|
||||
consistency with other pipeline inputs and outputs.
|
||||
|
||||
## Translation scheme for WGSL AST to SPIR-V
|
||||
|
||||
To translate from the WGSL AST to SPIR-V, do the following:
|
||||
|
||||
- Each entry point formal parameter is mapped to a SPIR-V `Input` variable.
|
||||
- Struct and array inputs may have to be broken down into individual variables.
|
||||
- The return of the entry point is broken down into fields, with one
|
||||
`Output` variable per field.
|
||||
- In the above, builtins must be separated from user attributes.
|
||||
- Builtin attributes are moved to the corresponding variable.
|
||||
- Location and interpolation attributes are moved to the corresponding
|
||||
variables.
|
||||
- This translation relies on the fact that pipeline inputs and pipeline
|
||||
outputs are IO-shareable types. IO-shareable types are always storable,
|
||||
and can be the store type of input/output variables.
|
||||
- Input function parameters will be automatically initialized by the system
|
||||
as part of setting up the pipeline inputs to the entry point.
|
||||
- Replace each return statement in the entry point with a code sequence
|
||||
which writes the return value components to the synthesized output variables,
|
||||
and then executes an `OpReturn` (without value).
|
||||
|
||||
This translation is sufficient even for fragment shaders with discard.
|
||||
In that case, outputs will be ignored because downstream pipeline
|
||||
operations will not be performed.
|
||||
This is the same rationale as for translation from SPIR-V to WGSL AST.
|
||||
115
docs/tint/spirv-ptr-ref.md
Normal file
115
docs/tint/spirv-ptr-ref.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# SPIR-V translation of WGSL pointers and references
|
||||
|
||||
WGSL was updated to have two kinds of memory views: pointers and references.
|
||||
See https://github.com/gpuweb/gpuweb/pull/1569
|
||||
|
||||
In summary:
|
||||
|
||||
* Reference types are never explicitly mentioned in WGSL source.
|
||||
* A use of a variable is a value of reference type corresponding
|
||||
to the reference memory view of the storage allocated for the
|
||||
variable.
|
||||
* Let-declared constants can be of pointer type, but not reference
|
||||
type.
|
||||
* Function parameter can be of pointer type, but not reference type.
|
||||
* A variable's store type is never a pointer type, and never a
|
||||
reference type.
|
||||
* The "Load Rule" allows a reference to decay to the underlying
|
||||
store type, by issuing a load of the value in the underlying memory.
|
||||
* For an assignment:
|
||||
* The right-hand side evaluates to a non-reference type (atomic-free
|
||||
plain type).
|
||||
* The left-hand side evaluates to a reference type, whose store
|
||||
type is the same as the result of evaluating the right hand side.
|
||||
* The address-of (unary `&`) operator converts a reference to a
|
||||
pointer.
|
||||
* The dereference (unary `*`) operator converts a pointer to a
|
||||
reference.
|
||||
|
||||
TODO: Passing textures and samplers to helper functions might be
|
||||
done by "handler value", or by pointer-to-handle.
|
||||
|
||||
## Writing SPIR-V from WGSL
|
||||
|
||||
The distinction in WGSL between reference and pointer disappears
|
||||
at the SPIR-V level. Both types map into pointer types in SPIR-V.
|
||||
|
||||
To translate a valid WGSL program to SPIR-V:
|
||||
|
||||
* The dereference operator (unary `*`) is the identity operation.
|
||||
* The address-of operator (unary `&`) is the identity operation.
|
||||
* Assignment maps to OpStore.
|
||||
* The Load Rule translates to OpLoad.
|
||||
|
||||
## Reading SPIR-V to create WGSL
|
||||
|
||||
The main changes to the SPIR-V reader are:
|
||||
|
||||
* When translating a SPIR-V pointer expression, track whether the
|
||||
corresponding WGSL expression is of corresponding WGSL pointer
|
||||
type or correspoinding WGSL type.
|
||||
* Insert dereference (unary-`*`) or address-of (unary-`&`) operators
|
||||
as needed to generate valid WGSL expressions.
|
||||
|
||||
The choices can be made deterministic, as described below.
|
||||
|
||||
The SPIR-V reader only supports baseline functionality in Vulkan.
|
||||
Therefore we assume no VariablePointers or VariablePointersStorageBuffer
|
||||
capabilities. All pointers are
|
||||
[SPIR-V logical pointers](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#LogicalPointerType).
|
||||
The [SPIR-V Universal Validation Rules](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_universal_validation_rules)
|
||||
specify where logical pointers can appear as results of instructions
|
||||
or operands of instructions.
|
||||
|
||||
Each SPIR-V pointer result expression is a logical pointer, and
|
||||
therefore is one of:
|
||||
|
||||
* OpVariable: map to the reference type.
|
||||
* OpFunctionParameter: map to the pointer type.
|
||||
* OpCopyObject:
|
||||
* When these only have one use, then these often fold away.
|
||||
Otherwise, they map to a a let-declared constant.
|
||||
* Map to the pointer type.
|
||||
* OpAccessChain, OpInBoundsAccessChain:
|
||||
* This could map to either pointer or reference, and adjustments
|
||||
in other areas could make it work. However, we recommend mapping
|
||||
this to the reference type.
|
||||
* OpImageTexelPointer is not supported in WGSL.
|
||||
It is used to get a pointer into a storage texture, for use with
|
||||
atomic instructions. But image atomics is not supported in
|
||||
WebGPU/WGSL.
|
||||
|
||||
Each SPIR-V pointer operand is also a logical pointer, and is an
|
||||
operand to one of:
|
||||
* OpLoad Pointer operand:
|
||||
* Map to reference, inserting a dereference operator if needed.
|
||||
* OpStore Pointer operand:
|
||||
* Map to reference, inserting a dereference operator if needed.
|
||||
* OpStore Pointer operand:
|
||||
* OpAccessChain, OpInBoundsAccessChain Base operand:
|
||||
* WGSL array-access and subfield access only works on references.
|
||||
* [Gpuweb issue 1530](https://github.com/gpuweb/gpuweb/issues/1530)
|
||||
is filed to allow those operations to work on pointers.
|
||||
* Map to reference, inserting a dereference operator if needed.
|
||||
* OpFunctionCall function argument pointer operands
|
||||
* Function operands can't be references.
|
||||
* Map to pointer, inserting an address-of operator if needed.
|
||||
* OpAtomic instruction Pointer operand
|
||||
* These map to WGSL atomic builtins.
|
||||
* Map to pointer, inserting an address-of operator if needed.
|
||||
* Note: As of this writing, the atomic instructions are not supported
|
||||
by the SPIR-V reader.
|
||||
* OpCopyObject source operand
|
||||
* This could have been mapped either way, but it's easiest to
|
||||
map to pointer, to match the choice for OpCopyObject result type.
|
||||
* Map to pointer, inserting an address-of operator if needed.
|
||||
* OpCopyMemory, source and destination operands
|
||||
* This acts as an assignment.
|
||||
* Map both source and destination to reference, inserting dereference
|
||||
operators if needed.
|
||||
* Note: As of this writing, OpCopyMemory is not supported by the
|
||||
SPIR-V reader.
|
||||
* Extended instruction set instructions Modf and Frexp
|
||||
* These map to builtins.
|
||||
* Map the pointer operand to pointer, inserting an address-of
|
||||
operator if needed.
|
||||
50
docs/tint/style_guide.md
Normal file
50
docs/tint/style_guide.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Tint style guide
|
||||
|
||||
* Generally, follow the [Chromium style guide for C++](https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/c++/c++.md)
|
||||
which itself is built on the [Google C++ style guide](https://google.github.io/styleguide/cppguide.html).
|
||||
|
||||
* Overall try to use the same style and convention as code around your change.
|
||||
|
||||
* Code must be formatted. Use `clang-format` with the provided [.clang-format](../.clang-format)
|
||||
file. The `tools/format` script runs the formatter.
|
||||
|
||||
* Code should not have linting errors.
|
||||
The `tools/lint` script runs the linter. So does `git cl upload`.
|
||||
|
||||
* Do not use C++ exceptions
|
||||
|
||||
* Do not use C++ RTTI.
|
||||
Instead, use `tint::Castable::As<T>()` from
|
||||
[src/castable.h](../src/castable.h)
|
||||
|
||||
* Generally, avoid `assert`. Instead, issue a [diagnostic](../src/diagnostic.h)
|
||||
and fail gracefully, possibly by returning an error sentinel value.
|
||||
Code that should not be reachable should call `TINT_UNREACHABLE` macro
|
||||
and other internal error conditions should call the `TINT_ICE` macro.
|
||||
See [src/debug.h](../src/debug.h)
|
||||
|
||||
* Use `type` as part of a name only when the name refers to a type
|
||||
in WGSL or another shader language processed by Tint. If the concept you are
|
||||
trying to name is about distinguishing between alternatives, use `kind` instead.
|
||||
|
||||
## Compiler support
|
||||
|
||||
Tint requires C++14.
|
||||
|
||||
Tint uses the Chromium build system and will stay synchronized with that system.
|
||||
Compiler configurations beyond that baseline is on a best-effort basis.
|
||||
We strive to support recent GCC and MSVC compilers.
|
||||
|
||||
## Test code
|
||||
|
||||
We might relax the above rules rules for test code, since test code
|
||||
shouldn't ship to users.
|
||||
|
||||
However, test code should still be readable and maintainable.
|
||||
|
||||
For test code, the tradeoff between readability and maintainability
|
||||
and other factors is weighted even more strongly toward readability
|
||||
and maintainability.
|
||||
|
||||
|
||||
|
||||
191
docs/tint/translations.md
Normal file
191
docs/tint/translations.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Translations
|
||||
|
||||
This document attempts to document how WGSL translates into the various backends
|
||||
for the cases where the translation is not a direct mapping.
|
||||
|
||||
# Access Control
|
||||
|
||||
## HLSL
|
||||
* ReadOnly -> `ByteAddressBuffer`
|
||||
* ReadWrite -> `RWByteAddressBuffer`
|
||||
|
||||
## MSL
|
||||
* ReadOnly -> `const`
|
||||
|
||||
## SPIR-V
|
||||
There are two ways this can be achieved in SPIR-V. Either the variable can be
|
||||
decorated with `NonWritable` or each member of the struct can be decorated with
|
||||
`NonWritable`. We chose to go the struct member route.
|
||||
* The read-only becomes part of the type in this case. Otherwise, you are
|
||||
treating the readonly type information as part of the variable which is
|
||||
confusing.
|
||||
* Treating the readonly as part of the variable means we should be
|
||||
deduplicating the types behind the access control, which causes confusing
|
||||
with the type_names and various tracking systems within Tint.
|
||||
|
||||
|
||||
# Builtin Decorations
|
||||
| Name | SPIR-V | MSL | HLSL |
|
||||
|------|--------|-----|------|
|
||||
| position | SpvBuiltInPosition |position | SV_Position |
|
||||
| vertex_index | SpvBuiltInVertexIndex |vertex_id | SV_VertexID |
|
||||
| instance_index | SpvBuiltInInstanceIndex | instance_id| SV_InstanceID |
|
||||
| front_facing | SpvBuiltInFrontFacing | front_facing | SV_IsFrontFacing |
|
||||
| frag_coord | SpvBuiltInFragCoord | position | SV_Position |
|
||||
| frag_depth | SpvBuiltInFragDepth | depth(any) | SV_Depth |
|
||||
| local_invocation_id | SpvBuiltInLocalInvocationId | thread_position_in_threadgroup | SV_GroupThreadID |
|
||||
| local_invocation_index | SpvBuiltInLocalInvocationIndex | thread_index_in_threadgroup | SV_GroupIndex |
|
||||
| global_invocation_id | SpvBuiltInGlobalInvocationId | thread_position_in_grid | SV_DispatchThreadID |
|
||||
|
||||
|
||||
# Builtins Methods
|
||||
| Name | SPIR-V | MSL | HLSL |
|
||||
| ------|--------|-----|------ |
|
||||
| abs | GLSLstd450FAbs or GLSLstd450SAbs| fabs or abs | abs |
|
||||
| acos | GLSLstd450Acos | acos | acos |
|
||||
| all | SpvOpAll | all | all |
|
||||
| any | SpvOpAny | any | any |
|
||||
| arrayLength | SpvOpArrayLength | | |
|
||||
| asin | GLSLstd450Asin | asin | asin |
|
||||
| atan | GLSLstd450Atan | atan | atan |
|
||||
| atan2 | GLSLstd450Atan2| atan2 | atan2 |
|
||||
| ceil | GLSLstd450Ceil| ceil | ceil |
|
||||
| clamp | GLSLstd450NClamp or GLSLstd450UClamp or GLSLstd450SClamp| clamp | clamp |
|
||||
| cos | GLSLstd450Cos | cos | cos |
|
||||
| cosh | GLSLstd450Cosh | cosh | cosh |
|
||||
| countOneBits | SpvOpBitCount | popcount | countbits |
|
||||
| cross | GLSLstd450Cross | cross | cross |
|
||||
| determinant | GLSLstd450Determinant | determinant | determinant |
|
||||
| distance | GLSLstd450Distance | distance | distance |
|
||||
| dot | SpOpDot | dot | dot |
|
||||
| dpdx | SpvOpDPdx | dpdx | ddx |
|
||||
| dpdxCoarse | SpvOpDPdxCoarse | dpdx | ddx_coarse |
|
||||
| dpdxFine | SpvOpDPdxFine | dpdx | ddx_fine |
|
||||
| dpdy | SpvOpDPdy | dpdy | ddy |
|
||||
| dpdyCoarse | SpvOpDPdyCoarse | dpdy | ddy_coarse |
|
||||
| dpdyFine | SpvOpDPdyFine | dpdy | ddy_fine |
|
||||
| exp | GLSLstd450Exp | exp | exp |
|
||||
| exp2 | GLSLstd450Exp2 | exp2 | exp2 |
|
||||
| faceForward | GLSLstd450FaceForward | faceforward | faceforward |
|
||||
| floor | GLSLstd450Floor | floor | floor |
|
||||
| fma | GLSLstd450Fma | fma | fma |
|
||||
| fract | GLSLstd450Fract | fract | frac |
|
||||
| frexp | GLSLstd450Frexp | | |
|
||||
| fwidth | SpvOpFwidth | fwidth | fwidth |
|
||||
| fwidthCoarse | SpvOpFwidthCoarse | fwidth | fwidth |
|
||||
| fwidthFine | SpvOpFwidthFine | fwidth | fwidth |
|
||||
| inverseSqrt | GLSLstd450InverseSqrt | rsqrt | rsqrt |
|
||||
| isFinite | | isfinite | isfinite |
|
||||
| isInf | SpvOpIsInf | isinf | isinf |
|
||||
| isNan | SpvOpIsNan | isnan | isnan |
|
||||
| isNormal | | isnormal | |
|
||||
| ldexp | GLSLstd450Ldexp | | |
|
||||
| length | GLSLstd450Length | length | length |
|
||||
| log | GLSLstd450Log | log | log |
|
||||
| log2 | GLSLstd450Log2 | log2 | log2 |
|
||||
| max | GLSLstd450NMax or GLSLstd450SMax or GLSLstd450UMax | fmax or max | max |
|
||||
| min | GLSLstd450NMin or GLSLstd450SMin or GLSLstd450UMin | fmin or min | min |
|
||||
| mix | GLSLstd450FMix | mix | mix |
|
||||
| modf | GLSLstd450Modf | | |
|
||||
| normalize | GLSLstd450Normalize | normalize | normalize |
|
||||
| pow | GLSLstd450Pow | pow | pow |
|
||||
| reflect | GLSLstd450Reflect | reflect | reflect |
|
||||
| reverseBits | SpvOpBitReverse | reverse_bits | reversebits |
|
||||
| round | GLSLstd450Round | round | round |
|
||||
| select | SpvOpSelect | select | |
|
||||
| sign | GLSLstd450FSign | sign | sign |
|
||||
| sin | GLSLstd450Sin | sin | sin |
|
||||
| sinh | GLSLstd450Sinh | sinh | sinh |
|
||||
| smoothStep | GLSLstd450SmoothStep | smoothstep | smoothstep |
|
||||
| sqrt | GLSLstd450Sqrt | sqrt | sqrt |
|
||||
| step | GLSLstd450Step | step | step |
|
||||
| tan | GLSLstd450Tan | tan | tan |
|
||||
| tanh | GLSLstd450Tanh | tanh | tanh |
|
||||
| trunc | GLSLstd450Trunc | trunc | trunc |
|
||||
|
||||
# Types
|
||||
## Sampler Types
|
||||
| WGSL | SPIR-V | MSL | HLSL |
|
||||
|------|--------|-----|------|
|
||||
| sampler | OpTypeSampler | sampler | SamplerState |
|
||||
| sampler_comparison | OpTypeSampler | sampler | SamplerComparisonState |
|
||||
|
||||
## Texture Types
|
||||
| WGSL | SPIR-V | MSL | HLSL |
|
||||
|------|--------|-----|------|
|
||||
| texture_1d<type> | OpTypeImage 1D Sampled=1 | texture1d<type, access::sample> | Texture1D |
|
||||
| texture_2d<type> | OpTypeImage 2D Sampled=1 | texture2d<type, access::sample> | Texture2D |
|
||||
| texture_2d_array<type> | OpTypeImage 2D Arrayed=1 Sampled=1 | texture2d_array<type, access::sample> | Texture2DArray |
|
||||
| texture_3d<type> | OpTypeImage 3D Sampled=1 | texture3d<type, access::sample> | Texture3D |
|
||||
| texture_cube<type> | OpTypeImage Cube Sampled=1 | texturecube<type, access::sample> | TextureCube |
|
||||
| texture_cube_array<type> | OpTypeImage Cube Arrayed=1 Sampled=1 | texturecube_array<type, access::sample> | TextureCubeArray |
|
||||
| | | |
|
||||
| texture_multisampled_2d<type> | OpTypeImage 2D MS=1 Sampled=1 | texture2d_ms<type, access::sample> | Texture2D |
|
||||
| | | |
|
||||
| texture_depth_2d | OpTypeImage 2D Depth=1 Sampled=1 | depth2d<float, access::sample>| Texture2D |
|
||||
| texture_depth_2d_array | OpTypeImage 2D Depth=1 Arrayed=1 Sampled=1 | depth2d_array<float, access::sample> | Texture2DArray |
|
||||
| texture_depth_cube | OpTypeImage Cube Depth=1 Sampled=1 | depthcube<float, access::sample> | TextureCube |
|
||||
| texture_depth_cube_array | OpTypeImage Cube Depth=1 Arrayed=1 Sampled=1 | depthcube_array<float, access::sample> | TextureCubeArray |
|
||||
| texture_depth_multisampled_2d | OpTypeImage 2D Depth=1 MS=1 Sampled=1 | depth2d<float, access::sample>| Texture2DMSArray |
|
||||
| | | |
|
||||
| texture_storage_1d<image_storage_type> | OpTypeImage 1D Sampled=2| texture1d<type, access::read> | RWTexture1D |
|
||||
| texture_storage_2d<image_storage_type> | OpTypeImage 2D Sampled=2 | texture2d<type, access::read> | RWTexture2D |
|
||||
| texture_storage_2d_array<image_storage_type> | OpTypeImage 2D Arrayed=1 Sampled=2 | texture2d_array<type, access::read> | RWTexture2DArray |
|
||||
| texture_storage_3d<image_storage_type> | OpTypeImage 3D Sampled=2 | texture3d<type, access::read> | RWTexture3D |
|
||||
| | | |
|
||||
| texture_storage_1d<image_storage_type> | OpTypeImage 1D Sampled=2 | texture1d<type, access::write> | RWTexture1D |
|
||||
| texture_storage_2d<image_storage_type> | OpTypeImage 2D Sampled=1 | texture2d<type, access::write> | RWTexture2D |
|
||||
| texture_storage_2d_array<image_storage_type> | OpTypeImage 2D Arrayed=1 Sampled=2 | texture2d_array<type, access::write> | RWTexture2DArray |
|
||||
| texture_storage_3d<image_storage_type> | OpTypeImage 3D Sampled=2 | texture3d<type, access::write> | RWTexture3D|
|
||||
|
||||
# Short-circuting
|
||||
## HLSL
|
||||
TODO(dsinclair): Nested if's
|
||||
|
||||
## SPIR-V
|
||||
TODO(dsinclair): Nested if's
|
||||
|
||||
# Storage classes
|
||||
TODO(dsinclair): do ...
|
||||
|
||||
# Storage buffers
|
||||
## HLSL
|
||||
TODO(dsinclair): Rewriting of accessors to loads
|
||||
|
||||
# Loop blocks
|
||||
## HLSL
|
||||
TODO(dsinclair): Rewrite with bools
|
||||
|
||||
## MSL
|
||||
TODO(dsinclair): Rewrite with bools
|
||||
|
||||
# Input / Output storage class
|
||||
## HLSL
|
||||
TODO(dsinclair): Structs and params
|
||||
|
||||
## MSL
|
||||
TODO(dsinclair): Structs and params
|
||||
|
||||
# Discard
|
||||
## HLSL
|
||||
* `discard`
|
||||
|
||||
## MSL
|
||||
* `discard_fragment()`
|
||||
|
||||
|
||||
# Specialization constants
|
||||
## HLSL
|
||||
```
|
||||
#ifndef WGSL_SPEC_CONSTANT_<id>
|
||||
-- if default provided
|
||||
#define WGSL_SPEC_CONSTANT_<id> default value
|
||||
-- else
|
||||
#error spec constant required for constant id
|
||||
--
|
||||
#endif
|
||||
static const <type> <name> = WGSL_SPEC_CONSTANT_<id>
|
||||
```
|
||||
|
||||
## MSL
|
||||
`@function_constant(<id>)`
|
||||
Reference in New Issue
Block a user