diff --git a/Cargo.lock b/Cargo.lock index e69aec8..befb3ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,13 +19,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] -name = "ahash" -version = "0.8.11" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.3", "once_cell", "version_check", "zerocopy", @@ -40,6 +46,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "android-activity" version = "0.6.0" @@ -47,7 +59,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.9.0", + "bitflags 2.9.1", "cc", "cesu8", "jni", @@ -58,7 +70,7 @@ dependencies = [ "ndk-context", "ndk-sys", "num_enum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -67,96 +79,47 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" -dependencies = [ - "anstyle", - "once_cell", - "windows-sys 0.59.0", -] - -[[package]] -name = "any_vec" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6ac04794a7749710e3c7f3c93222e3d04692993b69876d69393efd2565401a" - [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] -name = "apecs" -version = "0.8.4" +name = "arbitrary" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df7760d4baebb17003dcf99134d8e3a63f487e146d58911f0bcd27afb185d1c" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arboard" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1df21f715862ede32a0c525ce2ca4d52626bb0007f8c18b87a384503ac33e70" dependencies = [ - "any_vec", - "apecs-derive", - "async-channel", - "itertools", + "clipboard-win", + "image", "log", - "moongraph", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.1", "parking_lot", - "rayon", - "smallvec", - "snafu 0.8.5", + "percent-encoding", + "windows-sys 0.59.0", + "x11rb", ] [[package]] -name = "apecs-derive" -version = "0.3.0" +name = "arg_enum_proc_macro" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0f3ddfd31fd5276fb8039b75dc4d284c21213757a969e480c6ef8fde494f3b" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ - "moongraph-macros-syntax", "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -187,14 +150,37 @@ dependencies = [ ] [[package]] -name = "async-channel" -version = "1.9.0" +name = "assert_type_match" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043" dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-executor" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" +dependencies = [ + "async-task", "concurrent-queue", - "event-listener", - "futures-core", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +dependencies = [ + "portable-atomic", ] [[package]] @@ -202,6 +188,9 @@ name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +dependencies = [ + "portable-atomic", +] [[package]] name = "autocfg" @@ -209,6 +198,176 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "av1-grain" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "bevy_ecs" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2bf6521aae57a0ec3487c4bfb59e36c4a378e834b626a4bea6a885af2fdfe7" +dependencies = [ + "arrayvec", + "bevy_ecs_macros", + "bevy_platform", + "bevy_ptr", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "bitflags 2.9.1", + "bumpalo", + "concurrent-queue", + "derive_more", + "disqualified", + "fixedbitset", + "indexmap", + "log", + "nonmax", + "serde", + "smallvec", + "thiserror 2.0.12", + "variadics_please", +] + +[[package]] +name = "bevy_ecs_macros" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38748d6f3339175c582d751f410fb60a93baf2286c3deb7efebb0878dce7f413" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_macro_utils" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052eeebcb8e7e072beea5031b227d9a290f8a7fbbb947573ab6ec81df0fb94be" +dependencies = [ + "parking_lot", + "proc-macro2", + "quote", + "syn", + "toml_edit", +] + +[[package]] +name = "bevy_platform" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7573dc824a1b08b4c93fdbe421c53e1e8188e9ca1dd74a414455fe571facb47" +dependencies = [ + "cfg-if", + "critical-section", + "foldhash", + "hashbrown", + "portable-atomic", + "portable-atomic-util", + "serde", + "spin", +] + +[[package]] +name = "bevy_ptr" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7370d0e46b60e071917711d0860721f5347bc958bf325975ae6913a5dfcf01" + +[[package]] +name = "bevy_reflect" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daeb91a63a1a4df00aa58da8cc4ddbd4b9f16ab8bb647c5553eb156ce36fa8c2" +dependencies = [ + "assert_type_match", + "bevy_platform", + "bevy_ptr", + "bevy_reflect_derive", + "bevy_utils", + "derive_more", + "disqualified", + "downcast-rs 2.0.1", + "erased-serde", + "foldhash", + "glam 0.29.3", + "serde", + "smallvec", + "smol_str", + "thiserror 2.0.12", + "uuid", + "variadics_please", + "wgpu-types", +] + +[[package]] +name = "bevy_reflect_derive" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ddadc55fe16b45faaa54ab2f9cb00548013c74812e8b018aa172387103cce6" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", + "uuid", +] + +[[package]] +name = "bevy_tasks" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b674242641cab680688fc3b850243b351c1af49d4f3417a576debd6cca8dcf5" +dependencies = [ + "async-executor", + "async-task", + "atomic-waker", + "bevy_platform", + "cfg-if", + "crossbeam-queue", + "derive_more", + "futures-lite", + "heapless", +] + +[[package]] +name = "bevy_utils" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f7a8905a125d2017e8561beefb7f2f5e67e93ff6324f072ad87c5fd6ec3b99" +dependencies = [ + "bevy_platform", + "thread_local", +] + +[[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" @@ -217,9 +376,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +dependencies = [ + "serde", +] + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" [[package]] name = "block2" @@ -231,15 +399,10 @@ dependencies = [ ] [[package]] -name = "broomdog" -version = "0.1.1" +name = "built" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ec65645d8167b03c07e049f114a878a11ab889f20c071d6f7b30bf88fbe5af" -dependencies = [ - "log", - "rustc-hash", - "snafu 0.8.5", -] +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" [[package]] name = "bumpalo" @@ -249,24 +412,36 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytemuck" -version = "1.22.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.8.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.10.1" @@ -279,12 +454,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "log", "polling", "rustix", "slab", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -301,9 +476,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" dependencies = [ "jobserver", "libc", @@ -316,6 +491,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -328,6 +513,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "clipboard-win" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" +dependencies = [ + "error-code", +] + [[package]] name = "cmake" version = "0.1.54" @@ -338,10 +532,10 @@ dependencies = [ ] [[package]] -name = "colorchoice" -version = "1.0.3" +name = "color_quant" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "combine" @@ -360,6 +554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", + "portable-atomic", ] [[package]] @@ -372,6 +567,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -385,7 +590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types", "libc", @@ -398,10 +603,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -449,14 +669,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] -name = "dagga" -version = "0.2.1" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cf0d7dcd307c9c5d81277737c35d1faf08af9e2cb262966a01c91021686b68" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "log", - "rustc-hash", - "snafu 0.7.5", + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] @@ -465,6 +695,33 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "disqualified" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" + [[package]] name = "dlib" version = "0.5.2" @@ -474,12 +731,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "downcast-rs" version = "1.2.1" @@ -487,10 +738,75 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "dpi" -version = "0.1.1" +name = "downcast-rs" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "ecolor" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc4feb366740ded31a004a0e4452fbf84e80ef432ecf8314c485210229672fd1" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "egui" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3" +dependencies = [ + "ahash", + "bitflags 2.9.1", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", +] + +[[package]] +name = "egui-winit" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9dfbb78fe4eb9c3a39ad528b90ee5915c252e77bbab9d4ebc576541ab67e13" +dependencies = [ + "ahash", + "arboard", + "bytemuck", + "egui", + "log", + "profiling", + "raw-window-handle", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", +] + +[[package]] +name = "egui_winit_vulkano" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6abd5e69939cd416853fc3ec69c0e08721b175d03b508d5574849885c7e85a6" +dependencies = [ + "ahash", + "egui", + "egui-winit", + "image", + "vulkano", + "vulkano-shaders", + "winit", +] [[package]] name = "either" @@ -499,28 +815,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "env_filter" -version = "0.1.3" +name = "emath" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "9e4cadcff7a5353ba72b7fea76bf2122b5ebdbc68e8155aa56dfdea90083fe1b" dependencies = [ - "log", - "regex", + "bytemuck", ] [[package]] -name = "env_logger" -version = "0.11.7" +name = "epaint" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "41fcc0f5a7c613afd2dee5e4b30c3e6acafb8ad6f0edb06068811f708a67c562" dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", "log", + "nohash-hasher", + "parking_lot", + "profiling", ] +[[package]] +name = "epaint_default_fonts" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7e7a64c02cf7a5b51e745a9e45f60660a286f151c238b9d397b3e923f5082f" + [[package]] name = "equivalent" version = "1.0.2" @@ -528,26 +854,82 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "errno" -version = "0.3.10" +name = "erased-serde" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "error-code" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +dependencies = [ + "crc32fast", + "miniz_oxide", +] [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -567,7 +949,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -576,12 +958,54 @@ 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 = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "generator" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "gethostname" version = "0.4.3" @@ -594,26 +1018,57 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[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 = "glam" -version = "0.30.0" +version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fcdf9683c406c2fc4d124afd29c0d595e22210d633cbdb8695ba9935ab1dc6" +checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" +dependencies = [ + "serde", +] + +[[package]] +name = "glam" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b46b9ca4690308844c644e7c634d68792467260e051c8543e0c7871662b3ba7" [[package]] name = "half" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "bytemuck", "cfg-if", @@ -621,10 +1076,34 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.15.2" +name = "hash32" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +dependencies = [ + "equivalent", + "serde", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "portable-atomic", + "stable_deref_trait", +] [[package]] name = "heck" @@ -632,6 +1111,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.4.0" @@ -639,26 +1124,186 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] -name = "indexmap" -version = "2.8.0" +name = "home" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", ] [[package]] -name = "is_terminal_polyfill" -version = "1.70.1" +name = "interpolate_name" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "itertools" -version = "0.10.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -669,30 +1314,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "jiff" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", -] - -[[package]] -name = "jiff-static" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - [[package]] name = "jni" version = "0.21.1" @@ -704,7 +1325,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -717,13 +1338,20 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "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.77" @@ -735,16 +1363,38 @@ dependencies = [ ] [[package]] -name = "libc" -version = "0.2.171" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -756,9 +1406,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.12", ] [[package]] @@ -767,6 +1417,12 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + [[package]] name = "lock_api" version = "0.4.12" @@ -779,9 +1435,50 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[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" @@ -805,27 +1502,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "moongraph" -version = "0.4.3" +name = "miniz_oxide" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a4b09eb96a84205062b48ec5469c8c35c128167e838aa73dc620c4411af598" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ - "broomdog", - "dagga", - "log", - "rayon", - "snafu 0.8.5", -] - -[[package]] -name = "moongraph-macros-syntax" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08112087acc92cc28fb5d8f7bda1307123ecc9a275ed4835f1c03f1a8dd02c1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", + "adler2", + "simd-adler32", ] [[package]] @@ -834,13 +1517,13 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "jni-sys", "log", "ndk-sys", "num_enum", "raw-window-handle", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -858,6 +1541,18 @@ 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" @@ -868,6 +1563,78 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[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-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "num_enum" version = "0.7.3" @@ -886,7 +1653,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -907,9 +1674,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" dependencies = [ "objc2-encode", ] @@ -920,7 +1687,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "libc", "objc2 0.5.2", @@ -930,13 +1697,25 @@ dependencies = [ "objc2-quartz-core 0.2.2", ] +[[package]] +name = "objc2-app-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-graphics", + "objc2-foundation 0.3.1", +] + [[package]] name = "objc2-cloud-kit" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "objc2 0.5.2", "objc2-core-location", @@ -960,7 +1739,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -968,12 +1747,26 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.0", + "bitflags 2.9.1", + "dispatch2", + "objc2 0.6.1", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +dependencies = [ + "bitflags 2.9.1", + "dispatch2", + "objc2 0.6.1", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -1012,7 +1805,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "dispatch", "libc", @@ -1021,12 +1814,23 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.0", + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", "objc2-core-foundation", ] @@ -1038,7 +1842,7 @@ checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ "block2", "objc2 0.5.2", - "objc2-app-kit", + "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", ] @@ -1048,7 +1852,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1056,13 +1860,13 @@ dependencies = [ [[package]] name = "objc2-metal" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c41bc8b0e50ea7a5304a56f25e0066f526e99641b46fd7b9ad4421dd35bff6" +checksum = "7f246c183239540aab1782457b35ab2040d4259175bd1d0c58e46ada7b47a874" dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.0", - "objc2-foundation 0.3.0", + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] @@ -1071,7 +1875,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1080,15 +1884,15 @@ dependencies = [ [[package]] name = "objc2-quartz-core" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071" +checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.0", + "bitflags 2.9.1", + "objc2 0.6.1", "objc2-core-foundation", - "objc2-foundation 0.3.0", - "objc2-metal 0.3.0", + "objc2-foundation 0.3.1", + "objc2-metal 0.3.1", ] [[package]] @@ -1107,7 +1911,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "objc2 0.5.2", "objc2-cloud-kit", @@ -1139,7 +1943,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "objc2 0.5.2", "objc2-core-location", @@ -1148,9 +1952,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "orbclient" @@ -1161,6 +1965,12 @@ dependencies = [ "libredox", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owned_ttf_parser" version = "0.25.0" @@ -1170,6 +1980,12 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -1188,11 +2004,17 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.12", "smallvec", "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1216,7 +2038,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1231,6 +2053,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polling" version = "3.7.4" @@ -1248,9 +2083,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -1261,6 +2096,24 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro-crate" version = "3.3.0" @@ -1272,18 +2125,52 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] -name = "quick-xml" -version = "0.37.2" +name = "profiling" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +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.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" dependencies = [ "memchr", ] @@ -1297,6 +2184,121 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[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 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps", + "thiserror 1.0.69", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -1309,10 +2311,10 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" dependencies = [ - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", - "objc2-foundation 0.3.0", - "objc2-quartz-core 0.3.0", + "objc2-foundation 0.3.1", + "objc2-quartz-core 0.3.1", ] [[package]] @@ -1346,11 +2348,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -1361,8 +2363,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1373,15 +2384,27 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + [[package]] name = "roxmltree" version = "0.14.1" @@ -1396,28 +2419,30 @@ name = "rust_vulkan_test" version = "0.1.0" dependencies = [ "anyhow", - "apecs", - "env_logger", - "glam", - "log", + "bevy_ecs", + "egui_winit_vulkano", + "glam 0.30.3", + "image", + "rand 0.9.1", + "thiserror 2.0.12", + "tobj", + "tracing", + "tracing-log", + "tracing-subscriber", + "tracing-tracy", "vulkano", "vulkano-shaders", + "vulkano-util", "winit", ] -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustix" version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", @@ -1487,7 +2512,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1502,6 +2527,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "shaderc" version = "0.8.3" @@ -1523,12 +2557,36 @@ dependencies = [ "roxmltree", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[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 = "slab" version = "0.4.9" @@ -1546,9 +2604,9 @@ checksum = "9db491c0d4152a069911a0fbdaca959691bf0b9d7110d98a7ed1c8e59b79ab30" [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "smithay-client-toolkit" @@ -1556,7 +2614,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "calloop", "calloop-wayland-source", "cursor-icon", @@ -1564,7 +2622,7 @@ dependencies = [ "log", "memmap2", "rustix", - "thiserror", + "thiserror 1.0.69", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -1575,6 +2633,17 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "smithay-clipboard" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" +dependencies = [ + "libc", + "smithay-client-toolkit", + "wayland-backend", +] + [[package]] name = "smol_str" version = "0.2.2" @@ -1585,47 +2654,19 @@ dependencies = [ ] [[package]] -name = "snafu" -version = "0.7.5" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "doc-comment", - "snafu-derive 0.7.5", + "portable-atomic", ] [[package]] -name = "snafu" -version = "0.8.5" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" -dependencies = [ - "snafu-derive 0.8.5", -] - -[[package]] -name = "snafu-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "snafu-derive" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.100", -] +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strict-num" @@ -1635,9 +2676,9 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -1645,23 +2686,51 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.100" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn", ] +[[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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -1672,7 +2741,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1685,6 +2765,17 @@ 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" @@ -1711,18 +2802,54 @@ dependencies = [ ] [[package]] -name = "toml_datetime" -version = "0.6.8" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tobj" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04aca6092e5978e708ee784e8ab9b5cf3cdb598b28f99a2f257446e7081a7025" +dependencies = [ + "ahash", +] + +[[package]] +name = "toml" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", + "serde", + "serde_spanned", "toml_datetime", "winnow", ] @@ -1734,14 +2861,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-tracy" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracy-client", +] + +[[package]] +name = "tracy-client" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d90a2c01305b02b76fdd89ac8608bae27e173c829a35f7d76a345ab5d33836db" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys", +] + +[[package]] +name = "tracy-client-sys" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fff37da548239c3bf9e64a12193d261e8b22b660991c6fd2df057c168f435f" +dependencies = [ + "cc", + "windows-targets 0.52.6", +] [[package]] name = "ttf-parser" @@ -1749,6 +2953,12 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -1762,10 +2972,73 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "utf8parse" -version = "0.2.2" +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "serde", + "wasm-bindgen", +] + +[[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 = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "variadics_please" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" @@ -1793,7 +3066,7 @@ dependencies = [ "crossbeam-queue", "foldhash", "half", - "heck", + "heck 0.4.1", "indexmap", "libloading", "nom", @@ -1823,7 +3096,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1833,14 +3106,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf501461be7cef2893c0e62c50945add9763cc482051d29053f6157089d5ea9" dependencies = [ "foldhash", - "heck", + "heck 0.4.1", "proc-macro2", "quote", "shaderc", - "syn 2.0.100", + "syn", "vulkano", ] +[[package]] +name = "vulkano-util" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25dc54fd5e14a0e01c7282f9b5d9c6e133745e1df3228b0352366e34c83bb6b" +dependencies = [ + "foldhash", + "vulkano", + "winit", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -1857,6 +3141,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -1879,7 +3172,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn", "wasm-bindgen-shared", ] @@ -1914,7 +3207,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1930,12 +3223,12 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf" +checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" dependencies = [ "cc", - "downcast-rs", + "downcast-rs 1.2.1", "rustix", "scoped-tls", "smallvec", @@ -1944,11 +3237,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" +checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "rustix", "wayland-backend", "wayland-scanner", @@ -1960,16 +3253,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d" +checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" dependencies = [ "rustix", "wayland-client", @@ -1978,11 +3271,11 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.6" +version = "0.32.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc" +checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-scanner", @@ -1990,11 +3283,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccaacc76703fefd6763022ac565b590fcade92202492381c95b2edfdf7d46b3" +checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2003,11 +3296,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2" +checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2057,6 +3350,58 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5df295f8451142f1856b1bd86a606dfe9587d439bc036e319c827700dbd555e" +dependencies = [ + "core-foundation 0.10.0", + "home", + "jni", + "log", + "ndk-context", + "objc2 0.6.1", + "objc2-foundation 0.3.1", + "url", + "web-sys", +] + +[[package]] +name = "weezl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "wgpu-types" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c" +dependencies = [ + "bitflags 2.9.1", + "js-sys", + "log", + "serde", + "web-sys", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -2066,6 +3411,114 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -2139,6 +3592,15 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -2273,20 +3735,20 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.9" +version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" +checksum = "b0d05bd8908e14618c9609471db04007e644fd9cce6529756046cfc577f9155e" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.9.0", + "bitflags 2.9.1", "block2", "bytemuck", "calloop", "cfg_aliases", "concurrent-queue", - "core-foundation", + "core-foundation 0.9.4", "core-graphics", "cursor-icon", "dpi", @@ -2295,7 +3757,7 @@ dependencies = [ "memmap2", "ndk", "objc2 0.5.2", - "objc2-app-kit", + "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", "objc2-ui-kit", "orbclient", @@ -2325,13 +3787,28 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + [[package]] name = "x11-dl" version = "2.21.0" @@ -2376,7 +3853,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "dlib", "log", "once_cell", @@ -2391,9 +3868,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "xmlparser" @@ -2402,21 +3879,123 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" [[package]] -name = "zerocopy" -version = "0.7.35" +name = "yoke" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +dependencies = [ + "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index ba7eb9d..6883189 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,17 +7,30 @@ publish = false [dependencies] anyhow = "1.0" +thiserror = "2.0" winit = { version = "0.30", features = ["rwh_06"] } vulkano = "0.35" vulkano-shaders = "0.35" +vulkano-util = "0.35" +egui_winit_vulkano = { version = "0.28" } + +image = { version = "0.25", features = ["png", "jpeg"] } # Math glam = { version = "0.30" } -# ECS -apecs = "0.8" - # Log and tracing -log = "0.4" -env_logger = "0.11.5" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } +tracing-log = "0.2" +tracing-tracy = "0.11" + +# Random +rand = "0.9" + +# OBJ loader +tobj = "4.0" + +# ECS +bevy_ecs = "0.16.1" # Latest version diff --git a/README.md b/README.md new file mode 100644 index 0000000..c271fd8 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Project + +## Notes + +1. Run renderdoc on wayland: + +```console +WAYLAND_DISPLAY= QT_QPA_PLATFORM=xcb qrenderdoc +``` +> Not supported yet https://github.com/baldurk/renderdoc/issues/853 + +2. [Difference Between OpenGL and Vulkan](./docs/OPENGL_VULKAN_DIFF.md) + +## Usefull links + +- https://vulkan-tutorial.com/fr/Introduction +- https://github.com/bwasty/vulkan-tutorial-rs diff --git a/docs/OPENGL_VULKAN_DIFF.md b/docs/OPENGL_VULKAN_DIFF.md new file mode 100644 index 0000000..93d0855 --- /dev/null +++ b/docs/OPENGL_VULKAN_DIFF.md @@ -0,0 +1,11 @@ +# Difference between Vulkan and OpenGL + +Viewport: + +- Y axis is flipped like D3D +- Clipped Z axis is not [-1; 1] but [0; 1] + +![normalized viewport coordinates](./images/normalized_device_coordinates.svg) +![coord_sys](./images/coord_sys.png) + +See: [Vulkan Tutorial (Vertex step)](https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Shader_modules) and [VK_KHR_maintenance1 (Allow negative height)](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_maintenance1.html#_description) diff --git a/docs/USE_ASH_METHODS.md b/docs/USE_ASH_METHODS.md new file mode 100644 index 0000000..a69997d --- /dev/null +++ b/docs/USE_ASH_METHODS.md @@ -0,0 +1,15 @@ +# Informations + +```rust +let fns = vulkano_context.instance().fns(); +let mut props = ash::vk::PhysicalDeviceProperties::default(); + +unsafe { + (fns.v1_0.get_physical_device_properties)( + vulkano_context.device().physical_device().handle(), + &mut props, + ); +} + +println!("{:?}", props); +``` diff --git a/docs/images/coord_sys.png b/docs/images/coord_sys.png new file mode 100644 index 0000000..6d195f6 Binary files /dev/null and b/docs/images/coord_sys.png differ diff --git a/docs/images/normalized_device_coordinates.svg b/docs/images/normalized_device_coordinates.svg new file mode 100644 index 0000000..970c9f4 --- /dev/null +++ b/docs/images/normalized_device_coordinates.svg @@ -0,0 +1,219 @@ + + + + + + + + + + image/svg+xml + + + + + + + + Framebuffer coordinates + (0, 0) + (1920, 0) + (0, 1080) + (1920, 1080) + + (960, 540) + + Normalized device coordinates + (-1, -1) + (1, -1) + (-1, 1) + (1, 1) + + (0, 0) + + diff --git a/flake.lock b/flake.lock index 2853bb7..4f4cf7e 100644 --- a/flake.lock +++ b/flake.lock @@ -44,11 +44,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1742546557, - "narHash": "sha256-QyhimDBaDBtMfRc7kyL28vo+HTwXRPq3hz+BgSJDotw=", + "lastModified": 1747312588, + "narHash": "sha256-MmJvj6mlWzeRwKGLcwmZpKaOPZ5nJb/6al5CXqJsgjo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "bfa9810ff7104a17555ab68ebdeafb6705f129b1", + "rev": "b1bebd0fe266bbd1820019612ead889e96a8fa2d", "type": "github" }, "original": { @@ -73,11 +73,11 @@ ] }, "locked": { - "lastModified": 1742524367, - "narHash": "sha256-KzTwk/5ETJavJZYV1DEWdCx05M4duFCxCpRbQSKWpng=", + "lastModified": 1747363019, + "narHash": "sha256-N4dwkRBmpOosa4gfFkFf/LTD8oOcNkAyvZ07JvRDEf0=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "70bf752d176b2ce07417e346d85486acea9040ef", + "rev": "0e624f2b1972a34be1a9b35290ed18ea4b419b6f", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 565976b..645ade4 100644 --- a/flake.nix +++ b/flake.nix @@ -31,18 +31,15 @@ cargo = rust; }); - renderdoc = pkgs.renderdoc.overrideAttrs (oldAttrs: { - cmakeFlags = oldAttrs.cmakeFlags ++ [ - (pkgs.lib.cmakeBool "ENABLE_UNSUPPORTED_EXPERIMENTAL_POSSIBLY_BROKEN_WAYLAND" true) - ]; - }); - - buildInputs = with pkgs; [ vulkan-headers vulkan-loader vulkan-validation-layers renderdoc ] + buildInputs = with pkgs; [ vulkan-headers vulkan-loader vulkan-validation-layers renderdoc tracy ] ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux (with pkgs; [ + stdenv.cc.cc.lib + # Wayland libxkbcommon wayland libGL + # Xorg xorg.libX11 xorg.libXcursor @@ -60,7 +57,7 @@ mkCustomShell = { packages ? [ ] }: pkgs.mkShell { nativeBuildInputs = [ - renderdoc + pkgs.renderdoc (rust.override { extensions = [ "rust-src" "rust-analyzer" ]; }) ] ++ nativeBuildInputs; @@ -68,8 +65,8 @@ ++ packages; LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs; - VK_LAYER_PATH = "${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d:${renderdoc}/share/vulkan/implicit_layer.d"; - RUST_LOG = "info,rust_vulkan_test=trace"; + VK_LAYER_PATH = "${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d"; + RUST_LOG = "debug,rust_vulkan_test=trace"; }; in { @@ -80,7 +77,7 @@ packages = { default = rustPlatform.buildRustPackage { - pname = "rust_ash_test"; + pname = "vulkan_test"; version = "0.1.0"; src = self; diff --git a/res/objects/cube-diffuse.jpg b/res/objects/cube-diffuse.jpg new file mode 100644 index 0000000..c89b31d Binary files /dev/null and b/res/objects/cube-diffuse.jpg differ diff --git a/res/objects/cube-normal.png b/res/objects/cube-normal.png new file mode 100644 index 0000000..5bbac0a Binary files /dev/null and b/res/objects/cube-normal.png differ diff --git a/res/objects/cube.obj b/res/objects/cube.obj new file mode 100644 index 0000000..03b3bca --- /dev/null +++ b/res/objects/cube.obj @@ -0,0 +1,1143 @@ +# Blender v2.82 (sub 7) OBJ File: 'cube.blend' +# www.blender.org +mtllib cube.mtl +o Cube_Finished_Cube.001 +v 0.900000 0.900000 -1.000000 +v 0.900000 1.000000 -0.900000 +v 1.000000 0.900000 -0.900000 +v 0.900000 0.930907 -0.995104 +v 0.900000 0.958769 -0.980909 +v 0.930907 0.900000 -0.995104 +v 0.931727 0.931906 -0.989305 +v 0.930693 0.957414 -0.975905 +v 0.958769 0.900000 -0.980909 +v 0.957466 0.930772 -0.975834 +v 0.952912 0.952912 -0.966338 +v 0.930907 0.995104 -0.900000 +v 0.958769 0.980909 -0.900000 +v 0.900000 0.995104 -0.930907 +v 0.931906 0.989305 -0.931727 +v 0.957414 0.975905 -0.930693 +v 0.900000 0.980909 -0.958769 +v 0.930772 0.975834 -0.957466 +v 0.952912 0.966338 -0.952912 +v 0.995104 0.900000 -0.930907 +v 0.980909 0.900000 -0.958769 +v 0.995104 0.930907 -0.900000 +v 0.989305 0.931727 -0.931906 +v 0.975905 0.930693 -0.957414 +v 0.980909 0.958769 -0.900000 +v 0.975834 0.957466 -0.930772 +v 0.966338 0.952912 -0.952912 +v 0.900000 -1.000000 -0.900000 +v 0.900000 -0.900000 -1.000000 +v 1.000000 -0.900000 -0.900000 +v 0.900000 -0.995104 -0.930907 +v 0.900000 -0.980909 -0.958769 +v 0.930907 -0.995104 -0.900000 +v 0.931727 -0.989305 -0.931906 +v 0.930693 -0.975905 -0.957414 +v 0.958769 -0.980909 -0.900000 +v 0.957466 -0.975834 -0.930772 +v 0.952912 -0.966338 -0.952912 +v 0.930907 -0.900000 -0.995104 +v 0.958769 -0.900000 -0.980909 +v 0.900000 -0.930907 -0.995104 +v 0.931906 -0.931727 -0.989305 +v 0.957414 -0.930693 -0.975905 +v 0.900000 -0.958769 -0.980909 +v 0.930772 -0.957466 -0.975834 +v 0.952912 -0.952912 -0.966338 +v 0.995104 -0.930907 -0.900000 +v 0.980909 -0.958769 -0.900000 +v 0.995104 -0.900000 -0.930907 +v 0.989305 -0.931906 -0.931727 +v 0.975905 -0.957414 -0.930693 +v 0.980909 -0.900000 -0.958769 +v 0.975834 -0.930772 -0.957466 +v 0.966338 -0.952912 -0.952912 +v 1.000000 0.900000 0.900000 +v 0.900000 1.000000 0.900000 +v 0.900000 0.900000 1.000000 +v 0.995104 0.930907 0.900000 +v 0.980909 0.958769 0.900000 +v 0.995104 0.900000 0.930907 +v 0.989305 0.931906 0.931727 +v 0.975905 0.957414 0.930693 +v 0.980909 0.900000 0.958769 +v 0.975834 0.930772 0.957466 +v 0.966338 0.952912 0.952912 +v 0.900000 0.995104 0.930907 +v 0.900000 0.980909 0.958769 +v 0.930907 0.995104 0.900000 +v 0.931727 0.989305 0.931906 +v 0.930693 0.975905 0.957414 +v 0.958769 0.980909 0.900000 +v 0.957466 0.975834 0.930772 +v 0.952912 0.966338 0.952912 +v 0.930907 0.900000 0.995104 +v 0.958769 0.900000 0.980909 +v 0.900000 0.930907 0.995104 +v 0.931906 0.931727 0.989305 +v 0.957414 0.930693 0.975905 +v 0.900000 0.958769 0.980909 +v 0.930772 0.957466 0.975834 +v 0.952912 0.952912 0.966338 +v 1.000000 -0.900000 0.900000 +v 0.900000 -0.900000 1.000000 +v 0.900000 -1.000000 0.900000 +v 0.995104 -0.900000 0.930907 +v 0.980909 -0.900000 0.958769 +v 0.995104 -0.930907 0.900000 +v 0.989305 -0.931727 0.931906 +v 0.975905 -0.930693 0.957414 +v 0.980909 -0.958769 0.900000 +v 0.975834 -0.957466 0.930772 +v 0.966338 -0.952912 0.952912 +v 0.900000 -0.930907 0.995104 +v 0.900000 -0.958769 0.980909 +v 0.930907 -0.900000 0.995104 +v 0.931727 -0.931906 0.989305 +v 0.930693 -0.957414 0.975905 +v 0.958769 -0.900000 0.980909 +v 0.957466 -0.930772 0.975834 +v 0.952912 -0.952912 0.966338 +v 0.930907 -0.995104 0.900000 +v 0.958769 -0.980909 0.900000 +v 0.900000 -0.995104 0.930907 +v 0.931906 -0.989305 0.931727 +v 0.957414 -0.975905 0.930693 +v 0.900000 -0.980909 0.958769 +v 0.930772 -0.975834 0.957466 +v 0.952912 -0.966338 0.952912 +v -0.900000 0.900000 -1.000000 +v -1.000000 0.900000 -0.900000 +v -0.900000 1.000000 -0.900000 +v -0.930907 0.900000 -0.995104 +v -0.958769 0.900000 -0.980909 +v -0.900000 0.930907 -0.995104 +v -0.931906 0.931727 -0.989305 +v -0.957414 0.930693 -0.975905 +v -0.900000 0.958769 -0.980909 +v -0.930772 0.957466 -0.975834 +v -0.952912 0.952912 -0.966338 +v -0.995104 0.930907 -0.900000 +v -0.980909 0.958769 -0.900000 +v -0.995104 0.900000 -0.930907 +v -0.989305 0.931906 -0.931727 +v -0.975905 0.957414 -0.930693 +v -0.980909 0.900000 -0.958769 +v -0.975834 0.930772 -0.957466 +v -0.966338 0.952912 -0.952912 +v -0.900000 0.995104 -0.930907 +v -0.900000 0.980909 -0.958769 +v -0.930907 0.995104 -0.900000 +v -0.931727 0.989305 -0.931906 +v -0.930693 0.975905 -0.957414 +v -0.958769 0.980909 -0.900000 +v -0.957466 0.975834 -0.930772 +v -0.952912 0.966338 -0.952912 +v -1.000000 -0.900000 -0.900000 +v -0.900000 -0.900000 -1.000000 +v -0.900000 -1.000000 -0.900000 +v -0.995104 -0.900000 -0.930907 +v -0.980909 -0.900000 -0.958769 +v -0.995104 -0.930907 -0.900000 +v -0.989305 -0.931727 -0.931906 +v -0.975905 -0.930693 -0.957414 +v -0.980909 -0.958769 -0.900000 +v -0.975834 -0.957466 -0.930772 +v -0.966338 -0.952912 -0.952912 +v -0.900000 -0.930907 -0.995104 +v -0.900000 -0.958769 -0.980909 +v -0.930907 -0.900000 -0.995104 +v -0.931727 -0.931906 -0.989305 +v -0.930693 -0.957414 -0.975905 +v -0.958769 -0.900000 -0.980909 +v -0.957466 -0.930772 -0.975834 +v -0.952912 -0.952912 -0.966338 +v -0.930907 -0.995104 -0.900000 +v -0.958769 -0.980909 -0.900000 +v -0.900000 -0.995104 -0.930907 +v -0.931906 -0.989305 -0.931727 +v -0.957414 -0.975905 -0.930693 +v -0.900000 -0.980909 -0.958769 +v -0.930772 -0.975834 -0.957466 +v -0.952912 -0.966338 -0.952912 +v -1.000000 0.900000 0.900000 +v -0.900000 0.900000 1.000000 +v -0.900000 1.000000 0.900000 +v -0.995104 0.900000 0.930907 +v -0.980909 0.900000 0.958769 +v -0.995104 0.930907 0.900000 +v -0.989305 0.931727 0.931906 +v -0.975905 0.930693 0.957414 +v -0.980909 0.958769 0.900000 +v -0.975834 0.957466 0.930772 +v -0.966338 0.952912 0.952912 +v -0.900000 0.930907 0.995104 +v -0.900000 0.958769 0.980909 +v -0.930907 0.900000 0.995104 +v -0.931727 0.931906 0.989305 +v -0.930693 0.957414 0.975905 +v -0.958769 0.900000 0.980909 +v -0.957466 0.930772 0.975834 +v -0.952912 0.952912 0.966338 +v -0.930907 0.995104 0.900000 +v -0.958769 0.980909 0.900000 +v -0.900000 0.995104 0.930907 +v -0.931906 0.989305 0.931727 +v -0.957414 0.975905 0.930693 +v -0.900000 0.980909 0.958769 +v -0.930772 0.975834 0.957466 +v -0.952912 0.966338 0.952912 +v -0.900000 -1.000000 0.900000 +v -0.900000 -0.900000 1.000000 +v -1.000000 -0.900000 0.900000 +v -0.900000 -0.995104 0.930907 +v -0.900000 -0.980909 0.958769 +v -0.930907 -0.995104 0.900000 +v -0.931727 -0.989305 0.931906 +v -0.930693 -0.975905 0.957414 +v -0.958769 -0.980909 0.900000 +v -0.957466 -0.975834 0.930772 +v -0.952912 -0.966338 0.952912 +v -0.930907 -0.900000 0.995104 +v -0.958769 -0.900000 0.980909 +v -0.900000 -0.930907 0.995104 +v -0.931906 -0.931727 0.989305 +v -0.957414 -0.930693 0.975905 +v -0.900000 -0.958769 0.980909 +v -0.930772 -0.957466 0.975834 +v -0.952912 -0.952912 0.966338 +v -0.995104 -0.930907 0.900000 +v -0.980909 -0.958769 0.900000 +v -0.995104 -0.900000 0.930907 +v -0.989305 -0.931906 0.931727 +v -0.975905 -0.957414 0.930693 +v -0.980909 -0.900000 0.958769 +v -0.975834 -0.930772 0.957466 +v -0.966338 -0.952912 0.952912 +vt 0.362500 0.512500 +vt 0.137500 0.737500 +vt 0.137500 0.512500 +vt 0.612500 0.012500 +vt 0.387500 0.237500 +vt 0.387500 0.012500 +vt 0.612500 0.762500 +vt 0.387500 0.987500 +vt 0.387500 0.762500 +vt 0.862500 0.512500 +vt 0.637500 0.737500 +vt 0.637500 0.512500 +vt 0.612500 0.512500 +vt 0.387500 0.737500 +vt 0.387500 0.512500 +vt 0.616363 0.487500 +vt 0.612500 0.491363 +vt 0.612500 0.487500 +vt 0.619846 0.487500 +vt 0.616488 0.491466 +vt 0.625000 0.487500 +vt 0.619677 0.491337 +vt 0.612500 0.494846 +vt 0.619114 0.494114 +vt 0.616346 0.494683 +vt 0.625000 0.491347 +vt 0.633637 0.512500 +vt 0.637500 0.508637 +vt 0.630154 0.512500 +vt 0.633512 0.508534 +vt 0.619846 0.512500 +vt 0.630323 0.508663 +vt 0.637500 0.505154 +vt 0.630886 0.505886 +vt 0.633654 0.505317 +vt 0.619683 0.508653 +vt 0.612500 0.508637 +vt 0.616363 0.512500 +vt 0.612500 0.505154 +vt 0.616466 0.508512 +vt 0.616337 0.505323 +vt 0.619114 0.505886 +vt 0.625000 0.494114 +vt 0.619114 0.500000 +vt 0.362500 0.508637 +vt 0.366363 0.512500 +vt 0.362500 0.505154 +vt 0.366466 0.508512 +vt 0.362500 0.500000 +vt 0.366337 0.505323 +vt 0.369846 0.512500 +vt 0.369114 0.505886 +vt 0.369683 0.508653 +vt 0.366347 0.500000 +vt 0.387500 0.491363 +vt 0.383637 0.487500 +vt 0.387500 0.487500 +vt 0.387500 0.494846 +vt 0.383534 0.491488 +vt 0.387500 0.505154 +vt 0.383663 0.494677 +vt 0.380154 0.487500 +vt 0.380886 0.494114 +vt 0.380317 0.491346 +vt 0.383653 0.505317 +vt 0.383637 0.512500 +vt 0.387500 0.508637 +vt 0.380154 0.512500 +vt 0.383512 0.508534 +vt 0.380323 0.508663 +vt 0.380886 0.505886 +vt 0.369114 0.500000 +vt 0.375000 0.505886 +vt 0.616363 0.737500 +vt 0.612500 0.741363 +vt 0.612500 0.737500 +vt 0.619846 0.737500 +vt 0.616488 0.741466 +vt 0.630154 0.737500 +vt 0.619677 0.741337 +vt 0.612500 0.744846 +vt 0.619114 0.744114 +vt 0.616346 0.744683 +vt 0.630317 0.741346 +vt 0.637500 0.741363 +vt 0.633637 0.737500 +vt 0.637500 0.744846 +vt 0.633534 0.741488 +vt 0.637500 0.750000 +vt 0.633664 0.744677 +vt 0.630886 0.744114 +vt 0.633653 0.750000 +vt 0.612500 0.758637 +vt 0.616363 0.762500 +vt 0.612500 0.755154 +vt 0.616466 0.758512 +vt 0.616337 0.755323 +vt 0.619846 0.762500 +vt 0.619114 0.755886 +vt 0.619683 0.758653 +vt 0.625000 0.744114 +vt 0.619114 0.750000 +vt 0.387500 0.741363 +vt 0.383637 0.737500 +vt 0.387500 0.744846 +vt 0.383534 0.741488 +vt 0.387500 0.755154 +vt 0.383663 0.744677 +vt 0.380154 0.737500 +vt 0.380886 0.744114 +vt 0.380317 0.741346 +vt 0.383653 0.755317 +vt 0.383637 0.762500 +vt 0.387500 0.758637 +vt 0.380154 0.762500 +vt 0.383512 0.758534 +vt 0.375000 0.762500 +vt 0.380323 0.758663 +vt 0.380886 0.755886 +vt 0.375000 0.758654 +vt 0.366363 0.737500 +vt 0.362500 0.741363 +vt 0.362500 0.737500 +vt 0.369846 0.737500 +vt 0.366488 0.741466 +vt 0.369677 0.741337 +vt 0.362500 0.744846 +vt 0.369114 0.744114 +vt 0.366347 0.744683 +vt 0.380886 0.750000 +vt 0.375000 0.744114 +vt 0.612500 0.258637 +vt 0.616363 0.262500 +vt 0.612500 0.262500 +vt 0.612500 0.255154 +vt 0.616466 0.258512 +vt 0.612500 0.244846 +vt 0.616337 0.255323 +vt 0.619846 0.262500 +vt 0.619114 0.255886 +vt 0.619683 0.258653 +vt 0.616346 0.244683 +vt 0.616363 0.237500 +vt 0.612500 0.241363 +vt 0.612500 0.237500 +vt 0.619846 0.237500 +vt 0.616488 0.241466 +vt 0.625000 0.237500 +vt 0.619677 0.241337 +vt 0.619114 0.244114 +vt 0.625000 0.241347 +vt 0.862500 0.508637 +vt 0.866363 0.512500 +vt 0.862500 0.505154 +vt 0.866466 0.508512 +vt 0.862500 0.500000 +vt 0.866337 0.505323 +vt 0.869846 0.512500 +vt 0.869114 0.505886 +vt 0.869683 0.508653 +vt 0.866347 0.500000 +vt 0.619114 0.250000 +vt 0.625000 0.255886 +vt 0.387500 0.241363 +vt 0.383637 0.237500 +vt 0.387500 0.244846 +vt 0.383534 0.241488 +vt 0.387500 0.255154 +vt 0.383663 0.244677 +vt 0.380154 0.237500 +vt 0.380886 0.244114 +vt 0.380317 0.241346 +vt 0.383653 0.255317 +vt 0.383637 0.262500 +vt 0.387500 0.258637 +vt 0.387500 0.262500 +vt 0.380154 0.262500 +vt 0.383512 0.258534 +vt 0.375000 0.262500 +vt 0.380323 0.258663 +vt 0.380886 0.255886 +vt 0.375000 0.258653 +vt 0.133637 0.512500 +vt 0.137500 0.508637 +vt 0.130154 0.512500 +vt 0.133512 0.508534 +vt 0.125000 0.512500 +vt 0.130323 0.508663 +vt 0.137500 0.505154 +vt 0.130886 0.505886 +vt 0.133653 0.505317 +vt 0.125000 0.508654 +vt 0.380886 0.250000 +vt 0.375000 0.244114 +vt 0.612500 0.008637 +vt 0.616363 0.012500 +vt 0.612500 0.005154 +vt 0.616466 0.008512 +vt 0.612500 0.000000 +vt 0.616337 0.005323 +vt 0.619846 0.012500 +vt 0.619114 0.005886 +vt 0.619683 0.008654 +vt 0.616346 0.000000 +vt 0.616363 0.987500 +vt 0.612500 0.991363 +vt 0.612500 0.987500 +vt 0.619846 0.987500 +vt 0.616488 0.991466 +vt 0.625000 0.987500 +vt 0.619677 0.991337 +vt 0.612500 0.994846 +vt 0.619114 0.994114 +vt 0.616346 0.994683 +vt 0.625000 0.991346 +vt 0.866363 0.737500 +vt 0.862500 0.741363 +vt 0.862500 0.737500 +vt 0.869846 0.737500 +vt 0.866488 0.741466 +vt 0.875000 0.737500 +vt 0.869677 0.741337 +vt 0.862500 0.744846 +vt 0.869114 0.744114 +vt 0.866346 0.744683 +vt 0.875000 0.741347 +vt 0.619114 0.000000 +vt 0.625000 0.005886 +vt 0.137500 0.741363 +vt 0.133637 0.737500 +vt 0.137500 0.744846 +vt 0.133534 0.741488 +vt 0.137500 0.750000 +vt 0.133663 0.744677 +vt 0.130154 0.737500 +vt 0.130886 0.744114 +vt 0.130317 0.741346 +vt 0.133653 0.750000 +vt 0.387500 0.991363 +vt 0.383637 0.987500 +vt 0.387500 0.994846 +vt 0.383534 0.991488 +vt 0.387500 1.000000 +vt 0.383663 0.994677 +vt 0.380154 0.987500 +vt 0.380886 0.994114 +vt 0.380317 0.991346 +vt 0.383654 1.000000 +vt 0.383637 0.012500 +vt 0.387500 0.008637 +vt 0.380154 0.012500 +vt 0.383512 0.008534 +vt 0.375000 0.012500 +vt 0.380323 0.008663 +vt 0.387500 0.005154 +vt 0.380886 0.005886 +vt 0.383653 0.005317 +vt 0.375000 0.008653 +vt 0.130886 0.750000 +vt 0.125000 0.744114 +vt 0.630886 0.750000 +vt 0.375000 0.755886 +vt 0.625000 0.244114 +vt 0.869114 0.500000 +vt 0.375000 0.255886 +vt 0.125000 0.505886 +vt 0.625000 0.994114 +vt 0.875000 0.744114 +vt 0.380886 1.000000 +vt 0.375000 0.005886 +vt 0.125000 0.737500 +vt 0.137500 0.500000 +vt 0.612500 1.000000 +vt 0.862500 0.750000 +vt 0.362500 0.750000 +vt 0.875000 0.512500 +vt 0.637500 0.500000 +vn 0.0779 -0.9939 -0.0779 +vn -0.0779 -0.9939 0.0779 +vn -0.0779 -0.9939 -0.0779 +vn -0.9939 0.0779 0.0779 +vn -0.9939 -0.0779 -0.0779 +vn -0.9939 -0.0779 0.0779 +vn 0.0779 0.0779 0.9939 +vn -0.0779 -0.0779 0.9939 +vn 0.0779 -0.0779 0.9939 +vn -0.0779 0.9939 -0.0779 +vn 0.0779 0.9939 0.0779 +vn 0.0779 0.9939 -0.0779 +vn 0.9939 0.0779 -0.0779 +vn 0.9939 -0.0779 0.0779 +vn 0.9939 -0.0779 -0.0779 +vn 0.0783 0.3064 -0.9486 +vn 0.3066 0.0787 -0.9485 +vn 0.0779 0.0779 -0.9939 +vn 0.0754 0.5855 -0.8071 +vn 0.3089 0.3098 -0.8992 +vn 0.0757 0.8072 -0.5853 +vn 0.2866 0.5718 -0.7687 +vn 0.5853 0.0757 -0.8072 +vn 0.5154 0.5156 -0.6844 +vn 0.5719 0.2870 -0.7685 +vn 0.2870 0.7685 -0.5719 +vn 0.3064 0.9486 -0.0783 +vn 0.0787 0.9485 -0.3066 +vn 0.5855 0.8071 -0.0754 +vn 0.3098 0.8992 -0.3089 +vn 0.8072 0.5853 -0.0757 +vn 0.5718 0.7687 -0.2866 +vn 0.5156 0.6844 -0.5154 +vn 0.7685 0.5719 -0.2870 +vn 0.9486 0.0783 -0.3064 +vn 0.9485 0.3066 -0.0787 +vn 0.8071 0.0754 -0.5855 +vn 0.8992 0.3089 -0.3098 +vn 0.7687 0.2866 -0.5718 +vn 0.6844 0.5154 -0.5156 +vn 0.0783 -0.9486 -0.3064 +vn 0.3066 -0.9485 -0.0787 +vn 0.0754 -0.8071 -0.5855 +vn 0.3089 -0.8992 -0.3098 +vn 0.0757 -0.5853 -0.8072 +vn 0.2866 -0.7687 -0.5718 +vn 0.5853 -0.8072 -0.0757 +vn 0.5154 -0.6844 -0.5156 +vn 0.5719 -0.7685 -0.2870 +vn 0.2870 -0.5719 -0.7685 +vn 0.3064 -0.0783 -0.9486 +vn 0.0787 -0.3066 -0.9485 +vn 0.0779 -0.0779 -0.9939 +vn 0.5855 -0.0754 -0.8071 +vn 0.3098 -0.3089 -0.8992 +vn 0.8072 -0.0757 -0.5853 +vn 0.5718 -0.2866 -0.7687 +vn 0.5156 -0.5154 -0.6844 +vn 0.7685 -0.2870 -0.5719 +vn 0.9486 -0.3064 -0.0783 +vn 0.9485 -0.0787 -0.3066 +vn 0.8071 -0.5855 -0.0754 +vn 0.8992 -0.3098 -0.3089 +vn 0.7687 -0.5718 -0.2866 +vn 0.6844 -0.5156 -0.5154 +vn 0.9486 0.3064 0.0783 +vn 0.9485 0.0787 0.3066 +vn 0.9939 0.0779 0.0779 +vn 0.8071 0.5855 0.0754 +vn 0.8992 0.3098 0.3089 +vn 0.5853 0.8072 0.0757 +vn 0.7687 0.5718 0.2866 +vn 0.8072 0.0757 0.5853 +vn 0.6844 0.5156 0.5154 +vn 0.7685 0.2870 0.5719 +vn 0.5719 0.7685 0.2870 +vn 0.0783 0.9486 0.3064 +vn 0.3066 0.9485 0.0787 +vn 0.0754 0.8071 0.5855 +vn 0.3089 0.8992 0.3098 +vn 0.0757 0.5853 0.8072 +vn 0.2866 0.7687 0.5718 +vn 0.5154 0.6844 0.5156 +vn 0.2870 0.5719 0.7685 +vn 0.3064 0.0783 0.9486 +vn 0.0787 0.3066 0.9485 +vn 0.5855 0.0754 0.8071 +vn 0.3098 0.3089 0.8992 +vn 0.5718 0.2866 0.7687 +vn 0.5156 0.5154 0.6844 +vn 0.9486 -0.0783 0.3064 +vn 0.9485 -0.3066 0.0787 +vn 0.8071 -0.0754 0.5855 +vn 0.8992 -0.3089 0.3098 +vn 0.5853 -0.0757 0.8072 +vn 0.7687 -0.2866 0.5718 +vn 0.8072 -0.5853 0.0757 +vn 0.6844 -0.5154 0.5156 +vn 0.7685 -0.5719 0.2870 +vn 0.5719 -0.2870 0.7685 +vn 0.0783 -0.3064 0.9486 +vn 0.3066 -0.0787 0.9485 +vn 0.0754 -0.5855 0.8071 +vn 0.3089 -0.3098 0.8992 +vn 0.0757 -0.8072 0.5853 +vn 0.2866 -0.5718 0.7687 +vn 0.5154 -0.5156 0.6844 +vn 0.2870 -0.7685 0.5719 +vn 0.3064 -0.9486 0.0783 +vn 0.0787 -0.9485 0.3066 +vn 0.0779 -0.9939 0.0779 +vn 0.5855 -0.8071 0.0754 +vn 0.3098 -0.8992 0.3089 +vn 0.5718 -0.7687 0.2866 +vn 0.5156 -0.6844 0.5154 +vn -0.3064 0.0783 -0.9486 +vn -0.0787 0.3066 -0.9485 +vn -0.0779 0.0779 -0.9939 +vn -0.5855 0.0754 -0.8071 +vn -0.3098 0.3089 -0.8992 +vn -0.8072 0.0757 -0.5853 +vn -0.5718 0.2866 -0.7687 +vn -0.0757 0.5853 -0.8072 +vn -0.5156 0.5154 -0.6844 +vn -0.2870 0.5719 -0.7685 +vn -0.7685 0.2870 -0.5719 +vn -0.9486 0.3064 -0.0783 +vn -0.9485 0.0787 -0.3066 +vn -0.9939 0.0779 -0.0779 +vn -0.8071 0.5855 -0.0754 +vn -0.8992 0.3098 -0.3089 +vn -0.5853 0.8072 -0.0757 +vn -0.7687 0.5718 -0.2866 +vn -0.6844 0.5156 -0.5154 +vn -0.5719 0.7685 -0.2870 +vn -0.0783 0.9486 -0.3064 +vn -0.3066 0.9485 -0.0787 +vn -0.0754 0.8071 -0.5855 +vn -0.3089 0.8992 -0.3098 +vn -0.2866 0.7687 -0.5718 +vn -0.5154 0.6844 -0.5156 +vn -0.9486 -0.0783 -0.3064 +vn -0.9485 -0.3066 -0.0787 +vn -0.8071 -0.0754 -0.5855 +vn -0.8992 -0.3089 -0.3098 +vn -0.5853 -0.0757 -0.8072 +vn -0.7687 -0.2866 -0.5718 +vn -0.8072 -0.5853 -0.0757 +vn -0.6844 -0.5154 -0.5156 +vn -0.7685 -0.5719 -0.2870 +vn -0.5719 -0.2870 -0.7685 +vn -0.0783 -0.3064 -0.9486 +vn -0.3066 -0.0787 -0.9485 +vn -0.0779 -0.0779 -0.9939 +vn -0.0754 -0.5855 -0.8071 +vn -0.3089 -0.3098 -0.8992 +vn -0.0757 -0.8072 -0.5853 +vn -0.2866 -0.5718 -0.7687 +vn -0.5154 -0.5156 -0.6844 +vn -0.2870 -0.7685 -0.5719 +vn -0.3064 -0.9486 -0.0783 +vn -0.0787 -0.9485 -0.3066 +vn -0.5855 -0.8071 -0.0754 +vn -0.3098 -0.8992 -0.3089 +vn -0.5718 -0.7687 -0.2866 +vn -0.5156 -0.6844 -0.5154 +vn -0.9486 0.0783 0.3064 +vn -0.9485 0.3066 0.0787 +vn -0.8071 0.0754 0.5855 +vn -0.8992 0.3089 0.3098 +vn -0.5853 0.0757 0.8072 +vn -0.7687 0.2866 0.5718 +vn -0.8072 0.5853 0.0757 +vn -0.6844 0.5154 0.5156 +vn -0.7685 0.5719 0.2870 +vn -0.5719 0.2870 0.7685 +vn -0.0783 0.3064 0.9486 +vn -0.3066 0.0787 0.9485 +vn -0.0779 0.0779 0.9939 +vn -0.0754 0.5855 0.8071 +vn -0.3089 0.3098 0.8992 +vn -0.0757 0.8072 0.5853 +vn -0.2866 0.5718 0.7687 +vn -0.5154 0.5156 0.6844 +vn -0.2870 0.7685 0.5719 +vn -0.3064 0.9486 0.0783 +vn -0.0787 0.9485 0.3066 +vn -0.0779 0.9939 0.0779 +vn -0.5855 0.8071 0.0754 +vn -0.3098 0.8992 0.3089 +vn -0.5718 0.7687 0.2866 +vn -0.5156 0.6844 0.5154 +vn -0.0783 -0.9486 0.3064 +vn -0.3066 -0.9485 0.0787 +vn -0.0754 -0.8071 0.5855 +vn -0.3089 -0.8992 0.3098 +vn -0.0757 -0.5853 0.8072 +vn -0.2866 -0.7687 0.5718 +vn -0.5853 -0.8072 0.0757 +vn -0.5154 -0.6844 0.5156 +vn -0.5719 -0.7685 0.2870 +vn -0.2870 -0.5719 0.7685 +vn -0.3064 -0.0783 0.9486 +vn -0.0787 -0.3066 0.9485 +vn -0.5855 -0.0754 0.8071 +vn -0.3098 -0.3089 0.8992 +vn -0.8072 -0.0757 0.5853 +vn -0.5718 -0.2866 0.7687 +vn -0.5156 -0.5154 0.6844 +vn -0.7685 -0.2870 0.5719 +vn -0.9486 -0.3064 0.0783 +vn -0.9485 -0.0787 0.3066 +vn -0.8071 -0.5855 0.0754 +vn -0.8992 -0.3098 0.3089 +vn -0.7687 -0.5718 0.2866 +vn -0.6844 -0.5156 0.5154 +usemtl Material.001 +s 1 +f 28/1/1 190/2/2 138/3/3 +f 163/4/4 136/5/5 192/6/6 +f 57/7/7 191/8/8 83/9/9 +f 111/10/10 56/11/11 2/12/12 +f 3/13/13 82/14/14 30/15/15 +f 4/16/16 6/17/17 1/18/18 +f 5/19/19 7/20/20 4/16/16 +f 17/21/21 8/22/22 5/19/19 +f 7/20/20 9/23/23 6/17/17 +f 7/20/20 11/24/24 10/25/25 +f 18/26/26 11/24/24 8/22/22 +f 12/27/27 14/28/28 2/12/12 +f 13/29/29 15/30/30 12/27/27 +f 25/31/31 16/32/32 13/29/29 +f 15/30/30 17/33/21 14/28/28 +f 15/30/30 19/34/33 18/35/26 +f 26/36/34 19/34/33 16/32/32 +f 20/37/35 22/38/36 3/13/13 +f 21/39/37 23/40/38 20/37/35 +f 9/23/23 24/41/39 21/39/37 +f 23/40/38 25/31/31 22/38/36 +f 23/40/38 27/42/40 26/36/34 +f 10/25/25 27/42/40 24/41/39 +f 11/24/24 19/43/33 27/44/40 +f 31/45/41 33/46/42 28/1/1 +f 32/47/43 34/48/44 31/45/41 +f 44/49/45 35/50/46 32/47/43 +f 34/48/44 36/51/47 33/46/42 +f 34/48/44 38/52/48 37/53/49 +f 45/54/50 38/52/48 35/50/46 +f 39/55/51 41/56/52 29/57/53 +f 40/58/54 42/59/55 39/55/51 +f 52/60/56 43/61/57 40/58/54 +f 42/59/55 44/62/45 41/56/52 +f 42/59/55 46/63/58 45/64/50 +f 53/65/59 46/63/58 43/61/57 +f 47/66/60 49/67/61 30/15/15 +f 48/68/62 50/69/63 47/66/60 +f 36/51/47 51/70/64 48/68/62 +f 50/69/63 52/60/56 49/67/61 +f 50/69/63 54/71/65 53/65/59 +f 37/53/49 54/71/65 51/70/64 +f 38/52/48 46/72/58 54/73/65 +f 58/74/66 60/75/67 55/76/68 +f 59/77/69 61/78/70 58/74/66 +f 71/79/71 62/80/72 59/77/69 +f 61/78/70 63/81/73 60/75/67 +f 61/78/70 65/82/74 64/83/75 +f 72/84/76 65/82/74 62/80/72 +f 66/85/77 68/86/78 56/11/11 +f 67/87/79 69/88/80 66/85/77 +f 79/89/81 70/90/82 67/87/79 +f 69/88/80 71/79/71 68/86/78 +f 69/88/80 73/91/83 72/84/76 +f 80/92/84 73/91/83 70/90/82 +f 74/93/85 76/94/86 57/7/7 +f 75/95/87 77/96/88 74/93/85 +f 63/81/73 78/97/89 75/95/87 +f 77/96/88 79/98/81 76/94/86 +f 77/96/88 81/99/90 80/100/84 +f 64/83/75 81/99/90 78/97/89 +f 65/82/74 73/101/83 81/102/90 +f 85/103/91 87/104/92 82/14/14 +f 86/105/93 88/106/94 85/103/91 +f 98/107/95 89/108/96 86/105/93 +f 88/106/94 90/109/97 87/104/92 +f 88/106/94 92/110/98 91/111/99 +f 99/112/100 92/110/98 89/108/96 +f 93/113/101 95/114/102 83/9/9 +f 94/115/103 96/116/104 93/113/101 +f 106/117/105 97/118/106 94/115/103 +f 96/116/104 98/107/95 95/114/102 +f 96/116/104 100/119/107 99/112/100 +f 107/120/108 100/119/107 97/118/106 +f 101/121/109 103/122/110 84/123/111 +f 102/124/112 104/125/113 101/121/109 +f 90/109/97 105/126/114 102/124/112 +f 104/125/113 106/127/105 103/122/110 +f 104/125/113 108/128/115 107/129/108 +f 91/111/99 108/128/115 105/126/114 +f 92/110/98 100/130/107 108/131/115 +f 112/132/116 114/133/117 109/134/118 +f 113/135/119 115/136/120 112/132/116 +f 125/137/121 116/138/122 113/135/119 +f 115/136/120 117/139/123 114/133/117 +f 115/136/120 119/140/124 118/141/125 +f 126/142/126 119/140/124 116/138/122 +f 120/143/127 122/144/128 110/145/129 +f 121/146/130 123/147/131 120/143/127 +f 133/148/132 124/149/133 121/146/130 +f 123/147/131 125/137/121 122/144/128 +f 123/147/131 127/150/134 126/142/126 +f 134/151/135 127/150/134 124/149/133 +f 128/152/136 130/153/137 111/10/10 +f 129/154/138 131/155/139 128/152/136 +f 117/156/123 132/157/140 129/154/138 +f 131/155/139 133/158/132 130/153/137 +f 131/155/139 135/159/141 134/160/135 +f 118/161/125 135/159/141 132/157/140 +f 119/140/124 127/162/134 135/163/141 +f 139/164/142 141/165/143 136/5/5 +f 140/166/144 142/167/145 139/164/142 +f 152/168/146 143/169/147 140/166/144 +f 142/167/145 144/170/148 141/165/143 +f 142/167/145 146/171/149 145/172/150 +f 153/173/151 146/171/149 143/169/147 +f 147/174/152 149/175/153 137/176/154 +f 148/177/155 150/178/156 147/174/152 +f 160/179/157 151/180/158 148/177/155 +f 150/178/156 152/168/146 149/175/153 +f 150/178/156 154/181/159 153/173/151 +f 161/182/160 154/181/159 151/180/158 +f 155/183/161 157/184/162 138/3/3 +f 156/185/163 158/186/164 155/183/161 +f 144/187/148 159/188/165 156/185/163 +f 158/186/164 160/189/157 157/184/162 +f 158/186/164 162/190/166 161/191/160 +f 145/192/150 162/190/166 159/188/165 +f 146/171/149 154/193/159 162/194/166 +f 166/195/167 168/196/168 163/4/4 +f 167/197/169 169/198/170 166/195/167 +f 179/199/171 170/200/172 167/197/169 +f 169/198/170 171/201/173 168/196/168 +f 169/198/170 173/202/174 172/203/175 +f 180/204/176 173/202/174 170/200/172 +f 174/205/177 176/206/178 164/207/179 +f 175/208/180 177/209/181 174/205/177 +f 187/210/182 178/211/183 175/208/180 +f 177/209/181 179/212/171 176/206/178 +f 177/209/181 181/213/184 180/214/176 +f 188/215/185 181/213/184 178/211/183 +f 182/216/186 184/217/187 165/218/188 +f 183/219/189 185/220/190 182/216/186 +f 171/221/173 186/222/191 183/219/189 +f 185/220/190 187/223/182 184/217/187 +f 185/220/190 189/224/192 188/225/185 +f 172/226/175 189/224/192 186/222/191 +f 173/202/174 181/227/184 189/228/192 +f 193/229/193 195/230/194 190/2/2 +f 194/231/195 196/232/196 193/229/193 +f 206/233/197 197/234/198 194/231/195 +f 196/232/196 198/235/199 195/230/194 +f 196/232/196 200/236/200 199/237/201 +f 207/238/202 200/236/200 197/234/198 +f 201/239/203 203/240/204 191/8/8 +f 202/241/205 204/242/206 201/239/203 +f 214/243/207 205/244/208 202/241/205 +f 204/242/206 206/245/197 203/240/204 +f 204/242/206 208/246/209 207/247/202 +f 215/248/210 208/246/209 205/244/208 +f 209/249/211 211/250/212 192/6/6 +f 210/251/213 212/252/214 209/249/211 +f 198/253/199 213/254/215 210/251/213 +f 212/252/214 214/255/207 211/250/212 +f 212/252/214 216/256/216 215/257/210 +f 199/258/201 216/256/216 213/254/215 +f 200/236/200 208/259/209 216/260/216 +f 190/2/2 155/183/161 138/3/3 +f 195/230/194 156/185/163 155/183/161 +f 198/235/199 144/187/148 156/185/163 +f 210/251/213 141/165/143 144/170/148 +f 209/249/211 136/5/5 141/165/143 +f 138/3/3 31/45/41 28/1/1 +f 157/184/162 32/47/43 31/45/41 +f 160/189/157 44/49/45 32/47/43 +f 148/177/155 41/56/52 44/62/45 +f 147/174/152 29/57/53 41/56/52 +f 30/15/15 20/37/35 3/13/13 +f 49/67/61 21/39/37 20/37/35 +f 52/60/56 9/23/23 21/39/37 +f 40/58/54 6/17/17 9/23/23 +f 39/55/51 1/18/18 6/17/17 +f 164/207/179 201/239/203 191/8/8 +f 176/206/178 202/241/205 201/239/203 +f 179/212/171 214/243/207 202/241/205 +f 167/197/169 211/250/212 214/255/207 +f 166/195/167 192/6/6 211/250/212 +f 83/9/9 74/93/85 57/7/7 +f 95/114/102 75/95/87 74/93/85 +f 98/107/95 63/81/73 75/95/87 +f 86/105/93 60/75/67 63/81/73 +f 85/103/91 55/76/68 60/75/67 +f 137/176/154 112/132/116 109/134/118 +f 149/175/153 113/135/119 112/132/116 +f 152/168/146 125/137/121 113/135/119 +f 140/166/144 122/144/128 125/137/121 +f 139/164/142 110/145/129 122/144/128 +f 165/218/188 66/85/77 56/11/11 +f 184/217/187 67/87/79 66/85/77 +f 187/223/182 79/89/81 67/87/79 +f 175/208/180 76/94/86 79/98/81 +f 174/205/177 57/7/7 76/94/86 +f 56/11/11 12/27/27 2/12/12 +f 68/86/78 13/29/29 12/27/27 +f 71/79/71 25/31/31 13/29/29 +f 59/77/69 22/38/36 25/31/31 +f 58/74/66 3/13/13 22/38/36 +f 84/123/111 193/229/193 190/2/2 +f 103/122/110 194/231/195 193/229/193 +f 106/127/105 206/233/197 194/231/195 +f 94/115/103 203/240/204 206/245/197 +f 93/113/101 191/8/8 203/240/204 +f 111/10/10 182/216/186 165/218/188 +f 130/153/137 183/219/189 182/216/186 +f 133/158/132 171/221/173 183/219/189 +f 121/146/130 168/196/168 171/201/173 +f 120/143/127 163/4/4 168/196/168 +f 2/12/12 128/152/136 111/10/10 +f 14/28/28 129/154/138 128/152/136 +f 17/33/21 117/156/123 129/154/138 +f 5/19/19 114/133/117 117/139/123 +f 4/16/16 109/134/118 114/133/117 +f 28/1/1 101/121/109 84/123/111 +f 33/46/42 102/124/112 101/121/109 +f 36/51/47 90/109/97 102/124/112 +f 48/68/62 87/104/92 90/109/97 +f 47/66/60 82/14/14 87/104/92 +f 109/134/118 29/57/53 137/176/154 +f 28/1/1 84/123/111 190/2/2 +f 163/4/4 110/145/129 136/5/5 +f 57/7/7 164/207/179 191/8/8 +f 111/10/10 165/218/188 56/11/11 +f 3/13/13 55/76/68 82/14/14 +f 4/16/16 7/20/20 6/17/17 +f 5/19/19 8/22/22 7/20/20 +f 17/21/21 18/26/26 8/22/22 +f 7/20/20 10/25/25 9/23/23 +f 7/20/20 8/22/22 11/24/24 +f 18/26/26 19/43/33 11/24/24 +f 12/27/27 15/30/30 14/28/28 +f 13/29/29 16/32/32 15/30/30 +f 25/31/31 26/36/34 16/32/32 +f 15/30/30 18/35/26 17/33/21 +f 15/30/30 16/32/32 19/34/33 +f 26/36/34 27/42/40 19/34/33 +f 20/37/35 23/40/38 22/38/36 +f 21/39/37 24/41/39 23/40/38 +f 9/23/23 10/25/25 24/41/39 +f 23/40/38 26/36/34 25/31/31 +f 23/40/38 24/41/39 27/42/40 +f 10/25/25 11/24/24 27/42/40 +f 31/45/41 34/48/44 33/46/42 +f 32/47/43 35/50/46 34/48/44 +f 44/49/45 45/54/50 35/50/46 +f 34/48/44 37/53/49 36/51/47 +f 34/48/44 35/50/46 38/52/48 +f 45/54/50 46/72/58 38/52/48 +f 39/55/51 42/59/55 41/56/52 +f 40/58/54 43/61/57 42/59/55 +f 52/60/56 53/65/59 43/61/57 +f 42/59/55 45/64/50 44/62/45 +f 42/59/55 43/61/57 46/63/58 +f 53/65/59 54/71/65 46/63/58 +f 47/66/60 50/69/63 49/67/61 +f 48/68/62 51/70/64 50/69/63 +f 36/51/47 37/53/49 51/70/64 +f 50/69/63 53/65/59 52/60/56 +f 50/69/63 51/70/64 54/71/65 +f 37/53/49 38/52/48 54/71/65 +f 58/74/66 61/78/70 60/75/67 +f 59/77/69 62/80/72 61/78/70 +f 71/79/71 72/84/76 62/80/72 +f 61/78/70 64/83/75 63/81/73 +f 61/78/70 62/80/72 65/82/74 +f 72/84/76 73/91/83 65/82/74 +f 66/85/77 69/88/80 68/86/78 +f 67/87/79 70/90/82 69/88/80 +f 79/89/81 80/92/84 70/90/82 +f 69/88/80 72/84/76 71/79/71 +f 69/88/80 70/90/82 73/91/83 +f 80/92/84 81/261/90 73/91/83 +f 74/93/85 77/96/88 76/94/86 +f 75/95/87 78/97/89 77/96/88 +f 63/81/73 64/83/75 78/97/89 +f 77/96/88 80/100/84 79/98/81 +f 77/96/88 78/97/89 81/99/90 +f 64/83/75 65/82/74 81/99/90 +f 85/103/91 88/106/94 87/104/92 +f 86/105/93 89/108/96 88/106/94 +f 98/107/95 99/112/100 89/108/96 +f 88/106/94 91/111/99 90/109/97 +f 88/106/94 89/108/96 92/110/98 +f 99/112/100 100/119/107 92/110/98 +f 93/113/101 96/116/104 95/114/102 +f 94/115/103 97/118/106 96/116/104 +f 106/117/105 107/120/108 97/118/106 +f 96/116/104 99/112/100 98/107/95 +f 96/116/104 97/118/106 100/119/107 +f 107/120/108 108/262/115 100/119/107 +f 101/121/109 104/125/113 103/122/110 +f 102/124/112 105/126/114 104/125/113 +f 90/109/97 91/111/99 105/126/114 +f 104/125/113 107/129/108 106/127/105 +f 104/125/113 105/126/114 108/128/115 +f 91/111/99 92/110/98 108/128/115 +f 112/132/116 115/136/120 114/133/117 +f 113/135/119 116/138/122 115/136/120 +f 125/137/121 126/142/126 116/138/122 +f 115/136/120 118/141/125 117/139/123 +f 115/136/120 116/138/122 119/140/124 +f 126/142/126 127/150/134 119/140/124 +f 120/143/127 123/147/131 122/144/128 +f 121/146/130 124/149/133 123/147/131 +f 133/148/132 134/151/135 124/149/133 +f 123/147/131 126/142/126 125/137/121 +f 123/147/131 124/149/133 127/150/134 +f 134/151/135 135/263/141 127/150/134 +f 128/152/136 131/155/139 130/153/137 +f 129/154/138 132/157/140 131/155/139 +f 117/156/123 118/161/125 132/157/140 +f 131/155/139 134/160/135 133/158/132 +f 131/155/139 132/157/140 135/159/141 +f 118/161/125 119/264/124 135/159/141 +f 139/164/142 142/167/145 141/165/143 +f 140/166/144 143/169/147 142/167/145 +f 152/168/146 153/173/151 143/169/147 +f 142/167/145 145/172/150 144/170/148 +f 142/167/145 143/169/147 146/171/149 +f 153/173/151 154/181/159 146/171/149 +f 147/174/152 150/178/156 149/175/153 +f 148/177/155 151/180/158 150/178/156 +f 160/179/157 161/182/160 151/180/158 +f 150/178/156 153/173/151 152/168/146 +f 150/178/156 151/180/158 154/181/159 +f 161/182/160 162/265/166 154/181/159 +f 155/183/161 158/186/164 157/184/162 +f 156/185/163 159/188/165 158/186/164 +f 144/187/148 145/192/150 159/188/165 +f 158/186/164 161/191/160 160/189/157 +f 158/186/164 159/188/165 162/190/166 +f 145/192/150 146/266/149 162/190/166 +f 166/195/167 169/198/170 168/196/168 +f 167/197/169 170/200/172 169/198/170 +f 179/199/171 180/204/176 170/200/172 +f 169/198/170 172/203/175 171/201/173 +f 169/198/170 170/200/172 173/202/174 +f 180/204/176 181/227/184 173/202/174 +f 174/205/177 177/209/181 176/206/178 +f 175/208/180 178/211/183 177/209/181 +f 187/210/182 188/215/185 178/211/183 +f 177/209/181 180/214/176 179/212/171 +f 177/209/181 178/211/183 181/213/184 +f 188/215/185 189/267/192 181/213/184 +f 182/216/186 185/220/190 184/217/187 +f 183/219/189 186/222/191 185/220/190 +f 171/221/173 172/226/175 186/222/191 +f 185/220/190 188/225/185 187/223/182 +f 185/220/190 186/222/191 189/224/192 +f 172/226/175 173/268/174 189/224/192 +f 193/229/193 196/232/196 195/230/194 +f 194/231/195 197/234/198 196/232/196 +f 206/233/197 207/238/202 197/234/198 +f 196/232/196 199/237/201 198/235/199 +f 196/232/196 197/234/198 200/236/200 +f 207/238/202 208/259/209 200/236/200 +f 201/239/203 204/242/206 203/240/204 +f 202/241/205 205/244/208 204/242/206 +f 214/243/207 215/248/210 205/244/208 +f 204/242/206 207/247/202 206/245/197 +f 204/242/206 205/244/208 208/246/209 +f 215/248/210 216/269/216 208/246/209 +f 209/249/211 212/252/214 211/250/212 +f 210/251/213 213/254/215 212/252/214 +f 198/253/199 199/258/201 213/254/215 +f 212/252/214 215/257/210 214/255/207 +f 212/252/214 213/254/215 216/256/216 +f 199/258/201 200/270/200 216/256/216 +f 190/2/2 195/230/194 155/183/161 +f 195/230/194 198/235/199 156/185/163 +f 198/235/199 210/271/213 144/187/148 +f 210/251/213 209/249/211 141/165/143 +f 209/249/211 192/6/6 136/5/5 +f 138/3/3 157/184/162 31/45/41 +f 157/184/162 160/189/157 32/47/43 +f 160/189/157 148/272/155 44/49/45 +f 148/177/155 147/174/152 41/56/52 +f 147/174/152 137/176/154 29/57/53 +f 30/15/15 49/67/61 20/37/35 +f 49/67/61 52/60/56 21/39/37 +f 52/60/56 40/58/54 9/23/23 +f 40/58/54 39/55/51 6/17/17 +f 39/55/51 29/57/53 1/18/18 +f 164/207/179 176/206/178 201/239/203 +f 176/206/178 179/212/171 202/241/205 +f 179/212/171 167/273/169 214/243/207 +f 167/197/169 166/195/167 211/250/212 +f 166/195/167 163/4/4 192/6/6 +f 83/9/9 95/114/102 74/93/85 +f 95/114/102 98/107/95 75/95/87 +f 98/107/95 86/105/93 63/81/73 +f 86/105/93 85/103/91 60/75/67 +f 85/103/91 82/14/14 55/76/68 +f 137/176/154 149/175/153 112/132/116 +f 149/175/153 152/168/146 113/135/119 +f 152/168/146 140/166/144 125/137/121 +f 140/166/144 139/164/142 122/144/128 +f 139/164/142 136/5/5 110/145/129 +f 165/218/188 184/217/187 66/85/77 +f 184/217/187 187/223/182 67/87/79 +f 187/223/182 175/274/180 79/89/81 +f 175/208/180 174/205/177 76/94/86 +f 174/205/177 164/207/179 57/7/7 +f 56/11/11 68/86/78 12/27/27 +f 68/86/78 71/79/71 13/29/29 +f 71/79/71 59/77/69 25/31/31 +f 59/77/69 58/74/66 22/38/36 +f 58/74/66 55/76/68 3/13/13 +f 84/123/111 103/122/110 193/229/193 +f 103/122/110 106/127/105 194/231/195 +f 106/127/105 94/275/103 206/233/197 +f 94/115/103 93/113/101 203/240/204 +f 93/113/101 83/9/9 191/8/8 +f 111/10/10 130/153/137 182/216/186 +f 130/153/137 133/158/132 183/219/189 +f 133/158/132 121/276/130 171/221/173 +f 121/146/130 120/143/127 168/196/168 +f 120/143/127 110/145/129 163/4/4 +f 2/12/12 14/28/28 128/152/136 +f 14/28/28 17/33/21 129/154/138 +f 17/33/21 5/277/19 117/156/123 +f 5/19/19 4/16/16 114/133/117 +f 4/16/16 1/18/18 109/134/118 +f 28/1/1 33/46/42 101/121/109 +f 33/46/42 36/51/47 102/124/112 +f 36/51/47 48/68/62 90/109/97 +f 48/68/62 47/66/60 87/104/92 +f 47/66/60 30/15/15 82/14/14 +f 109/134/118 1/18/18 29/57/53 diff --git a/res/shaders/simple.frag b/res/shaders/simple.frag new file mode 100644 index 0000000..67831a9 --- /dev/null +++ b/res/shaders/simple.frag @@ -0,0 +1,12 @@ +#version 450 + +layout (location = 0) in vec2 tex_coords; + +layout (location = 0) out vec4 f_color; + +layout(set = 1, binding = 0) uniform sampler mySampler; +layout(set = 1, binding = 1) uniform texture2D myTexture; + +void main() { + f_color = texture(sampler2D(myTexture, mySampler), tex_coords); +} diff --git a/res/shaders/simple.vert b/res/shaders/simple.vert new file mode 100644 index 0000000..8c1df7c --- /dev/null +++ b/res/shaders/simple.vert @@ -0,0 +1,20 @@ +#version 450 + +layout (location = 0) in vec3 position; +layout (location = 1) in vec2 uv; +layout (location = 2) in mat4 model; + +layout (location = 0) out vec2 fragUv; + +layout (set = 0, binding = 0) uniform MVP { + mat4 world; + mat4 view; + mat4 projection; +} uniforms; + +void main() { + mat4 worldview = uniforms.view * uniforms.world; + vec4 modelPosition = model * vec4(position, 1.0); + gl_Position = uniforms.projection * worldview * modelPosition; + fragUv = uv; +} diff --git a/res/shaders/vertex.frag b/res/shaders/vertex.frag deleted file mode 100644 index 720d192..0000000 --- a/res/shaders/vertex.frag +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 - -layout (location = 0) in vec3 color; - -layout (location = 0) out vec4 f_color; - -void main() { - f_color = vec4(color, 1.0); -} \ No newline at end of file diff --git a/res/shaders/vertex.vert b/res/shaders/vertex.vert deleted file mode 100644 index 65b0acf..0000000 --- a/res/shaders/vertex.vert +++ /dev/null @@ -1 +0,0 @@ -#version 450 layout (location = 0) in vec2 position; layout (location = 1) in vec3 color; layout (location = 0) out vec3 fragColor; layout (set = 0, binding = 0) uniform MVPData { mat4 world; mat4 view; mat4 projection; } uniforms; void main() { mat4 worldview = uniforms.view * uniforms.world; gl_Position = uniforms.projection * worldview * vec4(position, 0.0, 1.0); fragColor = color; } \ No newline at end of file diff --git a/res/textures/wooden-crate.jpg b/res/textures/wooden-crate.jpg new file mode 100644 index 0000000..d1c8734 Binary files /dev/null and b/res/textures/wooden-crate.jpg differ diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 00822fd..b8889a3 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.85.1" +channel = "1.87.0" diff --git a/src/core/app/context.rs b/src/core/app/context.rs new file mode 100644 index 0000000..00e8256 --- /dev/null +++ b/src/core/app/context.rs @@ -0,0 +1,135 @@ +use std::{ + cell::RefCell, + rc::Rc, + sync::{Arc, RwLock}, +}; + +use egui_winit_vulkano::Gui; +use vulkano_util::{renderer::VulkanoWindowRenderer, window::VulkanoWindows}; +use winit::{event_loop::EventLoopProxy, monitor::MonitorHandle, window::WindowId}; + +use crate::core::{input::InputManager, render::vulkan_context::VulkanContext}; + +use super::user_event::UserEvent; + +/// Contexte d'application unifié pour les fonctions liées à la fenêtre +pub struct WindowContext { + // Données Vulkan (immutables) + pub vulkan_context: Arc, + pub event_loop_proxy: EventLoopProxy, + pub window_id: WindowId, + + // Données mutables partagées avec Arc> + pub vulkano_windows: Rc>, + pub input_manager: Arc>, + pub gui: Rc>, +} + +impl WindowContext { + pub fn new( + vulkan_context: Arc, + vulkano_windows: Rc>, + input_manager: Arc>, + gui: Rc>, + event_loop_proxy: EventLoopProxy, + window_id: WindowId, + ) -> Self { + Self { + // Données Vulkan + vulkan_context, + event_loop_proxy, + window_id, + + // Données mutables partagées + vulkano_windows, + input_manager, + gui, + } + } + + pub fn vulkan_context(&self) -> &VulkanContext { + &self.vulkan_context + } + + /// Extrait les résolutions d'un moniteur donné + fn extract_resolutions_from_monitor(monitor: MonitorHandle) -> Vec<(u32, u32)> { + let video_modes: Vec<_> = monitor.video_modes().collect(); + + let resolutions: Vec<(u32, u32)> = video_modes + .into_iter() + .map(|mode| { + let size = mode.size(); + (size.width, size.height) + }) + .collect(); + + tracing::trace!( + "Modes vidéo trouvés pour {:?}: {:?}", + monitor.name(), + resolutions + ); + resolutions + } + + /// Récupère les résolutions disponibles + pub fn get_available_resolutions(&self) -> Vec<(u32, u32)> { + self.with_renderer(|renderer| { + renderer + .window() + .current_monitor() + .map(Self::extract_resolutions_from_monitor) + .unwrap_or_default() + }) + } + + /// Récupère la taille de la fenêtre depuis le renderer + pub fn get_window_size(&self) -> [f32; 2] { + self.with_renderer(|renderer| renderer.window_size()) + } + + /// Récupère l'aspect ratio depuis le renderer + pub fn get_aspect_ratio(&self) -> f32 { + self.with_renderer(|renderer| renderer.aspect_ratio()) + } + + pub fn with_renderer(&self, f: F) -> T + where + F: FnOnce(&VulkanoWindowRenderer) -> T, + { + let vulkano_windows = self.vulkano_windows.borrow(); + let renderer = vulkano_windows + .get_renderer(self.window_id) + .expect("Failed to get renderer"); + f(renderer) + } + + /// Méthode utilitaire pour accéder au renderer de manière thread-safe + pub fn with_renderer_mut(&mut self, f: F) -> T + where + F: FnOnce(&mut VulkanoWindowRenderer) -> T, + { + let mut vulkano_windows = self.vulkano_windows.borrow_mut(); + let renderer = vulkano_windows + .get_renderer_mut(self.window_id) + .expect("Failed to get renderer"); + f(renderer) + } + + /// Méthode utilitaire pour accéder au gui de manière thread-safe + pub fn with_gui(&self, f: F) -> T + where + F: FnOnce(&Gui) -> T, + { + let gui = self.gui.borrow(); + f(&gui) + } + + /// Méthode utilitaire pour accéder au gui de manière thread-safe + pub fn with_gui_mut(&mut self, f: F) -> T + where + F: FnOnce(&mut Gui) -> T, + { + let mut gui = self.gui.borrow_mut(); + f(&mut gui) + } +} diff --git a/src/core/app/mod.rs b/src/core/app/mod.rs new file mode 100644 index 0000000..2d3ecde --- /dev/null +++ b/src/core/app/mod.rs @@ -0,0 +1,253 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; +use std::sync::{Arc, RwLock}; + +use super::render::vulkan_context::VulkanContext; +use crate::core::input::InputManager; +use crate::core::scene::manager::SceneManager; +use crate::game::scenes::main_scene::MainScene; +use egui_winit_vulkano::{Gui, GuiConfig}; +use user_event::UserEvent; +use vulkano::format::Format; +use vulkano::image::ImageUsage; +use vulkano::swapchain::PresentMode; +use vulkano_util::context::VulkanoContext; +use vulkano_util::window::{VulkanoWindows, WindowDescriptor}; +use winit::application::ApplicationHandler; +use winit::event::WindowEvent; +use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::window::WindowId; + +use self::context::WindowContext; + +pub mod context; +pub mod user_event; + +pub const DEPTH_IMAGE_ID: usize = 0; + +pub struct App { + vulkan_context: Arc, + vulkano_windows: Rc>, + gui: HashMap>>, + scene_manager: HashMap, + input_manager: Arc>, + event_loop_proxy: EventLoopProxy, + + // Context d'application partagé par fenêtre - architecture unifiée + app_contexts: HashMap>>, +} + +impl App { + pub fn new( + vulkano_context: VulkanoContext, + input_manager: InputManager, + event_loop_proxy: EventLoopProxy, + ) -> Self { + Self { + vulkan_context: Arc::new(VulkanContext::new(vulkano_context)), + vulkano_windows: Rc::new(RefCell::new(VulkanoWindows::default())), + gui: HashMap::new(), + input_manager: Arc::new(RwLock::new(input_manager)), + scene_manager: HashMap::new(), + event_loop_proxy, + app_contexts: HashMap::new(), + } + } +} + +impl ApplicationHandler for App { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + let mut vulkano_windows = self.vulkano_windows.borrow_mut(); + let window_id = vulkano_windows.create_window( + event_loop, + self.vulkan_context.vulkano_context(), + &WindowDescriptor { + title: "Rust ASH Test".to_string(), + width: 800.0, + height: 600.0, + present_mode: PresentMode::Fifo, + cursor_visible: false, + cursor_locked: true, + ..Default::default() + }, + |_| {}, + ); + + let renderer = vulkano_windows.get_renderer_mut(window_id).unwrap(); + renderer.add_additional_image_view( + DEPTH_IMAGE_ID, + Format::D16_UNORM, + ImageUsage::DEPTH_STENCIL_ATTACHMENT, + ); + + let gui = { + Gui::new( + event_loop, + renderer.surface(), + renderer.graphics_queue(), + renderer.swapchain_format(), + GuiConfig { + is_overlay: true, + allow_srgb_render_target: true, + ..Default::default() + }, + ) + }; + self.gui.insert(window_id, Rc::new(RefCell::new(gui))); + + // Create the WindowContext with simplified arguments + let app_context = Rc::new(RefCell::new(WindowContext::new( + self.vulkan_context.clone(), + self.vulkano_windows.clone(), + self.input_manager.clone(), + self.gui.get(&window_id).unwrap().clone(), + self.event_loop_proxy.clone(), + window_id, + ))); + self.app_contexts.insert(window_id, app_context.clone()); + + // Now use the created context to load the scene + let mut scene_manager = SceneManager::new(); + scene_manager.set_new_scene(Box::new(MainScene::default())); + + self.scene_manager.insert(window_id, scene_manager); + } + + fn device_event( + &mut self, + _event_loop: &ActiveEventLoop, + _device_id: winit::event::DeviceId, + event: winit::event::DeviceEvent, + ) { + let mut input_manager = self.input_manager.write().unwrap(); + input_manager.process_device_event(&event); + } + + fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { + { + let gui = self.gui.get_mut(&id).unwrap(); + let mut gui = gui.borrow_mut(); + if !gui.update(&event) { + let mut input_manager = self.input_manager.write().unwrap(); + input_manager.process_window_event(&event); + } + } + + match event { + WindowEvent::CloseRequested => { + tracing::debug!("The close button was pressed; stopping"); + event_loop.exit(); + } + WindowEvent::Resized(_) | WindowEvent::ScaleFactorChanged { .. } => { + let mut vulkano_windows = self.vulkano_windows.borrow_mut(); + vulkano_windows.get_renderer_mut(id).unwrap().resize(); + } + WindowEvent::RedrawRequested => { + let _frame_span = tracing::info_span!("frame").entered(); + + { + let _input_span = tracing::debug_span!("input_update").entered(); + let mut input_manager = self + .input_manager + .write() + .expect("Failed to lock input manager"); + input_manager.update(); + } + + // Créer ou mettre à jour le contexte d'application + let window_context = self.app_contexts.get(&id).unwrap().clone(); + let scene_manager = self.scene_manager.get_mut(&id).unwrap(); + + // Utiliser le contexte partagé pour les scènes + { + let mut context = window_context.borrow_mut(); + + { + let _scene_span = + tracing::info_span!("scene_loading_if_not_loaded").entered(); + scene_manager + .load_scene_if_not_loaded(&mut context) + .unwrap(); + } + + if let Some(scene) = scene_manager.current_scene_mut() { + { + let _update_span = tracing::debug_span!("scene_update").entered(); + scene.update(&context).unwrap(); + } + + let acquire_future = { + let _acquire_span = tracing::debug_span!("acquire_swapchain").entered(); + context.with_renderer_mut(|renderer| { + renderer.acquire(None, |_| {}).unwrap() + }) + }; + + let acquire_future = { + let _render_span = tracing::debug_span!("scene_render").entered(); + scene.render(acquire_future, &mut context).unwrap() + }; + + { + let _present_span = tracing::debug_span!("present_frame").entered(); + context.with_renderer_mut(|renderer| { + renderer.present(acquire_future, true); + }); + } + } else { + tracing::warn!("No current scene found for update!"); + } + } + + { + let _gui_span = tracing::debug_span!("request_redraw").entered(); + let mut window_context = window_context.borrow_mut(); + window_context.with_renderer_mut(|renderer| { + renderer.window().request_redraw(); + }); + } + } + _ => {} + } + } + + fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) { + match event { + UserEvent::CursorGrabMode(window_id, grab) => { + let vulkano_windows = self.vulkano_windows.borrow(); + let window = vulkano_windows.get_window(window_id).unwrap(); + if let Err(e) = window.set_cursor_grab(grab) { + tracing::error!("Failed to set cursor grab: {}", e); + } + } + UserEvent::CursorVisible(window_id, visible) => { + let vulkano_windows = self.vulkano_windows.borrow(); + let window = vulkano_windows.get_window(window_id).unwrap(); + window.set_cursor_visible(visible); + } + UserEvent::ChangeScene(window_id, scene) => { + if let Some(scene_manager) = self.scene_manager.get_mut(&window_id) { + scene_manager.set_new_scene(scene); + } + } + UserEvent::ChangeResolution(window_id, width, height) => { + let mut vulkano_windows = self.vulkano_windows.borrow_mut(); + let window = vulkano_windows.get_window(window_id).unwrap(); + let _ = window.request_inner_size(winit::dpi::LogicalSize::new(width, height)); + let renderer = vulkano_windows.get_renderer_mut(window_id).unwrap(); + renderer.resize(); + tracing::trace!( + "Resolution changed to {}x{} for window {:?}", + width, + height, + window_id + ); + } + UserEvent::Exit(window_id) => { + tracing::trace!("Exit requested for window {:?}", window_id); + event_loop.exit(); + } + } + } +} diff --git a/src/core/app/user_event.rs b/src/core/app/user_event.rs new file mode 100644 index 0000000..498aac0 --- /dev/null +++ b/src/core/app/user_event.rs @@ -0,0 +1,11 @@ +use winit::window::{CursorGrabMode, WindowId}; + +use crate::core::scene::AsScene; + +pub enum UserEvent { + CursorGrabMode(WindowId, CursorGrabMode), + CursorVisible(WindowId, bool), + ChangeScene(WindowId, Box), + ChangeResolution(WindowId, f32, f32), + Exit(WindowId), +} diff --git a/src/core/input/cache.rs b/src/core/input/cache.rs new file mode 100644 index 0000000..b9d562c --- /dev/null +++ b/src/core/input/cache.rs @@ -0,0 +1,86 @@ +use std::{ + collections::HashMap, + hash::Hash, + ops::{Add, AddAssign, Sub}, +}; + +use winit::event::ElementState; + +pub struct CachedElementState { + cache: HashMap, +} + +impl Default for CachedElementState { + fn default() -> Self { + Self { + cache: HashMap::new(), + } + } +} + +impl CachedElementState { + pub fn set_key_state(&mut self, key: K, state: ElementState) -> Option { + let key_state = self.cache.get(&key); + let new_key_state = match key_state { + Some(old) => match state { + ElementState::Pressed => match old { + ElementState::Released => Some(ElementState::Pressed), + ElementState::Pressed => None, + }, + ElementState::Released => match old { + ElementState::Released => None, + ElementState::Pressed => Some(ElementState::Released), + }, + }, + None => match state { + ElementState::Pressed => Some(ElementState::Pressed), + ElementState::Released => Some(ElementState::Released), + }, + }; + if let Some(new_key_state) = new_key_state { + self.cache.insert(key, new_key_state); + } + new_key_state + } +} + +#[derive(Default)] +pub struct CachedMovement +where + T: Sub + Add + Default + Copy, +{ + pub old_value: Option, + pub value: T, +} + +impl CachedMovement +where + T: Sub + Add + Default + Copy, +{ + pub fn set_value(&mut self, value: T) { + self.value = value; + } + + pub fn reset(&mut self) -> T { + match self.old_value.as_ref() { + Some(old_value) => { + let diff = self.value - *old_value; + self.old_value = Some(self.value); + diff + } + None => { + self.old_value = Some(self.value); + T::default() + } + } + } +} + +impl AddAssign for CachedMovement +where + T: Add + Sub + Default + Copy, +{ + fn add_assign(&mut self, rhs: T) { + self.value = self.value + rhs; + } +} diff --git a/src/core/input/mod.rs b/src/core/input/mod.rs new file mode 100644 index 0000000..aa3c85f --- /dev/null +++ b/src/core/input/mod.rs @@ -0,0 +1,104 @@ +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; + +use bevy_ecs::resource::Resource; +use cache::{CachedElementState, CachedMovement}; +use virtual_input::VirtualInput; +use winit::{ + event::{DeviceEvent, MouseButton, MouseScrollDelta, WindowEvent}, + keyboard::PhysicalKey, +}; + +mod cache; +mod virtual_binding; +mod virtual_input; +mod virtual_state; +pub use virtual_binding::{AxisDirection, VirtualBinding}; + +#[derive(Default)] +pub struct InputManager { + keys_state: CachedElementState, + mouse_buttons_state: CachedElementState, + mouse_position_delta: CachedMovement, + mouse_wheel_delta: CachedMovement, + virtual_input: VirtualInput, +} + +#[derive(Resource)] +pub struct InputManagerResource(pub Arc>); + +impl std::fmt::Debug for InputManager { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InputManager") + .field("virtual_input", &self.virtual_input) + .finish() + } +} + +impl InputManager { + pub fn new(input_mapping: HashMap>) -> Self { + let mut input_manager = InputManager::default(); + for (value_name, bindings) in input_mapping { + input_manager.add_virtual_bindings(value_name, bindings); + } + input_manager + } + + pub fn process_device_event(&mut self, event: &DeviceEvent) { + if let DeviceEvent::MouseMotion { delta, .. } = event { + self.mouse_position_delta += glam::Vec2::new(delta.0 as f32, delta.1 as f32); + } + } + + pub fn process_window_event(&mut self, event: &WindowEvent) { + match event { + WindowEvent::AxisMotion { axis, value, .. } => { + self.virtual_input.update_axis_binding(*axis, *value as f32); + } + WindowEvent::KeyboardInput { event, .. } => { + let new_key_state = self + .keys_state + .set_key_state(event.physical_key, event.state); + if let Some(new_key_state) = new_key_state { + self.virtual_input + .update_key_binding(event.physical_key, new_key_state); + } + } + WindowEvent::MouseInput { button, state, .. } => { + let new_mouse_button_state = + self.mouse_buttons_state.set_key_state(*button, *state); + if let Some(new_mouse_button_state) = new_mouse_button_state { + self.virtual_input + .update_mouse_button_binding(*button, new_mouse_button_state); + } + } + WindowEvent::MouseWheel { delta, .. } => { + self.mouse_wheel_delta += match delta { + MouseScrollDelta::PixelDelta(position) => { + glam::Vec2::new(position.x as f32, position.y as f32) + } + MouseScrollDelta::LineDelta(x, y) => glam::Vec2::new(*x, *y), + }; + } + _ => {} + } + } + + /// Updates deltas before running update + pub fn update(&mut self) { + self.virtual_input + .update_mouse_move_binding(&self.mouse_position_delta.reset()); + self.virtual_input + .update_mouse_wheel_binding(&self.mouse_wheel_delta.reset()); + } + + pub fn get_virtual_input_state(&self, value_name: &str) -> f32 { + self.virtual_input.get_state(value_name) + } + + fn add_virtual_bindings(&mut self, value_name: String, bindings: Vec) { + self.virtual_input.add_bindings(value_name, bindings); + } +} diff --git a/src/core/input/virtual_binding.rs b/src/core/input/virtual_binding.rs new file mode 100644 index 0000000..c11dd48 --- /dev/null +++ b/src/core/input/virtual_binding.rs @@ -0,0 +1,30 @@ +use winit::{ + event::{AxisId, MouseButton}, + keyboard::PhysicalKey, +}; + +#[derive(Clone)] +pub enum AxisDirection { + Normal, + Invert, +} + +impl From<&AxisDirection> for f32 { + fn from(direction: &AxisDirection) -> Self { + match direction { + AxisDirection::Normal => 1.0, + AxisDirection::Invert => -1.0, + } + } +} + +#[derive(Clone)] +pub enum VirtualBinding { + Keyboard(PhysicalKey, AxisDirection), + Axis(AxisId, AxisDirection, f32), // f32 deadzone + MouseX(AxisDirection), + MouseY(AxisDirection), + MouseWheelX(AxisDirection), + MouseWheelY(AxisDirection), + MouseButton(MouseButton, AxisDirection), +} diff --git a/src/core/input/virtual_input.rs b/src/core/input/virtual_input.rs new file mode 100644 index 0000000..999baed --- /dev/null +++ b/src/core/input/virtual_input.rs @@ -0,0 +1,150 @@ +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; + +use winit::{ + event::{AxisId, ElementState, MouseButton}, + keyboard::PhysicalKey, +}; + +use super::{ + virtual_binding::VirtualBinding, + virtual_state::{VirtualBindingState, VirtualInputState}, +}; + +#[derive(Default)] +pub struct VirtualInput { + // Global states + states: HashMap>>, + + // Per kind of input states to keep complexity low during state updates + states_by_key: HashMap>>>, + mouse_move_states: Vec>>, + mouse_wheel_states: Vec>>, + mouse_button_states: HashMap>>>, + axis_states: HashMap>>>, +} + +impl std::fmt::Debug for VirtualInput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut debug = f.debug_struct("VirtualInput"); + + for (name, state) in &self.states { + let value = state.read().expect("Poisoned lock for debug").value; + debug.field(name, &value); + } + + debug.finish() + } +} + +impl VirtualInput { + pub fn get_state(&self, value_name: &str) -> f32 { + self.states + .get(value_name) + .map(|state| state.read().expect("Poisoned lock for get state").value) + .unwrap_or(0.0) + } + + pub fn add_bindings(&mut self, value_name: String, new_bindings: Vec) { + let state = self + .states + .entry(value_name) + .or_insert(Arc::new(RwLock::new(VirtualInputState { + value: 0.0, + bindings: Vec::new(), + }))); + + for binding in &new_bindings { + match binding { + VirtualBinding::Keyboard(key, _) => { + self.states_by_key + .entry(*key) + .or_default() + .push(state.clone()); + } + VirtualBinding::MouseX(_) | VirtualBinding::MouseY(_) => { + self.mouse_move_states.push(state.clone()); + } + VirtualBinding::MouseButton(button, _) => { + self.mouse_button_states + .entry(*button) + .or_default() + .push(state.clone()); + } + VirtualBinding::MouseWheelX(_) | VirtualBinding::MouseWheelY(_) => { + self.mouse_wheel_states.push(state.clone()); + } + VirtualBinding::Axis(axis, _, _) => { + self.axis_states + .entry(*axis) + .or_default() + .push(state.clone()); + } + } + } + + state + .write() + .expect("Poisoned lock for add bindings") + .bindings + .extend(new_bindings.iter().map(|b| VirtualBindingState { + value: 0.0, + binding: b.clone(), + })); + } + + pub(super) fn update_key_binding(&mut self, key: PhysicalKey, key_state: ElementState) { + let states = self.states_by_key.get_mut(&key); + + if let Some(states) = states { + for state in states { + let mut state = state.write().expect("Poisoned lock for key update"); + state.update_from_key(key, key_state); + } + } + } + + pub(super) fn update_mouse_move_binding(&mut self, delta: &glam::Vec2) { + for state in &mut self.mouse_move_states { + let mut state = state.write().expect("Poisoned lock for mouse move update"); + state.update_from_mouse(delta); + } + } + + pub(super) fn update_mouse_wheel_binding(&mut self, delta: &glam::Vec2) { + for state in &mut self.mouse_wheel_states { + let mut state = state.write().expect("Poisoned lock for mouse wheel update"); + state.update_from_mouse_wheel(delta); + } + } + + pub(super) fn update_mouse_button_binding( + &mut self, + button: MouseButton, + button_state: ElementState, + ) { + let states = self.mouse_button_states.get_mut(&button); + + if let Some(states) = states { + for state in states { + let mut state = state + .write() + .expect("Poisoned lock for mouse button update"); + state.update_from_mouse_button(button, button_state); + } + } + } + + pub(super) fn update_axis_binding(&mut self, axis: AxisId, axis_state: f32) { + let states = self.axis_states.get_mut(&axis); + + if let Some(states) = states { + for state in states { + let mut state = state.write().expect("Poisoned lock for axis update"); + state.update_from_axis(axis, axis_state); + } + } + } +} diff --git a/src/core/input/virtual_state.rs b/src/core/input/virtual_state.rs new file mode 100644 index 0000000..2cfd098 --- /dev/null +++ b/src/core/input/virtual_state.rs @@ -0,0 +1,105 @@ +use winit::{ + event::{AxisId, ElementState, MouseButton}, + keyboard::PhysicalKey, +}; + +use super::virtual_binding::VirtualBinding; + +pub struct VirtualBindingState { + pub value: f32, + pub binding: VirtualBinding, +} + +pub struct VirtualInputState { + pub value: f32, + pub bindings: Vec, +} + +impl VirtualInputState { + pub fn update_from_key(&mut self, key: PhysicalKey, key_state: ElementState) { + let mut new_value = 0.0; + for binding in &mut self.bindings { + if let VirtualBinding::Keyboard(binding_key, direction) = &binding.binding { + if binding_key == &key { + if key_state == ElementState::Pressed { + binding.value += f32::from(direction); + } else { + binding.value = 0.0; + } + } + } + new_value += binding.value; + } + self.value = new_value; + } + + pub fn update_from_mouse(&mut self, delta: &glam::Vec2) { + let mut new_value = 0.0; + for binding in &mut self.bindings { + match &binding.binding { + VirtualBinding::MouseX(direction) => { + binding.value = f32::from(direction) * delta.x; + } + VirtualBinding::MouseY(direction) => { + binding.value = f32::from(direction) * delta.y; + } + _ => {} + } + new_value += binding.value; + } + self.value = new_value; + } + + pub fn update_from_mouse_wheel(&mut self, delta: &glam::Vec2) { + let mut new_value = 0.0; + for binding in &mut self.bindings { + match &binding.binding { + VirtualBinding::MouseWheelX(direction) => { + binding.value = f32::from(direction) * delta.x; + } + VirtualBinding::MouseWheelY(direction) => { + binding.value = f32::from(direction) * delta.y; + } + _ => {} + } + new_value += binding.value; + } + self.value = new_value; + } + + pub fn update_from_mouse_button(&mut self, button: MouseButton, button_state: ElementState) { + let mut new_value = 0.0; + for binding in &mut self.bindings { + if let VirtualBinding::MouseButton(binding_button, direction) = &binding.binding { + if binding_button == &button { + if button_state == ElementState::Pressed { + binding.value = f32::from(direction); + } else { + binding.value = 0.0; + } + } + } + new_value += binding.value; + } + self.value = new_value; + } + + pub fn update_from_axis(&mut self, axis: AxisId, axis_state: f32) { + let mut new_value = 0.0; + for binding in &mut self.bindings { + if let VirtualBinding::Axis(binding_axis, direction, deadzone) = &binding.binding { + if binding_axis == &axis { + binding.value = + f32::from(direction) * process_axis_deadzone(axis_state, *deadzone); + } + } + new_value += binding.value; + } + self.value = new_value; + } +} + +#[inline] +fn process_axis_deadzone(value: f32, deadzone: f32) -> f32 { + if value.abs() < deadzone { 0.0 } else { value } +} diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..b1c8000 --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,4 @@ +pub mod app; +pub mod input; +pub mod render; +pub mod scene; diff --git a/src/core/render/mod.rs b/src/core/render/mod.rs new file mode 100644 index 0000000..d3d0d42 --- /dev/null +++ b/src/core/render/mod.rs @@ -0,0 +1,4 @@ +pub mod primitives; +pub mod render_pass_manager; +pub mod resources; +pub mod vulkan_context; diff --git a/src/core/render/primitives/buffer.rs b/src/core/render/primitives/buffer.rs new file mode 100644 index 0000000..33284e7 --- /dev/null +++ b/src/core/render/primitives/buffer.rs @@ -0,0 +1,84 @@ +use std::{error::Error, sync::Arc}; + +use vulkano::{ + Validated, + buffer::{AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, Subbuffer}, + memory::allocator::{AllocationCreateInfo, StandardMemoryAllocator}, +}; + +pub trait AsBindableBuffer { + type BufferData: BufferContents + Clone; + + fn buffer_create_info() -> BufferCreateInfo; + + fn allocation_create_info() -> AllocationCreateInfo; + + fn to_buffer_data(&self) -> Self::BufferData; + + fn create_buffer( + &self, + memory_allocator: &Arc, + ) -> Result, Validated> { + Buffer::from_iter( + memory_allocator.clone(), + Self::buffer_create_info(), + Self::allocation_create_info(), + [self.to_buffer_data()], + ) + } + + fn update_buffer(&self, buffer: &Subbuffer<[Self::BufferData]>) -> Result<(), Box> { + let mut write_guard = buffer.write()?; + write_guard[0] = self.to_buffer_data(); + Ok(()) + } +} + +pub trait AsUniformBuffer: AsBindableBuffer { + fn create_uniform_buffer( + &self, + memory_allocator: &Arc, + ) -> Result, Validated> { + self.create_buffer(memory_allocator) + } +} + +pub trait AsVertexBuffer: AsBindableBuffer +where + Self: Sized, +{ + fn create_vertex_buffer( + memory_allocator: &Arc, + vertices: &[Self], + ) -> Result, Validated> { + let buffer_data: Vec = + vertices.iter().map(|v| v.to_buffer_data()).collect(); + + Buffer::from_iter( + memory_allocator.clone(), + Self::buffer_create_info(), + Self::allocation_create_info(), + buffer_data, + ) + } +} + +pub trait AsIndexBuffer: AsBindableBuffer +where + Self: Sized, +{ + fn create_index_buffer( + memory_allocator: &Arc, + indices: &[Self], + ) -> Result, Validated> { + let buffer_data: Vec = + indices.iter().map(|i| i.to_buffer_data()).collect(); + + Buffer::from_iter( + memory_allocator.clone(), + Self::buffer_create_info(), + Self::allocation_create_info(), + buffer_data, + ) + } +} diff --git a/src/core/render/primitives/camera.rs b/src/core/render/primitives/camera.rs new file mode 100644 index 0000000..008ecac --- /dev/null +++ b/src/core/render/primitives/camera.rs @@ -0,0 +1,81 @@ +use std::sync::Arc; + +use bevy_ecs::component::Component; +use glam::{Mat4, Vec3, Vec4}; +use vulkano::{ + Validated, + buffer::{AllocateBufferError, Subbuffer}, + memory::allocator::StandardMemoryAllocator, +}; + +use super::{AsUniformBuffer, mvp::Mvp}; + +// See docs/OPENGL_VULKAN_DIFF.md +const OPENGL_TO_VULKAN_Y_AXIS_FLIP: Mat4 = Mat4 { + x_axis: Vec4::new(1.0, 0.0, 0.0, 0.0), + y_axis: Vec4::new(0.0, -1.0, 0.0, 0.0), + z_axis: Vec4::new(0.0, 0.0, 1.0, 0.0), + w_axis: Vec4::new(0.0, 0.0, 0.0, 1.0), +}; + +#[derive(Component)] +pub struct Camera3D { + projection: Mat4, + aspect_ratio: f32, + fov: f32, + near: f32, + far: f32, +} + +#[derive(Component)] +pub struct Camera3DTransform { + pub position: Vec3, + pub rotation: Vec3, +} + +impl Camera3D { + pub fn new(aspect_ratio: f32, fov: f32, near: f32, far: f32) -> Self { + Self { + projection: Mat4::perspective_rh(fov, aspect_ratio, near, far), + aspect_ratio, + fov, + near, + far, + } + } + + pub fn update_projection(&mut self, window_aspect_ratio: f32) { + if self.aspect_ratio != window_aspect_ratio { + self.aspect_ratio = window_aspect_ratio; + self.projection = + Mat4::perspective_rh(self.fov, self.aspect_ratio, self.near, self.far); + } + } + + pub fn set_projection(&mut self, projection: Mat4) { + self.projection = projection; + } + + pub fn create_buffer( + &self, + transform: &Camera3DTransform, + memory_allocator: &Arc, + ) -> Result, Validated> { + let (sin_pitch, cos_pitch) = transform.rotation.x.sin_cos(); + let (sin_yaw, cos_yaw) = transform.rotation.y.sin_cos(); + + let view_matrix = Mat4::look_to_rh( + transform.position, + Vec3::new(cos_pitch * cos_yaw, sin_pitch, cos_pitch * sin_yaw).normalize(), + Vec3::Y, + ); + + let mvp = Mvp { + model: OPENGL_TO_VULKAN_Y_AXIS_FLIP.to_cols_array_2d(), + view: view_matrix.to_cols_array_2d(), + projection: self.projection.to_cols_array_2d(), + }; + + mvp.create_uniform_buffer(memory_allocator) + } +} diff --git a/src/core/render/primitives/command.rs b/src/core/render/primitives/command.rs new file mode 100644 index 0000000..36a7956 --- /dev/null +++ b/src/core/render/primitives/command.rs @@ -0,0 +1,113 @@ +use std::{error::Error, sync::Arc}; + +use vulkano::{ + buffer::{BufferContents, IndexBuffer, Subbuffer}, + command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer}, + descriptor_set::allocator::StandardDescriptorSetAllocator, + pipeline::GraphicsPipeline, +}; + +use super::AsDescriptorSet; + +pub trait AsRecordable { + fn record_bind_commands( + builder: &mut AutoCommandBufferBuilder, + descriptor_set_allocator: &Arc, + pipeline: &Arc, + mesh: &impl AsRenderableMesh, + instances: &impl AsRenderableMeshInstance, + descriptor_sets: Vec>, + ) -> Result<(), Box>; + + fn record_draw_commands( + builder: &mut AutoCommandBufferBuilder, + mesh: &impl AsRenderableMesh, + instances: &impl AsRenderableMeshInstance, + ) -> Result<(), Box> { + match mesh.index_buffer() { + Some(index_buffer) => { + builder.bind_index_buffer(index_buffer.clone())?; + unsafe { + builder.draw_indexed( + mesh.index_count(), + instances.instance_count(), + mesh.first_index(), + mesh.vertex_offset(), + instances.first_instance(), + )?; + } + } + None => unsafe { + builder.draw( + mesh.vertex_count(), + instances.instance_count(), + mesh.first_vertex(), + instances.first_instance(), + )?; + }, + } + + Ok(()) + } + + fn record_commands( + builder: &mut AutoCommandBufferBuilder, + descriptor_set_allocator: &Arc, + pipeline: &Arc, + mesh: &impl AsRenderableMesh, + instances: &impl AsRenderableMeshInstance, + descriptor_sets: Vec>, + ) -> Result<(), Box> { + Self::record_bind_commands( + builder, + descriptor_set_allocator, + pipeline, + mesh, + instances, + descriptor_sets, + )?; + Self::record_draw_commands(builder, mesh, instances)?; + Ok(()) + } +} + +pub trait AsRenderableMesh { + type VertexBufferData: BufferContents + Clone; + type IndexBuffer: Into + Clone; + + fn vertex_buffer(&self) -> &Subbuffer<[Self::VertexBufferData]>; + + fn vertex_count(&self) -> u32; + + fn first_vertex(&self) -> u32 { + 0 + } + + fn vertex_offset(&self) -> i32 { + 0 + } + + fn index_buffer(&self) -> Option<&Self::IndexBuffer> { + None + } + + fn index_count(&self) -> u32 { + 0 + } + + fn first_index(&self) -> u32 { + 0 + } +} + +pub trait AsRenderableMeshInstance { + type InstanceBufferData: BufferContents + Clone; + + fn instance_buffer(&self) -> &Subbuffer<[Self::InstanceBufferData]>; + + fn instance_count(&self) -> u32; + + fn first_instance(&self) -> u32 { + 0 + } +} diff --git a/src/core/render/primitives/descriptor_set.rs b/src/core/render/primitives/descriptor_set.rs new file mode 100644 index 0000000..964d5e9 --- /dev/null +++ b/src/core/render/primitives/descriptor_set.rs @@ -0,0 +1,22 @@ +use std::{collections::BTreeMap, sync::Arc}; + +use vulkano::{ + Validated, VulkanError, + descriptor_set::{ + DescriptorSet, + allocator::StandardDescriptorSetAllocator, + layout::{DescriptorSetLayout, DescriptorSetLayoutBinding}, + }, +}; + +pub trait AsDescriptorSetLayoutBindings { + fn as_descriptor_set_layout_bindings() -> BTreeMap; +} + +pub trait AsDescriptorSet { + fn as_descriptor_set( + &self, + descriptor_set_allocator: &Arc, + layout: &Arc, + ) -> Result, Validated>; +} diff --git a/src/core/render/primitives/mod.rs b/src/core/render/primitives/mod.rs new file mode 100644 index 0000000..28cd729 --- /dev/null +++ b/src/core/render/primitives/mod.rs @@ -0,0 +1,12 @@ +mod buffer; +mod command; +mod descriptor_set; + +pub mod camera; +pub mod mvp; +pub mod transform; +pub mod velocity; +pub mod vertex; +pub use buffer::{AsBindableBuffer, AsIndexBuffer, AsUniformBuffer, AsVertexBuffer}; +pub use command::{AsRecordable, AsRenderableMesh, AsRenderableMeshInstance}; +pub use descriptor_set::{AsDescriptorSet, AsDescriptorSetLayoutBindings}; diff --git a/src/core/render/primitives/mvp.rs b/src/core/render/primitives/mvp.rs new file mode 100644 index 0000000..814a6e6 --- /dev/null +++ b/src/core/render/primitives/mvp.rs @@ -0,0 +1,87 @@ +use std::collections::BTreeMap; +use std::sync::Arc; + +use vulkano::buffer::{ + AllocateBufferError, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer, +}; +use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator; +use vulkano::descriptor_set::layout::{ + DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType, +}; +use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet}; +use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}; +use vulkano::shader::ShaderStages; +use vulkano::{Validated, VulkanError}; + +use crate::core::render::primitives::{AsBindableBuffer, AsUniformBuffer}; + +use super::{AsDescriptorSet, AsDescriptorSetLayoutBindings}; + +#[derive(BufferContents, Clone, Copy)] +#[repr(C)] +pub struct Mvp { + pub model: [[f32; 4]; 4], + pub view: [[f32; 4]; 4], + pub projection: [[f32; 4]; 4], +} + +impl Mvp { + pub fn into_buffer( + self, + memory_allocator: &Arc, + ) -> Result, Validated> { + self.create_uniform_buffer(memory_allocator) + } +} + +impl AsBindableBuffer for Mvp { + type BufferData = Mvp; + + fn buffer_create_info() -> BufferCreateInfo { + BufferCreateInfo { + usage: BufferUsage::UNIFORM_BUFFER, + ..Default::default() + } + } + + fn allocation_create_info() -> AllocationCreateInfo { + AllocationCreateInfo { + memory_type_filter: MemoryTypeFilter::PREFER_DEVICE + | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, + ..Default::default() + } + } + + fn to_buffer_data(&self) -> Self::BufferData { + *self + } +} + +impl AsUniformBuffer for Mvp {} + +impl AsDescriptorSetLayoutBindings for Mvp { + fn as_descriptor_set_layout_bindings() -> BTreeMap { + BTreeMap::::from_iter([( + 0, + DescriptorSetLayoutBinding { + stages: ShaderStages::VERTEX, + ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer) + }, + )]) + } +} + +impl AsDescriptorSet for Subbuffer<[Mvp]> { + fn as_descriptor_set( + &self, + descriptor_set_allocator: &Arc, + layout: &Arc, + ) -> Result, Validated> { + DescriptorSet::new( + descriptor_set_allocator.clone(), + layout.clone(), + [WriteDescriptorSet::buffer(0, self.clone())], + [], + ) + } +} diff --git a/src/core/render/primitives/transform.rs b/src/core/render/primitives/transform.rs new file mode 100644 index 0000000..9bbda47 --- /dev/null +++ b/src/core/render/primitives/transform.rs @@ -0,0 +1,116 @@ +use std::sync::Arc; + +use bevy_ecs::prelude::*; +use glam::{Mat4, Quat, Vec3}; +use vulkano::{ + Validated, + buffer::{AllocateBufferError, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer}, + memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, + pipeline::graphics::vertex_input::Vertex, +}; + +use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer}; + +use super::command::AsRenderableMeshInstance; + +#[derive(Component, Debug, Clone)] +pub struct Transform { + pub position: Vec3, + pub rotation: Quat, + pub scale: Vec3, +} + +#[derive(BufferContents, Vertex, Clone, Copy, Debug)] +#[repr(C)] +pub struct TransformRaw { + #[format(R32G32B32A32_SFLOAT)] + pub model: [[f32; 4]; 4], +} + +impl Default for Transform { + fn default() -> Self { + Self { + position: Vec3::ZERO, + rotation: Quat::IDENTITY, + scale: Vec3::ONE, + } + } +} + +impl Transform { + pub fn new(position: Vec3, rotation: Quat, scale: Vec3) -> Self { + Self { + position, + rotation, + scale, + } + } + + /// Get the transformation matrix (immutable - recalculates each time) + pub fn matrix(&self) -> Mat4 { + Mat4::from_translation(self.position) + * Mat4::from_quat(self.rotation) + * Mat4::from_scale(self.scale) + } + + /// Convert to GPU-ready format (immutable - recalculates each time) + pub fn to_raw(&self) -> TransformRaw { + TransformRaw { + model: self.matrix().to_cols_array_2d(), + } + } + + /// Create a buffer from transforms (immutable - recalculates each time) + pub fn create_buffer( + memory_allocator: &Arc, + transforms: &[Transform], + ) -> Result, Validated> { + TransformRaw::create_vertex_buffer( + memory_allocator, + &transforms.iter().map(|t| t.to_raw()).collect::>(), + ) + } +} + +impl From<&Transform> for TransformRaw { + fn from(transform: &Transform) -> Self { + transform.to_raw() + } +} + +impl AsBindableBuffer for TransformRaw { + type BufferData = TransformRaw; + + fn buffer_create_info() -> BufferCreateInfo { + BufferCreateInfo { + usage: BufferUsage::VERTEX_BUFFER, + ..Default::default() + } + } + + fn allocation_create_info() -> AllocationCreateInfo { + AllocationCreateInfo { + memory_type_filter: MemoryTypeFilter::PREFER_DEVICE + | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, + ..Default::default() + } + } + + fn to_buffer_data(&self) -> Self::BufferData { + *self + } +} + +impl AsVertexBuffer for TransformRaw {} + +impl AsRenderableMeshInstance for Subbuffer<[TransformRaw]> { + type InstanceBufferData = TransformRaw; + + fn instance_buffer(&self) -> &Subbuffer<[Self::InstanceBufferData]> { + self + } + + fn instance_count(&self) -> u32 { + self.len() as u32 + } +} diff --git a/src/core/render/primitives/velocity.rs b/src/core/render/primitives/velocity.rs new file mode 100644 index 0000000..19899aa --- /dev/null +++ b/src/core/render/primitives/velocity.rs @@ -0,0 +1,14 @@ +use bevy_ecs::prelude::*; +use glam::Vec3; + +#[derive(Component, Debug, Clone, Default)] +pub struct Velocity { + pub linear: Vec3, + pub angular: Vec3, +} + +impl Velocity { + pub fn new(linear: Vec3, angular: Vec3) -> Self { + Self { linear, angular } + } +} diff --git a/src/core/render/primitives/vertex.rs b/src/core/render/primitives/vertex.rs new file mode 100644 index 0000000..14571c6 --- /dev/null +++ b/src/core/render/primitives/vertex.rs @@ -0,0 +1,101 @@ +use vulkano::buffer::BufferContents; +use vulkano::buffer::{BufferCreateInfo, BufferUsage}; +use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter}; +use vulkano::pipeline::graphics::vertex_input::Vertex; + +use crate::core::render::primitives::{AsBindableBuffer, AsIndexBuffer, AsVertexBuffer}; + +#[derive(BufferContents, Vertex, Clone, Copy)] +#[repr(C)] +pub struct Vertex2D { + #[format(R32G32_SFLOAT)] + pub position: [f32; 2], + + #[format(R32G32_SFLOAT)] + pub uv: [f32; 2], +} + +#[derive(BufferContents, Vertex, Clone, Copy)] +#[repr(C)] +pub struct Vertex3D { + #[format(R32G32B32_SFLOAT)] + pub position: [f32; 3], + + #[format(R32G32_SFLOAT)] + pub uv: [f32; 2], +} + +impl AsBindableBuffer for Vertex2D { + type BufferData = Vertex2D; + + fn buffer_create_info() -> BufferCreateInfo { + BufferCreateInfo { + usage: BufferUsage::VERTEX_BUFFER, + ..Default::default() + } + } + + fn allocation_create_info() -> AllocationCreateInfo { + AllocationCreateInfo { + memory_type_filter: MemoryTypeFilter::PREFER_DEVICE + | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, + ..Default::default() + } + } + + fn to_buffer_data(&self) -> Self::BufferData { + *self + } +} + +impl AsVertexBuffer for Vertex2D {} + +impl AsBindableBuffer for Vertex3D { + type BufferData = Vertex3D; + + fn buffer_create_info() -> BufferCreateInfo { + BufferCreateInfo { + usage: BufferUsage::VERTEX_BUFFER, + ..Default::default() + } + } + + fn allocation_create_info() -> AllocationCreateInfo { + AllocationCreateInfo { + memory_type_filter: MemoryTypeFilter::PREFER_DEVICE + | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, + ..Default::default() + } + } + + fn to_buffer_data(&self) -> Self::BufferData { + *self + } +} + +impl AsVertexBuffer for Vertex3D {} + +impl AsBindableBuffer for u32 { + type BufferData = u32; + + fn buffer_create_info() -> BufferCreateInfo { + BufferCreateInfo { + usage: BufferUsage::INDEX_BUFFER, + ..Default::default() + } + } + + fn allocation_create_info() -> AllocationCreateInfo { + AllocationCreateInfo { + memory_type_filter: MemoryTypeFilter::PREFER_DEVICE + | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, + ..Default::default() + } + } + + fn to_buffer_data(&self) -> Self::BufferData { + *self + } +} + +impl AsIndexBuffer for u32 {} diff --git a/src/core/render/render_pass_manager.rs b/src/core/render/render_pass_manager.rs new file mode 100644 index 0000000..02c3d7a --- /dev/null +++ b/src/core/render/render_pass_manager.rs @@ -0,0 +1,113 @@ +use std::sync::Arc; +use vulkano::{ + command_buffer::{AutoCommandBufferBuilder, RenderingAttachmentInfo, RenderingInfo}, + image::view::ImageView, + pipeline::graphics::viewport::Viewport, + render_pass::{AttachmentLoadOp, AttachmentStoreOp}, +}; + +/// Types de render passes disponibles +#[derive(Debug, Clone)] +pub enum RenderPassType { + Standard, + ShadowMap, + PostProcess, +} + +/// Configuration pour un render pass +#[derive(Debug, Clone)] +pub struct RenderPassConfig { + pub pass_type: RenderPassType, + pub clear_color: Option<[f32; 4]>, + pub clear_depth: Option, + pub load_op: AttachmentLoadOp, + pub store_op: AttachmentStoreOp, +} + +impl Default for RenderPassConfig { + fn default() -> Self { + Self { + pass_type: RenderPassType::Standard, + clear_color: Some([0.0, 0.0, 0.0, 1.0]), + clear_depth: Some(1.0), + load_op: AttachmentLoadOp::Clear, + store_op: AttachmentStoreOp::Store, + } + } +} + +/// Gestionnaire de render passes réutilisable +pub struct RenderPassManager; + +impl RenderPassManager { + /// Commence un render pass standard avec les paramètres donnés + pub fn begin_standard_rendering( + builder: &mut AutoCommandBufferBuilder, + config: &RenderPassConfig, + color_attachment: Arc, + depth_attachment: Option>, + window_size: [f32; 2], + ) -> Result<(), Box> { + let viewport = Viewport { + offset: [0.0, 0.0], + extent: window_size, + depth_range: 0.0..=1.0, + }; + + let mut rendering_info = RenderingInfo { + color_attachments: vec![Some(RenderingAttachmentInfo { + load_op: config.load_op, + store_op: config.store_op, + clear_value: config.clear_color.map(|c| c.into()), + ..RenderingAttachmentInfo::image_view(color_attachment) + })], + depth_attachment: None, + ..Default::default() + }; + + if let Some(depth_view) = depth_attachment { + rendering_info.depth_attachment = Some(RenderingAttachmentInfo { + load_op: AttachmentLoadOp::Clear, + store_op: AttachmentStoreOp::DontCare, + clear_value: config.clear_depth.map(|d| [d].into()), + ..RenderingAttachmentInfo::image_view(depth_view) + }); + } + + builder + .begin_rendering(rendering_info)? + .set_viewport(0, [viewport].into_iter().collect())?; + + Ok(()) + } + + /// Termine le render pass actuel + pub fn end_rendering( + builder: &mut AutoCommandBufferBuilder, + ) -> Result<(), Box> { + builder.end_rendering()?; + Ok(()) + } + + /// Crée une configuration pour un render pass shadow map + pub fn shadow_map_config() -> RenderPassConfig { + RenderPassConfig { + pass_type: RenderPassType::ShadowMap, + clear_color: None, + clear_depth: Some(1.0), + load_op: AttachmentLoadOp::Clear, + store_op: AttachmentStoreOp::Store, + } + } + + /// Crée une configuration pour un render pass de post-processing + pub fn post_process_config() -> RenderPassConfig { + RenderPassConfig { + pass_type: RenderPassType::PostProcess, + clear_color: Some([0.0, 0.0, 0.0, 1.0]), + clear_depth: None, + load_op: AttachmentLoadOp::Load, + store_op: AttachmentStoreOp::Store, + } + } +} diff --git a/src/core/render/resources/meshes/mod.rs b/src/core/render/resources/meshes/mod.rs new file mode 100644 index 0000000..c086209 --- /dev/null +++ b/src/core/render/resources/meshes/mod.rs @@ -0,0 +1,5 @@ +mod square; +pub use square::SquareMesh; + +mod obj; +pub use obj::ObjMesh; diff --git a/src/core/render/resources/meshes/obj.rs b/src/core/render/resources/meshes/obj.rs new file mode 100644 index 0000000..7ca648f --- /dev/null +++ b/src/core/render/resources/meshes/obj.rs @@ -0,0 +1,79 @@ +use std::{error::Error, path::PathBuf, sync::Arc}; + +use vulkano::{buffer::Subbuffer, memory::allocator::StandardMemoryAllocator}; + +use crate::core::render::primitives::{ + AsIndexBuffer, AsRenderableMesh, AsVertexBuffer, vertex::Vertex3D, +}; + +pub struct ObjMesh { + vertex_buffer: Subbuffer<[Vertex3D]>, + index_buffer: Subbuffer<[u32]>, +} + +impl ObjMesh { + pub fn new( + memory_allocator: &Arc, + file_path: impl Into, + ) -> Result, Box> { + let (models, _) = tobj::load_obj( + &file_path.into(), + &tobj::LoadOptions { + single_index: true, + triangulate: true, + ..Default::default() + }, + )?; + + let meshes = models + .into_iter() + .map(|model| { + let vertices = (0..model.mesh.positions.len() / 3) + .map(|i| Vertex3D { + position: [ + model.mesh.positions[i * 3], + model.mesh.positions[i * 3 + 1], + model.mesh.positions[i * 3 + 2], + ], + uv: [model.mesh.texcoords[i * 2], model.mesh.texcoords[i * 2 + 1]], + }) + .collect::>(); + + let indices = model.mesh.indices; + + let vertex_buffer = Vertex3D::create_vertex_buffer(memory_allocator, &vertices) + .expect("Failed to create vertex buffer"); + let index_buffer = u32::create_index_buffer(memory_allocator, &indices) + .expect("Failed to create index buffer"); + + Self { + vertex_buffer, + index_buffer, + } + }) + .collect::>(); + + Ok(meshes) + } +} + +impl AsRenderableMesh for ObjMesh { + type VertexBufferData = Vertex3D; + type IndexBuffer = Subbuffer<[u32]>; + + fn vertex_buffer(&self) -> &Subbuffer<[Self::VertexBufferData]> { + &self.vertex_buffer + } + + fn index_buffer(&self) -> Option<&Self::IndexBuffer> { + Some(&self.index_buffer) + } + + fn vertex_count(&self) -> u32 { + self.vertex_buffer.len() as u32 + } + + fn index_count(&self) -> u32 { + self.index_buffer.len() as u32 + } +} diff --git a/src/core/render/resources/meshes/square.rs b/src/core/render/resources/meshes/square.rs new file mode 100644 index 0000000..86f8cf9 --- /dev/null +++ b/src/core/render/resources/meshes/square.rs @@ -0,0 +1,66 @@ +use std::{error::Error, sync::Arc}; + +use vulkano::{buffer::Subbuffer, memory::allocator::StandardMemoryAllocator}; + +use crate::core::render::primitives::{ + AsIndexBuffer, AsRenderableMesh, AsVertexBuffer, vertex::Vertex3D, +}; + +const VERTICES: [Vertex3D; 4] = [ + Vertex3D { + position: [-0.5, -0.5, 0.0], + uv: [0.0, 0.0], + }, + Vertex3D { + position: [-0.5, 0.5, 0.0], + uv: [0.0, 1.0], + }, + Vertex3D { + position: [0.5, -0.5, 0.0], + uv: [1.0, 0.0], + }, + Vertex3D { + position: [0.5, 0.5, 0.0], + uv: [1.0, 1.0], + }, +]; + +const INDICES: [u32; 6] = [0, 2, 1, 2, 3, 1]; + +pub struct SquareMesh { + vertex_buffer: Subbuffer<[Vertex3D]>, + index_buffer: Subbuffer<[u32]>, +} + +impl SquareMesh { + pub fn new(memory_allocator: &Arc) -> Result> { + let vertex_buffer = Vertex3D::create_vertex_buffer(memory_allocator, &VERTICES)?; + let index_buffer = u32::create_index_buffer(memory_allocator, &INDICES)?; + + Ok(Self { + vertex_buffer, + index_buffer, + }) + } +} + +impl AsRenderableMesh for SquareMesh { + type VertexBufferData = Vertex3D; + type IndexBuffer = Subbuffer<[u32]>; + + fn vertex_buffer(&self) -> &Subbuffer<[Self::VertexBufferData]> { + &self.vertex_buffer + } + + fn index_buffer(&self) -> Option<&Self::IndexBuffer> { + Some(&self.index_buffer) + } + + fn vertex_count(&self) -> u32 { + VERTICES.len() as u32 + } + + fn index_count(&self) -> u32 { + INDICES.len() as u32 + } +} diff --git a/src/core/render/resources/mod.rs b/src/core/render/resources/mod.rs new file mode 100644 index 0000000..d60e2d2 --- /dev/null +++ b/src/core/render/resources/mod.rs @@ -0,0 +1,5 @@ +pub mod meshes; +pub mod pipeline; +pub mod texture; +pub mod timer; +pub mod vulkan; diff --git a/src/core/render/resources/pipeline/loader.rs b/src/core/render/resources/pipeline/loader.rs new file mode 100644 index 0000000..92c5f9a --- /dev/null +++ b/src/core/render/resources/pipeline/loader.rs @@ -0,0 +1,115 @@ +use std::{ + any::TypeId, + collections::HashMap, + error::Error, + sync::{Arc, RwLock}, +}; + +use bevy_ecs::resource::Resource; +use vulkano::{device::Device, format::Format, pipeline::GraphicsPipeline}; + +use super::{GraphicsPipelineLoadFn, LoadableGraphicsPipeline}; + +#[derive(PartialEq, Eq)] +pub enum PipelineState { + NeedBuild, + Loaded, +} + +#[derive(Resource)] +pub struct PipelineLoader { + device: Arc, + swapchain_image_format: Format, + depth_image_format: Format, + + // Arc is used in internal of vulkano. It's not possible to use Arc>> directly. + pipelines_index: HashMap, + pipelines_id: Vec, + pipelines_load_fn: Vec, + // Only content is protected by Arc and RwLock to avoid push in pipeline_loader in multiple threads and just allow to lock each pipeline when is needed as parallel pipelines loading. + // But only the pipeline loader is allowed to load a pipeline when it's needed. + pipelines: Vec>>>>, + pipelines_state: Vec>>, + pipelines_name: Vec<&'static str>, +} + +impl PipelineLoader { + pub fn new( + device: Arc, + swapchain_image_format: Format, + depth_image_format: Format, + ) -> Self { + Self { + device, + swapchain_image_format, + depth_image_format, + pipelines: Vec::new(), + pipelines_load_fn: Vec::new(), + pipelines_name: Vec::new(), + pipelines_id: Vec::new(), + pipelines_state: Vec::new(), + pipelines_index: HashMap::new(), + } + } + + pub fn register( + &mut self, + ) -> Result<(), Box> { + let id = TypeId::of::(); + self.pipelines_index.insert(id, self.pipelines.len()); + self.pipelines_id.push(id); + self.pipelines_load_fn.push(T::load); + self.pipelines_name.push(T::pipeline_name()); + self.pipelines_state + .push(Arc::new(RwLock::new(PipelineState::NeedBuild))); + self.pipelines.push(Arc::new(RwLock::new(None))); + Ok(()) + } + + pub fn load_pending_pipelines(&self) -> Result<(), Box> { + let iter = self + .pipelines_name + .iter() + .zip(self.pipelines.iter()) + .zip(self.pipelines_load_fn.iter()) + .zip(self.pipelines_state.iter()) + .filter(|(_, state)| { + let state = state.read().unwrap(); + *state == PipelineState::NeedBuild + }); + + for (((name, pipeline), load_fn), state) in iter { + let new_pipeline = load_fn( + &self.device, + self.swapchain_image_format, + self.depth_image_format, + )?; + let mut pipeline = pipeline.write().unwrap(); + *pipeline = Some(new_pipeline); + let mut state = state.write().unwrap(); + *state = PipelineState::Loaded; + tracing::trace!("Pipeline {name} loaded"); + } + Ok(()) + } + + fn mark_pipelines_as_need_build(&mut self) { + for state in self.pipelines_state.iter() { + let mut state = state.write().unwrap(); + *state = PipelineState::NeedBuild; + } + } + + pub fn with_pipeline(&self, f: F) -> Result<(), Box> + where + F: FnOnce(&Arc) -> Result<(), Box>, + { + let id = TypeId::of::(); + let index = self.pipelines_index.get(&id).ok_or("Pipeline not found")?; + let pipeline_locker = self.pipelines[*index] + .read() + .map_err(|_| "Failed to lock pipeline")?; + let pipeline = pipeline_locker.as_ref().ok_or("Pipeline not loaded")?; + f(pipeline) + } +} diff --git a/src/core/render/resources/pipeline/mod.rs b/src/core/render/resources/pipeline/mod.rs new file mode 100644 index 0000000..9fa9c79 --- /dev/null +++ b/src/core/render/resources/pipeline/mod.rs @@ -0,0 +1,18 @@ +mod loader; +use std::{error::Error, sync::Arc}; + +pub use loader::PipelineLoader; +use vulkano::{device::Device, format::Format, pipeline::GraphicsPipeline}; + +type GraphicsPipelineLoadFn = + fn(&Arc, Format, Format) -> Result, Box>; + +pub trait LoadableGraphicsPipeline { + fn load( + device: &Arc, + swapchain_image_format: Format, + depth_image_format: Format, + ) -> Result, Box>; + + fn pipeline_name() -> &'static str; +} diff --git a/src/core/render/resources/texture/loader.rs b/src/core/render/resources/texture/loader.rs new file mode 100644 index 0000000..2f34d4b --- /dev/null +++ b/src/core/render/resources/texture/loader.rs @@ -0,0 +1,133 @@ +use std::{collections::HashMap, error::Error, sync::Arc}; + +use vulkano::{ + command_buffer::{ + AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract, + allocator::StandardCommandBufferAllocator, + }, + device::{Device, Queue}, + format::Format, + image::sampler::SamplerCreateInfo, + memory::allocator::StandardMemoryAllocator, +}; + +use bevy_ecs::resource::Resource; + +use super::Texture; + +pub enum TextureSourceKind { + File(String), + Buffer(Vec), +} + +pub struct TextureLoadInfo { + pub source: TextureSourceKind, + pub sampler_create_info: SamplerCreateInfo, + pub image_format: Format, +} + +#[derive(Resource)] +pub struct TextureLoader { + loaded_textures: HashMap>, + pending_textures: HashMap, + device: Arc, + command_buffer_allocator: Arc, + memory_allocator: Arc, + queue: Arc, +} + +impl TextureLoader { + pub fn new( + device: Arc, + command_buffer_allocator: Arc, + memory_allocator: Arc, + queue: Arc, + ) -> Self { + Self { + loaded_textures: HashMap::new(), + pending_textures: HashMap::new(), + device, + command_buffer_allocator, + memory_allocator, + queue, + } + } + + pub fn select_best_suitable_queue( + graphics_queue: &Arc, + transfer_queue: Option<&Arc>, + ) -> Arc { + transfer_queue + .map(|queue| { + tracing::trace!( + "Select transfer queue for texture loading with family index: {:?}", + queue.queue_family_index() + ); + queue.clone() + }) + .unwrap_or_else(|| { + tracing::trace!( + "Select graphics queue for texture loading with family index: {:?}", + graphics_queue.queue_family_index() + ); + graphics_queue.clone() + }) + } + + pub fn add_texture(&mut self, name: String, load_info: TextureLoadInfo) { + self.pending_textures.insert(name, load_info); + } + + pub fn load_pending_textures(&mut self) -> Result<(), Box> { + let _span = tracing::info_span!("load_pending_textures"); + let mut uploads = AutoCommandBufferBuilder::primary( + self.command_buffer_allocator.clone(), + self.queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + )?; + + let mut loading_textures = HashMap::new(); + + tracing::trace!("Pending textures count: {}", self.pending_textures.len()); + + for (name, info) in self.pending_textures.iter() { + let texture = match &info.source { + TextureSourceKind::File(path) => Texture::from_file( + &self.device, + &self.memory_allocator, + &mut uploads, + path.as_str(), + info, + )?, + TextureSourceKind::Buffer(buffer) => Texture::from_bytes( + &self.device, + &self.memory_allocator, + &mut uploads, + &buffer, + info, + )?, + }; + + loading_textures.insert(name.clone(), Arc::new(texture)); + tracing::trace!("Loaded texture: {}", name); + } + + let _ = uploads.build()?.execute(self.queue.clone())?; + + self.loaded_textures.extend(loading_textures); + + Ok(()) + } + + pub fn get_texture(&self, name: &str) -> Option<&Arc> { + self.loaded_textures.get(name) + } + + pub fn pending_textures_count(&self) -> usize { + self.pending_textures.len() + } + + pub fn loaded_textures_count(&self) -> usize { + self.loaded_textures.len() + } +} diff --git a/src/core/render/resources/texture/mod.rs b/src/core/render/resources/texture/mod.rs new file mode 100644 index 0000000..7bd052e --- /dev/null +++ b/src/core/render/resources/texture/mod.rs @@ -0,0 +1,5 @@ +mod texture; +pub use texture::Texture; + +mod loader; +pub use loader::{TextureLoadInfo, TextureLoader, TextureSourceKind}; diff --git a/src/core/render/resources/texture/texture.rs b/src/core/render/resources/texture/texture.rs new file mode 100644 index 0000000..8eaf140 --- /dev/null +++ b/src/core/render/resources/texture/texture.rs @@ -0,0 +1,152 @@ +use std::{collections::BTreeMap, error::Error, sync::Arc}; + +use image::DynamicImage; +use vulkano::{ + Validated, VulkanError, + buffer::{Buffer, BufferCreateInfo, BufferUsage}, + command_buffer::{AutoCommandBufferBuilder, CopyBufferToImageInfo, PrimaryAutoCommandBuffer}, + descriptor_set::{ + DescriptorSet, WriteDescriptorSet, + allocator::StandardDescriptorSetAllocator, + layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType}, + }, + device::Device, + format::Format, + image::{Image, ImageCreateInfo, ImageType, ImageUsage, sampler::Sampler, view::ImageView}, + memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, + shader::ShaderStages, +}; + +use crate::core::render::primitives::{AsDescriptorSet, AsDescriptorSetLayoutBindings}; + +use super::TextureLoadInfo; + +pub struct Texture { + texture: Arc, + sampler: Arc, +} + +impl Texture { + fn new(texture: Arc, sampler: Arc) -> Self { + Self { texture, sampler } + } + + pub(super) fn from_file( + device: &Arc, + memory_allocator: &Arc, + builder: &mut AutoCommandBufferBuilder, + path: &str, + load_info: &TextureLoadInfo, + ) -> Result> { + let bytes = std::fs::read(path)?; + Self::from_bytes(device, memory_allocator, builder, &bytes, load_info) + } + + pub(super) fn from_bytes( + device: &Arc, + memory_allocator: &Arc, + builder: &mut AutoCommandBufferBuilder, + bytes: &[u8], + load_info: &TextureLoadInfo, + ) -> Result> { + let image = image::load_from_memory(bytes)?; + Self::from_dynamic_image(device, memory_allocator, builder, image, load_info) + } + + fn from_dynamic_image( + device: &Arc, + memory_allocator: &Arc, + builder: &mut AutoCommandBufferBuilder, + image: DynamicImage, + load_info: &TextureLoadInfo, + ) -> Result> { + let image_data = match load_info.image_format { + Format::R8G8B8A8_SRGB => image.to_rgba8(), + _ => return Err("Unsupported format".into()), + }; + let image_dimensions = image_data.dimensions(); + let image_data = image_data.into_raw(); + + let upload_buffer = Buffer::new_slice( + memory_allocator.clone(), + BufferCreateInfo { + usage: BufferUsage::TRANSFER_SRC, + ..Default::default() + }, + AllocationCreateInfo { + memory_type_filter: MemoryTypeFilter::PREFER_HOST + | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, + ..Default::default() + }, + image_data.len() as u64, + )?; + + { + let buffer_data = &mut *upload_buffer.write()?; + buffer_data.copy_from_slice(&image_data); + } + + let image = Image::new( + memory_allocator.clone(), + ImageCreateInfo { + image_type: ImageType::Dim2d, + format: load_info.image_format, + extent: [image_dimensions.0, image_dimensions.1, 1], + array_layers: 1, + usage: ImageUsage::TRANSFER_DST | ImageUsage::SAMPLED, + ..Default::default() + }, + AllocationCreateInfo::default(), + )?; + + builder.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image( + upload_buffer, + image.clone(), + ))?; + + let sampler = Sampler::new(device.clone(), load_info.sampler_create_info.clone())?; + + let image_view = ImageView::new_default(image)?; + + Ok(Self::new(image_view, sampler)) + } +} + +impl AsDescriptorSetLayoutBindings for Texture { + fn as_descriptor_set_layout_bindings() -> BTreeMap { + BTreeMap::::from_iter([ + ( + 0, + DescriptorSetLayoutBinding { + stages: ShaderStages::FRAGMENT, + ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::Sampler) + }, + ), + ( + 1, + DescriptorSetLayoutBinding { + stages: ShaderStages::FRAGMENT, + ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::SampledImage) + }, + ), + ]) + } +} + +impl AsDescriptorSet for Texture { + fn as_descriptor_set( + &self, + descriptor_set_allocator: &Arc, + layout: &Arc, + ) -> Result, Validated> { + DescriptorSet::new( + descriptor_set_allocator.clone(), + layout.clone(), + [ + WriteDescriptorSet::sampler(0, self.sampler.clone()), + WriteDescriptorSet::image_view(1, self.texture.clone()), + ], + [], + ) + } +} diff --git a/src/core/render/resources/timer.rs b/src/core/render/resources/timer.rs new file mode 100644 index 0000000..1efb5ad --- /dev/null +++ b/src/core/render/resources/timer.rs @@ -0,0 +1,37 @@ +use bevy_ecs::resource::Resource; + +#[derive(Resource)] +pub struct Timer { + start_time: std::time::Instant, + last_time: std::time::Instant, + current_time: std::time::Instant, + delta_time: f32, +} + +impl Timer { + pub fn new() -> Self { + Self { + start_time: std::time::Instant::now(), + last_time: std::time::Instant::now(), + current_time: std::time::Instant::now(), + delta_time: 0.0, + } + } + + pub fn update(&mut self) { + self.current_time = std::time::Instant::now(); + self.delta_time = self + .current_time + .duration_since(self.last_time) + .as_secs_f32(); + self.last_time = self.current_time; + } + + pub fn delta_time(&self) -> f32 { + self.delta_time + } + + pub fn start_time(&self) -> std::time::Instant { + self.start_time + } +} diff --git a/src/core/render/resources/vulkan.rs b/src/core/render/resources/vulkan.rs new file mode 100644 index 0000000..47dce68 --- /dev/null +++ b/src/core/render/resources/vulkan.rs @@ -0,0 +1,145 @@ +use bevy_ecs::prelude::Resource; +use std::{ops::Deref, sync::Arc}; +use vulkano::{ + command_buffer::allocator::StandardCommandBufferAllocator, + descriptor_set::allocator::StandardDescriptorSetAllocator, + device::{Device, Queue}, + instance::Instance, + memory::allocator::StandardMemoryAllocator, +}; + +#[derive(Resource)] +pub struct VulkanInstance(Arc); + +impl From<&Arc> for VulkanInstance { + fn from(instance: &Arc) -> Self { + Self(instance.clone()) + } +} + +impl Deref for VulkanInstance { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanDevice(Arc); + +impl From<&Arc> for VulkanDevice { + fn from(device: &Arc) -> Self { + Self(device.clone()) + } +} + +impl Deref for VulkanDevice { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanGraphicsQueue(Arc); + +impl From<&Arc> for VulkanGraphicsQueue { + fn from(queue: &Arc) -> Self { + Self(queue.clone()) + } +} + +impl Deref for VulkanGraphicsQueue { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanComputeQueue(Arc); + +impl From<&Arc> for VulkanComputeQueue { + fn from(queue: &Arc) -> Self { + Self(queue.clone()) + } +} + +impl Deref for VulkanComputeQueue { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanTransferQueue(Option>); + +impl From>> for VulkanTransferQueue { + fn from(queue: Option<&Arc>) -> Self { + Self(queue.cloned()) + } +} + +impl Deref for VulkanTransferQueue { + type Target = Option>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanMemoryAllocator(Arc); + +impl From<&Arc> for VulkanMemoryAllocator { + fn from(allocator: &Arc) -> Self { + Self(allocator.clone()) + } +} + +impl Deref for VulkanMemoryAllocator { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanCommandBufferAllocator(Arc); + +impl From<&Arc> for VulkanCommandBufferAllocator { + fn from(allocator: &Arc) -> Self { + Self(allocator.clone()) + } +} + +impl Deref for VulkanCommandBufferAllocator { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Resource)] +pub struct VulkanDescriptorSetAllocator(Arc); + +impl From<&Arc> for VulkanDescriptorSetAllocator { + fn from(allocator: &Arc) -> Self { + Self(allocator.clone()) + } +} + +impl Deref for VulkanDescriptorSetAllocator { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/src/core/render/vulkan_context.rs b/src/core/render/vulkan_context.rs new file mode 100644 index 0000000..3d91ec3 --- /dev/null +++ b/src/core/render/vulkan_context.rs @@ -0,0 +1,45 @@ +use std::sync::Arc; + +use vulkano::{ + command_buffer::allocator::StandardCommandBufferAllocator, + descriptor_set::allocator::StandardDescriptorSetAllocator, +}; +use vulkano_util::context::VulkanoContext; + +pub struct VulkanContext { + vulkano_context: VulkanoContext, + command_buffer_allocator: Arc, + descriptor_set_allocator: Arc, +} + +impl VulkanContext { + pub fn new(vulkano_context: VulkanoContext) -> Self { + let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new( + vulkano_context.device().clone(), + Default::default(), + )); + + let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( + vulkano_context.device().clone(), + Default::default(), + )); + + Self { + vulkano_context, + command_buffer_allocator, + descriptor_set_allocator, + } + } + + pub fn vulkano_context(&self) -> &VulkanoContext { + &self.vulkano_context + } + + pub fn command_buffer_allocator(&self) -> &Arc { + &self.command_buffer_allocator + } + + pub fn descriptor_set_allocator(&self) -> &Arc { + &self.descriptor_set_allocator + } +} diff --git a/src/core/scene/extract.rs b/src/core/scene/extract.rs new file mode 100644 index 0000000..9c61953 --- /dev/null +++ b/src/core/scene/extract.rs @@ -0,0 +1,81 @@ +use bevy_ecs::world::World; + +use crate::core::{ + app::{DEPTH_IMAGE_ID, context::WindowContext}, + render::{ + resources::vulkan::{ + VulkanCommandBufferAllocator, VulkanComputeQueue, VulkanDescriptorSetAllocator, + VulkanDevice, VulkanGraphicsQueue, VulkanInstance, VulkanMemoryAllocator, + VulkanTransferQueue, + }, + resources::{pipeline::PipelineLoader, texture::TextureLoader}, + vulkan_context::VulkanContext, + }, +}; + +pub fn extract_vulkan_ressources(world: &mut World, vulkan_context: &VulkanContext) { + let vulkano_context = vulkan_context.vulkano_context(); + + let vulkan_instance = vulkano_context.instance(); + let vulkan_device = vulkano_context.device(); + let vulkan_graphics_queue = vulkano_context.graphics_queue(); + let vulkan_compute_queue = vulkano_context.compute_queue(); + let vulkan_transfer_queue = vulkano_context.transfer_queue(); + let vulkan_memory_allocator = vulkano_context.memory_allocator(); + let vulkan_command_buffer_allocator = vulkan_context.command_buffer_allocator(); + let vulkan_descriptor_set_allocator = vulkan_context.descriptor_set_allocator(); + + world.insert_resource(VulkanInstance::from(vulkan_instance)); + world.insert_resource(VulkanDevice::from(vulkan_device)); + world.insert_resource(VulkanGraphicsQueue::from(vulkan_graphics_queue)); + world.insert_resource(VulkanComputeQueue::from(vulkan_compute_queue)); + world.insert_resource(VulkanTransferQueue::from(vulkan_transfer_queue)); + world.insert_resource(VulkanMemoryAllocator::from(vulkan_memory_allocator)); + world.insert_resource(VulkanCommandBufferAllocator::from( + vulkan_command_buffer_allocator, + )); + world.insert_resource(VulkanDescriptorSetAllocator::from( + vulkan_descriptor_set_allocator, + )); +} + +pub fn extract_texture_loader(world: &mut World, vulkan_context: &VulkanContext) { + let vulkano_context = vulkan_context.vulkano_context(); + + let vulkan_device = vulkano_context.device(); + let vulkan_command_buffer_allocator = vulkan_context.command_buffer_allocator(); + let vulkan_memory_allocator = vulkano_context.memory_allocator(); + let vulkan_graphics_queue = vulkano_context.graphics_queue(); + let vulkan_transfer_queue = vulkano_context.transfer_queue(); + + let texture_loader = TextureLoader::new( + vulkan_device.clone(), + vulkan_command_buffer_allocator.clone(), + vulkan_memory_allocator.clone(), + TextureLoader::select_best_suitable_queue(vulkan_graphics_queue, vulkan_transfer_queue), + ); + + world.insert_resource(texture_loader); +} + +pub fn extract_pipeline_loader(world: &mut World, window_context: &mut WindowContext) { + let vulkan_device = window_context + .vulkan_context() + .vulkano_context() + .device() + .clone(); + + let depth_image_view = window_context + .with_renderer_mut(|renderer| renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()); + + let swapchain_image_view = + window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone()); + + let pipeline_loader = PipelineLoader::new( + vulkan_device.clone(), + swapchain_image_view.format(), + depth_image_view.format(), + ); + + world.insert_resource(pipeline_loader); +} diff --git a/src/core/scene/manager.rs b/src/core/scene/manager.rs new file mode 100644 index 0000000..4bc82b3 --- /dev/null +++ b/src/core/scene/manager.rs @@ -0,0 +1,67 @@ +use std::error::Error; + +use crate::core::app::context::WindowContext; +use crate::core::input::InputManagerResource; +use crate::core::scene::AsScene; +use crate::core::scene::extract::{ + extract_pipeline_loader, extract_texture_loader, extract_vulkan_ressources, +}; +use bevy_ecs::world::World; + +use super::Scene; + +#[derive(Default)] +pub struct SceneManager { + current_scene: Option, + new_scene: Option>, +} + +impl SceneManager { + pub fn new() -> Self { + Self { + current_scene: None, + new_scene: None, + } + } + + fn create_world_with_resources(window_context: &mut WindowContext) -> World { + let mut world = World::new(); + + extract_vulkan_ressources(&mut world, window_context.vulkan_context()); + extract_texture_loader(&mut world, window_context.vulkan_context()); + extract_pipeline_loader(&mut world, window_context); + world.insert_resource(InputManagerResource(window_context.input_manager.clone())); + + world + } + + pub fn set_new_scene(&mut self, scene_impl: Box) { + self.new_scene = Some(scene_impl); + } + + pub fn current_scene(&self) -> Option<&Scene> { + self.current_scene.as_ref() + } + + pub fn current_scene_mut(&mut self) -> Option<&mut Scene> { + self.current_scene.as_mut() + } + + pub fn load_scene_if_not_loaded( + &mut self, + window_context: &mut WindowContext, + ) -> Result<(), Box> { + if let Some(new_scene) = self.new_scene.take() { + let world = Self::create_world_with_resources(window_context); + let mut scene = Scene::new(new_scene, world); + scene.load(window_context)?; + + if let Some(mut current_scene) = self.current_scene.take() { + current_scene.unload(); + } + + self.current_scene = Some(scene); + } + Ok(()) + } +} diff --git a/src/core/scene/mod.rs b/src/core/scene/mod.rs new file mode 100644 index 0000000..9f1c857 --- /dev/null +++ b/src/core/scene/mod.rs @@ -0,0 +1,74 @@ +use std::error::Error; + +use bevy_ecs::{schedule::Schedule, world::World}; +use vulkano::sync::GpuFuture; + +use crate::core::{app::context::WindowContext, scene::schedule::SceneScedule}; + +mod extract; +pub mod manager; +pub mod schedule; + +/// Structure Scene qui contient le world et l'implémentation AsScene +pub struct Scene { + pub world: World, + pub loop_schedule: Schedule, + pub implementation: Box, +} + +impl Scene { + pub fn new(implementation: Box, world: World) -> Self { + Self { + world, + loop_schedule: SceneScedule::base_schedule(), + implementation, + } + } + + pub fn loaded(&self) -> bool { + self.implementation.loaded() + } + + pub fn load(&mut self, window_context: &mut WindowContext) -> Result<(), Box> { + self.implementation.load(&mut self.world, window_context) + } + + pub fn update(&mut self, window_context: &WindowContext) -> Result<(), Box> { + self.implementation.update(&mut self.world, window_context) + } + + pub fn render( + &mut self, + acquire_future: Box, + window_context: &mut WindowContext, + ) -> Result, Box> { + self.implementation + .render(acquire_future, &mut self.world, window_context) + } + + pub fn unload(&mut self) { + self.implementation.unload() + } +} + +/// Trait pour les implémentations de scènes +pub trait AsScene { + fn loaded(&self) -> bool; + fn load( + &mut self, + world: &mut World, + window_context: &mut WindowContext, + ) -> Result<(), Box>; + fn update( + &mut self, + world: &mut World, + window_context: &WindowContext, + ) -> Result<(), Box>; + fn render( + &mut self, + acquire_future: Box, + world: &mut World, + window_context: &mut WindowContext, + ) -> Result, Box>; + fn unload(&mut self); +} diff --git a/src/core/scene/schedule.rs b/src/core/scene/schedule.rs new file mode 100644 index 0000000..9f1e97e --- /dev/null +++ b/src/core/scene/schedule.rs @@ -0,0 +1,24 @@ +use bevy_ecs::schedule::{IntoScheduleConfigs, Schedule, ScheduleLabel, SystemSet}; + +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +pub enum SceneSystems { + ExtractViews, + Update, + Render, + Present, +} + +#[derive(ScheduleLabel, Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct SceneScedule; + +impl SceneScedule { + pub fn base_schedule() -> Schedule { + use SceneSystems::*; + + let mut schedule = Schedule::new(Self); + + schedule.configure_sets((ExtractViews, Update, Render, Present).chain()); + + schedule + } +} diff --git a/src/game/assets/mod.rs b/src/game/assets/mod.rs new file mode 100644 index 0000000..81e613f --- /dev/null +++ b/src/game/assets/mod.rs @@ -0,0 +1 @@ +pub mod pipelines; diff --git a/src/game/assets/pipelines/mod.rs b/src/game/assets/pipelines/mod.rs new file mode 100644 index 0000000..b252f36 --- /dev/null +++ b/src/game/assets/pipelines/mod.rs @@ -0,0 +1 @@ +pub mod simple; diff --git a/src/game/assets/pipelines/simple.rs b/src/game/assets/pipelines/simple.rs new file mode 100644 index 0000000..6a114c8 --- /dev/null +++ b/src/game/assets/pipelines/simple.rs @@ -0,0 +1,178 @@ +use std::{error::Error, sync::Arc}; + +use vulkano::{ + command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer}, + descriptor_set::{ + allocator::StandardDescriptorSetAllocator, layout::DescriptorSetLayoutCreateInfo, + }, + device::Device, + format::Format, + pipeline::{ + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + PipelineShaderStageCreateInfo, + graphics::{ + GraphicsPipelineCreateInfo, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, + depth_stencil::{DepthState, DepthStencilState}, + input_assembly::InputAssemblyState, + multisample::MultisampleState, + rasterization::RasterizationState, + subpass::PipelineRenderingCreateInfo, + vertex_input::{Vertex, VertexDefinition}, + viewport::ViewportState, + }, + layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags}, + }, +}; + +use crate::core::render::{ + primitives::{ + AsDescriptorSet, AsDescriptorSetLayoutBindings, AsRecordable, AsRenderableMesh, + AsRenderableMeshInstance, mvp::Mvp, transform::TransformRaw, vertex::Vertex3D, + }, + resources::{pipeline::LoadableGraphicsPipeline, texture::Texture}, +}; + +pub struct SimplePipeline; + +impl LoadableGraphicsPipeline for SimplePipeline { + fn load( + device: &Arc, + swapchain_format: Format, + depth_format: Format, + ) -> Result, Box> { + let vs = shaders::vs::load(device.clone())? + .entry_point("main") + .ok_or("Failed find main entry point of vertex shader".to_string())?; + + let fs = shaders::fs::load(device.clone())? + .entry_point("main") + .ok_or("Failed find main entry point of fragment shader".to_string())?; + + let vertex_input_state = + [Vertex3D::per_vertex(), TransformRaw::per_instance()].definition(&vs)?; + + let stages = [ + PipelineShaderStageCreateInfo::new(vs), + PipelineShaderStageCreateInfo::new(fs), + ]; + + let mvp_bindings = Mvp::as_descriptor_set_layout_bindings(); + let texture_bindings = Texture::as_descriptor_set_layout_bindings(); + + let vertex_descriptor_set_layout = DescriptorSetLayoutCreateInfo { + bindings: mvp_bindings, + ..Default::default() + }; + + let fragment_descriptor_set_layout = DescriptorSetLayoutCreateInfo { + bindings: texture_bindings, + ..Default::default() + }; + + let create_info = PipelineDescriptorSetLayoutCreateInfo { + set_layouts: vec![vertex_descriptor_set_layout, fragment_descriptor_set_layout], + flags: PipelineLayoutCreateFlags::default(), + push_constant_ranges: vec![], + } + .into_pipeline_layout_create_info(device.clone())?; + + let layout = PipelineLayout::new(device.clone(), create_info)?; + + let subpass = PipelineRenderingCreateInfo { + color_attachment_formats: vec![Some(swapchain_format)], + depth_attachment_format: Some(depth_format), + ..Default::default() + }; + + let pipeline = GraphicsPipeline::new( + device.clone(), + None, + GraphicsPipelineCreateInfo { + stages: stages.into_iter().collect(), + vertex_input_state: Some(vertex_input_state), + input_assembly_state: Some(InputAssemblyState::default()), + viewport_state: Some(ViewportState::default()), + rasterization_state: Some(RasterizationState::default()), + multisample_state: Some(MultisampleState::default()), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.color_attachment_formats.len() as u32, + ColorBlendAttachmentState::default(), + )), + depth_stencil_state: Some(DepthStencilState { + depth: Some(DepthState::simple()), + ..Default::default() + }), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), + subpass: Some(subpass.into()), + ..GraphicsPipelineCreateInfo::layout(layout) + }, + )?; + + Ok(pipeline) + } + + fn pipeline_name() -> &'static str { + "SimplePipeline" + } +} + +impl AsRecordable for SimplePipeline { + fn record_bind_commands( + builder: &mut AutoCommandBufferBuilder, + descriptor_set_allocator: &Arc, + pipeline: &Arc, + mesh: &impl AsRenderableMesh, + instances: &impl AsRenderableMeshInstance, + descriptor_sets: Vec>, + ) -> Result<(), Box> { + builder.bind_pipeline_graphics(pipeline.clone())?; + + if !descriptor_sets.is_empty() { + let layouts = pipeline.layout().set_layouts(); + + let descriptor_sets = descriptor_sets + .iter() + .enumerate() + .map(|(layout_index, data)| { + data.as_descriptor_set(descriptor_set_allocator, &layouts[layout_index]) + }) + .collect::, _>>()?; + + builder.bind_descriptor_sets( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + descriptor_sets, + )?; + } + + builder.bind_vertex_buffers( + 0, + ( + mesh.vertex_buffer().clone(), + instances.instance_buffer().clone(), + ), + )?; + + Ok(()) + } +} + +pub mod shaders { + pub mod vs { + vulkano_shaders::shader! { + ty: "vertex", + path: r"res/shaders/simple.vert", + generate_structs: false, + } + } + + pub mod fs { + vulkano_shaders::shader! { + ty: "fragment", + path: r"res/shaders/simple.frag", + generate_structs: false, + } + } +} diff --git a/src/game/mod.rs b/src/game/mod.rs new file mode 100644 index 0000000..065e8e4 --- /dev/null +++ b/src/game/mod.rs @@ -0,0 +1,2 @@ +pub mod assets; +pub mod scenes; diff --git a/src/game/scenes/main_scene.rs b/src/game/scenes/main_scene.rs new file mode 100644 index 0000000..c500a82 --- /dev/null +++ b/src/game/scenes/main_scene.rs @@ -0,0 +1,491 @@ +use std::error::Error; +use std::sync::Arc; + +use super::settings_scene::SettingsScene; +use crate::core::app::DEPTH_IMAGE_ID; +use crate::core::app::context::WindowContext; +use crate::core::app::user_event::UserEvent; +use crate::core::input::InputManagerResource; +use crate::core::render::primitives::camera::{Camera3D, Camera3DTransform}; +use crate::core::render::primitives::transform::Transform; +use crate::core::render::primitives::velocity::Velocity; +use crate::core::render::primitives::{AsDescriptorSet, AsRecordable}; +use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager}; +use crate::core::render::resources::meshes::{ObjMesh, SquareMesh}; +use crate::core::render::resources::pipeline::PipelineLoader; +use crate::core::render::resources::texture::{TextureLoadInfo, TextureLoader, TextureSourceKind}; +use crate::core::render::resources::timer::Timer; +use crate::core::render::resources::vulkan::{ + VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanGraphicsQueue, + VulkanMemoryAllocator, +}; +use crate::core::scene::AsScene; +use crate::game::assets::pipelines::simple::SimplePipeline; +use bevy_ecs::prelude::*; +use bevy_ecs::schedule::Schedule; +use bevy_ecs::world::World; +use egui_winit_vulkano::egui; +use glam::EulerRot; +use glam::Quat; +use glam::Vec3; +use vulkano::format::Format; +use vulkano::image::sampler::{Filter, SamplerAddressMode, SamplerCreateInfo}; +use vulkano::{ + command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage}, + sync::GpuFuture, +}; +use winit::window::CursorGrabMode; + +#[derive(Component)] +pub struct Square; + +#[derive(Component)] +pub struct Cube; + +pub struct MainSceneState { + square: SquareMesh, + obj: ObjMesh, + scheduler: Schedule, +} + +#[derive(Resource)] +pub struct MovementSpeed(f32); + +#[derive(Resource)] +pub struct CameraSensitivity(f32); + +#[derive(Default)] +pub struct MainScene { + state: Option, +} + +impl AsScene for MainScene { + fn loaded(&self) -> bool { + self.state.is_some() + } + + fn load( + &mut self, + world: &mut World, + window_context: &mut WindowContext, + ) -> Result<(), Box> { + let mut pipeline_loader = world.resource_mut::(); + pipeline_loader.register::()?; + pipeline_loader.load_pending_pipelines()?; + + let mut texture_loader = world.resource_mut::(); + texture_loader.add_texture( + "wooden-crate".to_string(), + TextureLoadInfo { + source: TextureSourceKind::File("res/textures/wooden-crate.jpg".to_string()), + sampler_create_info: SamplerCreateInfo { + mag_filter: Filter::Linear, + min_filter: Filter::Linear, + address_mode: [SamplerAddressMode::Repeat; 3], + ..Default::default() + }, + image_format: Format::R8G8B8A8_SRGB, + }, + ); + texture_loader.add_texture( + "cube-diffuse".to_string(), + TextureLoadInfo { + source: TextureSourceKind::File("res/objects/cube-diffuse.jpg".to_string()), + sampler_create_info: SamplerCreateInfo { + mag_filter: Filter::Linear, + min_filter: Filter::Linear, + address_mode: [SamplerAddressMode::Repeat; 3], + ..Default::default() + }, + image_format: Format::R8G8B8A8_SRGB, + }, + ); + texture_loader.load_pending_textures()?; + + let square = SquareMesh::new(world.resource::())?; + + let obj = { + let obj = ObjMesh::new( + world.resource::(), + "res/objects/cube.obj", + )?; + obj.into_iter().next().unwrap() + }; + + world.spawn(( + Camera3D::new( + window_context.get_aspect_ratio(), + std::f32::consts::FRAC_PI_2, + 0.01, + 1000.0, + ), + Camera3DTransform { + position: Vec3::ZERO, + rotation: Vec3::ZERO, + }, + )); + + world.insert_resource(MovementSpeed(50.0)); + world.insert_resource(CameraSensitivity(10.0)); + + let mut scheduler = Schedule::default(); + scheduler.add_systems( + ( + update_camera_system, + update_velocity_system, + update_timer_system, + ) + .chain(), + ); + world.insert_resource(Timer::new()); + create_entities(world, 100, 10.0, 10.0); + + self.state = Some(MainSceneState { + square, + obj, + scheduler, + }); + + Ok(()) + } + + fn update( + &mut self, + world: &mut World, + window_context: &WindowContext, + ) -> Result<(), Box> { + let state = self.state.as_mut().unwrap(); + + { + let mut camera = world.query::<&mut Camera3D>().single_mut(world).unwrap(); + camera.update_projection(window_context.get_aspect_ratio()); + } + + { + let input_manager = world.resource::().0.read().unwrap(); + + if input_manager.get_virtual_input_state("mouse_left") > 0.0 { + let _ = window_context + .event_loop_proxy + .send_event(UserEvent::CursorVisible(window_context.window_id, false)); + let _ = window_context + .event_loop_proxy + .send_event(UserEvent::CursorGrabMode( + window_context.window_id, + CursorGrabMode::Locked, + )); + } + + if input_manager.get_virtual_input_state("mouse_right") > 0.0 { + let _ = window_context + .event_loop_proxy + .send_event(UserEvent::CursorVisible(window_context.window_id, true)); + let _ = window_context + .event_loop_proxy + .send_event(UserEvent::CursorGrabMode( + window_context.window_id, + CursorGrabMode::None, + )); + } + } + + state.scheduler.run(world); + + Ok(()) + } + + fn render( + &mut self, + before_future: Box, + world: &mut World, + window_context: &mut WindowContext, + ) -> Result, Box> { + let state = self.state.as_mut().ok_or("State not loaded")?; + + let mut builder = AutoCommandBufferBuilder::primary( + (*world.resource::()).clone(), + world.resource::().queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + )?; + + { + let swapchain_image_view = + window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone()); + let depth_image_view = window_context.with_renderer_mut(|renderer| { + renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone() + }); + let config = RenderPassConfig::default(); + RenderPassManager::begin_standard_rendering( + &mut builder, + &config, + swapchain_image_view, + Some(depth_image_view), + window_context.get_window_size(), + )?; + } + + // Create camera uniform using the actual camera + let camera_uniform = { + let result = world + .query_filtered::<(&Camera3D, &Camera3DTransform), With>() + .single(&world) + .unwrap(); + + Arc::new( + result + .0 + .create_buffer(result.1, world.resource::())?, + ) + }; + let square_transforms = world + .query_filtered::<&Transform, With>() + .iter(&world) + .cloned() + .collect::>(); + let square_transform_uniform = Transform::create_buffer( + world.resource::(), + &square_transforms, + )?; + let cube_transforms = world + .query_filtered::<&Transform, With>() + .iter(&world) + .cloned() + .collect::>(); + let cube_transform_uniform = + Transform::create_buffer(world.resource::(), &cube_transforms)?; + + let texture_loader = world.resource::(); + let pipeline_loader = world.resource::(); + + pipeline_loader.with_pipeline::(|pipeline| { + SimplePipeline::record_commands( + &mut builder, + world.resource::(), + pipeline, + &state.square, + &square_transform_uniform, + vec![ + camera_uniform.clone() as Arc, + texture_loader.get_texture("wooden-crate").unwrap().clone(), + ], + )?; + + SimplePipeline::record_commands( + &mut builder, + world.resource::(), + pipeline, + &state.obj, + &cube_transform_uniform, + vec![ + camera_uniform.clone() as Arc, + texture_loader.get_texture("cube-diffuse").unwrap().clone(), + ], + )?; + + Ok(()) + })?; + + RenderPassManager::end_rendering(&mut builder)?; + + let command_buffer = builder.build()?; + + let render_future = before_future.then_execute( + (*world.resource::()).clone(), + command_buffer, + )?; + + let swapchain_image_view = + window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone()); + let input_manager_status = { + let input_manager = world.resource::().0.read().unwrap(); + format!("{:#?}", input_manager) + }; + let event_loop_proxy = window_context.event_loop_proxy.clone(); + let delta_time = world.resource::().delta_time(); + let window_id = window_context.window_id; + let window_size = window_context.get_window_size(); + let camera_transform = world + .query_filtered::<&Camera3DTransform, With>() + .single(&world) + .unwrap(); + let render_future = window_context.with_gui_mut(|gui| { + gui.immediate_ui(|gui| { + let ctx = gui.context(); + egui::TopBottomPanel::top("top_panel").show(&ctx, |ui| { + ui.horizontal(|ui| { + ui.heading("Vulkan Test - Moteur 3D"); + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + if ui.button("Paramètres").clicked() { + let _ = event_loop_proxy.send_event(UserEvent::ChangeScene( + window_id, + Box::new(SettingsScene::default()), + )); + } + if ui.button("Quitter").clicked() { + let _ = event_loop_proxy.send_event(UserEvent::Exit(window_id)); + } + }); + }); + }); + + egui::SidePanel::left("side_panel").show(&ctx, |ui| { + ui.heading("Informations"); + + ui.separator(); + + ui.label(format!("Résolution: {:?}", window_size)); + ui.label(format!("Delta Time: {:.2}ms", delta_time * 1000.0)); + + ui.separator(); + + ui.label("Position caméra:"); + let position = camera_transform.position; + ui.label(format!(" X: {:.2}", position[0])); + ui.label(format!(" Y: {:.2}", position[1])); + ui.label(format!(" Z: {:.2}", position[2])); + + ui.separator(); + + ui.label("Rotation caméra:"); + let rotation = camera_transform.rotation; + ui.label(format!(" Yaw: {:.2}°", rotation.y.to_degrees())); + ui.label(format!(" Pitch: {:.2}°", rotation.x.to_degrees())); + + ui.separator(); + + ui.label(input_manager_status); + }); + }); + + gui.draw_on_image(render_future, swapchain_image_view.clone()) + }); + + Ok(Box::new(render_future)) + } + + fn unload(&mut self) { + self.state = None; + } +} + +fn create_entities( + world: &mut World, + num_instances: u32, + instance_size: f32, + instance_spacing: f32, +) { + let num_instances_per_row = (num_instances as f32 / instance_spacing).ceil() as u32; + + let square_instances = (0..num_instances) + .map(|i| { + let x_index = i % num_instances_per_row; + let z_index = i / num_instances_per_row; + + let transform = Transform::new( + Vec3::new( + x_index as f32 * (instance_spacing + instance_size), + 0.0, + z_index as f32 * (instance_spacing + instance_size), + ), + Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0), + Vec3::new(instance_size, instance_size, instance_size), + ); + + let velocity = Velocity::new(Vec3::ZERO, Vec3::new(0.0, x_index as f32, 0.0)); + + (Square, transform, velocity) + }) + .collect::>(); + + world.spawn_batch(square_instances); + + let cube_instances = (0..num_instances) + .map(|i| { + let x_index = i % num_instances_per_row; + let z_index = i / num_instances_per_row; + + let transform = Transform::new( + Vec3::new( + x_index as f32 * (instance_spacing + instance_size), + 0.0, + z_index as f32 * (instance_spacing + instance_size) * -1.0 + - instance_spacing * 2.0, + ), + Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0), + Vec3::new( + instance_size * 0.5, + instance_size * 0.5, + instance_size * 0.5, + ), + ); + + let velocity = Velocity::new(Vec3::ZERO, Vec3::new(0.0, x_index as f32, 0.0)); + + (Cube, transform, velocity) + }) + .collect::>(); + + world.spawn_batch(cube_instances); +} + +fn update_velocity_system(mut query: Query<(&mut Transform, &Velocity)>, time: Res) { + for (mut transform, velocity) in query.iter_mut() { + let delta_time = time.delta_time(); + + // Update linear position + transform.position += velocity.linear * delta_time; + + // Update angular rotation + let angular_delta = velocity.angular * delta_time; + let rotation_delta = Quat::from_euler( + EulerRot::XYZ, + angular_delta.x, + angular_delta.y, + angular_delta.z, + ); + transform.rotation *= rotation_delta; + } +} + +fn update_timer_system(mut timer: ResMut) { + timer.update(); +} + +fn update_camera_system( + mut query: Query<&mut Camera3DTransform, With>, + input_manager: Res, + camera_sensitivity: Res, + movement_speed: Res, + time: Res, +) { + let input_manager = input_manager.0.read().unwrap(); + let mut camera_transform = query.single_mut().unwrap(); + + let delta_time = time.delta_time(); + + camera_transform.rotation += Vec3::new( + (input_manager.get_virtual_input_state("mouse_y") * camera_sensitivity.0 * delta_time) + .to_radians(), + (input_manager.get_virtual_input_state("mouse_x") * camera_sensitivity.0 * delta_time) + .to_radians(), + 0.0, + ); + + if camera_transform.rotation.x > std::f32::consts::FRAC_PI_2 { + camera_transform.rotation.x = std::f32::consts::FRAC_PI_2; + } + + if camera_transform.rotation.x < -std::f32::consts::FRAC_PI_2 { + camera_transform.rotation.x = -std::f32::consts::FRAC_PI_2; + } + + let (yaw_sin, yaw_cos) = camera_transform.rotation.y.sin_cos(); + let forward = Vec3::new(yaw_cos, 0.0, yaw_sin).normalize(); + let right = Vec3::new(-yaw_sin, 0.0, yaw_cos).normalize(); + + let tx = input_manager.get_virtual_input_state("move_right") * movement_speed.0 * delta_time; + camera_transform.position += tx * right; + + let tz = input_manager.get_virtual_input_state("move_forward") * movement_speed.0 * delta_time; + camera_transform.position += tz * forward; +} diff --git a/src/game/scenes/mod.rs b/src/game/scenes/mod.rs new file mode 100644 index 0000000..516fa6f --- /dev/null +++ b/src/game/scenes/mod.rs @@ -0,0 +1,2 @@ +pub mod main_scene; +pub mod settings_scene; diff --git a/src/game/scenes/settings_scene.rs b/src/game/scenes/settings_scene.rs new file mode 100644 index 0000000..24aaccd --- /dev/null +++ b/src/game/scenes/settings_scene.rs @@ -0,0 +1,151 @@ +use std::error::Error; + +use crate::core::app::DEPTH_IMAGE_ID; +use crate::core::app::context::WindowContext; +use crate::core::app::user_event::UserEvent; +use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager}; +use crate::core::render::resources::vulkan::{VulkanCommandBufferAllocator, VulkanGraphicsQueue}; +use crate::core::scene::AsScene; +use bevy_ecs::world::World; +use egui_winit_vulkano::egui; +use vulkano::{ + command_buffer::AutoCommandBufferBuilder, command_buffer::CommandBufferUsage, sync::GpuFuture, +}; + +use super::main_scene::MainScene; + +pub struct SettingsSceneState { + current_resolution: [f32; 2], + available_resolutions: Vec<(u32, u32)>, +} + +#[derive(Default)] +pub struct SettingsScene { + state: Option, +} + +impl AsScene for SettingsScene { + fn loaded(&self) -> bool { + self.state.is_some() + } + + fn load( + &mut self, + _world: &mut World, + window_context: &mut WindowContext, + ) -> Result<(), Box> { + let current_resolution = window_context.get_window_size(); + let available_resolutions = window_context.get_available_resolutions(); + + self.state = Some(SettingsSceneState { + current_resolution, + available_resolutions, + }); + + Ok(()) + } + + fn update( + &mut self, + _world: &mut World, + _window_context: &WindowContext, + ) -> Result<(), Box> { + Ok(()) + } + + fn render( + &mut self, + before_future: Box, + world: &mut World, + window_context: &mut WindowContext, + ) -> Result, Box> { + let state = self.state.as_ref().ok_or("State not found")?; + + let mut builder = AutoCommandBufferBuilder::primary( + (*world.resource::()).clone(), + world.resource::().queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + )?; + + // Utiliser le RenderPassManager + { + let swapchain_image_view = + window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone()); + let depth_stencil_image_view = window_context.with_renderer_mut(|renderer| { + renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone() + }); + + let config = RenderPassConfig::default(); + RenderPassManager::begin_standard_rendering( + &mut builder, + &config, + swapchain_image_view, + Some(depth_stencil_image_view), + window_context.get_window_size(), + )?; + } + + // Pas de géométrie dans cette scène - juste un écran de paramètres + RenderPassManager::end_rendering(&mut builder)?; + + let command_buffer = builder.build()?; + + let render_future = before_future.then_execute( + (*world.resource::()).clone(), + command_buffer, + )?; + + let swapchain_image_view = + window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone()); + + let event_loop_proxy = window_context.event_loop_proxy.clone(); + let window_id = window_context.window_id; + + let render_future = window_context.with_gui_mut(|gui| { + gui.immediate_ui(|gui| { + let ctx = gui.context(); + + egui::CentralPanel::default().show(&ctx, |ui| { + ui.heading("Paramètres"); + + ui.separator(); + + ui.label(format!( + "Résolution actuelle: {:?}", + state.current_resolution + )); + + ui.separator(); + ui.label("Changer la résolution:"); + + for &(width, height) in &state.available_resolutions { + if ui.button(format!("{}x{}", width, height)).clicked() { + let _ = event_loop_proxy.send_event(UserEvent::ChangeResolution( + window_id, + width as f32, + height as f32, + )); + } + } + + ui.separator(); + + if ui.button("Retour au jeu").clicked() { + let _ = event_loop_proxy.send_event(UserEvent::ChangeScene( + window_id, + Box::new(MainScene::default()), + )); + } + }); + }); + + gui.draw_on_image(render_future, swapchain_image_view.clone()) + }); + + Ok(Box::new(render_future)) + } + + fn unload(&mut self) { + self.state = None; + } +} diff --git a/src/main.rs b/src/main.rs index 6c01c40..998f725 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,108 @@ -use std::error::Error; -use winit::event_loop::{ControlFlow, EventLoop}; +use core::input::{AxisDirection, InputManager, VirtualBinding}; +use std::collections::HashMap; -mod renderer; +use vulkano::device::{DeviceExtensions, DeviceFeatures}; +use vulkano_util::context::{VulkanoConfig, VulkanoContext}; +use winit::{ + event::MouseButton, + event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, +}; -fn main() -> Result<(), impl Error> { - env_logger::init(); +mod core; +mod game; - let event_loop = EventLoop::new().unwrap(); +fn main() { + use tracing_subscriber::layer::SubscriberExt; + use tracing_subscriber::util::SubscriberInitExt; + + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_target(true) + .with_thread_ids(true) + .with_file(true) + .with_line_number(true), + ) + .with(tracing_tracy::TracyLayer::default()) + .with( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), + ) + .init(); + + let input_manager = InputManager::new(HashMap::from([ + ( + "move_forward".to_string(), + vec![ + VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyW), AxisDirection::Normal), + VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyS), AxisDirection::Invert), + ], + ), + ( + "move_right".to_string(), + vec![ + VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyD), AxisDirection::Normal), + VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyA), AxisDirection::Invert), + ], + ), + ( + "mouse_x".to_string(), + vec![VirtualBinding::MouseX(AxisDirection::Normal)], + ), + ( + "mouse_y".to_string(), + vec![VirtualBinding::MouseY(AxisDirection::Normal)], + ), + ( + "mouse_wheel".to_string(), + vec![VirtualBinding::MouseWheelY(AxisDirection::Normal)], + ), + ( + "mouse_left".to_string(), + vec![VirtualBinding::MouseButton( + MouseButton::Left, + AxisDirection::Normal, + )], + ), + ( + "mouse_right".to_string(), + vec![VirtualBinding::MouseButton( + MouseButton::Right, + AxisDirection::Normal, + )], + ), + ])); + + let device_extensions = DeviceExtensions { + khr_swapchain: true, + ..Default::default() + }; + + let device_features = DeviceFeatures { + dynamic_rendering: true, + ..Default::default() + }; + + let vulkano_config = VulkanoConfig { + print_device_name: true, + device_extensions, + device_features, + ..Default::default() + }; + + let vulkano_context = VulkanoContext::new(vulkano_config); + + let event_loop = EventLoop::with_user_event().build().unwrap(); event_loop.set_control_flow(ControlFlow::Poll); + let proxy = event_loop.create_proxy(); - let mut app = renderer::App::new(&event_loop); + let mut app = core::app::App::new(vulkano_context, input_manager, proxy); - event_loop.run_app(&mut app) + match event_loop.run_app(&mut app) { + Ok(_) => {} + Err(e) => { + tracing::error!("Error running old app: {e}"); + } + } } diff --git a/src/renderer/app.rs b/src/renderer/app.rs deleted file mode 100644 index f791616..0000000 --- a/src/renderer/app.rs +++ /dev/null @@ -1,295 +0,0 @@ -use crate::renderer::render_context::RenderContext; -use crate::renderer::Scene; -use std::sync::Arc; -use vulkano::buffer::allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}; -use vulkano::buffer::BufferUsage; -use vulkano::command_buffer::allocator::StandardCommandBufferAllocator; -use vulkano::command_buffer::{ - AutoCommandBufferBuilder, CommandBufferUsage, RenderingAttachmentInfo, RenderingInfo, -}; -use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator; -use vulkano::device::physical::PhysicalDeviceType; -use vulkano::device::{ - Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures, Queue, QueueCreateInfo, QueueFlags, -}; -use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo}; -use vulkano::memory::allocator::{MemoryTypeFilter, StandardMemoryAllocator}; -use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp}; -use vulkano::swapchain::{acquire_next_image, Surface, SwapchainPresentInfo}; -use vulkano::sync::GpuFuture; -use vulkano::{sync, Validated, Version, VulkanError, VulkanLibrary}; -use winit::application::ApplicationHandler; -use winit::event::WindowEvent; -use winit::event_loop::{ActiveEventLoop, EventLoop}; -use winit::window::WindowId; - -pub struct App { - pub instance: Arc, - pub device: Arc, - pub queue: Arc, - - pub memory_allocator: Arc, - pub command_buffer_allocator: Arc, - pub uniform_buffer_allocator: SubbufferAllocator, - pub descriptor_set_allocator: Arc, - - pub rcx: Option, - scene: Option, -} - -impl App { - pub fn new(event_loop: &EventLoop<()>) -> Self { - let library = VulkanLibrary::new().unwrap(); - - for layer in library.layer_properties().unwrap() { - log::debug!("Available layer: {}", layer.name()); - } - - let required_extensions = Surface::required_extensions(event_loop).unwrap(); - - let instance = Instance::new( - library, - InstanceCreateInfo { - // Enable enumerating devices that use non-conformant Vulkan implementations. - // (e.g. MoltenVK) - flags: InstanceCreateFlags::ENUMERATE_PORTABILITY, - enabled_extensions: required_extensions, - enabled_layers: vec![String::from("VK_LAYER_KHRONOS_validation")], - ..Default::default() - }, - ) - .unwrap(); - - let mut device_extensions = DeviceExtensions { - khr_swapchain: true, - ..DeviceExtensions::empty() - }; - - let (physical_device, queue_family_index) = instance - .enumerate_physical_devices() - .unwrap() - .filter(|p| { - p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering - }) - .filter(|p| p.supported_extensions().contains(&device_extensions)) - .filter_map(|p| { - p.queue_family_properties() - .iter() - .enumerate() - .position(|(i, q)| { - q.queue_flags.intersects(QueueFlags::GRAPHICS) - && p.presentation_support(i as u32, event_loop).unwrap() - }) - .map(|i| (p, i as u32)) - }) - .min_by_key(|(p, _)| match p.properties().device_type { - PhysicalDeviceType::DiscreteGpu => 0, - PhysicalDeviceType::IntegratedGpu => 1, - PhysicalDeviceType::VirtualGpu => 2, - PhysicalDeviceType::Cpu => 3, - PhysicalDeviceType::Other => 4, - _ => 5, - }) - .expect("no suitable physical device found"); - - log::debug!( - "Using device: {} (type: {:?})", - physical_device.properties().device_name, - physical_device.properties().device_type, - ); - - if physical_device.api_version() < Version::V1_3 { - device_extensions.khr_dynamic_rendering = true; - } - - log::debug!("Using device extensions: {:#?}", device_extensions); - - let (device, mut queues) = Device::new( - physical_device, - DeviceCreateInfo { - queue_create_infos: vec![QueueCreateInfo { - queue_family_index, - ..Default::default() - }], - enabled_extensions: device_extensions, - enabled_features: DeviceFeatures { - dynamic_rendering: true, - ..DeviceFeatures::empty() - }, - ..Default::default() - }, - ) - .unwrap(); - - let queue = queues.next().unwrap(); - let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone())); - - let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new( - device.clone(), - Default::default(), - )); - - let uniform_buffer_allocator = SubbufferAllocator::new( - memory_allocator.clone(), - SubbufferAllocatorCreateInfo { - buffer_usage: BufferUsage::UNIFORM_BUFFER, - memory_type_filter: MemoryTypeFilter::PREFER_DEVICE - | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, - ..Default::default() - }, - ); - - let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( - device.clone(), - Default::default(), - )); - - Self { - instance, - device, - queue, - memory_allocator, - command_buffer_allocator, - uniform_buffer_allocator, - descriptor_set_allocator, - rcx: None, - scene: None, - } - } -} - -impl ApplicationHandler for App { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { - let window_attributes = winit::window::Window::default_attributes() - .with_title("Rust ASH Test") - .with_inner_size(winit::dpi::PhysicalSize::new( - f64::from(800), - f64::from(600), - )); - - let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); - - let surface = Surface::from_window(self.instance.clone(), window.clone()).unwrap(); - - self.rcx = Some(RenderContext::new(window, surface, &self.device)); - self.scene = Some(Scene::load(&self).unwrap()); - } - - fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { - match event { - WindowEvent::CloseRequested => { - log::debug!("The close button was pressed; stopping"); - event_loop.exit(); - } - WindowEvent::Resized(_) => { - let rcx = self.rcx.as_mut().unwrap(); - rcx.recreate_swapchain = true; - } - WindowEvent::RedrawRequested => { - let (image_index, acquire_future) = { - let rcx = self.rcx.as_mut().unwrap(); - let window_size = rcx.window.inner_size(); - - if window_size.width == 0 || window_size.height == 0 { - return; - } - - rcx.previous_frame_end.as_mut().unwrap().cleanup_finished(); - rcx.update_swapchain().unwrap(); - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(rcx.swapchain.clone(), None) - .map_err(Validated::unwrap) - { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - rcx.recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { - rcx.recreate_swapchain = true; - } - - (image_index, acquire_future) - }; - - let mut builder = AutoCommandBufferBuilder::primary( - self.command_buffer_allocator.clone(), - self.queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - - { - let rcx = self.rcx.as_ref().unwrap(); - builder - .begin_rendering(RenderingInfo { - color_attachments: vec![Some(RenderingAttachmentInfo { - load_op: AttachmentLoadOp::Clear, - store_op: AttachmentStoreOp::Store, - clear_value: Some([0.0, 0.0, 0.0, 1.0].into()), - ..RenderingAttachmentInfo::image_view( - rcx.attachment_image_views[image_index as usize].clone(), - ) - })], - ..Default::default() - }) - .unwrap() - .set_viewport(0, [rcx.viewport.clone()].into_iter().collect()) - .unwrap(); - } - - if let Some(scene) = self.scene.as_ref() { - scene.render(&self, &mut builder).unwrap(); - } - - builder.end_rendering().unwrap(); - - let command_buffer = builder.build().unwrap(); - - { - let rcx = self.rcx.as_mut().unwrap(); - - let future = rcx - .previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(self.queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - self.queue.clone(), - SwapchainPresentInfo::swapchain_image_index( - rcx.swapchain.clone(), - image_index, - ), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - rcx.previous_frame_end = Some(future.boxed()); - } - Err(VulkanError::OutOfDate) => { - rcx.recreate_swapchain = true; - rcx.previous_frame_end = Some(sync::now(self.device.clone()).boxed()); - } - Err(e) => { - println!("failed to flush future: {e}"); - rcx.previous_frame_end = Some(sync::now(self.device.clone()).boxed()); - } - } - } - } - _ => {} - } - } - - fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { - let rcx = self.rcx.as_mut().unwrap(); - rcx.window.request_redraw(); - } -} diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs deleted file mode 100644 index bbcff9a..0000000 --- a/src/renderer/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod app; -mod pipelines; -mod render_context; -mod vertex; -pub use app::App; - -mod scene; -pub use scene::Scene; -pub use vertex::Vertex2D; diff --git a/src/renderer/pipelines/mod.rs b/src/renderer/pipelines/mod.rs deleted file mode 100644 index e5f30a7..0000000 --- a/src/renderer/pipelines/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod triangle_pipeline; diff --git a/src/renderer/pipelines/triangle_pipeline.rs b/src/renderer/pipelines/triangle_pipeline.rs deleted file mode 100644 index f6001f7..0000000 --- a/src/renderer/pipelines/triangle_pipeline.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::collections::BTreeMap; -use std::error::Error; -use std::sync::Arc; -use vulkano::descriptor_set::layout::{ - DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType, -}; -use vulkano::device::Device; -use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState}; -use vulkano::pipeline::graphics::input_assembly::InputAssemblyState; -use vulkano::pipeline::graphics::multisample::MultisampleState; -use vulkano::pipeline::graphics::rasterization::RasterizationState; -use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo; -use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition}; -use vulkano::pipeline::graphics::viewport::ViewportState; -use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo; -use vulkano::pipeline::layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags}; -use vulkano::pipeline::{ - DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, -}; -use vulkano::shader::{EntryPoint, ShaderStages}; -use vulkano::swapchain::Swapchain; - -use crate::renderer::Vertex2D; - -pub mod shaders { - pub mod vs { - vulkano_shaders::shader! { - ty: "vertex", - path: r"res/shaders/vertex.vert", - } - } - - pub mod fs { - vulkano_shaders::shader! { - ty: "fragment", - path: r"res/shaders/vertex.frag", - } - } -} - -pub fn create_triangle_pipeline( - device: &Arc, - swapchain: &Arc, -) -> Result, Box> { - let (vs, fs) = load_shaders(device)?; - let vertex_input_state = Vertex2D::per_vertex().definition(&vs)?; - - let stages = [ - PipelineShaderStageCreateInfo::new(vs), - PipelineShaderStageCreateInfo::new(fs), - ]; - - let mut bindings = BTreeMap::::new(); - let mut descriptor_set_layout_binding = - DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer); - descriptor_set_layout_binding.stages = ShaderStages::VERTEX; - bindings.insert(0, descriptor_set_layout_binding); - - let descriptor_set_layout = DescriptorSetLayoutCreateInfo { - bindings, - ..Default::default() - }; - - let create_info = PipelineDescriptorSetLayoutCreateInfo { - set_layouts: vec![descriptor_set_layout], - flags: PipelineLayoutCreateFlags::default(), - push_constant_ranges: vec![], - } - .into_pipeline_layout_create_info(device.clone())?; - - let layout = PipelineLayout::new(device.clone(), create_info)?; - - let subpass = PipelineRenderingCreateInfo { - color_attachment_formats: vec![Some(swapchain.image_format())], - ..Default::default() - }; - - let pipeline = GraphicsPipeline::new( - device.clone(), - None, - GraphicsPipelineCreateInfo { - stages: stages.into_iter().collect(), - vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::default()), - rasterization_state: Some(RasterizationState::default()), - multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::with_attachment_states( - subpass.color_attachment_formats.len() as u32, - ColorBlendAttachmentState::default(), - )), - dynamic_state: [DynamicState::Viewport].into_iter().collect(), - subpass: Some(subpass.into()), - ..GraphicsPipelineCreateInfo::layout(layout) - }, - )?; - - Ok(pipeline) -} - -fn load_shaders(device: &Arc) -> Result<(EntryPoint, EntryPoint), Box> { - let vs = shaders::vs::load(device.clone())? - .entry_point("main") - .ok_or("Failed find main entry point of vertex shader".to_string())?; - - let fs = shaders::fs::load(device.clone())? - .entry_point("main") - .ok_or("Failed find main entry point of fragment shader".to_string())?; - - Ok((vs, fs)) -} diff --git a/src/renderer/render_context.rs b/src/renderer/render_context.rs deleted file mode 100644 index dd7e840..0000000 --- a/src/renderer/render_context.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::sync::Arc; -use vulkano::device::Device; -use vulkano::image::view::ImageView; -use vulkano::image::{Image, ImageUsage}; -use vulkano::pipeline::graphics::viewport::Viewport; -use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo}; -use vulkano::sync::GpuFuture; -use vulkano::{sync, Validated, VulkanError}; -use winit::window::Window; - -pub struct RenderContext { - pub(super) window: Arc, - pub(super) swapchain: Arc, - pub(super) attachment_image_views: Vec>, - pub(super) viewport: Viewport, - pub(super) recreate_swapchain: bool, - pub(super) previous_frame_end: Option>, -} - -impl RenderContext { - pub fn new(window: Arc, surface: Arc, device: &Arc) -> Self { - let window_size = window.inner_size(); - - let (swapchain, images) = { - let surface_capabilities = device - .physical_device() - .surface_capabilities(&surface, Default::default()) - .unwrap(); - - let (image_format, _) = device - .physical_device() - .surface_formats(&surface, Default::default()) - .unwrap()[0]; - - Swapchain::new( - device.clone(), - surface, - SwapchainCreateInfo { - // 2 because with some graphics driver, it crash on fullscreen because fullscreen need to min image to works. - min_image_count: surface_capabilities.min_image_count.max(2), - image_format, - image_extent: window_size.into(), - image_usage: ImageUsage::COLOR_ATTACHMENT, - composite_alpha: surface_capabilities - .supported_composite_alpha - .into_iter() - .next() - .unwrap(), - - ..Default::default() - }, - ) - .unwrap() - }; - - let attachment_image_views = window_size_dependent_setup(&images); - - let viewport = Viewport { - offset: [0.0, 0.0], - extent: window_size.into(), - depth_range: 0.0..=1.0, - }; - - let recreate_swapchain = false; - let previous_frame_end = Some(sync::now(device.clone()).boxed()); - - Self { - window, - swapchain, - attachment_image_views, - viewport, - recreate_swapchain, - previous_frame_end, - } - } - - pub fn update_swapchain(&mut self) -> Result<(), Validated> { - if !self.recreate_swapchain { - return Ok(()); - } - - let window_size = self.window.inner_size(); - let (new_swapchain, new_images) = self.swapchain.recreate(SwapchainCreateInfo { - image_extent: window_size.into(), - ..self.swapchain.create_info() - })?; - - self.swapchain = new_swapchain; - self.attachment_image_views = window_size_dependent_setup(&new_images); - self.viewport.extent = window_size.into(); - self.recreate_swapchain = false; - - Ok(()) - } -} - -fn window_size_dependent_setup(images: &[Arc]) -> Vec> { - images - .iter() - .map(|image| ImageView::new_default(image.clone()).unwrap()) - .collect::>() -} diff --git a/src/renderer/scene.rs b/src/renderer/scene.rs deleted file mode 100644 index e3c6b58..0000000 --- a/src/renderer/scene.rs +++ /dev/null @@ -1,151 +0,0 @@ -use crate::renderer::pipelines::triangle_pipeline::shaders::vs; -use glam::{Mat3, Mat4, Vec3}; -use std::error::Error; -use std::sync::Arc; -use std::time::Instant; -use vulkano::buffer::Subbuffer; -use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer}; -use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet}; -use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint}; - -use crate::renderer::{pipelines::triangle_pipeline::create_triangle_pipeline, App, Vertex2D}; - -const VERTICES: [Vertex2D; 12] = [ - // Triangle en haut à gauche - Vertex2D { - position: [-0.5, -0.75], - color: [1.0, 0.0, 0.0], - }, - Vertex2D { - position: [-0.75, -0.25], - color: [0.0, 1.0, 0.0], - }, - Vertex2D { - position: [-0.25, -0.25], - color: [0.0, 0.0, 1.0], - }, - // Triangle en bas à gauche - Vertex2D { - position: [-0.5, 0.25], - color: [0.5, 0.5, 0.5], - }, - Vertex2D { - position: [-0.75, 0.75], - color: [0.2, 0.8, 0.2], - }, - Vertex2D { - position: [-0.25, 0.75], - color: [0.8, 0.2, 0.2], - }, - // Triangle en haut à droite - Vertex2D { - position: [0.5, -0.75], - color: [1.0, 1.0, 0.0], - }, - Vertex2D { - position: [0.25, -0.25], - color: [0.0, 1.0, 1.0], - }, - Vertex2D { - position: [0.75, -0.25], - color: [1.0, 0.0, 1.0], - }, - // Triangle en bas à droite - Vertex2D { - position: [0.5, 0.25], - color: [0.1, 0.5, 0.8], - }, - Vertex2D { - position: [0.25, 0.75], - color: [0.8, 0.6, 0.1], - }, - Vertex2D { - position: [0.75, 0.75], - color: [0.3, 0.4, 0.6], - }, -]; - -pub struct Scene { - pipeline: Arc, - vertex_buffer: Subbuffer<[Vertex2D]>, - - rotation_start: Instant, -} - -impl Scene { - pub fn load(app: &App) -> Result> { - let pipeline = create_triangle_pipeline(&app.device, &app.rcx.as_ref().unwrap().swapchain)?; - let vertex_buffer = - Vertex2D::create_buffer(Vec::from_iter(VERTICES), &app.memory_allocator)?; - - Ok(Scene { - pipeline, - vertex_buffer, - rotation_start: Instant::now(), - }) - } - - pub fn render( - &self, - app: &App, - builder: &mut AutoCommandBufferBuilder, - ) -> Result<(), Box> { - let vertex_count = self.vertex_buffer.len() as u32; - let instance_count = vertex_count / 3; - - let uniform_buffer = self.get_uniform_buffer(app); - let layout = &self.pipeline.layout().set_layouts()[0]; - let descriptor_set = DescriptorSet::new( - app.descriptor_set_allocator.clone(), - layout.clone(), - [WriteDescriptorSet::buffer(0, uniform_buffer)], - [], - ) - .unwrap(); - - unsafe { - builder - .bind_pipeline_graphics(self.pipeline.clone())? - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - self.pipeline.layout().clone(), - 0, - descriptor_set, - )? - .bind_vertex_buffers(0, self.vertex_buffer.clone())? - .draw(vertex_count, instance_count, 0, 0)?; - } - - Ok(()) - } - - fn get_uniform_buffer(&self, app: &App) -> Subbuffer { - let swapchain = &app.rcx.as_ref().unwrap().swapchain; - let elapsed = self.rotation_start.elapsed(); - let rotation = elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000.0; - let rotation = Mat3::from_rotation_y(rotation as f32); - - // NOTE: This teapot was meant for OpenGL where the origin is at the lower left - // instead the origin is at the upper left in Vulkan, so we reverse the Y axis. - let aspect_ratio = swapchain.image_extent()[0] as f32 / swapchain.image_extent()[1] as f32; - - let proj = Mat4::perspective_rh_gl(std::f32::consts::FRAC_PI_2, aspect_ratio, 0.01, 100.0); - let view = Mat4::look_at_rh( - Vec3::new(0.3, 0.3, 1.0), - Vec3::new(0.0, 0.0, 0.0), - Vec3::new(0.0, -1.0, 0.0), - ); - let scale = Mat4::from_scale(Vec3::splat(1.0)); - - let uniform_data = vs::MVPData { - world: Mat4::from_mat3(rotation).to_cols_array_2d(), - view: (view * scale).to_cols_array_2d(), - projection: proj.to_cols_array_2d(), - }; - - let buffer = app.uniform_buffer_allocator.allocate_sized().unwrap(); - *buffer.write().unwrap() = uniform_data; - - buffer - } -} diff --git a/src/renderer/vertex.rs b/src/renderer/vertex.rs deleted file mode 100644 index fc2ee21..0000000 --- a/src/renderer/vertex.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::sync::Arc; -use vulkano::buffer::{ - AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer, -}; -use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}; -use vulkano::pipeline::graphics::vertex_input::Vertex; -use vulkano::Validated; - -#[derive(BufferContents, Vertex)] -#[repr(C)] -pub struct Vertex2D { - #[format(R32G32_SFLOAT)] - pub position: [f32; 2], - - #[format(R32G32B32_SFLOAT)] - pub color: [f32; 3], -} - -impl Vertex2D { - pub fn create_buffer( - vertices: Vec, - memory_allocator: &Arc, - ) -> Result, Validated> { - Buffer::from_iter( - memory_allocator.clone(), - BufferCreateInfo { - usage: BufferUsage::VERTEX_BUFFER, - ..Default::default() - }, - AllocationCreateInfo { - memory_type_filter: MemoryTypeFilter::PREFER_DEVICE - | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, - ..Default::default() - }, - vertices, - ) - } -}