From 2904a2ac10349775c0812d2ef944abeba92e02d1 Mon Sep 17 00:00:00 2001 From: chyyran Date: Fri, 23 Aug 2024 00:56:56 -0400 Subject: [PATCH] test(d3d11): Add D3D11 triangle test to image --- Cargo.lock | 369 ++++++++++++++++++++++++- Cargo.toml | 2 +- librashader-test/Cargo.toml | 35 +++ librashader-test/src/lib.rs | 16 ++ librashader-test/src/triangle/d3d11.rs | 219 +++++++++++++++ librashader-test/src/triangle/mod.rs | 37 +++ 6 files changed, 675 insertions(+), 3 deletions(-) create mode 100644 librashader-test/Cargo.toml create mode 100644 librashader-test/src/lib.rs create mode 100644 librashader-test/src/triangle/d3d11.rs create mode 100644 librashader-test/src/triangle/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1dcd575..fe2145f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,6 +63,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "allocator-api2" version = "0.2.18" @@ -154,12 +160,35 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "arc-swap" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "array-concat" version = "0.5.3" @@ -239,6 +268,29 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] + [[package]] name = "base64" version = "0.13.1" @@ -279,6 +331,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" @@ -291,6 +349,12 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "bitstream-io" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" + [[package]] name = "bitvec" version = "1.0.1" @@ -365,6 +429,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" +[[package]] +name = "built" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" + [[package]] name = "bumpalo" version = "3.16.0" @@ -457,7 +527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" dependencies = [ "clap", - "heck", + "heck 0.4.1", "indexmap", "log", "proc-macro2", @@ -486,6 +556,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -528,7 +608,7 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 2.0.77", @@ -784,6 +864,12 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -946,6 +1032,22 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide 0.7.4", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fastrand" version = "2.1.1" @@ -977,6 +1079,15 @@ dependencies = [ "miniz_oxide 0.8.0", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -1243,6 +1354,16 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "halfbrown" version = "0.2.5" @@ -1292,6 +1413,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.4.0" @@ -1330,10 +1457,15 @@ dependencies = [ "bytemuck", "byteorder-lite", "color_quant", + "exr", "gif", "image-webp", "num-traits", "png", + "qoi", + "ravif", + "rayon", + "rgb", "tiff", "zune-core", "zune-jpeg", @@ -1349,6 +1481,12 @@ dependencies = [ "quick-error", ] +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + [[package]] name = "indexmap" version = "2.5.0" @@ -1359,6 +1497,17 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "is-terminal" version = "0.4.13" @@ -1370,6 +1519,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1456,12 +1614,29 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "libc" version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + [[package]] name = "libloading" version = "0.8.5" @@ -1769,6 +1944,23 @@ dependencies = [ "winit", ] +[[package]] +name = "librashader-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "ash", + "gfx-maths", + "image", + "librashader", + "librashader-runtime", + "objc2 0.5.2", + "objc2-metal", + "wgpu", + "wgpu-types", + "windows 0.58.0", +] + [[package]] name = "libredox" version = "0.0.2" @@ -1824,6 +2016,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "mach-siegbert-vogt-dxcsa" version = "0.1.3" @@ -1842,6 +2043,15 @@ dependencies = [ "libc", ] +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.7.4" @@ -1950,6 +2160,12 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nom" version = "7.1.3" @@ -1971,6 +2187,12 @@ dependencies = [ "nom", ] +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + [[package]] name = "num" version = "0.4.3" @@ -2462,6 +2684,28 @@ name = "profiling" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn 2.0.77", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] [[package]] name = "quick-error" @@ -2529,6 +2773,55 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f0bfd976333248de2078d350bfdf182ff96e168a24d23d2436cef320dd4bdd" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.4.3" @@ -2655,6 +2948,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +dependencies = [ + "bytemuck", +] + [[package]] name = "ron" version = "0.7.1" @@ -2815,6 +3117,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "slab" version = "0.4.9" @@ -2884,6 +3195,15 @@ dependencies = [ "serde", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -3000,12 +3320,31 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.19", + "version-compare", +] + [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "tempfile" version = "3.12.0" @@ -3197,12 +3536,29 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + [[package]] name = "vec_extract_if_polyfill" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c9cb5fb67c2692310b6eb3fce7dd4b6e4c9a75be4f2f46b27f0b2b7799759c" +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "version_check" version = "0.9.5" @@ -4047,6 +4403,15 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + [[package]] name = "zune-jpeg" version = "0.4.13" diff --git a/Cargo.toml b/Cargo.toml index b1a3663..cfda6b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = [ "librashader-runtime-wgpu", "librashader-cache", "librashader-capi", - "librashader-build-script", "librashader-runtime-d3d9"] + "librashader-build-script", "librashader-runtime-d3d9", "librashader-test"] resolver = "2" [workspace.dependencies] diff --git a/librashader-test/Cargo.toml b/librashader-test/Cargo.toml new file mode 100644 index 0000000..76e1e8e --- /dev/null +++ b/librashader-test/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "librashader-test" +version = "0.1.0" +edition = "2021" + +[dependencies] +librashader = { version = "0.4.5", path = "../librashader" } +librashader-runtime = { version = "0.4.5", path = "../librashader-runtime"} +wgpu = { version = "22", default-features = false } +wgpu-types = { version = "22" } +anyhow = "1.0.86" +image = "0.25.2" +gfx-maths = "0.2.8" + +ash = "0.38.0+1.3.281" + +[target.'cfg(windows)'.dependencies.windows] +workspace = true +features = [ + "Win32_Foundation", + "Win32_Graphics_Dxgi_Common", + "Win32_Graphics_Direct3D", + "Win32_Graphics_Direct3D11", + "Win32_Graphics_Direct3D_Fxc", + "Win32_Graphics_Gdi", + "Win32_Security", + "Win32_System_LibraryLoader", + "Win32_System_Threading", + "Win32_UI_WindowsAndMessaging", + "Win32_UI", +] + +[target.'cfg(target_vendor="apple")'.dependencies] +objc2-metal = { version = "0.2.0" , features = [ "all" ] } +objc2 = { version = "0.5.0", features = ["apple"] } \ No newline at end of file diff --git a/librashader-test/src/lib.rs b/librashader-test/src/lib.rs new file mode 100644 index 0000000..470bcfe --- /dev/null +++ b/librashader-test/src/lib.rs @@ -0,0 +1,16 @@ +mod triangle; + +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/librashader-test/src/triangle/d3d11.rs b/librashader-test/src/triangle/d3d11.rs new file mode 100644 index 0000000..bf2ab75 --- /dev/null +++ b/librashader-test/src/triangle/d3d11.rs @@ -0,0 +1,219 @@ +use crate::render::RenderTest; +use anyhow::anyhow; +use image::RgbaImage; +use librashader::runtime::d3d11::*; +use librashader::runtime::{Size, Viewport}; +use std::path::Path; + +impl RenderTest for Direct3D11 { + fn render(&self, path: impl AsRef, frame_count: usize) -> anyhow::Result { + let (renderbuffer, rtv) = self.create_renderbuffer(self.image_bytes.size)?; + + unsafe { + let mut filter_chain = FilterChain::load_from_path( + path, + &self.device, + Some(&FilterChainOptions { + force_no_mipmaps: false, + disable_cache: true, + }), + )?; + filter_chain.frame( + None, + &self.image_srv, + &Viewport::new_render_target_sized_origin(rtv, None)?, + frame_count, + None, + )?; + + let mut renderbuffer_desc = Default::default(); + renderbuffer.GetDesc(&mut renderbuffer_desc); + + self.immediate_context.Flush(); + + let mut staging = None; + self.device.CreateTexture2D( + &D3D11_TEXTURE2D_DESC { + MipLevels: 1, + BindFlags: 0, + MiscFlags: 0, + Usage: D3D11_USAGE_STAGING, + CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32, + ..renderbuffer_desc + }, + None, + Some(&mut staging), + )?; + + let staging = staging.ok_or(anyhow!("Unable to create staging texture"))?; + + self.immediate_context.CopyResource(&staging, &renderbuffer); + + let mut map_info = Default::default(); + self.immediate_context + .Map(&staging, 0, D3D11_MAP_READ, 0, Some(&mut map_info))?; + + let slice = std::slice::from_raw_parts( + map_info.pData as *const u8, + (renderbuffer_desc.Height * map_info.RowPitch) as usize, + ); + + let image = RgbaImage::from_raw( + renderbuffer_desc.Width, + renderbuffer_desc.Height, + Vec::from(slice), + ) + .ok_or(anyhow!("Unable to create image from data"))?; + self.immediate_context.Unmap(&staging, 0); + + Ok(image) + } + } +} + +use librashader_runtime::image::{Image, UVDirection}; +use windows::{ + Win32::Foundation::*, Win32::Graphics::Direct3D::*, Win32::Graphics::Direct3D11::*, + Win32::Graphics::Dxgi::Common::*, Win32::Graphics::Dxgi::*, +}; + +pub struct Direct3D11 { + device: ID3D11Device, + immediate_context: ID3D11DeviceContext, + image_tex: ID3D11Texture2D, + image_srv: ID3D11ShaderResourceView, + image_bytes: Image, +} + +impl Direct3D11 { + fn create_device() -> anyhow::Result<(IDXGIFactory4, ID3D11Device, ID3D11DeviceContext)> { + let dxgi_factory: IDXGIFactory4 = unsafe { CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG) }?; + let feature_levels = vec![D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]; + + let mut out_device = None; + let mut out_context = None; + let mut _out_feature_level = D3D_FEATURE_LEVEL_11_0; + + unsafe { + D3D11CreateDevice( + None, + D3D_DRIVER_TYPE_HARDWARE, + HMODULE::default(), + D3D11_CREATE_DEVICE_DEBUG, + Some(&feature_levels), + D3D11_SDK_VERSION, + Some(&mut out_device), + Some(&mut _out_feature_level), + Some(&mut out_context), + ) + }?; + Ok((dxgi_factory, out_device.unwrap(), out_context.unwrap())) + } + + pub fn new(image_path: impl AsRef) -> anyhow::Result { + let (_factory, device, imm_context) = Self::create_device()?; + + let (image, image_tex, srv) = Self::load_image(&device, image_path)?; + Ok(Self { + device, + immediate_context: imm_context, + image_bytes: image, + image_tex, + image_srv: srv, + }) + } + + fn load_image( + device: &ID3D11Device, + image_path: impl AsRef, + ) -> anyhow::Result<(Image, ID3D11Texture2D, ID3D11ShaderResourceView)> { + let image = Image::load(image_path, UVDirection::TopLeft)?; + let mut desc = D3D11_TEXTURE2D_DESC { + Width: image.size.width, + Height: image.size.height, + // todo: set this to 0 + MipLevels: 1, + ArraySize: 1, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + CPUAccessFlags: 0, + Format: DXGI_FORMAT_R8G8B8A8_UNORM, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32, + ..Default::default() + }; + + unsafe { + let mut resource = None; + device.CreateTexture2D( + &desc, + Some(&D3D11_SUBRESOURCE_DATA { + pSysMem: image.bytes.as_ptr().cast(), + SysMemPitch: image.pitch as u32, + SysMemSlicePitch: 0, + }), + Some(&mut resource), + )?; + let resource = resource.ok_or(anyhow!("Failed to create texture"))?; + + let mut srv = None; + device.CreateShaderResourceView( + &resource, + Some(&D3D11_SHADER_RESOURCE_VIEW_DESC { + Format: desc.Format, + ViewDimension: D3D_SRV_DIMENSION_TEXTURE2D, + Anonymous: D3D11_SHADER_RESOURCE_VIEW_DESC_0 { + Texture2D: D3D11_TEX2D_SRV { + MostDetailedMip: 0, + MipLevels: u32::MAX, + }, + }, + }), + Some(&mut srv), + )?; + + let srv = srv.ok_or(anyhow!("Failed to create SRV"))?; + + Ok((image, resource, srv)) + } + } + + fn create_renderbuffer( + &self, + size: Size, + ) -> anyhow::Result<(ID3D11Texture2D, ID3D11RenderTargetView)> { + let desc = D3D11_TEXTURE2D_DESC { + Width: size.width, + Height: size.height, + // todo: set this to 0 + MipLevels: 1, + ArraySize: 1, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + CPUAccessFlags: 0, + Format: DXGI_FORMAT_R8G8B8A8_UNORM, + Usage: D3D11_USAGE_DEFAULT, + BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32, + ..Default::default() + }; + + unsafe { + let mut resource = None; + self.device + .CreateTexture2D(&desc, None, Some(&mut resource))?; + let resource = resource.ok_or(anyhow!("Failed to create texture"))?; + + let mut rtv = None; + self.device + .CreateRenderTargetView(&resource, None, Some(&mut rtv))?; + + let rtv = rtv.ok_or(anyhow!("Failed to create RTV"))?; + + Ok((resource, rtv)) + } + } +} diff --git a/librashader-test/src/triangle/mod.rs b/librashader-test/src/triangle/mod.rs new file mode 100644 index 0000000..cf98831 --- /dev/null +++ b/librashader-test/src/triangle/mod.rs @@ -0,0 +1,37 @@ +mod d3d11; + +use std::path::Path; + +/// Test harness to set up a device, render a triangle, and apply a shader +pub trait TriangleTest { + /// Render a triangle to an image buffer, applying the provided shader. + /// + /// The test should render in linear colour space for proper comparison against + /// backends. + fn triangle( + &self, + image: impl AsRef, + path: impl AsRef, + frame_count: usize, + ) -> anyhow::Result; +} + +#[cfg(test)] +mod test { + use crate::triangle::TriangleTest; + use image::codecs::png::PngEncoder; + use std::fs::File; + + const IMAGE_PATH: &str = "../triangle.png"; + const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp"; + + #[test] + pub fn test_d3d11() -> anyhow::Result<()> { + let d3d11 = super::d3d11::Direct3D11::new()?; + let image = d3d11.triangle(IMAGE_PATH, FILTER_PATH, 100)?; + + let out = File::create("out.png")?; + image.write_with_encoder(PngEncoder::new(out))?; + Ok(()) + } +}