diff --git a/Cargo.lock b/Cargo.lock index 653304f..030f2ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -9,10 +18,94 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "arrayref" -version = "0.3.7" +name = "ahash" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[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 = "anstream" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] [[package]] name = "arrayvec" @@ -20,12 +113,51 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bit_field" version = "0.10.2" @@ -38,11 +170,43 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + [[package]] name = "bytemuck" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "byteorder" @@ -50,18 +214,141 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets 0.48.5", +] + +[[package]] +name = "clap" +version = "4.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e54881c004cec7895b0068a0a954cd5d62da01aef83fa35b1e594497bf5445" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cb82d7f531603d2fd1f507441cdd35184fa81beff7bd489570de7f773460bb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "com-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -102,12 +389,45 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "d3d12" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16e44ab292b1dddfdaf7be62cfd8877df52f2f3fde5858d95bab606be259f20" +dependencies = [ + "bitflags 2.4.1", + "libloading 0.8.1", + "winapi", +] + [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "exr" version = "1.71.0" @@ -137,9 +457,17 @@ dependencies = [ name = "fishbowl" version = "0.1.0" dependencies = [ + "bytemuck", + "clap", + "flexi_logger", + "futures", + "futures-intrusive", "gif", "image", - "tiny-skia", + "indicatif", + "log", + "pollster", + "wgpu", ] [[package]] @@ -152,15 +480,174 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flexi_logger" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac35b454b60e1836602173e2eb7ef531173388c0212e02ec7f9fac086159ee5" +dependencies = [ + "chrono", + "glob", + "is-terminal", + "lazy_static", + "log", + "nu-ansi-term", + "regex", + "thiserror", +] + [[package]] name = "flume" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ + "futures-core", + "futures-sink", + "nanorand", "spin", ] +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + [[package]] name = "gif" version = "0.12.0" @@ -171,6 +658,103 @@ dependencies = [ "weezl", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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 = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "glow" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "886c2a30b160c4c6fec8f987430c26b526b7988ca71f664e6a699ddf6f9601e4" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.4.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.4.1", +] + +[[package]] +name = "gpu-allocator" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40fe17c8a05d60c38c0a4e5a3c802f2f1ceb66b76c67d96ffb34bef0475a7fad" +dependencies = [ + "backtrace", + "log", + "presser", + "thiserror", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" +dependencies = [ + "bitflags 2.4.1", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" +dependencies = [ + "bitflags 2.4.1", +] + [[package]] name = "half" version = "2.2.1" @@ -180,6 +764,72 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hassle-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" +dependencies = [ + "bitflags 1.3.2", + "com-rs", + "libc", + "libloading 0.7.4", + "thiserror", + "widestring", + "winapi", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "iana-time-zone" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "image" version = "0.24.7" @@ -199,6 +849,49 @@ dependencies = [ "tiff", ] +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indicatif" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "jpeg-decoder" version = "0.3.0" @@ -208,12 +901,76 @@ dependencies = [ "rayon", ] +[[package]] +name = "js-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +dependencies = [ + "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 0.8.1", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[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.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "lock_api" version = "0.4.11" @@ -230,6 +987,36 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "metal" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" +dependencies = [ + "bitflags 2.4.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -240,6 +1027,44 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "naga" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae585df4b6514cf8842ac0f1ab4992edc975892704835b549cf818dc0191249e" +dependencies = [ + "bit-set", + "bitflags 2.4.1", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "nu-ansi-term" +version = "0.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -270,19 +1095,139 @@ dependencies = [ "autocfg", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" + [[package]] name = "png" version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[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.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135ede8821cf6376eb7a64148901e1690b788c11ae94dc297ae917dbc91dc0e" + [[package]] name = "qoi" version = "0.4.1" @@ -292,6 +1237,27 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "range-alloc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + [[package]] name = "rayon" version = "1.8.0" @@ -312,6 +1278,75 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "renderdoc-sys" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -324,6 +1359,24 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.11.2" @@ -340,10 +1393,66 @@ dependencies = [ ] [[package]] -name = "strict-num" -version = "0.1.1" +name = "spirv" +version = "0.2.0+1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" +dependencies = [ + "bitflags 1.3.2", + "num-traits", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "tiff" @@ -357,29 +1466,115 @@ dependencies = [ ] [[package]] -name = "tiny-skia" -version = "0.11.3" +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a067b809476893fce6a254cf285850ff69c847e6cfbade6a20b655b6c7e80d" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", "cfg-if", - "log", - "png", - "tiny-skia-path", + "wasm-bindgen-macro", ] [[package]] -name = "tiny-skia-path" -version = "0.11.3" +name = "wasm-bindgen-backend" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de35e8a90052baaaf61f171680ac2f8e925a1e43ea9d2e3a00514772250e541" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ - "arrayref", - "bytemuck", - "strict-num", + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", ] [[package]] @@ -388,6 +1583,322 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +[[package]] +name = "wgpu" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e7d227c9f961f2061c26f4cb0fbd4df0ef37e056edd0931783599d6c94ef24" +dependencies = [ + "arrayvec", + "cfg-if", + "flume", + "js-sys", + "log", + "naga", + "parking_lot", + "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 = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef91c1d62d1e9e81c79e600131a258edf75c9531cbdbde09c44a011a47312726" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.4.1", + "codespan-reporting", + "log", + "naga", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84ecc802da3eb67b4cf3dd9ea6fe45bbb47ef13e6c49c5c3240868a9cc6cdd9" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.4.1", + "block", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.1", + "log", + "metal", + "naga", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d5ed5f0edf0de351fe311c53304986315ce866f394a2e6df0c4b3c70774bcdd" +dependencies = [ + "bitflags 2.4.1", + "js-sys", + "web-sys", +] + +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + +[[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-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[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 = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "xml-rs" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/Cargo.toml b/Cargo.toml index 28110e1..a00455e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,26 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +log = "0.4" image = "0.24" gif = "0.12" -tiny-skia = "0.11" +futures = "0.3" +wgpu = {version="0.18", features=["webgl"]} +bytemuck = {version="1.14", features=["derive"]} +futures-intrusive = "0.5" +pollster = "0.3" +clap = { version = "4.4.16", features = ["derive"] } +indicatif = "0.17" + +[dev-dependencies] +flexi_logger = "0.27" + +[profile.dev] +opt-level=1 +# codegen-units = 1 +# lto = "fat" [profile.release] +opt-level=3 codegen-units = 1 +lto = "fat" diff --git a/garden.gif b/garden.gif new file mode 100644 index 0000000..a413f30 Binary files /dev/null and b/garden.gif differ diff --git a/image.gif b/lisa.gif similarity index 100% rename from image.gif rename to lisa.gif diff --git a/resources/cube.png b/resources/cube.png new file mode 100644 index 0000000..3bdb57a Binary files /dev/null and b/resources/cube.png differ diff --git a/resources/garden.jpg b/resources/garden.jpg new file mode 100644 index 0000000..5d45437 Binary files /dev/null and b/resources/garden.jpg differ diff --git a/resources/riley.png b/resources/riley.png new file mode 100644 index 0000000..6f0c4ab Binary files /dev/null and b/resources/riley.png differ diff --git a/resources/thermo.png b/resources/thermo.png new file mode 100644 index 0000000..98628f5 Binary files /dev/null and b/resources/thermo.png differ diff --git a/src/draw.rs b/src/draw.rs new file mode 100644 index 0000000..e76c31f --- /dev/null +++ b/src/draw.rs @@ -0,0 +1,449 @@ +use wgpu::{ + util::{BufferInitDescriptor, DeviceExt}, + *, +}; + +#[repr(C)] +#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +struct Vertex { + position: [f32; 2], + uv: [f32; 2], +} + +impl Vertex { + pub fn desc() -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &[ + wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x2, + }, + wgpu::VertexAttribute { + offset: std::mem::size_of::<[f32; 2]>() as wgpu::BufferAddress, + shader_location: 1, + format: wgpu::VertexFormat::Float32x2, + }, + ], + } + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +pub struct Circle { + pub position: [f32; 2], + pub radius: f32, + pub color: [u8; 4], +} + +impl Circle { + fn desc() -> wgpu::VertexBufferLayout<'static> { + use std::mem; + wgpu::VertexBufferLayout { + array_stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Instance, + attributes: &[ + wgpu::VertexAttribute { + offset: 0, + shader_location: 2, + format: wgpu::VertexFormat::Float32x2, + }, + wgpu::VertexAttribute { + offset: mem::size_of::<[f32; 2]>() as wgpu::BufferAddress, + shader_location: 3, + format: wgpu::VertexFormat::Float32, + }, + wgpu::VertexAttribute { + offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, + shader_location: 4, + format: wgpu::VertexFormat::Uint32, + }, + ], + } + } +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct GpuUniforms { + width: f32, + height: f32, +} + +const SQUARE: &[Vertex] = &[ + Vertex { + position: [-1.0, 1.0], + uv: [0.0, 0.0], + }, + Vertex { + position: [1.0, 1.0], + uv: [1.0, 0.0], + }, + Vertex { + position: [1.0, -1.0], + uv: [1.0, 1.0], + }, + Vertex { + position: [1.0, -1.0], + uv: [1.0, 1.0], + }, + Vertex { + position: [-1.0, -1.0], + uv: [0.0, 1.0], + }, + Vertex { + position: [-1.0, 1.0], + uv: [0.0, 0.0], + }, +]; + +pub struct QuickDraw { + device: Device, + queue: Queue, + width: u32, + height: u32, + uniform_buffer: Buffer, + uniform_bind_group: BindGroup, + texture_desc: TextureDescriptor<'static>, + texture: Texture, + texture_view: TextureView, + instance_count: u64, + instance_buffer: Buffer, + output_buffer: Buffer, + vertex_buffer: Buffer, + pipeline: RenderPipeline, +} + +impl QuickDraw { + pub async fn new(width: u32, height: u32, max_circles: u64) -> Self { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + ..Default::default() + }); + + let adapter = match instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: None, + ..Default::default() + }) + .await + { + Some(a) => a, + None => { + eprintln!("Could not find WGPU adapter"); + std::process::exit(1); + }, + }; + let (device, queue) = + match adapter.request_device(&Default::default(), None).await { + Ok(r) => r, + Err(e) => { + eprintln!("Could not find WGPU device:"); + eprintln!("{}", e); + std::process::exit(1); + }, + }; + + let uniforms = GpuUniforms { + width: width as f32, + height: height as f32, + }; + let uniform_buffer = device.create_buffer_init(&BufferInitDescriptor { + label: Some("Uniform Buffer"), + contents: bytemuck::cast_slice(&[uniforms]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + let uniform_layout = + device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + label: Some("Uniform Bind Group Layout"), + }); + + let uniform_bind_group = + device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("Uniform Bind Group"), + layout: &uniform_layout, + entries: &[BindGroupEntry { + binding: 0, + resource: uniform_buffer.as_entire_binding(), + }], + }); + + let texture_desc = wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8Unorm, + view_formats: &[wgpu::TextureFormat::Rgba8Unorm], + usage: wgpu::TextureUsages::COPY_SRC + | wgpu::TextureUsages::RENDER_ATTACHMENT, + label: None, + }; + let texture = device.create_texture(&texture_desc); + let texture_view = texture.create_view(&Default::default()); + + let instance_buffer = device.create_buffer(&BufferDescriptor { + label: Some("Instance Buffer"), + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + mapped_at_creation: false, + size: max_circles * std::mem::size_of::() as u64, + }); + + let u32_size = std::mem::size_of::() as u32; + let output_buffer_size = (u32_size * width * height) as wgpu::BufferAddress; + let output_buffer = device.create_buffer(&wgpu::BufferDescriptor { + size: output_buffer_size, + usage: wgpu::BufferUsages::COPY_DST + // this tells wpgu that we want to read this buffer from the cpu + | wgpu::BufferUsages::MAP_READ, + label: None, + mapped_at_creation: true, + }); + let vertex_buffer = device.create_buffer_init(&BufferInitDescriptor { + label: Some("Vertex Buffer"), + usage: BufferUsages::VERTEX, + contents: bytemuck::cast_slice(SQUARE), + }); + // Shaders + let shader = std::borrow::Cow::Borrowed(include_str!("shader.wgsl")); + let vert = device.create_shader_module(ShaderModuleDescriptor { + label: Some("Vertex Shader"), + source: ShaderSource::Wgsl(shader.clone()), + }); + let frag = device.create_shader_module(ShaderModuleDescriptor { + label: Some("Vertex Shader"), + source: ShaderSource::Wgsl(shader), + }); + // Pipeline + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Render Pipeline Layout"), + bind_group_layouts: &[&uniform_layout], + push_constant_ranges: &[], + }); + let pipeline = + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + multiview: None, + label: Some("Render Pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: &vert, + entry_point: "vs_main", + buffers: &[Vertex::desc(), Circle::desc()], + }, + fragment: Some(wgpu::FragmentState { + module: &frag, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: texture_desc.format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + unclipped_depth: false, + conservative: false, + // Setting this to anything other than Fill requires + // Features::NON_FILL_POLYGON_MODE + polygon_mode: wgpu::PolygonMode::Fill, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + }); + + Self { + device, + queue, + width, + height, + uniform_buffer, + uniform_bind_group, + texture_desc, + texture, + texture_view, + instance_count: 0, + instance_buffer, + output_buffer, + vertex_buffer, + pipeline, + } + } + + pub async fn resize(&mut self, width: u32, height: u32, max_circles: usize) { + let texture_desc = wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8Unorm, + view_formats: &[wgpu::TextureFormat::Rgba8Unorm], + usage: wgpu::TextureUsages::COPY_SRC + | wgpu::TextureUsages::RENDER_ATTACHMENT, + label: None, + }; + let texture = self.device.create_texture(&texture_desc); + let texture_view = texture.create_view(&Default::default()); + + let u32_size = std::mem::size_of::() as u32; + let output_buffer_size = (u32_size * width * height) as wgpu::BufferAddress; + let output_buffer = self.device.create_buffer(&wgpu::BufferDescriptor { + size: output_buffer_size, + usage: wgpu::BufferUsages::COPY_DST + // this tells wpgu that we want to read this buffer from the cpu + | wgpu::BufferUsages::MAP_READ, + label: None, + mapped_at_creation: true, + }); + self.allocate(max_circles).await; + self.width = width; + self.height = height; + self.texture_desc = texture_desc; + self.texture = texture; + self.texture_view = texture_view; + self.output_buffer = output_buffer; + } + + async fn draw_call(&mut self) { + let mut encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + let render_pass_desc = wgpu::RenderPassDescriptor { + occlusion_query_set: None, + timestamp_writes: None, + label: Some("Render Pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &self.texture_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 1.0, + }), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + }; + let mut render_pass = encoder.begin_render_pass(&render_pass_desc); + + render_pass.set_pipeline(&self.pipeline); + render_pass.set_bind_group(0, &self.uniform_bind_group, &[]); + render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); + render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); + render_pass.draw(0..6, 0..self.instance_count as u32); + drop(render_pass); + + let u32_size = std::mem::size_of::() as u32; + + encoder.copy_texture_to_buffer( + wgpu::ImageCopyTexture { + aspect: wgpu::TextureAspect::All, + texture: &self.texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + wgpu::ImageCopyBuffer { + buffer: &self.output_buffer, + layout: wgpu::ImageDataLayout { + offset: 0, + bytes_per_row: Some(u32_size * self.width), + rows_per_image: Some(self.height), + }, + }, + self.texture_desc.size, + ); + self.output_buffer.unmap(); + self.queue.submit(Some(encoder.finish())); + } + + async fn read_output_buffer(&self) -> BufferView { + let buffer_slice = self.output_buffer.slice(..); + + // NOTE: We have to create the mapping THEN device.poll() + // before await the future. Otherwise the application + // will freeze. + let (tx, rx) = futures_intrusive::channel::shared::oneshot_channel(); + buffer_slice.map_async(wgpu::MapMode::Read, move |result| { + tx.send(result).unwrap(); + }); + // buffer_slice.map_async(wgpu::MapMode::Read, |_| {}); + self.device.poll(wgpu::Maintain::Wait); + rx.receive().await.unwrap().unwrap(); + buffer_slice.get_mapped_range() + } + + // Allocates space for *size* circles, also clears the + // circles buffer + pub async fn allocate(&mut self, size: usize) { + let size = (size * std::mem::size_of::()) as u64; + if size >= self.instance_buffer.size() { + self.instance_buffer = self.device.create_buffer(&BufferDescriptor { + label: Some("Instance Buffer"), + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + mapped_at_creation: false, + size, + }); + } + } + + async fn write_circles(&mut self, circles: &[Circle]) { + self.allocate(circles.len()).await; + self.queue.write_buffer( + &self.instance_buffer, + 0, + &bytemuck::cast_slice(&circles), + ); + // self.queue.submit([]); + self.instance_count = circles.len() as u64; + } + + async fn bytes(&self) -> Vec { + let mut buffer = vec![0; self.output_buffer.size() as usize]; + { + let data = self.read_output_buffer().await; + + for (i, d) in data.iter().enumerate() { + buffer[i] = *d; + } + } + buffer + } + + pub async fn draw_circles(&mut self, circles: &[Circle]) -> Vec { + self.write_circles(circles).await; + self.draw_call().await; + self.bytes().await + } +} diff --git a/src/drawing.rs b/src/drawing.rs deleted file mode 100644 index dff4d55..0000000 --- a/src/drawing.rs +++ /dev/null @@ -1,37 +0,0 @@ -use tiny_skia::*; - -use crate::sim::Circle; -pub fn clear(pixmap: &mut Pixmap) { - let mut black = Paint::default(); - black.set_color_rgba8(0, 0, 0, 255); - pixmap.fill_rect( - Rect::from_xywh(0.0, 0.0, pixmap.width() as f32, pixmap.height() as f32) - .unwrap(), - &black, - Transform::identity(), - None, - ); -} - -pub fn draw_circle(pixmap: &mut Pixmap, circle: &Circle) { - let x = circle.position.x; - let y = circle.position.y; - let radius = circle.radius; - let r = circle.color.0; - let g = circle.color.1; - let b = circle.color.2; - let mut paint = Paint::default(); - paint.set_color_rgba8(r, g, b, 255); - let mut brush = PathBuilder::new(); - brush.push_circle(x, y, radius); - brush.move_to(x, y); - brush.close(); - - pixmap.fill_path( - &brush.finish().unwrap(), - &paint, - FillRule::Winding, - tiny_skia::Transform::identity(), - None, - ) -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 6f0b71e..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::io::Write; - -use image::{ImageBuffer, Rgb}; - -mod drawing; -mod helper; -mod sim; - -fn write_frame( - sim: &sim::Simulation, - encoder: &mut gif::Encoder<&mut W>, -) { - let mut pixbuf = tiny_skia::Pixmap::new(500, 500).unwrap(); - drawing::clear(&mut pixbuf); - for index in 0..sim.circles.len() { - let circle = &sim.circles[index]; - drawing::draw_circle(&mut pixbuf, circle); - } - let mut frame = gif::Frame::from_rgba(500, 500, pixbuf.data_mut()); - frame.delay = 1; - encoder.write_frame(&frame).unwrap(); -} - -async fn write_frame_async( - sim: &sim::Simulation, - encoder: &mut gif::Encoder<&mut W>, -) { - write_frame(sim, encoder); -} - -pub fn generate(image: ImageBuffer, Vec>) -> Vec { - let (mut sim, it) = sim::Simulation::simulate_image(500.0, 500.0, 8.0, image); - - let mut buffer = Vec::::new(); - let mut encoder = gif::Encoder::new(&mut buffer, 500, 500, &[]).unwrap(); - // encoder.set_repeat(gif::Repeat::Infinite).unwrap(); - while sim.clock < it { - write_frame(&sim, &mut encoder); - (0..5).for_each(|_| sim.step()); - } - drop(encoder); - buffer -} - -pub async fn generate_async(image: ImageBuffer, Vec>) -> Vec { - let (mut sim, it) = - sim::Simulation::simulate_image_async(500.0, 500.0, 8.0, image).await; - - let mut buffer = Vec::::new(); - let mut encoder = gif::Encoder::new(&mut buffer, 500, 500, &[]).unwrap(); - // encoder.set_repeat(gif::Repeat::Infinite).unwrap(); - while sim.clock < it { - write_frame_async(&sim, &mut encoder).await; - (0..5).for_each(|_| sim.step()); - } - drop(encoder); - buffer -} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a3166f9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,176 @@ +#![feature(future_join)] +use std::{cell::RefCell, future::join, io::Write, path::Path, sync::Arc}; + +use draw::QuickDraw; +use gif::Frame; +use image::{ImageBuffer, Rgb}; +use indicatif::{ProgressBar, ProgressStyle}; +use log::debug; + +pub mod draw; +pub mod helper; +pub mod sim; +pub mod tests; + +pub fn make_progress(msg: &'static str, max: u64) -> ProgressBar { + let progress = ProgressBar::new(max); + progress.set_style(ProgressStyle::with_template("{msg} :: {bar}").unwrap()); + progress.set_message(msg); + progress +} + +const WIDTH: f32 = 512.0; +const HEIGHT: f32 = 512.0; + +pub async fn preprocess( + image: ImageBuffer, Vec>, + radius: f32, +) -> (sim::Simulation, usize, usize) { + let (sim, it, max_circles) = + sim::Simulation::simulate_image(WIDTH, HEIGHT, radius, image).await; + (sim, it, max_circles) +} + +pub async fn simulate( + draw: &mut QuickDraw, + mut sim: Simulation, + it: usize, + step: usize, + max_circles: usize, +) -> Vec> { + draw.resize(WIDTH as u32, HEIGHT as u32, max_circles).await; + let mut frames = vec![]; + let progress = + make_progress("Simulating ", ((it - sim.clock) / sim.substeps) as u64); + while sim.clock < it { + let circles = &sim + .circles + .iter() + .map(|c| draw::Circle { + position: [c.position.x, c.position.y], + radius: c.radius, + color: [c.color.0, c.color.1, c.color.2, 255], + }) + .collect::>(); + let bytes_future = draw.draw_circles(circles); + let steps = sim.steps(step); + let mut bytes = join!(bytes_future, steps).await.0; + let frame = gif::Frame::from_rgba(WIDTH as u16, HEIGHT as u16, &mut bytes); + frames.push(frame); + progress.inc(step as u64); + } + progress.finish(); + frames +} + +pub async fn encode(frames: Vec>, repeat: bool) -> Vec { + let mut buffer = Vec::::new(); + let mut encoder = + gif::Encoder::new(&mut buffer, WIDTH as u16, HEIGHT as u16, &[]).unwrap(); + let progress = make_progress("Encoding ", frames.len() as u64); + for mut frame in frames { + frame.delay = 1; + encoder.write_frame(&frame).unwrap(); + progress.inc(1); + } + progress.finish(); + if repeat { + encoder.set_repeat(gif::Repeat::Infinite).unwrap(); + } + drop(encoder); + buffer +} + +use clap::Parser; +use sim::Simulation; +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Input file to process. All common image types are + /// supported, see the `image` crate docs for specific + /// compatibility + #[arg(short = 'i', value_hint = clap::ValueHint::DirPath)] + input: std::path::PathBuf, + + /// Output file path ('./output.gif' by default) + #[arg(short = 'o', value_hint = clap::ValueHint::DirPath)] + output: Option, + + /// How many physics-steps between frames. Affects the + /// speed and length of the animation + #[arg(short = 's')] + step: Option, + + /// Radius of the circle, smaller means more detailed but + /// slower to compute (8.0 by default, must be between + /// 1.0 and 50.0 inclusive) + #[arg(short = 'r')] + radius: Option, + + /// Loop the GIF + #[arg(short = 'l', long = "loop")] + looping: bool, +} + +fn open_image>(path: P) -> ImageBuffer, Vec> { + let image = match image::io::Reader::open(path) { + Ok(i) => i, + Err(e) => { + eprintln!("Error opening file for processing: "); + eprintln!("{}", e); + std::process::exit(1); + }, + }; + + let decoded = match image.decode() { + Ok(d) => d, + Err(e) => { + eprintln!("Error processing file: "); + eprintln!("{}", e); + std::process::exit(1); + }, + }; + decoded.to_rgb8() +} + +fn main() { + let args = Args::parse(); + + let output = args.output.unwrap_or("output.gif".into()); + let step = args.step.unwrap_or(20) as usize; + if step == 0 { + eprintln!("Physics step cannot be 0"); + std::process::exit(1); + } + let radius = args.radius.unwrap_or(8.0); + if radius < 1.0 || radius > 50.0 { + eprintln!("Invalid radius {}", radius); + eprintln!("Must be between 1.0 and 50.0 inclusive"); + std::process::exit(1); + } + + let image = open_image(args.input); + let (sim, it, max) = pollster::block_on(preprocess(image, radius)); + let mut draw = pollster::block_on(QuickDraw::new(512, 512, 1000)); + let frames = pollster::block_on(simulate(&mut draw, sim, it, step, max)); + let gif = pollster::block_on(encode(frames, args.looping)); + let mut file = match std::fs::File::create(output.clone()) { + Ok(f) => f, + Err(e) => { + eprintln!("Error opening file for writing:"); + eprintln!("{}", e); + std::process::exit(1); + }, + }; + + match file.write(&gif) { + Ok(_) => { + println!("Successfully created file at '{}'", output.display()); + }, + Err(e) => { + eprintln!("Error writing output file: "); + eprintln!("{}", e); + std::process::exit(1); + }, + }; +} diff --git a/src/shader.wgsl b/src/shader.wgsl new file mode 100644 index 0000000..bc254c5 --- /dev/null +++ b/src/shader.wgsl @@ -0,0 +1,58 @@ +struct Uniforms { + width: f32, height: f32, +} + +@group(0) @binding(0) var uniforms: Uniforms; + +struct VertexInput { + @location(0) position: vec2, + @location(1) uv: vec2, + @location(2) offset: vec2, + @location(3) radius: f32, + @location(4) color: u32, +} + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) uv: vec2, + @location(1) color: vec4, +} + +fn get_color(input: u32) -> vec4 { + let r = f32(input & 255u) / 255.0; + let g = f32((input & (255u << 8u)) >> 8u) / 255.0; + let b = f32((input & (255u << 16u)) >> 16u) / 255.0; + let a = f32((input & (255u << 24u)) >> 24u) / 255.0; + return vec4(r, g, b, a); +} + +@vertex +fn vs_main( + model: VertexInput +) -> VertexOutput { + var out: VertexOutput; + var x = (model.position.x * model.radius) - uniforms.width / 2.0; + x += model.offset.x; + var y = (model.position.y * model.radius) - uniforms.height / 2.0; + y += model.offset.y; + var norm_x = x / (uniforms.width / 2.0); + var norm_y = -y / (uniforms.height / 2.0); + out.clip_position = vec4(norm_x, norm_y, 0.0, 1.0); + out.uv = model.uv; + out.color = get_color(model.color); + return out; +} + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + var x = in.uv.x - 0.5; + var y = in.uv.y - 0.5; + var d = sqrt(x * x + y * y) * 2.0; + if d > 1.1 { + discard; + } else if d > 1.0 { + return vec4(in.color.xyz, 1.1 - d); + } else { + return in.color; + } +} diff --git a/src/sim.rs b/src/sim.rs index 28101e2..5d84260 100644 --- a/src/sim.rs +++ b/src/sim.rs @@ -1,6 +1,6 @@ use std::hash::{Hash, Hasher}; -use crate::helper::*; +use crate::{helper::*, make_progress}; use image::{ImageBuffer, Rgb}; pub struct Circle { @@ -16,7 +16,7 @@ pub struct Simulation { pub colors: Vec, pub max_circles: usize, pub clock: usize, - substeps: usize, + pub substeps: usize, rand_seed: usize, timescale: f32, circle_radius: f32, @@ -27,6 +27,8 @@ pub struct Simulation { } impl Simulation { + pub const POST_PROCESS: usize = 120; + pub fn new( width: f32, height: f32, @@ -35,12 +37,12 @@ impl Simulation { ) -> Self { let area = width * height; let circle_area = circle_radius.powi(2) * std::f32::consts::PI; - let approx_max = ((area / circle_area).round() * 1.0) as usize; + let approx_max = ((area / circle_area).round() * 0.9) as usize; Self { circles: Vec::with_capacity(approx_max), max_circles: approx_max, timescale: 1.0 / 60.0, - substeps: 4, + substeps: 8, colors: vec![Color(255, 255, 255); approx_max], clock: rand_seed, rand_seed, @@ -48,12 +50,15 @@ impl Simulation { radius_variance: circle_radius * 0.1, area_size: (width, height), gravity: height, - response_mod: 0.4, + response_mod: 0.9, } } #[inline] - fn assign_colors_from_image(&mut self, img: ImageBuffer, Vec>) { + async fn assign_colors_from_image( + &mut self, + img: ImageBuffer, Vec>, + ) { let (width, height) = (img.width() as f32 - 1.0, img.height() as f32 - 1.0); for (pos, index) in self.circles.iter().map(|c| (c.position, c.index)) { let img_x = @@ -68,53 +73,37 @@ impl Simulation { } #[inline] - pub fn simulate_image( + pub async fn simulate_image( width: f32, height: f32, circle_radius: f32, img: ImageBuffer, Vec>, - ) -> (Self, usize) { + ) -> (Self, usize, usize) { let image_hash = ({ let mut s = std::hash::DefaultHasher::new(); img.hash(&mut s); s.finish() } % 1204) as usize; let mut sim = Simulation::new(width, height, circle_radius, image_hash); + let progress = make_progress( + "Preprocessing", + (sim.max_circles + Self::POST_PROCESS) as u64, + ); while sim.circles() < sim.max_circles { - sim.step(); + sim.step().await; + progress.inc(2); } - (0..120).for_each(|_| sim.step()); + for _ in 0..Self::POST_PROCESS { + sim.step().await; + progress.inc(1); + } + progress.finish(); let total_iterations = sim.clock; - sim.assign_colors_from_image(img); + let max_circles = sim.circles.len(); + sim.assign_colors_from_image(img).await; sim.circles.clear(); sim.clock = sim.rand_seed; - (sim, total_iterations) - } - - #[inline] - pub async fn simulate_image_async( - width: f32, - height: f32, - circle_radius: f32, - img: ImageBuffer, Vec>, - ) -> (Self, usize) { - let image_hash = ({ - let mut s = std::hash::DefaultHasher::new(); - img.hash(&mut s); - s.finish() - } % 1204) as usize; - let mut sim = Simulation::new(width, height, circle_radius, image_hash); - while sim.circles() < sim.max_circles { - sim.step_async().await; - } - for _ in 0..120 { - sim.step_async().await - } - let total_iterations = sim.clock; - sim.assign_colors_from_image(img); - sim.circles.clear(); - sim.clock = sim.rand_seed; - (sim, total_iterations) + (sim, total_iterations, max_circles) } #[inline] @@ -155,7 +144,7 @@ impl Simulation { // Insertion sort #[inline] - fn sort(&mut self) { + async fn sort(&mut self) { if self.circles.len() == 1 { return; } @@ -170,7 +159,7 @@ impl Simulation { } #[inline] - fn integrate(&mut self) { + async fn integrate(&mut self) { let delta = self.timescale * (1.0 / self.substeps as f32); let gravity = Vector2::new(0.0, self.gravity) * delta.powi(2); self.circles.iter_mut().for_each(|circle| { @@ -181,7 +170,7 @@ impl Simulation { } #[inline] - fn collide(&mut self) { + async fn collide(&mut self) { for i in 0..self.circles.len() { // Apply gravity for j in i..self.circles.len() { @@ -229,7 +218,7 @@ impl Simulation { } #[inline] - pub fn step(&mut self) { + pub async fn step(&mut self) { if self.circles.len() < self.max_circles { self.launch(); } @@ -237,42 +226,22 @@ impl Simulation { self.launch2(); } - (0..self.substeps).for_each(|_| { + for _ in 0..self.substeps { self.constrain_rect(); - self.sort(); - self.collide(); - self.integrate(); + self.sort().await; + self.collide().await; + self.integrate().await; self.clock += 1; - }); + } } #[inline] - pub async fn step_async(&mut self) { - if self.circles.len() < self.max_circles { - self.launch(); + pub async fn steps(&mut self, steps: usize) { + for _ in 0..steps { + self.step().await; } - if self.circles.len() < self.max_circles { - self.launch2(); - } - - (0..self.substeps).for_each(|_| { - self.constrain_rect(); - self.sort(); - self.collide(); - self.integrate(); - self.clock += 1; - }); } - // #[inline] - // pub fn draw(&self, d: &mut RaylibDrawHandle) { - // self - // .circles - // .iter() - // .map(|c| (c.position, c.radius, c.color)) - // .for_each(|(pos, radius, color)| d.draw_circle_v(pos, - // radius, color)); } - pub fn circles(&self) -> usize { self.circles.len() } diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..2a25f37 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,19 @@ +#[cfg(test)] +#[test] +fn bench_async() { + use std::io::Write; + flexi_logger::Logger::try_with_str("debug").unwrap(); + + let image = image::io::Reader::open( + "resources/mona + lisa.png", + ) + .unwrap() + .decode() + .unwrap() + .to_rgb8(); + // let gif = pollster::block_on(crate::generate_async(image, None)); + // let mut file = + // std::fs::File::create("test.gif").unwrap(); + // file.write(&gif).unwrap(); +} diff --git a/test.gif b/test.gif new file mode 100644 index 0000000..ff70e07 Binary files /dev/null and b/test.gif differ