From a307a2fe86e3ff021b6f2b4cfd94f25e550e6f86 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:21:45 +0100 Subject: [PATCH 01/13] Update wgpu to `main` and dependencies Use my branch of `wgpu` --- Cargo.lock | 3476 -------------------------------- Cargo.toml | 2 +- examples/with_winit/Cargo.toml | 2 +- vello/src/wgpu_engine.rs | 6 +- 4 files changed, 5 insertions(+), 3481 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index dc8f811c..00000000 --- a/Cargo.lock +++ /dev/null @@ -1,3476 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - -[[package]] -name = "android-activity" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" -dependencies = [ - "android-properties", - "bitflags 2.6.0", - "cc", - "cesu8", - "jni", - "jni-sys", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys 0.6.0+11769913", - "num_enum", - "thiserror", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "android_log-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" - -[[package]] -name = "android_logger" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" -dependencies = [ - "android_log-sys", - "env_filter", - "log", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "android_trace" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d564b0f7a9c9e272c7e43c59f1f09ba04d060774ba7c5fa14c2f966bbd6c4e" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "as-raw-xcb-connection" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" - -[[package]] -name = "ash" -version = "0.38.0+1.3.281" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" -dependencies = [ - "libloading", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bit-set" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "bytemuck" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[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.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" - -[[package]] -name = "calloop" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" -dependencies = [ - "bitflags 2.6.0", - "log", - "polling", - "rustix", - "slab", - "thiserror", -] - -[[package]] -name = "calloop-wayland-source" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" -dependencies = [ - "calloop", - "rustix", - "wayland-backend", - "wayland-client", -] - -[[package]] -name = "cargo-run-wasm" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9c33bbfab116bda01ec67729b988895b34167a1e9cf034343099092421ed43" -dependencies = [ - "devserver_lib", - "pico-args", - "serde_json", - "wasm-bindgen-cli-support", -] - -[[package]] -name = "cc" -version = "1.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "clap" -version = "4.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "clap_lex" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" - -[[package]] -name = "cmake" -version = "0.1.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" -dependencies = [ - "cc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "com" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" -dependencies = [ - "com_macros", -] - -[[package]] -name = "com_macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" -dependencies = [ - "com_macros_support", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "com_macros_support" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "console_log" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" -dependencies = [ - "log", - "web-sys", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "cursor-icon" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" - -[[package]] -name = "d3d12" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdbd1f579714e3c809ebd822c81ef148b1ceaeb3d535352afc73fd0c4c6a0017" -dependencies = [ - "bitflags 2.6.0", - "libloading", - "winapi", -] - -[[package]] -name = "devserver_lib" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf215dbb8cb1409cca7645aaed35f9e39fb0a21855bba1ac48bc0334903bf66" - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading", -] - -[[package]] -name = "document-features" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" -dependencies = [ - "litrs", -] - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - -[[package]] -name = "dpi" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" - -[[package]] -name = "env_filter" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "euclid" -version = "0.22.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" -dependencies = [ - "num-traits", -] - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fastrand" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" - -[[package]] -name = "fdeflate" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox 0.1.3", - "windows-sys 0.59.0", -] - -[[package]] -name = "flate2" -version = "1.0.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "font-types" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda6e36206148f69fc6ecb1bb6c0dedd7ee469f3db1d0dc2045beea28430ca43" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot", -] - -[[package]] -name = "gethostname" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" -dependencies = [ - "libc", - "windows-targets 0.48.5", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -dependencies = [ - "fallible-iterator", - "indexmap 1.9.3", - "stable_deref_trait", -] - -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - -[[package]] -name = "glow" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glutin_wgl_sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "gpu-alloc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" -dependencies = [ - "bitflags 2.6.0", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "gpu-allocator" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7" -dependencies = [ - "log", - "presser", - "thiserror", - "winapi", - "windows", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" -dependencies = [ - "bitflags 2.6.0", - "gpu-descriptor-types", - "hashbrown 0.14.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", - "serde", -] - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - -[[package]] -name = "hassle-rs" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" -dependencies = [ - "bitflags 2.6.0", - "com", - "libc", - "libloading", - "thiserror", - "widestring", - "winapi", -] - -[[package]] -name = "headless" -version = "0.0.0" -dependencies = [ - "anyhow", - "clap", - "env_logger", - "futures-intrusive", - "png", - "pollster", - "scenes", - "vello", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "id-arena" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" - -[[package]] -name = "image" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" -dependencies = [ - "bytemuck", - "byteorder-lite", - "num-traits", - "png", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" -dependencies = [ - "equivalent", - "hashbrown 0.15.0", - "serde", -] - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "khronos-egl" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[package]] -name = "khronos_api" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - -[[package]] -name = "kurbo" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" -dependencies = [ - "arrayvec", - "smallvec", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - -[[package]] -name = "libc" -version = "0.2.159" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" - -[[package]] -name = "libloading" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libredox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall 0.4.1", -] - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall 0.5.7", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memmap2" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" -dependencies = [ - "libc", -] - -[[package]] -name = "metal" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" -dependencies = [ - "bitflags 2.6.0", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", - "paste", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "naga" -version = "22.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags 2.6.0", - "cfg_aliases 0.1.1", - "codespan-reporting", - "hexf-parse", - "indexmap 2.6.0", - "log", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.6.0", - "jni-sys", - "log", - "ndk-sys 0.6.0+11769913", - "num_enum", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "notify" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" -dependencies = [ - "bitflags 2.6.0", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "walkdir", - "windows-sys 0.48.0", -] - -[[package]] -name = "notify-debouncer-mini" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43" -dependencies = [ - "crossbeam-channel", - "log", - "notify", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "nv-flip" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec3c68ac226790270de1d9d0eb5853832d82a34b62199ab2a1a4756df1a1974" -dependencies = [ - "nv-flip-sys", -] - -[[package]] -name = "nv-flip-sys" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "932e1eed40002ba70fccac6dab3b64be3301607c3ee88bd14989c4d4e1c1c993" -dependencies = [ - "cc", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.6.0", - "block2", - "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2", - "objc2", - "objc2-contacts", - "objc2-foundation", -] - -[[package]] -name = "objc2-encode" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.6.0", - "block2", - "dispatch", - "libc", - "objc2", -] - -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation", - "objc2-link-presentation", - "objc2-quartz-core", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "once_cell" -version = "1.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "orbclient" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" -dependencies = [ - "libredox 0.0.2", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.7", - "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 = "peniko" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a648c93f502a0bef0a9cb47fa1335994958a2744667d3f82defe513f276741a" -dependencies = [ - "kurbo", - "smallvec", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pico-args" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - -[[package]] -name = "png" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "3.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "pollster" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" - -[[package]] -name = "portable-atomic" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "presser" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" - -[[package]] -name = "proc-macro-crate" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" -dependencies = [ - "profiling-procmacros", - "tracing", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" -dependencies = [ - "quote", - "syn 2.0.79", -] - -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - -[[package]] -name = "read-fonts" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb94d9ac780fdcf9b6b252253f7d8f221379b84bd3573131139b383df69f85e1" -dependencies = [ - "bytemuck", - "font-types", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "renderdoc-sys" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" - -[[package]] -name = "roxmltree" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" - -[[package]] -name = "run_wasm" -version = "0.0.0" -dependencies = [ - "cargo-run-wasm", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[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.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scenes" -version = "0.0.0" -dependencies = [ - "anyhow", - "clap", - "getrandom", - "image", - "rand", - "roxmltree", - "vello", - "web-time", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sctk-adwaita" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" -dependencies = [ - "ab_glyph", - "log", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", -] - -[[package]] -name = "sdl2" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" -dependencies = [ - "bitflags 1.3.2", - "lazy_static", - "libc", - "raw-window-handle", - "sdl2-sys", -] - -[[package]] -name = "sdl2-sys" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" -dependencies = [ - "cfg-if", - "cmake", - "libc", - "version-compare", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "serde_json" -version = "1.0.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[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 = "simple" -version = "0.0.0" -dependencies = [ - "anyhow", - "pollster", - "vello", - "winit", -] - -[[package]] -name = "simple_sdl2" -version = "0.0.0" -dependencies = [ - "pollster", - "sdl2", - "vello", -] - -[[package]] -name = "skrifa" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe" -dependencies = [ - "bytemuck", - "read-fonts", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "smithay-client-toolkit" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" -dependencies = [ - "bitflags 2.6.0", - "calloop", - "calloop-wayland-source", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix", - "thiserror", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", -] - -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] - -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strict-num" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "svg_fmt" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempfile" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" -dependencies = [ - "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "tiny-skia" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap 2.6.0", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "sharded-slab", - "smallvec", - "thread_local", - "tracing-core", -] - -[[package]] -name = "tracing_android_trace" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fae205f9c07bfae3d36d199ab985118c90d225ff70a38e7ff3ecbdb4ef61bc" -dependencies = [ - "android_trace", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "ttf-parser" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vello" -version = "0.3.0" -dependencies = [ - "bytemuck", - "futures-intrusive", - "log", - "peniko", - "png", - "raw-window-handle", - "skrifa", - "static_assertions", - "thiserror", - "vello_encoding", - "vello_shaders", - "wgpu", - "wgpu-profiler", -] - -[[package]] -name = "vello_encoding" -version = "0.3.0" -dependencies = [ - "bytemuck", - "guillotiere", - "peniko", - "skrifa", - "smallvec", -] - -[[package]] -name = "vello_shaders" -version = "0.3.0" -dependencies = [ - "bytemuck", - "naga", - "thiserror", - "vello_encoding", -] - -[[package]] -name = "vello_tests" -version = "0.0.0" -dependencies = [ - "anyhow", - "futures-intrusive", - "image", - "nv-flip", - "png", - "pollster", - "scenes", - "vello", -] - -[[package]] -name = "version-compare" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "walrus" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501ace8ec3492754a9b3c4b59eac7159ceff8414f9e43a05029fe8ef43b9218f" -dependencies = [ - "anyhow", - "gimli", - "id-arena", - "leb128", - "log", - "walrus-macro", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "walrus-macro" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e5bd22c71e77d60140b0bd5be56155a37e5bd14e24f5f87298040d0cc40d7" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.79", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-cli-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7f49ca6e7da74d53d6d716b868828a47d1c3808a8f676e2104fadd3b9874bb" -dependencies = [ - "anyhow", - "base64", - "log", - "rustc-demangle", - "serde_json", - "tempfile", - "unicode-ident", - "walrus", - "wasm-bindgen-externref-xform", - "wasm-bindgen-multi-value-xform", - "wasm-bindgen-shared", - "wasm-bindgen-threads-xform", - "wasm-bindgen-wasm-conventions", - "wasm-bindgen-wasm-interpreter", -] - -[[package]] -name = "wasm-bindgen-externref-xform" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1f37f2705f4177cc87e5b2763115d078d39e4843e351438b34b085d53a8930" -dependencies = [ - "anyhow", - "walrus", - "wasm-bindgen-wasm-conventions", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-multi-value-xform" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2864e3f221fef3869992b541b238e55f53f99b43c4ce220422a6e1ec9458dc21" -dependencies = [ - "anyhow", - "walrus", - "wasm-bindgen-wasm-conventions", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "wasm-bindgen-threads-xform" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9ca60ee029d64cf6f63a630050935360c3877844f6de38e8287afb8f1d2715" -dependencies = [ - "anyhow", - "walrus", - "wasm-bindgen-wasm-conventions", -] - -[[package]] -name = "wasm-bindgen-wasm-conventions" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e429e00149de60ffc768e6e1f0563778a237e7c11cc01801edf9734bff8161f" -dependencies = [ - "anyhow", - "leb128", - "log", - "walrus", - "wasmparser", -] - -[[package]] -name = "wasm-bindgen-wasm-interpreter" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771c49db324f195f221796bf3868247dd91cca4a85604dcb3729213e439abe59" -dependencies = [ - "anyhow", - "log", - "walrus", - "wasm-bindgen-wasm-conventions", -] - -[[package]] -name = "wasm-encoder" -version = "0.212.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501940df4418b8929eb6d52f1aade1fdd15a5b86c92453cb696e3c906bd3fc33" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasmparser" -version = "0.212.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d28bc49ba1e5c5b61ffa7a2eace10820443c4b7d1c0b144109261d14570fdf8" -dependencies = [ - "ahash", - "bitflags 2.6.0", - "hashbrown 0.14.5", - "indexmap 2.6.0", - "semver", - "serde", -] - -[[package]] -name = "wayland-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" -dependencies = [ - "cc", - "downcast-rs", - "rustix", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" -dependencies = [ - "bitflags 2.6.0", - "rustix", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-csd-frame" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" -dependencies = [ - "bitflags 2.6.0", - "cursor-icon", - "wayland-backend", -] - -[[package]] -name = "wayland-cursor" -version = "0.31.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a94697e66e76c85923b0d28a0c251e8f0666f58fc47d316c0f4da6da75d37cb" -dependencies = [ - "rustix", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-plasma" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0a41a6875e585172495f7a96dfa42ca7e0213868f4f15c313f7c33221a7eff" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad87b5fd1b1d3ca2f792df8f686a2a11e3fe1077b71096f7a175ab699f89109" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" -dependencies = [ - "proc-macro2", - "quick-xml", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" -dependencies = [ - "dlib", - "log", - "once_cell", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wgpu" -version = "22.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d1c4ba43f80542cf63a0a6ed3134629ae73e8ab51e4b765a67f3aa062eb433" -dependencies = [ - "arrayvec", - "cfg_aliases 0.1.1", - "document-features", - "js-sys", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "22.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0348c840d1051b8e86c3bcd31206080c5e71e5933dabd79be1ce732b0b2f089a" -dependencies = [ - "arrayvec", - "bit-vec", - "bitflags 2.6.0", - "cfg_aliases 0.1.1", - "document-features", - "indexmap 2.6.0", - "log", - "naga", - "once_cell", - "parking_lot", - "profiling", - "raw-window-handle", - "rustc-hash", - "smallvec", - "thiserror", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6bbf4b4de8b2a83c0401d9e5ae0080a2792055f25859a02bf9be97952bbed4f" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.6.0", - "block", - "cfg_aliases 0.1.1", - "core-graphics-types", - "d3d12", - "glow", - "glutin_wgl_sys", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hassle-rs", - "js-sys", - "khronos-egl", - "libc", - "libloading", - "log", - "metal", - "naga", - "ndk-sys 0.5.0+25.2.9519653", - "objc", - "once_cell", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "rustc-hash", - "smallvec", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-profiler" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06b2cee91fdc885ff0d3d714c59810cc72c6d84b81b0eaa48bab8ff2ad54fb5b" -dependencies = [ - "parking_lot", - "thiserror", - "wgpu", -] - -[[package]] -name = "wgpu-types" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9d91f0e2c4b51434dfa6db77846f2793149d8e73f800fa2e41f52b8eac3c5d" -dependencies = [ - "bitflags 2.6.0", - "js-sys", - "web-sys", -] - -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -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.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winit" -version = "0.30.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" -dependencies = [ - "ahash", - "android-activity", - "atomic-waker", - "bitflags 2.6.0", - "block2", - "bytemuck", - "calloop", - "cfg_aliases 0.2.1", - "concurrent-queue", - "core-foundation", - "core-graphics", - "cursor-icon", - "dpi", - "js-sys", - "libc", - "memmap2", - "ndk", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "objc2-ui-kit", - "orbclient", - "percent-encoding", - "pin-project", - "raw-window-handle", - "redox_syscall 0.4.1", - "rustix", - "sctk-adwaita", - "smithay-client-toolkit", - "smol_str", - "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-plasma", - "web-sys", - "web-time", - "windows-sys 0.52.0", - "x11-dl", - "x11rb", - "xkbcommon-dl", -] - -[[package]] -name = "winnow" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" -dependencies = [ - "memchr", -] - -[[package]] -name = "with_winit" -version = "0.0.0" -dependencies = [ - "android_logger", - "anyhow", - "clap", - "console_error_panic_hook", - "console_log", - "env_logger", - "getrandom", - "log", - "notify-debouncer-mini", - "pollster", - "profiling", - "scenes", - "tracing", - "tracing-subscriber", - "tracing_android_trace", - "vello", - "vello_shaders", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "wgpu-profiler", - "winit", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" -dependencies = [ - "as-raw-xcb-connection", - "gethostname", - "libc", - "libloading", - "once_cell", - "rustix", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" - -[[package]] -name = "xcursor" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" - -[[package]] -name = "xkbcommon-dl" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" -dependencies = [ - "bitflags 2.6.0", - "dlib", - "log", - "once_cell", - "xkeysym", -] - -[[package]] -name = "xkeysym" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" - -[[package]] -name = "xml-rs" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - -[[package]] -name = "zune-jpeg" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" -dependencies = [ - "zune-core", -] diff --git a/Cargo.toml b/Cargo.toml index 624d1781..00b1724d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ static_assertions = "1.1.0" thiserror = "1.0.64" # NOTE: Make sure to keep this in sync with the version badge in README.md and vello/README.md -wgpu = { version = "22.1.0" } +wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "62cef44a1fa04f9ef811362d2b3fd8f80ee306b6" } log = "0.4.22" image = { version = "0.25.2", default-features = false } diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 7cdd3181..6fa07d53 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -12,7 +12,7 @@ name = "with_winit" crate-type = ["cdylib", "lib"] [features] -default = ["wgpu-profiler"] +default = [] # Enable the use of wgpu-profiler. This is an optional feature for times when we use a git dependency on # wgpu (which means the dependency used in wgpu-profiler would be incompatible) wgpu-profiler = ["dep:wgpu-profiler", "vello/wgpu-profiler"] diff --git a/vello/src/wgpu_engine.rs b/vello/src/wgpu_engine.rs index 549bfa58..c7b04a5d 100644 --- a/vello/src/wgpu_engine.rs +++ b/vello/src/wgpu_engine.rs @@ -331,7 +331,7 @@ impl WgpuEngine { layout: Some(&pipeline_layout), vertex: wgpu::VertexState { module, - entry_point: vertex_main, + entry_point: Some(vertex_main), buffers: vertex_buffer .as_ref() .map(core::slice::from_ref) @@ -340,7 +340,7 @@ impl WgpuEngine { }, fragment: Some(wgpu::FragmentState { module, - entry_point: fragment_main, + entry_point: Some(fragment_main), targets: &[Some(color_attachment)], compilation_options: PipelineCompilationOptions::default(), }), @@ -827,7 +827,7 @@ impl WgpuEngine { label: Some(label), layout: Some(&compute_pipeline_layout), module: &shader_module, - entry_point: "main", + entry_point: None, compilation_options: PipelineCompilationOptions { zero_initialize_workgroup_memory: false, ..Default::default() From 8e6fbdfaa79d63dd08e1f57c1e64f691878585dc Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:52:20 +0100 Subject: [PATCH 02/13] Experiment with display timing --- Cargo.toml | 2 +- examples/with_winit/Cargo.toml | 1 + examples/with_winit/src/lib.rs | 75 +++++++++++++++++++++++++++++++++- vello/src/util.rs | 3 +- 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 00b1724d..091bef22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ static_assertions = "1.1.0" thiserror = "1.0.64" # NOTE: Make sure to keep this in sync with the version badge in README.md and vello/README.md -wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "62cef44a1fa04f9ef811362d2b3fd8f80ee306b6" } +wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "e99a2167bfc1d6f6bb24908e04192e2dbcf1fff1" } log = "0.4.22" image = { version = "0.25.2", default-features = false } diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 6fa07d53..7d630813 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -41,6 +41,7 @@ log = { workspace = true } # We're still using env-logger, but we want to use tracing spans to allow using # tracing_android_trace tracing = { version = "0.1.40", features = ["log-always"] } +ash = { version = "0.38.0", default-features = false } [target.'cfg(not(target_os = "android"))'.dependencies] # We use android_logger on Android diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index e3771e19..f1bba718 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -107,6 +107,10 @@ const AA_CONFIGS: [AaConfig; 1] = [AaConfig::Area]; struct VelloApp<'s> { context: RenderContext, renderers: Vec>, + + google_display_timing_ext_devices: Vec>, + present_id: u32, + state: Option>, // Whilst suspended, we drop `render_state`, but need to keep the same window. // If render_state exists, we must store the window in it, to maintain drop order @@ -172,6 +176,8 @@ impl<'s> ApplicationHandler for VelloApp<'s> { #[cfg(not(target_arch = "wasm32"))] fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + use vello::wgpu::hal::vulkan; + let Option::None = self.state else { return; }; @@ -194,6 +200,8 @@ impl<'s> ApplicationHandler for VelloApp<'s> { let render_state = RenderState { window, surface }; self.renderers .resize_with(self.context.devices.len(), || None); + self.google_display_timing_ext_devices + .resize_with(self.context.devices.len(), || None); let id = render_state.surface.dev_id; self.renderers[id].get_or_insert_with(|| { let start = Instant::now(); @@ -224,6 +232,29 @@ impl<'s> ApplicationHandler for VelloApp<'s> { .expect("Not setting max_num_pending_frames"); renderer }); + let display_timing_ext_device = &mut self.google_display_timing_ext_devices[id]; + let device_handle = &self.context.devices[id]; + if display_timing_ext_device.is_none() + && device_handle + .device + .features() + .contains(wgpu::Features::VULKAN_GOOGLE_DISPLAY_TIMING) + { + *display_timing_ext_device = unsafe { + device_handle + .device + .as_hal::(|device| { + let device = device?; + let instance = self.context.instance.as_hal::()?; + Some(ash::google::display_timing::Device::new( + instance.shared_instance().raw_instance(), + device.raw_device(), + )) + }) + .flatten() + }; + } + Some(render_state) }; } @@ -443,7 +474,9 @@ impl<'s> ApplicationHandler for VelloApp<'s> { render_state.window.request_redraw(); - let Some(RenderState { surface, window }) = &self.state else { + render_state.window.request_redraw(); + + let Some(RenderState { surface, window }) = &mut self.state else { return; }; let width = surface.config.width; @@ -541,6 +574,44 @@ impl<'s> ApplicationHandler for VelloApp<'s> { .get_current_texture() .expect("failed to get surface texture"); + let present_id = self.present_id; + self.present_id = self.present_id.wrapping_add(1); + if device_handle + .device + .features() + .contains(wgpu::Features::VULKAN_GOOGLE_DISPLAY_TIMING) + { + unsafe { + let swc = surface + .surface + .as_hal::(|surface| { + if let Some(surface) = surface { + surface.set_next_present_time(ash::vk::PresentTimeGOOGLE { + desired_present_time: 0, + present_id, + }); + Some(surface.raw_swapchain()) + } else { + None + } + }) + .flatten() + .flatten(); + if let Some(swc) = swc { + let display_timing = self.google_display_timing_ext_devices + [surface.dev_id] + .as_ref() + .unwrap(); + // let result = display_timing.get_refresh_cycle_duration(swc); + // eprintln!("Refresh duration: {result:?}"); + if present_id % 2 == 0 { + let result = display_timing.get_past_presentation_timing(swc); + eprintln!("Display timings: {result:?}"); + eprintln!("Most recent present id: {}", present_id); + } + } + } + } drop(texture_span); let render_span = tracing::trace_span!("Dispatching render").entered(); // Note: we don't run the async/"robust" pipeline, as @@ -702,6 +773,8 @@ fn run( let debug = DebugLayers::none(); let mut app = VelloApp { + present_id: 0, + google_display_timing_ext_devices: vec![None; renderers.len()], context: render_cx, renderers, state: render_state, diff --git a/vello/src/util.rs b/vello/src/util.rs index 5a508dbb..58d39f63 100644 --- a/vello/src/util.rs +++ b/vello/src/util.rs @@ -138,7 +138,8 @@ impl RenderContext { let features = adapter.features(); let limits = Limits::default(); #[allow(unused_mut)] - let mut maybe_features = wgpu::Features::CLEAR_TEXTURE; + let mut maybe_features = + wgpu::Features::CLEAR_TEXTURE | wgpu::Features::VULKAN_GOOGLE_DISPLAY_TIMING; #[cfg(feature = "wgpu-profiler")] { maybe_features |= wgpu_profiler::GpuProfiler::ALL_WGPU_TIMER_FEATURES; From 4ba6f5e134c35bc2d11419928f1838c734ecc76e Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:30:01 +0100 Subject: [PATCH 03/13] Migrate to merged `wgpu` version Also start sketching out the frame pacing library --- Cargo.toml | 3 ++- vello_pacing/Cargo.toml | 13 +++++++++++ vello_pacing/README.md | 9 ++++++++ vello_pacing/src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 vello_pacing/Cargo.toml create mode 100644 vello_pacing/README.md create mode 100644 vello_pacing/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 091bef22..d612cd0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "vello", "vello_encoding", + "vello_pacing", "vello_shaders", "vello_tests", @@ -52,7 +53,7 @@ static_assertions = "1.1.0" thiserror = "1.0.64" # NOTE: Make sure to keep this in sync with the version badge in README.md and vello/README.md -wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "e99a2167bfc1d6f6bb24908e04192e2dbcf1fff1" } +wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "685c2133f296ea5bf48e4ee96853f725c2a68980" } log = "0.4.22" image = { version = "0.25.2", default-features = false } diff --git a/vello_pacing/Cargo.toml b/vello_pacing/Cargo.toml new file mode 100644 index 00000000..040f1306 --- /dev/null +++ b/vello_pacing/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "vello_pacing" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +wgpu.workspace = true + +[lints] +workspace = true diff --git a/vello_pacing/README.md b/vello_pacing/README.md new file mode 100644 index 00000000..70809e49 --- /dev/null +++ b/vello_pacing/README.md @@ -0,0 +1,9 @@ +# Vello Pacing + +A frame pacing library for wgpu, optimised for 2d graphics use cases. + +In particular, special care is taken to handle animation use cases correctly. + +## Backends + +This library currently only targets Android, but has working fallbacks for other platforms. diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs new file mode 100644 index 00000000..cf363cb5 --- /dev/null +++ b/vello_pacing/src/lib.rs @@ -0,0 +1,49 @@ +pub struct VelloPacing {} + +/// Docs used to type out how this is being reasoned about. +/// +/// We manage four clocks: +/// 1) The CPU side clock. This is treated as an opaque nanosecond value, used only for sleeping. +/// 2) The GPU "render complete clock". We wait for rendering work to complete to schedule the "present" of the *next* frame, to avoid stuttering. +/// On Android, we calibrate this to the "latching" clock using `presentMargin`. +/// Additionally, if a frame "failed", we. +/// 3) The GPU "latching" clock. This is the +/// 4) The display "present clock". +/// +/// We observe that `earliest_present_time` can be earlier than `actual_present_time` because. +/// +/// There are three cases for when we want to render: +/// 1) Active rendering, i.e. animation +/// 2) Rendering "once", i.e. in response to a keypress. Note that scrolling will likely be treated as animation, and is an important case for latency minimisation. +/// 3) Stopping active rendering, i.e. the last frame +/// +/// Note also that we need to be aware of in this design. +/// +pub struct Thinking; + +/// A sketch of the expected API. +impl VelloPacing { + pub fn new() -> Self { + Self {} + } + + pub fn launch() {} + + /// Run a rendering task until presentation. Useful on macOS for resizing. + pub fn present_synchronously(&mut self) { + let token: () = self.present_immediately(); + self.wait_on_present(token); + } + + pub fn present_immediately(&mut self) {} + + fn wait_on_present(&mut self, (): ()) {} + + pub fn stop(&mut self) {} +} + +impl Default for VelloPacing { + fn default() -> Self { + Self::new() + } +} From a7b62c7a42cd474589ac8635ee8ae7ade7dcd572 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:16:25 +0100 Subject: [PATCH 04/13] Do a lot more writing on potential solutions. Save some more thoughts Continue sketch of pacing --- examples/with_winit/src/lib.rs | 4 +- vello_pacing/Cargo.toml | 2 + vello_pacing/src/lib.rs | 169 ++++++++++++++++++++++++++++++--- 3 files changed, 161 insertions(+), 14 deletions(-) diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index f1bba718..bdb90178 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; use std::num::NonZeroUsize; use std::sync::Arc; +use std::time::Duration; #[cfg(not(target_arch = "wasm32"))] use std::time::Instant; use vello::low_level::DebugLayers; @@ -604,7 +605,8 @@ impl<'s> ApplicationHandler for VelloApp<'s> { .unwrap(); // let result = display_timing.get_refresh_cycle_duration(swc); // eprintln!("Refresh duration: {result:?}"); - if present_id % 2 == 0 { + if present_id % 5 == 0 { + // std::thread::sleep(Duration::from_millis(300)); let result = display_timing.get_past_presentation_timing(swc); eprintln!("Display timings: {result:?}"); eprintln!("Most recent present id: {}", present_id); diff --git a/vello_pacing/Cargo.toml b/vello_pacing/Cargo.toml index 040f1306..e2f79a0c 100644 --- a/vello_pacing/Cargo.toml +++ b/vello_pacing/Cargo.toml @@ -8,6 +8,8 @@ repository.workspace = true [dependencies] wgpu.workspace = true +vello.workspace = true +ash = { version = "0.38.0", default-features = false } [lints] workspace = true diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index cf363cb5..c8363658 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,33 +1,124 @@ -pub struct VelloPacing {} +use std::{ + collections::HashMap, + sync::{ + atomic::{AtomicU64, Ordering}, + mpsc::{Receiver, RecvTimeoutError, TryRecvError}, + Arc, + }, + time::{Duration, Instant}, +}; /// Docs used to type out how this is being reasoned about. /// -/// We manage four clocks: -/// 1) The CPU side clock. This is treated as an opaque nanosecond value, used only for sleeping. +/// We manage six clocks: +/// 1) The CPU side clock. This is treated as an opaque nanosecond value, used only(?) for sleeping. /// 2) The GPU "render complete clock". We wait for rendering work to complete to schedule the "present" of the *next* frame, to avoid stuttering. /// On Android, we calibrate this to the "latching" clock using `presentMargin`. -/// Additionally, if a frame "failed", we. -/// 3) The GPU "latching" clock. This is the -/// 4) The display "present clock". -/// -/// We observe that `earliest_present_time` can be earlier than `actual_present_time` because. +/// Additionally, if a frame "failed", we choose not to present the next frame. +/// 3) The GPU render start clock, used to get a quick estimate for likely stutters. +/// 4) The GPU "latching" clock. This is only implied by `presentMargin` in relation to the render complete clock. +/// 5) The display "present clock". We assume that this is a potentially variable, but generally fixed amount of +/// time from the "latching" clock (due to compositing time). +/// 6) The CPU side present clock, which is the time we think presentation will happen. +/// These are always a fixed number of nanoseconds away from the "true presentation time" (this difference can be +/// calculated using +/// and the true presentation time). /// /// There are three cases for when we want to render: -/// 1) Active rendering, i.e. animation -/// 2) Rendering "once", i.e. in response to a keypress. Note that scrolling will likely be treated as animation, and is an important case for latency minimisation. -/// 3) Stopping active rendering, i.e. the last frame +/// 1) Active rendering +/// - Active Passive, e.g. playing an animation (/a video) +/// - Active Active, e.g. scrolling using a touch screen +/// - These have slightly different characteristics, because animation smoothness in in the passive case is more important. +/// Whereas latency reduction is more important in the active case. +/// 2) Rendering "once", i.e. in response to a keypress. Note that scrolling will likely be treated +/// as animation, and is an important case for latency minimisation. +/// 3) Stopping active rendering, i.e. the last frame. /// /// Note also that we need to be aware of in this design. /// +/// We observe that `earliest_present_time` can be earlier than `actual_present_time` because of earlier presents "getting in the way". +/// +/// In the rendering once case, we just render as soon as possible. +/// It *could* be possible to coalesce these updates. +/// There are two phases to the multiple renders case: +/// 1) Up-to-date control loop +/// 2) Outdated control loop. +/// +/// The outdated control loop case is due to the Presentation Time API having ~5 frames of latency. +/// (see , +/// the "Android 8.0, presentation timing latency" heading). +/// +/// At the start of rendering, we are in the outdated control loop case, because of the above mentioned latency. That involves: +/// 1) We render the first frame immediately. This uses a best-effort estimated present time. +/// This does *not* have an requestedPresentationTime. +/// 2) We then set about rendering the second frame, which uses an estimated present time *one* interval +/// of display refresh rate after the first presentation. We start the rendering work for this frame +/// (tunable) ~20% sooner than one refresh rate interval after the start of rendering work for the first frame. +/// - If work has already finished on the first frame, then +/// - A potential option here is to cancel this render (GPU side) if the previous frame took (significantly) longer +/// than one refresh interval. It is future work to reason about this. +/// We foresee this as potentially advantageous because the CPU side work would be a relatively small part of +/// a frame, and so it would probably lead to "better" animation smoothness. +/// 3) Once the first frame finishes rendering, we present the second frame. We use "render end time" - "render start time" (`T_R`) to +/// estimate how many refresh durations (`N`) this render took, with a (tunable) ~25% "grace reduction" in the value. +/// This grace amount is to account for a likely ramping up of GPU power states, so future frames will probably be faster. +/// We also use `T_R` to estimate how many refresh durations the second frame will take to render (`N_2`), for scheduling the +/// present of the second frame. This does not use the grace reduction, but does have a grace subtraction of ~45% of the refresh cycle to +/// count as one frame. This grace period is to account for the fact that we don't know when in the refresh cycle we started rendering, +/// so there's a chance that even if both frames took longer than one refresh duration to render, we can "fake" smoothness. +/// Additionally, this slightly helps account for the GPU power state ramp-up. +/// 4) We present the second frame with a time which is "render end time" + previous "present clock - latching clock" + `N_2` * refresh durations. +/// 5) We start rendering on the third frame, either `N_2 + N` or `2*N` (TBD) refresh durations after the first frame rendering started. +/// This will have an estimated present time of the same `N_2 + N` or `2*N` refresh durations from the estimated present time. +/// +/// Using a statistical model for the variable time from starting rendering from event `1` to `2`. pub struct Thinking; +pub struct FrameRenderRequest { + scene: vello::Scene, + frame: FrameId, + expected_present: u64, + // In general, if touch is held, will need the next frame. + needs_next_frame: bool, // TODO: No, LatencyOptimised, ConsistencyOptimised? + present_immediately: bool, + paint_start: Instant, +} + +pub struct FrameStats { + /// When the rendering work started on the GPU, in nanoseconds. + /// + /// Used to estimate how long frames are taking to render, to get + /// faster feedback on whether we should request a slower (or faster) display mode. + /// (We choose to be more conservative in requesting a faster display mode) + render_start: u64, + /// When the rendering work finished on the GPU, in nanoseconds. + /// + /// Used to: + /// - estimate the compositing time + /// - for estimating the expected presentation times before up-to-date timestamps become available + render_end: u64, + /// + estimated_present: u64, + paint_start: Instant, + presentation_time: Option, +} + +pub struct VelloPacing { + rx: Receiver, + queue: Arc, + device: Arc, + stats: HashMap, +} + /// A sketch of the expected API. impl VelloPacing { pub fn new() -> Self { - Self {} + todo!() } - pub fn launch() {} + pub fn launch(self) { + std::thread::spawn(|| self.run()); + } /// Run a rendering task until presentation. Useful on macOS for resizing. pub fn present_synchronously(&mut self) { @@ -40,6 +131,58 @@ impl VelloPacing { fn wait_on_present(&mut self, (): ()) {} pub fn stop(&mut self) {} + + fn run(mut self) { + loop { + match self.rx.recv_timeout(Duration::from_millis(4)) { + Ok(frame_request) => { + self.paint_frame(); + if frame_request.needs_next_frame {} + continue; + } + Err(RecvTimeoutError::Disconnected) => { + unreachable!("The main thread has stopped without telling rendering to stop") + } + Err(RecvTimeoutError::Timeout) => {} + } + self.poll_frame(); + } + } + + fn paint_frame(&mut self) { + // Prepare command buffers, etc. + + // If the previous frame returned + self.poll_frame(); + } + + fn poll_frame(&mut self) { + self.device.poll(wgpu::Maintain::Poll); + if self.penultimate_frame_finished() { + if self.penultimate_frame_failed() {} + } + } + + fn penultimate_frame_finished(&self) -> bool { + false + } + + fn penultimate_frame_failed(&self) -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct FrameId(u32); + +impl FrameId { + pub fn next(self) -> Self { + Self(self.0.wrapping_add(1)) + } + + pub fn raw(self) -> u32 { + self.0 + } } impl Default for VelloPacing { From 028d2022b6776d0c6818715de0c65d6b5c639284 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Thu, 5 Sep 2024 09:33:57 +0100 Subject: [PATCH 05/13] Update `wgpu` to main More writings/logic --- Cargo.toml | 2 +- examples/with_winit/src/lib.rs | 2 -- vello_pacing/src/lib.rs | 63 +++++++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d612cd0a..c6306b07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ static_assertions = "1.1.0" thiserror = "1.0.64" # NOTE: Make sure to keep this in sync with the version badge in README.md and vello/README.md -wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "685c2133f296ea5bf48e4ee96853f725c2a68980" } +wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "aeac0f29fed2ae4240869c8ff419ea93523d32d9" } log = "0.4.22" image = { version = "0.25.2", default-features = false } diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index bdb90178..5d43bdb8 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -8,7 +8,6 @@ use std::collections::HashSet; use std::num::NonZeroUsize; use std::sync::Arc; -use std::time::Duration; #[cfg(not(target_arch = "wasm32"))] use std::time::Instant; use vello::low_level::DebugLayers; @@ -606,7 +605,6 @@ impl<'s> ApplicationHandler for VelloApp<'s> { // let result = display_timing.get_refresh_cycle_duration(swc); // eprintln!("Refresh duration: {result:?}"); if present_id % 5 == 0 { - // std::thread::sleep(Duration::from_millis(300)); let result = display_timing.get_past_presentation_timing(swc); eprintln!("Display timings: {result:?}"); eprintln!("Most recent present id: {}", present_id); diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index c8363658..780981c8 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, VecDeque}, sync::{ atomic::{AtomicU64, Ordering}, mpsc::{Receiver, RecvTimeoutError, TryRecvError}, @@ -8,6 +8,8 @@ use std::{ time::{Duration, Instant}, }; +use wgpu::Buffer; + /// Docs used to type out how this is being reasoned about. /// /// We manage six clocks: @@ -72,6 +74,8 @@ use std::{ /// This will have an estimated present time of the same `N_2 + N` or `2*N` refresh durations from the estimated present time. /// /// Using a statistical model for the variable time from starting rendering from event `1` to `2`. +/// +/// TODO: Reason about multi-window/multi-display? pub struct Thinking; pub struct FrameRenderRequest { @@ -89,25 +93,55 @@ pub struct FrameStats { /// /// Used to estimate how long frames are taking to render, to get /// faster feedback on whether we should request a slower (or faster) display mode. - /// (We choose to be more conservative in requesting a faster display mode) + /// (We choose to be more conservative in requesting a faster display mode, but + /// act quickly on requesting a slower one.) render_start: u64, /// When the rendering work finished on the GPU, in nanoseconds. /// /// Used to: - /// - estimate the compositing time + /// - estimate the amount of time compositing takes /// - for estimating the expected presentation times before up-to-date timestamps become available render_end: u64, + /// The time we told the application that this frame would be rendered at. + /// + /// In early frames, this was a best-effort guess, but we should be consistent in the use of this. /// + /// For most users, the estimated present is only useful in terms of "how long between presents". + /// However, an absolute timestamp is useful for calibrating Audio with Video estimated_present: u64, + /// The time which we started the entire painting for this frame, including scene construction, etc. + /// + /// This is used for: + /// 1) Providing the time at which rendering should start, generally + /// 1 refresh duration later than the previous frame +- some margin. paint_start: Instant, + // /// The time at which the frame pacing controller received the frame to be rendered. + // /// + // /// This is used to predict a possible frame deadline miss early + // paint_end: Instant, + /// The information we received from `SurfaceFlinger`, which is severely outdated by design. + /// + /// We might not get this information, so should be ready to work without it. presentation_time: Option, } +pub struct InFlightStatus {} + +pub struct InFlightFrame { + download_buffer: Buffer, +} + +/// The state of the frame pacing controller thread. pub struct VelloPacing { rx: Receiver, queue: Arc, device: Arc, - stats: HashMap, + /// Stats from previous frames, stored in a ring buffer (max capacity ~10?). + stats: VecDeque<(FrameId, FrameStats)>, + /// The refresh rate reported by the system. + refresh_rate: u64, + presenting_frame: InFlightFrame, + gpu_working_frame: InFlightFrame, } /// A sketch of the expected API. @@ -134,7 +168,14 @@ impl VelloPacing { fn run(mut self) { loop { - match self.rx.recv_timeout(Duration::from_millis(4)) { + let timeout = if self.frame_in_flight() { + Duration::from_millis(4) + } else { + // If there is no frame in flight, then we can + // keep ticking the device, but it isn't really needed + Duration::from_millis(100) + }; + match self.rx.recv_timeout(timeout) { Ok(frame_request) => { self.paint_frame(); if frame_request.needs_next_frame {} @@ -158,16 +199,20 @@ impl VelloPacing { fn poll_frame(&mut self) { self.device.poll(wgpu::Maintain::Poll); - if self.penultimate_frame_finished() { - if self.penultimate_frame_failed() {} + if self.presented_frame_work_done() { + if self.presented_frame_failed() {} } } - fn penultimate_frame_finished(&self) -> bool { + fn presented_frame_work_done(&self) -> bool { false } - fn penultimate_frame_failed(&self) -> bool { + fn presented_frame_failed(&self) -> bool { + false + } + // fn presented_frame_status(&self) -> FrameStatus {} + fn frame_in_flight(&self) -> bool { false } } From e4ff4f20f48d2194844ab6dd8ee6439c5c3b1601 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:11:00 +0100 Subject: [PATCH 06/13] Start writing out the logic in earnest Some initial resizing logic --- vello_pacing/Cargo.toml | 1 + vello_pacing/src/lib.rs | 219 +++++++++++++++++++++++++++++++++++----- 2 files changed, 193 insertions(+), 27 deletions(-) diff --git a/vello_pacing/Cargo.toml b/vello_pacing/Cargo.toml index e2f79a0c..96986764 100644 --- a/vello_pacing/Cargo.toml +++ b/vello_pacing/Cargo.toml @@ -10,6 +10,7 @@ repository.workspace = true wgpu.workspace = true vello.workspace = true ash = { version = "0.38.0", default-features = false } +tracing = "0.1.40" [lints] workspace = true diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index 780981c8..7f3e15c8 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,14 +1,15 @@ use std::{ collections::{HashMap, VecDeque}, sync::{ - atomic::{AtomicU64, Ordering}, - mpsc::{Receiver, RecvTimeoutError, TryRecvError}, + atomic::{AtomicBool, AtomicU64, Ordering}, + mpsc::{Receiver, RecvTimeoutError, Sender, TryRecvError}, Arc, }, time::{Duration, Instant}, }; -use wgpu::Buffer; +use vello::Scene; +use wgpu::{core::present, Buffer, SubmissionIndex, SurfaceTexture}; /// Docs used to type out how this is being reasoned about. /// @@ -115,6 +116,8 @@ pub struct FrameStats { /// 1) Providing the time at which rendering should start, generally /// 1 refresh duration later than the previous frame +- some margin. paint_start: Instant, + /// Whether the source paint request wanted there to be a next frame. + next_frame_continued: bool, // /// The time at which the frame pacing controller received the frame to be rendered. // /// // /// This is used to predict a possible frame deadline miss early @@ -128,20 +131,42 @@ pub struct FrameStats { pub struct InFlightStatus {} pub struct InFlightFrame { - download_buffer: Buffer, + download_map_buffer: Buffer, + work_complete: Arc, + paint_start: Instant, + id: FrameId, + submission_index: SubmissionIndex, + /// Information needed to perform a presentation, and not before. + required_to_present: Option<(SurfaceTexture, Scene)>, + estimated_present: u64, + next_frame_expected: bool, +} + +pub enum VelloControl { + Frame(FrameRenderRequest), + Stop, + /// A resize request. This might skip rendering a previous frame + /// if it arrives before that frame is presented. + Resize(FrameRenderRequest, (u32, u32), Sender), } /// The state of the frame pacing controller thread. pub struct VelloPacing { - rx: Receiver, + rx: Receiver, queue: Arc, device: Arc, + surface: wgpu::Surface<'static>, /// Stats from previous frames, stored in a ring buffer (max capacity ~10?). stats: VecDeque<(FrameId, FrameStats)>, - /// The refresh rate reported by the system. + /// The refresh rate reported "by the system". refresh_rate: u64, - presenting_frame: InFlightFrame, - gpu_working_frame: InFlightFrame, + // TODO: Does this need a capacity of 2? + unmapped_download_buffer: Option<(Buffer, Arc)>, + /// Details about the previous frame, which has already been presented. + presenting_frame: Option, + /// Details about the frame whose work has been submitted to the. + gpu_working_frame: Option, + abandoned_frames: Vec, } /// A sketch of the expected API. @@ -151,7 +176,7 @@ impl VelloPacing { } pub fn launch(self) { - std::thread::spawn(|| self.run()); + std::thread::spawn(move || self.run()); } /// Run a rendering task until presentation. Useful on macOS for resizing. @@ -176,44 +201,184 @@ impl VelloPacing { Duration::from_millis(100) }; match self.rx.recv_timeout(timeout) { - Ok(frame_request) => { - self.paint_frame(); - if frame_request.needs_next_frame {} + Ok(command) => { + match command { + VelloControl::Frame(request) => { + self.poll_frame(); + // TODO: Error handling + let texture = self.surface.get_current_texture().unwrap(); + self.paint_frame(request.scene, texture); + self.poll_frame(); + } + VelloControl::Stop => break, + #[expect( + unreachable_code, + unused_variables, + reason = "We stub out the unused variables" + )] + VelloControl::Resize(request, (_, _), done) => { + if let Some(mut old_frame) = self.gpu_working_frame.take() { + // This frame will never be presented + drop(old_frame.required_to_present.take()); + self.abandoned_frames.push(old_frame); + } + // Make sure any easily detectable needed reallocation happens + // TODO: What do we want to do if: + // 1) The previous frame didn't succeed + // 2) We are trying to resize + // Do we just draw a clear colour? + self.poll_frame(); + // self.surface + // .configure(&self.device, SurfaceConfiguration { width, height }); + unimplemented!(); + + let texture = self.surface.get_current_texture().unwrap(); + let frame = self.paint_frame_inner(&request.scene, &texture); + texture.present(); + // TODO: Maybe: self.abandoned_frames.extend(self.presenting_frame.take()); + self.presenting_frame = Some(frame); + if let Err(e) = done.send(request.frame) { + tracing::error!("Failed to send present result {e}"); + }; + } + } + continue; } Err(RecvTimeoutError::Disconnected) => { - unreachable!("The main thread has stopped without telling rendering to stop") + // TODO: Is this just the implicit stop command? + tracing::error!( + "The main thread has stopped without telling rendering to stop" + ); + // TODO: self.poll_frame();? + // What do we need to be careful about dropping? + break; + } + Err(RecvTimeoutError::Timeout) => { + // Fall through intentionally } - Err(RecvTimeoutError::Timeout) => {} } self.poll_frame(); } } - fn paint_frame(&mut self) { + fn paint_frame(&mut self, scene: Scene, to: SurfaceTexture) { + // TODO: It could happen that frames get sent not in response to our handling code (e.g. as an immediate frame) + // Do we just always want to abandon the current working frame? + assert!(self.gpu_working_frame.is_none()); + let mut res = self.paint_frame_inner(&scene, &to); + res.required_to_present = Some((to, scene)); + self.gpu_working_frame = Some(res); + } + + #[must_use] + #[expect(unused_variables, reason = "Not yet implemented")] + fn paint_frame_inner(&mut self, scene: &Scene, to: &SurfaceTexture) -> InFlightFrame { // Prepare command buffers, etc. - // If the previous frame returned - self.poll_frame(); + todo!(); } fn poll_frame(&mut self) { self.device.poll(wgpu::Maintain::Poll); - if self.presented_frame_work_done() { - if self.presented_frame_failed() {} - } - } + let mut failed = false; + let mut desired_present_time: Option = None; + if let Some(presenting) = &mut self.presenting_frame { + if let Some(value) = Arc::get_mut(&mut presenting.work_complete) { + // Reset the value to false, because we're about to reuse it. + if std::mem::take(value.get_mut()) { + let presenting = self + .presenting_frame + .take() + .expect("We know this value is present"); - fn presented_frame_work_done(&self) -> bool { - false + { + let value = presenting.download_map_buffer.slice(..).get_mapped_range(); + eprintln!("Downloaded: {value:?}"); + presenting.download_map_buffer.unmap(); + // Will be calculated from `value`, as part of https://github.com/linebender/vello/pull/606 + failed = false; + if failed { + // Perform reallocation. Will be part of https://github.com/linebender/vello/pull/606. + } + // The time which we should not present before. + // If `value` indicates we really badly overflowed, then this will be later than otherwise expected. + desired_present_time = None; + self.stats.push_back(( + presenting.id, + FrameStats { + // TODO: Make optional because some backends don't support timestamp queries? + render_start: 0, + render_end: 0, + estimated_present: presenting.estimated_present, + paint_start: presenting.paint_start, + presentation_time: None, + next_frame_continued: presenting.next_frame_expected, + }, + )); + } + self.unmapped_download_buffer = + Some((presenting.download_map_buffer, presenting.work_complete)); + } else { + unreachable!( + "Buffer mapping/work complete callback dropped without being called." + ) + } + } else { + // Probably nothing to do? + } + } + if self.presenting_frame.is_none() { + if let Some(mut working_frame) = self.gpu_working_frame.take() { + let (texture, scene) = working_frame.required_to_present.take().unwrap(); + if failed { + // Then redo the paint; we know the previous attempted frame will have been cancalled, so won't be expensive. + // We choose to present here immediately, to minimise likely latency costs. + self.paint_frame_inner(&scene, &texture); + } else if working_frame.work_complete.load(Ordering::Relaxed) { + // I don't think there's actually anything interesting to do here, but might need to be reasoned about. + }; + // We run a display timing request after the present occurs, but we only need to get the Vulkan swapchain once. + let mut swc = None; + if let Some(desired_present_time) = + // Pseudocode for the or-else case. This is to handle the scenario where the previous frame finished + // *before* we. + desired_present_time + .or_else(|| Some(self.stats.front()?.1.estimated_present)) + { + swc = unsafe { + self.surface + .as_hal::(|surface| { + if let Some(surface) = surface { + surface.set_next_present_time(ash::vk::PresentTimeGOOGLE { + desired_present_time, + present_id: working_frame.id.0, + }); + Some(surface.raw_swapchain()) + } else { + None + } + }) + .flatten() + .flatten() + }; + } + texture.present(); + if let Some(_swc) = swc { + // Load past present timing information + } + if working_frame.next_frame_expected { + // Do the maths for when we should ask the main thread for the next frame + // TODO: Do we need our own timer thread for just that, or should something else happen? + } + self.presenting_frame = Some(working_frame); + } + } } - fn presented_frame_failed(&self) -> bool { - false - } // fn presented_frame_status(&self) -> FrameStatus {} fn frame_in_flight(&self) -> bool { - false + self.gpu_working_frame.is_some() } } From 501c03c21ad73c9ebae75a667fb6fe8c87c82565 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:00:06 +0100 Subject: [PATCH 07/13] Continue pacing implementation Continued resource management --- vello_pacing/src/lib.rs | 123 +++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 22 deletions(-) diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index 7f3e15c8..7dacf9c9 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,15 +1,15 @@ use std::{ - collections::{HashMap, VecDeque}, + collections::VecDeque, sync::{ - atomic::{AtomicBool, AtomicU64, Ordering}, - mpsc::{Receiver, RecvTimeoutError, Sender, TryRecvError}, + atomic::{AtomicBool, Ordering}, + mpsc::{Receiver, RecvTimeoutError, Sender}, Arc, }, time::{Duration, Instant}, }; use vello::Scene; -use wgpu::{core::present, Buffer, SubmissionIndex, SurfaceTexture}; +use wgpu::{Buffer, SubmissionIndex, SurfaceTexture}; /// Docs used to type out how this is being reasoned about. /// @@ -155,18 +155,21 @@ pub struct VelloPacing { rx: Receiver, queue: Arc, device: Arc, + google_display_timing_ext_devices: Vec>, + adapter: Arc, surface: wgpu::Surface<'static>, /// Stats from previous frames, stored in a ring buffer (max capacity ~10?). stats: VecDeque<(FrameId, FrameStats)>, /// The refresh rate reported "by the system". refresh_rate: u64, - // TODO: Does this need a capacity of 2? - unmapped_download_buffer: Option<(Buffer, Arc)>, + mapped_unused_download_buffers: Vec<(Buffer, Arc)>, + mapped_unused_download_buffers_scratch: Vec<(Buffer, Arc)>, + // TODO: Smallvec? + free_download_buffers: Vec<(Buffer, Arc)>, /// Details about the previous frame, which has already been presented. presenting_frame: Option, /// Details about the frame whose work has been submitted to the. gpu_working_frame: Option, - abandoned_frames: Vec, } /// A sketch of the expected API. @@ -210,23 +213,34 @@ impl VelloPacing { self.paint_frame(request.scene, texture); self.poll_frame(); } - VelloControl::Stop => break, + VelloControl::Stop => { + // TODO: + if let Some(mut old_frame) = self.gpu_working_frame.take() { + // This frame will never be presented + drop(old_frame.required_to_present.take()); + } + // self.device.poll(wgpu::MaintainBase::Wait); + // What do we need to be careful about dropping? + // Do we need to run the GPU + break; + } #[expect( unreachable_code, unused_variables, reason = "We stub out the unused variables" )] VelloControl::Resize(request, (_, _), done) => { + // Cancel the frame which hasn't been scheduled for presentation. if let Some(mut old_frame) = self.gpu_working_frame.take() { // This frame will never be presented drop(old_frame.required_to_present.take()); - self.abandoned_frames.push(old_frame); + self.abandon(old_frame); } // Make sure any easily detectable needed reallocation happens // TODO: What do we want to do if: // 1) The previous frame didn't succeed // 2) We are trying to resize - // Do we just draw a clear colour? + // We choose not to address this presently, because it is a. self.poll_frame(); // self.surface // .configure(&self.device, SurfaceConfiguration { width, height }); @@ -235,6 +249,9 @@ impl VelloPacing { let texture = self.surface.get_current_texture().unwrap(); let frame = self.paint_frame_inner(&request.scene, &texture); texture.present(); + if let Some(old_presenting) = self.presenting_frame.take() { + self.abandon(old_presenting); + } // TODO: Maybe: self.abandoned_frames.extend(self.presenting_frame.take()); self.presenting_frame = Some(frame); if let Err(e) = done.send(request.frame) { @@ -250,8 +267,6 @@ impl VelloPacing { tracing::error!( "The main thread has stopped without telling rendering to stop" ); - // TODO: self.poll_frame();? - // What do we need to be careful about dropping? break; } Err(RecvTimeoutError::Timeout) => { @@ -262,6 +277,21 @@ impl VelloPacing { } } + fn abandon(&mut self, frame: InFlightFrame) { + // This is accurate since we never make a `Weak` for the `work_complete` buffers + // If that became untrue, the only risk is that the buffer and value would be dropped instead of reused. + if Arc::strong_count(&frame.work_complete) == 1 { + Self::handle_completed_mapping_finished( + &mut self.free_download_buffers, + frame.download_map_buffer, + frame.work_complete, + ); + } else { + self.mapped_unused_download_buffers + .push((frame.download_map_buffer, frame.work_complete)); + } + } + fn paint_frame(&mut self, scene: Scene, to: SurfaceTexture) { // TODO: It could happen that frames get sent not in response to our handling code (e.g. as an immediate frame) // Do we just always want to abandon the current working frame? @@ -293,16 +323,18 @@ impl VelloPacing { .expect("We know this value is present"); { - let value = presenting.download_map_buffer.slice(..).get_mapped_range(); - eprintln!("Downloaded: {value:?}"); - presenting.download_map_buffer.unmap(); - // Will be calculated from `value`, as part of https://github.com/linebender/vello/pull/606 + let map_result = + presenting.download_map_buffer.slice(..).get_mapped_range(); + eprintln!("Downloaded: {map_result:?}"); + // Will be calculated from `map_result`, as part of https://github.com/linebender/vello/pull/606 failed = false; if failed { // Perform reallocation. Will be part of https://github.com/linebender/vello/pull/606. } // The time which we should not present before. - // If `value` indicates we really badly overflowed, then this will be later than otherwise expected. + // If `map_result` indicates we really badly overflowed the available time, + // then this will be later than otherwise expected, to avoid a stutter. + // See https://developer.android.com/games/sdk/frame-pacing desired_present_time = None; self.stats.push_back(( presenting.id, @@ -317,15 +349,18 @@ impl VelloPacing { }, )); } - self.unmapped_download_buffer = - Some((presenting.download_map_buffer, presenting.work_complete)); + Self::handle_completed_mapping_finished( + &mut self.free_download_buffers, + presenting.download_map_buffer, + presenting.work_complete, + ); } else { unreachable!( "Buffer mapping/work complete callback dropped without being called." ) } } else { - // Probably nothing to do? + // The presenting frame's work isn't complete. Probably nothing to do? } } if self.presenting_frame.is_none() { @@ -334,7 +369,10 @@ impl VelloPacing { if failed { // Then redo the paint; we know the previous attempted frame will have been cancalled, so won't be expensive. // We choose to present here immediately, to minimise likely latency costs. - self.paint_frame_inner(&scene, &texture); + // We know that the. + let new_inner = self.paint_frame_inner(&scene, &texture); + let old_working = std::mem::replace(&mut working_frame, new_inner); + self.abandon(old_working); } else if working_frame.work_complete.load(Ordering::Relaxed) { // I don't think there's actually anything interesting to do here, but might need to be reasoned about. }; @@ -347,6 +385,7 @@ impl VelloPacing { .or_else(|| Some(self.stats.front()?.1.estimated_present)) { swc = unsafe { + // SAFETY: We do not "manually drop" the raw handle, i.e. call "vkDestroySurfaceKHR" self.surface .as_hal::(|surface| { if let Some(surface) = surface { @@ -374,12 +413,52 @@ impl VelloPacing { self.presenting_frame = Some(working_frame); } } + assert!(self.mapped_unused_download_buffers_scratch.is_empty()); + for (buffer, work_complete) in self.mapped_unused_download_buffers.drain(..) { + // We know that the `work_complete` will not change again. + if Arc::strong_count(&work_complete) == 1 { + Self::handle_completed_mapping_finished( + &mut self.free_download_buffers, + buffer, + work_complete, + ); + } else { + self.mapped_unused_download_buffers_scratch + .push((buffer, work_complete)); + } + } + std::mem::swap( + &mut self.mapped_unused_download_buffers_scratch, + &mut self.mapped_unused_download_buffers, + ); } - // fn presented_frame_status(&self) -> FrameStatus {} fn frame_in_flight(&self) -> bool { self.gpu_working_frame.is_some() } + + /// Handle a completed buffer mapping for reuse. + /// `buffer` should be finished with, but mapped. + /// + /// Associated function for borrow checker purposes + fn handle_completed_mapping_finished( + unmapped_download_buffers: &mut Vec<(Buffer, Arc)>, + buffer: Buffer, + mut work_complete: Arc, + ) { + if let Some(value) = Arc::get_mut(&mut work_complete) { + let value = value.get_mut(); + if !*value { + tracing::error!("Tried to unmap buffer which was never assigned for mapping?"); + } else { + buffer.unmap(); + } + *value = false; + if unmapped_download_buffers.len() < 4 { + unmapped_download_buffers.push((buffer, work_complete)); + } + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] From ac7f66aa2a436c931a75046508fdd6be11f90597 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:59:50 +0100 Subject: [PATCH 08/13] Start working towards wiring Get the past presentation timing information Merge branch 'achoreographer' into android-pacing --- Cargo.toml | 6 + examples/with_winit/Cargo.toml | 4 + examples/with_winit/src/lib.rs | 57 ++++++- vello_pacing/src/lib.rs | 274 ++++++++++++++++++++++----------- 4 files changed, 241 insertions(+), 100 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c6306b07..4bbcdc8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,3 +64,9 @@ pollster = "0.3.0" web-time = "1.1.0" wgpu-profiler = "0.18.2" scenes = { path = "examples/scenes" } + +[patch.crates-io] +# "Choreographer" branch: https://github.com/rust-mobile/ndk/tree/choreographer +# With a patch to make version numbers work https://github.com/djmcnab/ndk/tree/choreographer +ndk = { git = "https://github.com/djmcnab/ndk/", rev = "81627a7564982a04027a49d538cac1686d870dbd" } +ndk-sys = { git = "https://github.com/djmcnab/ndk/", rev = "81627a7564982a04027a49d538cac1686d870dbd" } diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 7d630813..8c49b95d 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -63,6 +63,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = "registry", ] } profiling = { version = "1.0.15", features = ["profile-with-tracing"] } +ndk = { version = "0.9", features = ["api-level-33"] } [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.7" @@ -71,3 +72,6 @@ wasm-bindgen-futures = "0.4.43" web-sys = { version = "0.3.70", features = ["HtmlCollection", "Text"] } web-time = { workspace = true } getrandom = { version = "0.2.15", features = ["js"] } + +[package.metadata.android.application] +debuggable = true diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index 5d43bdb8..d9dc2263 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -16,6 +16,7 @@ use web_time::Instant; use winit::application::ApplicationHandler; use winit::event::*; use winit::keyboard::*; +use winit::window::WindowId; #[cfg(all(feature = "wgpu-profiler", not(target_arch = "wasm32")))] use std::time::Duration; @@ -168,6 +169,9 @@ struct VelloApp<'s> { modifiers: ModifiersState, debug: DebugLayers, + choreographer: Option, + animation_in_flight: bool, + proxy: winit::event_loop::EventLoopProxy, } impl<'s> ApplicationHandler for VelloApp<'s> { @@ -469,13 +473,12 @@ impl<'s> ApplicationHandler for VelloApp<'s> { self.prior_position = Some(position); } WindowEvent::RedrawRequested => { + if self.animation_in_flight { + return; + } let _rendering_span = tracing::trace_span!("Actioning Requested Redraw").entered(); let encoding_span = tracing::trace_span!("Encoding scene").entered(); - render_state.window.request_redraw(); - - render_state.window.request_redraw(); - let Some(RenderState { surface, window }) = &mut self.state else { return; }; @@ -660,6 +663,33 @@ impl<'s> ApplicationHandler for VelloApp<'s> { frame_time_us: (new_time - self.frame_start_time).as_micros() as u64, }); self.frame_start_time = new_time; + + if let Some(choreographer) = self.choreographer.as_ref() { + let proxy = self.proxy.clone(); + choreographer.post_vsync_callback(Box::new(move |frame| { + // eprintln!("New frame"); + // let frame_time = frame.frame_time(); + // let preferred_index = frame.preferred_frame_timeline_index(); + // for timeline in 0..frame.frame_timelines_length() { + // eprintln!( + // "{:?} {}", + // frame.frame_timeline_deadline(timeline) - frame_time, + // if timeline == preferred_index { + // "(Preferred)" + // } else { + // "" + // } + // ); + // } + // eprintln!("{frame:?}"); + proxy + .send_event(UserEvent::ChoreographerFrame(window_id)) + .unwrap(); + })); + self.animation_in_flight = true; + } else { + window.request_redraw(); + } } _ => {} } @@ -678,12 +708,14 @@ impl<'s> ApplicationHandler for VelloApp<'s> { * self.transform; } - if let Some(render_state) = &mut self.state { - render_state.window.request_redraw(); - } + // if let Some(render_state) = &mut self.state { + // if !self.animation_in_flight { + // render_state.window.request_redraw(); + // } + // } } - fn user_event(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) { + fn user_event(&mut self, event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) { match event { #[cfg(not(any(target_arch = "wasm32", target_os = "android")))] UserEvent::HotReload => { @@ -703,6 +735,10 @@ impl<'s> ApplicationHandler for VelloApp<'s> { Err(e) => log::error!("Failed to reload shaders: {e}"), } } + UserEvent::ChoreographerFrame(window_id) => { + self.animation_in_flight = false; + self.window_event(event_loop, window_id, WindowEvent::RedrawRequested); + } } } @@ -819,6 +855,10 @@ fn run( prev_scene_ix: 0, modifiers: ModifiersState::default(), debug, + // We know looper is active since we have the `EventLoop` + choreographer: ndk::choreographer::Choreographer::instance(), + proxy: event_loop.create_proxy(), + animation_in_flight: false, }; event_loop.run_app(&mut app).expect("run to completion"); @@ -857,6 +897,7 @@ fn window_attributes() -> WindowAttributes { enum UserEvent { #[cfg(not(any(target_arch = "wasm32", target_os = "android")))] HotReload, + ChoreographerFrame(WindowId), } #[cfg(target_arch = "wasm32")] diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index 7dacf9c9..729a392f 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,3 +1,5 @@ +#![deny(unsafe_op_in_unsafe_fn)] + use std::{ collections::VecDeque, sync::{ @@ -9,7 +11,10 @@ use std::{ }; use vello::Scene; -use wgpu::{Buffer, SubmissionIndex, SurfaceTexture}; +use wgpu::{ + hal::vulkan, Buffer, Instance, SubmissionIndex, Surface, SurfaceConfiguration, SurfaceTarget, + SurfaceTexture, TextureFormat, +}; /// Docs used to type out how this is being reasoned about. /// @@ -80,22 +85,124 @@ use wgpu::{Buffer, SubmissionIndex, SurfaceTexture}; pub struct Thinking; pub struct FrameRenderRequest { - scene: vello::Scene, - frame: FrameId, - expected_present: u64, + pub scene: vello::Scene, + pub frame: FrameId, + pub expected_present: u64, // In general, if touch is held, will need the next frame. - needs_next_frame: bool, // TODO: No, LatencyOptimised, ConsistencyOptimised? - present_immediately: bool, - paint_start: Instant, + pub needs_next_frame: bool, // TODO: No, LatencyOptimised, ConsistencyOptimised? + pub present_immediately: bool, + pub paint_start: Instant, +} + +pub enum VelloControl { + Frame(FrameRenderRequest), + /// A resize request. This might skip rendering a previous frame + /// if it arrives before that frame is presented. + /// + /// The second parameter is (width, height). + Resize(FrameRenderRequest, (u32, u32), Sender), +} + +pub struct VelloPacingConfiguration { + queue: Arc, + device: Arc, + surface: Surface<'static>, + adapter: Arc, + config: SurfaceConfiguration, +} + +pub fn launch( + instance: &wgpu::Instance, + mut params: VelloPacingConfiguration, +) -> Sender { + let (tx, rx) = std::sync::mpsc::channel(); + let display_timing = if params + .device + .features() + .contains(wgpu::Features::VULKAN_GOOGLE_DISPLAY_TIMING) + { + unsafe { + params + .device + // Safety: + // We do not destroy the device handle we are given. + .as_hal::(|device| { + let device = device?; + // Safety: + // We do not destroy the instance we are given. + let instance = instance.as_hal::()?; + Some(ash::google::display_timing::Device::new( + instance.shared_instance().raw_instance(), + device.raw_device(), + )) + }) + .flatten() + } + } else { + None + }; + // Ensure that the surface is compatible with this device. + params.surface.configure(¶ms.device, ¶ms.config); + let refresh_rate = display_timing + .as_ref() + .and_then(|display_timing| unsafe { + // Safety: We don't manually destroy the surface + params + .surface + .as_hal::(|surface| { + let surface = surface?; + // Safety: We know the device and the swapchain are compatible, based on the above configure + Some( + display_timing + .get_refresh_cycle_duration(surface.raw_swapchain()?) + .ok()? + .refresh_duration, + ) + }) + .flatten() + }) + .unwrap_or(0); + + let pacing = VelloPacing { + rx, + queue: params.queue, + device: params.device, + google_display_timing_ext_device: display_timing, + adapter: params.adapter, + surface: params.surface, + surface_config: params.config, + stats: Default::default(), + refresh_rate, + mapped_unused_download_buffers: Default::default(), + mapped_unused_download_buffers_scratch: Default::default(), + free_download_buffers: Default::default(), + presenting_frame: None, + gpu_working_frame: None, + }; + pacing.start(); + tx } -pub struct FrameStats { +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct FrameId(u32); + +impl FrameId { + pub fn next(self) -> Self { + Self(self.0.wrapping_add(1)) + } + + pub fn raw(self) -> u32 { + self.0 + } +} + +struct FrameStats { /// When the rendering work started on the GPU, in nanoseconds. /// /// Used to estimate how long frames are taking to render, to get /// faster feedback on whether we should request a slower (or faster) display mode. - /// (We choose to be more conservative in requesting a faster display mode, but - /// act quickly on requesting a slower one.) + /// (We might choose to be more conservative in requesting a faster display mode, but + /// act quickly on requesting a slower one?) render_start: u64, /// When the rendering work finished on the GPU, in nanoseconds. /// @@ -128,36 +235,30 @@ pub struct FrameStats { presentation_time: Option, } -pub struct InFlightStatus {} - -pub struct InFlightFrame { +struct InFlightFrame { download_map_buffer: Buffer, work_complete: Arc, paint_start: Instant, id: FrameId, submission_index: SubmissionIndex, + width: u32, + height: u32, /// Information needed to perform a presentation, and not before. required_to_present: Option<(SurfaceTexture, Scene)>, estimated_present: u64, next_frame_expected: bool, } -pub enum VelloControl { - Frame(FrameRenderRequest), - Stop, - /// A resize request. This might skip rendering a previous frame - /// if it arrives before that frame is presented. - Resize(FrameRenderRequest, (u32, u32), Sender), -} - /// The state of the frame pacing controller thread. -pub struct VelloPacing { +struct VelloPacing { rx: Receiver, queue: Arc, device: Arc, - google_display_timing_ext_devices: Vec>, adapter: Arc, surface: wgpu::Surface<'static>, + + google_display_timing_ext_device: Option, + surface_config: SurfaceConfiguration, /// Stats from previous frames, stored in a ring buffer (max capacity ~10?). stats: VecDeque<(FrameId, FrameStats)>, /// The refresh rate reported "by the system". @@ -168,32 +269,16 @@ pub struct VelloPacing { free_download_buffers: Vec<(Buffer, Arc)>, /// Details about the previous frame, which has already been presented. presenting_frame: Option, - /// Details about the frame whose work has been submitted to the. + /// Details about the frame whose work has been submitted to the GPU, but not yet presented. gpu_working_frame: Option, } /// A sketch of the expected API. impl VelloPacing { - pub fn new() -> Self { - todo!() - } - - pub fn launch(self) { + fn start(self) { std::thread::spawn(move || self.run()); } - /// Run a rendering task until presentation. Useful on macOS for resizing. - pub fn present_synchronously(&mut self) { - let token: () = self.present_immediately(); - self.wait_on_present(token); - } - - pub fn present_immediately(&mut self) {} - - fn wait_on_present(&mut self, (): ()) {} - - pub fn stop(&mut self) {} - fn run(mut self) { loop { let timeout = if self.frame_in_flight() { @@ -213,23 +298,7 @@ impl VelloPacing { self.paint_frame(request.scene, texture); self.poll_frame(); } - VelloControl::Stop => { - // TODO: - if let Some(mut old_frame) = self.gpu_working_frame.take() { - // This frame will never be presented - drop(old_frame.required_to_present.take()); - } - // self.device.poll(wgpu::MaintainBase::Wait); - // What do we need to be careful about dropping? - // Do we need to run the GPU - break; - } - #[expect( - unreachable_code, - unused_variables, - reason = "We stub out the unused variables" - )] - VelloControl::Resize(request, (_, _), done) => { + VelloControl::Resize(request, (width, height), done) => { // Cancel the frame which hasn't been scheduled for presentation. if let Some(mut old_frame) = self.gpu_working_frame.take() { // This frame will never be presented @@ -241,18 +310,16 @@ impl VelloPacing { // 1) The previous frame didn't succeed // 2) We are trying to resize // We choose not to address this presently, because it is a. - self.poll_frame(); - // self.surface - // .configure(&self.device, SurfaceConfiguration { width, height }); - unimplemented!(); + if let Some(old_presenting) = self.presenting_frame.take() { + self.abandon(old_presenting); + } + self.surface_config.width = width; + self.surface_config.height = height; + self.surface.configure(&self.device, &self.surface_config); let texture = self.surface.get_current_texture().unwrap(); let frame = self.paint_frame_inner(&request.scene, &texture); texture.present(); - if let Some(old_presenting) = self.presenting_frame.take() { - self.abandon(old_presenting); - } - // TODO: Maybe: self.abandoned_frames.extend(self.presenting_frame.take()); self.presenting_frame = Some(frame); if let Err(e) = done.send(request.frame) { tracing::error!("Failed to send present result {e}"); @@ -263,10 +330,14 @@ impl VelloPacing { continue; } Err(RecvTimeoutError::Disconnected) => { - // TODO: Is this just the implicit stop command? - tracing::error!( - "The main thread has stopped without telling rendering to stop" - ); + // TODO: Is this an error, or the right way to signal to stop rendering? + if let Some(mut old_frame) = self.gpu_working_frame.take() { + // This frame will never be presented + drop(old_frame.required_to_present.take()); + } + // What do we need to be careful about dropping? + // Do we need to run the GPU the completion? + // self.device.poll(wgpu::MaintainBase::Wait); break; } Err(RecvTimeoutError::Timeout) => { @@ -331,7 +402,7 @@ impl VelloPacing { if failed { // Perform reallocation. Will be part of https://github.com/linebender/vello/pull/606. } - // The time which we should not present before. + // The time which the "next" frame (the `gpu_working_frame`) should not present before. // If `map_result` indicates we really badly overflowed the available time, // then this will be later than otherwise expected, to avoid a stutter. // See https://developer.android.com/games/sdk/frame-pacing @@ -403,8 +474,46 @@ impl VelloPacing { }; } texture.present(); - if let Some(_swc) = swc { - // Load past present timing information + if let Some(swc) = swc { + // We load the past present timing information, because the timings we get access to were updated + // in response to `present`. + // This is because https://android.googlesource.com/platform/frameworks/native/+/refs/heads/main/vulkan/libvulkan/swapchain.cpp#2394 + // is called inside `QueuePresentKHR` + if let Some(device) = self.google_display_timing_ext_device.as_ref() { + // Safety: We validated that the swapchain came from the same device. + let timing_info = unsafe { device.get_past_presentation_timing(swc) }; + match timing_info { + Ok(timing_info) => { + 'outer: for info in timing_info { + for (frame_id, stats) in &mut self.stats { + if frame_id.0 == info.present_id { + // TODO: Can there be multiple of these for the same present id? + stats.presentation_time = Some(info); + continue 'outer; + } + } + // TODO: This would be possible if we clear out items which are too old, in additional to those which are too far behind. + if false { + // Maybe we should warn once here? + tracing::warn!( + "Got present timing information for unknown frame '{}'", + info.present_id + ); + } + } + } + // All the possible errors are pretty fatal + Err(err) => tracing::error!( + "Got {err} whilst trying to get presentation timing results" + ), + } + // Safety: We validated that the swapchain came from the same device. + let refresh_rate = unsafe { device.get_refresh_cycle_duration(swc) }; + self.refresh_rate = refresh_rate + .ok() + .map(|it| it.refresh_duration) + .unwrap_or(self.refresh_rate); + } } if working_frame.next_frame_expected { // Do the maths for when we should ask the main thread for the next frame @@ -460,22 +569,3 @@ impl VelloPacing { } } } - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct FrameId(u32); - -impl FrameId { - pub fn next(self) -> Self { - Self(self.0.wrapping_add(1)) - } - - pub fn raw(self) -> u32 { - self.0 - } -} - -impl Default for VelloPacing { - fn default() -> Self { - Self::new() - } -} From f484209f8f69a3e6d823d1e6f6b1bff35d3f0ba2 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 30 Sep 2024 08:36:02 +0100 Subject: [PATCH 09/13] Start thinking about a proper integration with AChoreographer Start sketching the fully choreographed version. Allow negative timestamp --- vello_pacing/Cargo.toml | 2 + vello_pacing/src/choreographed.rs | 113 ++++++++++++++++++++++++++++++ vello_pacing/src/lib.rs | 2 + 3 files changed, 117 insertions(+) create mode 100644 vello_pacing/src/choreographed.rs diff --git a/vello_pacing/Cargo.toml b/vello_pacing/Cargo.toml index 96986764..076ea144 100644 --- a/vello_pacing/Cargo.toml +++ b/vello_pacing/Cargo.toml @@ -11,6 +11,8 @@ wgpu.workspace = true vello.workspace = true ash = { version = "0.38.0", default-features = false } tracing = "0.1.40" +ndk = { version = "0.9", features = ["api-level-33"] } +nix = { default-features = false, features = ["time"], version = "0.29.0" } [lints] workspace = true diff --git a/vello_pacing/src/choreographed.rs b/vello_pacing/src/choreographed.rs new file mode 100644 index 00000000..aea07fac --- /dev/null +++ b/vello_pacing/src/choreographed.rs @@ -0,0 +1,113 @@ +use std::ops::Mul; + +use nix::time::ClockId; + +/// A slightly tweaked version of the thinking, now that we have an understanding of `AChoreographer`. +/// +/// Observations: +/// 1) A frame drop can happen because CPU or GPU work overruns. +/// 2) GPU work starts ~a fixed time after the end of the [`wgpu::Queue::submit`] call. +/// 3) We can predict a frame drop due to CPU time problems due to this case. +/// 4) Just dropping a frame is better than stuttering when we do so. +/// +/// We need to think about three cases: +/// +/// 1) The CPU-side work to prepare a scene is longer than one vsync. We ignore this case due to parallel command construction. +/// 2) The GPU-side work to prepare a frame is longer than one vsync. +/// 3) The total GPU+CPU side work is longer than one vsync (but individually each is shorter) +/// 4) Neither is the case. +/// +/// For the first draft of this feature, we focus only on the third of these. +/// I.e. both the CPU and GPU side work of a frame are relatively cheap. +/// N.B. we do `Scene` preparation on the main thread, but it is included in +/// this CPU-side work. +/// +/// The rendering loop goes as follows: +/// +/// 1) We submit frame A. +/// 2) We start the CPU side work for frame B at the estimated start time. +/// 3) We race wait until the *deadline* for frame A with the CPU side work for frame B. +/// 4) If the deadline happened first (normal case, GPU work less than 1 frame), we compare +/// the timestamp of the end of the blit pass with the deadline. +/// +/// For the moment, we ignore the possibility of a frame failing. +/// That doesn't actually change any behaviour here, because we render with `MailBox`. +pub struct Thinking; + +// We generally want to be thinking about two frames at a time, except for some statistical modelling. + +/// A timestamp in `CLOCK_MONOTONIC` +/// +/// For simplicity, all timestamps are treated as happening in the `CLOCK_MONOTONIC` timebase. +/// We'll validate that GPU performance counter timestamps meet this expectation as it becomes relevant. +/// +/// This might not actually be true - the timebase of the return values from [`ndk::choreographer::ChoreographerFrameCallbackData`] +/// aren't documented by +struct Timestamp(i64); + +impl Mul for Timestamp { + type Output = Self; + + fn mul(self, rhs: i64) -> Self::Output { + Self(self.0 * rhs) + } +} + +impl Timestamp { + const fn from_nanos(nanos: i64) -> Self { + Self(nanos) + } + + const fn from_micros(micros: i64) -> Self { + Self::from_nanos(micros * 1_000) + } + + const fn from_millis(millis: i64) -> Self { + Self::from_nanos(millis * 1_000_000) + } + + /// Get the current time in `CLOCK_MONOTONIC`. + /// + /// TODO: This assumed the returned value is not negative. + /// Hopefully that's fine? + fn now() -> Self { + let spec = nix::time::clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap(); + Self(spec.tv_sec() * 1_000_000_000 + spec.tv_nsec()) + } +} + +/// A margin of latency which we *always* render against for safety. +const DEADLINE_MARGIN: Timestamp = Timestamp::from_millis(2); + +/// A margin of latency before the deadline, which if we aren't before, we assume that the +/// frame probably missed the deadline. +/// +/// In those cases, we bring future frames forward. +const DEADLINE_ASSUME_FAILED: Timestamp = Timestamp::from_micros(500); + +struct OngoingFrame { + /// The [present time][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_expected_presentation_time]. + target_present_time: Timestamp, + /// The [vsync id][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_vsync_id] we're aiming for. + target_vsync_id: i64, + /// The deadline which this frame needs to meet to be rendered at `target_present_time`. + /// + /// We aim for a time [`DEADLINE_MARGIN`] before the deadline. + target_deadline: Timestamp, + + /// The time at which we wanted to start this frame. + /// + /// `start_time` should try to be `requested_start_time - EPSILON`, + /// but if this is far off, we know early that we might drop this frame (and so should request + /// the next frame super early). + /// If this is significantly off, then we will likely drop this frame to avoid stuttering. + requested_start_time: Timestamp, + + /// The time at which `Scene` [rendering](`vello::Renderer::render_to_texture`) began. + /// + /// TODO: Does this include `Scene` construction time? + start_time: Timestamp, + + /// The time at which [`wgpu::Queue::submit`] finished for this frame. + submit_time: Timestamp, +} diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index 729a392f..3fb675ec 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,5 +1,7 @@ #![deny(unsafe_op_in_unsafe_fn)] +mod choreographed; + use std::{ collections::VecDeque, sync::{ From f232e0f29553ad752348a507d1531b8c4e307388 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:23:01 +0100 Subject: [PATCH 10/13] More experimentation --- Cargo.lock | 3696 +++++++++++++++++++++++++++++ examples/with_winit/Cargo.toml | 6 +- examples/with_winit/src/lib.rs | 117 +- vello_pacing/src/choreographed.rs | 167 +- 4 files changed, 3944 insertions(+), 42 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..69a34c77 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3696 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ab_glyph" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.6.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_log-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" + +[[package]] +name = "android_logger" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "android_trace" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d564b0f7a9c9e272c7e43c59f1f09ba04d060774ba7c5fa14c2f966bbd6c4e" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bit-set" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f" +dependencies = [ + "bit-vec 0.7.0", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec 0.8.0", +] + +[[package]] +name = "bit-vec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.6.0", + "log", + "polling", + "rustix", + "slab", + "thiserror", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cargo-run-wasm" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9c33bbfab116bda01ec67729b988895b34167a1e9cf034343099092421ed43" +dependencies = [ + "devserver_lib", + "pico-args", + "serde_json", + "wasm-bindgen-cli-support", +] + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "cmake" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +dependencies = [ + "cc", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "cursor-icon" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + +[[package]] +name = "d3d12" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbd1f579714e3c809ebd822c81ef148b1ceaeb3d535352afc73fd0c4c6a0017" +dependencies = [ + "bitflags 2.6.0", + "libloading", + "winapi", +] + +[[package]] +name = "devserver_lib" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf215dbb8cb1409cca7645aaed35f9e39fb0a21855bba1ac48bc0334903bf66" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fdeflate" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "font-types" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dda6e36206148f69fc6ecb1bb6c0dedd7ee469f3db1d0dc2045beea28430ca43" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glow" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glow" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.6.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7" +dependencies = [ + "log", + "presser", + "thiserror", + "winapi", + "windows 0.52.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror", + "windows 0.58.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" +dependencies = [ + "bitflags 2.6.0", + "gpu-descriptor-types", + "hashbrown 0.14.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.6.0", + "com", + "libc", + "libloading", + "thiserror", + "widestring", + "winapi", +] + +[[package]] +name = "headless" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "env_logger", + "futures-intrusive", + "png", + "pollster", + "scenes", + "vello", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "image" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc144d44a31d753b02ce64093d532f55ff8dc4ebf2ffb8a63c0dda691385acae" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", + "serde", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "kurbo" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" +dependencies = [ + "arrayvec", + "smallvec", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.7", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "metal" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "naga" +version = "22.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9#aeac0f29fed2ae4240869c8ff419ea93523d32d9" +dependencies = [ + "arrayvec", + "bit-set 0.8.0", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "hexf-parse", + "indexmap 2.6.0", + "log", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "naga" +version = "22.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad" +dependencies = [ + "arrayvec", + "bit-set 0.6.0", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "hexf-parse", + "indexmap 2.6.0", + "log", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "git+https://github.com/djmcnab/ndk/?rev=81627a7564982a04027a49d538cac1686d870dbd#81627a7564982a04027a49d538cac1686d870dbd" +dependencies = [ + "bitflags 2.6.0", + "jni-sys", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "git+https://github.com/djmcnab/ndk/?rev=81627a7564982a04027a49d538cac1686d870dbd#81627a7564982a04027a49d538cac1686d870dbd" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify-debouncer-mini" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43" +dependencies = [ + "crossbeam-channel", + "log", + "notify", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "nv-flip" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec3c68ac226790270de1d9d0eb5853832d82a34b62199ab2a1a4756df1a1974" +dependencies = [ + "nv-flip-sys", +] + +[[package]] +name = "nv-flip-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "932e1eed40002ba70fccac6dab3b64be3301607c3ee88bd14989c4d4e1c1c993" +dependencies = [ + "cc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.7", + "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 = "peniko" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a648c93f502a0bef0a9cb47fa1335994958a2744667d3f82defe513f276741a" +dependencies = [ + "kurbo", + "smallvec", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "png" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", + "tracing", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn 2.0.85", +] + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "range-alloc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "read-fonts" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a04b892cb6f91951f144c33321843790c8574c825aafdb16d815fd7183b5229" +dependencies = [ + "bytemuck", + "font-types", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "run_wasm" +version = "0.0.0" +dependencies = [ + "cargo-run-wasm", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[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.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scenes" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "getrandom", + "image", + "rand", + "roxmltree", + "vello", + "web-time", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "sdl2" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "libc", + "raw-window-handle", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" +dependencies = [ + "cfg-if", + "cmake", + "libc", + "version-compare", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[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 = "simple" +version = "0.0.0" +dependencies = [ + "anyhow", + "pollster", + "vello", + "winit", +] + +[[package]] +name = "simple_sdl2" +version = "0.0.0" +dependencies = [ + "pollster", + "sdl2", + "vello", +] + +[[package]] +name = "skrifa" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe" +dependencies = [ + "bytemuck", + "read-fonts", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.6.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix", + "thiserror", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "svg_fmt" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", +] + +[[package]] +name = "tracing_android_trace" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fae205f9c07bfae3d36d199ab985118c90d225ff70a38e7ff3ecbdb4ef61bc" +dependencies = [ + "android_trace", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "ttf-parser" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5902c5d130972a0000f60860bfbf46f7ca3db5391eddfedd1b8728bd9dc96c0e" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vello" +version = "0.3.0" +dependencies = [ + "bytemuck", + "futures-intrusive", + "log", + "peniko", + "png", + "raw-window-handle", + "skrifa", + "static_assertions", + "thiserror", + "vello_encoding", + "vello_shaders", + "wgpu 22.0.0", + "wgpu-profiler", +] + +[[package]] +name = "vello_encoding" +version = "0.3.0" +dependencies = [ + "bytemuck", + "guillotiere", + "peniko", + "skrifa", + "smallvec", +] + +[[package]] +name = "vello_pacing" +version = "0.3.0" +dependencies = [ + "ash", + "ndk", + "nix", + "tracing", + "vello", + "wgpu 22.0.0", +] + +[[package]] +name = "vello_shaders" +version = "0.3.0" +dependencies = [ + "bytemuck", + "naga 22.1.0", + "thiserror", + "vello_encoding", +] + +[[package]] +name = "vello_tests" +version = "0.0.0" +dependencies = [ + "anyhow", + "futures-intrusive", + "image", + "nv-flip", + "png", + "pollster", + "scenes", + "vello", +] + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "walrus" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68aa3c7b80be75c8458fc087453e5a31a226cfffede2e9b932393b2ea1c624a" +dependencies = [ + "anyhow", + "gimli", + "id-arena", + "leb128", + "log", + "walrus-macro", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "walrus-macro" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ad39ff894c43c9649fa724cdde9a6fc50b855d517ef071a93e5df82fe51d3" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.85", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-cli-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b21cf9e89b196d78ff95c442a8076cc417171001e75dc062fe2c421cd2a0f9" +dependencies = [ + "anyhow", + "base64", + "log", + "rustc-demangle", + "serde", + "serde_json", + "tempfile", + "unicode-ident", + "walrus", + "wasm-bindgen-externref-xform", + "wasm-bindgen-multi-value-xform", + "wasm-bindgen-shared", + "wasm-bindgen-threads-xform", + "wasm-bindgen-wasm-conventions", + "wasm-bindgen-wasm-interpreter", +] + +[[package]] +name = "wasm-bindgen-externref-xform" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9f5eaefdb356e4266ca53d76526f5500e1e3b0961da8ee932193f08ada25ec7" +dependencies = [ + "anyhow", + "walrus", + "wasm-bindgen-wasm-conventions", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-multi-value-xform" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22689c6bbdc7f3a9110f1aa21873398a7ab2c50474ba9a45595c9ffde49c0cd" +dependencies = [ + "anyhow", + "walrus", + "wasm-bindgen-wasm-conventions", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "wasm-bindgen-threads-xform" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17d3c6389a7c8fa49ee4f55847d01b74c640a60387598952cdf3211b8499520c" +dependencies = [ + "anyhow", + "walrus", + "wasm-bindgen-wasm-conventions", +] + +[[package]] +name = "wasm-bindgen-wasm-conventions" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b4d6bf2704173b57d7f319316593a35f2102e18bc92251d96909f89e7d4595" +dependencies = [ + "anyhow", + "leb128", + "log", + "walrus", + "wasmparser", +] + +[[package]] +name = "wasm-bindgen-wasm-interpreter" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b123244c6bf9e7abbb6ad9aa98ed86f927b55ee9d95b5552dd9346910341d5e2" +dependencies = [ + "anyhow", + "log", + "walrus", + "wasm-bindgen-wasm-conventions", +] + +[[package]] +name = "wasm-encoder" +version = "0.212.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501940df4418b8929eb6d52f1aade1fdd15a5b86c92453cb696e3c906bd3fc33" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasmparser" +version = "0.212.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d28bc49ba1e5c5b61ffa7a2eace10820443c4b7d1c0b144109261d14570fdf8" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "hashbrown 0.14.5", + "indexmap 2.6.0", + "semver", + "serde", +] + +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" +dependencies = [ + "bitflags 2.6.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.6.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" +dependencies = [ + "rustix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b31cab548ee68c7eb155517f2212049dc151f7cd7910c2b66abfd31c3ee12bd" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "22.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9#aeac0f29fed2ae4240869c8ff419ea93523d32d9" +dependencies = [ + "arrayvec", + "cfg_aliases 0.1.1", + "document-features", + "js-sys", + "log", + "naga 22.0.0", + "parking_lot", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core 22.0.0", + "wgpu-hal 22.0.0 (git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9)", + "wgpu-types 22.0.0 (git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9)", +] + +[[package]] +name = "wgpu" +version = "22.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d1c4ba43f80542cf63a0a6ed3134629ae73e8ab51e4b765a67f3aa062eb433" +dependencies = [ + "arrayvec", + "cfg_aliases 0.1.1", + "document-features", + "js-sys", + "log", + "naga 22.1.0", + "parking_lot", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core 22.1.0", + "wgpu-hal 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wgpu-types 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wgpu-core" +version = "22.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9#aeac0f29fed2ae4240869c8ff419ea93523d32d9" +dependencies = [ + "arrayvec", + "bit-vec 0.8.0", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "document-features", + "indexmap 2.6.0", + "log", + "naga 22.0.0", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "wgpu-hal 22.0.0 (git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9)", + "wgpu-types 22.0.0 (git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9)", +] + +[[package]] +name = "wgpu-core" +version = "22.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348c840d1051b8e86c3bcd31206080c5e71e5933dabd79be1ce732b0b2f089a" +dependencies = [ + "arrayvec", + "bit-vec 0.7.0", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "document-features", + "indexmap 2.6.0", + "log", + "naga 22.1.0", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "wgpu-hal 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wgpu-types 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wgpu-hal" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6bbf4b4de8b2a83c0401d9e5ae0080a2792055f25859a02bf9be97952bbed4f" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set 0.6.0", + "bitflags 2.6.0", + "block", + "cfg_aliases 0.1.1", + "core-graphics-types", + "d3d12", + "glow 0.13.1", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator 0.26.0", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga 22.1.0", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types 22.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", +] + +[[package]] +name = "wgpu-hal" +version = "22.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9#aeac0f29fed2ae4240869c8ff419ea93523d32d9" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set 0.8.0", + "bitflags 2.6.0", + "block", + "cfg_aliases 0.1.1", + "core-graphics-types", + "glow 0.14.2", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator 0.27.0", + "gpu-descriptor", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga 22.0.0", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types 22.0.0 (git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9)", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "wgpu-profiler" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06b2cee91fdc885ff0d3d714c59810cc72c6d84b81b0eaa48bab8ff2ad54fb5b" +dependencies = [ + "parking_lot", + "thiserror", + "wgpu 22.1.0", +] + +[[package]] +name = "wgpu-types" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9d91f0e2c4b51434dfa6db77846f2793149d8e73f800fa2e41f52b8eac3c5d" +dependencies = [ + "bitflags 2.6.0", + "js-sys", + "web-sys", +] + +[[package]] +name = "wgpu-types" +version = "22.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=aeac0f29fed2ae4240869c8ff419ea93523d32d9#aeac0f29fed2ae4240869c8ff419ea93523d32d9" +dependencies = [ + "bitflags 2.6.0", + "js-sys", + "web-sys", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winit" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.6.0", + "block2", + "bytemuck", + "calloop", + "cfg_aliases 0.2.1", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "with_winit" +version = "0.0.0" +dependencies = [ + "android_logger", + "anyhow", + "ash", + "clap", + "console_error_panic_hook", + "console_log", + "env_logger", + "getrandom", + "log", + "ndk", + "notify-debouncer-mini", + "pollster", + "profiling", + "scenes", + "tracing", + "tracing-subscriber", + "tracing_android_trace", + "vello", + "vello_shaders", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "wgpu-profiler", + "winit", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xcursor" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.6.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-jpeg" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +dependencies = [ + "zune-core", +] diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 8c49b95d..848c0222 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -63,7 +63,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = "registry", ] } profiling = { version = "1.0.15", features = ["profile-with-tracing"] } -ndk = { version = "0.9", features = ["api-level-33"] } +ndk = { version = "0.9", features = ["api-level-33", "nativewindow"] } [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.7" @@ -75,3 +75,7 @@ getrandom = { version = "0.2.15", features = ["js"] } [package.metadata.android.application] debuggable = true + +[package.metadata.android.sdk] +target_sdk_version = 33 +min_sdk_version = 33 diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index d9dc2263..76dfb19f 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -6,6 +6,7 @@ use std::collections::HashSet; use std::num::NonZeroUsize; +use std::rc::Rc; use std::sync::Arc; #[cfg(not(target_arch = "wasm32"))] @@ -16,6 +17,8 @@ use web_time::Instant; use winit::application::ApplicationHandler; use winit::event::*; use winit::keyboard::*; +use winit::raw_window_handle::HasRawWindowHandle; +use winit::raw_window_handle::HasWindowHandle; use winit::window::WindowId; #[cfg(all(feature = "wgpu-profiler", not(target_arch = "wasm32")))] @@ -169,7 +172,7 @@ struct VelloApp<'s> { modifiers: ModifiersState, debug: DebugLayers, - choreographer: Option, + choreographer: Option>, animation_in_flight: bool, proxy: winit::event_loop::EventLoopProxy, } @@ -405,13 +408,45 @@ impl<'s> ApplicationHandler for VelloApp<'s> { // in a touch context (i.e. Windows/Linux/MacOS with a touch screen could // also be using mouse/keyboard controls) // Note that winit's rendering is y-down - if let Some(RenderState { surface, .. }) = &self.state { + if let Some(RenderState { surface, window }) = &self.state { if touch.location.y > surface.config.height as f64 * 2. / 3. { self.navigation_fingers.insert(touch.id); // The left third of the navigation zone navigates backwards if touch.location.x < surface.config.width as f64 / 3. { + if let wgpu::rwh::RawWindowHandle::AndroidNdk( + android_ndk_window_handle, + ) = window.window_handle().unwrap().as_raw() + { + let window = unsafe { + ndk::native_window::NativeWindow::clone_from_ptr( + android_ndk_window_handle.a_native_window.cast(), + ) + }; + window + .set_frame_rate( + 60., + ndk::native_window::FrameRateCompatibility::Default, + ) + .unwrap(); + } self.scene_ix = self.scene_ix.saturating_sub(1); } else if touch.location.x > 2. * surface.config.width as f64 / 3. { + if let wgpu::rwh::RawWindowHandle::AndroidNdk( + android_ndk_window_handle, + ) = window.window_handle().unwrap().as_raw() + { + let window = unsafe { + ndk::native_window::NativeWindow::clone_from_ptr( + android_ndk_window_handle.a_native_window.cast(), + ) + }; + window + .set_frame_rate( + 90., + ndk::native_window::FrameRateCompatibility::Default, + ) + .unwrap(); + } self.scene_ix = self.scene_ix.saturating_add(1); } } @@ -608,9 +643,9 @@ impl<'s> ApplicationHandler for VelloApp<'s> { // let result = display_timing.get_refresh_cycle_duration(swc); // eprintln!("Refresh duration: {result:?}"); if present_id % 5 == 0 { - let result = display_timing.get_past_presentation_timing(swc); - eprintln!("Display timings: {result:?}"); - eprintln!("Most recent present id: {}", present_id); + // let result = display_timing.get_past_presentation_timing(swc); + // eprintln!("Display timings: {result:?}"); + // eprintln!("Most recent present id: {}", present_id); } } } @@ -666,27 +701,27 @@ impl<'s> ApplicationHandler for VelloApp<'s> { if let Some(choreographer) = self.choreographer.as_ref() { let proxy = self.proxy.clone(); - choreographer.post_vsync_callback(Box::new(move |frame| { - // eprintln!("New frame"); - // let frame_time = frame.frame_time(); - // let preferred_index = frame.preferred_frame_timeline_index(); - // for timeline in 0..frame.frame_timelines_length() { - // eprintln!( - // "{:?} {}", - // frame.frame_timeline_deadline(timeline) - frame_time, - // if timeline == preferred_index { - // "(Preferred)" - // } else { - // "" - // } - // ); - // } - // eprintln!("{frame:?}"); - proxy - .send_event(UserEvent::ChoreographerFrame(window_id)) - .unwrap(); - })); - self.animation_in_flight = true; + // choreographer.post_vsync_callback(Box::new(move |frame| { + // eprintln!("New frame"); + // let frame_time = frame.frame_time(); + // let preferred_index = frame.preferred_frame_timeline_index(); + // for timeline in 0..(frame.frame_timelines_length().min(3)) { + // eprintln!( + // "{:?} {}", + // frame.frame_timeline_deadline(timeline) - frame_time, + // if timeline == preferred_index { + // "(Preferred)" + // } else { + // "" + // } + // ); + // } + // eprintln!("{frame:?}"); + // // proxy + // // .send_event(UserEvent::ChoreographerFrame(window_id)) + // // .unwrap(); + // })); + window.request_redraw(); } else { window.request_redraw(); } @@ -856,10 +891,38 @@ fn run( modifiers: ModifiersState::default(), debug, // We know looper is active since we have the `EventLoop` - choreographer: ndk::choreographer::Choreographer::instance(), + choreographer: ndk::choreographer::Choreographer::instance().map(Rc::new), proxy: event_loop.create_proxy(), animation_in_flight: false, }; + if let Some(choreographer) = app.choreographer.as_ref() { + fn post_callback(choreographer: &Rc) { + let new_choreographer = Rc::clone(choreographer); + choreographer.post_vsync_callback(Box::new(move |frame| { + eprintln!("New frame"); + let frame_time = frame.frame_time(); + let preferred_index = frame.preferred_frame_timeline_index(); + for timeline in 0..(frame.frame_timelines_length().min(4)) { + eprintln!( + "{:?} {}", + frame.frame_timeline_deadline(timeline) - frame_time, + if timeline == preferred_index { + "(Preferred)" + } else { + "" + } + ); + } + eprintln!("{frame:?}"); + post_callback(&new_choreographer); + })); + } + // post_callback(choreographer); + choreographer.register_refresh_rate_callback(Box::new(|value| { + let span = tracing::info_span!("Getting a new refresh rate", ?value).entered(); + eprintln!("New refresh rate Testing: {value:?}; {}", value.as_nanos()); + })); + } event_loop.run_app(&mut app).expect("run to completion"); } diff --git a/vello_pacing/src/choreographed.rs b/vello_pacing/src/choreographed.rs index aea07fac..9f261721 100644 --- a/vello_pacing/src/choreographed.rs +++ b/vello_pacing/src/choreographed.rs @@ -1,6 +1,21 @@ -use std::ops::Mul; - +#![allow(unused)] +#![warn(unused_variables)] + +use std::{ + cell::RefCell, + mem::ManuallyDrop, + ops::Mul, + rc::Rc, + sync::mpsc::{self, Receiver}, + time::Duration, +}; + +use ndk::{ + choreographer::Choreographer, + looper::{self, ForeignLooper}, +}; use nix::time::ClockId; +use vello::Scene; /// A slightly tweaked version of the thinking, now that we have an understanding of `AChoreographer`. /// @@ -34,6 +49,30 @@ use nix::time::ClockId; /// That doesn't actually change any behaviour here, because we render with `MailBox`. pub struct Thinking; +enum PacingCommand {} + +pub struct PacingChannel { + waker: ForeignLooper, + channel: ManuallyDrop>, +} + +impl PacingChannel { + fn send_command(&self, command: PacingCommand) { + self.channel.send(command); + // We add to the channel before waking, so that the event will be received by the right wake. + self.waker.wake(); + } +} + +impl Drop for PacingChannel { + fn drop(&mut self) { + // Safety: We don't use `self.channel` after this line. + // We drop the value before performing the wake, so that we instantly know that the drop has happened. + unsafe { ManuallyDrop::drop(&mut self.channel) }; + self.waker.wake(); + } +} + // We generally want to be thinking about two frames at a time, except for some statistical modelling. /// A timestamp in `CLOCK_MONOTONIC` @@ -42,7 +81,8 @@ pub struct Thinking; /// We'll validate that GPU performance counter timestamps meet this expectation as it becomes relevant. /// /// This might not actually be true - the timebase of the return values from [`ndk::choreographer::ChoreographerFrameCallbackData`] -/// aren't documented by +/// aren't documented by anything to be `CLOCK_MONOTONIC`, and I suspect we'll need to use [`ash::khr::calibrated_timestamps`] to get +/// the proper results. struct Timestamp(i64); impl Mul for Timestamp { @@ -67,9 +107,6 @@ impl Timestamp { } /// Get the current time in `CLOCK_MONOTONIC`. - /// - /// TODO: This assumed the returned value is not negative. - /// Hopefully that's fine? fn now() -> Self { let spec = nix::time::clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap(); Self(spec.tv_sec() * 1_000_000_000 + spec.tv_nsec()) @@ -77,37 +114,139 @@ impl Timestamp { } /// A margin of latency which we *always* render against for safety. -const DEADLINE_MARGIN: Timestamp = Timestamp::from_millis(2); +const DEADLINE_MARGIN: Timestamp = Timestamp::from_millis(3); /// A margin of latency before the deadline, which if we aren't before, we assume that the /// frame probably missed the deadline. /// -/// In those cases, we bring future frames forward. +/// In those cases, we bring future frames forward to try and avoid a cascading stutter +/// (and instead maintain only a dropped frame). +/// +/// Note that this frame might still have technically counted as hitting the deadline. +/// However, we think a prolonged timing mismatch is worse than one dropped frame. const DEADLINE_ASSUME_FAILED: Timestamp = Timestamp::from_micros(500); +/// The time within which we expect our estimations to be correct. +const EXPECTED_CONSISTENCY: Timestamp = Timestamp::from_millis(3); + struct OngoingFrame { - /// The [present time][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_expected_presentation_time]. + /// The [present time][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_expected_presentation_time] we + /// expect this frame to be displayed at. target_present_time: Timestamp, /// The [vsync id][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_vsync_id] we're aiming for. target_vsync_id: i64, - /// The deadline which this frame needs to meet to be rendered at `target_present_time`. + /// The [deadline][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_deadline] which this frame needs to meet to be rendered at `target_present_time`. /// /// We aim for a time [`DEADLINE_MARGIN`] before the deadline. target_deadline: Timestamp, /// The time at which we wanted to start this frame. /// - /// `start_time` should try to be `requested_start_time - EPSILON`, + /// `cpu_start_time` should try to be `requested_cpu_start_time - EPSILON`, /// but if this is far off, we know early that we might drop this frame (and so should request /// the next frame super early). /// If this is significantly off, then we will likely drop this frame to avoid stuttering. - requested_start_time: Timestamp, + requested_cpu_start_time: Timestamp, /// The time at which `Scene` [rendering](`vello::Renderer::render_to_texture`) began. /// /// TODO: Does this include `Scene` construction time? - start_time: Timestamp, + cpu_start_time: Timestamp, /// The time at which [`wgpu::Queue::submit`] finished for this frame. - submit_time: Timestamp, + /// + /// If this is "much" later than + cpu_submit_time: Timestamp, + + /// The time at which work on the GPU started. + gpu_start_time: Timestamp, + /// The time at which work on the GPU finished. + /// + /// This should be before `target_deadline`. + /// `gpu_finish_time` - `cpu_start_time` is used to estimate how long a total frame takes + /// (and `gpu_finished_time` - `cpu_submit_time`) is used to estimate if a submission has + /// missed a deadline. + /// + /// There is some really interesting trickery we can do here; the *next* frame + /// on the GPU can definitely know this value, and can compare it against the deadline. + /// If we know that the submitted frame will miss the deadline, then we can. + gpu_finish_time: Timestamp, +} + +struct VelloPacingController { + choreographer: Choreographer, + command_rx: Receiver, + /// The duration of each frame, as reported by the system. + /// + /// For a short time, we don't have the refresh rate. + /// + /// This is used to detect the case where `AChoreographer` is giving us incorrect future vsyncs. + refresh_rate: Option, + looper: looper::ThreadLooper, +} + +/// We need to use a shared +type SharedPacing = Rc>; + +enum GpuCommand { + Render(Scene), + Resize(u32, u32, Scene), +} + +pub fn launch_pacing() -> PacingChannel { + let (channel_tx, channel_rx) = std::sync::mpsc::sync_channel(0); + // TODO: Give thread a name + std::thread::spawn(|| { + let looper = looper::ThreadLooper::prepare(); + let waker = looper.as_foreign().clone(); + let (command_tx, command_rx) = std::sync::mpsc::channel(); + channel_tx.send(PacingChannel { + waker, + channel: ManuallyDrop::new(command_tx), + }); + drop(channel_tx); + let choreographer = Choreographer::instance().expect("We just made the `Looper`"); + + let state = VelloPacingController { + choreographer, + command_rx, + refresh_rate: None, + looper: looper::ThreadLooper::for_thread().unwrap(), + }; + let state = Rc::new(RefCell::new(state)); + { + let callback_state = Rc::clone(&state); + let state = state.borrow(); + state + .choreographer + .register_refresh_rate_callback(Box::new(move |rate| { + let mut state = callback_state.borrow_mut(); + state.refresh_rate = Some(rate); + })); + } + let (gpu_tx, gpu_rx) = std::sync::mpsc::channel::(); + // TODO: Give thread a name + std::thread::spawn(|| { + // We perform all GPU work on this thread + // Since submitting work and polling the GPU are mutually exclusive, we + }); + loop { + let poll = looper.poll_once().expect("'Unrecoverable' error"); + assert!( + !matches!(poll, looper::Poll::Timeout | looper::Poll::Event { .. }), + "Impossible poll results from our use of Looper APIs." + ); + let state = state.borrow_mut(); + match state.command_rx.try_recv() { + Ok(command) => { + // Action `command` + } + Err(mpsc::TryRecvError::Disconnected) => {} + Err(mpsc::TryRecvError::Empty) => {} + } + } + }); + channel_rx + .recv_timeout(Duration::from_millis(100)) + .expect("Could not create pacing controller") } From 5360c1350298223360891fc3808b8508df5b0917 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Tue, 29 Oct 2024 11:58:08 +0000 Subject: [PATCH 11/13] Update to newest choreographer --- Cargo.lock | 10 +++++----- Cargo.toml | 5 ++--- examples/with_winit/src/lib.rs | 16 +++++----------- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69a34c77..6b0ba22a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,7 +68,7 @@ dependencies = [ "log", "ndk", "ndk-context", - "ndk-sys 0.6.0+11769913", + "ndk-sys 0.6.0+12185904", "num_enum", "thiserror", ] @@ -1359,12 +1359,12 @@ dependencies = [ [[package]] name = "ndk" version = "0.9.0" -source = "git+https://github.com/djmcnab/ndk/?rev=81627a7564982a04027a49d538cac1686d870dbd#81627a7564982a04027a49d538cac1686d870dbd" +source = "git+https://github.com/rust-mobile/ndk/?rev=d6eaac2df982f091dde061f8c3e0f36cb495e788#d6eaac2df982f091dde061f8c3e0f36cb495e788" dependencies = [ "bitflags 2.6.0", "jni-sys", "log", - "ndk-sys 0.6.0+11769913", + "ndk-sys 0.6.0+12185904", "num_enum", "raw-window-handle", "thiserror", @@ -1387,8 +1387,8 @@ dependencies = [ [[package]] name = "ndk-sys" -version = "0.6.0+11769913" -source = "git+https://github.com/djmcnab/ndk/?rev=81627a7564982a04027a49d538cac1686d870dbd#81627a7564982a04027a49d538cac1686d870dbd" +version = "0.6.0+12185904" +source = "git+https://github.com/rust-mobile/ndk/?rev=d6eaac2df982f091dde061f8c3e0f36cb495e788#d6eaac2df982f091dde061f8c3e0f36cb495e788" dependencies = [ "jni-sys", ] diff --git a/Cargo.toml b/Cargo.toml index 4bbcdc8a..1b374e0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,5 @@ scenes = { path = "examples/scenes" } [patch.crates-io] # "Choreographer" branch: https://github.com/rust-mobile/ndk/tree/choreographer -# With a patch to make version numbers work https://github.com/djmcnab/ndk/tree/choreographer -ndk = { git = "https://github.com/djmcnab/ndk/", rev = "81627a7564982a04027a49d538cac1686d870dbd" } -ndk-sys = { git = "https://github.com/djmcnab/ndk/", rev = "81627a7564982a04027a49d538cac1686d870dbd" } +ndk = { git = "https://github.com/rust-mobile/ndk/", rev = "d6eaac2df982f091dde061f8c3e0f36cb495e788" } +ndk-sys = { git = "https://github.com/rust-mobile/ndk/", rev = "d6eaac2df982f091dde061f8c3e0f36cb495e788" } diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index 76dfb19f..f2762007 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -17,7 +17,6 @@ use web_time::Instant; use winit::application::ApplicationHandler; use winit::event::*; use winit::keyboard::*; -use winit::raw_window_handle::HasRawWindowHandle; use winit::raw_window_handle::HasWindowHandle; use winit::window::WindowId; @@ -900,20 +899,15 @@ fn run( let new_choreographer = Rc::clone(choreographer); choreographer.post_vsync_callback(Box::new(move |frame| { eprintln!("New frame"); + // The vsync point let frame_time = frame.frame_time(); - let preferred_index = frame.preferred_frame_timeline_index(); - for timeline in 0..(frame.frame_timelines_length().min(4)) { + for timeline in frame.frame_timelines().take(3) { eprintln!( - "{:?} {}", - frame.frame_timeline_deadline(timeline) - frame_time, - if timeline == preferred_index { - "(Preferred)" - } else { - "" - } + "{:?} to present {:?} later", + timeline.deadline() - frame_time, + timeline.expected_presentation_time() - timeline.deadline() ); } - eprintln!("{frame:?}"); post_callback(&new_choreographer); })); } From ad618d2af8536c45dd5e3a72c7b7106a048cef4f Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:33:29 +0000 Subject: [PATCH 12/13] Start to seriously design getting choreography Also some more reasoning about frame duration changing --- vello_pacing/src/choreographed.rs | 136 ++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 24 deletions(-) diff --git a/vello_pacing/src/choreographed.rs b/vello_pacing/src/choreographed.rs index 9f261721..9ab8f27b 100644 --- a/vello_pacing/src/choreographed.rs +++ b/vello_pacing/src/choreographed.rs @@ -5,16 +5,20 @@ use std::{ cell::RefCell, mem::ManuallyDrop, ops::Mul, - rc::Rc, + os::fd::{AsFd, AsRawFd}, + rc::{self, Rc}, sync::mpsc::{self, Receiver}, time::Duration, }; use ndk::{ - choreographer::Choreographer, - looper::{self, ForeignLooper}, + choreographer::{self, Choreographer}, + looper::{self, FdEvent, ForeignLooper}, +}; +use nix::{ + sys::timerfd::{self, TimerFd}, + time::ClockId, }; -use nix::time::ClockId; use vello::Scene; /// A slightly tweaked version of the thinking, now that we have an understanding of `AChoreographer`. @@ -46,11 +50,12 @@ use vello::Scene; /// the timestamp of the end of the blit pass with the deadline. /// /// For the moment, we ignore the possibility of a frame failing. -/// That doesn't actually change any behaviour here, because we render with `MailBox`. +/// That doesn't actually change any behaviour here, because we render with [`Mailbox`](wgpu::PresentMode::Mailbox). pub struct Thinking; enum PacingCommand {} +/// The controller for a frame pacing thread. pub struct PacingChannel { waker: ForeignLooper, channel: ManuallyDrop>, @@ -80,7 +85,7 @@ impl Drop for PacingChannel { /// For simplicity, all timestamps are treated as happening in the `CLOCK_MONOTONIC` timebase. /// We'll validate that GPU performance counter timestamps meet this expectation as it becomes relevant. /// -/// This might not actually be true - the timebase of the return values from [`ndk::choreographer::ChoreographerFrameCallbackData`] +/// This might not actually be true - the timebase of the return values from [`choreographer::ChoreographerFrameCallbackData`] /// aren't documented by anything to be `CLOCK_MONOTONIC`, and I suspect we'll need to use [`ash::khr::calibrated_timestamps`] to get /// the proper results. struct Timestamp(i64); @@ -130,12 +135,12 @@ const DEADLINE_ASSUME_FAILED: Timestamp = Timestamp::from_micros(500); const EXPECTED_CONSISTENCY: Timestamp = Timestamp::from_millis(3); struct OngoingFrame { - /// The [present time][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_expected_presentation_time] we + /// The [present time][choreographer::FrameTimeline::expected_presentation_time] we /// expect this frame to be displayed at. target_present_time: Timestamp, - /// The [vsync id][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_vsync_id] we're aiming for. + /// The [vsync id][choreographer::FrameTimeline::vsync_id] we're aiming for. target_vsync_id: i64, - /// The [deadline][ndk::choreographer::ChoreographerFrameCallbackData::frame_timeline_deadline] which this frame needs to meet to be rendered at `target_present_time`. + /// The [deadline][choreographer::FrameTimeline::deadline] which this frame needs to meet to be rendered at `target_present_time`. /// /// We aim for a time [`DEADLINE_MARGIN`] before the deadline. target_deadline: Timestamp, @@ -178,14 +183,22 @@ struct VelloPacingController { command_rx: Receiver, /// The duration of each frame, as reported by the system. /// - /// For a short time, we don't have the refresh rate. + /// In most cases, this can be inferred from the active frame timelines. + /// However, for a short time after the refresh rate changes, `AChoreographer` is + /// giving us incorrect future vsyncs. + /// In particular, when we get a refresh rate callback, we know that frames after the + /// next vsync will be this duration long. /// - /// This is used to detect the case where `AChoreographer` is giving us incorrect future vsyncs. + /// In those cases, we choose to render based on the fastest of the new or old. + /// refresh rates until the updated refresh rate is being used. + /// In some cases, this means that we will get inconsistent latency/apparent frame times; however it avoids + /// dropping frames around a refresh rate window. refresh_rate: Option, looper: looper::ThreadLooper, + timer: TimerFd, } -/// We need to use a shared +/// We need to use a shared pacing controller here because of callback based APIs. type SharedPacing = Rc>; enum GpuCommand { @@ -207,42 +220,117 @@ pub fn launch_pacing() -> PacingChannel { drop(channel_tx); let choreographer = Choreographer::instance().expect("We just made the `Looper`"); + let timer = TimerFd::new( + timerfd::ClockId::CLOCK_MONOTONIC, + timerfd::TimerFlags::TFD_CLOEXEC, + ) + // Something is much more badly wrong if this fails + .expect("Could create a timer file descriptor"); + looper + .as_foreign() + .add_fd(timer.as_fd(), 0, FdEvent::INPUT, std::ptr::null_mut()); + let state = VelloPacingController { choreographer, command_rx, refresh_rate: None, looper: looper::ThreadLooper::for_thread().unwrap(), + timer, }; let state = Rc::new(RefCell::new(state)); { - let callback_state = Rc::clone(&state); + // Since our pointer will not be deallocated/freed unless unregister is called, + // and we can't call unregister, we use a Weak. + // Note that if `state` has been dropped, this thread will be ending, + // so the looper will never be polled again. + let callback_state = Rc::downgrade(&state); let state = state.borrow(); state .choreographer .register_refresh_rate_callback(Box::new(move |rate| { - let mut state = callback_state.borrow_mut(); - state.refresh_rate = Some(rate); + if let Some(state) = callback_state.upgrade() { + let mut state = state.borrow_mut(); + state.refresh_rate = Some(rate); + } else { + tracing::error!( + "Kept getting refresh rate callbacks from Android despite thread ending." + ); + } })); } + { + let callback_state = Rc::downgrade(&state); + let state = state.borrow(); + fn vsync_callback( + data: &choreographer::ChoreographerFrameCallbackData, + callback_state: rc::Weak>, + ) { + if let Some(state) = callback_state.upgrade() { + let mut state = state.borrow_mut(); + state + .choreographer + .post_vsync_callback(Box::new(move |data| { + vsync_callback(data, callback_state); + })); + } + } + state + .choreographer + .post_vsync_callback(Box::new(move |data| vsync_callback(data, callback_state))); + } let (gpu_tx, gpu_rx) = std::sync::mpsc::channel::(); // TODO: Give thread a name - std::thread::spawn(|| { - // We perform all GPU work on this thread - // Since submitting work and polling the GPU are mutually exclusive, we + std::thread::spawn(move || { + // We perform all rendering work on this thread + // Since submitting work and polling the GPU are mutually exclusive, + // we do them on the same thread? + loop { + let command = gpu_rx.recv_timeout(Duration::from_millis(5)); + } }); + loop { + // TODO: Ideally, we'd have the GPU polling happen through this looper. let poll = looper.poll_once().expect("'Unrecoverable' error"); - assert!( - !matches!(poll, looper::Poll::Timeout | looper::Poll::Event { .. }), - "Impossible poll results from our use of Looper APIs." - ); + // Outside of the looper polling operation, so no chance of overlap. let state = state.borrow_mut(); + match poll { + // Fallthrough to checking the command channel + looper::Poll::Wake | looper::Poll::Callback => {} + looper::Poll::Timeout => { + unreachable!("Timeout reached, but we didn't set a timeout") + } + looper::Poll::Event { + ident, + fd, + events, + data: _, + } => { + if fd.as_raw_fd() == state.timer.as_fd().as_raw_fd() { + // TODO: A Hangup might be expected for a timer? + if events.contains(FdEvent::ERROR | FdEvent::INVALID | FdEvent::HANGUP) { + panic!("Got an error from the timer file descriptor {events:?}") + } + assert!(ident == 0); + // Clear out the existing timer value, so that we won't immediately retrigger. + state.timer.wait().unwrap(); + // We should now do whatever we set the timer for. + // Presumably, that is start rendering? + } + } + } + match state.command_rx.try_recv() { Ok(command) => { // Action `command` + match command {} + } + Err(mpsc::TryRecvError::Disconnected) => { + return; + } + Err(mpsc::TryRecvError::Empty) => { + // Continue } - Err(mpsc::TryRecvError::Disconnected) => {} - Err(mpsc::TryRecvError::Empty) => {} } } }); From fe1dd9fce2edddb63a5ee2a2f30ce8da7d461f05 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Wed, 6 Nov 2024 09:39:39 +0000 Subject: [PATCH 13/13] Stash work, slightly bogged down --- Cargo.lock | 1 + examples/with_winit/src/lib.rs | 6 +- vello_pacing/Cargo.toml | 1 + vello_pacing/src/choreographed.rs | 164 +++++++++++++++++++++++++----- vello_pacing/src/core.rs | 3 + vello_pacing/src/lib.rs | 1 + 6 files changed, 146 insertions(+), 30 deletions(-) create mode 100644 vello_pacing/src/core.rs diff --git a/Cargo.lock b/Cargo.lock index 6b0ba22a..5bb1ef7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2566,6 +2566,7 @@ name = "vello_pacing" version = "0.3.0" dependencies = [ "ash", + "jni", "ndk", "nix", "tracing", diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index f2762007..7f38b57b 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -901,7 +901,7 @@ fn run( eprintln!("New frame"); // The vsync point let frame_time = frame.frame_time(); - for timeline in frame.frame_timelines().take(3) { + for timeline in frame.frame_timelines().take(6) { eprintln!( "{:?} to present {:?} later", timeline.deadline() - frame_time, @@ -911,10 +911,10 @@ fn run( post_callback(&new_choreographer); })); } - // post_callback(choreographer); + post_callback(choreographer); choreographer.register_refresh_rate_callback(Box::new(|value| { let span = tracing::info_span!("Getting a new refresh rate", ?value).entered(); - eprintln!("New refresh rate Testing: {value:?}; {}", value.as_nanos()); + tracing::warn!("New refresh rate Testing: {value:?}; {}", value.as_nanos()); })); } diff --git a/vello_pacing/Cargo.toml b/vello_pacing/Cargo.toml index 076ea144..78a9f597 100644 --- a/vello_pacing/Cargo.toml +++ b/vello_pacing/Cargo.toml @@ -13,6 +13,7 @@ ash = { version = "0.38.0", default-features = false } tracing = "0.1.40" ndk = { version = "0.9", features = ["api-level-33"] } nix = { default-features = false, features = ["time"], version = "0.29.0" } +jni = "0.21.1" [lints] workspace = true diff --git a/vello_pacing/src/choreographed.rs b/vello_pacing/src/choreographed.rs index 9ab8f27b..8a258ff0 100644 --- a/vello_pacing/src/choreographed.rs +++ b/vello_pacing/src/choreographed.rs @@ -3,11 +3,12 @@ use std::{ cell::RefCell, + collections::VecDeque, mem::ManuallyDrop, - ops::Mul, + ops::{Add, Mul}, os::fd::{AsFd, AsRawFd}, rc::{self, Rc}, - sync::mpsc::{self, Receiver}, + sync::mpsc::{self, Receiver, RecvTimeoutError}, time::Duration, }; @@ -64,7 +65,8 @@ pub struct PacingChannel { impl PacingChannel { fn send_command(&self, command: PacingCommand) { self.channel.send(command); - // We add to the channel before waking, so that the event will be received by the right wake. + // We add to the channel before waking, so that the event will be + // received by the right wake. self.waker.wake(); } } @@ -72,9 +74,12 @@ impl PacingChannel { impl Drop for PacingChannel { fn drop(&mut self) { // Safety: We don't use `self.channel` after this line. - // We drop the value before performing the wake, so that we instantly know that the drop has happened. + // We drop the value before performing the wake, so that we the controller + // thread knows the drop has happened. unsafe { ManuallyDrop::drop(&mut self.channel) }; self.waker.wake(); + // TODO: Block on the thread itself finishing. + // This makes using the Android NDK context in that thread *safer*. } } @@ -88,8 +93,22 @@ impl Drop for PacingChannel { /// This might not actually be true - the timebase of the return values from [`choreographer::ChoreographerFrameCallbackData`] /// aren't documented by anything to be `CLOCK_MONOTONIC`, and I suspect we'll need to use [`ash::khr::calibrated_timestamps`] to get /// the proper results. +// TODO: Does `Eq` make sense? +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] struct Timestamp(i64); +impl Add for Timestamp { + type Output = Timestamp; + + fn add(self, rhs: Duration) -> Self::Output { + Self::from_nanos( + self.as_nanos() + .checked_add(rhs.as_nanos().try_into().unwrap()) + .unwrap(), + ) + } +} + impl Mul for Timestamp { type Output = Self; @@ -99,18 +118,34 @@ impl Mul for Timestamp { } impl Timestamp { + /// Create a timespec for `nanos` nanoseconds since the origin of `CLOCK_MONOTIC`. const fn from_nanos(nanos: i64) -> Self { Self(nanos) } + /// Create a timespec for `micros` microseconds since the origin of `CLOCK_MONOTIC`. const fn from_micros(micros: i64) -> Self { Self::from_nanos(micros * 1_000) } + /// Create a timespec for `millis` milliseconds since the origin of `CLOCK_MONOTIC`. const fn from_millis(millis: i64) -> Self { Self::from_nanos(millis * 1_000_000) } + /// Create a timestamp from a `Duration`, assuming that the duration is from + /// `CLOCK_MONOTONIC`'s zero point. + /// + /// This matches the behaviour of values in [choreographer]. + fn from_ndk_crate(duration: Duration) -> Self { + Self::from_nanos(duration.as_nanos().try_into().unwrap()) + } + + /// Get the number of nanoseconds since the origin of `CLOCK_MONOTIC` for this time. + fn as_nanos(&self) -> i64 { + self.0 + } + /// Get the current time in `CLOCK_MONOTONIC`. fn now() -> Self { let spec = nix::time::clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap(); @@ -135,15 +170,10 @@ const DEADLINE_ASSUME_FAILED: Timestamp = Timestamp::from_micros(500); const EXPECTED_CONSISTENCY: Timestamp = Timestamp::from_millis(3); struct OngoingFrame { - /// The [present time][choreographer::FrameTimeline::expected_presentation_time] we - /// expect this frame to be displayed at. - target_present_time: Timestamp, - /// The [vsync id][choreographer::FrameTimeline::vsync_id] we're aiming for. - target_vsync_id: i64, - /// The [deadline][choreographer::FrameTimeline::deadline] which this frame needs to meet to be rendered at `target_present_time`. + /// The vertical blanking interval we're aiming to be presented at. /// - /// We aim for a time [`DEADLINE_MARGIN`] before the deadline. - target_deadline: Timestamp, + /// We aim to finish GPU work [`DEADLINE_MARGIN`] before `deadline`. + target_vsync: UpcomingVsync, /// The time at which we wanted to start this frame. /// @@ -160,10 +190,13 @@ struct OngoingFrame { /// The time at which [`wgpu::Queue::submit`] finished for this frame. /// - /// If this is "much" later than + /// If this is "much" later than expected (TODO: What would be expected?) + /// then we will start the CPU side work for the next frame early. cpu_submit_time: Timestamp, - /// The time at which work on the GPU started. + /// The time at which work for this frame on the GPU started happening. + /// + /// Note: This assumes that gpu_start_time: Timestamp, /// The time at which work on the GPU finished. /// @@ -178,8 +211,16 @@ struct OngoingFrame { gpu_finish_time: Timestamp, } +/// The *shared* state of the pacing controller. +/// +/// This is the state which *must* be available to callback based APIs. struct VelloPacingController { + // Resources used to implement the controller, which must be shared. choreographer: Choreographer, + looper: looper::ThreadLooper, + timer: TimerFd, + + // Communication primitives command_rx: Receiver, /// The duration of each frame, as reported by the system. /// @@ -189,17 +230,36 @@ struct VelloPacingController { /// In particular, when we get a refresh rate callback, we know that frames after the /// next vsync will be this duration long. /// - /// In those cases, we choose to render based on the fastest of the new or old. - /// refresh rates until the updated refresh rate is being used. - /// In some cases, this means that we will get inconsistent latency/apparent frame times; however it avoids - /// dropping frames around a refresh rate window. - refresh_rate: Option, - looper: looper::ThreadLooper, - timer: TimerFd, + /// There are three cases where this can happen: + /// 1) Where we ask for a slower framerate. We would do that when we are + /// consistently missing the target frame time. + /// 2) When we ask for a faster framerate. + /// 3) Where some other app (such as an overlay) asks for a faster framerate. + /// In that case, we need to catch up as quickly as possible. + /// + /// TODO: How does refresh rate interact with Poll and non-animated versions? + /// + /// Correct behaviour in this case is currently out-of-scope. + upcoming_refresh_rate: Option, + /// The time at which the most recent vsync happened. + latest_vsync_time: Option, + /// Upcoming vsyncs, (probably?) ordered by present time. + upcoming_vsyncs: VecDeque, } -/// We need to use a shared pacing controller here because of callback based APIs. -type SharedPacing = Rc>; +struct UpcomingVsync { + /// The [present time][choreographer::FrameTimeline::expected_presentation_time] of this vsync. + /// + /// That is, the time of the actual "flip". + /// Once this time has passed, the vsync is historical. + present_time: Timestamp, + /// The [vsync id][choreographer::FrameTimeline::vsync_id] we're aiming for. + vsync_id: i64, + /// The [deadline][choreographer::FrameTimeline::deadline] which a frame needs to meet to be rendered at `present_time`. + /// + /// Once this time has passed, the vsync is largely academic, ad + deadline: Timestamp, +} enum GpuCommand { Render(Scene), @@ -232,11 +292,14 @@ pub fn launch_pacing() -> PacingChannel { let state = VelloPacingController { choreographer, - command_rx, - refresh_rate: None, looper: looper::ThreadLooper::for_thread().unwrap(), timer, + command_rx, + upcoming_refresh_rate: None, + latest_vsync_time: None, + upcoming_vsyncs: Default::default(), }; + /// We need to use a shared pacing controller here because of callback based APIs. let state = Rc::new(RefCell::new(state)); { // Since our pointer will not be deallocated/freed unless unregister is called, @@ -248,9 +311,11 @@ pub fn launch_pacing() -> PacingChannel { state .choreographer .register_refresh_rate_callback(Box::new(move |rate| { + // Note: The refresh rate might be a multiple of some supported mode with interval + // higher than our. if let Some(state) = callback_state.upgrade() { let mut state = state.borrow_mut(); - state.refresh_rate = Some(rate); + state.upcoming_refresh_rate = Some(rate); } else { tracing::error!( "Kept getting refresh rate callbacks from Android despite thread ending." @@ -272,6 +337,33 @@ pub fn launch_pacing() -> PacingChannel { .post_vsync_callback(Box::new(move |data| { vsync_callback(data, callback_state); })); + let this_vsync_time = Timestamp::from_ndk_crate(data.frame_time()); + state.clear_historical_vsyncs(this_vsync_time); + if let Some(_frame_time) = state.upcoming_refresh_rate { + // We might need special handling for upcoming refresh rates here. + // Primarily, checking if the refresh rate change has trickled into + // Choreographer yet. + } + // TODO: What significance (if any) does "preferred frame timeline" have? + for timeline in data.frame_timelines() { + let vsync_id = timeline.vsync_id(); + // TODO: More efficient check here using ordering properties? + if state + .upcoming_vsyncs + .iter() + .any(|it| it.vsync_id == vsync_id) + { + continue; + } + let deadline = Timestamp::from_ndk_crate(timeline.deadline()); + let present_time = + Timestamp::from_ndk_crate(timeline.expected_presentation_time()); + state.upcoming_vsyncs.push_back(UpcomingVsync { + present_time, + vsync_id, + deadline, + }); + } } } state @@ -291,7 +383,9 @@ pub fn launch_pacing() -> PacingChannel { loop { // TODO: Ideally, we'd have the GPU polling happen through this looper. - let poll = looper.poll_once().expect("'Unrecoverable' error"); + let poll = looper + .poll_once() + .expect("'Unrecoverable' error should not occur"); // Outside of the looper polling operation, so no chance of overlap. let state = state.borrow_mut(); match poll { @@ -338,3 +432,19 @@ pub fn launch_pacing() -> PacingChannel { .recv_timeout(Duration::from_millis(100)) .expect("Could not create pacing controller") } + +impl VelloPacingController { + /// Clear the historical vsyncs which are definitely no longer relevant, given a + /// time that a vsync recently occurred. + fn clear_historical_vsyncs(&mut self, recent_vsync: Timestamp) { + // We assume FPS to be less than 1000; this gives flexibility here. + let vsync_cutoff = recent_vsync + Duration::from_millis(1); + while let Some(front) = self.upcoming_vsyncs.front() { + if front.present_time < vsync_cutoff { + self.upcoming_vsyncs.pop_front(); + } else { + break; + } + } + } +} diff --git a/vello_pacing/src/core.rs b/vello_pacing/src/core.rs new file mode 100644 index 00000000..74caee5c --- /dev/null +++ b/vello_pacing/src/core.rs @@ -0,0 +1,3 @@ +//! The cross-platform part of a frame pacing controller. +//! +//! This needs to consider variable refresh rates. diff --git a/vello_pacing/src/lib.rs b/vello_pacing/src/lib.rs index 3fb675ec..c95e1a30 100644 --- a/vello_pacing/src/lib.rs +++ b/vello_pacing/src/lib.rs @@ -1,6 +1,7 @@ #![deny(unsafe_op_in_unsafe_fn)] mod choreographed; +pub mod core; use std::{ collections::VecDeque,