diff --git a/Cargo.lock b/Cargo.lock index 48923e5..e82d1ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,21 @@ dependencies = [ "equator", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -46,7 +61,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -64,6 +79,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -113,6 +137,21 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "bit-set" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + [[package]] name = "bit_field" version = "0.10.3" @@ -143,6 +182,15 @@ dependencies = [ "no_std_io2", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "built" version = "0.8.1" @@ -172,7 +220,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -261,6 +309,23 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -328,6 +393,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.0", + "objc2", +] + [[package]] name = "displaydoc" version = "0.2.6" @@ -336,7 +411,25 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", ] [[package]] @@ -349,24 +442,12 @@ checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" name = "enkou-shaders" version = "0.1.0" dependencies = [ - "anyhow", "bytemuck", "glam", - "image", "libm", "rand 0.10.1", "rand_xoshiro", "spirv-std", - "tempfile", -] - -[[package]] -name = "enkou-shaders-tests" -version = "0.1.0" -dependencies = [ - "anyhow", - "cargo-gpu-install", - "rspirv 0.13.0+sdk-1.4.341.0", ] [[package]] @@ -386,7 +467,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -457,6 +538,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.9" @@ -467,6 +554,18 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -476,6 +575,94 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -509,6 +696,17 @@ dependencies = [ "weezl", ] +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + [[package]] name = "glam" version = "0.33.1" @@ -519,6 +717,41 @@ dependencies = [ "libm", ] +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror", + "windows", +] + [[package]] name = "half" version = "2.7.1" @@ -527,14 +760,38 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "num-traits", "zerocopy", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + [[package]] name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "icu_collections" @@ -662,6 +919,33 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "image-binary" +version = "0.1.0" +dependencies = [ + "enkou-shaders", + "glam", + "spirv-std", + "wgpu", +] + +[[package]] +name = "image-runner" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytemuck", + "cargo-gpu-install", + "enkou-shaders", + "futures", + "glam", + "image", + "image-binary", + "tempfile", + "wgpu", + "xflags", +] + [[package]] name = "image-webp" version = "0.2.4" @@ -685,7 +969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.17.1", ] [[package]] @@ -696,7 +980,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -714,6 +998,34 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.118", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -724,6 +1036,34 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "lebe" version = "0.5.3" @@ -746,6 +1086,16 @@ dependencies = [ "cc", ] +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libm" version = "0.2.16" @@ -773,6 +1123,21 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.32" @@ -823,6 +1188,54 @@ dependencies = [ "pxfm", ] +[[package]] +name = "naga" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23bf0a141a9ab6f07dbb492db53245e464bc9db42f407772d9ae03d83a2c1033" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.13.0", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.17.1", + "indexmap", + "libm", + "log", + "naga-types", + "num-traits", + "once_cell", + "petgraph", + "rustc-hash", + "spirv 0.4.0+sdk-1.4.341.0", + "thiserror", + "unicode-ident", +] + +[[package]] +name = "naga-types" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658200ddc25c6c7b860747516d132d1b284c0fafb7a380233acee9a72fb30e11" +dependencies = [ + "hashbrown 0.17.1", + "indexmap", + "rustc-hash", + "thiserror", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -871,7 +1284,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -904,6 +1317,92 @@ dependencies = [ "libm", ] +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-metal", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -925,6 +1424,38 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "paste" version = "1.0.15" @@ -943,6 +1474,29 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + [[package]] name = "png" version = "0.18.1" @@ -956,6 +1510,21 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -974,6 +1543,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "proc-macro2" version = "1.0.106" @@ -999,7 +1574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" dependencies = [ "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1091,6 +1666,12 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + [[package]] name = "rav1e" version = "0.8.1" @@ -1146,6 +1727,24 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-quartz-core", +] + [[package]] name = "rayon" version = "1.12.0" @@ -1166,6 +1765,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.0", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -1177,6 +1785,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + [[package]] name = "rgb" version = "0.8.53" @@ -1193,16 +1807,6 @@ dependencies = [ "spirv 0.3.0+sdk-1.3.268.0", ] -[[package]] -name = "rspirv" -version = "0.13.0+sdk-1.4.341.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091dca2e1d6fd3098417b5ec88e77e80d1ba5945750943419dc976858082c296" -dependencies = [ - "rustc-hash", - "spirv 0.4.0+sdk-1.4.341.0", -] - [[package]] name = "rustc-hash" version = "1.1.0" @@ -1214,7 +1818,7 @@ name = "rustc_codegen_spirv-types" version = "0.10.0-alpha.1" source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=67f1ff2#67f1ff27272a1dff82776a5ad7388c738e0b31be" dependencies = [ - "rspirv 0.12.0+sdk-1.3.268.0", + "rspirv", "semver", "serde", "serde_json", @@ -1241,6 +1845,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "1.0.28" @@ -1279,7 +1889,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float", + "ordered-float 2.10.1", "serde", ] @@ -1300,7 +1910,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1346,6 +1956,21 @@ dependencies = [ "quote", ] +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.15.2" @@ -1408,7 +2033,7 @@ dependencies = [ "proc-macro2", "quote", "spirv-std-types", - "syn", + "syn 2.0.118", ] [[package]] @@ -1422,6 +2047,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "2.0.118" @@ -1433,6 +2064,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -1441,7 +2083,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1458,23 +2100,32 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "2.0.18" +name = "termcolor" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -1554,6 +2205,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -1589,6 +2246,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1606,9 +2269,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -1618,10 +2281,20 @@ dependencies = [ ] [[package]] -name = "wasm-bindgen-macro" -version = "0.2.125" +name = "wasm-bindgen-futures" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1629,38 +2302,337 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.125" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "weezl" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +[[package]] +name = "wgpu" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d8f4bd44d92da5270f03409dba9f952dab24f128e05d6a554926101d1bf9114" +dependencies = [ + "arrayvec", + "bitflags 2.13.0", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.17.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08763620e76fc980bca7bf84de82568614487a53172dd968d89187282eb87fa2" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.13.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.17.1", + "indexmap", + "log", + "naga", + "naga-types", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-naga-bridge", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3283b6da70d7fc892de95840215aa36381b5d0cbc479e88ee2b173c7b992b225" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85dcf2b2e5c2afb9eda64c570a87a4e570304bf39e52eddbaaf222d655b656ad" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76bc9c1c186ff3d9054e0d224c93c8c1c79d6653907c5249a5c1ea1a2cb1e43" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf765132d8d5f50e192e7880464890c13f4e7457aafe8e5466e8174586e9f101" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.13.0", + "block2", + "bytemuck", + "cfg-if", + "cfg_aliases", + "glow", + "glutin_wgl_sys", + "gpu-allocator", + "hashbrown 0.17.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "naga", + "naga-types", + "ndk-sys", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", + "once_cell", + "ordered-float 5.3.0", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "raw-window-metal", + "renderdoc-sys", + "smallvec", + "static_assertions", + "thiserror", + "wasm-bindgen", + "wayland-sys", + "web-sys", + "wgpu-naga-bridge", + "wgpu-types", + "windows", + "windows-core", + "windows-result", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9eaac644e5008925c78567d272b9d66ef83da55a53cc17fc7daade7bb6e66e5" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9c93c2b35edde326df60ffdee4c0f5864eac3011d6768b70d43f028ad93565" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "js-sys", + "log", + "naga-types", + "raw-window-handle", + "static_assertions", + "web-sys", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1670,6 +2642,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "winnow" version = "0.7.15" @@ -1691,6 +2672,27 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "xflags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944" +dependencies = [ + "xflags-macros", +] + +[[package]] +name = "xflags-macros" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + [[package]] name = "y4m" version = "0.8.0" @@ -1716,7 +2718,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", "synstructure", ] @@ -1737,7 +2739,7 @@ checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1757,7 +2759,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", "synstructure", ] @@ -1791,7 +2793,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b5fdf79..002c01a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] members = [ "enkou-shaders", - "enkou-shaders-tests", + "examples/image-runner", + "examples/image-binary", ] resolver = "3" @@ -13,6 +14,7 @@ license = "MIT" repository = "" [workspace.lints.rust] +missing_docs = { level = "warn" } unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } [workspace.dependencies] @@ -21,6 +23,7 @@ spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "67f1ff2" anyhow = "1.0.102" bytemuck = { version = "1.25.0", features = ["derive"] } +futures = "0.3.32" glam = { version = "0.33.1", default-features = false, features = ["bytemuck", "scalar-math"] } image = { version = "0.25.10", default-features = false, features = ["default-formats"]} libm = "0.2.16" @@ -28,3 +31,6 @@ rand = { version = "0.10.1", default-features = false } rand_xoshiro = "0.8.1" rspirv = "0.13.0" tempfile = "3.27.0" +thiserror = "2.0.19" +wgpu = { version = "30.0.0", features = ["spirv"] } +xflags = "0.3.2" diff --git a/enkou-shaders-tests/src/lib.rs b/enkou-shaders-tests/src/lib.rs deleted file mode 100644 index 7aa1873..0000000 --- a/enkou-shaders-tests/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -#[cfg(test)] -mod test { - use rspirv::binary::parse_bytes; - use rspirv::dr::{Module, Operand}; - use rspirv::spirv::ExecutionModel; - use std::sync::OnceLock; - - static SHADER_MODULE: OnceLock = OnceLock::new(); - - fn shader() -> &'static Module { - SHADER_MODULE.get_or_init(|| { - let shader_bytes = include_bytes!(env!("SHADER_SPV_PATH")); - - let mut loader = rspirv::dr::Loader::new(); - parse_bytes(shader_bytes, &mut loader).expect("Unable to parse shader"); - - loader.module() - }) - } - - fn has_entry_point(execution_model: ExecutionModel, name: &str) -> bool { - for entry_point in shader().entry_points.iter() { - let operands: Vec = entry_point - .operands - .iter() - .filter(|op| matches!(op, Operand::ExecutionModel(_) | Operand::LiteralString(_))) - .cloned() - .collect(); - - assert_eq!(operands.len(), 2); - match &operands[0] { - Operand::ExecutionModel(actual) => { - if execution_model != *actual { - continue; - } - } - op => panic!("Unexpected operand; {}", op), - } - - match &operands[1] { - Operand::LiteralString(actual) => { - if name != actual { - continue; - } - } - op => panic!("Unexpected operand; {}", op), - } - - return true; - } - - false - } - - #[test] - pub fn has_entry_main_chaos_game() { - assert!(has_entry_point( - ExecutionModel::GLCompute, - "main_chaos_game" - )) - } - - #[test] - pub fn has_entry_main_camera() { - assert!(has_entry_point(ExecutionModel::GLCompute, "main_camera")) - } -} diff --git a/enkou-shaders/Cargo.toml b/enkou-shaders/Cargo.toml index 23d34ef..d5e82b6 100644 --- a/enkou-shaders/Cargo.toml +++ b/enkou-shaders/Cargo.toml @@ -16,8 +16,3 @@ libm.workspace = true rand.workspace = true rand_xoshiro.workspace = true spirv-std.workspace = true - -[dev-dependencies] -anyhow.workspace = true -image.workspace = true -tempfile.workspace = true diff --git a/enkou-shaders/examples/gasket.rs b/enkou-shaders/examples/gasket.rs deleted file mode 100644 index 9c3bbe2..0000000 --- a/enkou-shaders/examples/gasket.rs +++ /dev/null @@ -1,95 +0,0 @@ -use anyhow::{Context, Result}; -use enkou_shaders::Coefficients2; -use enkou_shaders::camera::Camera; -use enkou_shaders::camera::entry::main_camera; -use enkou_shaders::chaos_game::entry::main_chaos_game; -use enkou_shaders::transform::Transform; -use enkou_shaders::variation::Variation; -use glam::{Affine2, IVec2, UVec2, Vec2, uvec2}; -use image::{GrayImage, Luma}; -use std::mem; -use std::process::Command; -use tempfile::NamedTempFile; - -const ITERATIONS_DISCARD: u32 = 20; -const ITERATIONS: u32 = 50_000; -const IMAGE_DIMENSION: UVec2 = uvec2(600, 600); - -pub fn main() -> Result<()> { - let transforms = [ - { - // F_0: (x / 2, y / 2) - let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.0); - Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) - }, - { - // F_1: ((x + 1) / 2, y / 2) - let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.5, 0.0, 0.5, 0.0); - Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) - }, - { - // F_2: (x / 2, (y + 1) / 2) - let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.5); - Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) - }, - ]; - - let weights = [1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0]; - - let variations = [Variation::IDENTITY]; - - let mut output_points_ifs = Vec::new(); - output_points_ifs.resize(ITERATIONS as usize, Vec2::ZERO); - - main_chaos_game( - ITERATIONS_DISCARD, - &[4u8; 32], - &transforms, - &weights, - &variations, - &mut output_points_ifs, - ); - - // The gasket is defined on the range [0, 1] for both X and Y - let camera = Camera::new( - IMAGE_DIMENSION, - Vec2::ONE * 0.5, - 0.0, - Vec2::ZERO, - IMAGE_DIMENSION.as_vec2(), - ); - - let mut output_points_pixel = Vec::new(); - output_points_pixel.resize(ITERATIONS as usize, IVec2::ZERO); - - main_camera(&camera, &output_points_ifs, &mut output_points_pixel); - - let mut image = GrayImage::new(IMAGE_DIMENSION.x, IMAGE_DIMENSION.y); - let dimensions = image.dimensions(); - output_points_pixel - .iter() - .skip_while(|p| { - p.x < 0 || (p.x as u32) > dimensions.0 || p.y < 0 || (p.y as u32) > dimensions.1 - }) - .map(|p| (p.x as u32, p.y as u32)) - .for_each(|(x, y)| image.put_pixel(x, y, Luma([255u8]))); - - let temp = NamedTempFile::with_suffix(".png").context("Unable to create file for image")?; - image.save(temp.path()).context("Unable to save image")?; - - let open_program: &str = cfg_select! { - unix => "xdg-open", - _ => panic!("No available program to open images") - }; - - Command::new(open_program) - .arg(temp.path()) - .spawn()? - .wait()?; - - // In case the image viewer forks and gives control back prior to reading the file, - // drop it and don't run the destructor - mem::forget(temp); - - Ok(()) -} diff --git a/enkou-shaders/src/chaos_game.rs b/enkou-shaders/src/chaos_game.rs index 8ac3858..20a84e5 100644 --- a/enkou-shaders/src/chaos_game.rs +++ b/enkou-shaders/src/chaos_game.rs @@ -106,39 +106,3 @@ impl<'a, R: Rng> Iterator for ChaosGame<'a, R> { Some(next_point) } } - -/// Shader entry point for running the chaos game to produce new IFS coordinates -pub mod entry { - use crate::chaos_game::ChaosGame; - use crate::rng::xoshiro256starstar_from_seed; - use crate::transform::Transform; - use crate::variation::Variation; - use glam::Vec2; - use spirv_std::spirv; - - /// Given a set of fractal flame parameters, generate new IFS coordinates - /// and store them in the output array. - #[spirv(compute(entry_point_name = "main_chaos_game", threads(1)))] - pub fn main_chaos_game( - #[spirv(spec_constant(id = 1, default = 20))] iteration_discard: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] rng_seed: &[u8], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform], - #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation], - #[spirv(storage_buffer, descriptor_set = 1, binding = 0)] output: &mut [Vec2], - ) { - let mut rng_seed_actual = [0u8; 32]; - (0..32).for_each(|i| rng_seed_actual[i] = rng_seed[i]); - - let mut rng = xoshiro256starstar_from_seed(rng_seed_actual); - let mut chaos_game = ChaosGame::new(&mut rng, transforms, weights, variations); - - for _ in 0..iteration_discard { - chaos_game.next().unwrap(); - } - - for i in 0..output.len() { - output[i] = chaos_game.next().unwrap(); - } - } -} diff --git a/enkou-shaders/src/lib.rs b/enkou-shaders/src/lib.rs index 0cb9009..c2534e2 100644 --- a/enkou-shaders/src/lib.rs +++ b/enkou-shaders/src/lib.rs @@ -1,11 +1,12 @@ //! # Enkou -#![no_std] -#![deny(missing_docs)] -#![allow(clippy::needless_range_loop)] // SPIR-V backend has issues with iteration over items +#![cfg_attr(target_arch = "spirv", no_std)] + +// SPIR-V backend is unable to compile iteration over items +#![allow(clippy::needless_range_loop)] pub mod camera; pub mod chaos_game; -mod rng; +pub mod rng; pub mod transform; pub mod variation; diff --git a/enkou-shaders/src/rng.rs b/enkou-shaders/src/rng.rs index 2169847..fc63ce1 100644 --- a/enkou-shaders/src/rng.rs +++ b/enkou-shaders/src/rng.rs @@ -1,3 +1,6 @@ +//! # RNG +//! +//! Random number generation utilities for shaders use rand::SeedableRng; use rand_xoshiro::Xoshiro256StarStar; @@ -14,7 +17,7 @@ use rand_xoshiro::Xoshiro256StarStar; /// This function assumes a properly-initialized state array; /// output may silently degenerate if the initial state is all zeros, /// so this module is private to the crate. -pub(crate) fn xoshiro256starstar_from_seed( +pub fn xoshiro256starstar_from_seed( rng_state: ::Seed, ) -> Xoshiro256StarStar { let mut rng_state_actual = [0u64; 4]; diff --git a/enkou-shaders/src/variation.rs b/enkou-shaders/src/variation.rs index 81c3463..37a085a 100644 --- a/enkou-shaders/src/variation.rs +++ b/enkou-shaders/src/variation.rs @@ -68,7 +68,7 @@ impl Variation { }; /// Create a new variation by providing the variation kind, weight, and parameters. - pub fn new(kind: VariationKind, weight: f32, params: VariationParams) -> Variation { + pub const fn new(kind: VariationKind, weight: f32, params: VariationParams) -> Variation { Variation { kind, weight, diff --git a/enkou-shaders-tests/Cargo.toml b/examples/image-binary/Cargo.toml similarity index 52% rename from enkou-shaders-tests/Cargo.toml rename to examples/image-binary/Cargo.toml index 1627234..f02c03f 100644 --- a/enkou-shaders-tests/Cargo.toml +++ b/examples/image-binary/Cargo.toml @@ -1,18 +1,16 @@ [package] -name = "enkou-shaders-tests" -publish = false +name = "image-binary" version.workspace = true authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +[dependencies] +enkou-shaders = { path = "../../enkou-shaders" } +glam.workspace = true +spirv-std.workspace = true +wgpu = { workspace = true, optional = true } + [lints] workspace = true - -[dependencies] -rspirv.workspace = true - -[build-dependencies] -anyhow.workspace = true -cargo-gpu-install.workspace = true diff --git a/examples/image-binary/src/lib.rs b/examples/image-binary/src/lib.rs new file mode 100644 index 0000000..4dc32c3 --- /dev/null +++ b/examples/image-binary/src/lib.rs @@ -0,0 +1,82 @@ +//! # Binary image +#![cfg_attr(target_arch = "spirv", no_std)] +use enkou_shaders::camera::Camera; +use enkou_shaders::chaos_game::ChaosGame; +use enkou_shaders::rng::xoshiro256starstar_from_seed; +use enkou_shaders::transform::Transform; +use enkou_shaders::variation::Variation; +use glam::{UVec2, UVec4}; +use spirv_std::spirv; + +#[cfg(feature = "wgpu")] +pub use wgpu::*; + +const IMAGE_QUALITY: f32 = 1.0; +const ITERATIONS_FUSE: u32 = 20; + +/// Sierpinski Gasket +#[spirv(compute(entry_point_name = "main_image_binary", threads(1)))] +pub fn main_image_binary( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] image_dimensions: &UVec2, + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform], + #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32], + #[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation], + #[spirv(storage_buffer, descriptor_set = 0, binding = 4)] camera: &Camera, + #[spirv(storage_buffer, descriptor_set = 0, binding = 5)] image_buffer: &mut [UVec4], +) { + // Initialize RNG and run the chaos game + let mut rng = xoshiro256starstar_from_seed([4; 32]); + let mut chaos_game = ChaosGame::new(&mut rng, transforms, weights, variations); + + // Discard the first few iterations + for _ in 0..ITERATIONS_FUSE { + chaos_game.next().unwrap(); + } + + // Plot the remaining points generated by the chaos game + let iterations = (image_dimensions.as_vec2().element_product() * IMAGE_QUALITY) as u32; + for _ in 0..iterations { + let ifs_point = chaos_game.next().unwrap(); + let pixel_point = camera.transform_point_to_image(ifs_point); + + if let Some(pixel_point) = pixel_point { + let pixel_index = pixel_point.y * image_dimensions.x + pixel_point.x; + image_buffer[pixel_index as usize] = UVec4::splat(255); + } + } +} + +#[cfg(feature = "wgpu")] +pub mod wgpu { + const fn bgle(binding: u32, read_only: bool) -> wgpu::BindGroupLayoutEntry { + wgpu::BindGroupLayoutEntry { + binding, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + } + } + + pub const BGLE_IMAGE_DIMENSIONS: wgpu::BindGroupLayoutEntry = bgle(0, true); + pub const BGLE_TRANSFORMS: wgpu::BindGroupLayoutEntry = bgle(1, true); + pub const BGLE_WEIGHTS: wgpu::BindGroupLayoutEntry = bgle(2, true); + pub const BGLE_VARIATIONS: wgpu::BindGroupLayoutEntry = bgle(3, true); + pub const BGLE_CAMERA: wgpu::BindGroupLayoutEntry = bgle(4, true); + pub const BGLE_IMAGE_BUFFER: wgpu::BindGroupLayoutEntry = bgle(5, false); + + pub const BIND_GROUP_IMAGE_BINARY: wgpu::BindGroupLayoutDescriptor = wgpu::BindGroupLayoutDescriptor { + label: Some("main_image_binary"), + entries: &[ + BGLE_IMAGE_DIMENSIONS, + BGLE_TRANSFORMS, + BGLE_WEIGHTS, + BGLE_VARIATIONS, + BGLE_CAMERA, + BGLE_IMAGE_BUFFER, + ], + }; +} diff --git a/examples/image-runner/Cargo.toml b/examples/image-runner/Cargo.toml new file mode 100644 index 0000000..5849365 --- /dev/null +++ b/examples/image-runner/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "image-runner" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +enkou-shaders = { path = "../../enkou-shaders" } +image-binary = { path = "../image-binary", features = ["wgpu"] } + +anyhow.workspace = true +bytemuck.workspace = true +futures.workspace = true +glam = { workspace = true, features = ["u8"] } +image.workspace = true +tempfile.workspace = true +wgpu.workspace = true +xflags.workspace = true + +[build-dependencies] +anyhow.workspace = true +cargo-gpu-install.workspace = true + +[lints] +workspace = true diff --git a/enkou-shaders-tests/build.rs b/examples/image-runner/build.rs similarity index 84% rename from enkou-shaders-tests/build.rs rename to examples/image-runner/build.rs index 117b150..351fe6e 100644 --- a/enkou-shaders-tests/build.rs +++ b/examples/image-runner/build.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; pub fn main() -> anyhow::Result<()> { let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let crate_path = [manifest_dir, "..", "enkou-shaders"] + let crate_path = [manifest_dir, "..", "image-binary"] .iter() .copied() .collect::(); @@ -20,6 +20,9 @@ pub fn main() -> anyhow::Result<()> { let compile_result = builder.build()?; let spv_path = compile_result.module.unwrap_single(); - println!("cargo::rustc-env=SHADER_SPV_PATH={}", spv_path.display()); + println!( + "cargo::rustc-env=SHADER_SPV_PATH_IMAGE_BINARY={}", + spv_path.display() + ); Ok(()) } diff --git a/examples/image-runner/src/image_binary.rs b/examples/image-runner/src/image_binary.rs new file mode 100644 index 0000000..c6dea3d --- /dev/null +++ b/examples/image-runner/src/image_binary.rs @@ -0,0 +1,210 @@ +use enkou_shaders::Coefficients2; +use enkou_shaders::transform::Transform; +use enkou_shaders::variation::Variation; +use futures::channel::oneshot; +use futures::executor::block_on; +use glam::{uvec2, Affine2, UVec2, UVec4, Vec2}; +use image::{Rgba, RgbaImage}; +use image_binary::{main_image_binary, BIND_GROUP_IMAGE_BINARY, BGLE_IMAGE_DIMENSIONS, BGLE_TRANSFORMS, BGLE_WEIGHTS, BGLE_CAMERA, BGLE_IMAGE_BUFFER, BGLE_VARIATIONS}; +use std::path::Path; +use wgpu::util::DeviceExt; +use enkou_shaders::camera::Camera; + +fn transforms() -> [Transform; 3] { + [ + { + // F_0: (x / 2, y / 2) + let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.0); + Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) + }, + { + // F_1: ((x + 1) / 2, y / 2) + let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.5, 0.0, 0.5, 0.0); + Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) + }, + { + // F_2: (x / 2, (y + 1) / 2) + let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.5); + Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) + }, + ] +} + +fn weights() -> [f32; 3] { + [1.0 / 3.0; 3] +} + +fn variations() -> [Variation; 1] { + [Variation::IDENTITY] +} + +fn camera(image_dimensions: UVec2) -> Camera { + Camera::new( + image_dimensions, + Vec2::ONE * 0.5, + 0.0, + Vec2::ZERO, + Vec2::splat(image_dimensions.min_element() as f32), + ) +} + +pub(crate) fn main_cpu(image_dimensions: UVec2, output_path: &Path) -> Result<(), anyhow::Error> { + let mut image_buffer = Vec::::new(); + image_buffer.resize(image_dimensions.element_product() as usize, UVec4::ZERO); + + main_image_binary( + &image_dimensions, + &transforms(), + &weights(), + &variations(), + &camera(image_dimensions), + &mut image_buffer, + ); + + let mut image = RgbaImage::new(image_dimensions.x, image_dimensions.y); + for (i, color) in image_buffer.into_iter().enumerate() { + let image_x = i as u32 % image_dimensions.x; + let image_y = i as u32 / image_dimensions.x; + + image.put_pixel(image_x, image_y, color.as_u8vec4().to_array().into()); + } + + image.save(output_path)?; + Ok(()) +} + +const SHADER_MODULE: wgpu::ShaderModuleDescriptor = wgpu::include_spirv!(env!("SHADER_SPV_PATH_IMAGE_BINARY")); + +fn bge<'a>(entry: &'a wgpu::BindGroupLayoutEntry, buffer: &'a wgpu::Buffer) -> wgpu::BindGroupEntry<'a> { + wgpu::BindGroupEntry { + binding: entry.binding, + resource: buffer.as_entire_binding(), + } +} + +pub(crate) fn main_gpu(device: &wgpu::Device, queue: &wgpu::Queue, image_dimensions: UVec2, output_path: &Path) -> Result<(), anyhow::Error> { + + let bind_group_layout = device.create_bind_group_layout(&BIND_GROUP_IMAGE_BINARY); + + let image_dimensions_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("image_dimensions"), + contents: bytemuck::bytes_of(&image_dimensions), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::STORAGE, + }); + + let transforms_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("transforms"), + contents: bytemuck::cast_slice(&transforms()), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::STORAGE, + }); + + let weights_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("weights"), + contents: bytemuck::cast_slice(&weights()), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::STORAGE, + }); + + let variations_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("variations"), + contents: bytemuck::cast_slice(&variations()), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::STORAGE, + }); + + let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("camera"), + contents: bytemuck::bytes_of(&camera(image_dimensions)), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::STORAGE, + }); + + let image_buffer_elements = image_dimensions.element_product() as u64; + let image_buffer_size = image_buffer_elements * size_of::() as u64; + let image_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("image_buffer"), + size: image_buffer_size, + usage: wgpu::BufferUsages::COPY_SRC | wgpu::BufferUsages::STORAGE, + mapped_at_creation: false, + }); + + let image_staging = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("image_buffer_staging"), + size: image_buffer_size, + usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("main_image_binary"), + layout: &bind_group_layout, + entries: &[ + bge(&BGLE_IMAGE_DIMENSIONS, &image_dimensions_buffer), + bge(&BGLE_TRANSFORMS, &transforms_buffer), + bge(&BGLE_WEIGHTS, &weights_buffer), + bge(&BGLE_VARIATIONS, &variations_buffer), + bge(&BGLE_CAMERA, &camera_buffer), + bge(&BGLE_IMAGE_BUFFER, &image_buffer), + ], + }); + + let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("main_image_binary"), + bind_group_layouts: &[Some(&bind_group_layout)], + immediate_size: 0, + }); + + let module = device.create_shader_module(SHADER_MODULE); + + let compute_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { + label: Some("main_image_binary"), + layout: Some(&layout), + module: &module, + entry_point: Some("main_image_binary"), + compilation_options: Default::default(), + cache: None, + }); + + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("main_image_binary"), + }); + + { + let mut compute_pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("main_image_binary"), + timestamp_writes: None, + }); + + compute_pass.set_pipeline(&compute_pipeline); + compute_pass.set_bind_group(0, &bind_group, &[]); + } + + encoder.copy_buffer_to_buffer(&image_buffer, 0, &image_staging, 0, Some(image_buffer_size)); + + let (sender, receiver) = oneshot::channel(); + let image_staging_capturable = image_staging.clone(); + encoder.map_buffer_on_submit(&image_buffer, wgpu::MapMode::Read, .., move |result| { + result.expect("unable to map buffer"); + + let staging_buffer_view = image_staging_capturable.get_mapped_range(..).expect("Unable to map staging buffer"); + + let mut image = RgbaImage::new(image_dimensions.x, image_dimensions.y); + let image_buffer_elements = bytemuck::cast_slice::(staging_buffer_view.as_ref()); + for (i, element) in image_buffer_elements.iter().enumerate() { + let image_x = i as u32 % image_dimensions.x; + let image_y = i as u32 / image_dimensions.x; + + let pixel_colors = element.as_u8vec4(); + image.put_pixel(image_x, image_y, Rgba(*pixel_colors.as_ref())) + } + + sender.send(image).expect("Unable to send image"); + }); + + queue.submit(Some(encoder.finish())); + device.poll(wgpu::PollType::wait_indefinitely())?; + let image = block_on(receiver)?; + + image_staging.unmap(); + + image.save(output_path)?; + + Ok(()) +} \ No newline at end of file diff --git a/examples/image-runner/src/main.rs b/examples/image-runner/src/main.rs new file mode 100644 index 0000000..da72185 --- /dev/null +++ b/examples/image-runner/src/main.rs @@ -0,0 +1,77 @@ +use glam::{uvec2}; +use std::mem; +use std::process::Command; +use std::path::PathBuf; +use futures::executor::block_on; +use tempfile::NamedTempFile; + +mod image_binary; + +fn main() -> Result<(), anyhow::Error> { + let instance_future = wgpu::util::new_instance_with_webgpu_detection(wgpu::InstanceDescriptor { + backends: Default::default(), + flags: Default::default(), + memory_budget_thresholds: Default::default(), + backend_options: Default::default(), + display: None, + }); + let instance = block_on(instance_future); + + let adapter_future = instance.request_adapter(&wgpu::RequestAdapterOptions { + power_preference: Default::default(), + force_fallback_adapter: false, + compatible_surface: None, + apply_limit_buckets: false, + }); + let adapter = block_on(adapter_future)?; + + let device_future = adapter.request_device(&wgpu::DeviceDescriptor { + label: Some("image-runner"), + required_features: Default::default(), + required_limits: Default::default(), + experimental_features: Default::default(), + memory_hints: Default::default(), + trace: Default::default(), + }); + let (device, queue) = block_on(device_future)?; + + let flags = xflags::parse_or_exit! { + /// Image dimensions to output, as `width,height` + optional -d, --dimensions dimensions: String + + /// Output pathname to use + optional -o, --output output: PathBuf + + /// Image type to generate + required image: String + }; + + let dimensions = if let Some(dimensions) = flags.dimensions { + let (width_str, height_str) = dimensions.split_once(",").ok_or(anyhow::anyhow!("Invalid format for image dimensions"))?; + uvec2(width_str.parse()?, height_str.parse()?) + } else { + uvec2(1600, 900) + }; + + let output = if let Some(output) = flags.output { output } else { + let path = NamedTempFile::with_suffix(".png")?; + let pathbuf: PathBuf = path.path().into(); + mem::forget(path); + pathbuf + }; + + match flags.image.as_ref() { + "binary_cpu" => image_binary::main_cpu(dimensions, output.as_ref()), + "binary_gpu" => image_binary::main_gpu(&device, &queue, dimensions, output.as_ref()), + _ => Err(anyhow::anyhow!("Unrecognized image type")) + }?; + + let mut command = cfg_select! { + unix => Command::new("xdg-open").arg(temp.path()).spawn(), + windows => Command::new("PowerShell").arg("-Command").arg(format!("start {}", output.display())).spawn(), + _ => Err(anyhow::anyhow!("No available program to open images"))? + }?; + command.wait()?; + + Ok(()) +}