diff --git a/Cargo.lock b/Cargo.lock index abb1ff7..8fd68ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,12 +46,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "aligned-vec" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" - [[package]] name = "android-activity" version = "0.5.2" @@ -79,72 +73,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[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 = "anyhow" version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" -[[package]] -name = "arbitrary" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" - -[[package]] -name = "arboard" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2041f1943049c7978768d84e6d0fd95de98b76d6c4727b09e78ec253d29fa58" -dependencies = [ - "clipboard-win", - "log", - "objc", - "objc-foundation", - "objc_id", - "parking_lot", - "thiserror", - "x11rb", -] - -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "arrayref" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.4" @@ -184,29 +124,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "av1-grain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" -dependencies = [ - "anyhow", - "arrayvec 0.7.4", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" -dependencies = [ - "arrayvec 0.7.4", -] - [[package]] name = "backtrace" version = "0.3.70" @@ -222,21 +139,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - [[package]] name = "bitflags" version = "1.3.2" @@ -249,27 +151,6 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - -[[package]] -name = "bitstream-io" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c9989a51171e2e81038ab168b6ae22886fe9ded214430dbb4f41c28cf176da" - -[[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.2.1" @@ -289,12 +170,6 @@ dependencies = [ "objc2", ] -[[package]] -name = "built" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d17f4d6e4dc36d1a02fbedc2753a096848e7c1b0772f7654eab8e2c927dd53" - [[package]] name = "bumpalo" version = "3.15.4" @@ -321,12 +196,6 @@ dependencies = [ "syn", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.5.0" @@ -375,16 +244,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -[[package]] -name = "cfg-expr" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -397,27 +256,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" -[[package]] -name = "chrono" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "windows-targets 0.52.4", -] - -[[package]] -name = "clipboard-win" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d517d4b86184dbb111d3556a10f1c8a04da7428d2987bf1081602bf11c3aa9ee" -dependencies = [ - "error-code", -] - [[package]] name = "cmake" version = "0.1.50" @@ -427,31 +265,6 @@ dependencies = [ "cc", ] -[[package]] -name = "codegen" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff61280aed771c3070e7dcc9e050c66f1eb1e3b96431ba66f9f74641d02fc41d" -dependencies = [ - "indexmap 1.9.3", -] - -[[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 = "combine" version = "4.6.6" @@ -511,15 +324,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam-channel" version = "0.5.12" @@ -575,40 +379,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.3", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - [[package]] name = "dispatch" version = "0.2.0" @@ -630,74 +400,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" -[[package]] -name = "ecolor" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb152797942f72b84496eb2ebeff0060240e0bf55096c4525ffa22dd54722d86" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "egui" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1b8cc14b0b260aa6bd124ef12c8a94f57ffe8e40aa970f3db710c21bb945f3" -dependencies = [ - "ahash", - "epaint", - "log", - "nohash-hasher", -] - -[[package]] -name = "egui-winit" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3733435d6788c760bb98ce4cb1b8b7a2d953a3a7b421656ba8b3e014019be3d0" -dependencies = [ - "arboard", - "egui", - "log", - "raw-window-handle 0.6.0", - "smithay-clipboard", - "web-time", - "webbrowser", - "winit", -] - [[package]] name = "either" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" -[[package]] -name = "emath" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555a7cbfcc52c81eb5f8f898190c840fa1c435f67f30b7ef77ce7cf6b7dcd987" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "epaint" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd63c37156e949bda80f7e39cc11508bc34840aecf52180567e67cdb2bf1a5fe" -dependencies = [ - "ab_glyph", - "ahash", - "bytemuck", - "ecolor", - "emath", - "log", - "nohash-hasher", - "parking_lot", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -723,37 +431,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-code" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" - -[[package]] -name = "exr" -version = "1.72.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" -dependencies = [ - "bit_field", - "flume", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "fdeflate" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" -dependencies = [ - "simd-adler32", -] - [[package]] name = "filetime" version = "0.2.23" @@ -766,16 +443,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "flax" version = "0.6.2" @@ -788,7 +455,7 @@ dependencies = [ "erased-serde", "flax-derive", "flume", - "itertools 0.11.0", + "itertools", "once_cell", "rayon", "serde", @@ -804,7 +471,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d141b9bb793ce817c1ec513e93b72e4e2a6d9494b18d5c1e454fa08905586d6" dependencies = [ - "itertools 0.11.0", + "itertools", "proc-macro-crate 2.0.0", "proc-macro2", "quote", @@ -850,15 +517,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "fsevent-sys" version = "4.1.0" @@ -874,63 +532,12 @@ 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-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-core", - "futures-macro", - "futures-task", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -954,16 +561,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "gimli" version = "0.28.1" @@ -981,22 +578,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", - "serde", -] - [[package]] name = "hashbrown" version = "0.14.3" @@ -1009,50 +590,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -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 = "icrate" version = "0.0.4" @@ -1064,88 +607,6 @@ dependencies = [ "objc2", ] -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "im-lists" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7233fb8b1ffc0b1d6033fd311a74a0443164628c62abbc871185ee95098b63" -dependencies = [ - "smallvec", -] - -[[package]] -name = "im-rc" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" -dependencies = [ - "bitmaps", - "rand_core", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "image" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b4f005360d32e9325029b38ba47ebd7a56f3316df09249368939562d518645" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "image-webp", - "num-traits", - "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "image-webp" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a84a25dcae3ac487bc24ef280f9e20c79c9b1a3e5e32cbed3041d1c514aa87c" -dependencies = [ - "byteorder", - "thiserror", -] - -[[package]] -name = "imgref" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.2.5" @@ -1153,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -1176,17 +637,6 @@ dependencies = [ "libc", ] -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "itertools" version = "0.11.0" @@ -1196,15 +646,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.10" @@ -1242,12 +683,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - [[package]] name = "js-sys" version = "0.3.69" @@ -1257,32 +692,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "khors" -version = "0.1.0" -dependencies = [ - "ahash", - "anyhow", - "downcast-rs", - "egui", - "egui-winit", - "flax", - "flume", - "image", - "notify", - "notify-debouncer-mini", - "parking_lot", - "serde", - "serde-lexpr", - "steel-core", - "steel-derive", - "tokio", - "vulkano", - "vulkano-shaders", - "vulkano-util", - "winit", -] - [[package]] name = "kqueue" version = "1.0.8" @@ -1303,23 +712,6 @@ dependencies = [ "libc", ] -[[package]] -name = "lasso" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4644821e1c3d7a560fe13d842d13f587c07348a1a05d3a797152d41c90c56df2" -dependencies = [ - "dashmap", - "hashbrown 0.13.2", - "serde", -] - -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - [[package]] name = "lexpr" version = "0.2.7" @@ -1347,17 +739,6 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" -[[package]] -name = "libfuzzer-sys" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" -dependencies = [ - "arbitrary", - "cc", - "once_cell", -] - [[package]] name = "libloading" version = "0.7.4" @@ -1378,17 +759,6 @@ dependencies = [ "windows-targets 0.52.4", ] -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.2", - "libc", - "redox_syscall 0.4.1", -] - [[package]] name = "libredox" version = "0.0.2" @@ -1422,15 +792,6 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - [[package]] name = "malloc_buf" version = "0.0.6" @@ -1440,16 +801,6 @@ dependencies = [ "libc", ] -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "memchr" version = "2.7.1" @@ -1478,7 +829,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", - "simd-adler32", ] [[package]] @@ -1533,18 +883,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - [[package]] name = "nom" version = "7.1.3" @@ -1555,12 +893,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - [[package]] name = "notify" version = "6.1.1" @@ -1591,95 +923,6 @@ dependencies = [ "notify", ] -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-complex" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" -dependencies = [ - "num-traits", - "serde", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-traits" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" -dependencies = [ - "autocfg", -] - [[package]] name = "num_cpus" version = "1.16.0" @@ -1720,17 +963,6 @@ dependencies = [ "malloc_buf", ] -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - [[package]] name = "objc-sys" version = "0.3.2" @@ -1753,15 +985,6 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - [[package]] name = "object" version = "0.32.2" @@ -1777,19 +1000,13 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - [[package]] name = "orbclient" version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox 0.0.2", + "libredox", ] [[package]] @@ -1824,12 +1041,6 @@ dependencies = [ "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 = "percent-encoding" version = "2.3.1" @@ -1842,31 +1053,12 @@ 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.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "png" -version = "0.17.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "polling" version = "3.5.0" @@ -1881,23 +1073,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "pretty" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" -dependencies = [ - "arrayvec 0.5.2", - "typed-arena", - "unicode-width", -] - [[package]] name = "proc-macro-crate" version = "2.0.0" @@ -1925,40 +1100,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "profiling" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quick-xml" version = "0.31.0" @@ -1968,16 +1109,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quickscope" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d47bcfc3e13850589cf9338a02b6dfb5aebb3748a0f93a392e8df91d6193b6b" -dependencies = [ - "indexmap 1.9.3", - "smallvec", -] - [[package]] name = "quote" version = "1.0.35" @@ -1987,101 +1118,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radix_fmt" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec 0.7.4", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.12.1", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "once_cell", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "system-deps", - "thiserror", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc13288f5ab39e6d7c9d501759712e6969fcc9734220846fc9ed26cae2cc4234" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - [[package]] name = "raw-window-handle" version = "0.5.2" @@ -2132,26 +1168,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom", - "libredox 0.0.1", - "thiserror", -] - -[[package]] -name = "rgb" -version = "0.8.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" -dependencies = [ - "bytemuck", -] - [[package]] name = "roxmltree" version = "0.14.1" @@ -2261,15 +1277,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" -dependencies = [ - "serde", -] - [[package]] name = "shaderc" version = "0.8.3" @@ -2291,6 +1298,12 @@ dependencies = [ "roxmltree", ] +[[package]] +name = "shrev" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ea33232fdcf1bf691ca33450e5a94dde13e1a8cbb8caabc5e4f9d761e10b1a" + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2300,31 +1313,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", -] - [[package]] name = "slab" version = "0.4.9" @@ -2371,17 +1359,6 @@ dependencies = [ "xkeysym", ] -[[package]] -name = "smithay-clipboard" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" -dependencies = [ - "libc", - "smithay-client-toolkit", - "wayland-backend", -] - [[package]] name = "smol_str" version = "0.2.1" @@ -2410,88 +1387,12 @@ dependencies = [ "lock_api", ] -[[package]] -name = "steel-core" -version = "0.6.0" -source = "git+https://github.com/mattwparas/steel.git?branch=master#08c3a14a540027575f3a37f9f6dba3b4c1b48b7d" -dependencies = [ - "bincode", - "chrono", - "codespan-reporting", - "dirs", - "futures-executor", - "futures-task", - "futures-util", - "fxhash", - "im-lists", - "im-rc", - "lasso", - "log", - "num", - "once_cell", - "pretty", - "quickscope", - "radix_fmt", - "rand", - "serde", - "serde_derive", - "serde_json", - "smallvec", - "steel-derive", - "steel-gen", - "steel-parser", - "strsim", - "weak-table", - "which", -] - -[[package]] -name = "steel-derive" -version = "0.5.0" -source = "git+https://github.com/mattwparas/steel.git?branch=master#08c3a14a540027575f3a37f9f6dba3b4c1b48b7d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "steel-gen" -version = "0.2.0" -source = "git+https://github.com/mattwparas/steel.git?branch=master#08c3a14a540027575f3a37f9f6dba3b4c1b48b7d" -dependencies = [ - "codegen", - "serde", - "serde_derive", -] - -[[package]] -name = "steel-parser" -version = "0.6.0" -source = "git+https://github.com/mattwparas/steel.git?branch=master#08c3a14a540027575f3a37f9f6dba3b4c1b48b7d" -dependencies = [ - "fxhash", - "lasso", - "num", - "once_cell", - "pretty", - "serde", - "serde_derive", - "smallvec", -] - [[package]] name = "strict-num" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" -[[package]] -name = "strsim" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" - [[package]] name = "syn" version = "2.0.53" @@ -2503,34 +1404,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "target-lexicon" -version = "0.12.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" - -[[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.58" @@ -2561,17 +1434,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - [[package]] name = "tiny-skia" version = "0.11.4" @@ -2579,7 +1441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec", "bytemuck", "cfg-if", "log", @@ -2597,21 +1459,6 @@ dependencies = [ "strict-num", ] -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.36.0" @@ -2642,26 +1489,11 @@ dependencies = [ "syn", ] -[[package]] -name = "toml" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.9", -] - [[package]] name = "toml_datetime" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" -dependencies = [ - "serde", -] [[package]] name = "toml_edit" @@ -2669,9 +1501,9 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.2.5", + "indexmap", "toml_datetime", - "winnow 0.5.40", + "winnow", ] [[package]] @@ -2680,22 +1512,9 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.5", + "indexmap", "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" -dependencies = [ - "indexmap 2.2.5", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.5", + "winnow", ] [[package]] @@ -2744,79 +1563,18 @@ dependencies = [ "nom", ] -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "v_frame" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - [[package]] name = "version_check" version = "0.9.4" @@ -2843,8 +1601,8 @@ dependencies = [ "core-graphics-types", "crossbeam-queue", "half", - "heck 0.4.1", - "indexmap 2.2.5", + "heck", + "indexmap", "libloading 0.8.3", "nom", "objc", @@ -2879,7 +1637,7 @@ version = "0.34.0" source = "git+https://github.com/vulkano-rs/vulkano.git?branch=master#7cbf3a7f2694f75e44c778878b5520a45c6a2d1c" dependencies = [ "ahash", - "heck 0.4.1", + "heck", "proc-macro2", "quote", "shaderc", @@ -3088,12 +1846,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "weak-table" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" - [[package]] name = "web-sys" version = "0.3.69" @@ -3114,41 +1866,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webbrowser" -version = "0.8.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1b04c569c83a9bb971dd47ec6fd48753315f4bf989b9b04a2e7ca4d7f0dc950" -dependencies = [ - "core-foundation", - "home", - "jni", - "log", - "ndk-context", - "objc", - "raw-window-handle 0.5.2", - "url", - "web-sys", -] - -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" @@ -3180,15 +1897,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.4", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -3445,15 +2153,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winnow" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" -dependencies = [ - "memchr", -] - [[package]] name = "x11-dl" version = "2.21.0" @@ -3544,25 +2243,22 @@ dependencies = [ ] [[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +name = "ztest" +version = "0.1.0" dependencies = [ - "simd-adler32", -] - -[[package]] -name = "zune-jpeg" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" -dependencies = [ - "zune-core", + "anyhow", + "downcast-rs", + "flax", + "flume", + "notify", + "notify-debouncer-mini", + "parking_lot", + "serde", + "serde-lexpr", + "shrev", + "tokio", + "vulkano", + "vulkano-shaders", + "vulkano-util", + "winit", ] diff --git a/Cargo.toml b/Cargo.toml index 84aea6d..0c9b5e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.80" +shrev = "1.1.3" winit = { version = "0.29.15",features = ["rwh_05"] } vulkano = { git = "https://github.com/vulkano-rs/vulkano.git", branch = "master" } vulkano-shaders = { git = "https://github.com/vulkano-rs/vulkano.git", branch = "master" } @@ -20,9 +21,3 @@ serde-lexpr = "0.1.3" tokio = { version = "1.36.0", features = ["full"] } notify = "6.1.1" notify-debouncer-mini = "0.4.1" -steel-core = { git="https://github.com/mattwparas/steel.git", branch = "master" } -steel-derive = { git="https://github.com/mattwparas/steel.git", branch = "master" } -egui = "0.27.1" -image = "0.25.0" -ahash = "0.8.11" -egui-winit = "0.27.1" diff --git a/src/app.rs b/src/app.rs index a1cc560..44183fb 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,37 +1,22 @@ #![warn(dead_code)] -use std::collections::HashMap; - -use crate::{ - core::{ - events::Events, - module::{Module, ModulesStack, RenderModule as ThreadLocalModule, RenderModulesStack}, - }, - modules::graphics::egui::{Gui, GuiConfig}, -}; -use anyhow::Result; use flax::{Schedule, World}; -use vulkano::device::DeviceFeatures; -use vulkano_util::{ - context::{VulkanoConfig, VulkanoContext}, - window::VulkanoWindows, +use anyhow::Result; +use crate::{ + core::events::Events, + module::{Module, ModulesStack}, }; -use winit::{event::{Event, WindowEvent}, window::WindowId}; #[allow(dead_code)] pub struct App { name: String, modules: ModulesStack, - thread_local_modules: RenderModulesStack, world: World, schedule: Schedule, events: Events, rx: flume::Receiver, running: bool, event_cleanup_time: std::time::Duration, - vk_context: VulkanoContext, - vk_windows: VulkanoWindows, - guis: HashMap, } impl App { @@ -41,158 +26,36 @@ impl App { let (tx, rx) = flume::unbounded(); events.subscribe_custom(tx); - let schedule = Schedule::builder().build(); - - let vk_config = VulkanoConfig { - device_features: DeviceFeatures { - dynamic_rendering: true, - ..Default::default() - }, - ..Default::default() - }; - let vk_context = VulkanoContext::new(vk_config); - let vk_windows = VulkanoWindows::default(); - Self { - name: "Khors".into(), + name: "ZTest".into(), modules: ModulesStack::new(), - thread_local_modules: RenderModulesStack::new(), world: World::new(), - schedule, + schedule: Schedule::default(), events, rx, running: false, event_cleanup_time: std::time::Duration::from_secs(60), - vk_context, - vk_windows, - guis: HashMap::new(), } } pub fn run(&mut self) -> Result<()> { self.running = true; - self.schedule.execute_par(&mut self.world).unwrap(); + // self.schedule.execute_par(&mut self.world).unwrap(); - let vk_context = &mut self.vk_context; - let vk_windows = &mut self.vk_windows; let world = &mut self.world; let events = &mut self.events; let frame_time = std::time::Duration::from_millis(16); - let guis = &mut self.guis; for module in self.modules.iter_mut() { module.on_update(world, events, frame_time)?; } - for module in self.thread_local_modules.iter_mut() { - module.on_update(guis, vk_context, vk_windows, world, events, frame_time)?; - } - self.handle_events(); Ok(()) } - pub fn create_window(&mut self, event_loop: &winit::event_loop::EventLoopWindowTarget) - where - T: Clone + Send + Sync, - { - let window = self.vk_windows.create_window( - event_loop, - &self.vk_context, - &vulkano_util::window::WindowDescriptor { - title: self.name.clone(), - present_mode: vulkano::swapchain::PresentMode::Fifo, - ..Default::default() - }, - |_| {}, - ); - - let renderer = self.vk_windows.get_renderer(window).unwrap(); - let gui = Gui::new( - event_loop, - renderer.surface().clone(), - renderer.graphics_queue().clone(), - renderer.swapchain_format(), - GuiConfig { is_overlay: true, allow_srgb_render_target: false, ..Default::default() }, - ); - - self.guis.insert(window, gui); - } - - pub fn process_event_loop( - &mut self, - event: winit::event::Event, - _elwt: &winit::event_loop::EventLoopWindowTarget, - ) -> Result - where - T: Clone + Send + Sync, - { - match &event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - return Ok(true); - } - Event::WindowEvent { - event: WindowEvent::Focused(_), - .. - } => self.events().send(event.clone()), - Event::WindowEvent { - event: WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. }, - window_id, - } => self - .vk_windows - .get_renderer_mut(*window_id) - .unwrap() - .resize(), - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - window_id, - } => 'redraw: { - // Tasks for redrawing: - // 1. Update state based on events - // 2. Compute & Render - // 3. Reset input state - // 4. Update time & title - - // The rendering part goes here: - match self - .vk_windows - .get_renderer(*window_id) - .unwrap() - .window_size() - { - [w, h] => { - // Skip this frame when minimized. - if w == 0.0 || h == 0.0 { - break 'redraw; - } - } - } - - self.run()?; - } - Event::WindowEvent { window_id, event } => { - let window = self.vk_windows.get_window(*window_id).unwrap(); - let gui = self.guis.get_mut(window_id).unwrap(); - gui.update(window, event); - } - Event::AboutToWait => { - for (window_id, _) in self.vk_windows.iter() { - self.vk_windows - .get_window(*window_id) - .unwrap() - .request_redraw() - } - } - _ => (), - } - Ok(false) - } - pub fn handle_events(&mut self) { for event in self.rx.try_iter() { match event { @@ -201,17 +64,14 @@ impl App { } } - #[allow(dead_code)] pub fn set_schedule(&mut self, schedule: Schedule) { self.schedule = schedule; } - #[allow(dead_code)] pub fn world(&self) -> &World { &self.world } - #[allow(dead_code)] pub fn world_mut(&mut self) -> &mut World { &mut self.world } @@ -220,49 +80,24 @@ impl App { &self.events } - #[allow(dead_code)] pub fn events_mut(&mut self) -> &mut Events { &mut self.events } - /// Pushes a module from the provided init closure to to the top of the layer stack. The provided - /// closure to construct the layer takes in the world and events. - pub fn push_render_module(&mut self, func: F) - where - F: FnOnce( - &mut VulkanoContext, - &mut VulkanoWindows, - &mut Schedule, - &mut World, - &mut Events, - ) -> T, - T: 'static + ThreadLocalModule, - { - let module = func( - &mut self.vk_context, - &mut self.vk_windows, - &mut self.schedule, - &mut self.world, - &mut self.events, - ); - self.thread_local_modules.push(module); - } - /// Pushes a layer from the provided init closure to to the top of the layer stack. The provided /// closure to construct the layer takes in the world and events. pub fn push_module(&mut self, func: F) where - F: FnOnce(&mut Schedule, &mut World, &mut Events) -> T, + F: FnOnce(&mut World, &mut Events) -> T, T: 'static + Module, { - let module = func(&mut self.schedule, &mut self.world, &mut self.events); + let module = func(&mut self.world, &mut self.events); self.modules.push(module); } /// Pushes a module from the provided init closure to to the top of the module stack. The provided /// closure to construct the module takes in the world and events, and may return an error which /// is propagated to the callee. - #[allow(dead_code)] pub fn try_push_module(&mut self, func: F) -> Result<(), E> where F: FnOnce(&mut World, &mut Events) -> Result, @@ -275,7 +110,6 @@ impl App { /// Inserts a module from the provided init closure to to the top of the module stack. The provided /// closure to construct the module takes in the world and events. - #[allow(dead_code)] pub fn insert_module(&mut self, index: usize, func: F) where F: FnOnce(&mut World, &mut Events) -> T, @@ -288,7 +122,6 @@ impl App { /// Pushes a module from the provided init closure to to the top of the module stack. The provided /// closure to construct the module takes in the world and events, and may return an error which /// is propagated to the callee. - #[allow(dead_code)] pub fn try_insert_module(&mut self, index: usize, func: F) -> Result<(), E> where F: FnOnce(&mut World, &mut Events) -> Result, diff --git a/src/comp.rs b/src/comp.rs new file mode 100644 index 0000000..8b2efaf --- /dev/null +++ b/src/comp.rs @@ -0,0 +1,42 @@ +use flax::{component, BoxedSystem, EntityBorrow, Query, System}; +use winit::window::Window; + +component! { + pub window_width: f32, + pub window: Window, + pub counter: i32, + + pub resources, +} + +pub fn update_distance_system() -> BoxedSystem { + System::builder() + .with_name("update_distance") + .with_query( + Query::new((window_width().as_mut(), window(), counter().as_mut())).entity(resources()), + ) + .build(|mut query: EntityBorrow<_>| { + if let Ok((window_width, _window, counter)) = query.get() { + // println!("Win width: {window_width}"); + *(window_width as &mut f32) = *(counter as &mut i32) as f32; + *(counter as &mut i32) += 1; + } + }) + .boxed() +} + +pub fn log_window_system() -> BoxedSystem { + let query = Query::new((window_width(), window())).entity(resources()); + + System::builder() + .with_query(query) + .build(|mut q: EntityBorrow<_>| { + if let Ok((width, wind)) = q.get() { + println!("window id: {:?}", (wind as &Window).id()); + println!("Config changed width: {width}"); + } else { + println!("No config change"); + } + }) + .boxed() +} diff --git a/src/components/mod.rs b/src/components/mod.rs new file mode 100644 index 0000000..ff0a229 --- /dev/null +++ b/src/components/mod.rs @@ -0,0 +1,10 @@ +use std::sync::Arc; + +use specs::{Component, VecStorage}; +use winit::window::Window; + +#[derive(Component, Debug)] +#[storage(VecStorage)] +pub struct EntityWindow { + pub window: Arc, +} diff --git a/src/modules/config/components.rs b/src/config/components.rs similarity index 100% rename from src/modules/config/components.rs rename to src/config/components.rs diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 0000000..548e6e4 --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,68 @@ +use flax::{Schedule, World}; +use notify::{Config as NotifyConfig, INotifyWatcher, RecommendedWatcher, RecursiveMode, Watcher}; +use serde::{Deserialize, Serialize}; +use std::env::current_dir; + +use crate::module::Module; + +use self::{components::{notify_file_event, resources}, systems::{read_config_system, read_notify_events_system}}; + +pub mod components; +pub mod systems; + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +pub struct Config { + pub asset_path: String, +} + + +#[allow(dead_code)] +pub struct ConfigModule { + schedule: Schedule, + watcher: INotifyWatcher, + watcher_rx: std::sync::mpsc::Receiver>, +} + +impl ConfigModule { + pub fn new(_world: &mut World, _events: &mut crate::core::events::Events) -> Self { + let (tx, rx) = std::sync::mpsc::channel(); + let mut watcher = RecommendedWatcher::new(tx, NotifyConfig::default().with_poll_interval(std::time::Duration::from_secs(2))).unwrap(); + + watcher + .watch(¤t_dir().unwrap(), RecursiveMode::NonRecursive) + .unwrap(); + + let schedule = Schedule::builder() + .with_system(read_config_system()) + .with_system(read_notify_events_system()) + .build(); + + Self { + schedule, + watcher, + watcher_rx: rx, + } + } +} + +impl Module for ConfigModule { + fn on_update( + &mut self, + world: &mut World, + _events: &mut crate::core::events::Events, + _frame_time: std::time::Duration, + ) -> anyhow::Result<()> { + self.schedule.execute_par(world).unwrap(); + + if let Ok(event) = self.watcher_rx.recv() { + match event { + Ok(e) => { + world.set(resources(), notify_file_event(), e.clone()).unwrap(); + } + Err(e) => println!("Watcher error. {}", e), + } + } + + Ok(()) + } +} diff --git a/src/modules/config/systems.rs b/src/config/systems.rs similarity index 72% rename from src/modules/config/systems.rs rename to src/config/systems.rs index 8585159..780a220 100644 --- a/src/modules/config/systems.rs +++ b/src/config/systems.rs @@ -5,21 +5,19 @@ use serde_lexpr::from_str; use super::{components::{config, notify_file_event, resources}, Config}; -#[allow(dead_code)] pub fn read_config_system() -> BoxedSystem { let query = Query::new(notify_file_event()).entity(resources()); System::builder() .with_name("read_config") .with_cmd_mut() .with_query(query) - .build(|cmd: &mut CommandBuffer, mut _q: EntityBorrow<_>| { - // if let Ok(n_event) = q.get() { - // println!("here"); - // if (n_event as ¬ify::Event).kind.is_modify() { - // println!("file modified: {:?}", (n_event as ¬ify::Event).paths); - cmd.set(resources(), config(), read_engine_config()); - // } - // } + .build(|cmd: &mut CommandBuffer, mut q: EntityBorrow<_>| { + if let Ok(n_event) = q.get() { + if (n_event as ¬ify::Event).kind.is_modify() { + println!("file modified: {:?}", (n_event as ¬ify::Event).paths); + cmd.set(resources(), config(), read_engine_config()); + } + } }) .boxed() } @@ -33,7 +31,7 @@ fn read_engine_config() -> Config { config } -pub fn first_read_config_system() -> BoxedSystem { +pub fn read_notify_events_system() -> BoxedSystem { let query = Query::new(config().as_mut()).entity(resources()); System::builder() .with_name("first_read_config") diff --git a/src/core/mod.rs b/src/core/mod.rs index bd43ed8..1d84135 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,2 +1,2 @@ pub mod events; -pub mod module; +// pub mod render; diff --git a/src/core/module.rs b/src/core/module.rs deleted file mode 100644 index 670b666..0000000 --- a/src/core/module.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::{collections::HashMap, time::Duration}; - -use anyhow::Result; -use flax::World; -use winit::window::WindowId; - -use crate::{core::events::Events, modules::graphics::egui::Gui}; - -pub trait Module { - fn on_update(&mut self, world: &mut World, events: &mut Events, frame_time: Duration) -> Result<()>; -} - -pub struct ModulesStack { - modules: Vec>, -} - -impl ModulesStack { - pub fn new() -> Self { - Self { modules: Vec::new() } - } - - pub fn iter(&self) -> std::slice::Iter> { - self.modules.iter() - } - - pub fn iter_mut(&mut self) -> std::slice::IterMut> { - self.modules.iter_mut() - } - - pub fn push(&mut self, layer: T) { - let layer = Box::new(layer); - self.modules.push(layer); - } - - pub fn insert(&mut self, index: usize, layer: T) { - let layer = Box::new(layer); - self.modules.insert(index, layer); - } -} - -impl Default for ModulesStack { - fn default() -> Self { - Self::new() - } -} - -impl<'a> IntoIterator for &'a ModulesStack { - type Item = &'a Box; - - type IntoIter = std::slice::Iter<'a, Box>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a> IntoIterator for &'a mut ModulesStack { - type Item = &'a mut Box; - - type IntoIter = std::slice::IterMut<'a, Box>; - - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -// THREAD LOCAL STUFF - -pub trait RenderModule { - fn on_update(&mut self, gui: &mut HashMap, vk_context: &mut vulkano_util::context::VulkanoContext, vk_windows: &mut vulkano_util::window::VulkanoWindows, world: &mut World, events: &mut Events, frame_time: Duration) -> Result<()>; -} - -pub struct RenderModulesStack { - modules: Vec>, -} - -impl RenderModulesStack { - pub fn new() -> Self { - Self { modules: Vec::new() } - } - - pub fn iter(&self) -> std::slice::Iter> { - self.modules.iter() - } - - pub fn iter_mut(&mut self) -> std::slice::IterMut> { - self.modules.iter_mut() - } - - pub fn push(&mut self, layer: T) { - let layer = Box::new(layer); - self.modules.push(layer); - } - - pub fn insert(&mut self, index: usize, layer: T) { - let layer = Box::new(layer); - self.modules.insert(index, layer); - } -} - -impl Default for RenderModulesStack { - fn default() -> Self { - Self::new() - } -} - -impl<'a> IntoIterator for &'a RenderModulesStack { - type Item = &'a Box; - - type IntoIter = std::slice::Iter<'a, Box>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a> IntoIterator for &'a mut RenderModulesStack { - type Item = &'a mut Box; - - type IntoIter = std::slice::IterMut<'a, Box>; - - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} diff --git a/src/core/render/mod.rs b/src/core/render/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/core/render/mod.rs @@ -0,0 +1 @@ + diff --git a/src/main.rs b/src/main.rs index d24e21b..2c4d5eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,51 +1,112 @@ -use anyhow::Result; use app::App; -use modules::{config::ConfigModule, graphics::RenderModule, window::WindowModule}; +use config::ConfigModule; use tokio::runtime::Builder; -use winit::event_loop::{ControlFlow, EventLoopBuilder}; +use vulkano_util::{ + context::{VulkanoConfig, VulkanoContext}, + renderer::VulkanoWindowRenderer, + window::{VulkanoWindows, WindowDescriptor}, +}; +use winit::{ + event::{Event, WindowEvent}, + event_loop::{ControlFlow, EventLoopBuilder}, +}; mod app; +mod config; mod core; -mod modules; +mod module; -fn main() -> Result<()> { - let event_loop = EventLoopBuilder::new().build()?; +fn main() { + let event_loop = EventLoopBuilder::new().build().unwrap(); + let context = VulkanoContext::new(VulkanoConfig::default()); + let mut windows = VulkanoWindows::default(); - let runtime = Builder::new_multi_thread().enable_all().build()?; - // let (event_tx, event_rx) = flume::unbounded(); + let runtime = Builder::new_multi_thread().enable_all().build().unwrap(); + let (event_tx, event_rx) = flume::unbounded(); runtime.block_on(async { runtime.spawn(async move { loop { - std::thread::sleep(std::time::Duration::from_secs(1)); - // let _event = event_rx.recv_async().await.unwrap(); + let _event = event_rx.recv_async().await.unwrap(); // println!( // "Tokio got event: {:?} on thread: {:?}", // event, // std::thread::current().id() // ); + std::thread::sleep(std::time::Duration::from_secs(1)); } }); }); - let mut app = App::new(); // TODO: Move renderer into App - app.create_window(&event_loop); + let _id = windows.create_window( + &event_loop, + &context, + &WindowDescriptor { + title: "ztest".into(), + present_mode: vulkano::swapchain::PresentMode::Fifo, + ..Default::default() + }, + |_| {}, + ); + + let primary_window_renderer = windows.get_primary_renderer_mut().unwrap(); + let _gfx_queue = context.graphics_queue(); + + let mut app = App::new(); app.push_module(ConfigModule::new); - app.push_module(WindowModule::new); - app.push_render_module(RenderModule::new); - event_loop.run(move |event, elwt| { - elwt.set_control_flow(ControlFlow::Poll); + event_loop + .run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + if process_event(primary_window_renderer, &event, &mut app) { + elwt.exit(); + } - if app - .process_event_loop(event, elwt) - .expect("Execution failed") - { - elwt.exit(); - } - - // event_tx.send(event.clone()).unwrap(); - })?; - - Ok(()) + event_tx.send(event.clone()).unwrap(); + }) + .unwrap(); +} + +pub fn process_event( + renderer: &mut VulkanoWindowRenderer, + event: &Event<()>, + app: &mut App, +) -> bool { + match &event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + return true; + } + Event::WindowEvent { + event: WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. }, + .. + } => renderer.resize(), + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => 'redraw: { + app.run().unwrap(); + + // Tasks for redrawing: + // 1. Update state based on events + // 2. Compute & Render + // 3. Reset input state + // 4. Update time & title + + // The rendering part goes here: + match renderer.window_size() { + [w, h] => { + // Skip this frame when minimized. + if w == 0.0 || h == 0.0 { + break 'redraw; + } + } + } + } + Event::AboutToWait => renderer.window().request_redraw(), + _ => (), + } + false } diff --git a/src/module/mod.rs b/src/module/mod.rs new file mode 100644 index 0000000..230d662 --- /dev/null +++ b/src/module/mod.rs @@ -0,0 +1,64 @@ +use std::time::Duration; + +use anyhow::Result; +use flax::World; + +use crate::core::events::Events; + +pub trait Module { + fn on_update(&mut self, world: &mut World, events: &mut Events, frame_time: Duration) -> Result<()>; +} + +pub struct ModulesStack { + modules: Vec>, +} + +impl ModulesStack { + pub fn new() -> Self { + Self { modules: Vec::new() } + } + + pub fn iter(&self) -> std::slice::Iter> { + self.modules.iter() + } + + pub fn iter_mut(&mut self) -> std::slice::IterMut> { + self.modules.iter_mut() + } + + pub fn push(&mut self, layer: T) { + let layer = Box::new(layer); + self.modules.push(layer); + } + + pub fn insert(&mut self, index: usize, layer: T) { + let layer = Box::new(layer); + self.modules.insert(index, layer); + } +} + +impl Default for ModulesStack { + fn default() -> Self { + Self::new() + } +} + +impl<'a> IntoIterator for &'a ModulesStack { + type Item = &'a Box; + + type IntoIter = std::slice::Iter<'a, Box>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a> IntoIterator for &'a mut ModulesStack { + type Item = &'a mut Box; + + type IntoIter = std::slice::IterMut<'a, Box>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} diff --git a/src/modules/config/mod.rs b/src/modules/config/mod.rs deleted file mode 100644 index 3ac0e1f..0000000 --- a/src/modules/config/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -use flax::{Schedule, World}; -use serde::{Deserialize, Serialize}; - -use crate::core::module::Module; - -use self::systems::first_read_config_system; - -pub mod components; -pub mod systems; - -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] -pub struct Config { - pub asset_path: String, -} - -#[allow(dead_code)] -pub struct ConfigModule { - // watcher: INotifyWatcher, - // watcher_rx: std::sync::mpsc::Receiver>, -} - -impl ConfigModule { - pub fn new( - schedule: &mut Schedule, - _world: &mut World, - _events: &mut crate::core::events::Events, - ) -> Self { - let schedule_r = Schedule::builder() - // .with_system(read_config_system()) - .with_system(first_read_config_system()) - .build(); - - schedule.append(schedule_r); - - Self { - // schedule, - // watcher, - // watcher_rx: rx, - } - } -} - -impl Module for ConfigModule { - fn on_update( - &mut self, - _world: &mut World, - _events: &mut crate::core::events::Events, - _frame_time: std::time::Duration, - ) -> anyhow::Result<()> { - // println!("ConfigModule on_update"); - - Ok(()) - } -} diff --git a/src/modules/graphics/egui/integration.rs b/src/modules/graphics/egui/integration.rs deleted file mode 100644 index f642371..0000000 --- a/src/modules/graphics/egui/integration.rs +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) 2021 Okko Hakola, 2024 Klink -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. -use std::sync::Arc; - -use egui::{ClippedPrimitive, TexturesDelta}; -use egui_winit::winit::event_loop::EventLoopWindowTarget; -use vulkano::{ - command_buffer::CommandBuffer, device::Queue, format::{Format, NumericFormat}, image::{sampler::SamplerCreateInfo, view::ImageView, SampleCount}, render_pass::Subpass, swapchain::Surface, sync::GpuFuture -}; -use winit::window::Window; - -use super::{ - renderer::{RenderResources, Renderer}, - utils::{immutable_texture_from_bytes, immutable_texture_from_file}, -}; - -pub struct GuiConfig { - /// Allows supplying sRGB ImageViews as render targets instead of just UNORM ImageViews, defaults to false. - /// **Using sRGB will cause minor discoloration of UI elements** due to blending in linear color space and not - /// sRGB as Egui expects. - /// - /// If you would like to visually compare between UNORM and sRGB render targets, run the `demo_app` example of - /// this crate. - pub allow_srgb_render_target: bool, - /// Whether to render gui as overlay. Only relevant in the case of `Gui::new`, not when using - /// subpass. Determines whether the pipeline should clear the target image. - pub is_overlay: bool, - /// Multisample count. Defaults to 1. If you use more than 1, you'll have to ensure your - /// pipeline and target image matches that. - pub samples: SampleCount, -} - -impl Default for GuiConfig { - fn default() -> Self { - GuiConfig { - allow_srgb_render_target: false, - is_overlay: false, - samples: SampleCount::Sample1, - } - } -} - -impl GuiConfig { - pub fn validate(&self, output_format: Format) { - if output_format.numeric_format_color().unwrap() == NumericFormat::SRGB { - assert!( - self.allow_srgb_render_target, - "Using an output format with sRGB requires `GuiConfig::allow_srgb_render_target` \ - to be set! Egui prefers UNORM render targets. Using sRGB will cause minor \ - discoloration of UI elements due to blending in linear color space and not sRGB \ - as Egui expects." - ); - } - } -} - -pub struct Gui { - pub egui_ctx: egui::Context, - pub egui_winit: egui_winit::State, - renderer: Renderer, - surface: Arc, - - shapes: Vec, - textures_delta: egui::TexturesDelta, -} - -impl Gui { - /// Creates new Egui to Vulkano integration by setting the necessary parameters - /// This is to be called once we have access to vulkano_win's winit window surface - /// and gfx queue. Created with this, the renderer will own a render pass which is useful to e.g. place your render pass' images - /// onto egui windows - pub fn new( - event_loop: &EventLoopWindowTarget, - surface: Arc, - gfx_queue: Arc, - output_format: Format, - config: GuiConfig, - ) -> Gui { - config.validate(output_format); - let renderer = Renderer::new_with_render_pass( - gfx_queue, - output_format, - config.is_overlay, - config.samples, - ); - Self::new_internal(event_loop, surface, renderer) - } - - /// Same as `new` but instead of integration owning a render pass, egui renders on your subpass - pub fn new_with_subpass( - event_loop: &EventLoopWindowTarget, - surface: Arc, - gfx_queue: Arc, - subpass: Subpass, - output_format: Format, - config: GuiConfig, - ) -> Gui { - config.validate(output_format); - let renderer = Renderer::new_with_subpass(gfx_queue, output_format, subpass); - Self::new_internal(event_loop, surface, renderer) - } - - /// Same as `new` but instead of integration owning a render pass, egui renders on your subpass - fn new_internal( - event_loop: &EventLoopWindowTarget, - surface: Arc, - renderer: Renderer, - ) -> Gui { - let max_texture_side = renderer - .queue() - .device() - .physical_device() - .properties() - .max_image_dimension2_d as usize; - let egui_ctx: egui::Context = Default::default(); - let egui_winit = egui_winit::State::new( - egui_ctx.clone(), - egui_ctx.viewport_id(), - event_loop, - Some(surface_window(&surface).scale_factor() as f32), - Some(max_texture_side), - ); - Gui { - egui_ctx, - egui_winit, - renderer, - surface, - shapes: vec![], - textures_delta: Default::default(), - } - } - - /// Returns the pixels per point of the window of this gui. - fn pixels_per_point(&self) -> f32 { - egui_winit::pixels_per_point(&self.egui_ctx, surface_window(&self.surface)) - } - - /// Returns a set of resources used to construct the render pipeline. These can be reused - /// to create additional pipelines and buffers to be rendered in a `PaintCallback`. - pub fn render_resources(&self) -> RenderResources { - self.renderer.render_resources() - } - - /// Updates context state by winit window event. - /// Returns `true` if egui wants exclusive use of this event - /// (e.g. a mouse click on an egui window, or entering text into a text field). - /// For instance, if you use egui for a game, you want to first call this - /// and only when this returns `false` pass on the events to your game. - /// - /// Note that egui uses `tab` to move focus between elements, so this will always return `true` for tabs. - pub fn update(&mut self, window: &Window, winit_event: &winit::event::WindowEvent) -> bool { - self.egui_winit - .on_window_event(window, winit_event) - .consumed - } - - /// Begins Egui frame & determines what will be drawn later. This must be called before draw, and after `update` (winit event). - pub fn immediate_ui(&mut self, layout_function: impl FnOnce(&mut Self)) { - let raw_input = self - .egui_winit - .take_egui_input(surface_window(&self.surface)); - self.egui_ctx.begin_frame(raw_input); - // Render Egui - layout_function(self); - } - - /// If you wish to better control when to begin frame, do so by calling this function - /// (Finish by drawing) - pub fn begin_frame(&mut self) { - let raw_input = self - .egui_winit - .take_egui_input(surface_window(&self.surface)); - self.egui_ctx.begin_frame(raw_input); - } - - /// Renders ui on `final_image` & Updates cursor icon - /// Finishes Egui frame - /// - `before_future` = Vulkano's GpuFuture - /// - `final_image` = Vulkano's image (render target) - pub fn draw_on_image( - &mut self, - before_future: F, - final_image: Arc, - ) -> Box - where - F: GpuFuture + 'static, - { - if !self.renderer.has_renderpass() { - panic!( - "Gui integration has been created with subpass, use `draw_on_subpass_image` \ - instead" - ) - } - - let (clipped_meshes, textures_delta) = self.extract_draw_data_at_frame_end(); - - self.renderer.draw_on_image( - &clipped_meshes, - &textures_delta, - self.pixels_per_point(), - before_future, - final_image, - ) - } - - /// Creates commands for rendering ui on subpass' image and returns the command buffer for execution on your side - /// - Finishes Egui frame - /// - You must execute the secondary command buffer yourself - pub fn draw_on_subpass_image( - &mut self, - image_dimensions: [u32; 2], - ) -> Arc { - if self.renderer.has_renderpass() { - panic!( - "Gui integration has been created with its own render pass, use `draw_on_image` \ - instead" - ) - } - - let (clipped_meshes, textures_delta) = self.extract_draw_data_at_frame_end(); - - self.renderer.draw_on_subpass_image( - &clipped_meshes, - &textures_delta, - self.pixels_per_point(), - image_dimensions, - ) - } - - fn extract_draw_data_at_frame_end(&mut self) -> (Vec, TexturesDelta) { - self.end_frame(); - let shapes = std::mem::take(&mut self.shapes); - let textures_delta = std::mem::take(&mut self.textures_delta); - let clipped_meshes = self.egui_ctx.tessellate(shapes, self.pixels_per_point()); - (clipped_meshes, textures_delta) - } - - fn end_frame(&mut self) { - let egui::FullOutput { - platform_output, - textures_delta, - shapes, - pixels_per_point: _, - viewport_output: _, - } = self.egui_ctx.end_frame(); - - self.egui_winit.handle_platform_output( - surface_window(&self.surface), - platform_output, - ); - self.shapes = shapes; - self.textures_delta = textures_delta; - } - - /// Registers a user image from Vulkano image view to be used by egui - pub fn register_user_image_view( - &mut self, - image: Arc, - sampler_create_info: SamplerCreateInfo, - ) -> egui::TextureId { - self.renderer.register_image(image, sampler_create_info) - } - - /// Registers a user image to be used by egui - /// - `image_file_bytes`: e.g. include_bytes!("./assets/tree.png") - /// - `format`: e.g. vulkano::format::Format::R8G8B8A8Unorm - pub fn register_user_image( - &mut self, - image_file_bytes: &[u8], - format: vulkano::format::Format, - sampler_create_info: SamplerCreateInfo, - ) -> egui::TextureId { - let image = immutable_texture_from_file( - self.renderer.allocators(), - self.renderer.queue(), - image_file_bytes, - format, - ) - .expect("Failed to create image"); - self.renderer.register_image(image, sampler_create_info) - } - - pub fn register_user_image_from_bytes( - &mut self, - image_byte_data: &[u8], - dimensions: [u32; 2], - format: vulkano::format::Format, - sampler_create_info: SamplerCreateInfo, - ) -> egui::TextureId { - let image = immutable_texture_from_bytes( - self.renderer.allocators(), - self.renderer.queue(), - image_byte_data, - dimensions, - format, - ) - .expect("Failed to create image"); - self.renderer.register_image(image, sampler_create_info) - } - - /// Unregisters a user image - pub fn unregister_user_image(&mut self, texture_id: egui::TextureId) { - self.renderer.unregister_image(texture_id); - } - - /// Access egui's context (which can be used to e.g. set fonts, visuals etc) - pub fn context(&self) -> egui::Context { - self.egui_ctx.clone() - } -} - -// Helper to retrieve Window from surface object -fn surface_window(surface: &Surface) -> &Window { - surface.object().unwrap().downcast_ref::().unwrap() -} diff --git a/src/modules/graphics/egui/mod.rs b/src/modules/graphics/egui/mod.rs deleted file mode 100644 index ec672e0..0000000 --- a/src/modules/graphics/egui/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2021 Okko Hakola, 2024 Klink -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -mod integration; -mod renderer; -mod utils; - -pub use egui; -pub use integration::*; -#[allow(unused_imports)] -pub use renderer::{CallbackContext, CallbackFn, RenderResources}; -#[allow(unused_imports)] -pub use utils::{immutable_texture_from_bytes, immutable_texture_from_file}; diff --git a/src/modules/graphics/egui/renderer.rs b/src/modules/graphics/egui/renderer.rs deleted file mode 100644 index ab61b19..0000000 --- a/src/modules/graphics/egui/renderer.rs +++ /dev/null @@ -1,1208 +0,0 @@ -// Copyright (c) 2021 Okko Hakola, 2024 Klink -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -use std::sync::Arc; - -use ahash::AHashMap; -use egui::{epaint::Primitive, ClippedPrimitive, PaintCallbackInfo, Rect, TexturesDelta}; -use vulkano::{ - buffer::{ - allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, - Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer, - }, - command_buffer::{ - allocator::StandardCommandBufferAllocator, auto::RecordingCommandBuffer, BufferImageCopy, - CommandBuffer, CommandBufferBeginInfo, CommandBufferInheritanceInfo, CommandBufferLevel, - CommandBufferUsage, CopyBufferToImageInfo, RenderPassBeginInfo, SubpassBeginInfo, - SubpassContents, - }, - descriptor_set::{ - allocator::StandardDescriptorSetAllocator, layout::DescriptorSetLayout, DescriptorSet, - WriteDescriptorSet, - }, - device::Queue, - format::{Format, NumericFormat}, - image::{ - sampler::{ - ComponentMapping, ComponentSwizzle, Filter, Sampler, SamplerAddressMode, - SamplerCreateInfo, SamplerMipmapMode, - }, - view::{ImageView, ImageViewCreateInfo}, - Image, ImageAspects, ImageCreateInfo, ImageLayout, ImageSubresourceLayers, ImageType, - ImageUsage, SampleCount, - }, - memory::{ - allocator::{ - AllocationCreateInfo, DeviceLayout, MemoryTypeFilter, StandardMemoryAllocator, - }, - DeviceAlignment, - }, - pipeline::{ - graphics::{ - color_blend::{ - AttachmentBlend, BlendFactor, ColorBlendAttachmentState, ColorBlendState, - }, - input_assembly::InputAssemblyState, - multisample::MultisampleState, - rasterization::RasterizationState, - vertex_input::{Vertex, VertexDefinition}, - viewport::{Scissor, Viewport, ViewportState}, - GraphicsPipelineCreateInfo, - }, - layout::PipelineDescriptorSetLayoutCreateInfo, - DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, - PipelineShaderStageCreateInfo, - }, - render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, - sync::GpuFuture, - DeviceSize, NonZeroDeviceSize, -}; - -use super::utils::Allocators; - -const VERTICES_PER_QUAD: DeviceSize = 4; -const VERTEX_BUFFER_SIZE: DeviceSize = 1024 * 1024 * VERTICES_PER_QUAD; -const INDEX_BUFFER_SIZE: DeviceSize = 1024 * 1024 * 2; - -type VertexBuffer = Subbuffer<[egui::epaint::Vertex]>; -type IndexBuffer = Subbuffer<[u32]>; - -/// Should match vertex definition of egui -#[repr(C)] -#[derive(BufferContents, Vertex)] -pub struct EguiVertex { - #[format(R32G32_SFLOAT)] - pub position: [f32; 2], - #[format(R32G32_SFLOAT)] - pub tex_coords: [f32; 2], - #[format(R8G8B8A8_UNORM)] - pub color: [u8; 4], -} - -pub struct Renderer { - gfx_queue: Arc, - render_pass: Option>, - is_overlay: bool, - output_in_linear_colorspace: bool, - - #[allow(unused)] - format: vulkano::format::Format, - font_sampler: Arc, - // May be R8G8_UNORM or R8G8B8A8_SRGB - font_format: Format, - - allocators: Allocators, - vertex_index_buffer_pool: SubbufferAllocator, - pipeline: Arc, - subpass: Subpass, - - texture_desc_sets: AHashMap>, - texture_images: AHashMap>, - next_native_tex_id: u64, -} - -impl Renderer { - pub fn new_with_subpass( - gfx_queue: Arc, - final_output_format: Format, - subpass: Subpass, - ) -> Renderer { - Self::new_internal(gfx_queue, final_output_format, subpass, None, false) - } - - /// Creates a new [Renderer] which is responsible for rendering egui with its own renderpass - /// See examples - pub fn new_with_render_pass( - gfx_queue: Arc, - final_output_format: Format, - is_overlay: bool, - samples: SampleCount, - ) -> Renderer { - // Create Gui render pass with just depth and final color - let render_pass = if is_overlay { - vulkano::single_pass_renderpass!(gfx_queue.device().clone(), - attachments: { - final_color: { - format: final_output_format, - samples: samples, - load_op: Load, - store_op: Store, - } - }, - pass: { - color: [final_color], - depth_stencil: {} - } - ) - .unwrap() - } else { - vulkano::single_pass_renderpass!(gfx_queue.device().clone(), - attachments: { - final_color: { - format: final_output_format, - samples: samples, - load_op: Clear, - store_op: Store, - } - }, - pass: { - color: [final_color], - depth_stencil: {} - } - ) - .unwrap() - }; - let subpass = Subpass::from(render_pass.clone(), 0).unwrap(); - Self::new_internal( - gfx_queue, - final_output_format, - subpass, - Some(render_pass), - is_overlay, - ) - } - - fn new_internal( - gfx_queue: Arc, - final_output_format: Format, - subpass: Subpass, - render_pass: Option>, - is_overlay: bool, - ) -> Renderer { - let output_in_linear_colorspace = - // final_output_format.type_color().unwrap() == NumericType::SRGB; - final_output_format.numeric_format_color().unwrap() == NumericFormat::SRGB; - let allocators = Allocators::new_default(gfx_queue.device()); - let vertex_index_buffer_pool = SubbufferAllocator::new( - allocators.memory.clone(), - SubbufferAllocatorCreateInfo { - arena_size: INDEX_BUFFER_SIZE + VERTEX_BUFFER_SIZE, - buffer_usage: BufferUsage::INDEX_BUFFER | BufferUsage::VERTEX_BUFFER, - memory_type_filter: MemoryTypeFilter::PREFER_DEVICE - | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, - ..Default::default() - }, - ); - let pipeline = Self::create_pipeline(gfx_queue.clone(), subpass.clone()); - let font_sampler = Sampler::new( - gfx_queue.device().clone(), - SamplerCreateInfo { - mag_filter: Filter::Linear, - min_filter: Filter::Linear, - address_mode: [SamplerAddressMode::ClampToEdge; 3], - mipmap_mode: SamplerMipmapMode::Linear, - ..Default::default() - }, - ) - .unwrap(); - let font_format = Self::choose_font_format(gfx_queue.device()); - Renderer { - gfx_queue, - format: final_output_format, - render_pass, - vertex_index_buffer_pool, - pipeline, - subpass, - texture_desc_sets: AHashMap::default(), - texture_images: AHashMap::default(), - next_native_tex_id: 0, - is_overlay, - output_in_linear_colorspace, - font_sampler, - font_format, - allocators, - } - } - - pub fn has_renderpass(&self) -> bool { - self.render_pass.is_some() - } - - fn create_pipeline(gfx_queue: Arc, subpass: Subpass) -> Arc { - let vs = vs::load(gfx_queue.device().clone()) - .expect("failed to create shader module") - .entry_point("main") - .unwrap(); - let fs = fs::load(gfx_queue.device().clone()) - .expect("failed to create shader module") - .entry_point("main") - .unwrap(); - - let mut blend = AttachmentBlend::alpha(); - blend.src_color_blend_factor = BlendFactor::One; - blend.src_alpha_blend_factor = BlendFactor::OneMinusDstAlpha; - blend.dst_alpha_blend_factor = BlendFactor::One; - let blend_state = ColorBlendState { - attachments: vec![ColorBlendAttachmentState { - blend: Some(blend), - ..Default::default() - }], - ..ColorBlendState::default() - }; - - let vertex_input_state = Some( - EguiVertex::per_vertex() - .definition(&vs) - .unwrap(), - ); - - let stages = [ - PipelineShaderStageCreateInfo::new(vs), - PipelineShaderStageCreateInfo::new(fs), - ]; - - let layout = PipelineLayout::new( - gfx_queue.device().clone(), - PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages) - .into_pipeline_layout_create_info(gfx_queue.device().clone()) - .unwrap(), - ) - .unwrap(); - - GraphicsPipeline::new( - gfx_queue.device().clone(), - None, - GraphicsPipelineCreateInfo { - stages: stages.into_iter().collect(), - vertex_input_state, - input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::default()), - rasterization_state: Some(RasterizationState::default()), - multisample_state: Some(MultisampleState { - rasterization_samples: subpass.num_samples().unwrap_or(SampleCount::Sample1), - ..Default::default() - }), - color_blend_state: Some(blend_state), - dynamic_state: [DynamicState::Viewport, DynamicState::Scissor] - .into_iter() - .collect(), - subpass: Some(subpass.into()), - ..GraphicsPipelineCreateInfo::layout(layout) - }, - ) - .unwrap() - } - - /// Creates a descriptor set for images - fn sampled_image_desc_set( - &self, - layout: &Arc, - image: Arc, - sampler: Arc, - ) -> Arc { - DescriptorSet::new( - self.allocators.descriptor_set.clone(), - layout.clone(), - [WriteDescriptorSet::image_view_sampler(0, image, sampler)], - [], - ) - .unwrap() - } - - /// Registers a user texture. User texture needs to be unregistered when it is no longer needed - pub fn register_image( - &mut self, - image: Arc, - sampler_create_info: SamplerCreateInfo, - ) -> egui::TextureId { - let layout = self.pipeline.layout().set_layouts().first().unwrap(); - let sampler = Sampler::new(self.gfx_queue.device().clone(), sampler_create_info).unwrap(); - let desc_set = self.sampled_image_desc_set(layout, image.clone(), sampler); - let id = egui::TextureId::User(self.next_native_tex_id); - self.next_native_tex_id += 1; - self.texture_desc_sets.insert(id, desc_set); - self.texture_images.insert(id, image); - id - } - - /// Unregister user texture. - pub fn unregister_image(&mut self, texture_id: egui::TextureId) { - self.texture_desc_sets.remove(&texture_id); - self.texture_images.remove(&texture_id); - } - /// Choose a font format, attempt to minimize memory footprint and CPU unpacking time - /// by choosing a swizzled linear format. - fn choose_font_format(device: &vulkano::device::Device) -> Format { - // Some portability subset devices are unable to swizzle views. - let supports_swizzle = !device - .physical_device() - .supported_extensions() - .khr_portability_subset - || device - .physical_device() - .supported_features() - .image_view_format_swizzle; - // Check that this format is supported for all our uses: - let is_supported = |device: &vulkano::device::Device, format: Format| { - device - .physical_device() - .image_format_properties(vulkano::image::ImageFormatInfo { - format, - usage: ImageUsage::SAMPLED - | ImageUsage::TRANSFER_DST - | ImageUsage::TRANSFER_SRC, - ..Default::default() - }) - // Ok(Some(..)) is supported format for this usage. - .is_ok_and(|properties| properties.is_some()) - }; - if supports_swizzle && is_supported(device, Format::R8G8_UNORM) { - // We can save mem by swizzling in hardware! - Format::R8G8_UNORM - } else { - // Rest of implementation assumes R8G8B8A8_SRGB anyway! - Format::R8G8B8A8_SRGB - } - } - /// Based on self.font_format, extract into bytes. - fn pack_font_data_into(&self, data: &egui::FontImage, into: &mut [u8]) { - match self.font_format { - Format::R8G8_UNORM => { - // Egui expects RGB to be linear in shader, but alpha to be *nonlinear.* - // Thus, we use R channel for linear coverage, G for the same coverage converted to nonlinear. - // Then gets swizzled up to RRRG to match expected values. - let linear = data - .pixels - .iter() - .map(|f| (f.clamp(0.0, 1.0 - f32::EPSILON) * 256.0) as u8); - let bytes = linear - .zip(data.srgba_pixels(None)) - .flat_map(|(linear, srgb)| [linear, srgb.a()]); - - into.iter_mut() - .zip(bytes) - .for_each(|(into, from)| *into = from); - } - Format::R8G8B8A8_SRGB => { - // No special tricks, pack them directly. - let bytes = data.srgba_pixels(None).flat_map(|color| color.to_array()); - into.iter_mut() - .zip(bytes) - .for_each(|(into, from)| *into = from); - } - // This is the exhaustive list of choosable font formats. - _ => unreachable!(), - } - } - fn image_size_bytes(&self, delta: &egui::epaint::ImageDelta) -> usize { - match &delta.image { - egui::ImageData::Color(c) => { - // Always four bytes per pixel for sRGBA - c.width() * c.height() * 4 - } - egui::ImageData::Font(f) => { - f.width() - * f.height() - * match self.font_format { - Format::R8G8_UNORM => 2, - Format::R8G8B8A8_SRGB => 4, - // Exhaustive list of valid font formats - _ => unreachable!(), - } - } - } - } - /// Write a single texture delta using the provided staging region and commandbuffer - fn update_texture_within( - &mut self, - id: egui::TextureId, - delta: &egui::epaint::ImageDelta, - stage: Subbuffer<[u8]>, - mapped_stage: &mut [u8], - cbb: &mut RecordingCommandBuffer, - ) { - // Extract pixel data from egui, writing into our region of the stage buffer. - let format = match &delta.image { - egui::ImageData::Color(image) => { - assert_eq!( - image.width() * image.height(), - image.pixels.len(), - "Mismatch between texture size and texel count" - ); - let bytes = image.pixels.iter().flat_map(|color| color.to_array()); - mapped_stage - .iter_mut() - .zip(bytes) - .for_each(|(into, from)| *into = from); - Format::R8G8B8A8_SRGB - } - egui::ImageData::Font(image) => { - // Dynamically pack based on chosen format - self.pack_font_data_into(image, mapped_stage); - self.font_format - } - }; - - // Copy texture data to existing image if delta pos exists (e.g. font changed) - if let Some(pos) = delta.pos { - let Some(existing_image) = self.texture_images.get(&id) else { - // Egui wants us to update this texture but we don't have it to begin with! - panic!("attempt to write into non-existing image"); - }; - // Make sure delta image type and destination image type match. - assert_eq!(existing_image.format(), format); - - // Defer upload of data - cbb.copy_buffer_to_image(CopyBufferToImageInfo { - regions: [BufferImageCopy { - // Buffer offsets are derived - image_offset: [pos[0] as u32, pos[1] as u32, 0], - image_extent: [delta.image.width() as u32, delta.image.height() as u32, 1], - // Always use the whole image (no arrays or mips are performed) - image_subresource: ImageSubresourceLayers { - aspects: ImageAspects::COLOR, - mip_level: 0, - array_layers: 0..1, - }, - ..Default::default() - }] - .into(), - ..CopyBufferToImageInfo::buffer_image(stage, existing_image.image().clone()) - }) - .unwrap(); - } else { - // Otherwise save the newly created image - let img = { - let extent = [delta.image.width() as u32, delta.image.height() as u32, 1]; - Image::new( - self.allocators.memory.clone(), - ImageCreateInfo { - image_type: ImageType::Dim2d, - format, - extent, - usage: ImageUsage::TRANSFER_DST | ImageUsage::SAMPLED, - initial_layout: ImageLayout::Undefined, - ..Default::default() - }, - AllocationCreateInfo::default(), - ) - .unwrap() - }; - // Defer upload of data - cbb.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image(stage, img.clone())) - .unwrap(); - // Swizzle packed font images up to a full premul white. - let component_mapping = match format { - Format::R8G8_UNORM => ComponentMapping { - r: ComponentSwizzle::Red, - g: ComponentSwizzle::Red, - b: ComponentSwizzle::Red, - a: ComponentSwizzle::Green, - }, - _ => ComponentMapping::identity(), - }; - let view = ImageView::new( - img.clone(), - ImageViewCreateInfo { - component_mapping, - ..ImageViewCreateInfo::from_image(&img) - }, - ) - .unwrap(); - // Create a descriptor for it - let layout = self.pipeline.layout().set_layouts().first().unwrap(); - let desc_set = - self.sampled_image_desc_set(layout, view.clone(), self.font_sampler.clone()); - // Save! - self.texture_desc_sets.insert(id, desc_set); - self.texture_images.insert(id, view); - }; - } - /// Write the entire texture delta for this frame. - fn update_textures(&mut self, sets: &[(egui::TextureId, egui::epaint::ImageDelta)]) { - // Allocate enough memory to upload every delta at once. - let total_size_bytes = sets - .iter() - .map(|(_, set)| self.image_size_bytes(set)) - .sum::() - * 4; - // Infallible - unless we're on a 128 bit machine? :P - let total_size_bytes = u64::try_from(total_size_bytes).unwrap(); - let Ok(total_size_bytes) = vulkano::NonZeroDeviceSize::try_from(total_size_bytes) else { - // Nothing to upload! - return; - }; - let buffer = Buffer::new( - self.allocators.memory.clone(), - BufferCreateInfo { - usage: BufferUsage::TRANSFER_SRC, - ..Default::default() - }, - AllocationCreateInfo { - memory_type_filter: MemoryTypeFilter::PREFER_DEVICE - | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, - ..Default::default() - }, - // Bytes, align of one, infallible. - DeviceLayout::new(total_size_bytes, DeviceAlignment::MIN).unwrap(), - ) - .unwrap(); - let buffer = Subbuffer::new(buffer); - - // Shared command buffer for every upload in this batch. - // prim - let mut cbb = RecordingCommandBuffer::new( - self.allocators.command_buffer.clone(), - self.gfx_queue.queue_family_index(), - CommandBufferLevel::Primary, - CommandBufferBeginInfo { - usage: CommandBufferUsage::OneTimeSubmit, - ..Default::default() - }, - ) - .unwrap(); - - { - // Scoped to keep writer lock bounded - // Should be infallible - Just made the buffer so it's exclusive, and we have host access to it. - let mut writer = buffer.write().unwrap(); - - // Keep track of where to write the next image to into the staging buffer. - let mut past_buffer_end = 0usize; - - for (id, delta) in sets { - let image_size_bytes = self.image_size_bytes(delta); - let range = past_buffer_end..(image_size_bytes + past_buffer_end); - - // Bump for next loop - past_buffer_end += image_size_bytes; - - // Represents the same memory in two ways. Writable memmap, and gpu-side description. - let stage = buffer.clone().slice(range.start as u64..range.end as u64); - let mapped_stage = &mut writer[range]; - - self.update_texture_within(*id, delta, stage, mapped_stage, &mut cbb); - } - } - - // Execute every upload at once and await: - let command_buffer = cbb.end().unwrap(); - // Executing on the graphics queue not only since it's what we have, but - // we must guarantee a transfer granularity of [1,1,x] which graphics queue is required to have. - command_buffer - .execute(self.gfx_queue.clone()) - .unwrap() - .then_signal_fence_and_flush() - .unwrap() - .wait(None) - .unwrap(); - } - - fn get_rect_scissor( - &self, - scale_factor: f32, - framebuffer_dimensions: [u32; 2], - rect: Rect, - ) -> Scissor { - let min = rect.min; - let min = egui::Pos2 { - x: min.x * scale_factor, - y: min.y * scale_factor, - }; - let min = egui::Pos2 { - x: min.x.clamp(0.0, framebuffer_dimensions[0] as f32), - y: min.y.clamp(0.0, framebuffer_dimensions[1] as f32), - }; - let max = rect.max; - let max = egui::Pos2 { - x: max.x * scale_factor, - y: max.y * scale_factor, - }; - let max = egui::Pos2 { - x: max.x.clamp(min.x, framebuffer_dimensions[0] as f32), - y: max.y.clamp(min.y, framebuffer_dimensions[1] as f32), - }; - Scissor { - offset: [min.x.round() as u32, min.y.round() as u32], - extent: [ - (max.x.round() - min.x) as u32, - (max.y.round() - min.y) as u32, - ], - } - } - - fn create_secondary_command_buffer_builder(&self) -> RecordingCommandBuffer { - RecordingCommandBuffer::new( - self.allocators.command_buffer.clone(), - self.gfx_queue.queue_family_index(), - CommandBufferLevel::Secondary, - CommandBufferBeginInfo { - usage: CommandBufferUsage::MultipleSubmit, - inheritance_info: Some(CommandBufferInheritanceInfo { - render_pass: Some(self.subpass.clone().into()), - ..Default::default() - }), - ..Default::default() - }, - ) - .unwrap() - } - - // Starts the rendering pipeline and returns [`RecordingCommandBuffer`] for drawing - fn start(&mut self, final_image: Arc) -> (RecordingCommandBuffer, [u32; 2]) { - // Get dimensions - let img_dims = final_image.image().extent(); - // Create framebuffer (must be in same order as render pass description in `new` - let framebuffer = Framebuffer::new( - self.render_pass - .as_ref() - .expect( - "No renderpass on this renderer (created with subpass), use 'draw_subpass' \ - instead", - ) - .clone(), - FramebufferCreateInfo { - attachments: vec![final_image], - ..Default::default() - }, - ) - .unwrap(); - //prim - let mut command_buffer_builder = RecordingCommandBuffer::new( - self.allocators.command_buffer.clone(), - self.gfx_queue.queue_family_index(), - CommandBufferLevel::Primary, - CommandBufferBeginInfo { - usage: CommandBufferUsage::OneTimeSubmit, - ..Default::default() - }, - ) - .unwrap(); - // Add clear values here for attachments and begin render pass - command_buffer_builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![if !self.is_overlay { - Some([0.0; 4].into()) - } else { - None - }], - ..RenderPassBeginInfo::framebuffer(framebuffer) - }, - SubpassBeginInfo { - contents: SubpassContents::SecondaryCommandBuffers, - ..SubpassBeginInfo::default() - }, - ) - .unwrap(); - (command_buffer_builder, [img_dims[0], img_dims[1]]) - } - - /// Executes our draw commands on the final image and returns a `GpuFuture` to wait on - pub fn draw_on_image( - &mut self, - clipped_meshes: &[ClippedPrimitive], - textures_delta: &TexturesDelta, - scale_factor: f32, - before_future: F, - final_image: Arc, - ) -> Box - where - F: GpuFuture + 'static, - { - self.update_textures(&textures_delta.set); - - let (mut command_buffer_builder, framebuffer_dimensions) = self.start(final_image); - let mut builder = self.create_secondary_command_buffer_builder(); - self.draw_egui( - scale_factor, - clipped_meshes, - framebuffer_dimensions, - &mut builder, - ); - // Execute draw commands - let command_buffer = builder.end().unwrap(); - command_buffer_builder - .execute_commands(command_buffer) - .unwrap(); - let done_future = self.finish(command_buffer_builder, Box::new(before_future)); - - for &id in &textures_delta.free { - self.unregister_image(id); - } - - done_future - } - - // Finishes the rendering pipeline - fn finish( - &self, - mut command_buffer_builder: RecordingCommandBuffer, - before_main_cb_future: Box, - ) -> Box { - // We end render pass - command_buffer_builder - .end_render_pass(Default::default()) - .unwrap(); - // Then execute our whole command buffer - let command_buffer = command_buffer_builder.end().unwrap(); - let after_main_cb = before_main_cb_future - .then_execute(self.gfx_queue.clone(), command_buffer) - .unwrap(); - // Return our future - Box::new(after_main_cb) - } - - pub fn draw_on_subpass_image( - &mut self, - clipped_meshes: &[ClippedPrimitive], - textures_delta: &TexturesDelta, - scale_factor: f32, - framebuffer_dimensions: [u32; 2], - ) -> Arc { - self.update_textures(&textures_delta.set); - let mut builder = self.create_secondary_command_buffer_builder(); - self.draw_egui( - scale_factor, - clipped_meshes, - framebuffer_dimensions, - &mut builder, - ); - let buffer = builder.end().unwrap(); - for &id in &textures_delta.free { - self.unregister_image(id); - } - buffer - } - /// Uploads all meshes in bulk. They will be available in the same order, packed. - /// None if no vertices or no indices. - fn upload_meshes( - &mut self, - clipped_meshes: &[ClippedPrimitive], - ) -> Option<(VertexBuffer, IndexBuffer)> { - use egui::epaint::Vertex; - type Index = u32; - const VERTEX_ALIGN: DeviceAlignment = DeviceAlignment::of::(); - const INDEX_ALIGN: DeviceAlignment = DeviceAlignment::of::(); - - // Iterator over only the meshes, no user callbacks. - let meshes = clipped_meshes - .iter() - .filter_map(|mesh| match &mesh.primitive { - Primitive::Mesh(m) => Some(m), - _ => None, - }); - - // Calculate counts of each mesh, and total bytes for combined data - let (total_vertices, total_size_bytes) = { - let mut total_vertices = 0; - let mut total_indices = 0; - - for mesh in meshes.clone() { - total_vertices += mesh.vertices.len(); - total_indices += mesh.indices.len(); - } - if total_indices == 0 || total_vertices == 0 { - return None; - } - - let total_size_bytes = total_vertices * std::mem::size_of::() - + total_indices * std::mem::size_of::(); - ( - total_vertices, - // Infallible! Checked above. - NonZeroDeviceSize::new(u64::try_from(total_size_bytes).unwrap()).unwrap(), - ) - }; - - // Allocate a buffer which can hold both packed arrays: - let layout = DeviceLayout::new(total_size_bytes, VERTEX_ALIGN.max(INDEX_ALIGN)).unwrap(); - let buffer = self.vertex_index_buffer_pool.allocate(layout).unwrap(); - - // We must put the items with stricter align *first* in the packed buffer. - // Correct at time of writing, but assert in case that changes. - assert!(VERTEX_ALIGN >= INDEX_ALIGN); - let (vertices, indices) = { - let partition_bytes = total_vertices as u64 * std::mem::size_of::() as u64; - ( - // Slice the start as vertices - buffer - .clone() - .slice(..partition_bytes) - .reinterpret::<[Vertex]>(), - // Take the rest, reinterpret as indices. - buffer.slice(partition_bytes..).reinterpret::<[Index]>(), - ) - }; - - // We have to upload in two mapping steps to avoid trivial but ugly unsafe. - { - let mut vertex_write = vertices.write().unwrap(); - vertex_write - .iter_mut() - .zip(meshes.clone().flat_map(|m| &m.vertices).copied()) - .for_each(|(into, from)| *into = from); - } - { - let mut index_write = indices.write().unwrap(); - index_write - .iter_mut() - .zip(meshes.flat_map(|m| &m.indices).copied()) - .for_each(|(into, from)| *into = from); - } - - Some((vertices, indices)) - } - - fn draw_egui( - &mut self, - scale_factor: f32, - clipped_meshes: &[ClippedPrimitive], - framebuffer_dimensions: [u32; 2], - builder: &mut RecordingCommandBuffer, - ) { - let push_constants = vs::PushConstants { - screen_size: [ - framebuffer_dimensions[0] as f32 / scale_factor, - framebuffer_dimensions[1] as f32 / scale_factor, - ], - output_in_linear_colorspace: self.output_in_linear_colorspace.into(), - }; - - let mesh_buffers = self.upload_meshes(clipped_meshes); - - // Current position of renderbuffers, advances as meshes are consumed. - let mut vertex_cursor = 0; - let mut index_cursor = 0; - // Some of our state is immutable and only changes - // if a user callback thrashes it, rebind all when this is set: - let mut needs_full_rebind = true; - // Track resources that change from call-to-call. - // egui already makes the optimization that draws with identical resources are merged into one, - // so every mesh changes usually one or possibly both of these. - let mut current_rect = None; - let mut current_texture = None; - - for ClippedPrimitive { - clip_rect, - primitive, - } in clipped_meshes - { - match primitive { - Primitive::Mesh(mesh) => { - // Nothing to draw if we don't have vertices & indices - if mesh.vertices.is_empty() || mesh.indices.is_empty() { - // Consume the mesh and skip it. - index_cursor += mesh.indices.len() as u32; - vertex_cursor += mesh.vertices.len() as u32; - continue; - } - // Reset overall state, if needed. - // Only happens on first mesh, and after a user callback which does unknowable - // things to the command buffer's state. - if needs_full_rebind { - needs_full_rebind = false; - - // Bind combined meshes. - let Some((vertices, indices)) = mesh_buffers.clone() else { - // Only None if there are no mesh calls, but here we are in a mesh call! - unreachable!() - }; - - builder - .bind_pipeline_graphics(self.pipeline.clone()) - .unwrap() - .bind_index_buffer(indices) - .unwrap() - .bind_vertex_buffers(0, [vertices]) - .unwrap() - .set_viewport( - 0, - [Viewport { - offset: [0.0, 0.0], - extent: [ - framebuffer_dimensions[0] as f32, - framebuffer_dimensions[1] as f32, - ], - depth_range: 0.0..=1.0, - }] - .into_iter() - .collect(), - ) - .unwrap() - .push_constants(self.pipeline.layout().clone(), 0, push_constants) - .unwrap(); - } - // Find and bind image, if different. - if current_texture != Some(mesh.texture_id) { - if self.texture_desc_sets.get(&mesh.texture_id).is_none() { - eprintln!("This texture no longer exists {:?}", mesh.texture_id); - continue; - } - current_texture = Some(mesh.texture_id); - - let desc_set = self.texture_desc_sets.get(&mesh.texture_id).unwrap(); - - builder - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - self.pipeline.layout().clone(), - 0, - desc_set.clone(), - ) - .unwrap(); - }; - // Calculate and set scissor, if different - if current_rect != Some(*clip_rect) { - current_rect = Some(*clip_rect); - let new_scissor = - self.get_rect_scissor(scale_factor, framebuffer_dimensions, *clip_rect); - - builder - .set_scissor(0, [new_scissor].into_iter().collect()) - .unwrap(); - } - - // All set up to draw! - unsafe { - builder - .draw_indexed( - mesh.indices.len() as u32, - 1, - index_cursor, - vertex_cursor as i32, - 0, - ) - .unwrap(); - } - - // Consume this mesh for next iteration - index_cursor += mesh.indices.len() as u32; - vertex_cursor += mesh.vertices.len() as u32; - } - Primitive::Callback(callback) => { - if callback.rect.is_positive() { - let Some(callback_fn) = callback.callback.downcast_ref::() - else { - println!( - "Warning: Unsupported render callback. Expected \ - egui_winit_vulkano::CallbackFn" - ); - continue; - }; - - let rect_min_x = scale_factor * callback.rect.min.x; - let rect_min_y = scale_factor * callback.rect.min.y; - let rect_max_x = scale_factor * callback.rect.max.x; - let rect_max_y = scale_factor * callback.rect.max.y; - - let rect_min_x = rect_min_x.round(); - let rect_min_y = rect_min_y.round(); - let rect_max_x = rect_max_x.round(); - let rect_max_y = rect_max_y.round(); - - builder - .set_viewport( - 0, - [Viewport { - offset: [rect_min_x, rect_min_y], - extent: [rect_max_x - rect_min_x, rect_max_y - rect_min_y], - depth_range: 0.0..=1.0, - }] - .into_iter() - .collect(), - ) - .unwrap() - .set_scissor( - 0, - [self.get_rect_scissor( - scale_factor, - framebuffer_dimensions, - *clip_rect, - )] - .into_iter() - .collect(), - ) - .unwrap(); - - let info = egui::PaintCallbackInfo { - viewport: callback.rect, - clip_rect: *clip_rect, - pixels_per_point: scale_factor, - screen_size_px: framebuffer_dimensions, - }; - (callback_fn.f)( - info, - &mut CallbackContext { - builder, - resources: self.render_resources(), - }, - ); - - // The user could have done much here - rebind pipes, set views, bind things, etc. - // Mark all state as lost so that next mesh rebinds everything to a known state. - needs_full_rebind = true; - current_rect = None; - current_texture = None; - } - } - } - } - } - - pub fn render_resources(&self) -> RenderResources { - RenderResources { - queue: self.queue(), - subpass: self.subpass.clone(), - memory_allocator: self.allocators.memory.clone(), - descriptor_set_allocator: &self.allocators.descriptor_set, - command_buffer_allocator: &self.allocators.command_buffer, - } - } - - pub fn queue(&self) -> Arc { - self.gfx_queue.clone() - } - - pub fn allocators(&self) -> &Allocators { - &self.allocators - } -} - -/// A set of objects used to perform custom rendering in a `PaintCallback`. It -/// includes [`RenderResources`] for constructing a subpass pipeline and a secondary -/// command buffer for pushing render commands onto it. -/// -/// # Example -/// -/// See the `triangle` demo source for a detailed usage example. -pub struct CallbackContext<'a> { - pub builder: &'a mut RecordingCommandBuffer, - pub resources: RenderResources<'a>, -} - -/// A set of resources used to construct the render pipeline. These can be reused -/// to create additional pipelines and buffers to be rendered in a `PaintCallback`. -/// -/// # Example -/// -/// See the `triangle` demo source for a detailed usage example. -#[derive(Clone)] -pub struct RenderResources<'a> { - pub memory_allocator: Arc, - pub descriptor_set_allocator: &'a StandardDescriptorSetAllocator, - pub command_buffer_allocator: &'a StandardCommandBufferAllocator, - pub queue: Arc, - pub subpass: Subpass, -} - -pub type CallbackFnDef = dyn Fn(PaintCallbackInfo, &mut CallbackContext) + Sync + Send; - -/// A callback function that can be used to compose an [`epaint::PaintCallback`] for -/// custom rendering with [`vulkano`]. -/// -/// The callback is passed an [`egui::PaintCallbackInfo`] and a [`CallbackContext`] which -/// can be used to construct Vulkano graphics pipelines and buffers. -/// -/// # Example -/// -/// See the `triangle` demo source for a detailed usage example. -pub struct CallbackFn { - pub(crate) f: Box, -} - -#[allow(dead_code)] -impl CallbackFn { - pub fn new( - callback: F, - ) -> Self { - let f = Box::new(callback); - CallbackFn { f } - } -} - -mod vs { - vulkano_shaders::shader! { - ty: "vertex", - src: " -#version 450 - -layout(location = 0) in vec2 position; -layout(location = 1) in vec2 tex_coords; -layout(location = 2) in vec4 color; - -layout(location = 0) out vec4 v_color; -layout(location = 1) out vec2 v_tex_coords; - -layout(push_constant) uniform PushConstants { - vec2 screen_size; - int output_in_linear_colorspace; -} push_constants; - -void main() { - gl_Position = vec4( - 2.0 * position.x / push_constants.screen_size.x - 1.0, - 2.0 * position.y / push_constants.screen_size.y - 1.0, - 0.0, 1.0 - ); - v_color = color; - v_tex_coords = tex_coords; -}" - } -} - -// Similar to https://github.com/ArjunNair/egui_sdl2_gl/blob/main/src/painter.rs -mod fs { - vulkano_shaders::shader! { - ty: "fragment", - src: " -#version 450 - -layout(location = 0) in vec4 v_color; -layout(location = 1) in vec2 v_tex_coords; - -layout(location = 0) out vec4 f_color; - -layout(binding = 0, set = 0) uniform sampler2D font_texture; - -layout(push_constant) uniform PushConstants { - vec2 screen_size; - int output_in_linear_colorspace; -} push_constants; - -// 0-1 sRGB from 0-1 linear -vec3 srgb_from_linear(vec3 linear) { - bvec3 cutoff = lessThan(linear, vec3(0.0031308)); - vec3 lower = linear * vec3(12.92); - vec3 higher = vec3(1.055) * pow(linear, vec3(1./2.4)) - vec3(0.055); - return mix(higher, lower, vec3(cutoff)); -} - -// 0-1 sRGBA from 0-1 linear -vec4 srgba_from_linear(vec4 linear) { - return vec4(srgb_from_linear(linear.rgb), linear.a); -} - -// 0-1 linear from 0-1 sRGB -vec3 linear_from_srgb(vec3 srgb) { - bvec3 cutoff = lessThan(srgb, vec3(0.04045)); - vec3 lower = srgb / vec3(12.92); - vec3 higher = pow((srgb + vec3(0.055) / vec3(1.055)), vec3(2.4)); - return mix(higher, lower, vec3(cutoff)); -} - -// 0-1 linear from 0-1 sRGB -vec4 linear_from_srgba(vec4 srgb) { - return vec4(linear_from_srgb(srgb.rgb), srgb.a); -} - -void main() { - // ALL calculations should be done in gamma space, this includes texture * color and blending - vec4 texture_color = srgba_from_linear(texture(font_texture, v_tex_coords)); - vec4 color = v_color * texture_color; - - // If output_in_linear_colorspace is true, we are rendering into an sRGB image, for which we'll convert to linear color space. - // **This will break blending** as it will be performed in linear color space instead of sRGB like egui expects. - if (push_constants.output_in_linear_colorspace == 1) { - color = linear_from_srgba(color); - } - f_color = color; -}" - } -} diff --git a/src/modules/graphics/egui/utils.rs b/src/modules/graphics/egui/utils.rs deleted file mode 100644 index 2436580..0000000 --- a/src/modules/graphics/egui/utils.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2021 Okko Hakola, 2024 Klink -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -use std::sync::Arc; - -use image::RgbaImage; -use vulkano::{ - buffer::{AllocateBufferError, Buffer, BufferCreateInfo, BufferUsage}, - command_buffer::{ - allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo}, CommandBufferBeginInfo, CommandBufferLevel, CommandBufferUsage, CopyBufferToImageInfo, RecordingCommandBuffer - }, - descriptor_set::allocator::StandardDescriptorSetAllocator, - device::{Device, Queue}, - image::{view::ImageView, AllocateImageError, Image, ImageCreateInfo, ImageType, ImageUsage}, - memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, - Validated, ValidationError, VulkanError, -}; - -#[derive(Debug)] -pub enum ImageCreationError { - Vulkan(Validated), - AllocateImage(Validated), - AllocateBuffer(Validated), - Validation(Box), -} - -pub fn immutable_texture_from_bytes( - allocators: &Allocators, - queue: Arc, - byte_data: &[u8], - dimensions: [u32; 2], - format: vulkano::format::Format, -) -> Result, ImageCreationError> { - let mut cbb = RecordingCommandBuffer::new( - allocators.command_buffer.clone(), - queue.queue_family_index(), - CommandBufferLevel::Primary, - CommandBufferBeginInfo { - usage: CommandBufferUsage::OneTimeSubmit, - ..Default::default() - } - ) - .map_err(ImageCreationError::Vulkan)?; - - let texture_data_buffer = Buffer::from_iter( - allocators.memory.clone(), - BufferCreateInfo { - usage: BufferUsage::TRANSFER_SRC, - ..Default::default() - }, - AllocationCreateInfo { - memory_type_filter: MemoryTypeFilter::PREFER_HOST - | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, - ..Default::default() - }, - byte_data.iter().cloned(), - ) - .map_err(ImageCreationError::AllocateBuffer)?; - - let texture = Image::new( - allocators.memory.clone(), - ImageCreateInfo { - image_type: ImageType::Dim2d, - format, - extent: [dimensions[0], dimensions[1], 1], - usage: ImageUsage::TRANSFER_DST | ImageUsage::SAMPLED, - ..Default::default() - }, - AllocationCreateInfo::default(), - ) - .map_err(ImageCreationError::AllocateImage)?; - - cbb.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image( - texture_data_buffer, - texture.clone(), - )) - .map_err(ImageCreationError::Validation)?; - - let _fut = cbb.end().unwrap().execute(queue).unwrap(); - - Ok(ImageView::new_default(texture).unwrap()) -} - -pub fn immutable_texture_from_file( - allocators: &Allocators, - queue: Arc, - file_bytes: &[u8], - format: vulkano::format::Format, -) -> Result, ImageCreationError> { - use image::GenericImageView; - - let img = image::load_from_memory(file_bytes).expect("Failed to load image from bytes"); - let rgba = if let Some(rgba) = img.as_rgba8() { - rgba.to_owned().to_vec() - } else { - // Convert rgb to rgba - let rgb = img.as_rgb8().unwrap().to_owned(); - let mut raw_data = vec![]; - for val in rgb.chunks(3) { - raw_data.push(val[0]); - raw_data.push(val[1]); - raw_data.push(val[2]); - raw_data.push(255); - } - let new_rgba = RgbaImage::from_raw(rgb.width(), rgb.height(), raw_data).unwrap(); - new_rgba.to_vec() - }; - let dimensions = img.dimensions(); - immutable_texture_from_bytes( - allocators, - queue, - &rgba, - [dimensions.0, dimensions.1], - format, - ) -} - -pub struct Allocators { - pub memory: Arc, - pub descriptor_set: Arc, - pub command_buffer: Arc, -} - -impl Allocators { - pub fn new_default(device: &Arc) -> Self { - Self { - memory: Arc::new(StandardMemoryAllocator::new_default(device.clone())), - descriptor_set: Arc::new(StandardDescriptorSetAllocator::new(device.clone(), Default::default())), - command_buffer: Arc::new(StandardCommandBufferAllocator::new( - device.clone(), - StandardCommandBufferAllocatorCreateInfo { - secondary_buffer_count: 32, - ..Default::default() - }, - )), - } - } -} diff --git a/src/modules/graphics/events.rs b/src/modules/graphics/events.rs deleted file mode 100644 index d03a452..0000000 --- a/src/modules/graphics/events.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[derive(Debug, Clone, Copy, PartialEq)] -#[allow(dead_code)] -pub enum GraphicsEvent { - /// Signifies that the swapchain was recreated. This requires images that - /// reference the old swapchain to be recreated. - SwapchainRecreation, -} diff --git a/src/modules/graphics/mod.rs b/src/modules/graphics/mod.rs deleted file mode 100644 index 2cdcca9..0000000 --- a/src/modules/graphics/mod.rs +++ /dev/null @@ -1,287 +0,0 @@ -use std::{collections::HashMap, sync::Arc}; - -use flax::{entity_ids, BoxedSystem, Query, QueryBorrow, Schedule, System, World}; -use vulkano::{ - command_buffer::{ - allocator::{CommandBufferAllocator, StandardCommandBufferAllocator}, - CommandBufferBeginInfo, CommandBufferLevel, CommandBufferUsage, RecordingCommandBuffer, - RenderingAttachmentInfo, RenderingInfo, - }, - image::view::ImageView, - pipeline::graphics::viewport::Viewport, - render_pass::{AttachmentLoadOp, AttachmentStoreOp}, - sync::GpuFuture, -}; -use vulkano_util::{ - context::VulkanoContext, renderer::VulkanoWindowRenderer, window::VulkanoWindows, -}; -use winit::window::WindowId; - -use crate::core::module::RenderModule as ThreadLocalModule; - -use self::{egui::Gui, test_pipeline::test_pipeline}; - -pub mod egui; -pub mod events; -mod test_pipeline; - -pub struct RenderModule { - schedule: Schedule, - command_buffer_allocator: Arc, - viewport: Viewport, -} - -impl RenderModule { - pub fn new( - vk_context: &mut VulkanoContext, - _vk_windows: &mut VulkanoWindows, - _schedule: &mut Schedule, - _world: &mut World, - _events: &mut crate::core::events::Events, - ) -> Self { - let schedule = Schedule::builder() - .with_system(add_distance_system()) - .build(); - - let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new( - vk_context.device().clone(), - Default::default(), - )); - - let viewport = Viewport { - offset: [0.0, 0.0], - extent: [0.0, 0.0], - depth_range: 0.0..=1.0, - }; - - Self { - schedule, - command_buffer_allocator, - viewport, - } - } -} - -impl ThreadLocalModule for RenderModule { - fn on_update( - &mut self, - guis: &mut HashMap, - vk_context: &mut VulkanoContext, - vk_windows: &mut vulkano_util::window::VulkanoWindows, - world: &mut World, - _events: &mut crate::core::events::Events, - _frame_time: std::time::Duration, - ) -> anyhow::Result<()> { - self.schedule.execute_seq(world).unwrap(); - - let viewport = &mut self.viewport; - - for (window_id, renderer) in vk_windows.iter_mut() { - let gui = guis.get_mut(window_id).unwrap(); - draw( - self.command_buffer_allocator.clone(), - viewport, - vk_context, - renderer, - gui, - ); - } - Ok(()) - } -} - -pub fn add_distance_system() -> BoxedSystem { - let query = Query::new(entity_ids()); - - System::builder() - .with_query(query) - .build(|mut query: QueryBorrow<'_, flax::EntityIds, _>| { - for _id in &mut query { - // println!("----------: {}", _id.index()); - } - }) - .boxed() -} - -fn draw( - command_buffer_allocator: Arc, - viewport: &mut Viewport, - context: &mut VulkanoContext, - renderer: &mut VulkanoWindowRenderer, - gui: &mut Gui, -) { - let (vertex_buffer, pipeline) = test_pipeline( - context.device().clone(), - context.memory_allocator().clone(), - renderer.swapchain_format(), - ); - - // Do not draw the frame when the screen size is zero. On Windows, this can - // occur when minimizing the application. - let image_extent: [u32; 2] = renderer.window().inner_size().into(); - - if image_extent.contains(&0) { - return; - } - - // Begin rendering by acquiring the gpu future from the window renderer. - let previous_frame_end = renderer - .acquire(|swapchain_images| { - // Whenever the window resizes we need to recreate everything dependent - // on the window size. In this example that - // includes the swapchain, the framebuffers - // and the dynamic state viewport. - window_size_dependent_setup(swapchain_images, viewport); - }) - .unwrap(); - - let mut builder = RecordingCommandBuffer::new( - command_buffer_allocator.clone(), - context.graphics_queue().queue_family_index(), - CommandBufferLevel::Primary, - CommandBufferBeginInfo { - usage: CommandBufferUsage::OneTimeSubmit, - ..Default::default() - }, - ) - .unwrap(); - - builder - // Before we can draw, we have to *enter a render pass*. We specify which - // attachments we are going to use for rendering here, which needs to match - // what was previously specified when creating the pipeline. - .begin_rendering(RenderingInfo { - // As before, we specify one color attachment, but now we specify the image - // view to use as well as how it should be used. - color_attachments: vec![Some(RenderingAttachmentInfo { - // `Clear` means that we ask the GPU to clear the content of this - // attachment at the start of rendering. - load_op: AttachmentLoadOp::Clear, - // `Store` means that we ask the GPU to store the rendered output in - // the attachment image. We could also ask it to discard the result. - store_op: AttachmentStoreOp::Store, - // The value to clear the attachment with. Here we clear it with a blue - // color. - // - // Only attachments that have `AttachmentLoadOp::Clear` are provided - // with clear values, any others should use `None` as the clear value. - clear_value: Some([0.0, 0.0, 1.0, 1.0].into()), - ..RenderingAttachmentInfo::image_view( - // We specify image view corresponding to the currently acquired - // swapchain image, to use for this attachment. - // attachment_image_views[image_index as usize].clone(), - renderer.swapchain_image_view().clone(), - ) - })], - ..Default::default() - }) - .unwrap() - // We are now inside the first subpass of the render pass. - // - // TODO: Document state setting and how it affects subsequent draw commands. - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap(); - - unsafe { - builder - // We add a draw command. - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap(); - } - - builder - // We leave the render pass. - .end_rendering() - .unwrap(); - - // Finish recording the command buffer by calling `end`. - let command_buffer = builder.end().unwrap(); - - draw_gui(gui); - - let before_future = previous_frame_end - .then_execute(context.graphics_queue().clone(), command_buffer) - .unwrap() - .boxed(); - - let after_future = gui - .draw_on_image(before_future, renderer.swapchain_image_view()) - .boxed(); - - // The color output is now expected to contain our triangle. But in order to - // show it on the screen, we have to *present* the image by calling - // `present` on the window renderer. - // - // This function does not actually present the image immediately. Instead it - // submits a present command at the end of the queue. This means that it will - // only be presented once the GPU has finished executing the command buffer - // that draws the triangle. - renderer.present(after_future, true); -} - -fn draw_gui(gui: &mut Gui) { - let mut code = CODE.to_owned(); - gui.immediate_ui(|gui| { - let ctx = gui.context(); - egui::egui::Window::new("Colors") - .vscroll(true) - .show(&ctx, |ui| { - ui.vertical_centered(|ui| { - ui.add(egui::egui::widgets::Label::new("Hi there!")); - sized_text(ui, "Rich Text", 32.0); - }); - ui.separator(); - ui.columns(2, |columns| { - egui::egui::ScrollArea::vertical().id_source("source").show( - &mut columns[0], - |ui| { - ui.add( - egui::egui::TextEdit::multiline(&mut code) - .font(egui::egui::TextStyle::Monospace), - ); - }, - ); - egui::egui::ScrollArea::vertical() - .id_source("rendered") - .show(&mut columns[1], |ui| { - ui.add(egui::egui::widgets::Label::new("Good day!")); - }); - }); - }); - }); -} - -fn sized_text(ui: &mut egui::egui::Ui, text: impl Into, size: f32) { - ui.label( - egui::egui::RichText::new(text) - .size(size) - .family(::egui::FontFamily::Monospace), - ); -} - -const CODE: &str = r" -# Some markup -``` -let mut gui = Gui::new(&event_loop, renderer.surface(), None, renderer.queue(), SampleCount::Sample1); -``` -"; - -fn window_size_dependent_setup( - image_views: &[Arc], - viewport: &mut Viewport, -) -> Vec> { - let extent = image_views[0].image().extent(); - viewport.extent = [extent[0] as f32, extent[1] as f32]; - - image_views - .iter() - .map(|image_view| { - let image = image_view.image().clone(); - ImageView::new_default(image).unwrap() - }) - .collect::>() -} diff --git a/src/modules/graphics/test_pipeline.rs b/src/modules/graphics/test_pipeline.rs deleted file mode 100644 index d710779..0000000 --- a/src/modules/graphics/test_pipeline.rs +++ /dev/null @@ -1,190 +0,0 @@ -use std::sync::Arc; - -use vulkano::{ - buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer}, - device::Device, - format::Format, - memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter}, - pipeline::{ - graphics::{ - color_blend::{ColorBlendAttachmentState, ColorBlendState}, - input_assembly::InputAssemblyState, - multisample::MultisampleState, - rasterization::RasterizationState, - subpass::PipelineRenderingCreateInfo, - vertex_input::{Vertex, VertexDefinition}, - viewport::ViewportState, - GraphicsPipelineCreateInfo, - }, - layout::PipelineDescriptorSetLayoutCreateInfo, - DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, - }, -}; - -pub fn test_pipeline( - device: Arc, - memory_allocator: Arc, - image_format: Format, -) -> (Subbuffer<[MyVertex]>, Arc) { - let vertices = [ - MyVertex { - position: [-0.5, -0.25], - }, - MyVertex { - position: [0.0, 0.5], - }, - MyVertex { - position: [0.25, -0.1], - }, - ]; - let vertex_buffer = Buffer::from_iter( - memory_allocator, - BufferCreateInfo { - usage: BufferUsage::VERTEX_BUFFER, - ..Default::default() - }, - AllocationCreateInfo { - memory_type_filter: MemoryTypeFilter::PREFER_DEVICE - | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, - ..Default::default() - }, - vertices, - ) - .unwrap(); - - - - let pipeline = { - // First, we load the shaders that the pipeline will use: - // the vertex shader and the fragment shader. - // - // A Vulkan shader can in theory contain multiple entry points, so we have to specify which - // one. - let vs = vs::load(device.clone()) - .unwrap() - .entry_point("main") - .unwrap(); - let fs = fs::load(device.clone()) - .unwrap() - .entry_point("main") - .unwrap(); - - // Automatically generate a vertex input state from the vertex shader's input interface, - // that takes a single vertex buffer containing `Vertex` structs. - let vertex_input_state = MyVertex::per_vertex().definition(&vs).unwrap(); - - // Make a list of the shader stages that the pipeline will have. - let stages = [ - PipelineShaderStageCreateInfo::new(vs), - PipelineShaderStageCreateInfo::new(fs), - ]; - - // We must now create a **pipeline layout** object, which describes the locations and types - // of descriptor sets and push constants used by the shaders in the pipeline. - // - // Multiple pipelines can share a common layout object, which is more efficient. - // The shaders in a pipeline must use a subset of the resources described in its pipeline - // layout, but the pipeline layout is allowed to contain resources that are not present in - // the shaders; they can be used by shaders in other pipelines that share the same - // layout. Thus, it is a good idea to design shaders so that many pipelines have - // common resource locations, which allows them to share pipeline layouts. - let layout = PipelineLayout::new( - device.clone(), - // Since we only have one pipeline in this example, and thus one pipeline layout, - // we automatically generate the creation info for it from the resources used in the - // shaders. In a real application, you would specify this information manually so that - // you can re-use one layout in multiple pipelines. - PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages) - .into_pipeline_layout_create_info(device.clone()) - .unwrap(), - ) - .unwrap(); - - // We describe the formats of attachment images where the colors, depth and/or stencil - // information will be written. The pipeline will only be usable with this particular - // configuration of the attachment images. - let subpass = PipelineRenderingCreateInfo { - // We specify a single color attachment that will be rendered to. When we begin - // rendering, we will specify a swapchain image to be used as this attachment, so here - // we set its format to be the same format as the swapchain. - color_attachment_formats: vec![Some(image_format)], - ..Default::default() - }; - - // Finally, create the pipeline. - GraphicsPipeline::new( - device.clone(), - None, - GraphicsPipelineCreateInfo { - stages: stages.into_iter().collect(), - // How vertex data is read from the vertex buffers into the vertex shader. - vertex_input_state: Some(vertex_input_state), - // How vertices are arranged into primitive shapes. - // The default primitive shape is a triangle. - input_assembly_state: Some(InputAssemblyState::default()), - // How primitives are transformed and clipped to fit the framebuffer. - // We use a resizable viewport, set to draw over the entire window. - viewport_state: Some(ViewportState::default()), - // How polygons are culled and converted into a raster of pixels. - // The default value does not perform any culling. - rasterization_state: Some(RasterizationState::default()), - // How multiple fragment shader samples are converted to a single pixel value. - // The default value does not perform any multisampling. - multisample_state: Some(MultisampleState::default()), - // How pixel values are combined with the values already present in the framebuffer. - // The default value overwrites the old value with the new one, without any - // blending. - color_blend_state: Some(ColorBlendState::with_attachment_states( - subpass.color_attachment_formats.len() as u32, - ColorBlendAttachmentState::default(), - )), - // Dynamic states allows us to specify parts of the pipeline settings when - // recording the command buffer, before we perform drawing. - // Here, we specify that the viewport should be dynamic. - dynamic_state: [DynamicState::Viewport].into_iter().collect(), - subpass: Some(subpass.into()), - ..GraphicsPipelineCreateInfo::layout(layout) - }, - ) - .unwrap() - }; - - (vertex_buffer, pipeline) -} - -#[derive(BufferContents, Vertex)] -#[repr(C)] -pub struct MyVertex { - #[format(R32G32_SFLOAT)] - position: [f32; 2], -} - -mod vs { - vulkano_shaders::shader! { - ty: "vertex", - src: r" - #version 450 - - layout(location = 0) in vec2 position; - - void main() { - gl_Position = vec4(position, 0.0, 1.0); - } - ", - } -} - -mod fs { - vulkano_shaders::shader! { - ty: "fragment", - src: r" - #version 450 - - layout(location = 0) out vec4 f_color; - - void main() { - f_color = vec4(1.0, 0.0, 0.0, 1.0); - } - ", - } -} diff --git a/src/modules/mod.rs b/src/modules/mod.rs deleted file mode 100644 index 5b071f9..0000000 --- a/src/modules/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod config; -pub mod graphics; -pub mod window; -// pub mod steel; diff --git a/src/modules/steel/mod.rs b/src/modules/steel/mod.rs deleted file mode 100644 index 55fbbd9..0000000 --- a/src/modules/steel/mod.rs +++ /dev/null @@ -1,104 +0,0 @@ -use std::sync::Arc; - -use flax::{component, BoxedSystem, EntityBorrow, Query, QueryBorrow, Schedule, System, World}; -use steel::steel_vm::engine::Engine; -use steel::steel_vm::register_fn::RegisterFn; -use steel_derive::Steel; - -use crate::core::module::Module; - -component! { - steel_script: String, - steel_event_tx: flume::Sender, - - resources, -} - -pub fn execute_script_system() -> BoxedSystem { - let tx_query = Query::new(steel_event_tx()).entity(resources()); - let script_query = Query::new(steel_script()); - - System::builder() - .with_query(tx_query) - .with_query(script_query) - .build(|mut tx_query: EntityBorrow<'_, flax::Component>>, mut script_query: QueryBorrow>| { - if let Ok(tx) = tx_query.get() { - for script in &mut script_query { - println!("Got script and tx"); - tx.send(SteelEvent::Execute(script.into())).unwrap(); - } - } - }) - .boxed() -} - -#[derive(Debug, Steel)] -enum SteelEvent { - Execute(String), -} - -#[allow(dead_code)] -#[derive(Steel, Clone)] -pub struct SteelModule { - engine: Engine, - // schedule: Schedule, - rx: flume::Receiver, -} - -impl SteelModule { - pub fn new( - schedule: &mut Schedule, - world: &mut World, - _events: &mut crate::core::events::Events, - ) -> Self { - let mut engine = Engine::new(); - - let (tx, rx) = flume::unbounded::(); - - let schedule_r = Schedule::builder() - .with_system(execute_script_system()) - .build(); - schedule.append(schedule_r); - - world.set(resources(), steel_event_tx(), tx).unwrap(); - - // Some testing - let entity = world.spawn(); - world.set(entity, steel_script(), r#" -(require-builtin steel/time) -(display "Hello ") -(time/sleep-ms 5000) -(display "World!")"#.into()).unwrap(); - - Self { - engine, - // schedule, - rx, - } - } -} - -impl Module for SteelModule { - fn on_update( - &mut self, - world: &mut World, - _events: &mut crate::core::events::Events, - _frame_time: std::time::Duration, - ) -> anyhow::Result<()> { - // self.schedule.execute_par(world).unwrap(); - - if let Ok(event) = self.rx.recv() { - match event { - SteelEvent::Execute(script) => { - let handle = std::thread::spawn(|| { - let mut engine = Engine::new(); - let val = engine.run(script).unwrap(); - println!("Steel val: {:?}", val); - }); - } - } - } - - Ok(()) - } -} diff --git a/src/modules/window/mod.rs b/src/modules/window/mod.rs deleted file mode 100644 index 0d5aded..0000000 --- a/src/modules/window/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -use flax::{Schedule, World}; - -use crate::core::module::Module; - -pub struct WindowModule { -} - -impl WindowModule { - pub fn new( - schedule: &mut Schedule, - _world: &mut World, - _events: &mut crate::core::events::Events, - ) -> Self { - let schedule_r = Schedule::builder() - .build(); - schedule.append(schedule_r); - Self { - - } - } -} - -impl Module for WindowModule { - fn on_update( - &mut self, - _world: &mut World, - _events: &mut crate::core::events::Events, - _frame_time: std::time::Duration, - ) -> anyhow::Result<()> { - // println!("WindowModule on_update"); - - Ok(()) - } -} diff --git a/src/render/mod.rs b/src/render/mod.rs new file mode 100644 index 0000000..c590599 --- /dev/null +++ b/src/render/mod.rs @@ -0,0 +1,19 @@ +use vulkano::device::DeviceFeatures; +use vulkano_util::context::{VulkanoConfig, VulkanoContext}; + +pub fn make_render_config() -> VulkanoConfig { + let device_features: DeviceFeatures = DeviceFeatures { + dynamic_rendering: true, + ..DeviceFeatures::empty() + }; + + VulkanoConfig { + device_features, + print_device_name: true, + ..Default::default() + } +} + +pub fn make_render_context() -> VulkanoContext { + VulkanoContext::new(make_render_config()) +}