diff --git a/Cargo.lock b/Cargo.lock index c010f70450e..78ecaad27a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-activity" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", "bitflags 2.6.0", @@ -75,9 +75,9 @@ dependencies = [ "jni-sys", "libc", "log", - "ndk 0.8.0", + "ndk 0.9.0", "ndk-context", - "ndk-sys 0.5.0+25.2.9519653", + "ndk-sys 0.6.0+11769913", "num_enum 0.7.2", "thiserror", ] @@ -343,22 +343,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - [[package]] name = "block2" -version = "0.3.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "block-sys", "objc2", ] @@ -416,9 +406,9 @@ dependencies = [ [[package]] name = "calloop" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ "bitflags 2.6.0", "log", @@ -430,14 +420,14 @@ dependencies = [ [[package]] name = "calloop-wayland-source" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop 0.12.4", + "calloop 0.13.0", "rustix", "wayland-backend", - "wayland-client 0.31.2", + "wayland-client 0.31.5", ] [[package]] @@ -474,6 +464,12 @@ 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 = "cgl" version = "0.3.2" @@ -920,7 +916,7 @@ name = "d3d12" version = "22.0.0" dependencies = [ "bitflags 2.6.0", - "libloading 0.8.5", + "libloading 0.7.4", "winapi", ] @@ -1140,7 +1136,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.5", + "libloading 0.7.4", ] [[package]] @@ -1158,6 +1154,12 @@ 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 = "dwrote" version = "0.11.0" @@ -1746,7 +1748,7 @@ dependencies = [ "bitflags 2.6.0", "com", "libc", - "libloading 0.8.5", + "libloading 0.7.4", "thiserror", "widestring", "winapi", @@ -1805,17 +1807,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "icrate" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" -dependencies = [ - "block2", - "dispatch", - "objc2", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2013,7 +2004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2196,7 +2187,7 @@ dependencies = [ "arrayvec 0.7.4", "bit-set", "bitflags 2.6.0", - "cfg_aliases", + "cfg_aliases 0.1.1", "codespan-reporting", "diff", "env_logger", @@ -2277,14 +2268,14 @@ dependencies = [ [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ "bitflags 2.6.0", "jni-sys", "log", - "ndk-sys 0.5.0+25.2.9519653", + "ndk-sys 0.6.0+11769913", "num_enum 0.7.2", "raw-window-handle 0.6.2", "thiserror", @@ -2319,7 +2310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ "darling", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -2343,6 +2334,15 @@ 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 = "nix" version = "0.24.3" @@ -2451,7 +2451,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -2463,7 +2463,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.74", @@ -2510,19 +2510,200 @@ checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +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 = "3.0.0" +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 = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +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 = "object" @@ -2699,7 +2880,7 @@ dependencies = [ "serde", "wgpu-core", "wgpu-types", - "winit 0.29.15", + "winit 0.30.5", ] [[package]] @@ -2786,16 +2967,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] @@ -2838,9 +3010,9 @@ checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4" dependencies = [ "memchr", ] @@ -2925,15 +3097,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3122,14 +3285,14 @@ dependencies = [ [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "ab_glyph", "log", "memmap2 0.9.4", - "smithay-client-toolkit 0.18.1", + "smithay-client-toolkit 0.19.2", "tiny-skia 0.11.4", ] @@ -3310,12 +3473,12 @@ dependencies = [ [[package]] name = "smithay-client-toolkit" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ "bitflags 2.6.0", - "calloop 0.12.4", + "calloop 0.13.0", "calloop-wayland-source", "cursor-icon", "libc", @@ -3324,12 +3487,12 @@ dependencies = [ "rustix", "thiserror", "wayland-backend", - "wayland-client 0.31.2", + "wayland-client 0.31.5", "wayland-csd-frame", "wayland-cursor 0.31.1", - "wayland-protocols 0.31.2", + "wayland-protocols 0.32.3", "wayland-protocols-wlr", - "wayland-scanner 0.31.1", + "wayland-scanner 0.31.4", "xkeysym", ] @@ -3643,17 +3806,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - [[package]] name = "tracing" version = "0.1.40" @@ -4034,14 +4186,14 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.2" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" +checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943" dependencies = [ "bitflags 2.6.0", "rustix", "wayland-backend", - "wayland-scanner 0.31.1", + "wayland-scanner 0.31.4", ] [[package]] @@ -4085,7 +4237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" dependencies = [ "rustix", - "wayland-client 0.31.2", + "wayland-client 0.31.5", "xcursor", ] @@ -4113,40 +4265,40 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "62989625a776e827cc0f15d41444a3cea5205b963c3a25be48ae1b52d6b4daaa" dependencies = [ "bitflags 2.6.0", "wayland-backend", - "wayland-client 0.31.2", - "wayland-scanner 0.31.1", + "wayland-client 0.31.5", + "wayland-scanner 0.31.4", ] [[package]] name = "wayland-protocols-plasma" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +checksum = "f79f2d57c7fcc6ab4d602adba364bf59a5c24de57bd194486bf9b8360e06bfc4" dependencies = [ "bitflags 2.6.0", "wayland-backend", - "wayland-client 0.31.2", - "wayland-protocols 0.31.2", - "wayland-scanner 0.31.1", + "wayland-client 0.31.5", + "wayland-protocols 0.32.3", + "wayland-scanner 0.31.4", ] [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "fd993de54a40a40fbe5601d9f1fbcaef0aebcc5fda447d7dc8f6dcbaae4f8953" dependencies = [ "bitflags 2.6.0", "wayland-backend", - "wayland-client 0.31.2", - "wayland-protocols 0.31.2", - "wayland-scanner 0.31.1", + "wayland-client 0.31.5", + "wayland-protocols 0.32.3", + "wayland-scanner 0.31.4", ] [[package]] @@ -4162,9 +4314,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.1" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" +checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6" dependencies = [ "proc-macro2", "quick-xml", @@ -4214,12 +4366,22 @@ dependencies = [ "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" dependencies = [ "arrayvec 0.7.4", - "cfg_aliases", + "cfg_aliases 0.1.1", "document-features", "js-sys", "log", @@ -4263,7 +4425,7 @@ dependencies = [ "bit-vec", "bitflags 2.6.0", "bytemuck", - "cfg_aliases", + "cfg_aliases 0.1.1", "document-features", "indexmap", "log", @@ -4306,10 +4468,10 @@ dependencies = [ "wasm-bindgen-futures", "wasm-bindgen-test", "web-sys", - "web-time", + "web-time 0.2.4", "wgpu", "wgpu-test", - "winit 0.29.15", + "winit 0.30.5", ] [[package]] @@ -4323,7 +4485,7 @@ dependencies = [ "bitflags 2.6.0", "block", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "core-graphics-types", "d3d12", "env_logger", @@ -4338,7 +4500,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.5", + "libloading 0.7.4", "log", "metal", "naga", @@ -4358,7 +4520,7 @@ dependencies = [ "wgpu-types", "winapi", "windows", - "winit 0.29.15", + "winit 0.30.5", ] [[package]] @@ -4470,7 +4632,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4835,47 +4997,51 @@ dependencies = [ [[package]] name = "winit" -version = "0.29.15" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" dependencies = [ "ahash", "android-activity", "atomic-waker", "bitflags 2.6.0", + "block2", "bytemuck", - "calloop 0.12.4", - "cfg_aliases", + "calloop 0.13.0", + "cfg_aliases 0.2.1", + "concurrent-queue", "core-foundation", "core-graphics 0.23.2", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", "memmap2 0.9.4", - "ndk 0.8.0", - "ndk-sys 0.5.0+25.2.9519653", + "ndk 0.9.0", "objc2", - "once_cell", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", "orbclient", "percent-encoding", + "pin-project", "raw-window-handle 0.6.2", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", - "sctk-adwaita 0.8.1", - "smithay-client-toolkit 0.18.1", + "sctk-adwaita 0.10.1", + "smithay-client-toolkit 0.19.2", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", "wayland-backend", - "wayland-client 0.31.2", - "wayland-protocols 0.31.2", + "wayland-client 0.31.5", + "wayland-protocols 0.32.3", "wayland-protocols-plasma", "web-sys", - "web-time", - "windows-sys 0.48.0", + "web-time 1.1.0", + "windows-sys 0.52.0", "x11-dl", "x11rb", "xkbcommon-dl", diff --git a/Cargo.toml b/Cargo.toml index 04b26b8044f..3a79f17bd78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,7 +132,7 @@ wgpu-core = { version = "22.0.0", path = "./wgpu-core" } wgpu-macros = { version = "22.0.0", path = "./wgpu-macros" } wgpu-test = { version = "22.0.0", path = "./tests" } wgpu-types = { version = "22.0.0", path = "./wgpu-types" } -winit = { version = "0.29", features = ["android-native-activity"] } +winit = { version = "0.30", features = ["android-native-activity"] } # Metal dependencies block = "0.1" diff --git a/examples/src/framework.rs b/examples/src/framework.rs index ff86cc23570..2300dc6de16 100644 --- a/examples/src/framework.rs +++ b/examples/src/framework.rs @@ -2,11 +2,12 @@ use std::sync::Arc; use wgpu::{Instance, Surface}; use winit::{ + application::ApplicationHandler, dpi::PhysicalSize, - event::{Event, KeyEvent, StartCause, WindowEvent}, - event_loop::{EventLoop, EventLoopWindowTarget}, + event::{KeyEvent, WindowEvent}, + event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy}, keyboard::{Key, NamedKey}, - window::Window, + window::{Window, WindowId}, }; pub trait Example: 'static + Sized { @@ -89,36 +90,6 @@ fn init_logger() { } } -struct EventLoopWrapper { - event_loop: EventLoop<()>, - window: Arc, -} - -impl EventLoopWrapper { - pub fn new(title: &str) -> Self { - let event_loop = EventLoop::new().unwrap(); - let mut builder = winit::window::WindowBuilder::new(); - #[cfg(target_arch = "wasm32")] - { - use wasm_bindgen::JsCast; - use winit::platform::web::WindowBuilderExtWebSys; - let canvas = web_sys::window() - .unwrap() - .document() - .unwrap() - .get_element_by_id("canvas") - .unwrap() - .dyn_into::() - .unwrap(); - builder = builder.with_canvas(Some(canvas)); - } - builder = builder.with_title(title); - let window = Arc::new(builder.build(&event_loop).unwrap()); - - Self { event_loop, window } - } -} - /// Wrapper type which manages the surface and surface configuration. /// /// As surface usage varies per platform, wrapping this up cleans up the event loop code. @@ -128,44 +99,26 @@ struct SurfaceWrapper { } impl SurfaceWrapper { - /// Create a new surface wrapper with no surface or configuration. - fn new() -> Self { + /// Create a new surface wrapper with a surface. + /// + /// This should be called before the adapter is created. + fn new(instance: &Instance, window: Arc) -> Self { Self { - surface: None, + surface: Some(instance.create_surface(window).unwrap()), config: None, } } - /// Called after the instance is created, but before we request an adapter. - /// - /// On wasm, we need to create the surface here, as the WebGL backend needs - /// a surface (and hence a canvas) to be present to create the adapter. - /// - /// We cannot unconditionally create a surface here, as Android requires - /// us to wait until we receive the `Resumed` event to do so. - fn pre_adapter(&mut self, instance: &Instance, window: Arc) { - if cfg!(target_arch = "wasm32") { - self.surface = Some(instance.create_surface(window).unwrap()); - } - } - - /// Check if the event is the start condition for the surface. - fn start_condition(e: &Event<()>) -> bool { - match e { - // On all other platforms, we can create the surface immediately. - Event::NewEvents(StartCause::Init) => !cfg!(target_os = "android"), - // On android we need to wait for a resumed event to create the surface. - Event::Resumed => cfg!(target_os = "android"), - _ => false, - } - } - - /// Called when an event which matches [`Self::start_condition`] is received. - /// - /// On all native platforms, this is where we create the surface. + /// Configure the surface with the given adapter and device. /// - /// Additionally, we configure the surface based on the (now valid) window size. - fn resume(&mut self, context: &ExampleContext, window: Arc, srgb: bool) { + /// This should be called after the device is created. + fn configure( + &mut self, + adapter: &wgpu::Adapter, + device: &wgpu::Device, + window: &Window, + srgb: bool, + ) { // Window size is only actually valid after we enter the event loop. let window_size = window.inner_size(); let width = window_size.width.max(1); @@ -173,18 +126,11 @@ impl SurfaceWrapper { log::info!("Surface resume {window_size:?}"); - // We didn't create the surface in pre_adapter, so we need to do so now. - if !cfg!(target_arch = "wasm32") { - self.surface = Some(context.instance.create_surface(window).unwrap()); - } - - // From here on, self.surface should be Some. - let surface = self.surface.as_ref().unwrap(); // Get the default configuration, let mut config = surface - .get_default_config(&context.adapter, width, height) + .get_default_config(&adapter, width, height) .expect("Surface isn't supported by the adapter."); if srgb { // Not all platforms (WebGPU) support sRGB swapchains, so we need to use view formats @@ -197,23 +143,38 @@ impl SurfaceWrapper { config.view_formats.push(format); }; - surface.configure(&context.device, &config); + surface.configure(&device, &config); self.config = Some(config); } + /// Resume event which recreates the surface, if it was dropped. + fn resume( + &mut self, + instance: &Instance, + window: &Arc, + adapter: &wgpu::Adapter, + device: &wgpu::Device, + srgb: bool, + ) { + if self.surface.is_none() { + self.surface = Some(instance.create_surface(window.clone()).unwrap()); + self.configure(adapter, device, window, srgb); + } + } + /// Resize the surface, making sure to not resize to zero. - fn resize(&mut self, context: &ExampleContext, size: PhysicalSize) { + fn resize(&mut self, device: &wgpu::Device, size: PhysicalSize) { log::info!("Surface resize {size:?}"); let config = self.config.as_mut().unwrap(); config.width = size.width.max(1); config.height = size.height.max(1); let surface = self.surface.as_ref().unwrap(); - surface.configure(&context.device, config); + surface.configure(&device, config); } /// Acquire the next surface texture. - fn acquire(&mut self, context: &ExampleContext) -> wgpu::SurfaceTexture { + fn acquire(&mut self, device: &wgpu::Device) -> wgpu::SurfaceTexture { let surface = self.surface.as_ref().unwrap(); match surface.get_current_texture() { @@ -229,7 +190,7 @@ impl SurfaceWrapper { // If OutOfMemory happens, reconfiguring may not help, but we might as well try | wgpu::SurfaceError::OutOfMemory, ) => { - surface.configure(&context.device, self.config()); + surface.configure(&device, self.config()); surface .get_current_texture() .expect("Failed to acquire next surface texture!") @@ -241,9 +202,7 @@ impl SurfaceWrapper { /// /// A suspend event is always followed by at least one resume event. fn suspend(&mut self) { - if cfg!(target_os = "android") { - self.surface = None; - } + self.surface = None; } fn get(&self) -> Option<&Surface> { @@ -255,16 +214,54 @@ impl SurfaceWrapper { } } -/// Context containing global wgpu resources. -struct ExampleContext { +struct FrameCounter { + // Instant of the last time we printed the frame time. + last_printed_instant: web_time::Instant, + // Number of frames since the last time we printed the frame time. + frame_count: u32, +} + +impl FrameCounter { + fn new() -> Self { + Self { + last_printed_instant: web_time::Instant::now(), + frame_count: 0, + } + } + + fn update(&mut self) { + self.frame_count += 1; + let new_instant = web_time::Instant::now(); + let elapsed_secs = (new_instant - self.last_printed_instant).as_secs_f32(); + if elapsed_secs > 1.0 { + let elapsed_ms = elapsed_secs * 1000.0; + let frame_time = elapsed_ms / self.frame_count as f32; + let fps = self.frame_count as f32 / elapsed_secs; + log::info!("Frame time {:.2}ms ({:.1} FPS)", frame_time, fps); + + self.last_printed_instant = new_instant; + self.frame_count = 0; + } + } +} + +/// Stores all of the state of the example after initialization. +struct InitializedExample { instance: wgpu::Instance, adapter: wgpu::Adapter, device: wgpu::Device, queue: wgpu::Queue, + + window: Arc, + surface: SurfaceWrapper, + + frame_counter: FrameCounter, + example: E, } -impl ExampleContext { - /// Initializes the example context. - async fn init_async(surface: &mut SurfaceWrapper, window: Arc) -> Self { + +impl InitializedExample { + /// Asynchronously initialize the all the example state. + async fn new(window: Arc) -> InitializedExample { log::info!("Initializing wgpu..."); let backends = wgpu::util::backend_bits_from_env().unwrap_or_default(); @@ -277,7 +274,9 @@ impl ExampleContext { dx12_shader_compiler, gles_minor_version, }); - surface.pre_adapter(&instance, window); + + let mut surface = SurfaceWrapper::new(&instance, window.clone()); + let adapter = wgpu::util::initialize_adapter_from_env_or_default(&instance, surface.get()) .await .expect("No suitable GPU adapters found on the system!"); @@ -326,167 +325,224 @@ impl ExampleContext { .await .expect("Unable to find a suitable GPU adapter!"); - Self { + surface.configure(&adapter, &device, &window, E::SRGB); + + let frame_counter = FrameCounter::new(); + + let example = E::init(surface.config(), &adapter, &device, &queue); + + log::info!("Initialization complete."); + + InitializedExample { + window, + frame_counter, + example, + instance, adapter, device, queue, + surface, } } } -struct FrameCounter { - // Instant of the last time we printed the frame time. - last_printed_instant: web_time::Instant, - // Number of frames since the last time we printed the frame time. - frame_count: u32, +/// Event used to initialize the example state after initialization finishes. +struct StateInitEvent(InitializedExample); + +/// Initialization state for the example. +/// +/// State should only ever move down the chain, from `Uninitialized` -> `Initializing` -> `Initialized`. +enum InitState { + /// The example has not been initialized yet. + Uninitialized, + /// The example is being initialized asynchronously. + Initializing, + /// The example has been initialized. + Initialized(InitializedExample), } -impl FrameCounter { - fn new() -> Self { - Self { - last_printed_instant: web_time::Instant::now(), - frame_count: 0, +struct LoopState { + state: InitState, + title: &'static str, + event_loop_proxy: EventLoopProxy>, +} + +impl LoopState { + fn new(title: &'static str, event_loop: &EventLoop>) -> LoopState { + LoopState { + state: InitState::Uninitialized, + title, + event_loop_proxy: event_loop.create_proxy(), } } +} - fn update(&mut self) { - self.frame_count += 1; - let new_instant = web_time::Instant::now(); - let elapsed_secs = (new_instant - self.last_printed_instant).as_secs_f32(); - if elapsed_secs > 1.0 { - let elapsed_ms = elapsed_secs * 1000.0; - let frame_time = elapsed_ms / self.frame_count as f32; - let fps = self.frame_count as f32 / elapsed_secs; - log::info!("Frame time {:.2}ms ({:.1} FPS)", frame_time, fps); +impl ApplicationHandler> for LoopState { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + match self.state { + InitState::Uninitialized => { + // If we're uninitialized, start initializing and + // continue to the main body. + self.state = InitState::Initializing; + } + InitState::Initializing => { + // If we're already initializing, just ignore the resume event. + return; + } + InitState::Initialized(ref mut state) => { + // If we're already initialized, resume the surface. + state.surface.resume( + &state.instance, + &state.window, + &state.adapter, + &state.device, + E::SRGB, + ); + } + } - self.last_printed_instant = new_instant; - self.frame_count = 0; + log::info!("Initializing example..."); + + // Configure and create the window. + #[allow(unused_mut)] + let mut window_attributes = Window::default_attributes().with_title(self.title); + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen::JsCast; + use winit::platform::web::WindowAttributesExtWebSys; + let canvas = web_sys::window() + .unwrap() + .document() + .unwrap() + .get_element_by_id("canvas") + .unwrap() + .dyn_into::() + .unwrap(); + window_attributes = window_attributes.with_canvas(Some(canvas)); } - } -} + let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); -async fn start(title: &str) { - init_logger(); + // Create the example future. + let future = InitializedExample::new(window); - log::debug!( - "Enabled backends: {:?}", - wgpu::Instance::enabled_backend_features() - ); + cfg_if::cfg_if! { + if #[cfg(target_arch = "wasm32")] { + // WASM we can't use block_on, so we spawn the future and send the result back to the event loop. - let window_loop = EventLoopWrapper::new(title); - let mut surface = SurfaceWrapper::new(); - let context = ExampleContext::init_async::(&mut surface, window_loop.window.clone()).await; - let mut frame_counter = FrameCounter::new(); + let event_loop_proxy = self.event_loop_proxy.clone(); + wasm_bindgen_futures::spawn_local(async move { + let state = future.await; + event_loop_proxy.send_event(StateInitEvent(state)).unwrap_or_else(|_| { + panic!("Failed to send StateInitEvent"); + }); + }); + } else { + // On native, we can block on the future and send the result back directly. + let state = pollster::block_on(future); + self.event_loop_proxy.send_event(StateInitEvent(state)).unwrap_or_else(|_| { + panic!("Failed to send StateInitEvent"); + }); + } + }; + } - // We wait to create the example until we have a valid surface. - let mut example = None; + /// Handle the event where the example has been initialized. + fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: StateInitEvent) { + log::info!("Received initialized event."); - cfg_if::cfg_if! { - if #[cfg(target_arch = "wasm32")] { - use winit::platform::web::EventLoopExtWebSys; - let event_loop_function = EventLoop::spawn; - } else { - let event_loop_function = EventLoop::run; - } + let state = event.0; + state.window.request_redraw(); + + self.state = InitState::Initialized(state); } - log::info!("Entering event loop..."); - // On native this is a result, but on wasm it's a unit type. - #[allow(clippy::let_unit_value)] - let _ = (event_loop_function)( - window_loop.event_loop, - move |event: Event<()>, target: &EventLoopWindowTarget<()>| { - match event { - ref e if SurfaceWrapper::start_condition(e) => { - surface.resume(&context, window_loop.window.clone(), E::SRGB); - - // If we haven't created the example yet, do so now. - if example.is_none() { - example = Some(E::init( - surface.config(), - &context.adapter, - &context.device, - &context.queue, - )); - } - } - Event::Suspended => { - surface.suspend(); - } - Event::WindowEvent { event, .. } => match event { - WindowEvent::Resized(size) => { - surface.resize(&context, size); - example.as_mut().unwrap().resize( - surface.config(), - &context.device, - &context.queue, - ); - - window_loop.window.request_redraw(); - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: Key::Named(NamedKey::Escape), - .. - }, + fn suspended(&mut self, _event_loop: &ActiveEventLoop) { + let InitState::Initialized(ref mut state) = self.state else { + return; + }; + state.surface.suspend(); + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + _window_id: WindowId, + event: WindowEvent, + ) { + let InitState::Initialized(ref mut state) = self.state else { + return; + }; + + match event { + WindowEvent::Resized(size) => { + state.surface.resize(&state.device, size); + state + .example + .resize(state.surface.config(), &state.device, &state.queue); + + state.window.request_redraw(); + } + WindowEvent::KeyboardInput { + event: + KeyEvent { + logical_key: Key::Named(NamedKey::Escape), .. - } - | WindowEvent::CloseRequested => { - target.exit(); - } - #[cfg(not(target_arch = "wasm32"))] - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: Key::Character(s), - .. - }, + }, + .. + } + | WindowEvent::CloseRequested => { + event_loop.exit(); + } + #[cfg(not(target_arch = "wasm32"))] + WindowEvent::KeyboardInput { + event: + KeyEvent { + logical_key: Key::Character(s), .. - } if s == "r" => { - println!("{:#?}", context.instance.generate_report()); - } - WindowEvent::RedrawRequested => { - // On MacOS, currently redraw requested comes in _before_ Init does. - // If this happens, just drop the requested redraw on the floor. - // - // See https://github.com/rust-windowing/winit/issues/3235 for some discussion - if example.is_none() { - return; - } - - frame_counter.update(); - - let frame = surface.acquire(&context); - let view = frame.texture.create_view(&wgpu::TextureViewDescriptor { - format: Some(surface.config().view_formats[0]), - ..wgpu::TextureViewDescriptor::default() - }); - - example - .as_mut() - .unwrap() - .render(&view, &context.device, &context.queue); - - frame.present(); - - window_loop.window.request_redraw(); - } - _ => example.as_mut().unwrap().update(event), - }, - _ => {} + }, + .. + } if s == "r" => { + println!("{:#?}", state.instance.generate_report()); } - }, - ); + WindowEvent::RedrawRequested => { + state.frame_counter.update(); + + let frame = state.surface.acquire(&state.device); + + let view = frame.texture.create_view(&wgpu::TextureViewDescriptor { + format: Some(state.surface.config().view_formats[0]), + ..wgpu::TextureViewDescriptor::default() + }); + + state.example.render(&view, &state.device, &state.queue); + + frame.present(); + + state.window.request_redraw(); + } + _ => state.example.update(event), + } + } } pub fn run(title: &'static str) { + init_logger(); + + let event_loop = EventLoop::>::with_user_event() + .build() + .unwrap(); + #[cfg_attr(target_arch = "wasm32", allow(unused_mut))] + let mut loop_state: LoopState = LoopState::new(title, &event_loop); + + log::info!("Entering event loop..."); cfg_if::cfg_if! { if #[cfg(target_arch = "wasm32")] { - wasm_bindgen_futures::spawn_local(async move { start::(title).await }) + use winit::platform::web::EventLoopExtWebSys; + + event_loop.spawn_app(loop_state); } else { - pollster::block_on(start::(title)); + event_loop.run_app(&mut loop_state).unwrap(); } } } diff --git a/examples/src/hello_triangle/mod.rs b/examples/src/hello_triangle/mod.rs index 7c82d49cf07..cc9e71a11bb 100644 --- a/examples/src/hello_triangle/mod.rs +++ b/examples/src/hello_triangle/mod.rs @@ -1,179 +1,221 @@ -use std::borrow::Cow; +use std::{borrow::Cow, sync::Arc}; use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::Window, + application::ApplicationHandler, + event::WindowEvent, + event_loop::{ActiveEventLoop, EventLoop}, + window::{Window, WindowId}, }; -async fn run(event_loop: EventLoop<()>, window: Window) { - let mut size = window.inner_size(); - size.width = size.width.max(1); - size.height = size.height.max(1); - - let instance = wgpu::Instance::default(); - - let surface = instance.create_surface(&window).unwrap(); - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::default(), - force_fallback_adapter: false, - // Request an adapter which can render to our surface - compatible_surface: Some(&surface), - }) - .await - .expect("Failed to find an appropriate adapter"); - - // Create the logical device and command queue - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: None, - required_features: wgpu::Features::empty(), - // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain. - required_limits: wgpu::Limits::downlevel_webgl2_defaults() - .using_resolution(adapter.limits()), - memory_hints: wgpu::MemoryHints::MemoryUsage, +struct LoopState { + // See https://docs.rs/winit/latest/winit/changelog/v0_30/index.html#removed + // for the recommended practice regarding Window creation (from which everything depends) + // in winit >= 0.30.0. + // The actual state is in an Option because its initialization is now delayed to after + // the even loop starts running. + state: Option, +} + +impl LoopState { + fn new() -> LoopState { + LoopState { state: None } + } +} + +struct InitializedLoopState { + window: Arc, + _instance: wgpu::Instance, + surface: wgpu::Surface<'static>, + _adapter: wgpu::Adapter, + device: wgpu::Device, + queue: wgpu::Queue, + _shader: wgpu::ShaderModule, + _pipeline_layout: wgpu::PipelineLayout, + render_pipeline: wgpu::RenderPipeline, + config: wgpu::SurfaceConfiguration, +} + +impl InitializedLoopState { + async fn new(event_loop: &ActiveEventLoop) -> InitializedLoopState { + #[allow(unused_mut)] + let mut attributes = Window::default_attributes(); + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen::JsCast; + use winit::platform::web::WindowAttributesExtWebSys; + let canvas = web_sys::window() + .unwrap() + .document() + .unwrap() + .get_element_by_id("canvas") + .unwrap() + .dyn_into::() + .unwrap(); + builder = builder.with_canvas(Some(canvas)); + } + let window = Arc::new(event_loop.create_window(attributes).unwrap()); + + let mut size = window.inner_size(); + size.width = size.width.max(1); + size.height = size.height.max(1); + + let instance = wgpu::Instance::default(); + + let surface = instance.create_surface(window.clone()).unwrap(); + let adapter = wgpu::util::initialize_adapter_from_env_or_default(&instance, Some(&surface)) + .await + .expect("Failed to find an appropriate adapter"); + + // Create the logical device and command queue + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain. + required_limits: wgpu::Limits::downlevel_webgl2_defaults() + .using_resolution(adapter.limits()), + memory_hints: wgpu::MemoryHints::MemoryUsage, + }, + None, + ) + .await + .expect("Failed to create device"); + + // Load the shaders from disk + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), + }); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[], + push_constant_ranges: &[], + }); + + let swapchain_capabilities = surface.get_capabilities(&adapter); + let swapchain_format = swapchain_capabilities.formats[0]; + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: Some("vs_main"), + buffers: &[], + compilation_options: Default::default(), }, - None, - ) - .await - .expect("Failed to create device"); - - // Load the shaders from disk - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: None, - source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), - }); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: None, - bind_group_layouts: &[], - push_constant_ranges: &[], - }); - - let swapchain_capabilities = surface.get_capabilities(&adapter); - let swapchain_format = swapchain_capabilities.formats[0]; - - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: None, - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: Some("vs_main"), - buffers: &[], - compilation_options: Default::default(), - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: Some("fs_main"), - compilation_options: Default::default(), - targets: &[Some(swapchain_format.into())], - }), - primitive: wgpu::PrimitiveState::default(), - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - multiview: None, - cache: None, - }); - - let mut config = surface - .get_default_config(&adapter, size.width, size.height) - .unwrap(); - surface.configure(&device, &config); - - let window = &window; - event_loop - .run(move |event, target| { - // Have the closure take ownership of the resources. - // `event_loop.run` never returns, therefore we must do this to ensure - // the resources are properly cleaned up. - let _ = (&instance, &adapter, &shader, &pipeline_layout); - - if let Event::WindowEvent { - window_id: _, - event, - } = event + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: Some("fs_main"), + compilation_options: Default::default(), + targets: &[Some(swapchain_format.into())], + }), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + cache: None, + }); + + let config = surface + .get_default_config(&adapter, size.width, size.height) + .unwrap(); + surface.configure(&device, &config); + + InitializedLoopState { + window, + _instance: instance, + surface, + _adapter: adapter, + device, + queue, + _shader: shader, + _pipeline_layout: pipeline_layout, + render_pipeline, + config, + } + } +} + +impl ApplicationHandler for LoopState { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + if self.state.is_none() { + #[cfg(not(target_arch = "wasm32"))] { - match event { - WindowEvent::Resized(new_size) => { - // Reconfigure the surface with the new size - config.width = new_size.width.max(1); - config.height = new_size.height.max(1); - surface.configure(&device, &config); - // On macos the window needs to be redrawn manually after resizing - window.request_redraw(); - } - WindowEvent::RedrawRequested => { - let frame = surface - .get_current_texture() - .expect("Failed to acquire next swap chain texture"); - let view = frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - let mut encoder = - device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: None, - }); - { - let mut rpass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: None, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - rpass.set_pipeline(&render_pipeline); - rpass.draw(0..3, 0..1); - } - - queue.submit(Some(encoder.finish())); - frame.present(); + self.state = Some(pollster::block_on(InitializedLoopState::new(event_loop))); + } + #[cfg(target_arch = "wasm32")] + { + self.state = Some(wasm_bindgen_futures::spawn_local(async move { + InitializedLoopState::new(event_loop).await + })); + } + } + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + _window_id: WindowId, + event: WindowEvent, + ) { + if let Some(state) = self.state.as_mut() { + match event { + WindowEvent::Resized(new_size) => { + // Reconfigure the surface with the new size + state.config.width = new_size.width.max(1); + state.config.height = new_size.height.max(1); + state.surface.configure(&state.device, &state.config); + // On macos the window needs to be redrawn manually after resizing + state.window.request_redraw(); + } + WindowEvent::RedrawRequested => { + let frame = state + .surface + .get_current_texture() + .expect("Failed to acquire next swap chain texture"); + let view = frame + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = state + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + { + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + rpass.set_pipeline(&state.render_pipeline); + rpass.draw(0..3, 0..1); } - WindowEvent::CloseRequested => target.exit(), - _ => {} - }; + + state.queue.submit(Some(encoder.finish())); + frame.present(); + } + WindowEvent::CloseRequested => event_loop.exit(), + _ => {} } - }) - .unwrap(); + } + } } pub fn main() { + env_logger::init(); + + let mut loop_state = LoopState::new(); let event_loop = EventLoop::new().unwrap(); - #[allow(unused_mut)] - let mut builder = winit::window::WindowBuilder::new(); - #[cfg(target_arch = "wasm32")] - { - use wasm_bindgen::JsCast; - use winit::platform::web::WindowBuilderExtWebSys; - let canvas = web_sys::window() - .unwrap() - .document() - .unwrap() - .get_element_by_id("canvas") - .unwrap() - .dyn_into::() - .unwrap(); - builder = builder.with_canvas(Some(canvas)); - } - let window = builder.build(&event_loop).unwrap(); - #[cfg(not(target_arch = "wasm32"))] - { - env_logger::init(); - pollster::block_on(run(event_loop, window)); - } - #[cfg(target_arch = "wasm32")] - { - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - console_log::init().expect("could not initialize logger"); - wasm_bindgen_futures::spawn_local(run(event_loop, window)); - } + log::info!("Entering event loop..."); + event_loop.run_app(&mut loop_state).unwrap(); } diff --git a/examples/src/hello_windows/mod.rs b/examples/src/hello_windows/mod.rs index b568f35d38c..9d5c43ed536 100644 --- a/examples/src/hello_windows/mod.rs +++ b/examples/src/hello_windows/mod.rs @@ -2,8 +2,9 @@ use std::{collections::HashMap, sync::Arc}; use winit::{ - event::{Event, WindowEvent}, - event_loop::EventLoop, + application::ApplicationHandler, + event::WindowEvent, + event_loop::ActiveEventLoop, window::{Window, WindowId}, }; @@ -53,109 +54,31 @@ impl Viewport { } } -async fn run(event_loop: EventLoop<()>, viewports: Vec<(Arc, wgpu::Color)>) { - let instance = wgpu::Instance::default(); - let viewports: Vec<_> = viewports - .into_iter() - .map(|(window, color)| ViewportDesc::new(window, color, &instance)) - .collect(); - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - // Request an adapter which can render to our surface - compatible_surface: viewports.first().map(|desc| &desc.surface), - ..Default::default() - }) - .await - .expect("Failed to find an appropriate adapter"); +struct LoopState { + // See https://docs.rs/winit/latest/winit/changelog/v0_30/index.html#removed + // for the recommended practice regarding Window creation (from which everything depends) + // in winit >= 0.30.0. + // The actual state is in an Option because its initialization is now delayed to after + // the even loop starts running. + state: Option, +} - // Create the logical device and command queue - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: None, - required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::downlevel_defaults(), - memory_hints: wgpu::MemoryHints::MemoryUsage, - }, - None, - ) - .await - .expect("Failed to create device"); - - let mut viewports: HashMap = viewports - .into_iter() - .map(|desc| (desc.window.id(), desc.build(&adapter, &device))) - .collect(); - - event_loop - .run(move |event, target| { - // Have the closure take ownership of the resources. - // `event_loop.run` never returns, therefore we must do this to ensure - // the resources are properly cleaned up. - let _ = (&instance, &adapter); - - if let Event::WindowEvent { window_id, event } = event { - match event { - WindowEvent::Resized(new_size) => { - // Recreate the swap chain with the new size - if let Some(viewport) = viewports.get_mut(&window_id) { - viewport.resize(&device, new_size); - // On macos the window needs to be redrawn manually after resizing - viewport.desc.window.request_redraw(); - } - } - WindowEvent::RedrawRequested => { - if let Some(viewport) = viewports.get_mut(&window_id) { - let frame = viewport.get_current_texture(); - let view = frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - let mut encoder = - device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: None, - }); - { - let _rpass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: None, - color_attachments: &[Some( - wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear( - viewport.desc.background, - ), - store: wgpu::StoreOp::Store, - }, - }, - )], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - } - - queue.submit(Some(encoder.finish())); - frame.present(); - } - } - WindowEvent::CloseRequested => { - viewports.remove(&window_id); - if viewports.is_empty() { - target.exit(); - } - } - _ => {} - } - } - }) - .unwrap(); +impl LoopState { + fn new() -> LoopState { + LoopState { state: None } + } } -pub fn main() { - #[cfg(not(target_arch = "wasm32"))] - { +struct InitializedLoopState { + _instance: wgpu::Instance, + _adapter: wgpu::Adapter, + device: wgpu::Device, + queue: wgpu::Queue, + viewports: HashMap, +} + +impl InitializedLoopState { + async fn new(event_loop: &ActiveEventLoop) -> InitializedLoopState { const WINDOW_SIZE: u32 = 128; const WINDOW_PADDING: u32 = 16; const WINDOW_TITLEBAR: u32 = 32; @@ -163,14 +86,18 @@ pub fn main() { const ROWS: u32 = 4; const COLUMNS: u32 = 4; - let event_loop = EventLoop::new().unwrap(); let mut viewports = Vec::with_capacity((ROWS * COLUMNS) as usize); for row in 0..ROWS { for column in 0..COLUMNS { - let window = winit::window::WindowBuilder::new() - .with_title(format!("x{column}y{row}")) - .with_inner_size(winit::dpi::PhysicalSize::new(WINDOW_SIZE, WINDOW_SIZE)) - .build(&event_loop) + let window = event_loop + .create_window( + Window::default_attributes() + .with_title(format!("x{column}y{row}")) + .with_inner_size(winit::dpi::PhysicalSize::new( + WINDOW_SIZE, + WINDOW_SIZE, + )), + ) .unwrap(); let window = Arc::new(window); window.set_outer_position(winit::dpi::PhysicalPosition::new( @@ -192,8 +119,125 @@ pub fn main() { } } + let instance = wgpu::Instance::default(); + let viewports: Vec<_> = viewports + .into_iter() + .map(|(window, color)| ViewportDesc::new(window, color, &instance)) + .collect(); + let adapter = wgpu::util::initialize_adapter_from_env_or_default( + &instance, + viewports.first().map(|desc| &desc.surface), + ) + .await + .expect("Failed to find an appropriate adapter"); + + // Create the logical device and command queue + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_defaults(), + memory_hints: wgpu::MemoryHints::default(), + }, + None, + ) + .await + .expect("Failed to create device"); + + let viewports: HashMap = viewports + .into_iter() + .map(|desc| (desc.window.id(), desc.build(&adapter, &device))) + .collect(); + + InitializedLoopState { + _instance: instance, + _adapter: adapter, + device, + queue, + viewports, + } + } +} + +impl ApplicationHandler for LoopState { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + if self.state.is_none() { + self.state = Some(pollster::block_on(InitializedLoopState::new(event_loop))); + } + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: WindowId, + event: WindowEvent, + ) { + if let Some(state) = self.state.as_mut() { + match event { + WindowEvent::Resized(new_size) => { + // Recreate the swap chain with the new size + if let Some(viewport) = state.viewports.get_mut(&window_id) { + viewport.resize(&state.device, new_size); + // On macos the window needs to be redrawn manually after resizing + viewport.desc.window.request_redraw(); + } + } + WindowEvent::RedrawRequested => { + if let Some(viewport) = state.viewports.get_mut(&window_id) { + let frame = viewport.get_current_texture(); + let view = frame + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = + state + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: None, + }); + { + let _rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(viewport.desc.background), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + } + + state.queue.submit(Some(encoder.finish())); + frame.present(); + } + } + WindowEvent::CloseRequested => { + state.viewports.remove(&window_id); + if state.viewports.is_empty() { + event_loop.exit(); + } + } + _ => {} + } + } + } +} + +pub fn main() { + #[cfg(not(target_arch = "wasm32"))] + { env_logger::init(); - pollster::block_on(run(event_loop, viewports)); + + let mut loop_state = LoopState::new(); + let event_loop = EventLoop::new().unwrap(); + + log::info!("Entering event loop..."); + event_loop.run_app(&mut loop_state).unwrap(); } #[cfg(target_arch = "wasm32")] { diff --git a/examples/src/lib.rs b/examples/src/lib.rs index d212fd404ac..eb0c3a93298 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -10,6 +10,7 @@ pub mod cube; pub mod hello; pub mod hello_compute; pub mod hello_synchronization; +#[cfg(not(target_arch = "wasm32"))] pub mod hello_triangle; pub mod hello_windows; pub mod hello_workgroups; @@ -24,6 +25,7 @@ pub mod stencil_triangles; pub mod storage_texture; pub mod texture_arrays; pub mod timestamp_queries; +#[cfg(not(target_arch = "wasm32"))] pub mod uniform_values; pub mod water; diff --git a/examples/src/main.rs b/examples/src/main.rs index 8b149d5a28d..55e9b64712f 100644 --- a/examples/src/main.rs +++ b/examples/src/main.rs @@ -50,6 +50,7 @@ const EXAMPLES: &[ExampleDesc] = &[ webgl: false, // No canvas for WebGL webgpu: true, }, + #[cfg(not(target_arch = "wasm32"))] ExampleDesc { name: "hello_triangle", function: wgpu_examples::hello_triangle::main, @@ -134,6 +135,7 @@ const EXAMPLES: &[ExampleDesc] = &[ webgl: false, // No canvas for WebGL webgpu: false, // No timestamp queries }, + #[cfg(not(target_arch = "wasm32"))] ExampleDesc { name: "uniform_values", function: wgpu_examples::uniform_values::main, diff --git a/examples/src/uniform_values/mod.rs b/examples/src/uniform_values/mod.rs index f275853ba25..7a775189591 100644 --- a/examples/src/uniform_values/mod.rs +++ b/examples/src/uniform_values/mod.rs @@ -21,10 +21,11 @@ use std::sync::Arc; // with actual GPU-allocated WGPU storage buffers. use encase::ShaderType; use winit::{ - event::{Event, KeyEvent, WindowEvent}, - event_loop::EventLoop, + application::ApplicationHandler, + event::{KeyEvent, WindowEvent}, + event_loop::{ActiveEventLoop, EventLoop}, keyboard::{Key, NamedKey}, - window::Window, + window::{Window, WindowId}, }; const ZOOM_INCREMENT_FACTOR: f32 = 1.1; @@ -221,155 +222,187 @@ impl WgpuContext { } } -async fn run(event_loop: EventLoop<()>, window: Arc) { - let mut wgpu_context = Some(WgpuContext::new(window).await); - // (6) - let mut state = Some(AppState::default()); - let main_window_id = wgpu_context.as_ref().unwrap().window.id(); - event_loop - .run(move |event, target| { +struct LoopState { + // See https://docs.rs/winit/latest/winit/changelog/v0_30/index.html#removed + // for the recommended practice regarding Window creation (from which everything depends) + // in winit >= 0.30.0. + // The actual state is in an Option because its initialization is now delayed to after + // the even loop starts running. + state: Option, +} + +impl LoopState { + fn new() -> LoopState { + LoopState { state: None } + } +} + +struct InitializedLoopState { + wgpu_context: WgpuContext, + app_state: AppState, + main_window_id: WindowId, +} + +impl InitializedLoopState { + async fn new(event_loop: &ActiveEventLoop) -> InitializedLoopState { + #[allow(unused_mut)] + let mut window_attributes = Window::default_attributes() + .with_title("Remember: Use U/D to change sample count!") + .with_inner_size(winit::dpi::LogicalSize::new(900, 900)); + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen::JsCast; + use winit::platform::web::WindowAttributesExtWebSys; + let canvas = web_sys::window() + .unwrap() + .document() + .unwrap() + .get_element_by_id("canvas") + .unwrap() + .dyn_into::() + .unwrap(); + window_attributes = window_attributes.with_canvas(Some(canvas)); + } + + let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); + + let wgpu_context = WgpuContext::new(window).await; + // (6) + let app_state = AppState::default(); + let main_window_id = wgpu_context.window.id(); + + InitializedLoopState { + wgpu_context, + app_state, + main_window_id, + } + } +} + +impl ApplicationHandler for LoopState { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + if self.state.is_none() { + #[cfg(not(target_arch = "wasm32"))] + { + self.state = Some(pollster::block_on(InitializedLoopState::new(event_loop))); + } + #[cfg(target_arch = "wasm32")] + { + self.state = Some(wasm_bindgen_futures::spawn_local(async move { + InitializedLoopState::new(event_loop).await + })); + } + } + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: WindowId, + event: WindowEvent, + ) { + if let Some(state) = self.state.as_mut() { + if window_id != state.main_window_id { + return; + } match event { - Event::LoopExiting => { - wgpu_context = None; - state = None; + WindowEvent::CloseRequested => { + event_loop.exit(); } - Event::WindowEvent { window_id, event } if window_id == main_window_id => { - match event { - WindowEvent::CloseRequested => { - target.exit(); - } - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key, text, .. - }, - .. - } => { - let state_mut = state.as_mut().unwrap(); - let wgpu_context_ref = wgpu_context.as_ref().unwrap(); - - if let Key::Named(key) = logical_key { - match key { - NamedKey::Escape => target.exit(), - NamedKey::ArrowUp => state_mut.translate_view(1, 1), - NamedKey::ArrowDown => state_mut.translate_view(-1, 1), - NamedKey::ArrowLeft => state_mut.translate_view(-1, 0), - NamedKey::ArrowRight => state_mut.translate_view(1, 0), - _ => {} - } - } - - if let Some(text) = text { - if text == "u" { - state_mut.max_iterations += 3; - } else if text == "d" { - state_mut.max_iterations -= 3; - } - }; - - wgpu_context_ref.window.request_redraw(); - } - WindowEvent::MouseWheel { delta, .. } => { - let change = match delta { - winit::event::MouseScrollDelta::LineDelta(_, vertical) => vertical, - winit::event::MouseScrollDelta::PixelDelta(pos) => { - pos.y as f32 / 20.0 - } - }; - let state_mut = state.as_mut().unwrap(); - let wgpu_context_ref = wgpu_context.as_ref().unwrap(); - // (7b) - state_mut.zoom(change); - wgpu_context_ref.window.request_redraw(); - } - WindowEvent::Resized(new_size) => { - let wgpu_context_mut = wgpu_context.as_mut().unwrap(); - wgpu_context_mut.resize(new_size); - wgpu_context_mut.window.request_redraw(); + WindowEvent::KeyboardInput { + event: + KeyEvent { + logical_key, text, .. + }, + .. + } => { + if let Key::Named(key) = logical_key { + match key { + NamedKey::Escape => event_loop.exit(), + NamedKey::ArrowUp => state.app_state.translate_view(1, 1), + NamedKey::ArrowDown => state.app_state.translate_view(-1, 1), + NamedKey::ArrowLeft => state.app_state.translate_view(-1, 0), + NamedKey::ArrowRight => state.app_state.translate_view(1, 0), + _ => {} } - WindowEvent::RedrawRequested => { - let wgpu_context_ref = wgpu_context.as_ref().unwrap(); - let state_ref = state.as_ref().unwrap(); - let frame = wgpu_context_ref.surface.get_current_texture().unwrap(); - let view = frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - - // (8) - wgpu_context_ref.queue.write_buffer( - &wgpu_context_ref.uniform_buffer, - 0, - &state_ref.as_wgsl_bytes().expect( - "Error in encase translating AppState \ - struct to WGSL bytes.", - ), - ); - let mut encoder = wgpu_context_ref.device.create_command_encoder( - &wgpu::CommandEncoderDescriptor { label: None }, - ); - { - let mut render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: None, - color_attachments: &[Some( - wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), - store: wgpu::StoreOp::Store, - }, - }, - )], - depth_stencil_attachment: None, - occlusion_query_set: None, - timestamp_writes: None, - }); - render_pass.set_pipeline(&wgpu_context_ref.pipeline); - // (9) - render_pass.set_bind_group(0, &wgpu_context_ref.bind_group, &[]); - render_pass.draw(0..3, 0..1); - } - wgpu_context_ref.queue.submit(Some(encoder.finish())); - frame.present(); + } + + if let Some(text) = text { + if text == "u" { + state.app_state.max_iterations += 3; + } else if text == "d" { + state.app_state.max_iterations -= 3; } - _ => {} + }; + + state.wgpu_context.window.request_redraw(); + } + WindowEvent::MouseWheel { delta, .. } => { + let change = match delta { + winit::event::MouseScrollDelta::LineDelta(_, vertical) => vertical, + winit::event::MouseScrollDelta::PixelDelta(pos) => pos.y as f32 / 20.0, + }; + // (7b) + state.app_state.zoom(change); + state.wgpu_context.window.request_redraw(); + } + WindowEvent::Resized(new_size) => { + state.wgpu_context.resize(new_size); + state.wgpu_context.window.request_redraw(); + } + WindowEvent::RedrawRequested => { + let frame = state.wgpu_context.surface.get_current_texture().unwrap(); + let view = frame + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + + // (8) + state.wgpu_context.queue.write_buffer( + &state.wgpu_context.uniform_buffer, + 0, + &state.app_state.as_wgsl_bytes().expect( + "Error in encase translating AppState \ + struct to WGSL bytes.", + ), + ); + let mut encoder = state + .wgpu_context + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + { + let mut render_pass = + encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + occlusion_query_set: None, + timestamp_writes: None, + }); + render_pass.set_pipeline(&state.wgpu_context.pipeline); + // (9) + render_pass.set_bind_group(0, &state.wgpu_context.bind_group, &[]); + render_pass.draw(0..3, 0..1); } + state.wgpu_context.queue.submit(Some(encoder.finish())); + frame.present(); } _ => {} } - }) - .unwrap(); -} - -pub fn main() { - let event_loop = EventLoop::new().unwrap(); - #[allow(unused_mut)] - let mut builder = winit::window::WindowBuilder::new() - .with_title("Remember: Use U/D to change sample count!") - .with_inner_size(winit::dpi::LogicalSize::new(900, 900)); - - #[cfg(target_arch = "wasm32")] - { - use wasm_bindgen::JsCast; - use winit::platform::web::WindowBuilderExtWebSys; - let canvas = web_sys::window() - .unwrap() - .document() - .unwrap() - .get_element_by_id("canvas") - .unwrap() - .dyn_into::() - .unwrap(); - builder = builder.with_canvas(Some(canvas)); + } } - let window = builder.build(&event_loop).unwrap(); +} - let window = Arc::new(window); +async fn start() { #[cfg(not(target_arch = "wasm32"))] { env_logger::builder().format_timestamp_nanos().init(); - pollster::block_on(run(event_loop, window)); } #[cfg(target_arch = "wasm32")] { @@ -391,7 +424,21 @@ U, D: Increase / decrease sample count.", ); body.append_child(&controls_text) .expect("Failed to append controls text to body."); + } - wasm_bindgen_futures::spawn_local(run(event_loop, window)); + let mut loop_state = LoopState::new(); + let event_loop = EventLoop::new().unwrap(); + + log::info!("Entering event loop..."); + event_loop.run_app(&mut loop_state).unwrap(); +} + +pub fn main() { + cfg_if::cfg_if! { + if #[cfg(target_arch = "wasm32")] { + wasm_bindgen_futures::spawn_local(async move { start::(title).await }) + } else { + pollster::block_on(start()); + } } }