commit 5a8ef55bb320aa4ec05141626f218e3babd571ae Author: TriMill Date: Sat May 13 00:20:26 2023 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..5f4550e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1886 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ab_glyph" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-activity" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c77a0045eda8b888c76ea473c2b0515ba6f471d318f8927c5c72240937035a6" +dependencies = [ + "android-properties", + "bitflags 1.3.2", + "cc", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[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 = "approx" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "ash" +version = "0.37.2+1.3.238" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03" +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.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide 0.6.2", + "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 = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-sys" +version = "0.1.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" +dependencies = [ + "objc-sys", +] + +[[package]] +name = "block2" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" +dependencies = [ + "block-sys", + "objc2-encode", +] + +[[package]] +name = "bumpalo" +version = "3.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "calloop" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a59225be45a478d772ce015d9743e49e92798ece9e34eda9a6aa2a6a7f40192" +dependencies = [ + "log", + "nix 0.25.1", + "slotmap", + "thiserror", + "vec_map", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cgmath" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" +dependencies = [ + "approx", + "num-traits", +] + +[[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 = "com-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" + +[[package]] +name = "const_panic" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "foreign-types", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "d3d12" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da" +dependencies = [ + "bitflags 1.3.2", + "libloading 0.7.4", + "winapi", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +dependencies = [ + "libloading 0.7.4", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "encase" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ca07b3a7863d1bc1ddea8647d67394a0236fc5582035a343c4ef3a962ea62e" +dependencies = [ + "cgmath", + "const_panic", + "encase_derive", + "thiserror", +] + +[[package]] +name = "encase_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54141cb8a5d4ed9308fec79fb1cb9cd272fcd38aa8d1b1165bef654b18671161" +dependencies = [ + "encase_derive_impl", +] + +[[package]] +name = "encase_derive_impl" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dbc65b49ac8078eee25dd0a341e2763974031008518d17b9c448bffc1025541" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide 0.7.1", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "glow" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e007a07a24de5ecae94160f141029e9a347282cfe25d1d58d85d845cf3130f1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gpu-alloc" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" +dependencies = [ + "bitflags 1.3.2", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "gpu-allocator" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" +dependencies = [ + "backtrace", + "log", + "thiserror", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" +dependencies = [ + "bitflags 1.3.2", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[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 = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +dependencies = [ + "libc", + "libloading 0.7.4", + "pkg-config", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[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.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "naga" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00ce114f2867153c079d4489629dbd27aa4b5387a8ba5341bd3f6dfe870688f" +dependencies = [ + "bit-set", + "bitflags 1.3.2", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags 1.3.2", + "jni-sys", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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-sys" +version = "0.2.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" + +[[package]] +name = "objc2" +version = "0.3.0-beta.3.patch-leaks.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" +dependencies = [ + "block2", + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "2.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" +dependencies = [ + "objc-sys", +] + +[[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.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "orbclient" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1" +dependencies = [ + "redox_syscall 0.3.5", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" +dependencies = [ + "ttf-parser", +] + +[[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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "png" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.7.1", +] + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +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 = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" + +[[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.37.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sctk-adwaita" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda4e97be1fd174ccc2aae81c8b694e803fa99b34e8fd0f057a9d70698e3ed09" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "smithay-client-toolkit" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" +dependencies = [ + "bitflags 1.3.2", + "calloop", + "dlib", + "lazy_static", + "log", + "memmap2", + "nix 0.24.3", + "pkg-config", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + +[[package]] +name = "spirv" +version = "0.2.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "strict-num" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df65f20698aeed245efdde3628a6b559ea1239bbb871af1b6e3b58c413b2bd1" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "tiny-skia" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adbfb5d3f3dd57a0e11d12f4f13d4ebbbc1b5c15b7ab0a156d030b21da5f677c" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" + +[[package]] +name = "toml_edit" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "ttf-parser" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[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.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "wayland-client" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +dependencies = [ + "bitflags 1.3.2", + "downcast-rs", + "libc", + "nix 0.24.3", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +dependencies = [ + "nix 0.24.3", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +dependencies = [ + "nix 0.24.3", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +dependencies = [ + "bitflags 1.3.2", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +dependencies = [ + "dlib", + "lazy_static", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13edd72c7b08615b7179dd7e778ee3f0bdc870ef2de9019844ff2cceeee80b11" +dependencies = [ + "arrayvec", + "cfg-if", + "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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625bea30a0ba50d88025f95c80211d1a85c86901423647fb74f397f614abbd9a" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.2.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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41af2ea7d87bd41ad0a37146252d5f7c26490209f47f544b2ee3b3ff34c7732e" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.2.1", + "block", + "core-graphics-types", + "d3d12", + "foreign-types", + "glow", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.0", + "log", + "metal", + "naga", + "objc", + "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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd33a976130f03dcdcd39b3810c0c3fc05daf86f0aaf867db14bfb7c4a9a32b" +dependencies = [ + "bitflags 2.2.1", + "js-sys", + "web-sys", +] + +[[package]] +name = "wgpu_calc" +version = "0.1.0" +dependencies = [ + "cgmath", + "encase", + "env_logger", + "log", + "pollster", + "regex", + "wgpu", + "winit", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +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.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[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.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winit" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c9651471cd576737671fbf7081edfea43de3e06846dd9bd4e49ea803c9f55f" +dependencies = [ + "android-activity", + "bitflags 1.3.2", + "cfg_aliases", + "core-foundation", + "core-graphics", + "dispatch", + "instant", + "libc", + "log", + "mio", + "ndk", + "objc2", + "once_cell", + "orbclient", + "percent-encoding", + "raw-window-handle", + "redox_syscall 0.3.5", + "sctk-adwaita", + "smithay-client-toolkit", + "wasm-bindgen", + "wayland-client", + "wayland-commons", + "wayland-protocols", + "wayland-scanner", + "web-sys", + "windows-sys 0.45.0", + "x11-dl", +] + +[[package]] +name = "winnow" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +dependencies = [ + "memchr", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "xcursor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" +dependencies = [ + "nom", +] + +[[package]] +name = "xml-rs" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "699d0104bcdd7e7af6d093d6c6e2d0c479b8a129ee0d1023b31d2e0c71bfdda2" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c73874b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "wgpu_calc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +wgpu = "0.16" +env_logger = "0.10" +log = "0.4" +pollster = "0.3" +winit = "0.28" +cgmath = "0.18" +encase = { version = "0.6", features = ["cgmath"] } +regex = "1.8" diff --git a/src/complex.rs b/src/complex.rs new file mode 100644 index 0000000..c9018ed --- /dev/null +++ b/src/complex.rs @@ -0,0 +1,132 @@ +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Complex { + pub re: f64, + pub im: f64 +} + +impl Complex { + pub const fn new(re: f64, im: f64) -> Self { + Self { re, im } + } +} + +impl From for Complex { + fn from(value: f64) -> Self { + Self { re: value, im: 0.0 } + } +} + +pub mod cxfn { + use super::Complex; + + pub type Function = fn(args: &[Complex]) -> Complex; + + pub fn pos(a: &[Complex]) -> Complex { + a[0] + } + + pub fn neg(a: &[Complex]) -> Complex { + Complex::new(-a[0].re, -a[0].im) + } + + pub fn recip(a: &[Complex]) -> Complex { + let a = a[0]; + let d = a.re*a.re + a.im*a.im; + Complex::new(a.re / d, -a.im / d) + } + + pub fn re(a: &[Complex]) -> Complex { + Complex::new(a[0].re, 0.0) + } + + pub fn im(a: &[Complex]) -> Complex { + Complex::new(a[0].im, 0.0) + } + + pub fn conj(a: &[Complex]) -> Complex { + Complex::new(a[0].re, -a[0].im) + } + + pub fn abs_sq(a: &[Complex]) -> Complex { + Complex::new(a[0].re*a[0].re + a[0].im*a[0].im, 0.0) + } + + pub fn abs(a: &[Complex]) -> Complex { + Complex::new((a[0].re*a[0].re + a[0].im*a[0].im).sqrt(), 0.0) + } + + pub fn arg(a: &[Complex]) -> Complex { + Complex::new(f64::atan2(a[0].im, a[0].re), 0.0) + } + + pub fn add(a: &[Complex]) -> Complex { + let (a, b) = (a[0], a[1]); + Complex::new(a.re + b.re, a.im + b.im) + } + + pub fn sub(a: &[Complex]) -> Complex { + let (a, b) = (a[0], a[1]); + Complex::new(a.re - b.re, a.im - b.im) + } + + pub fn mul(a: &[Complex]) -> Complex { + let (a, b) = (a[0], a[1]); + Complex::new(a.re*b.re - a.im*b.im, a.im*b.re + a.re*b.im) + } + + pub fn div(a: &[Complex]) -> Complex { + let (a, b) = (a[0], a[1]); + let d = b.re*b.re + b.im*b.im; + Complex::new((a.re*b.re + a.im*b.im)/d, (a.im*b.re - a.re*b.im)/d) + } + + pub fn exp(a: &[Complex]) -> Complex { + let e = a[0].re.exp(); + Complex::new(e * a[0].im.cos(), e * a[0].im.sin()) + } + + pub fn log(a: &[Complex]) -> Complex { + let a = a[0]; + Complex::new(0.5 * (a.re*a.re + a.im*a.im).ln(), f64::atan2(a.im, a.re)) + } + + pub fn pow(a: &[Complex]) -> Complex { + exp(&[mul(&[log(&[a[0]]), a[1]])]) + } + + pub fn sqrt(a: &[Complex]) -> Complex { + pow(&[a[0],Complex::new(0.5, 0.0)]) + } + + pub fn sin(a: &[Complex]) -> Complex { + let a = a[0]; + Complex::new(a.re.sin()*a.im.cosh(), a.re.cos()*a.im.sinh()) + } + + pub fn cos(a: &[Complex]) -> Complex { + let a = a[0]; + Complex::new(a.re.cos()*a.im.cosh(), -a.re.sin()*a.re.sinh()) + } + + pub fn tan(a: &[Complex]) -> Complex { + let a = a[0]; + let d = (2.0*a.re).cos() + (2.0*a.im).cosh(); + Complex::new((2.0*a.re).sin() / d, (2.0*a.im).sinh() / d) + } + + pub fn sinh(a: &[Complex]) -> Complex { + let a = a[0]; + Complex::new(a.re.sinh()*a.im.cos(), a.re.cosh()*a.re.sin()) + } + + pub fn cosh(a: &[Complex]) -> Complex { + let a = a[0]; + Complex::new(a.re.cosh()*a.im.cos(), a.re.sinh()*a.re.sin()) + } + + pub fn tanh(a: &[Complex]) -> Complex { + let a = a[0]; + let d = (2.0*a.re).cosh() + (2.0*a.im).cos(); + Complex::new((2.0*a.re).sinh() / d, (2.0*a.im).sin() / d) + } +} diff --git a/src/language/compiler.rs b/src/language/compiler.rs new file mode 100644 index 0000000..90054bc --- /dev/null +++ b/src/language/compiler.rs @@ -0,0 +1,449 @@ +use std::{collections::HashMap, fmt::Write}; + +use regex::Regex; + +use crate::complex::{Complex, cxfn}; + +use super::parser::{Expr, Stmt, UnaryOp, BinaryOp}; + +#[derive(Clone, Debug)] +pub enum CompileError<'s> { + FmtError, + TypeError(&'s str), + ArgCount(&'s str), + UndefinedVar(&'s str), + GlobalReassignment(&'s str), + BuiltinReassignment(&'s str), + StandaloneDerivative(&'s str), +} + +impl <'s> From for CompileError<'s> { + fn from(_: std::fmt::Error) -> Self { + Self::FmtError + } +} + +thread_local! { + pub static BUILTINS: HashMap<&'static str, (&'static str, Type, Option)> = { + let mut m: HashMap<&'static str, (&'static str, Type, Option)> = HashMap::new(); + m.insert("i", ("CONST_I", Type::Number, Some(|_| Complex::new(0.0, 1.0)))); + m.insert("e", ("CONST_E", Type::Number, Some(|_| Complex::new(std::f64::consts::E, 0.0)))); + m.insert("tau", ("CONST_TAU",Type::Number, Some(|_| Complex::new(std::f64::consts::TAU, 0.0)))); + m.insert("re", ("c_re", Type::Function(1), Some(cxfn::re))); + m.insert("im", ("c_im", Type::Function(1), Some(cxfn::im))); + m.insert("conj", ("c_conj", Type::Function(1), Some(cxfn::conj))); + m.insert("abs_sq", ("c_abs_sq", Type::Function(1), Some(cxfn::abs_sq))); + m.insert("abs", ("c_abs", Type::Function(1), Some(cxfn::abs))); + m.insert("arg", ("c_arg", Type::Function(1), Some(cxfn::arg))); + m.insert("pos", ("c_pos", Type::Function(1), Some(cxfn::pos))); + m.insert("neg", ("c_neg", Type::Function(1), Some(cxfn::neg))); + m.insert("recip", ("c_recip", Type::Function(1), Some(cxfn::recip))); + m.insert("add", ("c_add", Type::Function(2), Some(cxfn::add))); + m.insert("sub", ("c_sub", Type::Function(2), Some(cxfn::sub))); + m.insert("mul", ("c_mul", Type::Function(2), Some(cxfn::mul))); + m.insert("div", ("c_div", Type::Function(2), Some(cxfn::div))); + m.insert("recip", ("c_recip", Type::Function(1), Some(cxfn::recip))); + m.insert("exp", ("c_exp", Type::Function(1), Some(cxfn::exp))); + m.insert("log", ("c_log", Type::Function(1), Some(cxfn::log))); + m.insert("sqrt", ("c_sqrt", Type::Function(1), Some(cxfn::sqrt))); + m.insert("sin", ("c_sin", Type::Function(1), Some(cxfn::sin))); + m.insert("cos", ("c_cos", Type::Function(1), Some(cxfn::cos))); + m.insert("tan", ("c_tan", Type::Function(1), Some(cxfn::tan))); + m.insert("sinh", ("c_sinh", Type::Function(1), Some(cxfn::sinh))); + m.insert("cosh", ("c_cosh", Type::Function(1), Some(cxfn::cosh))); + m.insert("tanh", ("c_tanh", Type::Function(1), Some(cxfn::tanh))); + m.insert("gamma", ("c_gamma", Type::Function(1), None)); + m + }; + + static RE_INVOKE: Regex = Regex::new(r"^invoke(\d+)$").unwrap(); + static RE_ITER: Regex = Regex::new(r"^iter(\d+)$").unwrap(); +} + +#[derive(Clone, Copy)] +pub enum Type { + Number, + Function(u32), +} + +#[derive(Clone, PartialEq, Eq, Hash)] +enum Generate { + FunctionId { argc: u32, id: u32 }, + Invoke { argc: u32 }, + Iter { argc: u32 }, + Derivative { func: String, nderiv: u32, argc: u32 }, +} + +enum NameInfo { + Local { id: u32 }, + Global { ty: Type, cname: String }, + Builtin { ty: Type, bname: &'static str }, + Generated { ty: Type, gname: String, gen: Generate } +} + +impl NameInfo { + pub fn get_compiled_name(&self) -> String { + match self { + NameInfo::Local { id } => format!("arg_{id}"), + NameInfo::Global { cname, .. } => cname.to_owned(), + NameInfo::Builtin { bname, .. } => (*bname).to_owned(), + NameInfo::Generated { gname, .. } => gname.to_owned(), + } + } +} + +type LocalTable<'s> = HashMap<&'s str, u32>; + +type CompileResult<'s,T=()> = Result>; + +pub fn compile<'s>(buf: &mut impl Write, stmts: &[Stmt<'s>]) -> CompileResult<'s> { + let mut compiler = Compiler::new(buf); + for stmt in stmts { + compiler.compile_stmt(stmt)?; + } + compiler.generate()?; + Ok(()) +} + + +struct Compiler<'s, 'w, W> where W: Write { + buf: &'w mut W, + globals: HashMap<&'s str, Type>, + generate: HashMap, + next_fn_id: u32, +} + +impl <'s, 'w, W: Write> Compiler<'s, 'w, W> { + fn new(buf: &'w mut W) -> Self { + Self { + buf, + globals: HashMap::new(), + generate: HashMap::new(), + next_fn_id: 0, + } + } + + ////////////////// + // Statements // + ////////////////// + + fn compile_stmt(&mut self, stmt: &Stmt<'s>) -> CompileResult<'s> { + match stmt { + Stmt::AssignConst(name, expr) => { + if BUILTINS.with(|m| m.contains_key(name)) { + return Err(CompileError::BuiltinReassignment(name)) + } + if self.globals.contains_key(name) { + return Err(CompileError::GlobalReassignment(name)) + } + self.globals.insert(name, Type::Number); + write!(self.buf, "const VAR_{name} = ")?; + + let locals = LocalTable::with_capacity(0); + self.compile_expr(&locals, expr)?; + + write!(self.buf, ";")?; + } + Stmt::AssignFunc(name, args, expr) => { + if BUILTINS.with(|m| m.contains_key(name)) { + return Err(CompileError::BuiltinReassignment(name)) + } + if self.globals.contains_key(name) { + return Err(CompileError::GlobalReassignment(name)) + } + self.globals.insert(name, Type::Function(args.len() as u32)); + write!(self.buf, "fn func_{name}(")?; + + let mut locals = LocalTable::with_capacity(args.len()); + for (i, arg) in args.iter().enumerate() { + write!(self.buf, "arg_{}:vec2f,", i)?; + locals.insert(arg, i as u32); + } + write!(self.buf, ")->vec2f{{return ")?; + self.compile_expr(&locals, expr)?; + write!(self.buf, ";}}")?; + } + } + writeln!(self.buf)?; + Ok(()) + } + + /////////////////// + // Expressions // + /////////////////// + + fn compile_expr(&mut self, locals: &LocalTable<'s>, expr: &Expr<'s>) -> CompileResult<'s> { + match expr { + Expr::Number(z) => self.compile_number(*z), + Expr::Name(name) => self.compile_var(locals, name), + Expr::NameDeriv(name, _) => return Err(CompileError::StandaloneDerivative(name)), + Expr::Unary(op, arg) => self.compile_unary(locals, *op, arg), + Expr::Binary(op, lhs, rhs) => self.compile_binary(locals, *op, lhs, rhs), + Expr::FnCall { name, args, nderiv } => self.compile_fncall(locals, name, args, *nderiv), + } + } + + fn compile_number(&mut self, z: Complex) -> CompileResult<'s> { + write!(self.buf, "vec2f({:?},{:?})", z.re, z.im)?; + Ok(()) + } + + fn compile_unary(&mut self, locals: &LocalTable<'s>, op: UnaryOp, arg: &Expr<'s>) -> CompileResult<'s> { + let strings = unop_strings(op); + write!(self.buf, "{}", strings[0])?; + self.compile_expr(locals, arg)?; + write!(self.buf, "{}", strings[1])?; + Ok(()) + } + + fn compile_binary(&mut self, locals: &LocalTable<'s>, op: BinaryOp, lhs: &Expr<'s>, rhs: &Expr<'s>) -> CompileResult<'s> { + let strings = binop_strings(op); + write!(self.buf, "{}", strings[0])?; + self.compile_expr(locals, lhs)?; + write!(self.buf, "{}", strings[1])?; + self.compile_expr(locals, rhs)?; + write!(self.buf, "{}", strings[2])?; + Ok(()) + } + + fn compile_var(&mut self, locals: &LocalTable<'s>, name: &'s str) -> CompileResult<'s> { + let Some(name_info) = self.name_info(name, Some(locals)) else { + return Err(CompileError::UndefinedVar(name)) + }; + self.compile_name(name, name_info)?; + Ok(()) + } + + fn compile_fncall(&mut self, locals: &LocalTable<'s>, name: &'s str, args: &Vec>, nderiv: u32) -> CompileResult<'s> { + let Some(name_info) = self.name_info(name, Some(locals)) else { + return Err(CompileError::UndefinedVar(name)) + }; + let compname = &name_info.get_compiled_name(); + for i in 0..nderiv { + self.add_gen_deriv(&compname, i+1, args.len() as u32); + write!(self.buf, "deriv_")?; + } + self.compile_name_fncall(name, name_info, args.len() as u32)?; + write!(self.buf, "(")?; + for arg in args { + self.compile_expr(locals, arg)?; + write!(self.buf, ",")?; + } + write!(self.buf, ")")?; + Ok(()) + } + + ///////////// + // Names // + ///////////// + + + fn compile_name_fncall(&mut self, name: &'s str, name_info: NameInfo, argc: u32) -> CompileResult<'s> { + match name_info { + NameInfo::Local { .. } => return Err(CompileError::TypeError(name)), + NameInfo::Global { ty: Type::Function(c), cname } if c == argc => { + write!(self.buf, "{cname}")?; + } + NameInfo::Global { ty: Type::Function(_), .. } => return Err(CompileError::ArgCount(name)), + NameInfo::Global { .. } => return Err(CompileError::TypeError(name)), + NameInfo::Builtin { ty: Type::Function(c), bname } if c == argc => { + write!(self.buf, "{bname}")?; + } + NameInfo::Builtin { ty: Type::Function(_), .. } => return Err(CompileError::ArgCount(name)), + NameInfo::Builtin { .. } => return Err(CompileError::TypeError(name)), + NameInfo::Generated { ty: Type::Function(c), gname, gen } if c == argc => { + write!(self.buf, "{gname}")?; + self.generate.insert(gname, gen); + } + NameInfo::Generated { ty: Type::Function(_), .. } => return Err(CompileError::ArgCount(name)), + NameInfo::Generated { .. } => return Err(CompileError::TypeError(name)), + } + Ok(()) + } + + fn compile_name(&mut self, name: &str, name_info: NameInfo) -> CompileResult<'s> { + match name_info { + NameInfo::Local { id } => { + write!(self.buf, "arg_{id}")?; + }, + NameInfo::Global { ty: Type::Function(c), cname } => { + self.add_gen_fid(format!("{cname}"), c); + write!(self.buf, "FID_{cname}")?; + }, + NameInfo::Global { ty: Type::Number, .. } => { + write!(self.buf, "VAR_{name}")?; + }, + NameInfo::Builtin { ty: Type::Function(c), bname } => { + self.add_gen_fid(bname.to_owned(), c); + write!(self.buf, "FID_{bname}")?; + }, + NameInfo::Builtin { ty: Type::Number, bname } => { + write!(self.buf, "{bname}")?; + }, + NameInfo::Generated { ty: Type::Function(c), gname, gen } => { + write!(self.buf, "FID_{gname}")?; + self.add_gen_fid(gname.to_owned(), c); + self.generate.insert(gname, gen); + }, + NameInfo::Generated { ty: Type::Number, gname, gen } => { + write!(self.buf, "{gname}")?; + self.generate.insert(gname, gen); + }, + } + Ok(()) + } + + fn name_info(&self, name: &'s str, locals: Option<&LocalTable<'s>>) -> Option { + if let Some(locals) = locals { + if let Some(id) = locals.get(name) { + return Some(NameInfo::Local { id: *id }) + } + } + if let Some(ty) = self.globals.get(name) { + return Some(NameInfo::Global { ty: *ty, cname: format!("func_{name}") }) + } + if let Some((bname, ty, _)) = BUILTINS.with(|m| m.get(name).copied()) { + return Some(NameInfo::Builtin { ty, bname }) + } + if let Some(caps) = RE_INVOKE.with(|re| re.captures(name)) { + if let Ok(n) = caps[1].parse() { + return Some(NameInfo::Generated { + ty: Type::Function(n + 1), + gname: format!("invoke{n}"), + gen: Generate::Invoke { argc: n }, + }) + } + } + if let Some(caps) = RE_ITER.with(|re| re.captures(name)) { + if let Ok(n) = caps[1].parse() { + return Some(NameInfo::Generated { + ty: Type::Function(n + 2), + gname: format!("iter{n}"), + gen: Generate::Iter { argc: n } + }) + } + } + None + } + + ////////////////// + // Generation // + ////////////////// + + fn add_gen_fid(&mut self, name: String, argc: u32) { + self.generate.insert(name, Generate::FunctionId { argc, id: self.next_fn_id }); + self.next_fn_id += 1; + } + + fn add_gen_deriv(&mut self, name: &str, nderiv: u32, argc: u32) { + let func_name = "deriv_".repeat(nderiv as usize - 1) + name; + let deriv_name = "deriv_".repeat(nderiv as usize) + name; + self.generate.insert(deriv_name, Generate::Derivative { func: func_name, nderiv, argc }); + } + + fn generate(&mut self) -> CompileResult<'s> { + for (name, g) in self.generate.clone() { + match g { + Generate::FunctionId { id, .. } => { + write!(self.buf, "const FID_{name}=vec2f({id}.0,0.0);")?; + } + Generate::Invoke { argc } => self.generate_invoke(argc)?, + Generate::Iter { argc } => self.generate_iter(argc)?, + Generate::Derivative { func, nderiv, argc } => self.generate_derivative(func, nderiv, argc)?, + } + writeln!(self.buf)?; + } + Ok(()) + } + + fn generate_invoke(&mut self, argc: u32) -> CompileResult<'s> { + write!(self.buf, "fn invoke{argc}(func:vec2f,")?; + for i in 0..argc { + write!(self.buf, "arg_{i}:vec2f")?; + write!(self.buf, ",")?; + } + write!(self.buf, ")->vec2f{{switch i32(func.x){{")?; + for (name, g) in &self.generate { + if let Generate::FunctionId { argc: fargc, id } = g { + write!(self.buf, "case {id}")?; + if *id == 0 { + write!(self.buf, ",default")?; + } + write!(self.buf, "{{return {name}(")?; + let a = argc.min(*fargc); + for i in 0..a { + write!(self.buf, "arg_{i},")?; + } + for _ in a..*fargc { + write!(self.buf, "vec2f(0.0),")?; + } + write!(self.buf, ");}}")?; + } + } + write!(self.buf, "}};}}")?; + Ok(()) + } + + fn generate_iter(&mut self, argc: u32) -> CompileResult<'s> { + if !self.generate.contains_key(&format!("invoke{argc}")) { + self.generate.insert(format!("invoke{argc}"), Generate::Iter { argc }); + self.generate_invoke(argc)?; + writeln!(self.buf)?; + } + write!(self.buf, "fn iter{argc}(func:vec2f,n:vec2f,")?; + for i in 0..argc { + write!(self.buf, "arg_{i}:vec2f")?; + write!(self.buf, ",")?; + } + write!(self.buf, ")->vec2f{{var result=arg_0;")?; + write!(self.buf, "for(var i=0;i CompileResult<'s> { + if let Some(f) = func.strip_suffix("deriv_") { + if !self.generate.contains_key(f) { + self.generate.insert(func.clone(), Generate::Derivative { func: f.to_owned(), nderiv: nderiv - 1, argc }); + self.generate_derivative(f.to_owned(), nderiv - 1, argc)?; + } + } + write!(self.buf, "fn deriv_{func}(z:vec2f")?; + let mut args = String::new(); + for i in 1..argc { + write!(self.buf, ",arg{i}:vec2f")?; + args += &format!(",arg{i}"); + } + write!(self.buf, ")->vec2f{{")?; + write!(self.buf, "\ + let a = c_mul({func}(z + vec2( D_EPS, 0.0){args}), vec2( 0.25/D_EPS, 0.0));\ + let b = c_mul({func}(z + vec2(-D_EPS, 0.0){args}), vec2(-0.25/D_EPS, 0.0));\ + let c = c_mul({func}(z + vec2(0.0, D_EPS){args}), vec2(0.0, -0.25/D_EPS));\ + let d = c_mul({func}(z + vec2(0.0, -D_EPS){args}), vec2(0.0, 0.25/D_EPS));\ + return a + b + c + d;}}\ + ")?; + Ok(()) + } +} + + +const fn unop_strings(op: UnaryOp) -> [&'static str; 2] { + match op { + UnaryOp::Pos => ["+(", ")"], + UnaryOp::Neg => ["-(", ")"], + UnaryOp::Recip => ["c_recip(", ")"], + } +} + +const fn binop_strings(op: BinaryOp) -> [&'static str; 3] { + match op { + BinaryOp::Add => ["(", ")+(", ")"], + BinaryOp::Sub => ["(", ")-(", ")"], + BinaryOp::Mul => ["c_mul(", ",", ")"], + BinaryOp::Div => ["c_div(", ",", ")"], + BinaryOp::Pow => ["c_pow(", ",", ")"], + } +} diff --git a/src/language/mod.rs b/src/language/mod.rs new file mode 100644 index 0000000..66f36bb --- /dev/null +++ b/src/language/mod.rs @@ -0,0 +1,42 @@ +mod scanner; +mod parser; +mod compiler; +mod optimizer; + +pub use parser::ParseError; +pub use compiler::CompileError; + +use self::optimizer::optimize; + +#[derive(Debug, Clone, Copy)] +pub struct Position { + pub pos: u32, + pub line: u32, + pub col: u32, +} + +#[derive(Clone, Debug)] +pub enum Error<'s> { + Parse(ParseError<'s>), + Compile(CompileError<'s>), +} + +impl <'s> From> for Error<'s> { + fn from(value: CompileError<'s>) -> Self { + Self::Compile(value) + } +} + +impl <'s> From> for Error<'s> { + fn from(value: ParseError<'s>) -> Self { + Self::Parse(value) + } +} + +pub fn compile(src: &str) -> Result { + let mut buf = String::new(); + let stmts = parser::Parser::new(src).parse()?; + let stmts = optimize(stmts); + compiler::compile(&mut buf, &stmts)?; + Ok(buf) +} diff --git a/src/language/optimizer.rs b/src/language/optimizer.rs new file mode 100644 index 0000000..06e3db8 --- /dev/null +++ b/src/language/optimizer.rs @@ -0,0 +1,65 @@ +use crate::complex::{Complex, cxfn}; + +use super::{parser::{Expr, UnaryOp, BinaryOp, Stmt}, compiler::{BUILTINS, Type}}; + +fn apply_unary(op: UnaryOp, arg: Complex) -> Complex { + match op { + UnaryOp::Pos => cxfn::pos(&[arg]), + UnaryOp::Neg => cxfn::neg(&[arg]), + UnaryOp::Recip => cxfn::recip(&[arg]), + } +} + +fn apply_binary(op: BinaryOp, u: Complex, v: Complex) -> Complex { + match op { + BinaryOp::Add => cxfn::add(&[u, v]), + BinaryOp::Sub => cxfn::sub(&[u, v]), + BinaryOp::Mul => cxfn::mul(&[u, v]), + BinaryOp::Div => cxfn::div(&[u, v]), + BinaryOp::Pow => cxfn::pow(&[u, v]), + } +} + +pub fn optimize<'s>(stmts: Vec>) -> Vec> { + stmts.into_iter().map(|s| match s { + Stmt::AssignConst(a, expr) => Stmt::AssignConst(a, optimize_expr(expr)), + Stmt::AssignFunc(a, b, expr) => Stmt::AssignFunc(a, b, optimize_expr(expr)), + }).collect() +} + +fn optimize_expr<'s>(e: Expr<'s>) -> Expr<'s> { + match e { + Expr::Unary(op, arg) => { + match optimize_expr(*arg) { + Expr::Number(z) => Expr::Number(apply_unary(op, z)), + e => Expr::Unary(op, Box::new(e)), + } + }, + Expr::Binary(op, lhs, rhs) => { + match (optimize_expr(*lhs), optimize_expr(*rhs)) { + (Expr::Number(u), Expr::Number(v)) => Expr::Number(apply_binary(op, u, v)), + (u, v) => Expr::Binary(op, Box::new(u), Box::new(v)) + } + }, + Expr::FnCall { name, args, nderiv } => { + let args: Vec> = args.into_iter().map(|a| optimize_expr(a)).collect(); + if let Some((_, Type::Function(argc), Some(func))) = BUILTINS.with(|m| m.get(name).copied()) { + if argc as usize == args.len() && nderiv == 0 { + if args.iter().all(|e| matches!(e, Expr::Number(_))) { + let ns: Vec = args.into_iter().map(|a| match a { Expr::Number(n) => n, _ => unreachable!() }).collect(); + return Expr::Number(func(&ns)) + } + } + } + Expr::FnCall { name, args, nderiv } + } + Expr::Name(name) => { + if let Some((_, Type::Number, Some(func))) = BUILTINS.with(|m| m.get(name).copied()) { + Expr::Number(func(&[])) + } else { + e + } + } + _ => e, + } +} diff --git a/src/language/parser.rs b/src/language/parser.rs new file mode 100644 index 0000000..1cfba2c --- /dev/null +++ b/src/language/parser.rs @@ -0,0 +1,216 @@ +use std::iter::Peekable; + +use crate::complex::Complex; + +use super::{scanner::{Scanner, Token}, Position}; + +#[derive(Clone, Debug)] +pub enum ParseError<'s> { + UnexpectedTokenPrefix(Position, Token<'s>), + Expected(Position, Token<'s>), + InvalidLValue(Position), + InvalidFunction(Expr<'s>), + UnexpectedEof, +} +#[derive(Debug, Clone, Copy)] +pub enum BinaryOp { + Add, Sub, Mul, Div, Pow, +} + +impl BinaryOp { + pub const fn from_token(tok: Token) -> Option { + match tok { + Token::Plus => Some(Self::Add), + Token::Minus => Some(Self::Sub), + Token::Star => Some(Self::Mul), + Token::Slash => Some(Self::Div), + Token::Caret => Some(Self::Pow), + _ => None, + } + } + + pub const fn precedence(self) -> (u32, u32) { + match self { + BinaryOp::Add => (10, 11), + BinaryOp::Sub => (10, 11), + BinaryOp::Mul => (20, 21), + BinaryOp::Div => (20, 21), + BinaryOp::Pow => (31, 30), + } + } + +} + +#[derive(Debug, Clone, Copy)] +pub enum UnaryOp { + Pos, Neg, Recip, +} + +impl UnaryOp { + pub const fn from_token(tok: Token) -> Option { + match tok { + Token::Plus => Some(Self::Pos), + Token::Minus => Some(Self::Neg), + Token::Slash => Some(Self::Recip), + _ => None, + } + } + + pub const fn precedence(self) -> u32 { + 40 + } +} + +#[derive(Clone, Debug)] +pub enum Expr<'s> { + Number(Complex), + Name(&'s str), + NameDeriv(&'s str, u32), + Unary(UnaryOp, Box>), + Binary(BinaryOp, Box>, Box>), + FnCall { name: &'s str, args: Vec>, nderiv: u32 }, +} + +#[derive(Debug)] +pub enum Stmt<'s> { + AssignConst(&'s str, Expr<'s>), + AssignFunc(&'s str, Vec<&'s str>, Expr<'s>), +} + +pub struct Parser<'s> { + scanner: Peekable>, +} + +impl <'s> Parser<'s> { + pub fn new(src: &'s str) -> Self { + Self { + scanner: Scanner::new(src).peekable() + } + } + + fn expect(&mut self, tok: Token<'s>) -> Result> { + match self.scanner.peek() { + Some((p, t)) if *t == tok => { + let p = *p; + self.scanner.next(); + Ok(p) + }, + Some((p, _)) => Err(ParseError::Expected(*p, tok)), + None => Err(ParseError::UnexpectedEof), + } + } + + fn expr(&mut self, min_prec: u32) -> Result, ParseError<'s>> { + let (pos, tok) = self.scanner.next().unwrap(); + let mut expr = match tok { + Token::Number(n) => Expr::Number(Complex::from(n)), + Token::Name(n) => Expr::Name(n), + Token::LParen => { + let e = self.expr(0)?; + self.expect(Token::RParen)?; + e + } + tok => if let Some(op) = UnaryOp::from_token(tok) { + Expr::Unary(op, Box::new(self.expr(op.precedence())?)) + } else { + return Err(ParseError::UnexpectedTokenPrefix(pos, tok)) + } + }; + + while let Some((_, tok)) = self.scanner.peek() { + expr = match tok { + Token::Equal | Token::RParen | Token::Newline | Token::Comma => break, + Token::Quote => { + self.scanner.next(); + match expr { + Expr::Name(name) => Expr::NameDeriv(name, 1), + Expr::NameDeriv(name, nderiv) => Expr::NameDeriv(name, nderiv+1), + _ => return Err(ParseError::InvalidFunction(expr)) + } + }, + Token::LParen => { + self.scanner.next(); + let mut args = Vec::new(); + while !matches!(self.scanner.peek(), None | Some((_, Token::RParen))) { + args.push(self.expr(0)?); + match self.scanner.peek() { + Some((_, Token::Comma)) => { self.scanner.next(); }, + Some((_, Token::RParen)) => break, + Some((pos, _)) => return Err(ParseError::Expected(*pos, Token::RParen)), + None => return Err(ParseError::UnexpectedEof), + } + } + self.expect(Token::RParen)?; + match expr { + Expr::Name(name) => Expr::FnCall { name, args, nderiv: 0 }, + Expr::NameDeriv(name, nderiv) => Expr::FnCall { name, args, nderiv }, + _ => return Err(ParseError::InvalidFunction(expr)), + } + }, + tok => if let Some(op) = BinaryOp::from_token(*tok) { + let (lp, rp) = op.precedence(); + if lp < min_prec { + break; + } + self.scanner.next(); + let rhs = self.expr(rp)?; + Expr::Binary(op, Box::new(expr), Box::new(rhs)) + } else { + let (lp, rp) = BinaryOp::Mul.precedence(); + if lp < min_prec { + break; + } + let rhs = self.expr(rp)?; + Expr::Binary(BinaryOp::Mul, Box::new(expr), Box::new(rhs)) + } + } + } + + Ok(expr) + } + + pub fn parse(&mut self) -> Result>, ParseError<'s>> { + let mut stmts = Vec::new(); + while self.scanner.peek().is_some() { + while matches!(self.scanner.peek(), Some((_, Token::Newline))) { + self.scanner.next(); + } + + if self.scanner.peek().is_none() { + break; + } + + let lhs_pos = self.scanner.peek().unwrap().0; + let lhs = self.expr(0)?; + + self.expect(Token::Equal)?; + + if self.scanner.peek().is_none() { + return Err(ParseError::UnexpectedEof) + } + + let rhs = self.expr(0)?; + + if self.scanner.peek().is_some() { + self.expect(Token::Newline)?; + } + + let stmt = match lhs { + Expr::Name(name) => Stmt::AssignConst(name, rhs), + Expr::FnCall { name, args, nderiv: 0 } => { + let mut arg_names = Vec::with_capacity(args.len()); + for arg in args { + if let Expr::Name(name) = arg { + arg_names.push(name) + } + } + Stmt::AssignFunc(name, arg_names, rhs) + } + _ => return Err(ParseError::InvalidLValue(lhs_pos)) + }; + + stmts.push(stmt); + } + Ok(stmts) + } +} diff --git a/src/language/scanner.rs b/src/language/scanner.rs new file mode 100644 index 0000000..bfe0753 --- /dev/null +++ b/src/language/scanner.rs @@ -0,0 +1,116 @@ +use std::{iter::Peekable, str::Chars}; + +use super::Position; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Token<'s> { + Error, + Name(&'s str), + Number(f64), + Plus, + Minus, + Star, + Slash, + Caret, + Equal, + Comma, + Quote, + LParen, + RParen, + Newline, +} + +pub struct Scanner<'s> { + pub src: &'s str, + pub chars: Peekable>, + pub pos: Position, +} + +impl <'s> Scanner<'s> { + pub fn new(src: &'s str) -> Self { + Self { + src, + chars: src.chars().peekable(), + pos: Position { pos: 0, line: 1, col: 1 } + } + } + + fn next(&mut self) -> Option { + match self.chars.next() { + Some('\n') => { + self.pos.pos += 1; + self.pos.line += 1; + self.pos.col = 1; + Some('\n') + }, + Some(c) => { + self.pos.pos += 1; + self.pos.col += 1; + Some(c) + }, + None => None, + } + } + + fn peek(&mut self) -> Option { + self.chars.peek().copied() + } + + fn next_number(&mut self, pos: u32) -> Token<'s> { + while matches!(self.peek(), Some('0'..='9')) { + self.next(); + } + if matches!(self.peek(), Some('.')) { + self.next(); + while matches!(self.peek(), Some('0'..='9')) { + self.next(); + } + } + let s = &self.src[pos as usize..self.pos.pos as usize]; + match s.parse() { + Ok(x) => Token::Number(x), + Err(_) => Token::Error, + } + } + + fn next_name(&mut self, pos: u32) -> Token<'s> { + while matches!(self.peek(), Some('a'..='z' | 'A'..='Z' | '0'..='9' | '_')) { + self.next(); + } + let s = &self.src[pos as usize..self.pos.pos as usize]; + Token::Name(s) + } + + pub fn next_token(&mut self) -> Option<(Position, Token<'s>)> { + while matches!(self.peek(), Some(' ' | '\t')) { + self.next(); + } + self.peek()?; + let pos = self.pos; + let tok = match self.next().unwrap() { + '\n' => Token::Newline, + '+' => Token::Plus, + '-' => Token::Minus, + '*' => Token::Star, + '/' => Token::Slash, + '^' => Token::Caret, + '\'' => Token::Quote, + '=' => Token::Equal, + ',' => Token::Comma, + '(' => Token::LParen, + ')' => Token::RParen, + '0'..='9' => self.next_number(pos.pos), + 'a'..='z' | 'A'..='Z' => self.next_name(pos.pos), + _ => Token::Error, + }; + Some((pos, tok)) + } +} + +impl <'s> Iterator for Scanner<'s> { + type Item = (Position, Token<'s>); + + fn next(&mut self) -> Option { + self.next_token() + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6e822e7 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,26 @@ +use language::compile; +use renderer::run; +use winit::{event_loop::EventLoop, window::Window}; + +mod language; +mod renderer; +mod complex; + +fn main() { + env_logger::init(); + + let src = r#" + f(z,a,b,c) = (z-a)*(z-b)*(z-c) + g(z,a,b,c) = z - f(z,a,b,c)/f'(z,a,b,c) + plot(z) = iter4(g, 50, z/3, z, 1, -1) + "#; + let wgsl = compile(src).unwrap(); + println!("{}", wgsl); + + let event_loop = EventLoop::new(); + let window = Window::new(&event_loop).unwrap(); + window.set_title("window"); + + pollster::block_on(run(event_loop, window, &wgsl)); + +} diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs new file mode 100644 index 0000000..050cdb9 --- /dev/null +++ b/src/renderer/mod.rs @@ -0,0 +1,236 @@ +use std::num::NonZeroU64; + +use encase::{ShaderType, ShaderSize, UniformBuffer}; +use wgpu::util::DeviceExt; +use winit::{event_loop::EventLoop, window::Window, event::{Event, WindowEvent}, dpi::PhysicalSize}; + +type Vec2u = cgmath::Vector2; +type Vec2f = cgmath::Vector2; + +#[derive(ShaderType)] +struct Uniforms { + resolution: Vec2u, + bounds_min: Vec2f, + bounds_max: Vec2f, + shading_intensity: f32, +} + +struct State { + surface: wgpu::Surface, + device: wgpu::Device, + config: wgpu::SurfaceConfiguration, + render_pipeline: Option, + uniform_bind_group: wgpu::BindGroup, + uniform_bind_group_layout: wgpu::BindGroupLayout, + uniform_buffer: wgpu::Buffer, + queue: wgpu::Queue, +} + +impl State { + async fn new(window: &Window) -> Self { + let size = window.inner_size(); + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default()); + let surface = unsafe { instance.create_surface(&window) }.unwrap(); + + let adapter = instance.request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }).await.unwrap(); + + let (device, queue) = adapter.request_device( + &wgpu::DeviceDescriptor { + label: None, + features: wgpu::Features::empty(), + limits: wgpu::Limits::default(), + }, + None + ).await.unwrap(); + + let format = surface.get_capabilities(&adapter).formats[0]; + + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format, + width: size.width, + height: size.height, + present_mode: wgpu::PresentMode::Mailbox, + alpha_mode: wgpu::CompositeAlphaMode::Auto, + view_formats: vec![format], + }; + surface.configure(&device, &config); + + // Uniforms // + + let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: None, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + contents: &[0; Uniforms::SHADER_SIZE.get() as usize], + }); + + let uniform_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + binding: 1, + }, + ] + }); + + let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &uniform_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &uniform_buffer, + offset: 0, + size: Some(NonZeroU64::new(Uniforms::SHADER_SIZE.get()).unwrap()), + }), + }, + ], + }); + + // Done // + + Self { + surface, + device, + config, + render_pipeline: None, + queue, + uniform_bind_group, + uniform_bind_group_layout, + uniform_buffer, + } + } + + fn load_shaders(&mut self, userdefs: &str) { + // Shaders // + let src = include_str!("shader.wgsl"); + let src = src.replace("//INCLUDE//\n", userdefs); + + let shader = self.device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(src.into()) + }); + + let vertex = wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[] + }; + + let fragment = wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: self.config.format, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent::REPLACE, + alpha: wgpu::BlendComponent::REPLACE, + }), + write_mask: wgpu::ColorWrites::ALL, + })], + }; + + // Pipeline // + + let pipeline_layout = self.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&self.uniform_bind_group_layout], + push_constant_ranges: &[], + }); + + let render_pipeline = self.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + vertex, + fragment: Some(fragment), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }); + + self.render_pipeline = Some(render_pipeline); + } + + fn redraw(&self, uniforms: &Uniforms) { + let frame = self.surface.get_current_texture().unwrap(); + let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + { + let color_attachment = wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: true, + } + }; + + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(color_attachment)], + depth_stencil_attachment: None, + }); + if let Some(pipeline) = &self.render_pipeline { + rpass.set_pipeline(pipeline); + rpass.set_bind_group(0, &self.uniform_bind_group, &[]); + rpass.draw(0..3, 0..1); + rpass.draw(1..4, 0..1); + } + } + let mut uniform_buffer = UniformBuffer::new([0; Uniforms::SHADER_SIZE.get() as usize]); + uniform_buffer.write(uniforms).unwrap(); + self.queue.write_buffer(&self.uniform_buffer, 0, &uniform_buffer.into_inner()); + self.queue.submit(Some(encoder.finish())); + frame.present(); + } + + fn resize(&mut self, size: PhysicalSize) { + self.config.width = size.width; + self.config.height = size.height; + self.surface.configure(&self.device, &self.config); + } +} + +pub async fn run(event_loop: EventLoop<()>, window: Window, code: &str) { + let mut state = State::new(&window).await; + state.load_shaders(code); + let mut uniforms = Uniforms { + resolution: [window.inner_size().width, window.inner_size().height].into(), + bounds_min: [0.73, 0.65].into(), + bounds_max: [0.98, 0.9].into(), + shading_intensity: 0.001, + }; + + event_loop.run(move |event, _, control_flow| { + control_flow.set_wait(); + match event { + Event::WindowEvent { event: WindowEvent::CloseRequested, .. } + => control_flow.set_exit(), + Event::RedrawRequested(_) + => state.redraw(&uniforms), + Event::WindowEvent { event: WindowEvent::Resized(size), .. } => { + uniforms.resolution = [size.width, size.height].into(); + state.resize(size); + window.request_redraw() + } + Event::MainEventsCleared => { + //window.request_redraw(); + } + _ => (), + } + }); +} diff --git a/src/renderer/shader.wgsl b/src/renderer/shader.wgsl new file mode 100644 index 0000000..a07e5c1 --- /dev/null +++ b/src/renderer/shader.wgsl @@ -0,0 +1,205 @@ +//////////////// +// uniforms // +//////////////// + +struct Uniforms { + resolution: vec2u, + bounds_min: vec2f, + bounds_max: vec2f, + shading_intensity: f32, +} + +@group(0) @binding(1) var uniforms: Uniforms; + +/////////////// +// utility // +/////////////// + +fn remap(val: vec2f, a1: vec2f, b1: vec2f, a2: vec2f, b2: vec2f) -> vec2f { + return a2 + (b2 - a2) * ((val - a1) / (b1 - a1)); +} + +///////////////// +// constants // +///////////////// + +const TAU = 6.283185307179586; +const E = 2.718281828459045; + +///////////////////////// +// complex functions // +///////////////////////// + +fn c_re(z: vec2f) -> vec2f { + return vec2(z.x, 0.0); +} + +fn c_im(z: vec2f) -> vec2f { + return vec2(z.y, 0.0); +} + +fn c_conj(z: vec2f) -> vec2f { + return z * vec2(1.0, -1.0); +} + +fn c_abs_sq(z: vec2f) -> vec2f { + return vec2(dot(z, z), 0.0); +} + +fn c_abs(z: vec2f) -> vec2f { + return vec2(sqrt(dot(z, z)), 0.0); +} + +fn c_arg(z: vec2f) -> vec2f { + return vec2(atan2(z.y, z.x), 0.0); +} + +fn c_add(u: vec2f, v: vec2f) -> vec2f { + return u + v; +} + +fn c_sub(u: vec2f, v: vec2f) -> vec2f { + return u - v; +} + +fn c_mul(u: vec2f, v: vec2f) -> vec2f { + return vec2(u.x*v.x - u.y*v.y, u.y*v.x + u.x*v.y); +} + +fn c_div(u: vec2f, v: vec2f) -> vec2f { + return vec2(u.x*v.x + u.y*v.y, u.y*v.x - u.x*v.y) / dot(v, v); +} + +fn c_pos(v: vec2f) -> vec2f { + return v; +} + +fn c_neg(v: vec2f) -> vec2f { + return -v; +} + +fn c_recip(v: vec2f) -> vec2f { + return vec2(v.x, -v.y) / dot(v, v); +} + +fn c_exp(z: vec2f) -> vec2f { + return exp(z.x) * vec2(cos(z.y), sin(z.y)); +} + +fn c_log(z: vec2f) -> vec2f { + return vec2(0.5 * log(dot(z, z)), atan2(z.y, z.x)); +} + +fn c_pow(u: vec2f, v: vec2f) -> vec2f { + return c_exp(c_mul(c_log(u), v)); +} + +fn c_sqrt(z: vec2f) -> vec2f { + return c_pow(z, vec2(0.5, 0.0)); +} + +fn c_sin(z: vec2f) -> vec2f { + return vec2(sin(z.x)*cosh(z.y), cos(z.x)*sinh(z.y)); +} + +fn c_cos(z: vec2f) -> vec2f { + return vec2(cos(z.x)*cosh(z.y), -sin(z.x)*sinh(z.y)); +} + +fn c_tan(z: vec2f) -> vec2f { + return vec2(sin(2.0*z.x), sinh(2.0*z.y)) / (cos(2.0*z.x) + cosh(2.0*z.y)); +} + +fn c_sinh(z: vec2f) -> vec2f { + return vec2(sinh(z.x)*cos(z.y), cosh(z.x)*sin(z.y)); +} + +fn c_cosh(z: vec2f) -> vec2f { + return vec2(cosh(z.x)*cos(z.y), sinh(z.x)*sin(z.y)); +} + +fn c_tanh(z: vec2f) -> vec2f { + return vec2(sinh(2.0*z.x), sin(2.0*z.y)) / (cosh(2.0*z.x) + cos(2.0*z.y)); +} + +fn c_gamma(z: vec2f) -> vec2f { + let reflect = z.x < 0.5; + var zp = z; + if reflect { + zp = vec2(1.0, 0.0) - z; + } + var w = c_gamma_inner2(zp); + if reflect { + w = TAU * 0.5 * c_recip(c_mul(c_sin(TAU * 0.5 * z), w)); + } + return w; +} + +// Yang, ZH., Tian, JF. An accurate approximation formula for gamma function. J Inequal Appl 2018, 56 (2018). +// https://doi.org/10.1186/s13660-018-1646-6 +fn c_gamma_inner(z: vec2f) -> vec2f { + let z2 = c_mul(z, z); + let z3 = c_mul(z2, z); + + let a = c_sqrt(TAU * z); + let b = c_pow(1.0 / (E * E) * c_mul(z3, c_sinh(c_recip(z))), 0.5 * z); + let c = c_exp(7.0/324.0 * c_recip(c_mul(z3, 35.0 * z2 + 33.0))); + + return c_mul(c_mul(a, b), c); +} + +fn c_gamma_inner2(z: vec2f) -> vec2f { + let w = c_gamma_inner(z + vec2(3.0, 0.0)); + return c_div(w, c_mul(c_mul(z, z + vec2(1.0, 0.0)), c_mul(z + vec2(2.0, 0.0), z + vec2(3.0, 0.0)))); +} + +const D_EPS = 0.01; + +///////////////// +// user code // +///////////////// + +//INCLUDE// + +////////////// +// vertex // +////////////// + +@vertex +fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4f { + var pos = array( + vec2(-1.0,-1.0), + vec2( 1.0,-1.0), + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + ); + + return vec4f(pos[in_vertex_index], 0.0, 1.0); +} + +//////////////// +// fragment // +//////////////// + +fn hsv2rgb(c: vec3f) -> vec3f { + let p = abs(fract(c.xxx + vec3f(1.0, 2.0/3.0, 1.0/3.0)) * 6.0 - vec3f(3.0)); + return c.z * mix(vec3f(1.0), clamp(p - vec3f(1.0), vec3f(0.0), vec3f(1.0)), c.y); +} + +fn shademap(r: f32) -> f32 { + return r*inverseSqrt(r * r + 0.0625 * uniforms.shading_intensity)*0.9875 + 0.0125; +} + +@fragment +fn fs_main(@builtin(position) in: vec4f) -> @location(0) vec4f { + let pos = vec2(in.x, f32(uniforms.resolution.y) - in.y); + var z = remap(pos, vec2(0.0), vec2f(uniforms.resolution), uniforms.bounds_min, uniforms.bounds_max); + + z = func_plot(z); + + let r = sqrt(z.x*z.x + z.y*z.y); + let arg = atan2(z.y, z.x); + let hsv = vec3f(arg / TAU + 1.0, shademap(1.0/r), shademap(r)); + let col = pow(hsv2rgb(hsv), vec3(2.0)); + return vec4f(col, 1.0); +} diff --git a/syntax.md b/syntax.md new file mode 100644 index 0000000..c370dbc --- /dev/null +++ b/syntax.md @@ -0,0 +1,15 @@ +``` +f(z) = z^3 - 1 +fp(z): deriv f(z) +n(z) = z - f(z)/fp(z) +plot(z): iter w = z, w = f(w), w, 100 +``` + +unary ops: - / (neg recip) +binary ops: + - * / ^ (add sub mul div pow) +holomorphic fns: sqrt exp ln sin cos tan sinh cosh tanh asin acos atan asinh acosh atanh gamma +bad fns: re im abs abssq arg conj +higher order: iter deriv +constants: i tau e + +type sigils: complex, $function, @integer