From 27eb1d1413ec982ce77a6766744da58c95e81a9f Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Thu, 18 Mar 2021 18:16:21 +0100 Subject: [PATCH] Refactor validation tests to use compiletest (#464) * Refactor validation tests to use compiletest * Update tests/ui/lang/core/ptr/allocate_const_scalar.rs --- .cargo/config | 3 + .gitattributes | 1 + .github/workflows/test.sh | 2 + .gitignore | 1 + Cargo.lock | 146 ++++- Cargo.toml | 6 + crates/spirv-builder/src/test/arch.rs | 304 ---------- crates/spirv-builder/src/test/basic.rs | 251 -------- crates/spirv-builder/src/test/control_flow.rs | 423 ------------- crates/spirv-builder/src/test/mod.rs | 1 - docs/src/SUMMARY.md | 5 +- docs/src/testing.md | 39 ++ tests/Cargo.lock | 563 ------------------ tests/Cargo.toml | 11 + tests/src/main.rs | 295 +++++++++ tests/ui/arch/all.rs | 7 + tests/ui/arch/any.rs | 7 + tests/ui/arch/f_add.rs | 10 + tests/ui/arch/f_div.rs | 10 + tests/ui/arch/f_mod.rs | 10 + tests/ui/arch/f_mul.rs | 10 + tests/ui/arch/f_negate.rs | 8 + tests/ui/arch/f_rem.rs | 10 + tests/ui/arch/f_sub.rs | 10 + tests/ui/arch/i_add.rs | 10 + tests/ui/arch/i_mul.rs | 10 + tests/ui/arch/i_sub.rs | 10 + tests/ui/arch/s_div.rs | 10 + tests/ui/arch/s_mod.rs | 10 + tests/ui/arch/s_negate.rs | 8 + tests/ui/arch/s_rem.rs | 10 + tests/ui/arch/u_div.rs | 10 + tests/ui/arch/u_mod.rs | 10 + tests/ui/arch/vector_extract_dynamic.rs | 14 + tests/ui/arch/vector_insert_dynamic.rs | 16 + tests/ui/arch/vector_times_scalar.rs | 8 + tests/ui/glam/mat3_vec3_multiply.rs | 11 + tests/ui/hello_world.rs | 8 + tests/ui/image/fetch.rs | 9 + tests/ui/image/read.rs | 10 + tests/ui/image/write.rs | 12 + tests/ui/lang/asm/const_args.rs | 20 + tests/ui/lang/control_flow/defer.rs | 16 + tests/ui/lang/control_flow/for_range.rs | 9 + .../for_with_custom_range_iter.rs | 32 + tests/ui/lang/control_flow/if.rs | 10 + tests/ui/lang/control_flow/if_else.rs | 12 + tests/ui/lang/control_flow/if_else_if_else.rs | 14 + tests/ui/lang/control_flow/if_if.rs | 12 + tests/ui/lang/control_flow/if_return_else.rs | 11 + .../control_flow/if_return_else_return.rs | 12 + tests/ui/lang/control_flow/if_while.rs | 11 + tests/ui/lang/control_flow/ifx2.rs | 13 + tests/ui/lang/control_flow/issue_283.rs | 48 ++ tests/ui/lang/control_flow/loop.rs | 8 + tests/ui/lang/control_flow/while.rs | 9 + tests/ui/lang/control_flow/while_break.rs | 10 + tests/ui/lang/control_flow/while_continue.rs | 10 + tests/ui/lang/control_flow/while_if_break.rs | 12 + .../control_flow/while_if_break_else_break.rs | 14 + .../control_flow/while_if_break_if_break.rs | 15 + .../ui/lang/control_flow/while_if_continue.rs | 12 + .../while_if_continue_else_continue.rs | 14 + tests/ui/lang/control_flow/while_return.rs | 10 + tests/ui/lang/control_flow/while_while.rs | 11 + .../ui/lang/control_flow/while_while_break.rs | 12 + .../lang/control_flow/while_while_continue.rs | 12 + .../lang/control_flow/while_while_if_break.rs | 14 + .../control_flow/while_while_if_continue.rs | 14 + .../core/mem/create_unitialized_memory.rs | 16 + tests/ui/lang/core/ops/logical_and.rs | 13 + .../ui/lang/core/ptr/allocate_const_scalar.rs | 16 + .../core/ptr/allocate_const_scalar.stderr | 13 + tests/ui/lang/core/ptr/allocate_null.rs | 12 + tests/ui/lang/core/ptr/allocate_vec_like.rs | 16 + tests/ui/lang/f32/signum.rs | 10 + tests/ui/lang/panic/builtin.rs | 13 + tests/ui/lang/panic/builtin_bounds_check.rs | 13 + tests/ui/lang/panic/simple.rs | 9 + tests/ui/storage_class/push_constant.rs | 21 + 80 files changed, 1313 insertions(+), 1545 deletions(-) delete mode 100644 crates/spirv-builder/src/test/arch.rs delete mode 100644 crates/spirv-builder/src/test/control_flow.rs create mode 100644 docs/src/testing.md delete mode 100644 tests/Cargo.lock create mode 100644 tests/Cargo.toml create mode 100644 tests/src/main.rs create mode 100644 tests/ui/arch/all.rs create mode 100644 tests/ui/arch/any.rs create mode 100644 tests/ui/arch/f_add.rs create mode 100644 tests/ui/arch/f_div.rs create mode 100644 tests/ui/arch/f_mod.rs create mode 100644 tests/ui/arch/f_mul.rs create mode 100644 tests/ui/arch/f_negate.rs create mode 100644 tests/ui/arch/f_rem.rs create mode 100644 tests/ui/arch/f_sub.rs create mode 100644 tests/ui/arch/i_add.rs create mode 100644 tests/ui/arch/i_mul.rs create mode 100644 tests/ui/arch/i_sub.rs create mode 100644 tests/ui/arch/s_div.rs create mode 100644 tests/ui/arch/s_mod.rs create mode 100644 tests/ui/arch/s_negate.rs create mode 100644 tests/ui/arch/s_rem.rs create mode 100644 tests/ui/arch/u_div.rs create mode 100644 tests/ui/arch/u_mod.rs create mode 100644 tests/ui/arch/vector_extract_dynamic.rs create mode 100644 tests/ui/arch/vector_insert_dynamic.rs create mode 100644 tests/ui/arch/vector_times_scalar.rs create mode 100644 tests/ui/glam/mat3_vec3_multiply.rs create mode 100644 tests/ui/hello_world.rs create mode 100644 tests/ui/image/fetch.rs create mode 100644 tests/ui/image/read.rs create mode 100644 tests/ui/image/write.rs create mode 100644 tests/ui/lang/asm/const_args.rs create mode 100644 tests/ui/lang/control_flow/defer.rs create mode 100644 tests/ui/lang/control_flow/for_range.rs create mode 100644 tests/ui/lang/control_flow/for_with_custom_range_iter.rs create mode 100644 tests/ui/lang/control_flow/if.rs create mode 100644 tests/ui/lang/control_flow/if_else.rs create mode 100644 tests/ui/lang/control_flow/if_else_if_else.rs create mode 100644 tests/ui/lang/control_flow/if_if.rs create mode 100644 tests/ui/lang/control_flow/if_return_else.rs create mode 100644 tests/ui/lang/control_flow/if_return_else_return.rs create mode 100644 tests/ui/lang/control_flow/if_while.rs create mode 100644 tests/ui/lang/control_flow/ifx2.rs create mode 100644 tests/ui/lang/control_flow/issue_283.rs create mode 100644 tests/ui/lang/control_flow/loop.rs create mode 100644 tests/ui/lang/control_flow/while.rs create mode 100644 tests/ui/lang/control_flow/while_break.rs create mode 100644 tests/ui/lang/control_flow/while_continue.rs create mode 100644 tests/ui/lang/control_flow/while_if_break.rs create mode 100644 tests/ui/lang/control_flow/while_if_break_else_break.rs create mode 100644 tests/ui/lang/control_flow/while_if_break_if_break.rs create mode 100644 tests/ui/lang/control_flow/while_if_continue.rs create mode 100644 tests/ui/lang/control_flow/while_if_continue_else_continue.rs create mode 100644 tests/ui/lang/control_flow/while_return.rs create mode 100644 tests/ui/lang/control_flow/while_while.rs create mode 100644 tests/ui/lang/control_flow/while_while_break.rs create mode 100644 tests/ui/lang/control_flow/while_while_continue.rs create mode 100644 tests/ui/lang/control_flow/while_while_if_break.rs create mode 100644 tests/ui/lang/control_flow/while_while_if_continue.rs create mode 100644 tests/ui/lang/core/mem/create_unitialized_memory.rs create mode 100644 tests/ui/lang/core/ops/logical_and.rs create mode 100644 tests/ui/lang/core/ptr/allocate_const_scalar.rs create mode 100644 tests/ui/lang/core/ptr/allocate_const_scalar.stderr create mode 100644 tests/ui/lang/core/ptr/allocate_null.rs create mode 100644 tests/ui/lang/core/ptr/allocate_vec_like.rs create mode 100644 tests/ui/lang/f32/signum.rs create mode 100644 tests/ui/lang/panic/builtin.rs create mode 100644 tests/ui/lang/panic/builtin_bounds_check.rs create mode 100644 tests/ui/lang/panic/simple.rs create mode 100644 tests/ui/storage_class/push_constant.rs diff --git a/.cargo/config b/.cargo/config index 148f915d26..9fefd2a86f 100644 --- a/.cargo/config +++ b/.cargo/config @@ -2,3 +2,6 @@ # Currently there's an issue where the Example CPU runner fails without # `-C prefer-dynamic`. rustflags = "-C prefer-dynamic" + +[alias] +compiletest = "run --release --manifest-path=tests/Cargo.toml" diff --git a/.gitattributes b/.gitattributes index 93e508a7f5..5585ecaa23 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ # configure GitHub linguist (language bar) https://github.com/github/linguist#overrides docs/* linguist-documentation +* text=auto eol=lf diff --git a/.github/workflows/test.sh b/.github/workflows/test.sh index 33926893f7..8e904efc63 100755 --- a/.github/workflows/test.sh +++ b/.github/workflows/test.sh @@ -51,3 +51,5 @@ cargo_test examples/runners/wgpu cargo_test_no_features examples/runners/cpu cargo_test_no_features examples/shaders/sky-shader cargo_test_no_features examples/shaders/simplest-shader + +cargo compiletest diff --git a/.gitignore b/.gitignore index a221ac104a..39742a760c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ .vscode/ +tests/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 42def4f135..32e057d75b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" + [[package]] name = "arrayvec" version = "0.5.2" @@ -324,6 +330,35 @@ dependencies = [ "objc", ] +[[package]] +name = "compiletest_rs" +version = "0.6.0" +source = "git+https://github.com/Manishearth/compiletest-rs.git?rev=1f4a4c4#1f4a4c40e06ba36fef63909ddfaa76edcb2ac620" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow 0.3.6", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "winapi 0.3.9", +] + +[[package]] +name = "compiletests" +version = "0.0.0" +dependencies = [ + "compiletest_rs", + "rustc_codegen_spirv", +] + [[package]] name = "compute-shader" version = "0.4.0-alpha.0" @@ -572,12 +607,39 @@ dependencies = [ "syn", ] +[[package]] +name = "diff" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" + [[package]] name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -844,6 +906,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.2" @@ -1295,7 +1366,7 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.2", "net2", "slab", "winapi 0.2.8", @@ -1325,6 +1396,16 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +dependencies = [ + "socket2", + "winapi 0.3.9", +] + [[package]] name = "mouse-shader" version = "0.1.0" @@ -1834,6 +1915,16 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall 0.2.5", +] + [[package]] name = "regex" version = "1.4.5" @@ -1912,6 +2003,18 @@ dependencies = [ "topological-sort", ] +[[package]] +name = "rustfix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c50b74badcddeb8f7652fa8323ce440b95286f8e4b64ebfd871c609672704e" +dependencies = [ + "anyhow", + "log", + "serde", + "serde_json", +] + [[package]] name = "rusttype" version = "0.9.2" @@ -1922,6 +2025,12 @@ dependencies = [ "owned_ttf_parser", ] +[[package]] +name = "rustversion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" + [[package]] name = "ryu" version = "1.0.5" @@ -2081,6 +2190,17 @@ dependencies = [ "wayland-protocols 0.28.5", ] +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi 0.3.9", +] + [[package]] name = "spirv-builder" version = "0.4.0-alpha.0" @@ -2269,6 +2389,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi 0.3.9", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -2278,6 +2409,19 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "tester" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb" +dependencies = [ + "cfg-if 1.0.0", + "getopts", + "libc", + "num_cpus", + "term", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index e52bf9f3f5..d2b4a26a33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +exclude = ["target/"] members = [ "examples/runners/cpu", "examples/runners/ash", @@ -11,6 +12,8 @@ members = [ "crates/rustc_codegen_spirv", "crates/spirv-builder", "crates/spirv-std", + + "tests", ] # Compile build-dependencies in release mode with @@ -23,3 +26,6 @@ codegen-units = 16 spirv-std = { path = "./crates/spirv-std" } spirv-std-macros = { path = "./crates/spirv-std-macros" } glam = { git = "https://github.com/bitshifter/glam-rs.git", rev ="b3e94fb" } +# TODO: Needed for handling SPIR-V extension across platforms. Remove once +# next version is released. +compiletest_rs= { git = "https://github.com/Manishearth/compiletest-rs.git", rev = "1f4a4c4" } diff --git a/crates/spirv-builder/src/test/arch.rs b/crates/spirv-builder/src/test/arch.rs deleted file mode 100644 index ba59079941..0000000000 --- a/crates/spirv-builder/src/test/arch.rs +++ /dev/null @@ -1,304 +0,0 @@ -use super::val; - -#[test] -fn any() { - val(r#" - -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let vector = glam::BVec2::new(true, false); - assert!(arch::any(vector)); -} -"#); -} - -#[test] -fn all() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let vector = glam::BVec2::new(true, true); - assert!(spirv_std::arch::all(vector)); -} -"#); -} - -#[test] -fn s_negate() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let operand: i32 = -5; - let vector = glam::IVec2::new(-5, -0); - assert!(arch::s_negate_vector(vector) == glam::IVec2::new(5, 0)); -} -"#); -} - -#[test] -fn f_negate() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let operand: f32 = -5.0; - let vector = glam::Vec2::new(-5.0, -0.0); - assert!(arch::f_negate_vector(vector) == glam::Vec2::new(5.0, 0.0)); -} -"#); -} - -#[test] -fn i_add() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 5; - let y = 2; - let vx = glam::IVec2::new(2, 5); - let vy = glam::IVec2::new(5, 2); - assert!(arch::i_add_vector(vx, vy) == glam::IVec2::new(7, 7)); -} -"#); -} - -#[test] -fn f_add() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 5.0; - let y = 2.0; - let vx = glam::Vec2::new(2.0, 5.0); - let vy = glam::Vec2::new(5.0, 2.0); - assert!(arch::f_add_vector(vx, vy) == glam::Vec2::new(7.0, 7.0)); -} -"#); -} - -#[test] -fn i_sub() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 5; - let y = 5; - let vx = glam::IVec2::new(5, 7); - let vy = glam::IVec2::new(5, 7); - assert!(arch::i_sub_vector(vx, vy) == glam::IVec2::new(0, 0)); -} -"#); -} - -#[test] -fn f_sub() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 5.0; - let y = 5.0; - let vx = glam::Vec2::new(5.0, 7.0); - let vy = glam::Vec2::new(5.0, 7.0); - assert!(arch::f_sub_vector(vx, vy) == glam::Vec2::new(0.0, 0.0)); -} -"#); -} - -#[test] -fn i_mul() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 5; - let y = 2; - let vx = glam::IVec2::new(5, 2); - let vy = glam::IVec2::new(2, 5); - assert!(arch::i_mul_vector(vx, vy) == glam::IVec2::new(10, 10)); -} -"#); -} - -#[test] -fn f_mul() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 5.0; - let y = 2.0; - let vx = glam::Vec2::new(5.0, 2.0); - let vy = glam::Vec2::new(2.0, 5.0); - assert!(arch::f_mul_vector(vx, vy) == glam::Vec2::new(10.0, 10.0)); -} -"#); -} - -#[test] -fn s_div() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 10; - let y = 2; - let vx = glam::IVec2::new(10, 10); - let vy = glam::IVec2::new(2, 2); - assert!(arch::s_div_vector(vx, vy) == glam::IVec2::new(5, 5)); -} -"#); -} - -#[test] -fn u_div() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x: u32 = 10; - let y = 2; - let vx = glam::UVec2::new(10, 10); - let vy = glam::UVec2::new(2, 2); - assert!(arch::u_div_vector(vx, vy) == glam::UVec2::new(5, 5)); -} -"#); -} - -#[test] -fn f_div() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 10.0; - let y = 2.0; - let vx = glam::Vec2::new(10.0, 10.0); - let vy = glam::Vec2::new(2.0, 2.0); - assert!(arch::f_div_vector(vx, vy) == glam::Vec2::new(5.0, 5.0)); -} -"#); -} - -#[test] -fn u_mod() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x: u32 = 10; - let y = 2; - let vx = glam::UVec2::new(10, 10); - let vy = glam::UVec2::new(2, 2); - assert!(arch::u_mod_vector(vx, vy) == glam::UVec2::new(0, 0)); -} -"#); -} - -#[test] -fn s_mod() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 10; - let y = 2; - let vx = glam::IVec2::new(10, 10); - let vy = glam::IVec2::new(2, 2); - assert!(arch::s_mod_vector(vx, vy) == glam::IVec2::new(0, 0)); -} -"#); -} - -#[test] -fn s_rem() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = -10; - let y = -2; - let vx = glam::IVec2::new(-10, -10); - let vy = glam::IVec2::new(-2, -2); - assert!(arch::s_rem_vector(vx, vy) == glam::IVec2::new(-0, -0)); -} -"#); -} - -#[test] -fn f_mod() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = 10.0; - let y = 2.0; - let vx = glam::Vec2::new(10.0, 10.0); - let vy = glam::Vec2::new(2.0, 2.0); - assert!(arch::f_mod_vector(vx, vy) == glam::Vec2::new(0.0, 0.0)); -} -"#); -} - -#[test] -fn f_rem() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let x = -10.0; - let y = -2.0; - let vx = glam::Vec2::new(-10.0, -10.0); - let vy = glam::Vec2::new(-2.0, -2.0); - assert!(arch::f_mod_vector(vx, vy) == glam::Vec2::new(-0.0, -0.0)); -} -"#); -} - -#[test] -fn vector_times_scalar() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let vector = glam::Vec2::new(10.0, 10.0); - let scalar = 2.0; - assert!(arch::vector_times_scalar(vector, scalar) == glam::Vec2::new(20.0, 20.0)); -} -"#); -} - -#[test] -fn vector_extract_dynamic() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let vector = glam::Vec2::new(1.0, 2.0); - let element = unsafe { spirv_std::arch::vector_extract_dynamic(vector, 1) }; - assert!(2.0 == element); -} -"#); -} - -#[test] -fn vector_insert_dynamic() { - val(r#" -#[allow(unused_attributes)] -#[spirv(fragment)] -pub fn main() { - let vector = glam::Vec2::new(1.0, 2.0); - let expected = glam::Vec2::new(1.0, 3.0); - let new_vector = unsafe { spirv_std::arch::vector_insert_dynamic(vector, 1, 3.0) }; - assert!(new_vector == expected); -} -"#); -} - - diff --git a/crates/spirv-builder/src/test/basic.rs b/crates/spirv-builder/src/test/basic.rs index b1323d6e17..fd32fa61c3 100644 --- a/crates/spirv-builder/src/test/basic.rs +++ b/crates/spirv-builder/src/test/basic.rs @@ -19,15 +19,6 @@ impl<'a> Drop for SetEnvVar<'a> { } } -#[test] -fn hello_world() { - val(r#" -#[spirv(fragment)] -pub fn main() { -} -"#); -} - #[test] fn custom_entry_point() { dis_globals( @@ -209,95 +200,6 @@ OpDecorate %4 Binding 0 ); } -#[test] -fn asm_const_arg() { - val(r#" -fn asm() { - unsafe { - const N: usize = 3; - asm!( - "%int = OpTypeInt 32 0", - "%type = OpTypeVector %int {len}", - len = const N, - ); - } -} -#[spirv(fragment)] -pub fn main() { - asm(); -} -"#); -} - -#[test] -fn logical_and() { - val(r#" -fn f(x: bool, y: bool) -> bool { - x && y -} -#[spirv(fragment)] -pub fn main() { - f(false, true); -}"#); -} - -#[test] -fn panic() { - val(r#" -#[spirv(fragment)] -pub fn main() { - panic!("aaa"); -} -"#); -} - -#[test] -fn panic_builtin() { - val(r#" -fn int_div(x: usize) -> usize { - 1 / x -} - -#[spirv(fragment)] -pub fn main() { - int_div(0); -} -"#); -} - -#[test] -fn panic_builtin_bounds_check() { - val(r#" -fn array_bounds_check(x: [u32; 4], i: usize) -> u32 { - x[i] -} - -#[spirv(fragment)] -pub fn main() { - array_bounds_check([0, 1, 2, 3], 5); -} -"#); -} - -// NOTE(eddyb) this won't pass Vulkan validation (see `push_constant_vulkan`), -// but should still pass the basline SPIR-V validation. -#[test] -fn push_constant() { - val(r#" -#[derive(Copy, Clone)] -pub struct ShaderConstants { - pub width: u32, - pub height: u32, - pub time: f32, -} - -#[spirv(fragment)] -pub fn main(constants: PushConstant) { - let _constants = *constants; -} -"#); -} - // NOTE(eddyb) we specifically run Vulkan validation here, as the default // validation rules are more lax and don't require a `Block` decoration // (`#[spirv(block)]` here) on `struct ShaderConstants`. @@ -321,15 +223,6 @@ pub fn main(constants: PushConstant) { ); } -#[test] -fn infinite_loop() { - val(r#" -#[spirv(fragment)] -pub fn main() { - loop {} -}"#); -} - #[test] fn unroll_loops() { dis_fn( @@ -390,115 +283,6 @@ OpFunctionEnd"#, ); } -#[test] -fn signum() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input, mut o: Output) { - *o = i.signum(); -}"#); -} - -#[test] -// Doesn't work, only worked before because I think it got optimized away before hitting the -// backend. -#[ignore] -fn allocate_const_scalar_pointer() { - val(r#" -use core::ptr::Unique; -const POINTER: Unique<[u8;4]> = Unique::<[u8; 4]>::dangling(); - -#[spirv(fragment)] -pub fn main() { - let _pointer = POINTER; -}"#); -} - -#[test] -fn allocate_vec_like_pointer() { - val(r#" -use core::ptr::Unique; -const VEC_LIKE: (Unique, usize, usize) = (Unique::::dangling(), 0, 0); - -pub fn assign_vec_like() { - let _vec_like = VEC_LIKE; -} -#[spirv(fragment)] -pub fn main() {}"#); -} - -#[test] -fn allocate_null_pointer() { - val(r#" -use core::ptr::null; -const NULL_PTR: *const i32 = null(); - -#[spirv(fragment)] -pub fn main() { - let _null_ptr = NULL_PTR; -}"#); -} - -#[test] -fn create_uninitialized_memory() { - val(r#" -use core::mem::MaybeUninit; -const MAYBEI32: MaybeUninit<&i32> = MaybeUninit::<&i32>::uninit(); - -pub fn create_uninit_and_write() { - let mut maybei32 = MAYBEI32; - unsafe { maybei32.as_mut_ptr().write(&0); } - let _maybei32 = unsafe { maybei32.assume_init() }; -} - -#[spirv(fragment)] -pub fn main() {}"#); -} - -#[test] -fn vector_extract_dynamic() { - val(r#" -#[spirv(fragment)] -pub fn main() { - let vector = glam::Vec2::new(1.0, 2.0); - let element = unsafe { spirv_std::arch::vector_extract_dynamic(vector, 1) }; - assert!(2.0 == element); - let uvector = glam::UVec2::new(1, 2); - let element: u32 = unsafe { spirv_std::arch::vector_extract_dynamic(uvector, 1) }; - assert!(2 == element); -} -"#); -} - -#[test] -fn vector_insert_dynamic() { - val(r#" -#[spirv(fragment)] -pub fn main() { - let vector = glam::Vec2::new(1.0, 2.0); - let expected = glam::Vec2::new(1.0, 3.0); - let new_vector = unsafe { spirv_std::arch::vector_insert_dynamic(vector, 1, 3.0) }; - assert!(new_vector == expected); - let uvector = glam::UVec2::new(1, 2); - let uexpected = glam::UVec2::new(1, 3); - let new_vector = unsafe { spirv_std::arch::vector_insert_dynamic(uvector, 1, 3) }; - assert!(new_vector == uexpected); -} -"#); -} - -#[test] -fn mat3_vec3_multiply() { - val(r#" -#[spirv(fragment)] -pub fn main(input: Input, mut output: Output) { - let input = *input; - let vector = input * glam::Vec3::new(1.0, 2.0, 3.0); - *output = vector; -} -"#); -} - #[test] fn complex_image_sample_inst() { dis_fn( @@ -570,41 +354,6 @@ OpFunctionEnd", ); } -#[test] -fn image_read() { - val(r#" -#[spirv(fragment)] -pub fn main(image: UniformConstant, mut output: Output) { - let coords = image.read(glam::IVec2::new(0, 1)); - *output = coords; -} -"#); -} - -#[test] -fn image_write() { - val(r#" -#[spirv(fragment)] -pub fn main(input: Input, image: UniformConstant) { - let texels = *input; - unsafe { - image.write(glam::UVec2::new(0, 1), texels); - } -} -"#); -} - -#[test] -fn image_fetch() { - val(r#" -#[spirv(fragment)] -pub fn main(image: UniformConstant, mut output: Output) { - let texel = image.fetch(glam::IVec2::new(0, 1)); - *output = texel; -} -"#); -} - /// Helper to generate all of the `ptr_*` tests below, which test that the various /// ways to use raw pointer `read`/`write`/`copy`, to copy a single value, work, /// and that the resulting SPIR-V uses either a pair of `OpLoad` and `OpStore`, diff --git a/crates/spirv-builder/src/test/control_flow.rs b/crates/spirv-builder/src/test/control_flow.rs deleted file mode 100644 index 04594c7a70..0000000000 --- a/crates/spirv-builder/src/test/control_flow.rs +++ /dev/null @@ -1,423 +0,0 @@ -use super::val; - -#[test] -fn cf_while() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - } -} -"#); -} - -#[test] -fn cf_while_while() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 20 { - while *i < 10 { - } - } -} -"#); -} - -#[test] -fn cf_while_while_break() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 20 { - while *i < 10 { - break; - } - } -} -"#); -} - -#[test] -fn cf_while_while_if_break() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 20 { - while *i < 10 { - if *i > 10 { - break; - } - } - } -} -"#); -} - -#[test] -fn cf_while_break() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - break; - } -} -"#); -} - -#[test] -fn cf_while_if_break() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - if *i == 0 { - break; - } - } -} -"#); -} - -#[test] -fn cf_while_if_break_else_break() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - if *i == 0 { - break; - } else { - break; - } - } -} -"#); -} - -#[test] -fn cf_while_if_break_if_break() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - if *i == 0 { - break; - } - if *i == 1 { - break; - } - } -} -"#); -} - -#[test] -fn cf_while_while_continue() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 20 { - while *i < 10 { - continue; - } - } -} -"#); -} - -#[test] -fn cf_while_while_if_continue() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 20 { - while *i < 10 { - if *i > 5 { - continue; - } - } - } -} -"#); -} - -#[test] -fn cf_while_continue() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - continue; - } -} -"#); -} - -#[test] -fn cf_while_if_continue() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - if *i == 0 { - continue; - } - } -} -"#); -} - -#[test] -fn cf_while_if_continue_else_continue() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - if *i == 0 { - continue; - } else { - continue; - } - } -} -"#); -} - -#[test] -fn cf_while_return() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 10 { - return; - } -} -"#); -} - -#[test] -fn cf_if_return_else() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i < 10 { - return; - } else { - } -} -"#); -} - -#[test] -fn cf_if_return_else_return() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i < 10 { - return; - } else { - return; - } -} -"#); -} - -#[test] -fn cf_if_while() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i == 0 { - while *i < 10 { - } - } -} -"#); -} - -#[test] -fn cf_if() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i > 0 { - - } -} -"#); -} -#[test] -fn cf_ifx2() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i > 0 { - - } - if *i > 1 { - - } -} -"#); -} - -#[test] -fn cf_if_else() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i > 0 { - - } else { - - } -} -"#); -} - -#[test] -fn cf_if_elseif_else() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i > 0 { - - } else if *i < 0 { - - } else { - - } -} -"#); -} - -#[test] -fn cf_if_if() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - if *i > 0 { - if *i < 10 { - - } - } -} -"#); -} - -#[test] -fn cf_defer() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - while *i < 32 { - let current_position = 0; - if *i < current_position { - break; - } - if *i < current_position { - break; - } - } -} -"#); -} - -#[test] -fn issue_283() { - // version of issue 283 with loop uncommented and warnings fixed - // https://github.com/EmbarkStudios/rust-gpu/issues/283 - val(r#" -use glam::*; -fn sphere_sdf(p: Vec3) -> f32 { - p.length() - 1.0 -} - -// Global scene to render -fn scene_sdf(p: Vec3) -> f32 { - sphere_sdf(p) -} - -fn render(eye: Vec3, dir: Vec3, start: f32, end: f32) -> f32 { - let max_marching_steps: i32 = 255; - let epsilon: f32 = 0.0001; - - let mut depth = start; - let mut i = 0; - - loop { - if i < max_marching_steps { - break; - } - - let dist = scene_sdf(eye + depth * dir); - - if dist < epsilon { - return depth; - } - - depth += dist; - - if depth >= end { - return end; - } - - i += 1; - } - - end -} - -#[spirv(fragment)] -pub fn main() { - let v = Vec3::new(1.0, 1.0, 1.0); - render(v, v, 1.0, 2.0); -}"#); -} - -// NOTE(eddyb) this tests `for` loop desugaring (with its call to `Iterator::next` -// and matching on the resulting `Option`), without relying on a `Range` iterator. -// More precisely, `Range` used to not compile, due to it using `mem::replace`, -// which, before https://github.com/rust-lang/rust/pull/83022, used to just call -// `mem::swap` (which has a block-wise optimization that can't work on SPIR-V). -#[test] -fn cf_for_with_custom_range_iter() { - val(r#" -use num_traits::Num; -use core::ops::Range; - -struct RangeIter(Range); - -impl Iterator for RangeIter { - type Item = T; - fn next(&mut self) -> Option { - let x = self.0.start; - if x >= self.0.end { - None - } else { - self.0.start = x + T::one(); - Some(x) - } - } -} - -#[spirv(fragment)] -pub fn main(i: Input) { - for _ in RangeIter(0..*i) { - } -} -"#); -} - -#[test] -fn cf_for_range() { - val(r#" -#[spirv(fragment)] -pub fn main(i: Input) { - for _ in 0..*i { - } -} -"#); -} diff --git a/crates/spirv-builder/src/test/mod.rs b/crates/spirv-builder/src/test/mod.rs index e520c62522..0dc909ae0a 100644 --- a/crates/spirv-builder/src/test/mod.rs +++ b/crates/spirv-builder/src/test/mod.rs @@ -1,5 +1,4 @@ mod basic; -mod control_flow; use lazy_static::lazy_static; use rustc_codegen_spirv::rspirv; diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index c289604648..ff30c92f0b 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -1,8 +1,9 @@ # Summary - [Introduction](./introduction.md) -- [Contributing]() - - [Building Rust-GPU](./building-rust-gpu.md) +- [Contributing to Rust-GPU]() + - [Building](./building-rust-gpu.md) + - [Testing](./testing.md) - [Minimizing bugs in SPIR-V](./spirv-minimization.md) - [Platform Support](./platform-support.md) - [Writing Shader Crates](./writing-shader-crates.md) diff --git a/docs/src/testing.md b/docs/src/testing.md new file mode 100644 index 0000000000..fd566ecdf7 --- /dev/null +++ b/docs/src/testing.md @@ -0,0 +1,39 @@ +# Testing Rust-GPU + +Rust-GPU has a couple of different kinds of tests, most can be ran through +`cargo test`, however Rust-GPU also has end-to-end tests for compiling Rust and +validating its SPIR-V output, which can ran by running `cargo compiletest`. + +```bash +cargo test && cargo compiletest +``` + +## Adding Tests + +Rust-GPU's end-to-end test's use an external version of the [`compiletest`] tool +as a testing framework. Be sure to check out the [repository][`compiletest`] and +the [rustc Dev-Guide][rustc-dev-guide] for more information about how it works, +how to configure it, and add new tests. + +### Blessing Tests + +You will occassionally need to "bless" the output from UI tests to update the +normalised output, you can do this by passing a `--bless` flag to +`cargo compiletest`. + +`` +cargo compiletest -- --bless +`` + +### Caching Tests + +`cargo compiletest` by default caches the build output for dependencies of test +cases such as `spirv-std` and `glam`. If you need to compile from a fresh source +you can pass the `--clean` flag to build from scratch. + +`` +cargo compiletest -- --clean +`` + +[`compiletest`]: https://github.com/laumann/compiletest-rs +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/tests/intro.html diff --git a/tests/Cargo.lock b/tests/Cargo.lock deleted file mode 100644 index 22b522d3e0..0000000000 --- a/tests/Cargo.lock +++ /dev/null @@ -1,563 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "aho-corasick" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bimap" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92b72b8f03128773278bf74418b9205f3d2a12c39a61f92395f47af390c32bf" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "byteorder" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" - -[[package]] -name = "cc" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "compiletest-suite" -version = "0.0.0" -dependencies = [ - "compiletest_rs", - "rustc_codegen_spirv", -] - -[[package]] -name = "compiletest_rs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb" -dependencies = [ - "diff", - "filetime", - "getopts", - "lazy_static", - "libc", - "log", - "miow", - "regex", - "rustfix", - "serde", - "serde_derive", - "serde_json", - "tester", - "winapi", -] - -[[package]] -name = "derive_more" -version = "0.99.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "diff" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "filetime" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" - -[[package]] -name = "hermit-abi" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itoa" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" - -[[package]] -name = "jobserver" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" -dependencies = [ - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" - -[[package]] -name = "miow" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" -dependencies = [ - "socket2", - "winapi", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea78b9742c52ac729753c1590e9adc5248ea9bdaf974597efd46c74cfaa5fb54" - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom", - "redox_syscall", -] - -[[package]] -name = "regex" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-syntax" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" - -[[package]] -name = "rspirv" -version = "0.7.0" -source = "git+https://github.com/gfx-rs/rspirv.git?rev=ee1e913#ee1e9135845409b2a096d880286c865c4e2ac3d6" -dependencies = [ - "derive_more", - "fxhash", - "num-traits", - "spirv_headers", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" - -[[package]] -name = "rustc_codegen_spirv" -version = "0.3.0-alpha.0" -dependencies = [ - "bimap", - "indexmap", - "rspirv", - "rustc-demangle", - "serde", - "serde_json", - "smallvec", - "spirv-tools", - "tar", - "topological-sort", -] - -[[package]] -name = "rustfix" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c50b74badcddeb8f7652fa8323ce440b95286f8e4b64ebfd871c609672704e" -dependencies = [ - "anyhow", - "log", - "serde", - "serde_json", -] - -[[package]] -name = "rustversion" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" - -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - -[[package]] -name = "serde" -version = "1.0.123" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.123" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "smallvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" - -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if", - "libc", - "winapi", -] - -[[package]] -name = "spirv-tools" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "148f3d945efac91764e0000290017ec65674f34633cfad1d2c038b3bedd794e8" -dependencies = [ - "spirv-tools-sys", -] - -[[package]] -name = "spirv-tools-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c5e3026e72f862ac788d9f9bf703ae133045694e83a5bef102f6289fd62824" -dependencies = [ - "cc", -] - -[[package]] -name = "spirv_headers" -version = "1.5.0" -source = "git+https://github.com/gfx-rs/rspirv.git?rev=ee1e913#ee1e9135845409b2a096d880286c865c4e2ac3d6" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "syn" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tar" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0bcfbd6a598361fda270d82469fff3d65089dc33e175c9a131f7b4cd395f228" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "tester" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb" -dependencies = [ - "cfg-if", - "getopts", - "libc", - "num_cpus", - "term", -] - -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - -[[package]] -name = "topological-sort" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" - -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "xattr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -dependencies = [ - "libc", -] diff --git a/tests/Cargo.toml b/tests/Cargo.toml new file mode 100644 index 0000000000..89b07038be --- /dev/null +++ b/tests/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "compiletests" +version = "0.0.0" +authors = ["Embark "] +edition = "2018" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +compiletest = { version = "0.6.0", package = "compiletest_rs" } +rustc_codegen_spirv = { path = "../crates/rustc_codegen_spirv" } diff --git a/tests/src/main.rs b/tests/src/main.rs new file mode 100644 index 0000000000..c817ca4594 --- /dev/null +++ b/tests/src/main.rs @@ -0,0 +1,295 @@ +use std::{ + env, + io::{Error, ErrorKind, Result}, + path::{Path, PathBuf}, +}; + +const TARGET: &str = "spirv-unknown-unknown"; +const TARGET_DIR: &str = "target/compiletest"; +const TEST_DEPS_PATH: &str = "target/compiletest/test-deps"; +const TEST_DEPS_TOML_PATH: &str = "target/compiletest/test-deps/Cargo.toml"; +const SPIRV_STD_TARGET: &str = "target/compiletest/spirv-std"; +const SPIRV_STD_HOST_DEPS: &str = "target/compiletest/spirv-std/debug/deps"; +const SPIRV_STD_TARGET_DEPS: &str = "target/compiletest/spirv-std/spirv-unknown-unknown/debug/deps"; +const CARGO_TOML: &str = r#"[package] +name = "test-deps" +version = "0.1.0" +description = "Shared dependencies of all the tests" +authors = ["Embark "] +edition = "2018" + +[dependencies] +spirv-std = { path = "../../../crates/spirv-std", features=["const-generics"] } + +[dependencies.glam] +git = "https://github.com/bitshifter/glam-rs.git" +rev="b3e94fb" +default-features=false +features = ["libm", "scalar-math"] + +# Patch glam's dependency on spirv-std with our local version. +[patch.crates-io] +spirv-std-macros = { path = "../../../crates/spirv-std-macros" } +spirv-std = { path = "../../../crates/spirv-std" } + +[workspace] +"#; + +fn main() { + let manifest_dir = PathBuf::from("./"); + std::env::set_var("CARGO_MANIFEST_DIR", &manifest_dir); + // Pull in rustc_codegen_spirv as a dynamic library in the same way + // spirv-builder does. + let codegen_backend_path = find_rustc_codegen_spirv(); + let libs = build_spirv_std(&manifest_dir, &codegen_backend_path); + + run_mode("ui", &codegen_backend_path, &libs); +} + +/// Runs the given `mode` on the directory that matches that name, using the +/// backend provided by `codegen_backend_path`. +fn run_mode(mode: &'static str, codegen_backend_path: &Path, libs: &TestDeps) { + let mut config = compiletest::Config::default(); + + /// RUSTFLAGS passed to all test files. + fn test_rustc_flags(codegen_backend_path: &Path, deps: &TestDeps, libs: &[&Path]) -> String { + [ + &*rust_flags(codegen_backend_path), + &*libs + .iter() + .map(|p| format!("-L {}", p.display())) + .fold(String::new(), |a, b| b + " " + &a), + "--edition 2018", + &*format!("--extern noprelude:core={}", deps.core.display()), + &*format!( + "--extern noprelude:compiler_builtins={}", + deps.compiler_builtins.display() + ), + &*format!( + "--extern spirv_std_macros={}", + deps.spirv_std_macros.display() + ), + &*format!("--extern spirv_std={}", deps.spirv_std.display()), + &*format!("--extern glam={}", deps.glam.display()), + "--crate-type dylib", + "-Zunstable-options", + "-Zcrate-attr=no_std", + "-Zcrate-attr=feature(register_attr,asm)", + "-Zcrate-attr=register_attr(spirv)", + ] + .join(" ") + } + + let flags = test_rustc_flags( + codegen_backend_path, + libs, + &[ + &PathBuf::from(format!("dependency={}", SPIRV_STD_TARGET_DEPS)), + &PathBuf::from(format!("dependency={}", SPIRV_STD_HOST_DEPS)), + ], + ); + + config.target_rustcflags = Some(flags); + config.mode = mode.parse().expect("Invalid mode"); + config.target = String::from(TARGET); + config.src_base = PathBuf::from(format!("./tests/{}", mode)); + config.build_base = PathBuf::from(format!("./{}-results", TARGET_DIR)); + config.bless = std::env::args().any(|a| a == "--bless"); + config.clean_rmeta(); + + compiletest::run_tests(&config); +} + +/// Runs the processes needed to build `spirv-std`. +fn build_spirv_std(manifest_dir: &Path, codegen_backend_path: &Path) -> TestDeps { + let target_dir = format!("--target-dir={}", SPIRV_STD_TARGET); + + // Create a new test-deps project. + if std::fs::metadata(TEST_DEPS_PATH).is_err() { + std::process::Command::new("cargo") + .args(&["new", "-q", "--lib", TEST_DEPS_PATH]) + .current_dir(manifest_dir) + .stderr(std::process::Stdio::inherit()) + .stdout(std::process::Stdio::inherit()) + .status() + .and_then(map_status_to_result) + .unwrap(); + + std::fs::write(TEST_DEPS_TOML_PATH, CARGO_TOML.as_bytes()).unwrap(); + std::fs::write(PathBuf::from(TEST_DEPS_PATH).join("src/lib.rs"), "").unwrap(); + } + + // Build test-deps + std::process::Command::new("cargo") + .args(&[ + "build", + &*format!("--manifest-path={}", TEST_DEPS_TOML_PATH), + "-Zbuild-std=core", + &*format!("--target={}", TARGET), + &*target_dir, + ]) + .env( + "RUSTFLAGS", + rust_flags(&codegen_backend_path) + " -Zcrate-attr=no_std", + ) + .env("CARGO_MANIFEST_DIR", manifest_dir) + .current_dir(manifest_dir) + .stderr(std::process::Stdio::inherit()) + .stdout(std::process::Stdio::inherit()) + .status() + .and_then(map_status_to_result) + .unwrap(); + + let compiler_builtins = find_lib(SPIRV_STD_TARGET_DEPS, "libcompiler_builtins", false).unwrap(); + let core = find_lib(SPIRV_STD_TARGET_DEPS, "libcore", false).unwrap(); + let spirv_std = find_lib(SPIRV_STD_TARGET_DEPS, "libspirv_std", false).unwrap(); + let glam = find_lib(SPIRV_STD_TARGET_DEPS, "libglam", false).unwrap(); + let spirv_std_macros = find_lib(SPIRV_STD_HOST_DEPS, "spirv_std_macros", true).unwrap(); + + if [ + &compiler_builtins, + &core, + &spirv_std, + &glam, + &spirv_std_macros, + ] + .iter() + .any(|o| o.is_none()) + { + clean_project(manifest_dir); + build_spirv_std(manifest_dir, codegen_backend_path) + } else { + TestDeps { + core: core.unwrap(), + glam: glam.unwrap(), + compiler_builtins: compiler_builtins.unwrap(), + spirv_std: spirv_std.unwrap(), + spirv_std_macros: spirv_std_macros.unwrap(), + } + } +} + +fn clean_project(manifest_dir: &Path) { + std::process::Command::new("cargo") + .args(&["clean", &*format!("--target-dir={}", TARGET_DIR)]) + .current_dir(manifest_dir) + .stderr(std::process::Stdio::inherit()) + .stdout(std::process::Stdio::inherit()) + .status() + .and_then(map_status_to_result) + .unwrap(); +} + +/// Attempt find the rlib that matches `base`, if multiple rlibs are found +/// then a clean build is required and `None` is returned. +fn find_lib( + dir: impl AsRef, + base: impl AsRef, + dynamic: bool, +) -> Result> { + let base = base.as_ref(); + let expected_name = if dynamic { + format!("{}{}", env::consts::DLL_PREFIX, base.display()) + } else { + base.display().to_string() + }; + + let paths = std::fs::read_dir(dir.as_ref())? + .filter_map(Result::ok) + .map(|entry| entry.path()) + .filter(|path| { + let name = { + let name = path.file_name(); + if name.is_none() { + return false; + } + name.unwrap() + }; + + let name_matches = name.to_str().unwrap().starts_with(&expected_name); + let extension_matches = path.extension().map_or(false, |ext| { + if dynamic { + ext == env::consts::DLL_EXTENSION + } else { + ext == "rlib" + } + }); + + name_matches && extension_matches + }) + .collect::>(); + + Ok(if paths.len() > 1 { + None + } else { + paths.into_iter().next() + }) +} + +/// Paths to all of the library artifacts of dependencies needed to compile tests. +struct TestDeps { + core: PathBuf, + compiler_builtins: PathBuf, + spirv_std: PathBuf, + spirv_std_macros: PathBuf, + glam: PathBuf, +} + +/// The RUSTFLAGS passed to all SPIR-V builds. +fn rust_flags(codegen_backend_path: &Path) -> String { + [ + &*format!("-Zcodegen-backend={}", codegen_backend_path.display()), + "-Coverflow-checks=off", + "-Cdebug-assertions=off", + "-Cdebuginfo=2", + "-Cembed-bitcode=no", + ] + .join(" ") +} + +/// Convience function to map process failure to results in Rust. +fn map_status_to_result(status: std::process::ExitStatus) -> Result<()> { + match status.success() { + true => Ok(()), + false => Err(Error::new( + ErrorKind::Other, + format!( + "process terminated with non-zero code: {}", + status.code().unwrap_or(0) + ), + )), + } +} + +// https://github.com/rust-lang/cargo/blob/1857880b5124580c4aeb4e8bc5f1198f491d61b1/src/cargo/util/paths.rs#L29-L52 +fn dylib_path_envvar() -> &'static str { + if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_FALLBACK_LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + +fn dylib_path() -> Vec { + match env::var_os(dylib_path_envvar()) { + Some(var) => env::split_paths(&var).collect(), + None => Vec::new(), + } +} + +fn find_rustc_codegen_spirv() -> PathBuf { + let filename = format!( + "{}rustc_codegen_spirv{}", + env::consts::DLL_PREFIX, + env::consts::DLL_SUFFIX + ); + for mut path in dylib_path() { + path.push(&filename); + if path.is_file() { + return path; + } + } + panic!("Could not find {} in library path", filename); +} diff --git a/tests/ui/arch/all.rs b/tests/ui/arch/all.rs new file mode 100644 index 0000000000..1e7f8514d0 --- /dev/null +++ b/tests/ui/arch/all.rs @@ -0,0 +1,7 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let vector = glam::BVec2::new(true, true); + assert!(spirv_std::arch::all(vector)); +} diff --git a/tests/ui/arch/any.rs b/tests/ui/arch/any.rs new file mode 100644 index 0000000000..49bb8e5867 --- /dev/null +++ b/tests/ui/arch/any.rs @@ -0,0 +1,7 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let vector = glam::BVec2::new(true, false); + assert!(spirv_std::arch::any(vector)); +} diff --git a/tests/ui/arch/f_add.rs b/tests/ui/arch/f_add.rs new file mode 100644 index 0000000000..369301036e --- /dev/null +++ b/tests/ui/arch/f_add.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 5.0; + let y = 2.0; + let vx = glam::Vec2::new(2.0, 5.0); + let vy = glam::Vec2::new(5.0, 2.0); + assert!(spirv_std::arch::f_add_vector(vx, vy) == glam::Vec2::new(7.0, 7.0)); +} diff --git a/tests/ui/arch/f_div.rs b/tests/ui/arch/f_div.rs new file mode 100644 index 0000000000..12a9fa2d77 --- /dev/null +++ b/tests/ui/arch/f_div.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 10.0; + let y = 2.0; + let vx = glam::Vec2::new(10.0, 10.0); + let vy = glam::Vec2::new(2.0, 2.0); + assert!(spirv_std::arch::f_div_vector(vx, vy) == glam::Vec2::new(5.0, 5.0)); +} diff --git a/tests/ui/arch/f_mod.rs b/tests/ui/arch/f_mod.rs new file mode 100644 index 0000000000..34c4dad047 --- /dev/null +++ b/tests/ui/arch/f_mod.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 10.0; + let y = 2.0; + let vx = glam::Vec2::new(10.0, 10.0); + let vy = glam::Vec2::new(2.0, 2.0); + assert!(spirv_std::arch::f_mod_vector(vx, vy) == glam::Vec2::new(0.0, 0.0)); +} diff --git a/tests/ui/arch/f_mul.rs b/tests/ui/arch/f_mul.rs new file mode 100644 index 0000000000..d946d7bbb7 --- /dev/null +++ b/tests/ui/arch/f_mul.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 5.0; + let y = 2.0; + let vx = glam::Vec2::new(5.0, 2.0); + let vy = glam::Vec2::new(2.0, 5.0); + assert!(spirv_std::arch::f_mul_vector(vx, vy) == glam::Vec2::new(10.0, 10.0)); +} diff --git a/tests/ui/arch/f_negate.rs b/tests/ui/arch/f_negate.rs new file mode 100644 index 0000000000..064c5473b9 --- /dev/null +++ b/tests/ui/arch/f_negate.rs @@ -0,0 +1,8 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let operand: f32 = -5.0; + let vector = glam::Vec2::new(-5.0, -0.0); + assert!(spirv_std::arch::f_negate_vector(vector) == glam::Vec2::new(5.0, 0.0)); +} diff --git a/tests/ui/arch/f_rem.rs b/tests/ui/arch/f_rem.rs new file mode 100644 index 0000000000..77a370daff --- /dev/null +++ b/tests/ui/arch/f_rem.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = -10.0; + let y = -2.0; + let vx = glam::Vec2::new(-10.0, -10.0); + let vy = glam::Vec2::new(-2.0, -2.0); + assert!(spirv_std::arch::f_mod_vector(vx, vy) == glam::Vec2::new(-0.0, -0.0)); +} diff --git a/tests/ui/arch/f_sub.rs b/tests/ui/arch/f_sub.rs new file mode 100644 index 0000000000..21bbcc04c7 --- /dev/null +++ b/tests/ui/arch/f_sub.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 5.0; + let y = 5.0; + let vx = glam::Vec2::new(5.0, 7.0); + let vy = glam::Vec2::new(5.0, 7.0); + assert!(spirv_std::arch::f_sub_vector(vx, vy) == glam::Vec2::new(0.0, 0.0)); +} diff --git a/tests/ui/arch/i_add.rs b/tests/ui/arch/i_add.rs new file mode 100644 index 0000000000..5b4b39f291 --- /dev/null +++ b/tests/ui/arch/i_add.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 5; + let y = 2; + let vx = glam::IVec2::new(2, 5); + let vy = glam::IVec2::new(5, 2); + assert!(unsafe { spirv_std::arch::i_add_vector(vx, vy) } == glam::IVec2::new(7, 7)); +} diff --git a/tests/ui/arch/i_mul.rs b/tests/ui/arch/i_mul.rs new file mode 100644 index 0000000000..03257fce84 --- /dev/null +++ b/tests/ui/arch/i_mul.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 5; + let y = 2; + let vx = glam::IVec2::new(5, 2); + let vy = glam::IVec2::new(2, 5); + assert!(spirv_std::arch::i_mul_vector(vx, vy) == glam::IVec2::new(10, 10)); +} diff --git a/tests/ui/arch/i_sub.rs b/tests/ui/arch/i_sub.rs new file mode 100644 index 0000000000..e536ae191b --- /dev/null +++ b/tests/ui/arch/i_sub.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 5; + let y = 5; + let vx = glam::IVec2::new(5, 7); + let vy = glam::IVec2::new(5, 7); + assert!(spirv_std::arch::i_sub_vector(vx, vy) == glam::IVec2::new(0, 0)); +} diff --git a/tests/ui/arch/s_div.rs b/tests/ui/arch/s_div.rs new file mode 100644 index 0000000000..c10f867cd2 --- /dev/null +++ b/tests/ui/arch/s_div.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 10; + let y = 2; + let vx = glam::IVec2::new(10, 10); + let vy = glam::IVec2::new(2, 2); + assert!(unsafe { spirv_std::arch::s_div_vector(vx, vy) } == glam::IVec2::new(5, 5)); +} diff --git a/tests/ui/arch/s_mod.rs b/tests/ui/arch/s_mod.rs new file mode 100644 index 0000000000..04f443cf26 --- /dev/null +++ b/tests/ui/arch/s_mod.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = 10; + let y = 2; + let vx = glam::IVec2::new(10, 10); + let vy = glam::IVec2::new(2, 2); + assert!(spirv_std::arch::s_mod_vector(vx, vy) == glam::IVec2::new(0, 0)); +} diff --git a/tests/ui/arch/s_negate.rs b/tests/ui/arch/s_negate.rs new file mode 100644 index 0000000000..364c3c548b --- /dev/null +++ b/tests/ui/arch/s_negate.rs @@ -0,0 +1,8 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let operand: i32 = -5; + let vector = glam::IVec2::new(-5, -0); + assert!(spirv_std::arch::s_negate_vector(vector) == glam::IVec2::new(5, 0)); +} diff --git a/tests/ui/arch/s_rem.rs b/tests/ui/arch/s_rem.rs new file mode 100644 index 0000000000..f9ea07d812 --- /dev/null +++ b/tests/ui/arch/s_rem.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x = -10; + let y = -2; + let vx = glam::IVec2::new(-10, -10); + let vy = glam::IVec2::new(-2, -2); + assert!(spirv_std::arch::s_rem_vector(vx, vy) == glam::IVec2::new(-0, -0)); +} diff --git a/tests/ui/arch/u_div.rs b/tests/ui/arch/u_div.rs new file mode 100644 index 0000000000..5601eb45d4 --- /dev/null +++ b/tests/ui/arch/u_div.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x: u32 = 10; + let y = 2; + let vx = glam::UVec2::new(10, 10); + let vy = glam::UVec2::new(2, 2); + assert!(unsafe { spirv_std::arch::u_div_vector(vx, vy) } == glam::UVec2::new(5, 5)); +} diff --git a/tests/ui/arch/u_mod.rs b/tests/ui/arch/u_mod.rs new file mode 100644 index 0000000000..e6eef084e3 --- /dev/null +++ b/tests/ui/arch/u_mod.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let x: u32 = 10; + let y = 2; + let vx = glam::UVec2::new(10, 10); + let vy = glam::UVec2::new(2, 2); + assert!(spirv_std::arch::u_mod_vector(vx, vy) == glam::UVec2::new(0, 0)); +} diff --git a/tests/ui/arch/vector_extract_dynamic.rs b/tests/ui/arch/vector_extract_dynamic.rs new file mode 100644 index 0000000000..5dd4714474 --- /dev/null +++ b/tests/ui/arch/vector_extract_dynamic.rs @@ -0,0 +1,14 @@ +// Test `OpVectorExtractDynamic` +// build-pass + +use spirv_std::arch; + +#[spirv(fragment)] +pub fn main() { + let vector = glam::Vec2::new(1.0, 2.0); + let element = unsafe { arch::vector_extract_dynamic(vector, 1) }; + assert!(2.0 == element); + let uvector = glam::UVec2::new(1, 2); + let uelement = unsafe { arch::vector_extract_dynamic(uvector, 1) }; + assert!(2 == uelement); +} diff --git a/tests/ui/arch/vector_insert_dynamic.rs b/tests/ui/arch/vector_insert_dynamic.rs new file mode 100644 index 0000000000..d850313b22 --- /dev/null +++ b/tests/ui/arch/vector_insert_dynamic.rs @@ -0,0 +1,16 @@ +// Test `OpVectorInsertDynamic` +// build-pass + +use spirv_std::arch; + +#[spirv(fragment)] +pub fn main() { + let vector = glam::Vec2::new(1.0, 2.0); + let expected = glam::Vec2::new(1.0, 3.0); + let new_vector = unsafe { arch::vector_insert_dynamic(vector, 1, 3.0) }; + assert!(new_vector == expected); + let uvector = glam::UVec2::new(1, 2); + let uexpected = glam::UVec2::new(1, 3); + let unew_vector = unsafe { arch::vector_insert_dynamic(uvector, 1, 3) }; + assert!(unew_vector == uexpected); +} diff --git a/tests/ui/arch/vector_times_scalar.rs b/tests/ui/arch/vector_times_scalar.rs new file mode 100644 index 0000000000..a17b1db5ce --- /dev/null +++ b/tests/ui/arch/vector_times_scalar.rs @@ -0,0 +1,8 @@ +// build-pass + +#[spirv(fragment)] +pub fn main() { + let vector = glam::Vec2::new(10.0, 10.0); + let scalar = 2.0; + assert!(spirv_std::arch::vector_times_scalar(vector, scalar) == glam::Vec2::new(20.0, 20.0)); +} diff --git a/tests/ui/glam/mat3_vec3_multiply.rs b/tests/ui/glam/mat3_vec3_multiply.rs new file mode 100644 index 0000000000..cf2db69979 --- /dev/null +++ b/tests/ui/glam/mat3_vec3_multiply.rs @@ -0,0 +1,11 @@ +// Tests muiltplying a `Mat3` by a `Vec3`. +// build-pass + +use spirv_std::storage_class::{Input, Output}; + +#[spirv(fragment)] +pub fn main(input: Input, mut output: Output) { + let input = *input; + let vector = input * glam::Vec3::new(1.0, 2.0, 3.0); + *output = vector; +} diff --git a/tests/ui/hello_world.rs b/tests/ui/hello_world.rs new file mode 100644 index 0000000000..1ff5318711 --- /dev/null +++ b/tests/ui/hello_world.rs @@ -0,0 +1,8 @@ +// Simple single entrypoint function test. +// build-pass + +use spirv_std as _; + +#[spirv(fragment)] +pub fn main() { +} diff --git a/tests/ui/image/fetch.rs b/tests/ui/image/fetch.rs new file mode 100644 index 0000000000..6243462f56 --- /dev/null +++ b/tests/ui/image/fetch.rs @@ -0,0 +1,9 @@ +// build-pass + +use spirv_std::{arch, storage_class::{Output, UniformConstant}, Image2d}; + +#[spirv(fragment)] +pub fn main(image: UniformConstant, mut output: Output) { + let texel = image.fetch(glam::IVec2::new(0, 1)); + *output = texel; +} diff --git a/tests/ui/image/read.rs b/tests/ui/image/read.rs new file mode 100644 index 0000000000..81dcbaea7a --- /dev/null +++ b/tests/ui/image/read.rs @@ -0,0 +1,10 @@ +// Test `OpImageRead` +// build-pass + +use spirv_std::{arch, storage_class::{Output, UniformConstant}, StorageImage2d}; + +#[spirv(fragment)] +pub fn main(image: UniformConstant, mut output: Output) { + let coords = image.read(glam::IVec2::new(0, 1)); + *output = coords; +} diff --git a/tests/ui/image/write.rs b/tests/ui/image/write.rs new file mode 100644 index 0000000000..703392a520 --- /dev/null +++ b/tests/ui/image/write.rs @@ -0,0 +1,12 @@ +// Test `OpImageWrite` +// build-pass + +use spirv_std::{arch, storage_class::{Input, Output, UniformConstant}, StorageImage2d}; + +#[spirv(fragment)] +pub fn main(input: Input, image: UniformConstant) { + let texels = *input; + unsafe { + image.write(glam::UVec2::new(0, 1), texels); + } +} diff --git a/tests/ui/lang/asm/const_args.rs b/tests/ui/lang/asm/const_args.rs new file mode 100644 index 0000000000..df33d3b20c --- /dev/null +++ b/tests/ui/lang/asm/const_args.rs @@ -0,0 +1,20 @@ +// Tests using `asm!` with a const argument. +// build-pass + +use spirv_std as _; + +fn asm() { + unsafe { + const N: usize = 3; + asm!( + "%int = OpTypeInt 32 0", + "%type = OpTypeVector %int {len}", + len = const N, + ); + } +} + +#[spirv(fragment)] +pub fn main() { + asm(); +} diff --git a/tests/ui/lang/control_flow/defer.rs b/tests/ui/lang/control_flow/defer.rs new file mode 100644 index 0000000000..e1f38b3356 --- /dev/null +++ b/tests/ui/lang/control_flow/defer.rs @@ -0,0 +1,16 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 32 { + let current_position = 0; + if *i < current_position { + break; + } + if *i < current_position { + break; + } + } +} diff --git a/tests/ui/lang/control_flow/for_range.rs b/tests/ui/lang/control_flow/for_range.rs new file mode 100644 index 0000000000..90518fb169 --- /dev/null +++ b/tests/ui/lang/control_flow/for_range.rs @@ -0,0 +1,9 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + for _ in 0..*i { + } +} diff --git a/tests/ui/lang/control_flow/for_with_custom_range_iter.rs b/tests/ui/lang/control_flow/for_with_custom_range_iter.rs new file mode 100644 index 0000000000..6b0b9bbb6b --- /dev/null +++ b/tests/ui/lang/control_flow/for_with_custom_range_iter.rs @@ -0,0 +1,32 @@ +// NOTE(eddyb) this tests `for` loop desugaring (with its call to `Iterator::next` +// and matching on the resulting `Option`), without relying on a `Range` iterator. +// More precisely, `Range` used to not compile, due to it using `mem::replace`, +// which, before https://github.com/rust-lang/rust/pull/83022, used to just call +// `mem::swap` (which has a block-wise optimization that can't work on SPIR-V). + +// build-pass + +use spirv_std::{num_traits::Num, storage_class::Input}; +use core::ops::Range; + +struct RangeIter(Range); + +impl Iterator for RangeIter { + type Item = T; + fn next(&mut self) -> Option { + let x = self.0.start; + if x >= self.0.end { + None + } else { + self.0.start = x + T::one(); + Some(x) + } + } +} + +#[spirv(fragment)] +pub fn main(i: Input) { + for _ in RangeIter(0..*i) { + } +} + diff --git a/tests/ui/lang/control_flow/if.rs b/tests/ui/lang/control_flow/if.rs new file mode 100644 index 0000000000..bc9d966dfb --- /dev/null +++ b/tests/ui/lang/control_flow/if.rs @@ -0,0 +1,10 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i > 0 { + + } +} diff --git a/tests/ui/lang/control_flow/if_else.rs b/tests/ui/lang/control_flow/if_else.rs new file mode 100644 index 0000000000..51aaf34935 --- /dev/null +++ b/tests/ui/lang/control_flow/if_else.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i > 0 { + + } else { + + } +} diff --git a/tests/ui/lang/control_flow/if_else_if_else.rs b/tests/ui/lang/control_flow/if_else_if_else.rs new file mode 100644 index 0000000000..27f5fe0c7b --- /dev/null +++ b/tests/ui/lang/control_flow/if_else_if_else.rs @@ -0,0 +1,14 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i > 0 { + + } else if *i < 0 { + + } else { + + } +} diff --git a/tests/ui/lang/control_flow/if_if.rs b/tests/ui/lang/control_flow/if_if.rs new file mode 100644 index 0000000000..e1983f5616 --- /dev/null +++ b/tests/ui/lang/control_flow/if_if.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i > 0 { + if *i < 10 { + + } + } +} diff --git a/tests/ui/lang/control_flow/if_return_else.rs b/tests/ui/lang/control_flow/if_return_else.rs new file mode 100644 index 0000000000..c121e162b5 --- /dev/null +++ b/tests/ui/lang/control_flow/if_return_else.rs @@ -0,0 +1,11 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i < 10 { + return; + } else { + } +} diff --git a/tests/ui/lang/control_flow/if_return_else_return.rs b/tests/ui/lang/control_flow/if_return_else_return.rs new file mode 100644 index 0000000000..ef04abcb94 --- /dev/null +++ b/tests/ui/lang/control_flow/if_return_else_return.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i < 10 { + return; + } else { + return; + } +} diff --git a/tests/ui/lang/control_flow/if_while.rs b/tests/ui/lang/control_flow/if_while.rs new file mode 100644 index 0000000000..131f895d03 --- /dev/null +++ b/tests/ui/lang/control_flow/if_while.rs @@ -0,0 +1,11 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i == 0 { + while *i < 10 { + } + } +} diff --git a/tests/ui/lang/control_flow/ifx2.rs b/tests/ui/lang/control_flow/ifx2.rs new file mode 100644 index 0000000000..9c7832dc83 --- /dev/null +++ b/tests/ui/lang/control_flow/ifx2.rs @@ -0,0 +1,13 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + if *i > 0 { + + } + if *i > 1 { + + } +} diff --git a/tests/ui/lang/control_flow/issue_283.rs b/tests/ui/lang/control_flow/issue_283.rs new file mode 100644 index 0000000000..b6f923ed3b --- /dev/null +++ b/tests/ui/lang/control_flow/issue_283.rs @@ -0,0 +1,48 @@ +// build-pass + +use glam::*; + +fn sphere_sdf(p: Vec3) -> f32 { + p.length() - 1.0 +} + +// Global scene to render +fn scene_sdf(p: Vec3) -> f32 { + sphere_sdf(p) +} + +fn render(eye: Vec3, dir: Vec3, start: f32, end: f32) -> f32 { + let max_marching_steps: i32 = 255; + let epsilon: f32 = 0.0001; + + let mut depth = start; + let mut i = 0; + + loop { + if i < max_marching_steps { + break; + } + + let dist = scene_sdf(eye + depth * dir); + + if dist < epsilon { + return depth; + } + + depth += dist; + + if depth >= end { + return end; + } + + i += 1; + } + + end +} + +#[spirv(fragment)] +pub fn main() { + let v = Vec3::new(1.0, 1.0, 1.0); + render(v, v, 1.0, 2.0); +} diff --git a/tests/ui/lang/control_flow/loop.rs b/tests/ui/lang/control_flow/loop.rs new file mode 100644 index 0000000000..cb2332e78e --- /dev/null +++ b/tests/ui/lang/control_flow/loop.rs @@ -0,0 +1,8 @@ +// build-pass + +use spirv_std as _; + +#[spirv(fragment)] +pub fn main() { + loop {} +} diff --git a/tests/ui/lang/control_flow/while.rs b/tests/ui/lang/control_flow/while.rs new file mode 100644 index 0000000000..442e13e29c --- /dev/null +++ b/tests/ui/lang/control_flow/while.rs @@ -0,0 +1,9 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + } +} diff --git a/tests/ui/lang/control_flow/while_break.rs b/tests/ui/lang/control_flow/while_break.rs new file mode 100644 index 0000000000..166047817e --- /dev/null +++ b/tests/ui/lang/control_flow/while_break.rs @@ -0,0 +1,10 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + break; + } +} diff --git a/tests/ui/lang/control_flow/while_continue.rs b/tests/ui/lang/control_flow/while_continue.rs new file mode 100644 index 0000000000..b1a8bcd708 --- /dev/null +++ b/tests/ui/lang/control_flow/while_continue.rs @@ -0,0 +1,10 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + continue; + } +} diff --git a/tests/ui/lang/control_flow/while_if_break.rs b/tests/ui/lang/control_flow/while_if_break.rs new file mode 100644 index 0000000000..5f01f6f132 --- /dev/null +++ b/tests/ui/lang/control_flow/while_if_break.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + if *i == 0 { + break; + } + } +} diff --git a/tests/ui/lang/control_flow/while_if_break_else_break.rs b/tests/ui/lang/control_flow/while_if_break_else_break.rs new file mode 100644 index 0000000000..378c39b7b8 --- /dev/null +++ b/tests/ui/lang/control_flow/while_if_break_else_break.rs @@ -0,0 +1,14 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + if *i == 0 { + break; + } else { + break; + } + } +} diff --git a/tests/ui/lang/control_flow/while_if_break_if_break.rs b/tests/ui/lang/control_flow/while_if_break_if_break.rs new file mode 100644 index 0000000000..61ad54f5ba --- /dev/null +++ b/tests/ui/lang/control_flow/while_if_break_if_break.rs @@ -0,0 +1,15 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + if *i == 0 { + break; + } + if *i == 1 { + break; + } + } +} diff --git a/tests/ui/lang/control_flow/while_if_continue.rs b/tests/ui/lang/control_flow/while_if_continue.rs new file mode 100644 index 0000000000..714f924886 --- /dev/null +++ b/tests/ui/lang/control_flow/while_if_continue.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + if *i == 0 { + continue; + } + } +} diff --git a/tests/ui/lang/control_flow/while_if_continue_else_continue.rs b/tests/ui/lang/control_flow/while_if_continue_else_continue.rs new file mode 100644 index 0000000000..ddcdd731a4 --- /dev/null +++ b/tests/ui/lang/control_flow/while_if_continue_else_continue.rs @@ -0,0 +1,14 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + if *i == 0 { + continue; + } else { + continue; + } + } +} diff --git a/tests/ui/lang/control_flow/while_return.rs b/tests/ui/lang/control_flow/while_return.rs new file mode 100644 index 0000000000..f30fdd7a72 --- /dev/null +++ b/tests/ui/lang/control_flow/while_return.rs @@ -0,0 +1,10 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 10 { + return; + } +} diff --git a/tests/ui/lang/control_flow/while_while.rs b/tests/ui/lang/control_flow/while_while.rs new file mode 100644 index 0000000000..24ece06d2d --- /dev/null +++ b/tests/ui/lang/control_flow/while_while.rs @@ -0,0 +1,11 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 20 { + while *i < 10 { + } + } +} diff --git a/tests/ui/lang/control_flow/while_while_break.rs b/tests/ui/lang/control_flow/while_while_break.rs new file mode 100644 index 0000000000..758e450e95 --- /dev/null +++ b/tests/ui/lang/control_flow/while_while_break.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 20 { + while *i < 10 { + break; + } + } +} diff --git a/tests/ui/lang/control_flow/while_while_continue.rs b/tests/ui/lang/control_flow/while_while_continue.rs new file mode 100644 index 0000000000..dfb2e57d46 --- /dev/null +++ b/tests/ui/lang/control_flow/while_while_continue.rs @@ -0,0 +1,12 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 20 { + while *i < 10 { + continue; + } + } +} diff --git a/tests/ui/lang/control_flow/while_while_if_break.rs b/tests/ui/lang/control_flow/while_while_if_break.rs new file mode 100644 index 0000000000..0f4a47b5ee --- /dev/null +++ b/tests/ui/lang/control_flow/while_while_if_break.rs @@ -0,0 +1,14 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 20 { + while *i < 10 { + if *i > 10 { + break; + } + } + } +} diff --git a/tests/ui/lang/control_flow/while_while_if_continue.rs b/tests/ui/lang/control_flow/while_while_if_continue.rs new file mode 100644 index 0000000000..b9c4341478 --- /dev/null +++ b/tests/ui/lang/control_flow/while_while_if_continue.rs @@ -0,0 +1,14 @@ +// build-pass + +use spirv_std::storage_class::Input; + +#[spirv(fragment)] +pub fn main(i: Input) { + while *i < 20 { + while *i < 10 { + if *i > 5 { + continue; + } + } + } +} diff --git a/tests/ui/lang/core/mem/create_unitialized_memory.rs b/tests/ui/lang/core/mem/create_unitialized_memory.rs new file mode 100644 index 0000000000..ae0a2817f6 --- /dev/null +++ b/tests/ui/lang/core/mem/create_unitialized_memory.rs @@ -0,0 +1,16 @@ +// Test creating unitialized memory. +// build-pass + +use spirv_std as _; + +use core::mem::MaybeUninit; +const MAYBEI32: MaybeUninit<&i32> = MaybeUninit::<&i32>::uninit(); + +pub fn create_uninit_and_write() { + let mut maybei32 = MAYBEI32; + unsafe { maybei32.as_mut_ptr().write(&0); } + let _maybei32 = unsafe { maybei32.assume_init() }; +} + +#[spirv(fragment)] +pub fn main() {} diff --git a/tests/ui/lang/core/ops/logical_and.rs b/tests/ui/lang/core/ops/logical_and.rs new file mode 100644 index 0000000000..158845dccb --- /dev/null +++ b/tests/ui/lang/core/ops/logical_and.rs @@ -0,0 +1,13 @@ +// Test using `&&` operator. +// build-pass + +extern crate spirv_std; + +fn f(x: bool, y: bool) -> bool { + x && y +} + +#[spirv(fragment)] +pub fn main() { + f(false, true); +} diff --git a/tests/ui/lang/core/ptr/allocate_const_scalar.rs b/tests/ui/lang/core/ptr/allocate_const_scalar.rs new file mode 100644 index 0000000000..d5981fe4fe --- /dev/null +++ b/tests/ui/lang/core/ptr/allocate_const_scalar.rs @@ -0,0 +1,16 @@ +// Doesn't work, only worked before because I think it got optimized away before +// hitting the backend. + +// build-fail + +#![feature(ptr_internals)] + +use spirv_std::storage_class::Output; + +use core::ptr::Unique; +const POINTER: Unique<[u8;4]> = Unique::<[u8; 4]>::dangling(); + +#[spirv(fragment)] +pub fn main(mut output: Output) { + let _pointer = POINTER; +} diff --git a/tests/ui/lang/core/ptr/allocate_const_scalar.stderr b/tests/ui/lang/core/ptr/allocate_const_scalar.stderr new file mode 100644 index 0000000000..3bb4366b16 --- /dev/null +++ b/tests/ui/lang/core/ptr/allocate_const_scalar.stderr @@ -0,0 +1,13 @@ +error: pointer has non-null integer address + | + = note: Stack: + allocate_const_scalar::main + Unnamed function ID %9 + +error: invalid binary:0:0 - No OpEntryPoint instruction was found. This is only allowed if the Linkage capability is being used. + | + = note: spirv-val failed + = note: module "./target/compiletest-results/lang/core/ptr/allocate_const_scalar.stage-id.spv" + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lang/core/ptr/allocate_null.rs b/tests/ui/lang/core/ptr/allocate_null.rs new file mode 100644 index 0000000000..1ada08585d --- /dev/null +++ b/tests/ui/lang/core/ptr/allocate_null.rs @@ -0,0 +1,12 @@ +// Tests allocating a null pointer at `const` time. +// build-pass + +use spirv_std as _; + +use core::ptr::null; +const NULL_PTR: *const i32 = null(); + +#[spirv(fragment)] +pub fn main() { + let _null_ptr = NULL_PTR; +} diff --git a/tests/ui/lang/core/ptr/allocate_vec_like.rs b/tests/ui/lang/core/ptr/allocate_vec_like.rs new file mode 100644 index 0000000000..71d21ec1ab --- /dev/null +++ b/tests/ui/lang/core/ptr/allocate_vec_like.rs @@ -0,0 +1,16 @@ +// Tests using a vector like pointer at `const` time. +// build-pass + +#![feature(ptr_internals)] + +use spirv_std as _; + +use core::ptr::Unique; +const VEC_LIKE: (Unique, usize, usize) = (Unique::::dangling(), 0, 0); + +pub fn assign_vec_like() { + let _vec_like = VEC_LIKE; +} + +#[spirv(fragment)] +pub fn main() {} diff --git a/tests/ui/lang/f32/signum.rs b/tests/ui/lang/f32/signum.rs new file mode 100644 index 0000000000..5825026132 --- /dev/null +++ b/tests/ui/lang/f32/signum.rs @@ -0,0 +1,10 @@ +// Test that `signum` works. +// build-pass + +use spirv_std::storage_class::{Input, Output}; +use spirv_std::num_traits::Float; + +#[spirv(fragment)] +pub fn main(i: Input, mut o: Output) { + *o = (*i).signum(); +} diff --git a/tests/ui/lang/panic/builtin.rs b/tests/ui/lang/panic/builtin.rs new file mode 100644 index 0000000000..6e6e2bf2f2 --- /dev/null +++ b/tests/ui/lang/panic/builtin.rs @@ -0,0 +1,13 @@ +// Test panics coming from the Rust language such as `1 / 0`. +// build-pass + +use spirv_std as _; + +fn int_div(x: usize) -> usize { + 1 / x +} + +#[spirv(fragment)] +pub fn main() { + int_div(0); +} diff --git a/tests/ui/lang/panic/builtin_bounds_check.rs b/tests/ui/lang/panic/builtin_bounds_check.rs new file mode 100644 index 0000000000..42168cf078 --- /dev/null +++ b/tests/ui/lang/panic/builtin_bounds_check.rs @@ -0,0 +1,13 @@ +// Test that bounds checking causes panics. +// build-pass + +use spirv_std as _; + +fn array_bounds_check(x: [u32; 4], i: usize) -> u32 { + x[i] +} + +#[spirv(fragment)] +pub fn main() { + array_bounds_check([0, 1, 2, 3], 5); +} diff --git a/tests/ui/lang/panic/simple.rs b/tests/ui/lang/panic/simple.rs new file mode 100644 index 0000000000..5b80682cf9 --- /dev/null +++ b/tests/ui/lang/panic/simple.rs @@ -0,0 +1,9 @@ +// Test that calling `panic!` works. +// build-pass + +use spirv_std as _; + +#[spirv(fragment)] +pub fn main() { + panic!("aaa"); +} diff --git a/tests/ui/storage_class/push_constant.rs b/tests/ui/storage_class/push_constant.rs new file mode 100644 index 0000000000..d74ed0412f --- /dev/null +++ b/tests/ui/storage_class/push_constant.rs @@ -0,0 +1,21 @@ +// Test that using push constants work. +// NOTE(eddyb) this won't pass Vulkan validation (see `push_constant_vulkan`), +// but should still pass the baseline SPIR-V validation. + +// build-pass + +extern crate spirv_std; +use spirv_std::storage_class::PushConstant; + + +#[derive(Copy, Clone)] +pub struct ShaderConstants { + pub width: u32, + pub height: u32, + pub time: f32, +} + +#[spirv(fragment)] +pub fn main(constants: PushConstant) { + let _constants = *constants; +}