|
1 | 1 | # Compiletests
|
2 | 2 |
|
3 |
| -This folder contains tests known as "compiletests". Each file in the `ui` folder corresponds to a |
4 |
| -single compiletest. The way they work is a tool iterates over every file, and tries to compile it. |
5 |
| -At the start of the file, there's some meta-comments about the expected result of the compile: |
6 |
| -whether it should succeed compilation, or fail. If it is expected to fail, there's a corresponding |
7 |
| -.stderr file next to the file that contains the expected compiler error message. |
| 3 | +This folder contains tests known as "compiletests", where each file in the `ui` folder corresponds |
| 4 | +to a single compiletest. Keep in mind that the tests here are not executed, they are merely checked |
| 5 | +for compile errors and the resulting binaries being valid (with spirv-val). If you also want to run |
| 6 | +your shaders and verify their output, have a look at the neighbouring "difftests" instead. |
8 | 7 |
|
9 |
| -The `src` folder here is the tool that iterates over every file in the `ui` folder. It uses the |
10 |
| -`compiletests` library, taken from rustc's own compiletest framework. |
11 |
| - |
12 |
| -You can run compiletests via `cargo compiletest`. This is an alias set up in `.cargo/config` for |
| 8 | +You can run compiletests via `cargo compiletest`, with an alias setup in `.cargo/config` for |
13 | 9 | `cargo run --release -p compiletests --`. You can filter to run specific tests by passing the
|
14 |
| -(partial) filenames to `cargo compiletest some_file_name`, and update the `.stderr` files to |
15 |
| -contain new output via the `--bless` flag (with `--bless`, make sure you're actually supposed to be |
16 |
| -changing the .stderr files due to an intentional change, and hand-validate the output is correct |
17 |
| -afterwards). |
18 |
| - |
19 |
| -Keep in mind that tests here here are not executed, merely checked for errors (including validating |
20 |
| -the resulting binary with spirv-val). Because of this, there might be some strange code in here - |
21 |
| -the point isn't to make a fully functional shader every time (that would take an annoying amount of |
22 |
| -effort), but rather validate that specific parts of the compiler are doing their job correctly |
23 |
| -(either succeeding as they should, or erroring as they should). |
| 10 | +(partial) filenames like `cargo compiletest arch/subgroup`. You can also `--bless` the tests, |
| 11 | +which will update their expected stderr output in their associated `.stderr` file, if you |
| 12 | +promise to **manually verify** the new contents before committing them. |
| 13 | + |
| 14 | +Our compiletests use the [`compiletest_rs`](https://github.com/Manishearth/compiletest-rs) library, |
| 15 | +which is the compiletest framework within rustc itself, and some glue code in `src`. |
| 16 | + |
| 17 | +## How to write a compiletest |
| 18 | + |
| 19 | +Create a new `test.rs` file within `./ui` and copy in the following minimal contents: |
| 20 | +```rust |
| 21 | +// build-pass |
| 22 | + |
| 23 | +use spirv_std::spirv; |
| 24 | + |
| 25 | +#[spirv(fragment)] |
| 26 | +pub fn main() {} |
| 27 | +``` |
| 28 | + |
| 29 | +The first lines are meta-comments containing instructions on how this test should be compiled, at |
| 30 | +the very least `build-pass` or `build-fail`. Additional flags can be found in the next chapter. |
| 31 | +Then you declare your shader entry point as you would normally, here a simple fragment shader that |
| 32 | +does nothing. You can only use external `spirv_std` crate as well as it's reexported dependents, so |
| 33 | +to get a `Vec4` you can `use spirv_std::glam::Vec4` and if you need complex f32 operations you can |
| 34 | +`use spirv_std::num_traits::Float`, just like you would in a normal shader. |
| 35 | + |
| 36 | +The stderr output of the build operation is expected to match the contents of the file |
| 37 | +`path/to/test.rs.stderr` and may be updated with `--bless`. The stderr output may either come from |
| 38 | +some errors emitted by rustc or the rust-gpu itself, usually on tests which are expected to fail, |
| 39 | +or from other flags to disassemble the shader. Please manually verify any changes to the output |
| 40 | +before committing them. |
| 41 | + |
| 42 | +## Meta-comments reference |
| 43 | + |
| 44 | +Most meta-comments can be added multiple times, for example multiple `compile-flags` will be |
| 45 | +appended to each other. Listed here are some of the common ones seen in rust-gpu compile tests, a |
| 46 | +full reference can be found in the |
| 47 | +[Compiletest documentation of rustc](https://rustc-dev-guide.rust-lang.org/tests/ui.html#error-annotations). |
| 48 | + |
| 49 | +* `// build-pass` the shader must build successfully |
| 50 | +* `// build-fail` the shader must fail to build |
| 51 | +* `// only-vulkan1.2` only run the test on target vulkan1.2, skip otherwise. Other targets are accepted. |
| 52 | +* `// ignore-vulkan1.2` skip the test on target vulkan1.2. Other targets are accepted. |
| 53 | +* `// compile-flags: something` adds `something` to the compile flags |
| 54 | +* `// compile-flags: -C target-feature=+StorageImageExtendedFormats` add a `Capability` like with `SpirvBuilder.capabilities` |
| 55 | +* `// compile-flags: -C +ext:SPV_KHR_ray_tracing` add an `Extension` like with `SpirvBuilder.extensions` |
| 56 | +* `// compile-flags: -C target-feature=+MeshShadingEXT,+ext:SPV_EXT_mesh_shader` add both an extension and a capability, as they are often go together |
| 57 | +* `// compile-flags: -C llvm-args=--abort-strategy=debug-printf` an example how to set some other property, see source of `SpirvBuilder` for reference |
| 58 | + |
| 59 | +### Disassembly |
| 60 | + |
| 61 | +All disassembly will be dumped to stderr, which makes the testing framework compare it to the |
| 62 | +contents of `path/to/test.rs.stdout`. |
| 63 | + |
| 64 | +* `// compile-flags: -C llvm-args=--disassemble` disassemble the entire shader |
| 65 | +* `// compile-flags: -C llvm-args=--disassemble-globals` disassemble only globals and function declarations, excludes function contents |
| 66 | +* `// compile-flags: -C llvm-args=--disassemble-entry=main` disassembles the `main` entry point, does not work on functions |
| 67 | +* `// compile-flags: -C llvm-args=--disassemble-fn=add_two_ints::add_two_ints` disassembles the |
| 68 | + function `add_two_ints`. The name must be `<file_name>::<function_name>`, the function must |
| 69 | + **not** be an entry point but must called by an entry point to not be dead-code eliminated. |
| 70 | + Usually, a test has the disassembled function and an entry point calling it. |
| 71 | +* `// normalize-stderr-test "targetSpecificMsg" -> ""` Replaces any substrings in stderr with another to normalise output |
| 72 | + between different machines and targets. By default, you should have to not specify any and only add them as needed. |
| 73 | + List of common substitutions: |
| 74 | + * `// normalize-stderr-test "OpLine .*\n" -> ""` remove all line numbers from debug info |
| 75 | + * `// normalize-stderr-test "OpSource .*\n" -> ""` remove all source code from debug info |
| 76 | + * `// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/"` normalize path to the `spirv-std` crate |
| 77 | + * `// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""` remove the vulkan memory model *capability*, only used by vulkan targets |
| 78 | + * `// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""` remove the vulkan memory model *extension*, only used by vulkan targets |
| 79 | + * `// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"` replace the `Vulkan` memory model with `Simple` |
| 80 | + * `// normalize-stderr-test "\S*/lib/rustlib/" -> "$$SYSROOT/lib/rustlib/"` normalize path to crates delivered with rustc, such as `core` |
0 commit comments