diff --git a/.gitattributes b/.gitattributes index c5ebf26c98..b8f70a660c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,12 +3,12 @@ alvr/client_core/cpp/VrApi_* linguist-vendored alvr/client_core/cpp/glm/** linguist-vendored alvr/client_core/cpp/tinygltf/** linguist-vendored -alvr/server/cpp/alvr_server/include/** linguist-vendored -alvr/server/cpp/alvr_server/nvEncodeAPI.h linguist-vendored -alvr/server/cpp/platform/win32/NvCodecUtils.h linguist-vendored -alvr/server/cpp/platform/win32/NvEncoder.cpp linguist-vendored -alvr/server/cpp/platform/win32/NvEncoder.h linguist-vendored -alvr/server/cpp/shared/** linguist-vendored +alvr/server_openvr/cpp/alvr_server/include/** linguist-vendored +alvr/server_openvr/cpp/alvr_server/nvEncodeAPI.h linguist-vendored +alvr/server_openvr/cpp/platform/win32/NvCodecUtils.h linguist-vendored +alvr/server_openvr/cpp/platform/win32/NvEncoder.cpp linguist-vendored +alvr/server_openvr/cpp/platform/win32/NvEncoder.h linguist-vendored +alvr/server_openvr/cpp/shared/** linguist-vendored # note: some of these folders contain ALVR code, but only a minor amount alvr/vulkan_layer/layer/** linguist-vendored alvr/vulkan_layer/util/** linguist-vendored diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3025cfbf21..db1c2f66c5 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,4 +10,5 @@ jobs: - uses: actions/stale@v9 with: stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - exempt-issue-labels: 'bug,documentation,enhancement,good-first-issue,hep-wanted,needs-testing,release' \ No newline at end of file + exempt-issue-labels: 'bug,documentation,enhancement,good-first-issue,hep-wanted,needs-testing,release' + exempt-draft-pr: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bdcd4e896..2b17656e49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,45 @@ # Changelog -### v20.7.1 +### v20.9.1 (2024-07-06) + +* Fix performance issues on lobby room. + +## v20.9.0 (2024-07-06) + +* Display license inside the dashboard (by @zarik5 #2117) +* Add GPU checks for Linux (by @Meister1593 #2110) +* Reorder settings (by @zarik5 #2119) +* Shallow rename "client" -> "device" (by @zarik5 #2120) +* Update manifest for AppLab (by @zarik5 #2146) +* Allow recentering in the lobby (by @zarik5 #2155) +* Tweak graph labels and colors (by @zarik5 #2176) +* Fix controller detection on Pico Neo 3 Link (by @HoLo85 #2192) +* Loosen restrictions on device selection with VoiceMeeter (by @xuan25 #2209) +* Fix HEVC black screen on Linux/VAAPI (by @Nibor62 #2203) +* Show hands and controllers in the lobby (by @zarik5 #2218) +* Add PipeWire support on Linux (by @Meister1593 #1973) + +### v20.8.1 (2024-05-08) + +* Fix crash on Linux (by @SniperJoe #2108) + +## v20.8.0 (2024-05-04) + +* Bring back settings tabs (by @Meister1593 #2076) +* Make FFE shader much lighter (by @yoyobuae #2083) +* Improve firewall rules on Linux (by @Meister1593 #2078) +* Fix error message not displaying correctly on Linux sometimes (by @SniperJoe #2088) +* Fix Nvidia encoder on some Linux systems (by @Xaphiosis @nowrep #2074) +* Fix client warmstart crash (by @ShootingKing-AM #2084) +* Fix segfault on Linux (by @SniperJoe #2090) +* Fix protocol break in v20.7.0 (by @zarik5 2098) + +### v20.7.1 (2024-04-11) * Fix colors on Pico (by @shinyquagsire23 and @zarik5) * Fix joystick gesture offset on right hand (by @jarettmillard #2065) -## v20.7.0 +## v20.7.0 (2024-04-06) * Add AV1 support on Windows/AMD (by @barnabwhy #1967) * Add AV1 support on Linux/Nvidia (by @wsippel #1975, @Vixea #1994) @@ -27,12 +61,12 @@ * Remove WIX installer (by @zarik5) * Remove AppImage (by @Meister1593 #2056) -### v20.6.1 +### v20.6.1 (2024-01-26) * Add AV1 support, only for Linux/VAAPI, with 10bits support (by @wsippel #1955 #1964) * Fix image corruption on h264/VAAPI (by @galister / @nowrep #1956) -## v20.6.0 +## v20.6.0 (2024-01-10) * Add tongue tracking for Quest Pro (by @zarik5) * This is a breaking change in the protocol, but only affects Quest Pro users. @@ -44,7 +78,7 @@ * Fix ADB connection (by @The-personified-devil #1942) * Fix rare bug preventing reconnections on wifi (by @zarik5) -## v20.5.0 +## v20.5.0 (2023-12-05) * Fix Vulkan layer GPU loading (by @nairaner #1847) * Fix dynamic bitrate for VAAPI (by @nowrep #1863) @@ -60,34 +94,34 @@ * Fix SteamVR hanging when restarting on Linux (by @Vixea @zarik5) * Other dashboard updates -### v20.4.3 +### v20.4.3 (2023-10-06) * Fix dashboard crash on Windows * Fix settings reset bug when upgrading (session extrapolation failed) -### v20.4.2 +### v20.4.2 (2023-09-22) * Fix YVR crash because of invalid controller bindings -### v20.4.1 +### v20.4.1 (2023-09-19) * Fix inverted `Enable skeleton` switch * Add `Only touch` gestures option -## v20.4.0 +## v20.4.0 (2023-09-15) * Full hand tracking gestures support, with joystick (by @barnabwhy #1794) * Fully remappable controller buttons (by @zarik5 #1817) * Custom controller profile (by @zarik5) * Fix Nvidia support on Linux (by @Killrmemz #1830) -### v20.3.1 +### v20.3.1 (2023-09-11) * Fix some controller buttons not working * Fix changing controller emulation profile not triggering a SteamVR restart * Add back Rift S controller emulation profile -## v20.3.0 +## v20.3.0 (2023-09-08) * Add Lynx R1 headset support (by @zarik5 #1823) * Currently there is an issue with hand tracking which is being investigated @@ -100,12 +134,12 @@ * Timeout connection if lingering (by @zarik5) * Fix warmstart crash on client (by @ShootingKing-AM #1813) -### v20.2.1 +### v20.2.1 (2023-08-27) * Fix VRCFaceTracking mode panicing. * (Potential) Fix for dashboard crash on Wayland. -## v20.2.0 +## v20.2.0 (2023-08-26) * Add Flatpak build (by @CharlieQLe #1683 #1724 #1735 #1742, @Meister1593 #1769) * Finish VRCFaceTracking support (by @zarik5) @@ -126,7 +160,7 @@ * Fix OpenGL crash on the client (by @ShootingKing-AM #1801) * Fix white dashboard bug on Linux (by @zarik5) -## v20.1.0 +## v20.1.0 (2023-06-20) * Fix firewall rules on Windows (by @zarik5) * Fix firewall rules on linux for the tar.gz (by @Vixea #1675) @@ -141,7 +175,7 @@ * Add option to disable game render optimization (by @zarik5) * Add separate history size for bitrate (by @zarik5) -# v20.0.0 +# v20.0.0 (2023-06-02) * New OpenXR-based client, add support for Vive Focus 3/XR Elite, Pico 4/Neo 3 and YVR 1/2. Worked on by: * @zarik5 #1321 @@ -167,11 +201,11 @@ * Some tweaks for alvr_client_core compatibility (by @ShootingKing-AM #1580 #1578 #1586 #1624 #1621) * Fix server build with clang (by @nowrep) -### v19.1.1 +### v19.1.1 (2023-03-03) * Relax discovery protocol for future ALVR versions -## v19.1.0 +## v19.1.0 (2023-02-14) * Encoder improvements and new Linux server compositor: * @deiteris #1227, #1252, #1281, #1287, #1302, #1304, #1318, #1331, #1336, #1368, #1393, #1367, #1397 diff --git a/Cargo.lock b/Cargo.lock index 93818cfccf..51f736e587 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.26" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e53b0a3d5760cd2ba9b787ae0c6440ad18ee294ff71b05e3381c900a7d16cfd" +checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -150,7 +150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce" dependencies = [ "alsa-sys", - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -166,7 +166,7 @@ dependencies = [ [[package]] name = "alvr_audio" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_session", @@ -177,12 +177,12 @@ dependencies = [ "rodio", "serde", "widestring", - "windows 0.56.0", + "windows 0.58.0", ] [[package]] name = "alvr_client_core" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_audio", "alvr_common", @@ -194,7 +194,7 @@ dependencies = [ "bincode", "bindgen", "cc", - "env_logger 0.11.3", + "env_logger", "glow", "glyph_brush_layout", "jni", @@ -205,29 +205,32 @@ dependencies = [ "ndk-context", "ndk-sys 0.6.0+11769913", "oboe", + "pollster", "rand", "serde", "serde_json", "walkdir", + "wgpu", + "wgpu-core", "whoami", ] [[package]] name = "alvr_client_mock" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_client_core", "alvr_common", "alvr_packets", "alvr_session", "eframe", - "env_logger 0.11.3", + "env_logger", "rand", ] [[package]] name = "alvr_client_openxr" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_client_core", "alvr_common", @@ -242,7 +245,7 @@ dependencies = [ [[package]] name = "alvr_common" -version = "20.9.1" +version = "20.10.0" dependencies = [ "anyhow", "backtrace", @@ -259,7 +262,7 @@ dependencies = [ [[package]] name = "alvr_dashboard" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_events", @@ -273,7 +276,7 @@ dependencies = [ "console_error_panic_hook", "cros-libva", "eframe", - "env_logger 0.11.3", + "env_logger", "ewebsock", "futures", "gloo-net", @@ -290,13 +293,13 @@ dependencies = [ "ureq", "wasm-bindgen-futures", "wasm-logger", - "wgpu 0.20.0", + "wgpu", "winres", ] [[package]] name = "alvr_events" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_packets", @@ -307,7 +310,7 @@ dependencies = [ [[package]] name = "alvr_filesystem" -version = "20.9.1" +version = "20.10.0" dependencies = [ "dirs", "once_cell", @@ -315,7 +318,7 @@ dependencies = [ [[package]] name = "alvr_gui_common" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "egui", @@ -323,7 +326,7 @@ dependencies = [ [[package]] name = "alvr_launcher" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_gui_common", @@ -333,7 +336,7 @@ dependencies = [ "futures-util", "ico", "open", - "reqwest 0.12.4", + "reqwest 0.12.5", "serde_json", "tar", "tokio", @@ -343,7 +346,7 @@ dependencies = [ [[package]] name = "alvr_packets" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_session", @@ -352,8 +355,8 @@ dependencies = [ ] [[package]] -name = "alvr_server" -version = "20.9.1" +name = "alvr_server_core" +version = "20.10.0" dependencies = [ "alvr_audio", "alvr_common", @@ -365,17 +368,14 @@ dependencies = [ "alvr_sockets", "ash 0.38.0+1.3.281", "bincode", - "bindgen", "bytes", - "cc", "chrono", "fern", "flume", "futures", "headers", - "hyper 0.14.28", + "hyper 0.14.30", "mdns-sd", - "pkg-config", "profiling", "reqwest 0.11.27", "rosc", @@ -385,12 +385,11 @@ dependencies = [ "tokio", "tokio-tungstenite", "tokio-util", - "walkdir", ] [[package]] name = "alvr_server_io" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_events", @@ -404,9 +403,25 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alvr_server_openvr" +version = "20.10.0" +dependencies = [ + "alvr_common", + "alvr_filesystem", + "alvr_packets", + "alvr_server_core", + "alvr_server_io", + "alvr_session", + "bindgen", + "cc", + "pkg-config", + "walkdir", +] + [[package]] name = "alvr_session" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_filesystem", @@ -419,7 +434,7 @@ dependencies = [ [[package]] name = "alvr_sockets" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_session", @@ -432,7 +447,7 @@ dependencies = [ [[package]] name = "alvr_vrcompositor_wrapper" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_filesystem", @@ -442,7 +457,7 @@ dependencies = [ [[package]] name = "alvr_vulkan_layer" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_common", "alvr_filesystem", @@ -454,7 +469,7 @@ dependencies = [ [[package]] name = "alvr_xtask" -version = "20.9.1" +version = "20.10.0" dependencies = [ "alvr_filesystem", "pico-args", @@ -470,7 +485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" dependencies = [ "android-properties", - "bitflags 2.5.0", + "bitflags 2.6.0", "cc", "cesu8", "jni", @@ -491,7 +506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.5.0", + "bitflags 2.6.0", "cc", "cesu8", "jni", @@ -525,14 +540,13 @@ checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" [[package]] name = "android_logger" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" dependencies = [ "android_log-sys", - "env_logger 0.10.2", + "env_filter", "log", - "once_cell", ] [[package]] @@ -586,9 +600,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -690,7 +704,7 @@ version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.8.3", + "libloading 0.8.4", ] [[package]] @@ -708,7 +722,7 @@ dependencies = [ "serde", "serde_repr", "url", - "zbus 4.2.2", + "zbus 4.3.1", ] [[package]] @@ -723,9 +737,9 @@ dependencies = [ [[package]] name = "async-broadcast" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" dependencies = [ "event-listener 5.3.1", "event-listener-strategy", @@ -813,7 +827,7 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.1", + "polling 3.7.2", "rustix 0.38.34", "slab", "tracing", @@ -902,14 +916,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] name = "async-signal" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329972aa325176e89114919f2a80fdae4f4c040f66a370b1a1159c6c0f94e7aa" +checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" dependencies = [ "async-io 2.3.3", "async-lock 3.4.0", @@ -931,13 +945,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -1002,9 +1016,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -1043,7 +1057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ "annotate-snippets", - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools", @@ -1056,7 +1070,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.70", "which", ] @@ -1083,9 +1097,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block" @@ -1170,9 +1184,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" dependencies = [ "bytemuck_derive", ] @@ -1185,7 +1199,7 @@ checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -1227,9 +1241,9 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "log", - "polling 3.7.1", + "polling 3.7.2", "rustix 0.38.34", "slab", "thiserror", @@ -1249,9 +1263,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.98" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "eaff6f8ce506b9773fa786672d63fc7a191ffea1be33f72bbd4aeacefca9ffc8" dependencies = [ "jobserver", "libc", @@ -1295,6 +1309,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" @@ -1315,7 +1335,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1336,7 +1356,7 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.3", + "libloading 0.8.4", ] [[package]] @@ -1347,43 +1367,13 @@ checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" [[package]] name = "clipboard-win" -version = "5.3.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79f4473f5144e20d9aceaf2972478f06ddf687831eafeeb434fbaf0acc4144ad" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" dependencies = [ "error-code", ] -[[package]] -name = "cocoa" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation", - "core-graphics", - "foreign-types 0.5.0", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation", - "core-graphics-types", - "libc", - "objc", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1394,12 +1384,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "colorchoice" version = "1.0.1" @@ -1647,16 +1631,16 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" dependencies = [ - "bitflags 2.5.0", - "libloading 0.8.3", + "bitflags 2.6.0", + "libloading 0.8.4", "winapi", ] [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -1664,27 +1648,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -1733,7 +1717,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -1776,13 +1760,13 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -1791,7 +1775,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.3", + "libloading 0.8.4", ] [[package]] @@ -1811,21 +1795,22 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "ecolor" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20930a432bbd57a6d55e07976089708d4893f3d556cf42a0d79e9e321fa73b10" +checksum = "2e6b451ff1143f6de0f33fc7f1b68fecfd2c7de06e104de96c4514de3f5396f8" dependencies = [ "bytemuck", + "emath", ] [[package]] name = "eframe" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020e2ccef6bbcec71dbc542f7eed64a5846fc3076727f5746da8fd307c91bab2" +checksum = "6490ef800b2e41ee129b1f32f9ac15f713233fe3bc18e241a1afe1e4fb6811e0" dependencies = [ + "ahash", "bytemuck", - "cocoa", "document-features", "egui", "egui-wgpu", @@ -1837,13 +1822,14 @@ dependencies = [ "image", "js-sys", "log", - "objc", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation", "parking_lot", "percent-encoding", "raw-window-handle 0.5.2", "raw-window-handle 0.6.2", "static_assertions", - "thiserror", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1854,12 +1840,13 @@ dependencies = [ [[package]] name = "egui" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584c5d1bf9a67b25778a3323af222dbe1a1feb532190e103901187f92c7fe29a" +checksum = "20c97e70a2768de630f161bb5392cbd3874fcf72868f14df0e002e82e06cb798" dependencies = [ "accesskit", "ahash", + "emath", "epaint", "log", "nohash-hasher", @@ -1867,10 +1854,11 @@ dependencies = [ [[package]] name = "egui-wgpu" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469ff65843f88a702b731a1532b7d03b0e8e96d283e70f3a22b0e06c46cb9b37" +checksum = "47c7a7c707877c3362a321ebb4f32be811c0b91f7aebf345fb162405c0218b4c" dependencies = [ + "ahash", "bytemuck", "document-features", "egui", @@ -1879,17 +1867,18 @@ dependencies = [ "thiserror", "type-map", "web-time", - "wgpu 0.19.4", + "wgpu", "winit", ] [[package]] name = "egui-winit" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e3da0cbe020f341450c599b35b92de4af7b00abde85624fd16f09c885573609" +checksum = "fac4e066af341bf92559f60dbdf2020b2a03c963415349af5f3f8d79ff7a4926" dependencies = [ "accesskit_winit", + "ahash", "arboard", "egui", "log", @@ -1902,10 +1891,11 @@ dependencies = [ [[package]] name = "egui_glow" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e5d975f3c86edc3d35b1db88bb27c15dde7c55d3b5af164968ab5ede3f44ca" +checksum = "4e2bdc8b38cfa17cc712c4ae079e30c71c00cd4c2763c9e16dc7860a02769103" dependencies = [ + "ahash", "bytemuck", "egui", "glow", @@ -1918,15 +1908,15 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "emath" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c3a552cfca14630702449d35f41c84a0d15963273771c6059175a803620f3f" +checksum = "0a6a21708405ea88f63d8309650b4d77431f4bc28fb9d8e6f77d3963b51249e6" dependencies = [ "bytemuck", ] @@ -1957,9 +1947,9 @@ checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" [[package]] name = "enumflags2" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ "enumflags2_derive", "serde", @@ -1967,13 +1957,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -1986,16 +1976,6 @@ dependencies = [ "regex", ] -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "log", - "regex", -] - [[package]] name = "env_logger" version = "0.11.3" @@ -2011,9 +1991,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.27.2" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b381f8b149657a4acf837095351839f32cd5c4aec1817fc4df84e18d76334176" +checksum = "3f0dcc0a0771e7500e94cd1cb797bd13c9f23b9409bdc3c824e2cbc562b7fa01" dependencies = [ "ab_glyph", "ahash", @@ -2231,7 +2211,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -2339,7 +2319,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -2438,9 +2418,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" +checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94" dependencies = [ "serde", ] @@ -2503,8 +2483,8 @@ version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" dependencies = [ - "bitflags 2.5.0", - "cfg_aliases", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", "cgl", "core-foundation", "dispatch", @@ -2512,7 +2492,7 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "icrate", - "libloading 0.8.3", + "libloading 0.8.4", "objc2 0.4.1", "once_cell", "raw-window-handle 0.5.2", @@ -2527,7 +2507,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" dependencies = [ - "cfg_aliases", + "cfg_aliases 0.1.1", "glutin", "raw-window-handle 0.5.2", "winit", @@ -2564,9 +2544,9 @@ dependencies = [ [[package]] name = "glyph_brush_layout" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" +checksum = "7b1e288bfd2f6c0313f78bf5aa538356ad481a3bb97e9b7f93220ab0066c5992" dependencies = [ "ab_glyph", "approx", @@ -2579,7 +2559,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "gpu-alloc-types", ] @@ -2589,7 +2569,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -2605,44 +2585,24 @@ dependencies = [ "windows 0.52.0", ] -[[package]] -name = "gpu-descriptor" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" -dependencies = [ - "bitflags 2.5.0", - "gpu-descriptor-types 0.1.2", - "hashbrown", -] - [[package]] name = "gpu-descriptor" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" dependencies = [ - "bitflags 2.5.0", - "gpu-descriptor-types 0.2.0", + "bitflags 2.6.0", + "gpu-descriptor-types", "hashbrown", ] -[[package]] -name = "gpu-descriptor-types" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" -dependencies = [ - "bitflags 2.5.0", -] - [[package]] name = "gpu-descriptor-types" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -2699,10 +2659,10 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "com", "libc", - "libloading 0.8.3", + "libloading 0.8.4", "thiserror", "widestring", "winapi", @@ -2744,6 +2704,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -2825,12 +2791,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -2838,9 +2804,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -2856,9 +2822,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2880,9 +2846,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -2900,19 +2866,20 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "rustls", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2922,7 +2889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.28", + "hyper 0.14.30", "native-tls", "tokio", "tokio-native-tls", @@ -2930,16 +2897,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.3.1", + "hyper 1.4.1", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -3020,13 +2987,12 @@ dependencies = [ [[package]] name = "image" -version = "0.24.9" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" dependencies = [ "bytemuck", "byteorder", - "color_quant", "num-traits", "png", ] @@ -3068,7 +3034,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -3193,7 +3159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.3", + "libloading 0.8.4", "pkg-config", ] @@ -3205,9 +3171,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -3244,12 +3210,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3264,7 +3230,7 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] @@ -3275,7 +3241,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -3285,7 +3251,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65f3a4b81b2a2d8c7f300643676202debd1b7c929dbf5c9bb89402ea11d19810" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cc", "convert_case", "cookie-factory", @@ -3355,9 +3321,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loom" @@ -3434,9 +3400,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -3465,28 +3431,13 @@ dependencies = [ "autocfg", ] -[[package]] -name = "metal" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" -dependencies = [ - "bitflags 2.5.0", - "block", - "core-graphics-types", - "foreign-types 0.5.0", - "log", - "objc", - "paste", -] - [[package]] name = "metal" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block", "core-graphics-types", "foreign-types 0.5.0", @@ -3509,9 +3460,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", @@ -3528,26 +3479,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "naga" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843" -dependencies = [ - "bit-set", - "bitflags 2.5.0", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "num-traits", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - [[package]] name = "naga" version = "0.20.0" @@ -3556,7 +3487,7 @@ checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.5.0", + "bitflags 2.6.0", "codespan-reporting", "hexf-parse", "indexmap", @@ -3571,9 +3502,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.29.0" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d506eb7e08d6329505faa8a3a00a5dcc6de9f76e0c77e4b75763ae3c770831ff" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" dependencies = [ "approx", "matrixmultiply", @@ -3589,13 +3520,13 @@ dependencies = [ [[package]] name = "nalgebra-macros" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.70", ] [[package]] @@ -3630,7 +3561,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "jni-sys", "log", "ndk-sys 0.5.0+25.2.9519653", @@ -3646,7 +3577,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "jni-sys", "log", "ndk-sys 0.6.0+11769913", @@ -3722,20 +3653,20 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "libc", ] [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", "memoffset 0.9.1", ] @@ -3798,7 +3729,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -3836,7 +3767,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -3858,7 +3789,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -3867,8 +3798,8 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9bff0aa1d48904a1385ea2a8b97576fbdcbc9a3cfccd0d31fe978e1c4038c5" dependencies = [ - "bitflags 2.5.0", - "libloading 0.8.3", + "bitflags 2.6.0", + "libloading 0.8.4", "nvml-wrapper-sys", "static_assertions", "thiserror", @@ -3881,7 +3812,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "698d45156f28781a4e79652b6ebe2eaa0589057d588d3aec1333f6466f13fcb5" dependencies = [ - "libloading 0.8.3", + "libloading 0.8.4", ] [[package]] @@ -3891,7 +3822,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", ] [[package]] @@ -3954,7 +3884,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -3970,7 +3900,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation", @@ -4015,7 +3945,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -4027,7 +3957,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation", @@ -4039,22 +3969,13 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation", "objc2-metal", ] -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - [[package]] name = "objc_id" version = "0.1.1" @@ -4066,9 +3987,9 @@ dependencies = [ [[package]] name = "object" -version = "0.35.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -4113,9 +4034,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "open" -version = "5.1.3" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb49fbd5616580e9974662cb96a3463da4476e649a7e4b258df0de065db0657" +checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" dependencies = [ "is-wsl", "libc", @@ -4128,7 +4049,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types 0.3.2", "libc", @@ -4145,7 +4066,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -4172,7 +4093,7 @@ version = "0.17.1" source = "git+https://github.com/alvr-org/openxrs?rev=f1f47ff#f1f47ff8509801bf28d44538cd4a379dc1b686cf" dependencies = [ "libc", - "libloading 0.8.3", + "libloading 0.8.4", "ndk-context", "openxr-sys", ] @@ -4218,9 +4139,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.21.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b41438d2fc63c46c74a2203bf5ccd82c41ba04347b2fcf5754f230b167067d5" +checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90" dependencies = [ "ttf-parser", ] @@ -4249,9 +4170,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.1", + "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4305,7 +4226,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -4338,7 +4259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08e645ba5c45109106d56610b3ee60eb13a6f2beb8b74f8dc8186cf261788dda" dependencies = [ "anyhow", - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "libspa", "libspa-sys", @@ -4396,13 +4317,13 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.1" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.4.0", "pin-project-lite", "rustix 0.38.34", "tracing", @@ -4440,7 +4361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -4464,9 +4385,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4488,18 +4409,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[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", ] +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2 0.5.7", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -4593,11 +4561,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4613,14 +4581,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -4634,13 +4602,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -4651,9 +4619,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "renderdoc-sys" @@ -4675,7 +4643,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.30", "hyper-tls", "ipnet", "js-sys", @@ -4689,7 +4657,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-native-tls", @@ -4703,9 +4671,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", @@ -4715,7 +4683,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-rustls", "hyper-util", "ipnet", @@ -4725,13 +4693,14 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "quinn", "rustls", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", "tokio-rustls", "tokio-util", @@ -4785,9 +4754,9 @@ dependencies = [ [[package]] name = "rodio" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1fceb9d127d515af1586d8d0cc601e1245bdb0af38e75c865a156290184f5b3" +checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" dependencies = [ "claxon", "cpal", @@ -4851,7 +4820,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno 0.3.9", "libc", "linux-raw-sys 0.4.14", @@ -4860,11 +4829,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ "log", + "once_cell", "ring", "rustls-pki-types", "rustls-webpki", @@ -4899,9 +4869,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring", "rustls-pki-types", @@ -4922,9 +4892,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe_arch" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" dependencies = [ "bytemuck", ] @@ -4961,9 +4931,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7" dependencies = [ "ab_glyph", "log", @@ -4978,7 +4948,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -5006,29 +4976,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -5043,7 +5013,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -5085,7 +5055,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -5125,9 +5095,9 @@ dependencies = [ [[package]] name = "simba" -version = "0.6.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b7840f121a46d63066ee7a99fc81dcabbc6105e437cae43528cea199b5a05f" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" dependencies = [ "approx", "num-complex", @@ -5172,7 +5142,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "calloop", "calloop-wayland-source", "cursor-icon", @@ -5246,7 +5216,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -5257,12 +5227,11 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "statrs" -version = "0.16.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d08e5e1748192713cc281da8b16924fb46be7b0c2431854eadc785823e5696e" +checksum = "f697a07e4606a0a25c044de247e583a330dbb1731d11bc7350b81f48ad567255" dependencies = [ "approx", - "lazy_static", "nalgebra", "num-traits", "rand", @@ -5282,9 +5251,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symphonia" @@ -5348,9 +5317,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ "proc-macro2", "quote", @@ -5363,11 +5332,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "sysinfo" -version = "0.30.12" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" dependencies = [ "cfg-if", "core-foundation-sys", @@ -5413,9 +5388,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -5424,9 +5399,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" [[package]] name = "tempfile" @@ -5466,7 +5441,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -5525,9 +5500,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -5564,7 +5539,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -5579,9 +5554,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls", "rustls-pki-types", @@ -5631,7 +5606,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.14", + "toml_edit 0.22.15", ] [[package]] @@ -5667,9 +5642,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap", "serde", @@ -5724,7 +5699,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -5794,9 +5769,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttf-parser" -version = "0.21.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" +checksum = "8686b91785aff82828ed725225925b33b4fde44c4bb15876e5f7c832724c420a" [[package]] name = "tungstenite" @@ -5909,9 +5884,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -5927,9 +5902,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.7" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" +checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" dependencies = [ "base64 0.22.1", "flate2", @@ -5937,7 +5912,6 @@ dependencies = [ "once_cell", "rustls", "rustls-pki-types", - "rustls-webpki", "serde", "serde_json", "url", @@ -5946,9 +5920,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -5970,9 +5944,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" @@ -6056,7 +6030,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", "wasm-bindgen-shared", ] @@ -6090,7 +6064,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6127,9 +6101,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34e9e6b6d4a2bb4e7e69433e0b35c7923b95d4dc8503a84d25ec917a4bbfdf07" +checksum = "269c04f203640d0da2092d1b8d89a2d081714ae3ac2f1b53e99f205740517198" dependencies = [ "cc", "downcast-rs", @@ -6141,11 +6115,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.3" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e63801c85358a431f986cffa74ba9599ff571fc5774ac113ed3b490c19a1133" +checksum = "08bd0f46c069d3382a36c8666c1b9ccef32b8b04f41667ca1fef06a1adcc2982" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "rustix 0.38.34", "wayland-backend", "wayland-scanner", @@ -6157,16 +6131,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.3" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a206e8b2b53b1d3fcb9428fec72bc278ce539e2fa81fe2bfc1ab27703d5187b9" +checksum = "09414bcf0fd8d9577d73e9ac4659ebc45bcc9cff1980a350543ad8e50ee263b2" dependencies = [ "rustix 0.38.34", "wayland-client", @@ -6179,7 +6153,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -6191,7 +6165,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6204,7 +6178,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6213,9 +6187,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67da50b9f80159dec0ea4c11c13e24ef9e7574bd6ce24b01860a175010cea565" +checksum = "edf466fc49a4feb65a511ca403fec3601494d0dee85dbf37fff6fa0dd4eec3b6" dependencies = [ "proc-macro2", "quick-xml", @@ -6224,9 +6198,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "105b1842da6554f91526c14a2a2172897b7f745a805d62af4ce698706be79c12" +checksum = "4a6754825230fa5b27bafaa28c30b3c9e72c55530581220cef401fa422c0fae7" dependencies = [ "dlib", "log", @@ -6256,67 +6230,44 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.15" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" +checksum = "425ba64c1e13b1c6e8c5d2541c8fac10022ca584f33da781db01b5756aef1f4e" dependencies = [ + "block2 0.5.1", "core-foundation", "home", "jni", "log", "ndk-context", - "objc", - "raw-window-handle 0.5.2", + "objc2 0.5.2", + "objc2-foundation", "url", "web-sys", ] [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ "rustls-pki-types", ] [[package]] name = "wgpu" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01" -dependencies = [ - "arrayvec", - "cfg-if", - "cfg_aliases", - "js-sys", - "log", - "parking_lot", - "profiling", - "raw-window-handle 0.6.2", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core 0.19.4", - "wgpu-hal 0.19.4", - "wgpu-types 0.19.2", -] - -[[package]] -name = "wgpu" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ff1bfee408e1028e2e3acbf6d32d98b08a5a059ccbf5f33305534453ba5d3e" +checksum = "90e37c7b9921b75dfd26dd973fdcbce36f13dfa6e2dc82aece584e0ed48c355c" dependencies = [ "arrayvec", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "document-features", "js-sys", "log", - "naga 0.20.0", + "naga", "parking_lot", "profiling", "raw-window-handle 0.6.2", @@ -6325,52 +6276,26 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "wgpu-core 0.20.0", - "wgpu-hal 0.20.0", - "wgpu-types 0.20.0", + "wgpu-core", + "wgpu-hal", + "wgpu-types", ] [[package]] name = "wgpu-core" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a" -dependencies = [ - "arrayvec", - "bit-vec", - "bitflags 2.5.0", - "cfg_aliases", - "codespan-reporting", - "indexmap", - "log", - "naga 0.19.2", - "once_cell", - "parking_lot", - "profiling", - "raw-window-handle 0.6.2", - "rustc-hash", - "smallvec", - "thiserror", - "web-sys", - "wgpu-hal 0.19.4", - "wgpu-types 0.19.2", -] - -[[package]] -name = "wgpu-core" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6a86eaa5e763e59c73cf9e97d55fffd4dfda69fd8bda19589fcf851ddfef1f" +checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" dependencies = [ "arrayvec", "bit-vec", - "bitflags 2.5.0", - "cfg_aliases", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", "codespan-reporting", "document-features", "indexmap", "log", - "naga 0.20.0", + "naga", "once_cell", "parking_lot", "profiling", @@ -6379,79 +6304,38 @@ dependencies = [ "smallvec", "thiserror", "web-sys", - "wgpu-hal 0.20.0", - "wgpu-types 0.20.0", + "wgpu-hal", + "wgpu-types", ] [[package]] name = "wgpu-hal" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1a4924366df7ab41a5d8546d6534f1f33231aa5b3f72b9930e300f254e39c3" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash 0.37.3+1.3.251", - "bitflags 2.5.0", - "cfg_aliases", - "core-graphics-types", - "glow", - "glutin_wgl_sys", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor 0.2.4", - "hassle-rs", - "js-sys", - "khronos-egl", - "libc", - "libloading 0.8.3", - "log", - "metal 0.27.0", - "naga 0.19.2", - "ndk-sys 0.5.0+25.2.9519653", - "objc", - "once_cell", - "parking_lot", - "profiling", - "raw-window-handle 0.6.2", - "renderdoc-sys", - "rustc-hash", - "smallvec", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types 0.19.2", - "winapi", -] - -[[package]] -name = "wgpu-hal" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d71c8ae05170583049b65ee562fd839fdc0b3e9ddb84f4e40c9d5f8ea0d4c8c" +checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" dependencies = [ "android_system_properties", "arrayvec", "ash 0.37.3+1.3.251", "bit-set", - "bitflags 2.5.0", + "bitflags 2.6.0", "block", - "cfg_aliases", + "cfg_aliases 0.1.1", "core-graphics-types", "d3d12", "glow", "glutin_wgl_sys", "gpu-alloc", "gpu-allocator", - "gpu-descriptor 0.3.0", + "gpu-descriptor", "hassle-rs", "js-sys", "khronos-egl", "libc", - "libloading 0.8.3", + "libloading 0.8.4", "log", - "metal 0.28.0", - "naga 0.20.0", + "metal", + "naga", "ndk-sys 0.5.0+25.2.9519653", "objc", "once_cell", @@ -6465,28 +6349,17 @@ dependencies = [ "thiserror", "wasm-bindgen", "web-sys", - "wgpu-types 0.20.0", + "wgpu-types", "winapi", ] -[[package]] -name = "wgpu-types" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805" -dependencies = [ - "bitflags 2.5.0", - "js-sys", - "web-sys", -] - [[package]] name = "wgpu-types" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "js-sys", "web-sys", ] @@ -6516,9 +6389,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.21" +version = "0.7.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8dc749a1b03f3c255a3064a4f5c0ee5ed09b7c6bc6d4525d31f779cd74d7fc" +checksum = "2caba658a80831539b30698ae9862a72db6697dfdd7151e46920f5f2755c3ce2" dependencies = [ "bytemuck", "safe_arch", @@ -6579,7 +6452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core 0.52.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6589,17 +6462,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ "windows-core 0.54.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "windows" -version = "0.56.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core 0.56.0", - "windows-targets 0.52.5", + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] @@ -6608,7 +6481,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6617,20 +6490,21 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result", - "windows-targets 0.52.5", + "windows-result 0.1.2", + "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.56.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement 0.56.0", - "windows-interface 0.56.0", - "windows-result", - "windows-targets 0.52.5", + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", ] [[package]] @@ -6646,13 +6520,13 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.56.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -6668,22 +6542,41 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.56.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] name = "windows-result" -version = "0.1.1" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets 0.52.5", + "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 0.2.0", + "windows-targets 0.52.6", ] [[package]] @@ -6710,7 +6603,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6745,18 +6638,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "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.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "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]] @@ -6773,9 +6666,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -6791,9 +6684,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -6809,15 +6702,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -6833,9 +6726,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -6851,9 +6744,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -6869,9 +6762,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -6887,9 +6780,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" @@ -6900,10 +6793,10 @@ dependencies = [ "ahash", "android-activity 0.5.2", "atomic-waker", - "bitflags 2.5.0", + "bitflags 2.6.0", "bytemuck", "calloop", - "cfg_aliases", + "cfg_aliases 0.1.1", "core-foundation", "core-graphics", "cursor-icon", @@ -6996,7 +6889,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -7019,7 +6912,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading 0.8.3", + "libloading 0.8.4", "once_cell", "rustix 0.38.34", "x11rb-protocol", @@ -7056,12 +6949,12 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "xdg-home" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" +checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -7076,7 +6969,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "dlib", "log", "once_cell", @@ -7085,9 +6978,9 @@ dependencies = [ [[package]] name = "xkeysym" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" @@ -7162,11 +7055,11 @@ dependencies = [ [[package]] name = "zbus" -version = "4.2.2" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c3977a7aafa97b12b9a35d21cdcff9b0d2289762b14683f45d66b1ba6c48f" +checksum = "851238c133804e0aa888edf4a0229481c753544ca12a60fd1c3230c8a500fe40" dependencies = [ - "async-broadcast 0.7.0", + "async-broadcast 0.7.1", "async-executor", "async-fs 2.1.2", "async-io 2.3.3", @@ -7182,7 +7075,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.28.0", + "nix 0.29.0", "ordered-stream", "rand", "serde", @@ -7193,9 +7086,9 @@ dependencies = [ "uds_windows", "windows-sys 0.52.0", "xdg-home", - "zbus_macros 4.2.2", + "zbus_macros 4.3.1", "zbus_names 3.0.0", - "zvariant 4.1.1", + "zvariant 4.1.2", ] [[package]] @@ -7214,14 +7107,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.2.2" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe9de53245dcf426b7be226a4217dd5e339080e5d46e64a02d6e5dcbf90fca1" +checksum = "8d5a3f12c20bd473be3194af6b49d50d7bb804ef3192dc70eddedb26b85d9da7" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", "zvariant_utils 2.0.0", ] @@ -7244,27 +7137,27 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" dependencies = [ "serde", "static_assertions", - "zvariant 4.1.1", + "zvariant 4.1.2", ] [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -7284,7 +7177,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] [[package]] @@ -7332,27 +7225,27 @@ dependencies = [ [[package]] name = "zstd" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.1.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.12+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" dependencies = [ "cc", "pkg-config", @@ -7374,16 +7267,16 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa6d31a02fbfb602bfde791de7fedeb9c2c18115b3d00f3a36e489f46ffbbc7" +checksum = "1724a2b330760dc7d2a8402d841119dc869ef120b139d29862d6980e9c75bfc9" dependencies = [ "endi", "enumflags2", "serde", "static_assertions", "url", - "zvariant_derive 4.1.1", + "zvariant_derive 4.1.2", ] [[package]] @@ -7401,14 +7294,14 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642bf1b6b6d527988b3e8193d20969d53700a36eac734d21ae6639db168701c8" +checksum = "55025a7a518ad14518fb243559c058a2e5b848b015e31f1d90414f36e3317859" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", "zvariant_utils 2.0.0", ] @@ -7431,5 +7324,5 @@ checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.70", ] diff --git a/Cargo.toml b/Cargo.toml index a7b2030198..0b082ed184 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,9 @@ resolver = "2" members = ["alvr/*"] [workspace.package] -version = "20.9.1" +version = "20.10.0" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" authors = ["alvr-org"] license = "MIT" @@ -15,11 +15,12 @@ alvr_client_core = { path = "alvr/client_core" } alvr_common = { path = "alvr/common" } alvr_events = { path = "alvr/events" } alvr_filesystem = { path = "alvr/filesystem" } +alvr_gui_common = { path = "alvr/gui_common" } alvr_packets = { path = "alvr/packets" } +alvr_server_core = { path = "alvr/server_core"} alvr_server_io = { path = "alvr/server_io" } alvr_session = { path = "alvr/session" } alvr_sockets = { path = "alvr/sockets" } -alvr_gui_common = { path = "alvr/gui_common" } [profile.release] debug = "limited" diff --git a/alvr/audio/Cargo.toml b/alvr/audio/Cargo.toml index 572b64f4b6..cd184e4008 100644 --- a/alvr/audio/Cargo.toml +++ b/alvr/audio/Cargo.toml @@ -12,12 +12,12 @@ alvr_session.workspace = true alvr_sockets.workspace = true cpal = { version = "0.15", features = ["jack"] } -rodio = "0.18" +rodio = "0.19" serde = "1" [target.'cfg(windows)'.dependencies] widestring = "1" -windows = { version = "0.56", features = [ +windows = { version = "0.58", features = [ "Win32_Devices_FunctionDiscovery", "Win32_Foundation", "Win32_Media_Audio_Endpoints", diff --git a/alvr/client_core/Cargo.toml b/alvr/client_core/Cargo.toml index 17cc66095c..81e5231d3c 100644 --- a/alvr/client_core/Cargo.toml +++ b/alvr/client_core/Cargo.toml @@ -29,13 +29,16 @@ jni = "0.21" khronos-egl = { version = "6", features = ["dynamic"] } local-ip-address = "0.6" mdns-sd = "0.11" +pollster = "0.3" rand = "0.8" serde = "1" serde_json = "1" +wgpu = "0.20" +wgpu-core = { version = "0.21", features = ["gles"] } whoami = "1" [target.'cfg(target_os = "android")'.dependencies] -android_logger = "0.13" +android_logger = "0.14" ndk = { version = "0.9", features = ["api-level-26", "media"] } ndk-context = "0.1" ndk-sys = "0.6" diff --git a/alvr/client_core/resources/lobby_fragment.glsl b/alvr/client_core/resources/lobby_fragment.glsl deleted file mode 100644 index eb5347968e..0000000000 --- a/alvr/client_core/resources/lobby_fragment.glsl +++ /dev/null @@ -1,62 +0,0 @@ -#version 300 es - -uniform lowp int object_type; -uniform sampler2D hud_texture; - -in vec2 uv; -in vec3 position; -out vec4 out_color; - -void main() { - if(object_type == 0) { // Ground - lowp vec3 groundCenter = vec3(0.0f, 0.0f, 0.0f); - lowp vec3 groundHorizon = vec3(0.0f, 0.0f, 0.015f); - - lowp vec3 gridClose = vec3(0.114f, 0.545f, 0.804f); - lowp vec3 gridFar = vec3(0.259f, 0.863f, 0.886f); - - lowp float lineFadeStart = 10.0f; - lowp float lineFadeEnd = 50.0f; - lowp float lineFadeDist = lineFadeEnd - lineFadeStart; - - lowp float lineBloom = 10.0f; - - lowp float distance = length(position.xz); - - // Pick a coordinate to visualize in a grid - lowp float cellSize = 2.0f; - lowp vec2 coord = position.xz / cellSize; - - // Compute anti-aliased world-space grid lines - lowp vec2 screenSpaceLineWidth = 1.0f * fwidth(coord); // todo: make resolution agnostic? - lowp vec2 grid = abs(fract(coord - 0.5f) - 0.5f) / screenSpaceLineWidth; - - // Create mask for grid lines and fade over distance - lowp float line = clamp(1.0f - min(grid.x, grid.y), 0.0f, 1.0f); - line *= clamp((lineFadeStart - distance) / lineFadeDist, 0.0f, 1.0f); - - // Fill in normal ground colour - out_color.rgb = groundCenter * (1.0f - line); - - // Add cheap and simple "bloom" to the grid lines - line *= 1.0f + lineBloom; - - // Fill in grid line colour - out_color.rgb += line * mix(gridFar, gridClose, clamp((lineFadeEnd - distance) / lineFadeEnd, 0.0f, 1.0f)); - - // Fade to the horizon colour over distance - if(distance > 10.0f) { - lowp float coef = 1.0f - 10.0f / distance; - out_color.rgb = (1.0f - coef) * out_color.rgb + coef * groundHorizon; - } - - out_color.a = 1.0f; - } else if(object_type == 1) { // HUD - lowp vec3 textColor = vec3(1.0f, 1.0f, 1.0f); - - out_color.rgb = textColor; - out_color.a = texture(hud_texture, uv).a; - } else if(object_type == 2) { // Hands - out_color = vec4(1.0f, 1.0f, 1.0f, 1.0f); - } -} diff --git a/alvr/client_core/resources/lobby_line.wgsl b/alvr/client_core/resources/lobby_line.wgsl new file mode 100644 index 0000000000..1d42a6a8c1 --- /dev/null +++ b/alvr/client_core/resources/lobby_line.wgsl @@ -0,0 +1,12 @@ + +var transform: mat4x4f; + +@vertex +fn vertex_main(@builtin(vertex_index) vertex_index: u32) -> @builtin(position) vec4f { + return transform * vec4f(0.0, 0.0, -f32(vertex_index), 1.0); +} + +@fragment +fn fragment_main() -> @location(0) vec4f { + return vec4f(1.0); +} \ No newline at end of file diff --git a/alvr/client_core/resources/lobby_quad.wgsl b/alvr/client_core/resources/lobby_quad.wgsl new file mode 100644 index 0000000000..839d1861cf --- /dev/null +++ b/alvr/client_core/resources/lobby_quad.wgsl @@ -0,0 +1,81 @@ +struct VertexOutput { + @builtin(position) position: vec4f, + @location(0) uv: vec2f, +} + +@group(0) @binding(0) var hud_texture: texture_2d; +@group(0) @binding(1) var hud_sampler: sampler; + +struct PushConstant { + transform: mat4x4f, + object_type: u32, + floor_side: f32, +} +var pc: PushConstant; + +@vertex +fn vertex_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput { + var result: VertexOutput; + + let norm_vert_a = f32(vertex_index & 1); + let norm_vert_b = f32(vertex_index >> 1); + + result.uv = vec2f(norm_vert_a, norm_vert_b); + result.position = pc.transform * vec4f(result.uv.x - 0.5, 0.5 - result.uv.y, 0.0, 1.0); + + return result; +} + +@fragment +fn fragment_main(@location(0) uv: vec2f) -> @location(0) vec4f { + if pc.object_type == 0 { // Ground + let world_xz = (uv - 0.5) * pc.floor_side; + + let ground_center = vec3f(0.0, 0.0, 0.0); + let ground_horizon = vec3f(0.0, 0.0, 0.015); + + let grid_close = vec3f(0.114, 0.545, 0.804); + let grid_far = vec3f(0.259, 0.863, 0.886); + + let line_fade_start = 10.0; + let line_fade_end = 50.0; + let line_fade_dist = line_fade_end - line_fade_start; + + let line_bloom = 10.0; + + let distance = length(world_xz); + + // Pick a coordinate to visualize in a grid + let cell_size = 2.0; + let coord = world_xz / cell_size; + + // Compute anti-aliased world-space grid lines + let screen_space_line_width = 1.0 * fwidth(coord); // todo: make resolution agnostic? + let grid = abs(fract(coord - 0.5) - 0.5) / screen_space_line_width; + + // Create mask for grid lines and fade over distance + var line = clamp(1.0 - min(grid.x, grid.y), 0.0, 1.0); + line *= clamp((line_fade_start - distance) / line_fade_dist, 0.0, 1.0); + + // Fill in normal ground colour + var out_color = ground_center * (1.0 - line); + + // Add cheap and simple "bloom" to the grid lines + line *= 1.0 + line_bloom; + + // Fill in grid line colour + out_color += line * mix(grid_far, grid_close, clamp((line_fade_end - distance) / line_fade_end, 0.0, 1.0)); + + // Fade to the horizon colour over distance + if distance > 10.0 { + let coef = 1.0 - 10.0 / distance; + out_color = (1.0 - coef) * out_color + coef * ground_horizon; + } + + return vec4f(out_color, 1.0); + } else { // HUD + let mask = textureSample(hud_texture, hud_sampler, uv).a; + + return vec4(1.0, 1.0, 1.0, mask); + } +} diff --git a/alvr/client_core/resources/lobby_vertex.glsl b/alvr/client_core/resources/lobby_vertex.glsl deleted file mode 100644 index f6ab32783b..0000000000 --- a/alvr/client_core/resources/lobby_vertex.glsl +++ /dev/null @@ -1,28 +0,0 @@ -#version 300 es - -const float PI = 3.14159265359f; -const float FAR = 150.0f; -const float SKY_SIDE = 500.0f; -const float HAND_BASE_HALF_SIDE = 0.1f; -const float HAND_SQUEEZE_MULTIPLIER = 1.2f; - -uniform lowp int object_type; -uniform mat4 transform; // each object type uses this differently -uniform float squeeze_amount; - -out vec3 position; -out vec2 uv; - -void main() { - float norm_vert_a = float(gl_VertexID & 1); - float norm_vert_b = float(gl_VertexID >> 1); - if(object_type == 0) { // Ground - position = vec3((norm_vert_a * 2.0f - 1.0f) * FAR, 0.0f, (norm_vert_b * 2.0f - 1.0f) * FAR); - gl_Position = transform * vec4(position, 1.0f); - } else if(object_type == 1) { // HUD - gl_Position = transform * vec4(norm_vert_a - 0.5f, norm_vert_b - 0.5f, 0.0f, 1.0f); - uv = vec2(norm_vert_a, 1.0f - norm_vert_b); - } else if(object_type == 2) { // Hands (single bone) - gl_Position = transform * vec4(0.0f, 0.0f, -float(gl_VertexID), 1.0f); - } -} diff --git a/alvr/client_core/resources/stream.wgsl b/alvr/client_core/resources/stream.wgsl new file mode 100644 index 0000000000..c7ee43ee42 --- /dev/null +++ b/alvr/client_core/resources/stream.wgsl @@ -0,0 +1,60 @@ +// todo: use expression directly when supported in naga +const DIV12: f32 = 0.0773993808;// 1.0 / 12.92 +const DIV1: f32 = 0.94786729857; // 1.0 / 1.055 +const THRESHOLD: f32 = 0.04045; +const GAMMA: vec3f = vec3f(2.4); + +// Convert from limited colors to full +const LIMITED_MIN: f32 = 0.06274509803; // 16.0 / 255.0 +const LIMITED_MAX: f32 = 0.92156862745; // 235.0 / 255.0 + +override FIX_LIMITED_RANGE: bool; +override ENABLE_SRGB_CORRECTION: bool; +override ENCODING_GAMMA: f32; + +var view_idx: u32; + +struct VertexOutput { + @builtin(position) position: vec4f, + @location(0) uv: vec2f, +} + +@group(0) @binding(0) var stream_texture: texture_2d; +@group(0) @binding(1) var stream_sampler: sampler; + +@vertex +fn vertex_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput { + var result: VertexOutput; + + let screen_uv = vec2f(f32(vertex_index & 1), f32(vertex_index >> 1)); + result.position = vec4f((screen_uv - vec2f(0.5, 0.5)) * 2.0, 0.0, 1.0); + result.uv = vec2f((screen_uv.x + f32(view_idx)) / 2.0, screen_uv.y); + + return result; +} + +@fragment +fn fragment_main(@location(0) uv: vec2f) -> @location(0) vec4f { + var result: vec3f = textureSample(stream_texture, stream_sampler, uv).rgb; + + if FIX_LIMITED_RANGE { + // For some reason, the encoder shifts full-range color into the negatives and over one. + result = LIMITED_MIN + ((LIMITED_MAX - LIMITED_MIN) * result); + } + + if ENABLE_SRGB_CORRECTION { + let condition = vec3f(f32(result.r < THRESHOLD), f32(result.g < THRESHOLD), f32(result.b < THRESHOLD)); + let lowValues = result * DIV12; + let highValues = pow((result + vec3f(0.055)) * DIV1, GAMMA); + result = condition * lowValues + (1.0 - condition) * highValues; + } + + if ENCODING_GAMMA != 0.0 { + let enc_condition = vec3f(f32(result.r < 0.0), f32(result.g < 0.0), f32(result.b < 0.0)); + let enc_lowValues = result; + let enc_highValues = pow(result, vec3f(ENCODING_GAMMA)); + result = enc_condition * enc_lowValues + (1.0 - enc_condition) * enc_highValues; + } + + return vec4f(result, 1.0); +} \ No newline at end of file diff --git a/alvr/client_core/resources/stream_fragment.glsl b/alvr/client_core/resources/stream_fragment.glsl deleted file mode 100644 index 119a8dd882..0000000000 --- a/alvr/client_core/resources/stream_fragment.glsl +++ /dev/null @@ -1,41 +0,0 @@ -#version 300 es - -const float DIV12 = 1.f / 12.92f; -const float DIV1 = 1.f / 1.055f; -const float THRESHOLD = 0.04045f; -const vec3 GAMMA = vec3(2.4f); - -// Convert from limited colors to full -const float LIMITED_MIN = 16.0f / 255.0f; -const float LIMITED_MAX = 235.0f / 255.0f; - -uniform sampler2D tex; -uniform int fix_limited_range; -uniform int enable_srgb_correction; -uniform float encoding_gamma; - -in vec2 uv; -out vec4 out_color; - -void main() { - out_color = texture(tex, uv); - - if(fix_limited_range == 1) { - // For some reason, the encoder shifts full-range color into the negatives and over one. - out_color.rgb = LIMITED_MIN + ((LIMITED_MAX - LIMITED_MIN) * out_color.rgb); - } - - if(enable_srgb_correction == 1) { - vec3 condition = vec3(out_color.r < THRESHOLD, out_color.g < THRESHOLD, out_color.b < THRESHOLD); - vec3 lowValues = out_color.rgb * DIV12; - vec3 highValues = pow((out_color.rgb + 0.055f) * DIV1, GAMMA); - out_color.rgb = condition * lowValues + (1.0f - condition) * highValues; - } - - if(encoding_gamma != 0.0f) { - vec3 enc_condition = vec3(out_color.r < 0.0f, out_color.g < 0.0f, out_color.b < 0.0f); - vec3 enc_lowValues = out_color.rgb; - vec3 enc_highValues = pow(out_color.rgb, vec3(encoding_gamma)); - out_color.rgb = enc_condition * enc_lowValues + (1.0f - enc_condition) * enc_highValues; - } -} diff --git a/alvr/client_core/resources/stream_vertex.glsl b/alvr/client_core/resources/stream_vertex.glsl deleted file mode 100644 index 03be904cc2..0000000000 --- a/alvr/client_core/resources/stream_vertex.glsl +++ /dev/null @@ -1,11 +0,0 @@ -#version 300 es - -uniform lowp int view_idx; - -out vec2 uv; - -void main() { - vec2 screen_uv = vec2(gl_VertexID & 1, gl_VertexID >> 1); - gl_Position = vec4((screen_uv - 0.5f) * 2.f, 0, 1); - uv = vec2((screen_uv.x + float(view_idx)) / 2.0f, 1.0 - screen_uv.y); -} diff --git a/alvr/client_core/src/c_api.rs b/alvr/client_core/src/c_api.rs index 651767c6a2..cd5bbe0f6d 100644 --- a/alvr/client_core/src/c_api.rs +++ b/alvr/client_core/src/c_api.rs @@ -698,7 +698,7 @@ pub struct AlvrStreamConfig { #[no_mangle] pub extern "C" fn alvr_initialize_opengl() { - GRAPHICS_CONTEXT.set(Some(Rc::new(GraphicsContext::new()))); + GRAPHICS_CONTEXT.set(Some(Rc::new(GraphicsContext::new_gl()))); } #[no_mangle] @@ -776,6 +776,7 @@ pub unsafe extern "C" fn alvr_start_stream_opengl(config: AlvrStreamConfig) { GRAPHICS_CONTEXT.with_borrow(|c| c.as_ref().unwrap().clone()), view_resolution, swapchain_textures, + glow::RGBA8, foveated_encoding, true, false, // TODO: limited range fix config diff --git a/alvr/client_core/src/graphics/lobby.rs b/alvr/client_core/src/graphics/lobby.rs index e832d32765..afd1a4c036 100644 --- a/alvr/client_core/src/graphics/lobby.rs +++ b/alvr/client_core/src/graphics/lobby.rs @@ -1,15 +1,26 @@ -use super::{ck, GraphicsContext, RenderTarget, RenderViewInput}; +use super::{GraphicsContext, SDR_FORMAT}; use alvr_common::{ - glam::{IVec2, Mat4, UVec2, Vec3, Vec4}, + glam::{Mat4, UVec2, Vec3, Vec4}, Fov, Pose, }; -use glow::{self as gl, HasContext, PixelUnpackData}; use glyph_brush_layout::{ ab_glyph::{Font, FontRef, ScaleFont}, FontId, GlyphPositioner, HorizontalAlign, Layout, SectionGeometry, SectionText, VerticalAlign, }; -use std::{f32::consts::FRAC_PI_2, num::NonZeroU32, rc::Rc}; +use std::{f32::consts::FRAC_PI_2, rc::Rc}; +use wgpu::{ + include_wgsl, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, + BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent, + BlendFactor, BlendOperation, BlendState, Color, ColorTargetState, ColorWrites, + CommandEncoderDescriptor, Device, Extent3d, FilterMode, FragmentState, ImageCopyTexture, + ImageDataLayout, LoadOp, Operations, Origin3d, PipelineLayoutDescriptor, PrimitiveState, + PrimitiveTopology, PushConstantRange, RenderPass, RenderPassColorAttachment, + RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, SamplerBindingType, + SamplerDescriptor, ShaderModuleDescriptor, ShaderStages, StoreOp, Texture, TextureAspect, + TextureSampleType, TextureView, TextureViewDimension, VertexState, +}; +const FLOOR_SIDE: f32 = 300.0; const HUD_DIST: f32 = 5.0; const HUD_SIDE: f32 = 3.5; const HUD_TEXTURE_SIDE: usize = 1024; @@ -54,23 +65,87 @@ fn projection_from_fov(fov: Fov) -> Mat4 { let c = (tanr + tanl) / (tanr - tanl); let d = (tanu + tand) / (tanu - tand); + // note: for wgpu compatibility, the b and d components should be flipped. Maybe a bug in the + // viewport handling in wgpu? Mat4::from_cols( Vec4::new(a, 0.0, c, 0.0), - Vec4::new(0.0, b, d, 0.0), - Vec4::new(0.0, 0.0, -1.0, -2.0 * NEAR), + Vec4::new(0.0, -b, -d, 0.0), + Vec4::new(0.0, 0.0, -1.0, -NEAR), Vec4::new(0.0, 0.0, -1.0, 0.0), ) .transpose() } +fn create_pipeline( + device: &Device, + label: &str, + bind_group_layouts: &[&BindGroupLayout], + push_constants_len: u32, + shader: ShaderModuleDescriptor, + topology: PrimitiveTopology, +) -> RenderPipeline { + let shader_module = device.create_shader_module(shader); + device.create_render_pipeline(&RenderPipelineDescriptor { + label: Some(label), + // Note: Layout cannot be inferred because of a bug with push constants + layout: Some(&device.create_pipeline_layout(&PipelineLayoutDescriptor { + label: Some(label), + bind_group_layouts, + push_constant_ranges: &[PushConstantRange { + stages: ShaderStages::VERTEX_FRAGMENT, + range: 0..push_constants_len, + }], + })), + vertex: VertexState { + module: &shader_module, + entry_point: "vertex_main", + compilation_options: Default::default(), + buffers: &[], + }, + primitive: PrimitiveState { + topology, + ..Default::default() + }, + depth_stencil: None, + multisample: Default::default(), + fragment: Some(FragmentState { + module: &shader_module, + entry_point: "fragment_main", + compilation_options: Default::default(), + targets: &[Some(ColorTargetState { + format: SDR_FORMAT, + blend: Some(BlendState { + color: BlendComponent { + src_factor: BlendFactor::SrcAlpha, + dst_factor: BlendFactor::OneMinusSrcAlpha, + operation: BlendOperation::Add, + }, + alpha: BlendComponent { + src_factor: BlendFactor::One, + dst_factor: BlendFactor::OneMinusSrcAlpha, + operation: BlendOperation::Add, + }, + }), + write_mask: ColorWrites::ALL, + })], + }), + multiview: None, + }) +} + +pub struct RenderViewInput { + pub pose: Pose, + pub fov: Fov, + pub swapchain_index: u32, +} + pub struct LobbyRenderer { context: Rc, - program: gl::Program, - object_type_uloc: gl::UniformLocation, - transform_uloc: gl::UniformLocation, - hud_texture: gl::Texture, - render_targets: [Vec; 2], - viewport_size: IVec2, + quad_pipeline: RenderPipeline, + line_pipeline: RenderPipeline, + hud_texture: Texture, + bind_group: BindGroup, + render_targets: [Vec; 2], } impl LobbyRenderer { @@ -80,54 +155,86 @@ impl LobbyRenderer { swapchain_textures: [Vec; 2], initial_hud_message: &str, ) -> Self { - let gl = &context.gl_context; - - let render_targets = [ - swapchain_textures[0] - .iter() - .map(|tex| { - RenderTarget::new( - Rc::clone(&context), - gl::NativeTexture(NonZeroU32::new(*tex).unwrap()), - ) - }) - .collect(), - swapchain_textures[1] - .iter() - .map(|tex| { - RenderTarget::new( - Rc::clone(&context), - gl::NativeTexture(NonZeroU32::new(*tex).unwrap()), - ) - }) - .collect(), - ]; - - let hud_texture = super::create_texture( - gl, - UVec2::new(HUD_TEXTURE_SIDE as u32, HUD_TEXTURE_SIDE as u32), - gl::RGBA8, + let device = &context.device; + + let hud_texture = + super::create_texture(device, UVec2::ONE * HUD_TEXTURE_SIDE as u32, SDR_FORMAT); + + let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor { + label: None, + entries: &[ + BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Texture { + sample_type: TextureSampleType::Float { filterable: true }, + view_dimension: TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + BindGroupLayoutEntry { + binding: 1, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Sampler(SamplerBindingType::Filtering), + count: None, + }, + ], + }); + + let quad_pipeline = create_pipeline( + device, + "lobby_quad", + &[&bind_group_layout], + 72, + include_wgsl!("../../resources/lobby_quad.wgsl"), + PrimitiveTopology::TriangleStrip, ); - let program = super::create_program( - gl, - include_str!("../../resources/lobby_vertex.glsl"), - include_str!("../../resources/lobby_fragment.glsl"), + let line_pipeline = create_pipeline( + device, + "lobby_line", + &[], + 64, + include_wgsl!("../../resources/lobby_line.wgsl"), + PrimitiveTopology::LineList, ); - let this = unsafe { - let object_type_uloc = ck!(gl.get_uniform_location(program, "object_type").unwrap()); - let transform_uloc = ck!(gl.get_uniform_location(program, "transform").unwrap()); - - Self { - context, - program, - object_type_uloc, - transform_uloc, - hud_texture, - render_targets, - viewport_size: view_resolution.as_ivec2(), - } + let bind_group = device.create_bind_group(&BindGroupDescriptor { + label: None, + layout: &bind_group_layout, + entries: &[ + BindGroupEntry { + binding: 0, + resource: BindingResource::TextureView( + &hud_texture.create_view(&Default::default()), + ), + }, + BindGroupEntry { + binding: 1, + resource: BindingResource::Sampler(&device.create_sampler( + &SamplerDescriptor { + mag_filter: FilterMode::Linear, + min_filter: FilterMode::Linear, + ..Default::default() + }, + )), + }, + ], + }); + + let render_targets = [ + super::create_gl_swapchain(device, &swapchain_textures[0], view_resolution, SDR_FORMAT), + super::create_gl_swapchain(device, &swapchain_textures[1], view_resolution, SDR_FORMAT), + ]; + + let this = Self { + context, + quad_pipeline, + line_pipeline, + hud_texture, + bind_group, + render_targets, }; this.update_hud_message(initial_hud_message); @@ -175,21 +282,25 @@ impl LobbyRenderer { } } - let gl = &self.context.gl_context; - unsafe { - ck!(gl.bind_texture(gl::TEXTURE_2D, Some(self.hud_texture))); - ck!(gl.tex_sub_image_2d( - gl::TEXTURE_2D, - 0, - 0, - 0, - HUD_TEXTURE_SIDE as i32, - HUD_TEXTURE_SIDE as i32, - gl::RGBA, - gl::UNSIGNED_BYTE, - PixelUnpackData::Slice(&buffer), - )); - } + self.context.queue.write_texture( + ImageCopyTexture { + texture: &self.hud_texture, + mip_level: 0, + origin: Origin3d::ZERO, + aspect: TextureAspect::All, + }, + &buffer, + ImageDataLayout { + offset: 0, + bytes_per_row: Some(HUD_TEXTURE_SIDE as u32 * 4), + rows_per_image: Some(HUD_TEXTURE_SIDE as u32), + }, + Extent3d { + width: HUD_TEXTURE_SIDE as u32, + height: HUD_TEXTURE_SIDE as u32, + depth_or_array_layers: 1, + }, + ); } pub fn render( @@ -197,119 +308,110 @@ impl LobbyRenderer { view_inputs: [RenderViewInput; 2], hand_poses: [(Option, Option<[Pose; 26]>); 2], ) { - let gl = &self.context.gl_context; - - unsafe { - ck!(gl.use_program(Some(self.program))); - - ck!(gl.disable(gl::SCISSOR_TEST)); - ck!(gl.disable(gl::DEPTH_TEST)); - ck!(gl.disable(gl::CULL_FACE)); - ck!(gl.enable(gl::BLEND)); - ck!(gl.blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA)); - - ck!(gl.viewport(0, 0, self.viewport_size.x, self.viewport_size.y)); - - for (view_idx, view_input) in view_inputs.iter().enumerate() { - self.render_targets[view_idx][view_input.swapchain_index as usize].bind(); - - let view = Mat4::from_rotation_translation( - view_input.pose.orientation, - view_input.pose.position, - ) - .inverse(); - let view_proj = projection_from_fov(view_input.fov) * view; - - ck!(gl.clear(gl::COLOR_BUFFER_BIT)); - ck!(gl.clear_color(0.0, 0.0, 0.02, 1.0)); - - // Draw the following geometry in the correct order (depth buffer is disabled) - - // Render ground - ck!(gl.uniform_1_i32(Some(&self.object_type_uloc), 0)); - ck!(gl.uniform_matrix_4_f32_slice( - Some(&self.transform_uloc), - false, - &view_proj.to_cols_array(), - )); - ck!(gl.draw_arrays(gl::TRIANGLE_STRIP, 0, 4)); - - // Render HUD - // todo: draw only one HUD panel and implement lazy follow - ck!(gl.uniform_1_i32(Some(&self.object_type_uloc), 1)); - ck!(gl.active_texture(gl::TEXTURE0)); - ck!(gl.bind_texture(gl::TEXTURE_2D, Some(self.hud_texture))); - for i in 0..4 { - let panel_transform = Mat4::from_rotation_y(FRAC_PI_2 * i as f32) - * Mat4::from_translation(Vec3::new(0.0, HUD_SIDE / 2.0, -HUD_DIST)) - * Mat4::from_scale(Vec3::ONE * HUD_SIDE); - ck!(gl.uniform_matrix_4_f32_slice( - Some(&self.transform_uloc), - false, - &(view_proj * panel_transform).to_cols_array(), - )); - ck!(gl.draw_arrays(gl::TRIANGLE_STRIP, 0, 4)); - } + let mut encoder = self + .context + .device + .create_command_encoder(&CommandEncoderDescriptor { + label: Some("lobby_command_encoder"), + }); + + for (view_idx, view_input) in view_inputs.iter().enumerate() { + let view = Mat4::from_rotation_translation( + view_input.pose.orientation, + view_input.pose.position, + ) + .inverse(); + let view_proj = projection_from_fov(view_input.fov) * view; + + let mut pass = encoder.begin_render_pass(&RenderPassDescriptor { + label: Some(&format!("lobby_view_{}", view_idx)), + color_attachments: &[Some(RenderPassColorAttachment { + view: &self.render_targets[view_idx][view_input.swapchain_index as usize], + resolve_target: None, + ops: Operations { + load: LoadOp::Clear(Color { + r: 0.0, + g: 0.0, + b: 0.02, + a: 1.0, + }), + store: StoreOp::Store, + }, + })], + ..Default::default() + }); + + fn transform_draw(pass: &mut RenderPass, transform: Mat4, vertices_count: u32) { + let data = transform + .to_cols_array() + .iter() + .flat_map(|v| v.to_le_bytes()) + .collect::>(); + pass.set_push_constants(ShaderStages::VERTEX_FRAGMENT, 0, &data); + pass.draw(0..vertices_count, 0..1); + } - // Render hands - gl.uniform_1_i32(Some(&self.object_type_uloc), 2); - for (maybe_pose, maybe_skeleton) in &hand_poses { - if let Some(skeleton) = maybe_skeleton { - for (joint1_idx, joint2_idx) in HAND_SKELETON_BONES { - let j1_pose = skeleton[joint1_idx]; - let j2_pose = skeleton[joint2_idx]; - - let bone_transform = Mat4::from_scale_rotation_translation( - Vec3::ONE * Vec3::distance(j1_pose.position, j2_pose.position), - j1_pose.orientation, - j1_pose.position, - ); - ck!(gl.uniform_matrix_4_f32_slice( - Some(&self.transform_uloc), - false, - &(view_proj * bone_transform).to_cols_array(), - )); - ck!(gl.draw_arrays(gl::LINES, 0, 2)); - } - } else if let Some(pose) = maybe_pose { - let hand_transform = Mat4::from_scale_rotation_translation( - Vec3::ONE * 0.2, - pose.orientation, - pose.position, - ); + // Draw the following geometry in the correct order (depth buffer is disabled) + + // Bind quad pipeline + pass.set_pipeline(&self.quad_pipeline); + pass.set_bind_group(0, &self.bind_group, &[]); + + // Render ground + pass.set_push_constants(ShaderStages::VERTEX_FRAGMENT, 64, &0_u32.to_le_bytes()); + pass.set_push_constants(ShaderStages::VERTEX_FRAGMENT, 68, &FLOOR_SIDE.to_le_bytes()); + let transform = view_proj + * Mat4::from_rotation_x(-FRAC_PI_2) + * Mat4::from_scale(Vec3::ONE * FLOOR_SIDE); + transform_draw(&mut pass, transform, 4); + + // Render HUD + pass.set_push_constants(ShaderStages::VERTEX_FRAGMENT, 64, &1_u32.to_le_bytes()); + for i in 0..4 { + let transform = Mat4::from_rotation_y(FRAC_PI_2 * i as f32) + * Mat4::from_translation(Vec3::new(0.0, HUD_SIDE / 2.0, -HUD_DIST)) + * Mat4::from_scale(Vec3::ONE * HUD_SIDE); + transform_draw(&mut pass, view_proj * transform, 4); + } - let segment_rotations = [ - Mat4::IDENTITY, - Mat4::from_rotation_y(FRAC_PI_2), - Mat4::from_rotation_x(FRAC_PI_2), - ]; - for rot in &segment_rotations { - let segment_transform = hand_transform - * *rot - * Mat4::from_scale(Vec3::ONE * 0.5) - * Mat4::from_translation(Vec3::Z * 0.5); - - ck!(gl.uniform_matrix_4_f32_slice( - Some(&self.transform_uloc), - false, - &(view_proj * segment_transform).to_cols_array(), - )); - ck!(gl.draw_arrays(gl::LINES, 0, 2)); - } + // Bind line pipeline and render hands + pass.set_pipeline(&self.line_pipeline); + for (maybe_pose, maybe_skeleton) in &hand_poses { + if let Some(skeleton) = maybe_skeleton { + for (joint1_idx, joint2_idx) in HAND_SKELETON_BONES { + let j1_pose = skeleton[joint1_idx]; + let j2_pose = skeleton[joint2_idx]; + + let transform = Mat4::from_scale_rotation_translation( + Vec3::ONE * Vec3::distance(j1_pose.position, j2_pose.position), + j1_pose.orientation, + j1_pose.position, + ); + transform_draw(&mut pass, view_proj * transform, 2); + } + } else if let Some(pose) = maybe_pose { + let hand_transform = Mat4::from_scale_rotation_translation( + Vec3::ONE * 0.2, + pose.orientation, + pose.position, + ); + + let segment_rotations = [ + Mat4::IDENTITY, + Mat4::from_rotation_y(FRAC_PI_2), + Mat4::from_rotation_x(FRAC_PI_2), + ]; + for rot in &segment_rotations { + let transform = hand_transform + * *rot + * Mat4::from_scale(Vec3::ONE * 0.5) + * Mat4::from_translation(Vec3::Z * 0.5); + transform_draw(&mut pass, view_proj * transform, 2); } } } } - } -} - -impl Drop for LobbyRenderer { - fn drop(&mut self) { - let gl = &self.context.gl_context; - unsafe { - ck!(gl.delete_texture(self.hud_texture)); - ck!(gl.delete_program(self.program)); - } + self.context.queue.submit(Some(encoder.finish())); } } diff --git a/alvr/client_core/src/graphics/mod.rs b/alvr/client_core/src/graphics/mod.rs index 066a4c351c..f31e57e38a 100644 --- a/alvr/client_core/src/graphics/mod.rs +++ b/alvr/client_core/src/graphics/mod.rs @@ -3,22 +3,22 @@ mod opengl; mod staging; mod stream; -use std::{ffi::c_void, mem, ptr, rc::Rc}; - pub use lobby::*; pub use stream::*; -use alvr_common::{glam::UVec2, Fov, Pose}; +use alvr_common::glam::UVec2; use glow::{self as gl, HasContext}; -use khronos_egl::{self as egl, EGL1_4}; - +use khronos_egl as egl; +use std::{ffi::c_void, mem, num::NonZeroU32, ptr}; +use wgpu::{ + hal::{self, api, MemoryFlags, TextureUses}, + Adapter, Device, Extent3d, Instance, InstanceDescriptor, InstanceFlags, Queue, Texture, + TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureView, +}; + +pub const SDR_FORMAT: TextureFormat = TextureFormat::Rgba8Unorm; +pub const SDR_FORMAT_GL: u32 = gl::RGBA8; pub const GL_TEXTURE_EXTERNAL_OES: u32 = 0x8D65; -const EGL_NATIVE_BUFFER_ANDROID: u32 = 0x3140; - -const CREATE_IMAGE_FN_STR: &str = "eglCreateImageKHR"; -const DESTROY_IMAGE_FN_STR: &str = "eglDestroyImageKHR"; -const GET_NATIVE_CLIENT_BUFFER_FN_STR: &str = "eglGetNativeClientBufferANDROID"; -const IMAGE_TARGET_TEXTURE_2D_FN_STR: &str = "glEGLImageTargetTexture2DOES"; type CreateImageFn = unsafe extern "C" fn( egl::EGLDisplay, @@ -51,164 +51,127 @@ macro_rules! ck { } pub(crate) use ck; -pub fn choose_swapchain_format(formats: Option<&[u32]>, enable_hdr: bool) -> u32 { +pub fn choose_swapchain_format(supported_formats: &[u32], enable_hdr: bool) -> u32 { // Priority-sorted list of swapchain formats we'll accept-- - let mut app_supported_swapchain_formats = vec![ - gl::SRGB8_ALPHA8, - gl::SRGB8, - gl::RGBA8, - gl::BGRA, - gl::RGB8, - gl::BGR, - ]; + let mut app_supported_swapchain_formats = vec![gl::SRGB8_ALPHA8, gl::RGBA8]; // float16 is required for HDR output. However, float16 swapchains // have a high perf cost, so only use these if HDR is enabled. if enable_hdr { - app_supported_swapchain_formats.insert(0, gl::RGB16F); app_supported_swapchain_formats.insert(0, gl::RGBA16F); } - if let Some(supported_formats) = formats { - for format in app_supported_swapchain_formats { - if supported_formats.contains(&format) { - return format; - } + for format in app_supported_swapchain_formats { + if supported_formats.contains(&format) { + return format; } } - // If we can't enumerate, default to a required format (SRGBA8) - gl::SRGB8_ALPHA8 + // If we can't enumerate, default to a required format + gl::RGBA8 } -fn create_texture(gl: &gl::Context, resolution: UVec2, internal_format: u32) -> gl::Texture { - unsafe { - let texture = gl.create_texture().unwrap(); - ck!(gl.bind_texture(gl::TEXTURE_2D, Some(texture))); - - ck!(gl.tex_image_2d( - gl::TEXTURE_2D, - 0, - internal_format as i32, - resolution.x as i32, - resolution.y as i32, - 0, - gl::RGBA, - gl::UNSIGNED_BYTE, - Some(&vec![0; 4 * (resolution.x * resolution.y) as usize]), - )); - ck!(gl.tex_parameter_i32(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32)); - ck!(gl.tex_parameter_i32(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32)); - ck!(gl.tex_parameter_i32(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32)); - ck!(gl.tex_parameter_i32(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32)); - - texture +pub fn gl_format_to_wgpu(format: u32) -> TextureFormat { + match format { + gl::SRGB8_ALPHA8 => TextureFormat::Rgba8UnormSrgb, + gl::RGBA8 => TextureFormat::Rgba8Unorm, + gl::RGBA16F => TextureFormat::Rgba16Float, + _ => panic!("Unsupported GL format: {}", format), } } -fn create_program( - gl: &gl::Context, - vertex_shader_source: &str, - fragment_shader_source: &str, -) -> gl::Program { - unsafe { - let vertex_shader = ck!(gl.create_shader(gl::VERTEX_SHADER).unwrap()); - ck!(gl.shader_source(vertex_shader, vertex_shader_source)); - ck!(gl.compile_shader(vertex_shader)); - if !gl.get_shader_compile_status(vertex_shader) { - panic!( - "Failed to compile vertex shader: {}", - gl.get_shader_info_log(vertex_shader) - ); - } - - let fragment_shader = ck!(gl.create_shader(gl::FRAGMENT_SHADER).unwrap()); - ck!(gl.shader_source(fragment_shader, fragment_shader_source)); - ck!(gl.compile_shader(fragment_shader)); - if !gl.get_shader_compile_status(fragment_shader) { - panic!( - "Failed to compile fragment shader: {}", - gl.get_shader_info_log(fragment_shader) - ); - } - - let program = ck!(gl.create_program().unwrap()); - ck!(gl.attach_shader(program, vertex_shader)); - ck!(gl.attach_shader(program, fragment_shader)); - ck!(gl.link_program(program)); - if !gl.get_program_link_status(program) { - panic!( - "Failed to link program: {}", - gl.get_program_info_log(program) - ); - } - - ck!(gl.delete_shader(vertex_shader)); - ck!(gl.delete_shader(fragment_shader)); - - program - } +pub fn create_texture(device: &Device, resolution: UVec2, format: TextureFormat) -> Texture { + device.create_texture(&TextureDescriptor { + label: None, + size: Extent3d { + width: resolution.x, + height: resolution.y, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: TextureDimension::D2, + format, + usage: TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }) } -struct RenderTarget { - graphics_context: Rc, - framebuffer: gl::Framebuffer, -} +fn create_texture_from_gles( + device: &Device, + texture: u32, + resolution: UVec2, + format: TextureFormat, +) -> Texture { + let size = Extent3d { + width: resolution.x, + height: resolution.y, + depth_or_array_layers: 1, + }; -impl RenderTarget { - fn new(context: Rc, texture: gl::Texture) -> Self { - let gl = &context.gl_context; - unsafe { - let framebuffer = ck!(gl.create_framebuffer().unwrap()); - ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(framebuffer))); - ck!(gl.framebuffer_texture_2d( - gl::DRAW_FRAMEBUFFER, - gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, - Some(texture), - 0, - )); - ck!(gl.bind_framebuffer(gl::FRAMEBUFFER, None)); - - Self { - graphics_context: context, - framebuffer, - } - } - } + unsafe { + let hal_texture = device + .as_hal::(|device| { + device.unwrap().texture_from_raw( + NonZeroU32::new(texture).unwrap(), + &hal::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: TextureDimension::D2, + format, + usage: TextureUses::COLOR_TARGET, + memory_flags: MemoryFlags::empty(), + view_formats: vec![], + }, + Some(Box::new(())), + ) + }) + .unwrap(); - fn bind(&self) { - unsafe { - self.graphics_context - .gl_context - .bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(self.framebuffer)); - } + device.create_texture_from_hal::( + hal_texture, + &TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: TextureDimension::D2, + format, + usage: TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }, + ) } } -impl Drop for RenderTarget { - fn drop(&mut self) { - unsafe { - self.graphics_context - .gl_context - .delete_framebuffer(self.framebuffer); - } - } -} - -pub struct RenderViewInput { - pub pose: Pose, - pub fov: Fov, - pub swapchain_index: u32, +// This is used to convert OpenXR swapchains to wgpu +pub fn create_gl_swapchain( + device: &Device, + gl_textures: &[u32], + resolution: UVec2, + format: TextureFormat, +) -> Vec { + gl_textures + .iter() + .map(|gl_tex| { + create_texture_from_gles(device, *gl_tex, resolution, format) + .create_view(&Default::default()) + }) + .collect() } pub struct GraphicsContext { - _instance: egl::DynamicInstance, + _instance: Instance, + adapter: Adapter, + device: Device, + queue: Queue, pub egl_display: egl::Display, pub egl_config: egl::Config, pub egl_context: egl::Context, - _dummy_surface: egl::Surface, pub gl_context: gl::Context, + dummy_surface: egl::Surface, create_image: CreateImageFn, destroy_image: DestroyImageFn, get_native_client_buffer: GetNativeClientBufferFn, @@ -216,94 +179,125 @@ pub struct GraphicsContext { } impl GraphicsContext { - pub fn new() -> Self { - let instance = unsafe { egl::DynamicInstance::::load_required().unwrap() }; - - let display = unsafe { instance.get_display(egl::DEFAULT_DISPLAY).unwrap() }; - - let _ = instance.initialize(display).unwrap(); - - let mut configs = Vec::with_capacity(instance.get_config_count(display).unwrap()); - instance.get_configs(display, &mut configs).unwrap(); - - const CONFIG_ATTRIBS: [i32; 19] = [ - egl::RED_SIZE, - 8, - egl::GREEN_SIZE, - 8, - egl::BLUE_SIZE, - 8, - egl::ALPHA_SIZE, - 8, - egl::DEPTH_SIZE, - 0, - egl::STENCIL_SIZE, - 0, - egl::SAMPLES, - 0, - egl::SURFACE_TYPE, - egl::PBUFFER_BIT, - egl::RENDERABLE_TYPE, - egl::OPENGL_ES3_BIT, - egl::NONE, - ]; - let config = instance - .choose_first_config(display, &CONFIG_ATTRIBS) - .unwrap() - .unwrap(); - - instance.bind_api(egl::OPENGL_ES_API).unwrap(); - - const CONTEXT_ATTRIBS: [i32; 3] = [egl::CONTEXT_CLIENT_VERSION, 3, egl::NONE]; - let egl_context = instance - .create_context(display, config, None, &CONTEXT_ATTRIBS) - .unwrap(); - - const PBUFFER_ATTRIBS: [i32; 5] = [egl::WIDTH, 16, egl::HEIGHT, 16, egl::NONE]; - let dummy_surface = instance - .create_pbuffer_surface(display, config, &PBUFFER_ATTRIBS) - .unwrap(); - - instance - .make_current( - display, - Some(dummy_surface), - Some(dummy_surface), - Some(egl_context), - ) - .unwrap(); + #[cfg(not(windows))] + pub fn new_gl() -> Self { + use wgpu::{Backends, DeviceDescriptor, Features, Limits}; + + const CREATE_IMAGE_FN_STR: &str = "eglCreateImageKHR"; + const DESTROY_IMAGE_FN_STR: &str = "eglDestroyImageKHR"; + const GET_NATIVE_CLIENT_BUFFER_FN_STR: &str = "eglGetNativeClientBufferANDROID"; + const IMAGE_TARGET_TEXTURE_2D_FN_STR: &str = "glEGLImageTargetTexture2DOES"; + + let flags = if cfg!(debug_assertions) { + InstanceFlags::DEBUG | InstanceFlags::VALIDATION + } else { + InstanceFlags::empty() + }; + + let instance = Instance::new(InstanceDescriptor { + backends: Backends::GL, + flags, + dx12_shader_compiler: Default::default(), + gles_minor_version: Default::default(), + }); + + let adapter = instance.enumerate_adapters(Backends::GL).remove(0); + let (device, queue) = pollster::block_on(adapter.request_device( + &DeviceDescriptor { + label: None, + required_features: Features::PUSH_CONSTANTS, + required_limits: Limits { + max_push_constant_size: 72, + ..adapter.limits() + }, + }, + None, + )) + .unwrap(); + + let raw_instance = unsafe { instance.as_hal::() }.unwrap(); + + let egl_display = raw_instance.raw_display(); + let egl_config = raw_instance.egl_config(); + + let ( + egl_context, + gl_context, + dummy_surface, + create_image, + destroy_image, + get_native_client_buffer, + image_target_texture_2d, + ) = unsafe { + adapter.as_hal::(|raw_adapter| { + let adapter_context = raw_adapter.unwrap().adapter_context(); + let egl_instance = adapter_context.egl_instance().unwrap(); + + let egl_context = egl::Context::from_ptr(adapter_context.raw_context()); + + const PBUFFER_ATTRIBS: [i32; 5] = [egl::WIDTH, 16, egl::HEIGHT, 16, egl::NONE]; + let dummy_surface = egl_instance + .create_pbuffer_surface(egl_display, egl_config, &PBUFFER_ATTRIBS) + .unwrap(); + + egl_instance + .make_current( + egl_display, + Some(dummy_surface), + Some(dummy_surface), + Some(egl_context), + ) + .unwrap(); + + let gl_context = gl::Context::from_loader_function(|fn_name| { + egl_instance + .get_proc_address(fn_name) + .map(|f| f as *const c_void) + .unwrap_or(ptr::null()) + }); + + let get_fn_ptr = |fn_name| { + egl_instance + .get_proc_address(fn_name) + .map(|f| f as *const c_void) + .unwrap_or(ptr::null()) + }; + + let create_image: CreateImageFn = mem::transmute(get_fn_ptr(CREATE_IMAGE_FN_STR)); + let destroy_image: DestroyImageFn = + mem::transmute(get_fn_ptr(DESTROY_IMAGE_FN_STR)); + let get_native_client_buffer: GetNativeClientBufferFn = + mem::transmute(get_fn_ptr(GET_NATIVE_CLIENT_BUFFER_FN_STR)); + let image_target_texture_2d: ImageTargetTexture2DFn = + mem::transmute(get_fn_ptr(IMAGE_TARGET_TEXTURE_2D_FN_STR)); + + ( + egl_context, + gl_context, + dummy_surface, + create_image, + destroy_image, + get_native_client_buffer, + image_target_texture_2d, + ) + }) + }; #[cfg(all(target_os = "android", feature = "use-cpp"))] unsafe { opengl::initGraphicsNative(); } - fn get_fn_ptr(instance: &egl::DynamicInstance, fn_name: &str) -> *const c_void { - instance - .get_proc_address(fn_name) - .map(|f| f as *const _) - .unwrap_or(std::ptr::null()) - } - - let gl_context = - unsafe { gl::Context::from_loader_function(|fn_name| get_fn_ptr(&instance, fn_name)) }; - - let create_image: CreateImageFn = - unsafe { mem::transmute(get_fn_ptr(&instance, CREATE_IMAGE_FN_STR)) }; - let destroy_image: DestroyImageFn = - unsafe { mem::transmute(get_fn_ptr(&instance, DESTROY_IMAGE_FN_STR)) }; - let get_native_client_buffer: GetNativeClientBufferFn = - unsafe { mem::transmute(get_fn_ptr(&instance, GET_NATIVE_CLIENT_BUFFER_FN_STR)) }; - let image_target_texture_2d: ImageTargetTexture2DFn = - unsafe { mem::transmute(get_fn_ptr(&instance, IMAGE_TARGET_TEXTURE_2D_FN_STR)) }; - Self { _instance: instance, - egl_display: display, - egl_config: config, + adapter, + device, + queue, + egl_display, + egl_config, egl_context, - _dummy_surface: dummy_surface, gl_context, + dummy_surface, create_image, destroy_image, get_native_client_buffer, @@ -311,6 +305,33 @@ impl GraphicsContext { } } + #[cfg(windows)] + pub fn new_gl() -> Self { + unimplemented!() + } + + pub fn make_current(&self) { + #[cfg(not(windows))] + unsafe { + self.adapter.as_hal::(|raw_adapter| { + let egl_instance = raw_adapter + .unwrap() + .adapter_context() + .egl_instance() + .unwrap(); + + egl_instance + .make_current( + self.egl_display, + Some(self.dummy_surface), + Some(self.dummy_surface), + Some(self.egl_context), + ) + .unwrap(); + }) + }; + } + /// # Safety /// `buffer` must be a valid AHardwareBuffer. /// `texture` must be a valid GL texture. @@ -320,6 +341,8 @@ impl GraphicsContext { texture: gl::Texture, render_cb: impl FnOnce(), ) { + const EGL_NATIVE_BUFFER_ANDROID: u32 = 0x3140; + if !buffer.is_null() { let client_buffer = (self.get_native_client_buffer)(buffer); check_error(&self.gl_context, "get_native_client_buffer"); @@ -348,8 +371,9 @@ impl GraphicsContext { } } +#[cfg(not(windows))] impl Default for GraphicsContext { fn default() -> Self { - Self::new() + Self::new_gl() } } diff --git a/alvr/client_core/src/graphics/staging.rs b/alvr/client_core/src/graphics/staging.rs index b6f5836008..981011eb65 100644 --- a/alvr/client_core/src/graphics/staging.rs +++ b/alvr/client_core/src/graphics/staging.rs @@ -1,14 +1,58 @@ -use super::{ck, GraphicsContext, RenderTarget}; +use super::{ck, GraphicsContext}; use crate::graphics::GL_TEXTURE_EXTERNAL_OES; use alvr_common::glam::{IVec2, UVec2}; use glow::{self as gl, HasContext}; use std::{ffi::c_void, rc::Rc}; +fn create_program( + gl: &gl::Context, + vertex_shader_source: &str, + fragment_shader_source: &str, +) -> gl::Program { + unsafe { + let vertex_shader = ck!(gl.create_shader(gl::VERTEX_SHADER).unwrap()); + ck!(gl.shader_source(vertex_shader, vertex_shader_source)); + ck!(gl.compile_shader(vertex_shader)); + if !gl.get_shader_compile_status(vertex_shader) { + panic!( + "Failed to compile vertex shader: {}", + gl.get_shader_info_log(vertex_shader) + ); + } + + let fragment_shader = ck!(gl.create_shader(gl::FRAGMENT_SHADER).unwrap()); + ck!(gl.shader_source(fragment_shader, fragment_shader_source)); + ck!(gl.compile_shader(fragment_shader)); + if !gl.get_shader_compile_status(fragment_shader) { + panic!( + "Failed to compile fragment shader: {}", + gl.get_shader_info_log(fragment_shader) + ); + } + + let program = ck!(gl.create_program().unwrap()); + ck!(gl.attach_shader(program, vertex_shader)); + ck!(gl.attach_shader(program, fragment_shader)); + ck!(gl.link_program(program)); + if !gl.get_program_link_status(program) { + panic!( + "Failed to link program: {}", + gl.get_program_info_log(program) + ); + } + + ck!(gl.delete_shader(vertex_shader)); + ck!(gl.delete_shader(fragment_shader)); + + program + } +} + pub struct StagingRenderer { context: Rc, program: gl::Program, surface_texture: gl::Texture, - render_target: RenderTarget, + framebuffer: gl::Framebuffer, viewport_size: IVec2, } @@ -19,10 +63,9 @@ impl StagingRenderer { resolution: UVec2, ) -> Self { let gl = &context.gl_context; + context.make_current(); - let render_target = RenderTarget::new(Rc::clone(&context), staging_texture); - - let program = super::create_program( + let program = create_program( gl, include_str!("../../resources/staging_vertex.glsl"), include_str!("../../resources/staging_fragment.glsl"), @@ -32,11 +75,22 @@ impl StagingRenderer { // This is an external surface and storage should not be initialized let surface_texture = ck!(gl.create_texture().unwrap()); + let framebuffer = ck!(gl.create_framebuffer().unwrap()); + ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(framebuffer))); + ck!(gl.framebuffer_texture_2d( + gl::DRAW_FRAMEBUFFER, + gl::COLOR_ATTACHMENT0, + gl::TEXTURE_2D, + Some(staging_texture), + 0, + )); + ck!(gl.bind_framebuffer(gl::FRAMEBUFFER, None)); + Self { context, program, surface_texture, - render_target, + framebuffer, viewport_size: resolution.as_ivec2(), } } @@ -54,7 +108,7 @@ impl StagingRenderer { ck!(gl.viewport(0, 0, self.viewport_size.x, self.viewport_size.y)); - self.render_target.bind(); + ck!(gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, Some(self.framebuffer))); ck!(gl.active_texture(gl::TEXTURE0)); ck!(gl.bind_texture(GL_TEXTURE_EXTERNAL_OES, Some(self.surface_texture))); @@ -70,6 +124,7 @@ impl Drop for StagingRenderer { unsafe { ck!(gl.delete_program(self.program)); ck!(gl.delete_texture(self.surface_texture)); + ck!(gl.delete_framebuffer(self.framebuffer)); } } } diff --git a/alvr/client_core/src/graphics/stream.rs b/alvr/client_core/src/graphics/stream.rs index 48a0dbef9a..62c2c1b981 100644 --- a/alvr/client_core/src/graphics/stream.rs +++ b/alvr/client_core/src/graphics/stream.rs @@ -1,28 +1,37 @@ -use super::{ck, staging::StagingRenderer, GraphicsContext, RenderTarget}; -use alvr_common::glam::{IVec2, UVec2}; +use super::{staging::StagingRenderer, GraphicsContext}; +use alvr_common::glam::UVec2; use alvr_session::FoveatedEncodingConfig; -use glow::{self as gl, HasContext}; -use std::{ffi::c_void, num::NonZeroU32, rc::Rc}; +use std::{ffi::c_void, iter, rc::Rc}; +use wgpu::{ + hal::{api, gles}, + include_wgsl, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, + BindGroupLayoutEntry, BindingResource, BindingType, ColorTargetState, ColorWrites, + FragmentState, LoadOp, PipelineCompilationOptions, PipelineLayoutDescriptor, PrimitiveState, + PrimitiveTopology, PushConstantRange, RenderPassColorAttachment, RenderPassDescriptor, + RenderPipeline, RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, ShaderStages, + StoreOp, TextureSampleType, TextureView, TextureViewDescriptor, TextureViewDimension, + VertexState, +}; -struct GlObjects { +struct RenderObjects { staging_renderer: StagingRenderer, - staging_texture: gl::Texture, - render_targets: [Vec; 2], - program: gl::Program, - view_idx_uloc: gl::UniformLocation, - viewport_size: IVec2, + pipeline: RenderPipeline, + bind_group: BindGroup, + render_targets: [Vec; 2], } pub struct StreamRenderer { context: Rc, - gl_objects: Option, + render_objects: Option, } impl StreamRenderer { + #[allow(clippy::too_many_arguments)] pub fn new( context: Rc, view_resolution: UVec2, swapchain_textures: [Vec; 2], + target_format: u32, foveated_encoding: Option, enable_srgb_correction: bool, fix_limited_range: bool, @@ -31,6 +40,8 @@ impl StreamRenderer { // if ffe is enabled, use old c++ code until it is rewritten #[allow(unused_variables)] if let Some(fe) = &foveated_encoding { + context.make_current(); + #[cfg(all(target_os = "android", feature = "use-cpp"))] unsafe { let config = super::opengl::FfiStreamConfig { @@ -58,116 +69,197 @@ impl StreamRenderer { Self { context, - gl_objects: None, + render_objects: None, } } else { + let device = &context.device; let gl = &context.gl_context; - let staging_texture = super::create_texture(gl, view_resolution, gl::RGBA8); + let target_format = super::gl_format_to_wgpu(target_format); + + let staging_texture = super::create_texture(device, view_resolution, target_format); + + let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor { + label: None, + entries: &[ + BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Texture { + sample_type: TextureSampleType::Float { filterable: true }, + view_dimension: TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + BindGroupLayoutEntry { + binding: 1, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Sampler(SamplerBindingType::Filtering), + count: None, + }, + ], + }); + + let shader_module = + device.create_shader_module(include_wgsl!("../../resources/stream.wgsl")); + let constants = &[ + ( + "ENABLE_SRGB_CORRECTION".into(), + enable_srgb_correction.into(), + ), + ("FIX_LIMITED_RANGE".into(), fix_limited_range.into()), + ("ENCODING_GAMMA".into(), encoding_gamma.into()), + ] + .into_iter() + .collect(); + let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { + label: None, + // Note: Layout cannot be inferred because of a bug with push constants + layout: Some(&device.create_pipeline_layout(&PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[PushConstantRange { + stages: ShaderStages::VERTEX_FRAGMENT, + range: 0..4, + }], + })), + vertex: VertexState { + module: &shader_module, + entry_point: "vertex_main", + compilation_options: PipelineCompilationOptions { + constants, + zero_initialize_workgroup_memory: false, + }, + buffers: &[], + }, + primitive: PrimitiveState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }, + depth_stencil: None, + multisample: Default::default(), + fragment: Some(FragmentState { + module: &shader_module, + entry_point: "fragment_main", + compilation_options: PipelineCompilationOptions { + constants, + zero_initialize_workgroup_memory: false, + }, + targets: &[Some(ColorTargetState { + format: target_format, + blend: None, + write_mask: ColorWrites::ALL, + })], + }), + multiview: None, + }); + + let bind_group = device.create_bind_group(&BindGroupDescriptor { + label: None, + layout: &bind_group_layout, + entries: &[ + BindGroupEntry { + binding: 0, + resource: BindingResource::TextureView( + &staging_texture.create_view(&TextureViewDescriptor::default()), + ), + }, + BindGroupEntry { + binding: 1, + resource: BindingResource::Sampler(&device.create_sampler( + &SamplerDescriptor { + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + ..Default::default() + }, + )), + }, + ], + }); let render_targets = [ - swapchain_textures[0] - .iter() - .map(|tex| { - RenderTarget::new( - Rc::clone(&context), - gl::NativeTexture(NonZeroU32::new(*tex).unwrap()), - ) - }) - .collect(), - swapchain_textures[1] - .iter() - .map(|tex| { - RenderTarget::new( - Rc::clone(&context), - gl::NativeTexture(NonZeroU32::new(*tex).unwrap()), - ) - }) - .collect(), + super::create_gl_swapchain( + device, + &swapchain_textures[0], + view_resolution, + target_format, + ), + super::create_gl_swapchain( + device, + &swapchain_textures[1], + view_resolution, + target_format, + ), ]; - let program = super::create_program( - gl, - include_str!("../../resources/stream_vertex.glsl"), - include_str!("../../resources/stream_fragment.glsl"), - ); + let staging_texture_gl = unsafe { + staging_texture.as_hal::(|tex| { + let gles::TextureInner::Texture { raw, .. } = tex.unwrap().inner else { + panic!("invalid texture type"); + }; + raw + }) + }; let staging_renderer = - StagingRenderer::new(Rc::clone(&context), staging_texture, view_resolution); + StagingRenderer::new(Rc::clone(&context), staging_texture_gl, view_resolution); - unsafe { - let view_idx_uloc = ck!(gl.get_uniform_location(program, "view_idx").unwrap()); - - let enable_srgb_correction_uloc = ck!(gl - .get_uniform_location(program, "enable_srgb_correction") - .unwrap()); - let fix_limited_range_uloc = ck!(gl - .get_uniform_location(program, "fix_limited_range") - .unwrap()); - let encoding_gamma_uloc = - ck!(gl.get_uniform_location(program, "encoding_gamma").unwrap()); - - ck!(gl.use_program(Some(program))); - ck!(gl.uniform_1_i32( - Some(&enable_srgb_correction_uloc), - enable_srgb_correction as i32 - )); - ck!(gl.uniform_1_i32(Some(&fix_limited_range_uloc), fix_limited_range as i32)); - ck!(gl.uniform_1_f32(Some(&encoding_gamma_uloc), encoding_gamma)); - - Self { - context, - gl_objects: Some(GlObjects { - staging_renderer, - staging_texture, - render_targets, - program, - view_idx_uloc, - viewport_size: view_resolution.as_ivec2(), - }), - } + Self { + context, + render_objects: Some(RenderObjects { + staging_renderer, + pipeline, + bind_group, + render_targets, + }), } } } - pub fn staging_texture(&self) -> Option { - self.gl_objects - .as_ref() - .map(|gl_objects| gl_objects.staging_texture) - } - #[allow(unused_variables)] pub unsafe fn render(&self, hardware_buffer: *mut c_void, swapchain_indices: [u32; 2]) { - if let Some(gl_objects) = &self.gl_objects { - let gl = &self.context.gl_context; - + if let Some(render_objects) = &self.render_objects { // if hardware_buffer is available copy stream to staging texture if !hardware_buffer.is_null() { - gl_objects.staging_renderer.render(hardware_buffer); + render_objects.staging_renderer.render(hardware_buffer); } - unsafe { - ck!(gl.use_program(Some(gl_objects.program))); + let mut encoder = self + .context + .device + .create_command_encoder(&Default::default()); - ck!(gl.disable(gl::SCISSOR_TEST)); - ck!(gl.disable(gl::DEPTH_TEST)); - ck!(gl.disable(gl::CULL_FACE)); - ck!(gl.disable(gl::BLEND)); + for (view_idx, swapchain_idx) in swapchain_indices.iter().enumerate() { + let mut render_pass = encoder.begin_render_pass(&RenderPassDescriptor { + label: None, + color_attachments: &[Some(RenderPassColorAttachment { + view: &self.render_objects.as_ref().unwrap().render_targets[view_idx] + [*swapchain_idx as usize], + resolve_target: None, + ops: wgpu::Operations { + load: LoadOp::Clear(wgpu::Color::BLACK), + store: StoreOp::Store, + }, + })], + ..Default::default() + }); - ck!(gl.viewport(0, 0, gl_objects.viewport_size.x, gl_objects.viewport_size.y)); - - for (view_idx, swapchain_idx) in swapchain_indices.iter().enumerate() { - gl_objects.render_targets[view_idx][*swapchain_idx as usize].bind(); - - ck!(gl.clear(gl::COLOR_BUFFER_BIT)); - ck!(gl.clear_color(0.0, 0.0, 0.0, 1.0)); - - ck!(gl.uniform_1_i32(Some(&gl_objects.view_idx_uloc), view_idx as i32)); - ck!(gl.active_texture(gl::TEXTURE0)); - ck!(gl.bind_texture(gl::TEXTURE_2D, Some(gl_objects.staging_texture))); - ck!(gl.draw_arrays(gl::TRIANGLE_STRIP, 0, 4)); - } + render_pass.set_pipeline(&self.render_objects.as_ref().unwrap().pipeline); + render_pass.set_bind_group( + 0, + &self.render_objects.as_ref().unwrap().bind_group, + &[], + ); + render_pass.set_push_constants( + ShaderStages::VERTEX_FRAGMENT, + 0, + &(view_idx as u32).to_le_bytes(), + ); + render_pass.draw(0..4, 0..1); } + + self.context.queue.submit(iter::once(encoder.finish())); } else { #[cfg(all(target_os = "android", feature = "use-cpp"))] super::opengl::renderStreamNative(hardware_buffer, swapchain_indices.as_ptr()); @@ -177,18 +269,9 @@ impl StreamRenderer { impl Drop for StreamRenderer { fn drop(&mut self) { - if let Some(gl_objects) = &self.gl_objects { - unsafe { - let gl = &self.context.gl_context; - - ck!(gl.delete_program(gl_objects.program)); - ck!(gl.delete_texture(gl_objects.staging_texture)); - } - } else { - #[cfg(all(target_os = "android", feature = "use-cpp"))] - unsafe { - super::opengl::destroyStream(); - } + #[cfg(all(target_os = "android", feature = "use-cpp"))] + if self.render_objects.is_none() { + unsafe { super::opengl::destroyStream() }; } } } diff --git a/alvr/client_mock/Cargo.toml b/alvr/client_mock/Cargo.toml index 20d2b7eacf..4322e6ea18 100644 --- a/alvr/client_mock/Cargo.toml +++ b/alvr/client_mock/Cargo.toml @@ -12,6 +12,6 @@ alvr_client_core.workspace = true alvr_packets.workspace = true alvr_session.workspace = true -eframe = "0.27" +eframe = "0.28" env_logger = "0.11" rand = "0.8" diff --git a/alvr/client_mock/src/main.rs b/alvr/client_mock/src/main.rs index c888f0a505..3d0cf62cb6 100644 --- a/alvr/client_mock/src/main.rs +++ b/alvr/client_mock/src/main.rs @@ -353,7 +353,7 @@ fn main() { viewport: ViewportBuilder::default().with_inner_size((400.0, 400.0)), ..Default::default() }, - Box::new(|_| Box::new(Window::new(input_sender, output_receiver))), + Box::new(|_| Ok(Box::new(Window::new(input_sender, output_receiver)))), ) .ok(); diff --git a/alvr/client_openxr/Cargo.toml b/alvr/client_openxr/Cargo.toml index f285ef8db0..9fea269fc8 100644 --- a/alvr/client_openxr/Cargo.toml +++ b/alvr/client_openxr/Cargo.toml @@ -49,7 +49,7 @@ required = true name = "android.hardware.vr.headtracking" required = true [[package.metadata.android.uses_feature]] -opengles_version = [3, 1] +opengles_version = [3, 2] required = true [[package.metadata.android.uses_permission]] @@ -121,7 +121,9 @@ name = "com.oculus.intent.category.VR" value = "vr_only" [[package.metadata.android.application.meta_data]] name = "com.oculus.supportedDevices" -value = "quest|quest2|questpro" +# Note: value is changed for the Meta store, which requires an explicit list of platforms. +# "all" is required to support Quest 1 which doesn't have newer platform names registered. +value = "all" [[package.metadata.android.application.meta_data]] name = "com.oculus.vr.focusaware" value = "true" diff --git a/alvr/client_openxr/src/graphics.rs b/alvr/client_openxr/src/graphics.rs index 745f600653..a5a9e9cc0d 100644 --- a/alvr/client_openxr/src/graphics.rs +++ b/alvr/client_openxr/src/graphics.rs @@ -16,16 +16,25 @@ pub fn session_create_info(ctx: &GraphicsContext) -> xr::opengles::SessionCreate unimplemented!() } +pub fn swapchain_format( + gfx_ctx: &GraphicsContext, + session: &xr::Session, + enable_hdr: bool, +) -> u32 { + gfx_ctx.make_current(); + + let formats = session.enumerate_swapchain_formats().unwrap(); + graphics::choose_swapchain_format(&formats, enable_hdr) +} + pub fn create_swapchain( session: &xr::Session, + gfx_ctx: &GraphicsContext, resolution: UVec2, + format: u32, foveation: Option<&xr::FoveationProfileFB>, - enable_hdr: bool, ) -> xr::Swapchain { - let format = graphics::choose_swapchain_format( - session.enumerate_swapchain_formats().ok().as_deref(), - enable_hdr, - ); + gfx_ctx.make_current(); let swapchain_info = xr::SwapchainCreateInfo { create_flags: xr::SwapchainCreateFlags::EMPTY, diff --git a/alvr/client_openxr/src/lib.rs b/alvr/client_openxr/src/lib.rs index e87f8b22c9..46e77ac26f 100644 --- a/alvr/client_openxr/src/lib.rs +++ b/alvr/client_openxr/src/lib.rs @@ -121,11 +121,7 @@ pub fn entry_point() { let platform = alvr_client_core::platform(); let loader_suffix = match platform { - Platform::Quest1 - | Platform::Quest2 - | Platform::Quest3 - | Platform::QuestPro - | Platform::QuestUnknown => "_quest", + Platform::Quest1 => "_quest1", Platform::PicoNeo3 | Platform::Pico4 => "_pico", Platform::Yvr => "_yvr", Platform::Lynx => "_lynx", @@ -139,6 +135,7 @@ pub fn entry_point() { xr_entry.initialize_android_loader().unwrap(); let available_extensions = xr_entry.enumerate_extensions().unwrap(); + alvr_common::info!("OpenXR available extensions: {available_extensions:#?}"); // todo: switch to vulkan assert!(available_extensions.khr_opengl_es_enable); @@ -167,6 +164,9 @@ pub fn entry_point() { exts.khr_convert_timespec_time = true; exts.khr_opengl_es_enable = true; + let available_layers = xr_entry.enumerate_layers().unwrap(); + alvr_common::info!("OpenXR available layers: {available_layers:#?}"); + let xr_instance = xr_entry .create_instance( &xr::ApplicationInfo { @@ -180,7 +180,7 @@ pub fn entry_point() { ) .unwrap(); - let graphics_context = Rc::new(GraphicsContext::new()); + let graphics_context = Rc::new(GraphicsContext::new_gl()); let mut last_lobby_message = String::new(); let mut stream_config = None::; @@ -385,8 +385,8 @@ pub fn entry_point() { &xr_session, xr::Path::NULL, &xr::HapticVibration::new() - .amplitude(amplitude) - .frequency(frequency) + .amplitude(amplitude.clamp(0.0, 1.0)) + .frequency(frequency.max(0.0)) .duration(xr::Duration::from_nanos(duration.as_nanos() as _)), ) .unwrap(); @@ -449,6 +449,7 @@ pub fn entry_point() { (layer, vsync_time) }; + graphics_context.make_current(); let res = xr_frame_stream.end( to_xr_time(display_time), xr::EnvironmentBlendMode::OPAQUE, diff --git a/alvr/client_openxr/src/lobby.rs b/alvr/client_openxr/src/lobby.rs index 7fbb14712e..49634aadab 100644 --- a/alvr/client_openxr/src/lobby.rs +++ b/alvr/client_openxr/src/lobby.rs @@ -3,7 +3,7 @@ use crate::{ interaction::{self, InteractionContext}, XrContext, }; -use alvr_client_core::graphics::{GraphicsContext, LobbyRenderer, RenderViewInput}; +use alvr_client_core::graphics::{GraphicsContext, LobbyRenderer, RenderViewInput, SDR_FORMAT_GL}; use alvr_common::glam::{UVec2, Vec3}; use openxr as xr; use std::{rc::Rc, sync::Arc}; @@ -39,8 +39,20 @@ impl Lobby { interaction::get_reference_space(&xr_ctx.session, reference_space_type); let swapchains = [ - graphics::create_swapchain(&xr_ctx.session, view_resolution, None, false), - graphics::create_swapchain(&xr_ctx.session, view_resolution, None, false), + graphics::create_swapchain( + &xr_ctx.session, + &gfx_ctx, + view_resolution, + SDR_FORMAT_GL, + None, + ), + graphics::create_swapchain( + &xr_ctx.session, + &gfx_ctx, + view_resolution, + SDR_FORMAT_GL, + None, + ), ]; let renderer = LobbyRenderer::new( diff --git a/alvr/client_openxr/src/stream.rs b/alvr/client_openxr/src/stream.rs index d206ecef13..cb7f9b9e2e 100644 --- a/alvr/client_openxr/src/stream.rs +++ b/alvr/client_openxr/src/stream.rs @@ -155,18 +155,23 @@ impl StreamContext { None }; + let format = + graphics::swapchain_format(&gfx_ctx, &xr_ctx.session, config.encoder_config.enable_hdr); + let swapchains = [ graphics::create_swapchain( &xr_ctx.session, + &gfx_ctx, config.view_resolution, + format, foveation_profile.as_ref(), - config.encoder_config.enable_hdr, ), graphics::create_swapchain( &xr_ctx.session, + &gfx_ctx, config.view_resolution, + format, foveation_profile.as_ref(), - config.encoder_config.enable_hdr, ), ]; @@ -187,6 +192,7 @@ impl StreamContext { .map(|i| *i as _) .collect(), ], + format, config.foveated_encoding_config.clone(), platform != Platform::Lynx && !((platform == Platform::Pico4 || platform == Platform::PicoNeo3) diff --git a/alvr/common/Cargo.toml b/alvr/common/Cargo.toml index f884b4183a..687f26f0fc 100644 --- a/alvr/common/Cargo.toml +++ b/alvr/common/Cargo.toml @@ -12,7 +12,7 @@ enable-messagebox = ["rfd"] [dependencies] anyhow = { version = "1", features = ["backtrace"] } backtrace = "0.3" -glam = { version = "0.27", features = ["serde"] } +glam = { version = "0.28", features = ["serde"] } log = "0.4" once_cell = "1" parking_lot = "0.12" diff --git a/alvr/common/src/inputs.rs b/alvr/common/src/inputs.rs index b4d0868b74..26ed34d6cb 100644 --- a/alvr/common/src/inputs.rs +++ b/alvr/common/src/inputs.rs @@ -44,6 +44,8 @@ devices! { (HEAD, "/user/head"), (HAND_LEFT, "/user/hand/left"), (HAND_RIGHT, "/user/hand/right"), + (HAND_TRACKER_LEFT,"/user/hand_tracker/left"), + (HAND_TRACKER_RIGHT, "/user/hand_tracker/right"), (BODY_CHEST, "/user/body/chest"), (BODY_HIPS, "/user/body/waist"), (BODY_LEFT_ELBOW, "/user/body/left_elbow"), diff --git a/alvr/dashboard/Cargo.toml b/alvr/dashboard/Cargo.toml index cb4905c134..6d599c7c0d 100644 --- a/alvr/dashboard/Cargo.toml +++ b/alvr/dashboard/Cargo.toml @@ -16,14 +16,14 @@ alvr_gui_common.workspace = true bincode = "1" chrono = "0.4" -eframe = "0.27" +eframe = "0.28" env_logger = "0.11" ico = "0.3" rand = "0.8" serde = { version = "1", features = ["derive"] } serde_json = "1" settings-schema = { git = "https://github.com/alvr-org/settings-schema-rs", rev = "676185f" } -statrs = "0.16" +statrs = "0.17" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] alvr_server_io.workspace = true diff --git a/alvr/dashboard/src/dashboard/basic_components/modal.rs b/alvr/dashboard/src/dashboard/basic_components/modal.rs deleted file mode 100644 index 697129b753..0000000000 --- a/alvr/dashboard/src/dashboard/basic_components/modal.rs +++ /dev/null @@ -1,52 +0,0 @@ -use eframe::egui::{Align, Align2, Layout, Ui, Window}; - -pub enum ModalResponse { - Ok, - Cancel, -} - -pub fn modal( - ui: &mut Ui, - title: &str, - content: impl FnOnce(&mut Ui, f32), // arg 2: available width - do_not_show_again: Option<&mut bool>, - visible: &mut bool, -) -> Option { - let mut response = None; - if *visible { - Window::new(title) - .collapsible(false) - .resizable(false) - .default_width(200_f32) - .anchor(Align2::CENTER_CENTER, (0_f32, 0_f32)) - .show(ui.ctx(), |ui| { - ui.vertical_centered_justified(|ui| { - ui.add_space(10_f32); - content(ui, ui.available_width() - 8_f32); // extra offset to avoid window resizing. todo: find origin - ui.add_space(10_f32); - - if let Some(do_not_show_again) = do_not_show_again { - ui.checkbox(do_not_show_again, "Do not ask again"); - } - - ui.columns(2, |cols| { - for (i, col) in cols.iter_mut().enumerate() { - col.with_layout(Layout::top_down_justified(Align::Center), |ui| { - if i == 0 { - if ui.button("Cancel").clicked() { - *visible = false; - response = Some(ModalResponse::Cancel); - } - } else if ui.button("OK").clicked() { - *visible = false; - response = Some(ModalResponse::Ok); - } - }); - } - }); - }); - }); - } - - response -} diff --git a/alvr/dashboard/src/dashboard/components/notifications.rs b/alvr/dashboard/src/dashboard/components/notifications.rs index 1b1a7e0b83..3acb900074 100644 --- a/alvr/dashboard/src/dashboard/components/notifications.rs +++ b/alvr/dashboard/src/dashboard/components/notifications.rs @@ -149,9 +149,7 @@ impl NotificationBar { self.expanded = false; } ui.with_layout(Layout::left_to_right(alignment), |ui| { - ui.add( - Label::new(RichText::new(&self.message).color(fg).size(12.0)).wrap(true), - ); + ui.add(Label::new(RichText::new(&self.message).color(fg).size(12.0)).wrap()); }) }) }); diff --git a/alvr/dashboard/src/dashboard/components/settings.rs b/alvr/dashboard/src/dashboard/components/settings.rs index cb6f4e114b..108d475bbe 100644 --- a/alvr/dashboard/src/dashboard/components/settings.rs +++ b/alvr/dashboard/src/dashboard/components/settings.rs @@ -1,9 +1,9 @@ use super::{ presets::{builtin_schema, PresetControl}, - NestingInfo, SettingControl, INDENTATION_STEP, + NestingInfo, SettingControl, }; -use crate::dashboard::{DisplayString, ServerRequest}; -use alvr_gui_common::theme; +use crate::dashboard::ServerRequest; +use alvr_gui_common::{theme, DisplayString}; use alvr_packets::AudioDevicesList; use alvr_session::{SessionSettings, Settings}; use eframe::egui::{self, Align, Frame, Grid, Layout, RichText, ScrollArea, Ui}; @@ -29,6 +29,7 @@ pub struct SettingsTab { encoder_preset: PresetControl, game_audio_preset: Option, microphone_preset: Option, + hand_tracking_interaction_preset: PresetControl, eye_face_tracking_preset: PresetControl, top_level_entries: Vec, session_settings_json: Option, @@ -71,6 +72,9 @@ impl SettingsTab { encoder_preset: PresetControl::new(builtin_schema::encoder_preset_schema()), game_audio_preset: None, microphone_preset: None, + hand_tracking_interaction_preset: PresetControl::new( + builtin_schema::hand_tracking_interaction_schema(), + ), eye_face_tracking_preset: PresetControl::new(builtin_schema::eye_face_tracking_schema()), top_level_entries, session_settings_json: None, @@ -92,6 +96,8 @@ impl SettingsTab { if let Some(preset) = self.microphone_preset.as_mut() { preset.update_session_settings(&settings_json) } + self.hand_tracking_interaction_preset + .update_session_settings(&settings_json); self.eye_face_tracking_preset .update_session_settings(&settings_json); @@ -160,31 +166,28 @@ impl SettingsTab { .striped(true) .num_columns(2) .show(ui, |ui| { - ui.add_space(INDENTATION_STEP); path_value_pairs.extend(self.resolution_preset.ui(ui)); ui.end_row(); - ui.add_space(INDENTATION_STEP); path_value_pairs.extend(self.framerate_preset.ui(ui)); ui.end_row(); - ui.add_space(INDENTATION_STEP); path_value_pairs.extend(self.encoder_preset.ui(ui)); ui.end_row(); if let Some(preset) = &mut self.game_audio_preset { - ui.add_space(INDENTATION_STEP); path_value_pairs.extend(preset.ui(ui)); ui.end_row(); } if let Some(preset) = &mut self.microphone_preset { - ui.add_space(INDENTATION_STEP); path_value_pairs.extend(preset.ui(ui)); ui.end_row(); } - ui.add_space(INDENTATION_STEP); + path_value_pairs.extend(self.hand_tracking_interaction_preset.ui(ui)); + ui.end_row(); + path_value_pairs.extend(self.eye_face_tracking_preset.ui(ui)); ui.end_row(); }) diff --git a/alvr/dashboard/src/dashboard/components/settings_controls/boolean.rs b/alvr/dashboard/src/dashboard/components/settings_controls/boolean.rs index f7c871b5a2..30fdf7e393 100644 --- a/alvr/dashboard/src/dashboard/components/settings_controls/boolean.rs +++ b/alvr/dashboard/src/dashboard/components/settings_controls/boolean.rs @@ -1,5 +1,4 @@ use super::{reset, NestingInfo}; -use crate::dashboard::basic_components; use alvr_packets::PathValuePair; use eframe::{ egui::{Layout, Ui}, @@ -46,7 +45,7 @@ impl Control { } ui.with_layout(Layout::left_to_right(Align::Center), |ui| { - if basic_components::switch(ui, enabled_mut).clicked() { + if alvr_gui_common::switch(ui, enabled_mut).clicked() { request = get_request(&self.nesting_info, *enabled_mut); } diff --git a/alvr/dashboard/src/dashboard/components/settings_controls/choice.rs b/alvr/dashboard/src/dashboard/components/settings_controls/choice.rs index 3523043e64..4380d0f060 100644 --- a/alvr/dashboard/src/dashboard/components/settings_controls/choice.rs +++ b/alvr/dashboard/src/dashboard/components/settings_controls/choice.rs @@ -1,5 +1,5 @@ use super::{reset, NestingInfo, SettingControl}; -use crate::dashboard::{basic_components, get_id, DisplayString}; +use alvr_gui_common::DisplayString; use alvr_packets::PathValuePair; use alvr_session::settings_schema::{ChoiceControlType, SchemaEntry, SchemaNode}; use eframe::{ @@ -94,7 +94,7 @@ impl Control { variant_indices, variant_controls, gui: gui.unwrap_or(ChoiceControlType::Dropdown), - combobox_id: get_id(), + combobox_id: alvr_gui_common::get_id(), } } @@ -122,7 +122,7 @@ impl Control { let mut request = None; ui.with_layout(Layout::left_to_right(Align::Center), |ui| { if matches!(&self.gui, ChoiceControlType::ButtonGroup) { - if basic_components::button_group_clicked(ui, &self.variant_labels, variant_mut) { + if alvr_gui_common::button_group_clicked(ui, &self.variant_labels, variant_mut) { request = get_request(&self.nesting_info, variant_mut); } } else if let Some(mut index) = self.variant_indices.get(variant_mut).cloned() { diff --git a/alvr/dashboard/src/dashboard/components/settings_controls/presets/builtin_schema.rs b/alvr/dashboard/src/dashboard/components/settings_controls/presets/builtin_schema.rs index b03627327e..7149bac80c 100644 --- a/alvr/dashboard/src/dashboard/components/settings_controls/presets/builtin_schema.rs +++ b/alvr/dashboard/src/dashboard/components/settings_controls/presets/builtin_schema.rs @@ -319,12 +319,74 @@ pub fn microphone_schema(devices: Vec) -> PresetSchemaNode { }) } +pub fn hand_tracking_interaction_schema() -> PresetSchemaNode { + const HELP: &str = r"Disabled: hands cannot emulate buttons. Useful for using Joy-Cons or other non-native controllers. +Separate trackers: create separate SteamVR devices for hand tracking. This is used for VRChat. +ALVR bindings: use ALVR hand tracking button bindings. Check the wiki for help. +"; + + const PREFIX: &str = "session_settings.headset.controllers.content"; + + PresetSchemaNode::HigherOrderChoice(HigherOrderChoiceSchema { + name: "Hand tracking interaction".into(), + strings: [("help".into(), HELP.into())].into_iter().collect(), + flags: ["steamvr-restart".into()].into_iter().collect(), + options: [ + HigherOrderChoiceOption { + display_name: "Disabled".into(), + modifiers: vec![ + bool_modifier("session_settings.headset.controllers.enabled", true), + bool_modifier( + &format!("{PREFIX}.hand_skeleton.content.use_separate_trackers"), + false, + ), + bool_modifier( + &format!("{PREFIX}.hand_tracking_interaction.enabled"), + false, + ), + ], + content: None, + }, + HigherOrderChoiceOption { + display_name: "Separate trackers".into(), + modifiers: vec![ + bool_modifier("session_settings.headset.controllers.enabled", true), + bool_modifier(&format!("{PREFIX}.hand_skeleton.enabled"), true), + bool_modifier( + &format!("{PREFIX}.hand_skeleton.content.use_separate_trackers"), + true, + ), + bool_modifier( + &format!("{PREFIX}.hand_tracking_interaction.enabled"), + false, + ), + ], + content: None, + }, + HigherOrderChoiceOption { + display_name: "ALVR bindings".into(), + modifiers: vec![ + bool_modifier("session_settings.headset.controllers.enabled", true), + bool_modifier( + &format!("{PREFIX}.hand_skeleton.content.use_separate_trackers"), + false, + ), + bool_modifier(&format!("{PREFIX}.hand_tracking_interaction.enabled"), true), + ], + content: None, + }, + ] + .into_iter() + .collect(), + default_option_index: 1, + gui: ChoiceControlType::ButtonGroup, + }) +} + pub fn eye_face_tracking_schema() -> PresetSchemaNode { PresetSchemaNode::HigherOrderChoice(HigherOrderChoiceSchema { - name: "eye_face_tracking".into(), - strings: [("display_name".into(), "Eye and face tracking".into())] - .into_iter() - .collect(), + name: "Eye and face tracking".into(), + strings: HashMap::new(), flags: HashSet::new(), options: [ HigherOrderChoiceOption { diff --git a/alvr/dashboard/src/dashboard/components/settings_controls/presets/higher_order_choice.rs b/alvr/dashboard/src/dashboard/components/settings_controls/presets/higher_order_choice.rs index 288a2fd73f..29defb198c 100644 --- a/alvr/dashboard/src/dashboard/components/settings_controls/presets/higher_order_choice.rs +++ b/alvr/dashboard/src/dashboard/components/settings_controls/presets/higher_order_choice.rs @@ -1,18 +1,16 @@ use std::collections::{HashMap, HashSet}; use super::schema::{HigherOrderChoiceSchema, PresetModifierOperation}; -use crate::dashboard::components::{self, NestingInfo, SettingControl}; +use crate::dashboard::components::{self, NestingInfo, SettingControl, INDENTATION_STEP}; use alvr_gui_common::theme::{ log_colors::{INFO_LIGHT, WARNING_LIGHT}, OK_GREEN, }; use alvr_packets::{PathSegment, PathValuePair}; -use eframe::egui::{self, popup, Ui}; +use eframe::egui::Ui; use serde_json as json; use settings_schema::{SchemaEntry, SchemaNode}; -const POPUP_ID: &str = "setpopup"; - pub struct Control { name: String, help: Option, @@ -139,18 +137,19 @@ impl Control { let mut response = None; ui.horizontal(|ui| { + ui.add_space(INDENTATION_STEP); ui.label(&self.name); if let Some(string) = &self.help { if ui.colored_label(INFO_LIGHT, "❓").hovered() { - popup::show_tooltip_text(ui.ctx(), egui::Id::new(POPUP_ID), string); + alvr_gui_common::tooltip(ui, &format!("{}_help_tooltip", self.name), string); } } if self.steamvr_restart_flag && ui.colored_label(WARNING_LIGHT, "⚠").hovered() { - popup::show_tooltip_text( - ui.ctx(), - egui::Id::new(POPUP_ID), - format!( + alvr_gui_common::tooltip( + ui, + "steamvr_restart_tooltip", + &format!( "Changing this setting will make SteamVR restart!\n{}", "Please save your in-game progress first" ), @@ -159,9 +158,9 @@ impl Control { // The emoji is blue but it will be green in the UI if self.real_time_flag && ui.colored_label(OK_GREEN, "🔵").hovered() { - popup::show_tooltip_text( - ui.ctx(), - egui::Id::new(POPUP_ID), + alvr_gui_common::tooltip( + ui, + "real_time_tooltip", "This setting can be changed in real-time during streaming!", ); } @@ -171,8 +170,6 @@ impl Control { .ui(ui, &mut self.preset_json, true) .or(response); - // ui.end_row(); - if let Some(desc) = response { // todo: handle children requests self.modifiers[desc.value.as_str().unwrap()].clone() diff --git a/alvr/dashboard/src/dashboard/components/settings_controls/section.rs b/alvr/dashboard/src/dashboard/components/settings_controls/section.rs index e762110271..0c502ad93b 100644 --- a/alvr/dashboard/src/dashboard/components/settings_controls/section.rs +++ b/alvr/dashboard/src/dashboard/components/settings_controls/section.rs @@ -1,16 +1,16 @@ use super::{collapsible, NestingInfo, SettingControl, INDENTATION_STEP}; -use crate::dashboard::DisplayString; -use alvr_gui_common::theme::{ - log_colors::{INFO_LIGHT, WARNING_LIGHT}, - OK_GREEN, +use alvr_gui_common::{ + theme::{ + log_colors::{INFO_LIGHT, WARNING_LIGHT}, + OK_GREEN, + }, + DisplayString, }; use alvr_packets::PathValuePair; use alvr_session::settings_schema::{SchemaEntry, SchemaNode}; -use eframe::egui::{self, popup, Ui}; +use eframe::egui::Ui; use serde_json as json; -const POPUP_ID: &str = "setpopup"; - struct Entry { id: DisplayString, help: Option, @@ -116,15 +116,19 @@ impl Control { if let Some(string) = &entry.help { if ui.colored_label(INFO_LIGHT, "❓").hovered() { - popup::show_tooltip_text(ui.ctx(), egui::Id::new(POPUP_ID), string); + alvr_gui_common::tooltip( + ui, + &format!("{}_help_tooltip", entry.id.display), + string, + ); } } if entry.steamvr_restart_flag && ui.colored_label(WARNING_LIGHT, "⚠").hovered() { - popup::show_tooltip_text( - ui.ctx(), - egui::Id::new(POPUP_ID), - format!( + alvr_gui_common::tooltip( + ui, + "steamvr_restart_tooltip", + &format!( "Changing this setting will make SteamVR restart!\n{}", "Please save your in-game progress first" ), @@ -133,9 +137,9 @@ impl Control { // The emoji is blue but it will be green in the UI if entry.real_time_flag && ui.colored_label(OK_GREEN, "🔵").hovered() { - popup::show_tooltip_text( - ui.ctx(), - egui::Id::new(POPUP_ID), + alvr_gui_common::tooltip( + ui, + "real_time_tooltip", "This setting can be changed in real-time during streaming!", ); } diff --git a/alvr/dashboard/src/dashboard/components/settings_controls/switch.rs b/alvr/dashboard/src/dashboard/components/settings_controls/switch.rs index 240f4c82ee..a07c22a332 100644 --- a/alvr/dashboard/src/dashboard/components/settings_controls/switch.rs +++ b/alvr/dashboard/src/dashboard/components/settings_controls/switch.rs @@ -1,5 +1,4 @@ use super::{reset, NestingInfo, SettingControl}; -use crate::dashboard::basic_components; use alvr_packets::PathValuePair; use alvr_session::settings_schema::SchemaNode; use eframe::{ @@ -63,7 +62,7 @@ impl Control { } ui.with_layout(Layout::left_to_right(Align::Center), |ui| { - if basic_components::switch(ui, enabled_mut).clicked() { + if alvr_gui_common::switch(ui, enabled_mut).clicked() { request = get_request(&self.nesting_info, *enabled_mut); } diff --git a/alvr/dashboard/src/dashboard/components/setup_wizard.rs b/alvr/dashboard/src/dashboard/components/setup_wizard.rs index 5700459b35..29c65efeea 100644 --- a/alvr/dashboard/src/dashboard/components/setup_wizard.rs +++ b/alvr/dashboard/src/dashboard/components/setup_wizard.rs @@ -1,5 +1,4 @@ -use crate::dashboard::basic_components; -use alvr_packets::{FirewallRulesAction, PathValuePair, ServerRequest}; +use alvr_packets::{FirewallRulesAction, ServerRequest}; use eframe::{ egui::{Button, Label, Layout, RichText, Ui}, emath::Align, @@ -16,10 +15,9 @@ enum Page { ResetSettings = 1, HardwareRequirements = 2, SoftwareRequirements = 3, - HandGestures = 4, - Firewall = 5, - Recommendations = 6, - Finished = 7, + Firewall = 4, + Recommendations = 5, + Finished = 6, } fn index_to_page(index: usize) -> Page { @@ -28,11 +26,10 @@ fn index_to_page(index: usize) -> Page { 1 => Page::ResetSettings, 2 => Page::HardwareRequirements, 3 => Page::SoftwareRequirements, - 4 => Page::HandGestures, - 5 => Page::Firewall, - 6 => Page::Recommendations, - 7 => Page::Finished, - _ => unreachable!(), + 4 => Page::Firewall, + 5 => Page::Recommendations, + 6 => Page::Finished, + _ => panic!("Invalid page index"), } } @@ -49,7 +46,7 @@ fn page_content( ui.with_layout(Layout::top_down(Align::LEFT), |ui| { ui.add_space(15.0); ui.heading(RichText::new(subtitle).size(20.0)); - ui.add(Label::new(RichText::new(paragraph).size(14.0)).wrap(true)); + ui.add(Label::new(RichText::new(paragraph).size(14.0)).wrap()); ui.add_space(30.0); ui.vertical_centered(interactible_content); }); @@ -59,14 +56,12 @@ fn page_content( pub struct SetupWizard { page: Page, - only_touch: bool, } impl SetupWizard { pub fn new() -> Self { Self { page: Page::Welcome, - only_touch: true, } } @@ -119,6 +114,8 @@ Make sure you have at least one output audio device.", "Software requirements", if cfg!(windows) { r"To stream the headset microphone on Windows you need to install VB-Cable or Voicemeeter." + } else if cfg!(target_os = "linux") { + r"You need the PipeWire package to be able to stream audio." } else { r"Unsupported OS" }, @@ -132,27 +129,6 @@ Make sure you have at least one output audio device.", } }, ), - - Page::HandGestures => page_content( - ui, - "Hand Gestures", - r"ALVR allows you to use Hand Tracking and emulate controller buttons using it. -By default, controller button emulation is set to prevent accidental clicks. You can re-enable gestures by disabling slider bellow.", - |ui| { - ui.label("Only touch"); - if basic_components::switch(ui, &mut self.only_touch).changed() { - request = Some(SetupWizardRequest::ServerRequest( - ServerRequest::SetValues(vec![PathValuePair { - path: alvr_packets::parse_path(&format!( - "session_settings.headset.controllers.content.{}", - "gestures.content.only_touch" - )), - value: serde_json::Value::Bool(self.only_touch), - }]), - )); - } - }, - ), Page::Firewall => page_content( ui, "Firewall", diff --git a/alvr/dashboard/src/dashboard/components/statistics.rs b/alvr/dashboard/src/dashboard/components/statistics.rs index 8e96828fb6..1937ea643c 100644 --- a/alvr/dashboard/src/dashboard/components/statistics.rs +++ b/alvr/dashboard/src/dashboard/components/statistics.rs @@ -1,4 +1,4 @@ -use crate::{dashboard::theme::graph_colors, dashboard::ServerRequest}; +use crate::dashboard::{theme::graph_colors, ServerRequest}; use alvr_events::{GraphStatistics, StatisticsSummary}; use alvr_gui_common::theme; use eframe::{ @@ -109,9 +109,12 @@ impl StatisticsTab { RectTransform::from_to(canvas_response.response.rect, canvas_response.inner) * pos; let history_index = (graph_pos.x as usize).clamp(0, GRAPH_HISTORY_SIZE - 1); - popup::show_tooltip(ui.ctx(), Id::new("popup"), |ui| { - tooltip_content(ui, &self.history[history_index]) - }); + popup::show_tooltip( + ui.ctx(), + ui.layer_id(), + Id::new(format!("{title}_popup")), + |ui| tooltip_content(ui, &self.history[history_index]), + ); } } diff --git a/alvr/dashboard/src/dashboard/mod.rs b/alvr/dashboard/src/dashboard/mod.rs index 9bdf575682..0ca3b675f0 100644 --- a/alvr/dashboard/src/dashboard/mod.rs +++ b/alvr/dashboard/src/dashboard/mod.rs @@ -1,4 +1,3 @@ -mod basic_components; mod components; use self::components::{ @@ -11,37 +10,7 @@ use alvr_gui_common::theme; use alvr_packets::{PathValuePair, ServerRequest}; use alvr_session::SessionConfig; use eframe::egui::{self, Align, CentralPanel, Frame, Layout, Margin, RichText, SidePanel, Stroke}; -use std::{ - collections::BTreeMap, - ops::Deref, - sync::{atomic::AtomicUsize, Arc}, -}; - -#[derive(Clone)] -pub struct DisplayString { - pub id: String, - pub display: String, -} - -impl From<(String, String)> for DisplayString { - fn from((id, display): (String, String)) -> Self { - Self { id, display } - } -} - -impl Deref for DisplayString { - type Target = String; - - fn deref(&self) -> &String { - &self.id - } -} - -fn get_id() -> usize { - static NEXT_ID: AtomicUsize = AtomicUsize::new(0); - - NEXT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed) -} +use std::{collections::BTreeMap, sync::Arc}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] enum Tab { @@ -230,7 +199,7 @@ impl eframe::App for Dashboard { .inner_margin(Margin::same(7.0)) .stroke(Stroke::new(1.0, theme::SEPARATOR_BG)), ) - .exact_width(150.0) + .exact_width(160.0) .show(context, |ui| { ui.with_layout(Layout::top_down_justified(Align::Center), |ui| { ui.add_space(13.0); diff --git a/alvr/dashboard/src/main.rs b/alvr/dashboard/src/main.rs index 98de5e4ff3..80ea7b71d7 100644 --- a/alvr/dashboard/src/main.rs +++ b/alvr/dashboard/src/main.rs @@ -109,7 +109,7 @@ fn main() { server_events_receiver, ); - Box::new(Dashboard::new(creation_context, data_source)) + Ok(Box::new(Dashboard::new(creation_context, data_source))) }) }, ) diff --git a/alvr/gui_common/Cargo.toml b/alvr/gui_common/Cargo.toml index 6f9cd93488..9d77eb27c7 100644 --- a/alvr/gui_common/Cargo.toml +++ b/alvr/gui_common/Cargo.toml @@ -9,4 +9,4 @@ license.workspace = true [dependencies] alvr_common.workspace = true -egui = "0.27" +egui = "0.28" diff --git a/alvr/dashboard/src/dashboard/basic_components/button_group.rs b/alvr/gui_common/src/basic_components/button_group.rs similarity index 88% rename from alvr/dashboard/src/dashboard/basic_components/button_group.rs rename to alvr/gui_common/src/basic_components/button_group.rs index 3a003c8c9e..309b3f6e25 100644 --- a/alvr/dashboard/src/dashboard/basic_components/button_group.rs +++ b/alvr/gui_common/src/basic_components/button_group.rs @@ -1,5 +1,5 @@ -use crate::dashboard::DisplayString; -use eframe::egui::Ui; +use crate::DisplayString; +use egui::Ui; // todo: use a custom widget pub fn button_group_clicked( diff --git a/alvr/dashboard/src/dashboard/basic_components/mod.rs b/alvr/gui_common/src/basic_components/mod.rs similarity index 54% rename from alvr/dashboard/src/dashboard/basic_components/mod.rs rename to alvr/gui_common/src/basic_components/mod.rs index 731e48a000..c88a5603ef 100644 --- a/alvr/dashboard/src/dashboard/basic_components/mod.rs +++ b/alvr/gui_common/src/basic_components/mod.rs @@ -1,5 +1,9 @@ mod button_group; +mod modal; mod switch; +mod tooltip; pub use button_group::*; +pub use modal::*; pub use switch::*; +pub use tooltip::*; diff --git a/alvr/gui_common/src/basic_components/modal.rs b/alvr/gui_common/src/basic_components/modal.rs new file mode 100644 index 0000000000..9b122952b5 --- /dev/null +++ b/alvr/gui_common/src/basic_components/modal.rs @@ -0,0 +1,56 @@ +use egui::{Align, Align2, Context, Layout, Ui, Window}; +use std::fmt::{self, Display, Formatter}; + +#[derive(Clone, PartialEq)] +pub enum ModalButton { + Ok, + Cancel, + Close, + Custom(String), +} + +impl Display for ModalButton { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + ModalButton::Ok => write!(f, "OK"), + ModalButton::Cancel => write!(f, "Cancel"), + ModalButton::Close => write!(f, "Close"), + ModalButton::Custom(text) => write!(f, "{}", text), + } + } +} + +pub fn modal( + context: &Context, + title: &str, + content: Option, + buttons: &[ModalButton], +) -> Option { + let mut response = None; + + Window::new(title) + .anchor(Align2::CENTER_CENTER, (0.0, 0.0)) + .collapsible(false) + .resizable(false) + .show(context, |ui| { + ui.vertical_centered_justified(|ui| { + if let Some(content) = content { + ui.add_space(10.0); + content(ui); + ui.add_space(10.0); + } + + ui.columns(buttons.len(), |cols| { + for (idx, response_type) in buttons.iter().enumerate() { + cols[idx].with_layout(Layout::top_down_justified(Align::Center), |ui| { + if ui.button(response_type.to_string()).clicked() { + response = Some(response_type.clone()); + } + }); + } + }); + }); + }); + + response +} diff --git a/alvr/dashboard/src/dashboard/basic_components/switch.rs b/alvr/gui_common/src/basic_components/switch.rs similarity index 91% rename from alvr/dashboard/src/dashboard/basic_components/switch.rs rename to alvr/gui_common/src/basic_components/switch.rs index 5bfe3a9746..2953296001 100644 --- a/alvr/dashboard/src/dashboard/basic_components/switch.rs +++ b/alvr/gui_common/src/basic_components/switch.rs @@ -1,4 +1,4 @@ -use eframe::egui::{self, Response, Sense, Ui, WidgetInfo, WidgetType}; +use egui::{self, Response, Sense, Ui, WidgetInfo, WidgetType}; pub fn switch(ui: &mut Ui, on: &mut bool) -> Response { let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0); @@ -7,7 +7,7 @@ pub fn switch(ui: &mut Ui, on: &mut bool) -> Response { *on = !*on; response.mark_changed(); } - response.widget_info(|| WidgetInfo::selected(WidgetType::Checkbox, *on, "")); + response.widget_info(|| WidgetInfo::selected(WidgetType::Checkbox, true, *on, "")); let how_on = ui.ctx().animate_bool(response.id, *on); let visuals = ui.style().interact_selectable(&response, *on); diff --git a/alvr/gui_common/src/basic_components/tooltip.rs b/alvr/gui_common/src/basic_components/tooltip.rs new file mode 100644 index 0000000000..d1913649cc --- /dev/null +++ b/alvr/gui_common/src/basic_components/tooltip.rs @@ -0,0 +1,5 @@ +use egui::{self, popup, Ui}; + +pub fn tooltip(ui: &mut Ui, id: &str, text: &str) { + popup::show_tooltip_text(ui.ctx(), ui.layer_id(), egui::Id::new(id), text); +} diff --git a/alvr/gui_common/src/lib.rs b/alvr/gui_common/src/lib.rs index 9757ba5fc1..313a2cd8d3 100644 --- a/alvr/gui_common/src/lib.rs +++ b/alvr/gui_common/src/lib.rs @@ -1 +1,32 @@ +mod basic_components; pub mod theme; + +pub use basic_components::*; + +use std::{ops::Deref, sync::atomic::AtomicUsize}; + +pub fn get_id() -> usize { + static NEXT_ID: AtomicUsize = AtomicUsize::new(0); + + NEXT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed) +} + +#[derive(Clone)] +pub struct DisplayString { + pub id: String, + pub display: String, +} + +impl From<(String, String)> for DisplayString { + fn from((id, display): (String, String)) -> Self { + Self { id, display } + } +} + +impl Deref for DisplayString { + type Target = String; + + fn deref(&self) -> &String { + &self.id + } +} diff --git a/alvr/launcher/Cargo.toml b/alvr/launcher/Cargo.toml index c4af5f8295..3469c294b0 100644 --- a/alvr/launcher/Cargo.toml +++ b/alvr/launcher/Cargo.toml @@ -11,7 +11,7 @@ alvr_common.workspace = true alvr_gui_common.workspace = true anyhow = "1" -eframe = "0.27" +eframe = "0.28" flate2 = "1.0.18" futures-util = "0.3.28" ico = "0.3" diff --git a/alvr/launcher/src/actions.rs b/alvr/launcher/src/actions.rs index 5d278a5d64..8b0759e0d2 100644 --- a/alvr/launcher/src/actions.rs +++ b/alvr/launcher/src/actions.rs @@ -193,7 +193,7 @@ async fn install_apk( .await?, ); - zip::ZipArchive::new(&mut buffer)?.extract(&data_dir())?; + zip::ZipArchive::new(&mut buffer)?.extract(data_dir())?; } worker_message_sender.send(WorkerMessage::ProgressUpdate(Progress { diff --git a/alvr/launcher/src/main.rs b/alvr/launcher/src/main.rs index 70ff3d1940..869ea40bc7 100644 --- a/alvr/launcher/src/main.rs +++ b/alvr/launcher/src/main.rs @@ -66,11 +66,11 @@ fn main() { ..Default::default() }, Box::new(move |cc| { - Box::new(Launcher::new( + Ok(Box::new(Launcher::new( cc, worker_message_receiver, ui_message_sender, - )) + ))) }), ) .expect("Failed to run eframe"); diff --git a/alvr/launcher/src/ui.rs b/alvr/launcher/src/ui.rs index 5cb401670a..46420b4879 100644 --- a/alvr/launcher/src/ui.rs +++ b/alvr/launcher/src/ui.rs @@ -1,10 +1,11 @@ use crate::{actions, InstallationInfo, Progress, ReleaseChannelsInfo, UiMessage, WorkerMessage}; +use alvr_gui_common::ModalButton; use eframe::{ egui::{ self, Button, CentralPanel, ComboBox, Context, Frame, Grid, Layout, ProgressBar, RichText, - ViewportCommand, Window, + Ui, ViewportCommand, }, - emath::{Align, Align2}, + emath::Align, epaint::Color32, }; use std::{ @@ -19,12 +20,12 @@ enum State { } #[derive(Default)] -enum Popup { +enum PopupType { #[default] None, DeleteInstallation(String), EditVersion(String), - Version(VersionPopup), + Version(Version), } #[derive(Clone, PartialEq, Eq)] @@ -35,21 +36,17 @@ enum ReleaseChannelType { #[derive(Clone, PartialEq, Eq)] struct Version { - version: String, + string: String, release_channel: ReleaseChannelType, } -struct VersionPopup { - version: Version, -} - pub struct Launcher { worker_message_receiver: Receiver, ui_message_sender: Sender, state: State, release_channels_info: Option, installations: Vec, - popup: Popup, + popup: PopupType, } impl Launcher { @@ -66,190 +63,177 @@ impl Launcher { state: State::Default, release_channels_info: None, installations: actions::get_installations(), - popup: Popup::None, + popup: PopupType::None, } } - fn version_popup(&mut self, ctx: &Context, mut version_popup: VersionPopup) -> Popup { - Window::new("Add version") - .anchor(Align2::CENTER_CENTER, (0.0, 0.0)) - .resizable(false) - .collapsible(false) - .show(ctx, |ui| { + fn version_popup(&mut self, ctx: &Context, version: Version) -> PopupType { + let response = alvr_gui_common::modal( + ctx, + "Add version", + { // Safety: unwrap is safe because the "Add release" button is available after populating the release_channels_info. let release_channels_info = self.release_channels_info.as_ref().unwrap(); - let (channel, version_str, versions): (&str, String, Vec) = - match version_popup.version.release_channel.clone() { - ReleaseChannelType::Stable => ( - "Stable", - version_popup.version.version.clone(), - release_channels_info - .stable - .iter() - .map(|release| Version { - version: release.version.clone(), - release_channel: ReleaseChannelType::Stable, - }) - .collect(), - ), - ReleaseChannelType::Nightly => ( - "Nightly", - version_popup.version.version.clone(), - release_channels_info - .nightly - .iter() - .map(|release| Version { - version: release.version.clone(), - release_channel: ReleaseChannelType::Nightly, - }) - .collect(), - ), - }; - Grid::new("add-version-grid").num_columns(2).show(ui, |ui| { - ui.label("Channel"); - - ui.with_layout(Layout::right_to_left(Align::Min), |ui| { - ComboBox::from_id_source("channel") - .selected_text(channel) - .show_ui(ui, |ui| { - ui.selectable_value( - &mut version_popup.version, - Version { - version: self - .release_channels_info - .as_ref() - .unwrap() - .stable[0] - .version - .clone(), + let mut version = version.clone(); + Some(move |ui: &mut Ui| { + let (channel, version_str, versions): (&str, String, Vec) = + match version.release_channel.clone() { + ReleaseChannelType::Stable => ( + "Stable", + version.string.clone(), + release_channels_info + .stable + .iter() + .map(|release| Version { + string: release.version.clone(), release_channel: ReleaseChannelType::Stable, - }, - "Stable", - ); - ui.selectable_value( - &mut version_popup.version, - Version { - version: self - .release_channels_info - .as_ref() - .unwrap() - .nightly[0] - .version - .clone(), + }) + .collect(), + ), + ReleaseChannelType::Nightly => ( + "Nightly", + version.string.clone(), + release_channels_info + .nightly + .iter() + .map(|release| Version { + string: release.version.clone(), release_channel: ReleaseChannelType::Nightly, - }, - "Nightly", - ); - }) - }); - ui.end_row(); + }) + .collect(), + ), + }; + Grid::new("add-version-grid").num_columns(2).show(ui, |ui| { + ui.label("Channel"); - ui.label("Version"); - ui.with_layout(Layout::right_to_left(Align::Min), |ui| { - ComboBox::from_id_source("version") - .selected_text(version_str) - .show_ui(ui, |ui| { - for version in versions { + ui.with_layout(Layout::right_to_left(Align::Min), |ui| { + ComboBox::from_id_source("channel") + .selected_text(channel) + .show_ui(ui, |ui| { + ui.selectable_value( + &mut version, + Version { + string: release_channels_info.stable[0].version.clone(), + release_channel: ReleaseChannelType::Stable, + }, + "Stable", + ); ui.selectable_value( - &mut version_popup.version, - version.clone(), - version.version, + &mut version, + Version { + string: release_channels_info.nightly[0] + .version + .clone(), + release_channel: ReleaseChannelType::Nightly, + }, + "Nightly", ); - } - }) + }) + }); + ui.end_row(); + + ui.label("Version"); + ui.with_layout(Layout::right_to_left(Align::Min), |ui| { + ComboBox::from_id_source("version") + .selected_text(version_str) + .show_ui(ui, |ui| { + for ver in versions { + ui.selectable_value(&mut version, ver.clone(), ver.string); + } + }) + }); + ui.end_row(); }); - ui.end_row(); - }); - ui.columns(2, |ui| { - if ui[0].button("Cancel").clicked() { - return Popup::None; - } + }) + }, + &[ModalButton::Cancel, ModalButton::Custom("Install".into())], + ); - if ui[1].button("Install").clicked() { - self.ui_message_sender - .send(UiMessage::InstallServer( - match &version_popup.version.release_channel { - ReleaseChannelType::Stable => release_channels_info - .stable - .iter() - .find(|release| { - release.version == version_popup.version.version - }) - .unwrap() - .clone(), - ReleaseChannelType::Nightly => release_channels_info - .nightly - .iter() - .find(|release| { - release.version == version_popup.version.version - }) - .unwrap() - .clone(), - }, - )) - .unwrap(); - return Popup::None; - } + match response { + Some(ModalButton::Cancel) => PopupType::None, + Some(ModalButton::Custom(_)) => { + self.ui_message_sender + .send(UiMessage::InstallServer(match &version.release_channel { + ReleaseChannelType::Stable => self + .release_channels_info + .as_ref() + .unwrap() + .stable + .iter() + .find(|release| release.version == version.string) + .unwrap() + .clone(), + ReleaseChannelType::Nightly => self + .release_channels_info + .as_ref() + .unwrap() + .nightly + .iter() + .find(|release| release.version == version.string) + .unwrap() + .clone(), + })) + .ok(); - Popup::Version(version_popup) - }) - }) - .unwrap() - .inner - .unwrap() + PopupType::None + } + _ => PopupType::Version(version), + } } - fn edit_popup(&self, ctx: &Context, version: String) -> Popup { - Window::new("Edit version") - .anchor(Align2::CENTER_CENTER, (0.0, 0.0)) - .resizable(false) - .collapsible(false) - .show(ctx, |ui| { + fn edit_popup(&self, ctx: &Context, version: String) -> PopupType { + let mut delete_version = false; + let response = alvr_gui_common::modal( + ctx, + "Edit version", + Some(|ui: &mut Ui| { ui.with_layout(Layout::top_down_justified(Align::Center), |ui| { - if ui.button("Delete version").clicked() { - return Popup::DeleteInstallation(version); - }; - if ui.button("Close").clicked() { - return Popup::None; - } + delete_version = ui.button("Delete version").clicked(); + }); + }), + &[ModalButton::Close], + ); - Popup::EditVersion(version) - }) - .inner - }) - .unwrap() - .inner - .unwrap() + if delete_version { + PopupType::DeleteInstallation(version) + } else if matches!(response, Some(ModalButton::Close)) { + PopupType::None + } else { + PopupType::EditVersion(version) + } } - fn delete_popup(&mut self, ctx: &Context, version: String) -> Popup { - Window::new("Are you sure?") - .anchor(Align2::CENTER_CENTER, (0.0, 0.0)) - .resizable(false) - .collapsible(false) - .show(ctx, |ui| { - ui.with_layout(Layout::top_down(Align::Center), |ui| { - ui.label(format!("This will permanently delete version {}", version)); - }); - ui.columns(2, |ui| { - if ui[0].button("Cancel").clicked() { - return Popup::None; - } - if ui[1].button("Delete version").clicked() { - if let Err(e) = actions::delete_installation(&version) { - self.state = State::Error(format!("Failed to delete version: {e}")); - } + fn delete_popup(&mut self, ctx: &Context, version: String) -> PopupType { + let response = alvr_gui_common::modal( + ctx, + "Are you sure?", + Some({ + let version = version.clone(); + move |ui: &mut Ui| { + ui.with_layout(Layout::top_down(Align::Center), |ui| { + ui.label(format!("This will permanently delete version {}", version)); + }); + } + }), + &[ + ModalButton::Cancel, + ModalButton::Custom("Delete version".into()), + ], + ); + + match response { + Some(ModalButton::Cancel) => PopupType::None, + Some(ModalButton::Custom(_)) => { + if let Err(e) = actions::delete_installation(&version) { + self.state = State::Error(format!("Failed to delete version: {e}")); + } - self.installations = actions::get_installations(); + self.installations = actions::get_installations(); - return Popup::None; - } - Popup::DeleteInstallation(version) - }) - }) - .unwrap() - .inner - .unwrap() + PopupType::None + } + _ => PopupType::DeleteInstallation(version), + } } } @@ -292,7 +276,7 @@ impl eframe::App for Launcher { ui.label(&installation.version); ui.with_layout(Layout::right_to_left(Align::Min), |ui| { if ui.button("Edit").clicked() { - self.popup = Popup::EditVersion( + self.popup = PopupType::EditVersion( installation.version.clone(), ); } @@ -323,7 +307,7 @@ impl eframe::App for Launcher { .send(UiMessage::InstallClient( release_info, )) - .unwrap(); + .ok(); } else { self.state = State::Error( "Failed to get release info".into(), @@ -338,7 +322,7 @@ impl eframe::App for Launcher { Ok(()) => { self.ui_message_sender .send(UiMessage::Quit) - .unwrap(); + .ok(); ctx.send_viewport_cmd( ViewportCommand::Close, ); @@ -360,21 +344,19 @@ impl eframe::App for Launcher { ) .clicked() { - self.popup = Popup::Version(VersionPopup { - version: Version { - version: self.release_channels_info.as_ref().unwrap().stable[0] - .version - .clone(), - release_channel: ReleaseChannelType::Stable, - }, + self.popup = PopupType::Version(Version { + string: self.release_channels_info.as_ref().unwrap().stable[0] + .version + .clone(), + release_channel: ReleaseChannelType::Stable, }); } let popup = match mem::take(&mut self.popup) { - Popup::Version(version_popup) => self.version_popup(ctx, version_popup), - Popup::EditVersion(version) => self.edit_popup(ctx, version), - Popup::DeleteInstallation(version) => self.delete_popup(ctx, version), - Popup::None => Popup::None, + PopupType::Version(version) => self.version_popup(ctx, version), + PopupType::EditVersion(version) => self.edit_popup(ctx, version), + PopupType::DeleteInstallation(version) => self.delete_popup(ctx, version), + PopupType::None => PopupType::None, }; self.popup = popup; }); @@ -399,7 +381,7 @@ impl eframe::App for Launcher { }); if ctx.input(|i| i.viewport().close_requested()) { - self.ui_message_sender.send(UiMessage::Quit).unwrap(); + self.ui_message_sender.send(UiMessage::Quit).ok(); } } } diff --git a/alvr/server/README.md b/alvr/server/README.md deleted file mode 100644 index 602d236bf3..0000000000 --- a/alvr/server/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# alvr_server - -SteamVR driver written in C++ and wrapped into a Rust library. The wrapping is done to use the same cross-patform build system of other ALVR compoents, and to allow to easily extend C++ code with Rust. diff --git a/alvr/server/Cargo.toml b/alvr/server_core/Cargo.toml similarity index 74% rename from alvr/server/Cargo.toml rename to alvr/server_core/Cargo.toml index 2411258e2d..00fc6b8459 100644 --- a/alvr/server/Cargo.toml +++ b/alvr/server_core/Cargo.toml @@ -1,66 +1,56 @@ -[package] -name = "alvr_server" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -authors = ["alvr-org", "Valve Corporation"] -license = "MIT" - -[lib] -crate-type = ["cdylib"] - -[features] -gpl = [] # Enable for FFmpeg support on Windows. Always enabled on Linux -trace-performance = ["profiling/profile-with-tracy"] - -[dependencies] -alvr_audio.workspace = true -alvr_common.workspace = true -alvr_events.workspace = true -alvr_filesystem.workspace = true -alvr_packets.workspace = true -alvr_server_io.workspace = true -alvr_session.workspace = true -alvr_sockets.workspace = true - -ash = "0.38" -bincode = "1" -bytes = "1" -chrono = "0.4" -fern = "0.6" -flume = "0.11" -futures = "0.3" -headers = "0.3" -hyper = { version = "0.14", features = [ - "http2", - "server", - "stream", - "runtime", - "tcp", -] } -mdns-sd = "0.11" -profiling = { version = "1", optional = true } -reqwest = "0.11" # not used but webserver does not work without it. todo: investigate -rosc = "0.10" -tokio = { version = "1", features = [ - "rt-multi-thread", - "macros", - "process", - "io-util", - "net", - "fs", -] } -tokio-tungstenite = "0.20" -tokio-util = { version = "0.7", features = ["codec"] } -serde = "1" -serde_json = "1" -sysinfo = { version = "0.30", default-features = false } - -[build-dependencies] -alvr_filesystem = { path = "../filesystem" } -bindgen = "0.69" -cc = { version = "1", features = ["parallel"] } -walkdir = "2" - -[target.'cfg(target_os = "linux")'.build-dependencies] -pkg-config = "0.3" +[package] +name = "alvr_server_core" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors = ["alvr-org", "Valve Corporation"] +license = "MIT" + +[lib] +crate-type = ["rlib", "cdylib"] + +[features] +trace-performance = ["profiling/profile-with-tracy"] + +[dependencies] +alvr_audio.workspace = true +alvr_common.workspace = true +alvr_events.workspace = true +alvr_filesystem.workspace = true +alvr_packets.workspace = true +alvr_server_io.workspace = true +alvr_session.workspace = true +alvr_sockets.workspace = true + +ash = "0.38" +bincode = "1" +bytes = "1" +chrono = "0.4" +fern = "0.6" +flume = "0.11" +futures = "0.3" +headers = "0.3" +hyper = { version = "0.14", features = [ + "http2", + "server", + "stream", + "runtime", + "tcp", +] } +mdns-sd = "0.11" +profiling = { version = "1", optional = true } +reqwest = "0.11" # not used but webserver does not work without it. todo: investigate +rosc = "0.10" +tokio = { version = "1", features = [ + "rt-multi-thread", + "macros", + "process", + "io-util", + "net", + "fs", +] } +tokio-tungstenite = "0.20" +tokio-util = { version = "0.7", features = ["codec"] } +serde = "1" +serde_json = "1" +sysinfo = { version = "0.30", default-features = false } diff --git a/alvr/server/cbindgen.toml b/alvr/server_core/cbindgen.toml similarity index 100% rename from alvr/server/cbindgen.toml rename to alvr/server_core/cbindgen.toml diff --git a/alvr/server/src/bitrate.rs b/alvr/server_core/src/bitrate.rs similarity index 100% rename from alvr/server/src/bitrate.rs rename to alvr/server_core/src/bitrate.rs diff --git a/alvr/server/src/body_tracking.rs b/alvr/server_core/src/body_tracking.rs similarity index 100% rename from alvr/server/src/body_tracking.rs rename to alvr/server_core/src/body_tracking.rs diff --git a/alvr/server/src/c_api.rs b/alvr/server_core/src/c_api.rs similarity index 77% rename from alvr/server/src/c_api.rs rename to alvr/server_core/src/c_api.rs index 46d0c08de3..52960564fb 100644 --- a/alvr/server/src/c_api.rs +++ b/alvr/server_core/src/c_api.rs @@ -1,4 +1,5 @@ #![allow(dead_code, unused_variables)] +#![allow(clippy::missing_safety_doc)] use crate::{logging_backend, ServerCoreContext, ServerCoreEvent, SERVER_DATA_MANAGER}; use alvr_common::{ @@ -13,11 +14,14 @@ use std::{ collections::{HashMap, VecDeque}, ffi::{c_char, CStr, CString}, ptr, + sync::mpsc, time::{Duration, Instant}, }; static SERVER_CORE_CONTEXT: Lazy>> = Lazy::new(|| RwLock::new(None)); +static EVENTS_RECEIVER: Lazy>>> = + Lazy::new(|| Mutex::new(None)); static TRACKING_QUEUE: Lazy>> = Lazy::new(|| Mutex::new(VecDeque::new())); static BUTTONS_QUEUE: Lazy>>> = Lazy::new(|| Mutex::new(VecDeque::new())); @@ -122,6 +126,7 @@ pub enum AlvrEvent { }, ButtonsUpdated, RequestIDR, + CaptureFrame, RestartPending, ShutdownPending, } @@ -197,22 +202,22 @@ pub unsafe extern "C" fn alvr_log_error(string_ptr: *const c_char) { alvr_common::show_e(CStr::from_ptr(string_ptr).to_string_lossy()); } -pub fn log(level: log::Level, string_ptr: *const c_char) { - unsafe { log::log!(level, "{}", CStr::from_ptr(string_ptr).to_string_lossy()) }; +pub unsafe fn log(level: log::Level, string_ptr: *const c_char) { + log::log!(level, "{}", CStr::from_ptr(string_ptr).to_string_lossy()); } #[no_mangle] -pub extern "C" fn alvr_log_warn(string_ptr: *const c_char) { +pub unsafe extern "C" fn alvr_log_warn(string_ptr: *const c_char) { log(log::Level::Warn, string_ptr); } #[no_mangle] -pub extern "C" fn alvr_log_info(string_ptr: *const c_char) { +pub unsafe extern "C" fn alvr_log_info(string_ptr: *const c_char) { log(log::Level::Info, string_ptr); } #[no_mangle] -pub extern "C" fn alvr_log_debug(string_ptr: *const c_char) { +pub unsafe extern "C" fn alvr_log_debug(string_ptr: *const c_char) { log(log::Level::Debug, string_ptr); } @@ -239,10 +244,7 @@ pub unsafe extern "C" fn alvr_log_periodically(tag_ptr: *const c_char, message_p #[no_mangle] pub extern "C" fn alvr_get_settings_json(buffer: *mut c_char) -> u64 { - string_to_c_str( - buffer, - &serde_json::to_string(&SERVER_DATA_MANAGER.read().settings()).unwrap(), - ) + string_to_c_str(buffer, &serde_json::to_string(&crate::settings()).unwrap()) } #[no_mangle] @@ -252,7 +254,9 @@ pub extern "C" fn alvr_initialize_logging() { #[no_mangle] pub unsafe extern "C" fn alvr_initialize() -> AlvrTargetConfig { - *SERVER_CORE_CONTEXT.write() = Some(ServerCoreContext::new()); + let (context, receiver) = ServerCoreContext::new(); + *SERVER_CORE_CONTEXT.write() = Some(context); + *EVENTS_RECEIVER.lock() = Some(receiver); let data_manager_lock = SERVER_DATA_MANAGER.read(); let restart_settings = &data_manager_lock.session().openvr_config; @@ -273,9 +277,9 @@ pub unsafe extern "C" fn alvr_start_connection() { } #[no_mangle] -pub unsafe extern "C" fn alvr_poll_event(out_event: *mut AlvrEvent) -> bool { - if let Some(context) = &*SERVER_CORE_CONTEXT.read() { - if let Some(event) = context.poll_event() { +pub unsafe extern "C" fn alvr_poll_event(out_event: *mut AlvrEvent, timeout_ns: u64) -> bool { + if let Some(receiver) = &*EVENTS_RECEIVER.lock() { + if let Ok(event) = receiver.recv_timeout(Duration::from_nanos(timeout_ns)) { match event { ServerCoreEvent::SetOpenvrProperty { .. } => {} // implementation not needed ServerCoreEvent::ClientConnected => { @@ -314,6 +318,7 @@ pub unsafe extern "C" fn alvr_poll_event(out_event: *mut AlvrEvent) -> bool { *out_event = AlvrEvent::ButtonsUpdated; } ServerCoreEvent::RequestIDR => *out_event = AlvrEvent::RequestIDR, + ServerCoreEvent::CaptureFrame => *out_event = AlvrEvent::CaptureFrame, ServerCoreEvent::GameRenderLatencyFeedback(_) => {} // implementation not needed ServerCoreEvent::RestartPending => { *out_event = AlvrEvent::RestartPending; @@ -404,7 +409,7 @@ pub extern "C" fn alvr_advance_tracking_queue() { /// Call with null out_entries to get the buffer length /// call with non-null out_entries to get the buttons and advanced the internal queue #[no_mangle] -pub extern "C" fn alvr_get_buttons(out_entries: *mut AlvrButtonEntry) -> u64 { +pub unsafe extern "C" fn alvr_get_buttons(out_entries: *mut AlvrButtonEntry) -> u64 { let entries_count = BUTTONS_QUEUE.lock().front().map(|e| e.len()).unwrap_or(0) as u64; if out_entries.is_null() { @@ -413,13 +418,11 @@ pub extern "C" fn alvr_get_buttons(out_entries: *mut AlvrButtonEntry) -> u64 { if let Some(button_entries) = BUTTONS_QUEUE.lock().pop_front() { for (i, entry) in button_entries.into_iter().enumerate() { - unsafe { - let out_entry = &mut (*out_entries.add(i)); - out_entry.id = entry.path_id; - match entry.value { - ButtonValue::Binary(value) => out_entry.value.scalar = value, - ButtonValue::Scalar(value) => out_entry.value.float = value, - } + let out_entry = &mut (*out_entries.add(i)); + out_entry.id = entry.path_id; + match entry.value { + ButtonValue::Binary(value) => out_entry.value.scalar = value, + ButtonValue::Scalar(value) => out_entry.value.float = value, } } @@ -447,7 +450,7 @@ pub extern "C" fn alvr_send_haptics( } #[no_mangle] -pub extern "C" fn alvr_set_video_config_nals( +pub unsafe extern "C" fn alvr_set_video_config_nals( codec: AlvrCodecType, buffer_ptr: *const u8, len: i32, @@ -460,7 +463,7 @@ pub extern "C" fn alvr_set_video_config_nals( let mut config_buffer = vec![0; len as usize]; - unsafe { ptr::copy_nonoverlapping(buffer_ptr, config_buffer.as_mut_ptr(), len as usize) }; + ptr::copy_nonoverlapping(buffer_ptr, config_buffer.as_mut_ptr(), len as usize); if let Some(context) = &*SERVER_CORE_CONTEXT.read() { context.set_video_config_nals(config_buffer, codec); @@ -468,19 +471,19 @@ pub extern "C" fn alvr_set_video_config_nals( } #[no_mangle] -pub extern "C" fn alvr_send_video_nal( +pub unsafe extern "C" fn alvr_send_video_nal( timestamp_ns: u64, buffer_ptr: *mut u8, len: i32, is_idr: bool, ) { if let Some(context) = &*SERVER_CORE_CONTEXT.read() { - let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, len as usize) }; + let buffer = std::slice::from_raw_parts(buffer_ptr, len as usize); context.send_video_nal(Duration::from_nanos(timestamp_ns), buffer.to_vec(), is_idr); } } -// Returns true if updated +/// Returns true if updated #[no_mangle] pub unsafe extern "C" fn alvr_get_dynamic_encoder_params( out_params: *mut AlvrDynamicEncoderParams, @@ -521,10 +524,10 @@ pub extern "C" fn alvr_report_present(timestamp_ns: u64, offset_ns: u64) { /// Retrun true if a valid value is provided #[no_mangle] -pub extern "C" fn alvr_duration_until_next_vsync(out_ns: *mut u64) -> bool { +pub unsafe extern "C" fn alvr_duration_until_next_vsync(out_ns: *mut u64) -> bool { if let Some(context) = &*SERVER_CORE_CONTEXT.read() { if let Some(duration) = context.duration_until_next_vsync() { - unsafe { *out_ns = duration.as_nanos() as u64 }; + *out_ns = duration.as_nanos() as u64; true } else { false @@ -545,114 +548,3 @@ pub unsafe extern "C" fn alvr_restart() { pub unsafe extern "C" fn alvr_shutdown() { SERVER_CORE_CONTEXT.write().take(); } - -// // Device API: - -// // Use the two-call pattern to first get the array length then the array data. -// #[no_mangle] -// pub unsafe extern "C" fn alvr_get_devices(out_device_configs: *mut AlvrDeviceConfig) -> u64 { -// todo!() -// } - -// // After this call, previous button and tracking data is discarded -// #[no_mangle] -// pub unsafe extern "C" fn alvr_update_inputs(device_id: u64) { -// todo!() -// } - -// // Use the two-call pattern to first get the array length then the array data. -// // Data is updated after a call to alvr_update_inputs. -// #[no_mangle] -// pub unsafe extern "C" fn alvr_get_inputs( -// device_id: u64, -// out_inputs_arr: *mut AlvrInput, -// out_timestamp_ns: u64, -// ) -> u64 { -// todo!() -// } - -// // pose_id is something like /user/hand/left/input/grip/pose -// #[no_mangle] -// pub unsafe extern "C" fn alvr_get_tracked_pose( -// pose_id: u64, -// timestamp_ns: u64, -// out_relation: *mut AlvrSpaceRelation, -// ) { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_get_hand_tracking( -// device_id: u64, -// timestamp_ns: u64, -// out_joint_set: *mut AlvrJointSet, -// ) { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_view_poses( -// out_head_relation: *mut AlvrSpaceRelation, -// out_fov_arr: *mut AlvrFov, // 2 elements -// out_relative_pose_arr: *mut AlvrPose, // 2 elements -// ) { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_destroy_device(device_id: u64) { -// todo!() -// } - -// // Compositor target API: - -// This should reflect the client current framerate -// #[no_mangle] -// pub unsafe extern "C" fn alvr_get_framerate() -> f32 { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_pre_vulkan() { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_post_vulkan() { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_create_vk_target_swapchain( -// width: u32, -// height: u32, -// vk_color_format: i32, -// vk_color_space: i32, -// vk_image_usage: u32, -// vk_present_mode: i32, -// image_count: u64, -// ) { -// todo!() -// } - -// // returns vkResult -// #[no_mangle] -// pub unsafe extern "C" fn alvr_acquire_image(out_swapchain_index: u64) -> i32 { -// todo!() -// } - -// // returns vkResult -// #[no_mangle] -// pub unsafe extern "C" fn alvr_present( -// vk_queue: u64, -// swapchain_index: u64, -// timeline_semaphore_value: u64, -// timestamp_ns: u64, -// ) -> i32 { -// todo!() -// } - -// #[no_mangle] -// pub unsafe extern "C" fn alvr_destroy_vk_target_swapchain() { -// todo!() -// } diff --git a/alvr/server/src/connection.rs b/alvr/server_core/src/connection.rs similarity index 95% rename from alvr/server/src/connection.rs rename to alvr/server_core/src/connection.rs index 58d54ea9c2..d758b0d522 100644 --- a/alvr/server/src/connection.rs +++ b/alvr/server_core/src/connection.rs @@ -72,6 +72,7 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { let mut controller_is_tracker = false; let mut _controller_profile = 0; + let mut use_separate_hand_trackers = false; let controllers_enabled = if let Switch::Enabled(config) = settings.headset.controllers { controller_is_tracker = matches!(config.emulation_mode, ControllersEmulationMode::ViveTracker); @@ -84,6 +85,11 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { ControllersEmulationMode::ViveTracker => 5, ControllersEmulationMode::Custom { .. } => 6, }; + use_separate_hand_trackers = config + .hand_skeleton + .as_option() + .map(|c| c.use_separate_trackers) + .unwrap_or(false); true } else { @@ -216,6 +222,7 @@ pub fn contruct_openvr_config(session: &SessionConfig) -> OpenvrConfig { nvenc_enable_weighted_prediction: nvenc_overrides.enable_weighted_prediction, capture_frame_dir: settings.extra.capture.capture_frame_dir, amd_bitrate_corruption_fix: settings.video.bitrate.image_corruption_fix, + use_separate_hand_trackers, _controller_profile, ..old_config } @@ -723,14 +730,14 @@ fn connection_pipeline( #[cfg(windows)] if let Ok(id) = alvr_audio::get_windows_device_id(&device) { - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::SetOpenvrProperty { + ctx.events_sender + .send(ServerCoreEvent::SetOpenvrProperty { device_id: *alvr_common::HEAD_ID, prop: alvr_session::OpenvrProperty::AudioDefaultPlaybackDeviceId( id, ), }) + .ok(); } else { continue; }; @@ -752,14 +759,14 @@ fn connection_pipeline( if let Ok(id) = AudioDevice::new_output(None) .and_then(|d| alvr_audio::get_windows_device_id(&d)) { - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::SetOpenvrProperty { + ctx.events_sender + .send(ServerCoreEvent::SetOpenvrProperty { device_id: *alvr_common::HEAD_ID, prop: alvr_session::OpenvrProperty::AudioDefaultPlaybackDeviceId( id, ), }) + .ok(); } } } @@ -775,12 +782,12 @@ fn connection_pipeline( #[cfg(windows)] if let Ok(id) = alvr_audio::get_windows_device_id(&source) { - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::SetOpenvrProperty { + ctx.events_sender + .send(ServerCoreEvent::SetOpenvrProperty { device_id: *alvr_common::HEAD_ID, prop: alvr_session::OpenvrProperty::AudioDefaultRecordingDeviceId(id), }) + .ok(); } let client_hostname = client_hostname.clone(); @@ -946,14 +953,14 @@ fn connection_pipeline( if let (Some(gestures_config), Some(gestures_button_mapping_manager)) = ( controllers_config .as_ref() - .and_then(|c| c.gestures.as_option()), + .and_then(|c| c.hand_tracking_interaction.as_option()), &mut gestures_button_mapping_manager, ) { let mut hand_gesture_manager_lock = hand_gesture_manager.lock(); if let Some(hand_skeleton) = tracking.hand_skeletons[0] { - ctx.events_queue.lock().push_back(ServerCoreEvent::Buttons( - trigger_hand_gesture_actions( + ctx.events_sender + .send(ServerCoreEvent::Buttons(trigger_hand_gesture_actions( gestures_button_mapping_manager, *HAND_LEFT_ID, &hand_gesture_manager_lock.get_active_gestures( @@ -962,12 +969,12 @@ fn connection_pipeline( *HAND_LEFT_ID, ), gestures_config.only_touch, - ), - )); + ))) + .ok(); } if let Some(hand_skeleton) = tracking.hand_skeletons[1] { - ctx.events_queue.lock().push_back(ServerCoreEvent::Buttons( - trigger_hand_gesture_actions( + ctx.events_sender + .send(ServerCoreEvent::Buttons(trigger_hand_gesture_actions( gestures_button_mapping_manager, *HAND_RIGHT_ID, &hand_gesture_manager_lock.get_active_gestures( @@ -976,23 +983,22 @@ fn connection_pipeline( *HAND_RIGHT_ID, ), gestures_config.only_touch, - ), - )); + ))) + .ok(); } } if let Some(stats) = &mut *ctx.statistics_manager.lock() { stats.report_tracking_received(tracking.target_timestamp); - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::Tracking { + ctx.events_sender + .send(ServerCoreEvent::Tracking { tracking: Box::new(Tracking { target_timestamp: tracking.target_timestamp, device_motions: motions, hand_skeletons: if controllers_config .as_ref() - .map(|c| c.enable_skeleton) + .map(|c| c.hand_skeleton.enabled()) .unwrap_or(false) { hand_skeletons @@ -1002,7 +1008,8 @@ fn connection_pipeline( face_data: tracking.face_data, }), controllers_pose_time_offset: stats.tracker_pose_time_offset(), - }); + }) + .ok(); } } } @@ -1027,9 +1034,9 @@ fn connection_pipeline( let decoder_latency = client_stats.video_decode; let (network_latency, game_latency) = stats.report_statistics(client_stats); - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::GameRenderLatencyFeedback(game_latency)); + ctx.events_sender + .send(ServerCoreEvent::GameRenderLatencyFeedback(game_latency)) + .ok(); let server_data_lock = SERVER_DATA_MANAGER.read(); ctx.bitrate_manager.lock().report_frame_latencies( @@ -1121,14 +1128,14 @@ fn connection_pipeline( let wh = area.x * area.y; if wh.is_finite() && wh > 0.0 { info!("Received new playspace with size: {}", area); - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::PlayspaceSync(area)); + ctx.events_sender + .send(ServerCoreEvent::PlayspaceSync(area)) + .ok(); } else { warn!("Received invalid playspace size: {}", area); - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::PlayspaceSync(Vec2::new(2.0, 2.0))); + ctx.events_sender + .send(ServerCoreEvent::PlayspaceSync(Vec2::new(2.0, 2.0))) + .ok(); } } } @@ -1139,23 +1146,18 @@ fn connection_pipeline( .send(&ServerControlPacket::DecoderConfig(config)) .ok(); } - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::RequestIDR); + ctx.events_sender.send(ServerCoreEvent::RequestIDR).ok(); } ClientControlPacket::VideoErrorReport => { // legacy endpoint. todo: remove if let Some(stats) = &mut *ctx.statistics_manager.lock() { stats.report_packet_loss(); } - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::RequestIDR) + ctx.events_sender.send(ServerCoreEvent::RequestIDR).ok(); } ClientControlPacket::ViewsConfig(config) => { - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::ViewsConfig(ViewsConfig { + ctx.events_sender + .send(ServerCoreEvent::ViewsConfig(ViewsConfig { local_view_transforms: [ Pose { position: Vec3::new(-config.ipd_m / 2., 0., 0.), @@ -1167,16 +1169,17 @@ fn connection_pipeline( }, ], fov: config.fov, - })); + })) + .ok(); } ClientControlPacket::Battery(packet) => { - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::Battery(BatteryInfo { + ctx.events_sender + .send(ServerCoreEvent::Battery(BatteryInfo { device_id: packet.device_id, gauge_value: packet.gauge_value, is_plugged: packet.is_plugged, - })); + })) + .ok(); if let Some(stats) = &mut *ctx.statistics_manager.lock() { stats.report_battery( @@ -1219,9 +1222,9 @@ fn connection_pipeline( .collect::>(); if !button_entries.is_empty() { - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::Buttons(button_entries)); + ctx.events_sender + .send(ServerCoreEvent::Buttons(button_entries)) + .ok(); } }; } @@ -1352,9 +1355,9 @@ fn connection_pipeline( ClientListAction::SetConnectionState(ConnectionState::Streaming), ); - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::ClientConnected); + ctx.events_sender + .send(ServerCoreEvent::ClientConnected) + .ok(); alvr_common::wait_rwlock(&disconnect_notif, &mut server_data_lock); @@ -1398,9 +1401,9 @@ fn connection_pipeline( keepalive_thread.join().ok(); lifecycle_check_thread.join().ok(); - ctx.events_queue - .lock() - .push_back(ServerCoreEvent::ClientDisconnected); + ctx.events_sender + .send(ServerCoreEvent::ClientDisconnected) + .ok(); Ok(()) } diff --git a/alvr/server/src/face_tracking.rs b/alvr/server_core/src/face_tracking.rs similarity index 100% rename from alvr/server/src/face_tracking.rs rename to alvr/server_core/src/face_tracking.rs diff --git a/alvr/server/src/hand_gestures.rs b/alvr/server_core/src/hand_gestures.rs similarity index 99% rename from alvr/server/src/hand_gestures.rs rename to alvr/server_core/src/hand_gestures.rs index de2372e05f..45f4b74e85 100644 --- a/alvr/server/src/hand_gestures.rs +++ b/alvr/server_core/src/hand_gestures.rs @@ -11,7 +11,7 @@ use alvr_common::{ }; use alvr_packets::{ButtonEntry, ButtonValue}; -use alvr_session::HandGestureConfig; +use alvr_session::HandTrackingInteractionConfig; use crate::input_mapping::ButtonMappingManager; @@ -107,7 +107,7 @@ impl HandGestureManager { pub fn get_active_gestures( &mut self, hand_skeleton: [Pose; 26], - config: &HandGestureConfig, + config: &HandTrackingInteractionConfig, device_id: u64, ) -> Vec { // global joints diff --git a/alvr/server/src/haptics.rs b/alvr/server_core/src/haptics.rs similarity index 100% rename from alvr/server/src/haptics.rs rename to alvr/server_core/src/haptics.rs diff --git a/alvr/server/src/input_mapping.rs b/alvr/server_core/src/input_mapping.rs similarity index 98% rename from alvr/server/src/input_mapping.rs rename to alvr/server_core/src/input_mapping.rs index caf4076812..9deaf39ea2 100644 --- a/alvr/server/src/input_mapping.rs +++ b/alvr/server_core/src/input_mapping.rs @@ -525,18 +525,6 @@ pub fn automatic_bindings( bindings } -pub extern "C" fn register_buttons(device_id: u64) { - for id in &*REGISTERED_BUTTON_SET { - if let Some(info) = BUTTON_INFO.get(id) { - if info.device_id == device_id { - unsafe { crate::RegisterButton(*id) }; - } - } else { - error!("Cannot register unrecognized button ID {id}"); - } - } -} - pub struct ButtonMappingManager { mappings: HashMap>, binary_source_states: HashMap, diff --git a/alvr/server/src/lib.rs b/alvr/server_core/src/lib.rs similarity index 83% rename from alvr/server/src/lib.rs rename to alvr/server_core/src/lib.rs index 214928c1ac..5090d330e5 100644 --- a/alvr/server/src/lib.rs +++ b/alvr/server_core/src/lib.rs @@ -3,29 +3,19 @@ mod body_tracking; mod c_api; mod connection; mod face_tracking; -mod graphics; mod hand_gestures; mod haptics; mod input_mapping; mod logging_backend; -mod openvr; mod sockets; mod statistics; mod tracking; mod web_server; -#[allow( - non_camel_case_types, - non_upper_case_globals, - dead_code, - non_snake_case, - clippy::unseparated_literal_suffix -)] -mod bindings { - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} -use alvr_sockets::StreamSender; -use bindings::*; +pub use c_api::*; +pub use input_mapping::REGISTERED_BUTTON_SET; +pub use logging_backend::init_logging; +pub use tracking::get_hand_skeleton_offsets; use crate::connection::VideoPacket; use alvr_common::{ @@ -37,24 +27,24 @@ use alvr_common::{ warn, ConnectionState, Fov, LifecycleState, Pose, RelaxedAtomic, DEVICE_ID_TO_PATH, }; use alvr_events::{EventType, HapticsEvent}; -use alvr_filesystem::{self as afs, Layout}; +use alvr_filesystem as afs; use alvr_packets::{ BatteryInfo, ButtonEntry, ClientListAction, DecoderInitializationConfig, Haptics, Tracking, VideoPacketHeader, }; use alvr_server_io::ServerDataManager; use alvr_session::{CodecType, OpenvrProperty, Settings}; +use alvr_sockets::StreamSender; use bitrate::{BitrateManager, DynamicEncoderParams}; use statistics::StatisticsManager; use std::{ - collections::{HashSet, VecDeque}, + collections::HashSet, env, - ffi::CString, fs::File, io::Write, sync::{ atomic::{AtomicBool, Ordering}, - mpsc::{SyncSender, TrySendError}, + mpsc::{self, SyncSender, TrySendError}, Arc, }, thread::{self, JoinHandle}, @@ -63,7 +53,7 @@ use std::{ use sysinfo::{ProcessRefreshKind, RefreshKind}; use tokio::{runtime::Runtime, sync::broadcast}; -static FILESYSTEM_LAYOUT: Lazy = Lazy::new(|| { +static FILESYSTEM_LAYOUT: Lazy = Lazy::new(|| { afs::filesystem_layout_from_openvr_driver_root_dir( &alvr_server_io::get_driver_dir_from_registered().unwrap(), ) @@ -95,13 +85,14 @@ pub enum ServerCoreEvent { }, Buttons(Vec), // Note: this is after mapping RequestIDR, + CaptureFrame, GameRenderLatencyFeedback(Duration), // only used for SteamVR ShutdownPending, RestartPending, } pub struct ConnectionContext { - events_queue: Mutex>, + events_sender: mpsc::Sender, statistics_manager: Mutex>, bitrate_manager: Mutex, decoder_config: Mutex>, @@ -134,7 +125,10 @@ pub fn create_recording_file(connection_context: &ConnectionContext, settings: & *connection_context.video_recording_file.lock() = Some(file); - unsafe { RequestIDR() }; + connection_context + .events_sender + .send(ServerCoreEvent::RequestIDR) + .ok(); } Err(e) => { error!("Failed to record video on disk: {e}"); @@ -159,7 +153,11 @@ pub fn notify_restart_driver() { } } -struct ServerCoreContext { +pub fn settings() -> Settings { + SERVER_DATA_MANAGER.read().settings().clone() +} + +pub struct ServerCoreContext { lifecycle_state: Arc>, is_restarting: RelaxedAtomic, connection_context: Arc, @@ -168,7 +166,7 @@ struct ServerCoreContext { } impl ServerCoreContext { - fn new() -> Self { + pub fn new() -> (Self, mpsc::Receiver) { if SERVER_DATA_MANAGER .read() .settings() @@ -181,8 +179,10 @@ impl ServerCoreContext { SERVER_DATA_MANAGER.write().clean_client_list(); + let (events_sender, events_receiver) = mpsc::channel(); + let connection_context = Arc::new(ConnectionContext { - events_queue: Mutex::new(VecDeque::new()), + events_sender, statistics_manager: Mutex::new(None), bitrate_manager: Mutex::new(BitrateManager::new(256, 60.0)), decoder_config: Mutex::new(None), @@ -200,43 +200,20 @@ impl ServerCoreContext { async move { alvr_common::show_err(web_server::web_server(connection_context).await) } }); - unsafe { - g_sessionPath = CString::new(FILESYSTEM_LAYOUT.session().to_string_lossy().to_string()) - .unwrap() - .into_raw(); - g_driverRootDir = CString::new( - FILESYSTEM_LAYOUT - .openvr_driver_root_dir - .to_string_lossy() - .to_string(), - ) - .unwrap() - .into_raw(); - }; - - graphics::initialize_shaders(); - - unsafe { - LogError = Some(c_api::alvr_log_error); - LogWarn = Some(c_api::alvr_log_warn); - LogInfo = Some(c_api::alvr_log_info); - LogDebug = Some(c_api::alvr_log_debug); - LogPeriodically = Some(c_api::alvr_log_periodically); - PathStringToHash = Some(c_api::alvr_path_to_id); - - CppInit(); - } - - Self { - lifecycle_state: Arc::new(RwLock::new(LifecycleState::StartingUp)), - is_restarting: RelaxedAtomic::new(false), - connection_context, - connection_thread: Arc::new(RwLock::new(None)), - webserver_runtime: Some(webserver_runtime), - } + ( + Self { + lifecycle_state: Arc::new(RwLock::new(LifecycleState::StartingUp)), + is_restarting: RelaxedAtomic::new(false), + connection_context, + + connection_thread: Arc::new(RwLock::new(None)), + webserver_runtime: Some(webserver_runtime), + }, + events_receiver, + ) } - fn start_connection(&self) { + pub fn start_connection(&self) { // Note: Idle state is not used on the server side *self.lifecycle_state.write() = LifecycleState::Resumed; @@ -247,11 +224,7 @@ impl ServerCoreContext { })); } - fn poll_event(&self) -> Option { - self.connection_context.events_queue.lock().pop_front() - } - - fn send_haptics(&self, haptics: Haptics) { + pub fn send_haptics(&self, haptics: Haptics) { let haptics_config = { let data_manager_lock = SERVER_DATA_MANAGER.read(); @@ -285,7 +258,7 @@ impl ServerCoreContext { } } - fn set_video_config_nals(&self, config_buffer: Vec, codec: CodecType) { + pub fn set_video_config_nals(&self, config_buffer: Vec, codec: CodecType) { if let Some(sender) = &*self.connection_context.video_mirror_sender.lock() { sender.send(config_buffer.clone()).ok(); } @@ -300,7 +273,7 @@ impl ServerCoreContext { }); } - fn send_video_nal(&self, target_timestamp: Duration, nal_buffer: Vec, is_idr: bool) { + pub fn send_video_nal(&self, target_timestamp: Duration, nal_buffer: Vec, is_idr: bool) { // start in the corrupts state, the client didn't receive the initial IDR yet. static STREAM_CORRUPTED: AtomicBool = AtomicBool::new(true); static LAST_IDR_INSTANT: Lazy> = Lazy::new(|| Mutex::new(Instant::now())); @@ -323,9 +296,9 @@ impl ServerCoreContext { > *LAST_IDR_INSTANT.lock() + Duration::from_secs(config.duration_s) { self.connection_context - .events_queue - .lock() - .push_back(ServerCoreEvent::RequestIDR); + .events_sender + .send(ServerCoreEvent::RequestIDR) + .ok(); if is_idr { create_recording_file( @@ -364,9 +337,9 @@ impl ServerCoreContext { ) { STREAM_CORRUPTED.store(true, Ordering::SeqCst); self.connection_context - .events_queue - .lock() - .push_back(ServerCoreEvent::RequestIDR); + .events_sender + .send(ServerCoreEvent::RequestIDR) + .ok(); warn!("Dropping video packet. Reason: Can't push to network"); } } else { @@ -384,7 +357,7 @@ impl ServerCoreContext { } } - fn get_dynamic_encoder_params(&self) -> Option { + pub fn get_dynamic_encoder_params(&self) -> Option { let pair = { let server_data_lock = SERVER_DATA_MANAGER.read(); self.connection_context @@ -404,13 +377,13 @@ impl ServerCoreContext { } } - fn report_composed(&self, target_timestamp: Duration, offset: Duration) { + pub fn report_composed(&self, target_timestamp: Duration, offset: Duration) { if let Some(stats) = &mut *self.connection_context.statistics_manager.lock() { stats.report_frame_composed(target_timestamp, offset); } } - fn report_present(&self, target_timestamp: Duration, offset: Duration) { + pub fn report_present(&self, target_timestamp: Duration, offset: Duration) { if let Some(stats) = &mut *self.connection_context.statistics_manager.lock() { stats.report_frame_present(target_timestamp, offset); } @@ -422,7 +395,7 @@ impl ServerCoreContext { .report_frame_present(&server_data_lock.settings().video.bitrate.adapt_to_framerate); } - fn duration_until_next_vsync(&self) -> Option { + pub fn duration_until_next_vsync(&self) -> Option { self.connection_context .statistics_manager .lock() @@ -430,7 +403,7 @@ impl ServerCoreContext { .map(|stats| stats.duration_until_next_vsync()) } - fn restart(self) { + pub fn restart(self) { self.is_restarting.set(true); // drop is called here for self diff --git a/alvr/server/src/logging_backend.rs b/alvr/server_core/src/logging_backend.rs similarity index 100% rename from alvr/server/src/logging_backend.rs rename to alvr/server_core/src/logging_backend.rs diff --git a/alvr/server/src/sockets.rs b/alvr/server_core/src/sockets.rs similarity index 100% rename from alvr/server/src/sockets.rs rename to alvr/server_core/src/sockets.rs diff --git a/alvr/server/src/statistics.rs b/alvr/server_core/src/statistics.rs similarity index 100% rename from alvr/server/src/statistics.rs rename to alvr/server_core/src/statistics.rs diff --git a/alvr/server/src/tracking.rs b/alvr/server_core/src/tracking.rs similarity index 100% rename from alvr/server/src/tracking.rs rename to alvr/server_core/src/tracking.rs diff --git a/alvr/server/src/web_server.rs b/alvr/server_core/src/web_server.rs similarity index 90% rename from alvr/server/src/web_server.rs rename to alvr/server_core/src/web_server.rs index 45d8ea172e..7b4b76c9ac 100644 --- a/alvr/server/src/web_server.rs +++ b/alvr/server_core/src/web_server.rs @@ -138,8 +138,18 @@ async fn http_api( alvr_events::send_event(EventType::AudioDevices(list)); } } - ServerRequest::CaptureFrame => unsafe { crate::CaptureFrame() }, - ServerRequest::InsertIdr => unsafe { crate::RequestIDR() }, + ServerRequest::CaptureFrame => { + connection_context + .events_sender + .send(ServerCoreEvent::CaptureFrame) + .ok(); + } + ServerRequest::InsertIdr => { + connection_context + .events_sender + .send(ServerCoreEvent::RequestIDR) + .ok(); + } ServerRequest::StartRecording => crate::create_recording_file( connection_context, SERVER_DATA_MANAGER.read().settings(), @@ -177,14 +187,18 @@ async fn http_api( alvr_events::send_event(EventType::DriversList(list)); } } - ServerRequest::RestartSteamvr => connection_context - .events_queue - .lock() - .push_back(ServerCoreEvent::RestartPending), - ServerRequest::ShutdownSteamvr => connection_context - .events_queue - .lock() - .push_back(ServerCoreEvent::ShutdownPending), + ServerRequest::RestartSteamvr => { + connection_context + .events_sender + .send(ServerCoreEvent::RestartPending) + .ok(); + } + ServerRequest::ShutdownSteamvr => { + connection_context + .events_sender + .send(ServerCoreEvent::ShutdownPending) + .ok(); + } } reply(StatusCode::OK)? @@ -217,7 +231,10 @@ async fn http_api( let res = websocket(request, sender, protocol::Message::Binary).await?; - unsafe { crate::RequestIDR() }; + connection_context + .events_sender + .send(ServerCoreEvent::RequestIDR) + .ok(); res } @@ -232,9 +249,9 @@ async fn http_api( .collect(); connection_context - .events_queue - .lock() - .push_back(ServerCoreEvent::Buttons(button_entries)); + .events_sender + .send(ServerCoreEvent::Buttons(button_entries)) + .ok(); reply(StatusCode::OK)? } diff --git a/alvr/server_io/Cargo.toml b/alvr/server_io/Cargo.toml index ed058ee4f9..90af596cc2 100644 --- a/alvr/server_io/Cargo.toml +++ b/alvr/server_io/Cargo.toml @@ -13,8 +13,10 @@ alvr_filesystem.workspace = true alvr_packets.workspace = true alvr_session.workspace = true -cpal = { version = "0.15", features = ["jack"] } encoding_rs_io = "0.1" dirs = "5" runas = "^1.2" # version 1.1 is broken serde_json = "1" + +[target.'cfg(not(target_os = "linux"))'.dependencies] +cpal = "0.15" diff --git a/alvr/server_io/src/lib.rs b/alvr/server_io/src/lib.rs index 7e5cd91997..95a911e9bf 100644 --- a/alvr/server_io/src/lib.rs +++ b/alvr/server_io/src/lib.rs @@ -13,7 +13,6 @@ use alvr_common::{ use alvr_events::EventType; use alvr_packets::{AudioDevicesList, ClientListAction, PathSegment, PathValuePair}; use alvr_session::{ClientConnectionConfig, SessionConfig, Settings}; -use cpal::traits::{DeviceTrait, HostTrait}; use serde_json as json; use std::{ collections::{hash_map::Entry, HashMap}, @@ -290,18 +289,30 @@ impl ServerDataManager { } pub fn get_audio_devices_list(&self) -> Result { - let host = cpal::default_host(); - - let output = host - .output_devices()? - .filter_map(|d| d.name().ok()) - .collect::>(); - let input = host - .input_devices()? - .filter_map(|d| d.name().ok()) - .collect::>(); - - Ok(AudioDevicesList { output, input }) + #[cfg(not(target_os = "linux"))] + { + use cpal::traits::{DeviceTrait, HostTrait}; + + let host = cpal::default_host(); + + let output = host + .output_devices()? + .filter_map(|d| d.name().ok()) + .collect::>(); + let input = host + .input_devices()? + .filter_map(|d| d.name().ok()) + .collect::>(); + + Ok(AudioDevicesList { output, input }) + } + #[cfg(target_os = "linux")] + { + Ok(AudioDevicesList { + input: vec![], + output: vec![], + }) + } } } diff --git a/alvr/server_openvr/Cargo.toml b/alvr/server_openvr/Cargo.toml new file mode 100644 index 0000000000..4f71252dc7 --- /dev/null +++ b/alvr/server_openvr/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "alvr_server_openvr" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors = ["alvr-org", "Valve Corporation"] +license = "MIT" + +[lib] +crate-type = ["cdylib"] + +[features] +gpl = [] # Enable for FFmpeg support on Windows. Always enabled on Linux + +[dependencies] +alvr_common.workspace = true +alvr_filesystem.workspace = true +alvr_packets.workspace = true +alvr_server_core.workspace = true +alvr_server_io.workspace = true +alvr_session.workspace = true + +[build-dependencies] +alvr_filesystem = { path = "../filesystem" } +bindgen = "0.69" +cc = { version = "1", features = ["parallel"] } +walkdir = "2" + +[target.'cfg(target_os = "linux")'.build-dependencies] +pkg-config = "0.3" diff --git a/alvr/server/LICENSE b/alvr/server_openvr/LICENSE similarity index 100% rename from alvr/server/LICENSE rename to alvr/server_openvr/LICENSE diff --git a/alvr/server/LICENSE-Valve b/alvr/server_openvr/LICENSE-Valve similarity index 100% rename from alvr/server/LICENSE-Valve rename to alvr/server_openvr/LICENSE-Valve diff --git a/alvr/server/build.rs b/alvr/server_openvr/build.rs similarity index 100% rename from alvr/server/build.rs rename to alvr/server_openvr/build.rs diff --git a/alvr/server/cpp/ALVR-common/common-utils.cpp b/alvr/server_openvr/cpp/ALVR-common/common-utils.cpp similarity index 100% rename from alvr/server/cpp/ALVR-common/common-utils.cpp rename to alvr/server_openvr/cpp/ALVR-common/common-utils.cpp diff --git a/alvr/server/cpp/ALVR-common/common-utils.h b/alvr/server_openvr/cpp/ALVR-common/common-utils.h similarity index 100% rename from alvr/server/cpp/ALVR-common/common-utils.h rename to alvr/server_openvr/cpp/ALVR-common/common-utils.h diff --git a/alvr/server/cpp/ALVR-common/exception.cpp b/alvr/server_openvr/cpp/ALVR-common/exception.cpp similarity index 100% rename from alvr/server/cpp/ALVR-common/exception.cpp rename to alvr/server_openvr/cpp/ALVR-common/exception.cpp diff --git a/alvr/server/cpp/ALVR-common/exception.h b/alvr/server_openvr/cpp/ALVR-common/exception.h similarity index 100% rename from alvr/server/cpp/ALVR-common/exception.h rename to alvr/server_openvr/cpp/ALVR-common/exception.h diff --git a/alvr/server/cpp/ALVR-common/packet_types.h b/alvr/server_openvr/cpp/ALVR-common/packet_types.h similarity index 100% rename from alvr/server/cpp/ALVR-common/packet_types.h rename to alvr/server_openvr/cpp/ALVR-common/packet_types.h diff --git a/alvr/server/cpp/alvr_server/ChaperoneUpdater.cpp b/alvr/server_openvr/cpp/alvr_server/ChaperoneUpdater.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/ChaperoneUpdater.cpp rename to alvr/server_openvr/cpp/alvr_server/ChaperoneUpdater.cpp diff --git a/alvr/server/cpp/alvr_server/Controller.cpp b/alvr/server_openvr/cpp/alvr_server/Controller.cpp similarity index 99% rename from alvr/server/cpp/alvr_server/Controller.cpp rename to alvr/server_openvr/cpp/alvr_server/Controller.cpp index 23f4fee9a4..aebf13232f 100644 --- a/alvr/server/cpp/alvr_server/Controller.cpp +++ b/alvr/server_openvr/cpp/alvr_server/Controller.cpp @@ -14,8 +14,9 @@ vr::ETrackedDeviceClass Controller::getControllerDeviceClass() { return vr::TrackedDeviceClass_Controller; } -Controller::Controller(uint64_t deviceID) - : TrackedDevice(deviceID) { +Controller::Controller(uint64_t deviceID, vr::EVRSkeletalTrackingLevel skeletonLevel) + : TrackedDevice(deviceID) + , m_skeletonLevel(skeletonLevel) { m_pose = vr::DriverPose_t {}; m_pose.poseIsValid = false; m_pose.deviceIsConnected = false; @@ -74,13 +75,13 @@ vr::EVRInitError Controller::Activate(vr::TrackedDeviceIndex_t unObjectId) { vr::VRScalarUnits_NormalizedOneSided ); - if (this->device_id == HAND_LEFT_ID) { + if (this->device_id == HAND_LEFT_ID || this->device_id == HAND_TRACKER_LEFT_ID) { vr_driver_input->CreateSkeletonComponent( this->prop_container, "/input/skeleton/left", "/skeleton/hand/left", "/pose/raw", - vr::EVRSkeletalTrackingLevel::VRSkeletalTracking_Partial, + m_skeletonLevel, nullptr, 0U, &m_compSkeleton @@ -91,7 +92,7 @@ vr::EVRInitError Controller::Activate(vr::TrackedDeviceIndex_t unObjectId) { "/input/skeleton/right", "/skeleton/hand/right", "/pose/raw", - vr::EVRSkeletalTrackingLevel::VRSkeletalTracking_Partial, + m_skeletonLevel, nullptr, 0U, &m_compSkeleton @@ -179,6 +180,10 @@ void Controller::RegisterButton(uint64_t id) { } void Controller::SetButton(uint64_t id, FfiButtonValue value) { + if (!this->isEnabled()) { + return; + } + for (auto id : ALVR_TO_STEAMVR_PATH_IDS[id]) { if (value.type == BUTTON_TYPE_BINARY) { vr::VRDriverInput()->UpdateBooleanComponent( @@ -249,6 +254,15 @@ bool Controller::onPoseUpdate( m_pose = pose; + vr::VRServerDriverHost()->TrackedDevicePoseUpdated( + this->object_id, pose, sizeof(vr::DriverPose_t) + ); + + // Early return to skip updating the skeleton + if (!this->isEnabled()) { + return false; + } + if (handSkeleton != nullptr) { vr::VRBoneTransform_t boneTransform[SKELETON_BONE_COUNT] = {}; for (int j = 0; j < 31; j++) { @@ -390,10 +404,6 @@ bool Controller::onPoseUpdate( } } - vr::VRServerDriverHost()->TrackedDevicePoseUpdated( - this->object_id, pose, sizeof(vr::DriverPose_t) - ); - return false; } diff --git a/alvr/server/cpp/alvr_server/Controller.h b/alvr/server_openvr/cpp/alvr_server/Controller.h similarity index 91% rename from alvr/server/cpp/alvr_server/Controller.h rename to alvr/server_openvr/cpp/alvr_server/Controller.h index 836ea660c4..21782a3b9c 100644 --- a/alvr/server/cpp/alvr_server/Controller.h +++ b/alvr/server_openvr/cpp/alvr_server/Controller.h @@ -7,7 +7,7 @@ class Controller : public TrackedDevice, public vr::ITrackedDeviceServerDriver { public: - Controller(uint64_t deviceID); + Controller(uint64_t deviceID, vr::EVRSkeletalTrackingLevel skeletonLevel); virtual ~Controller() {}; @@ -56,6 +56,7 @@ class Controller : public TrackedDevice, public vr::ITrackedDeviceServerDriver { vr::VRInputComponentHandle_t m_compHaptic; vr::VRInputComponentHandle_t m_compSkeleton = vr::k_ulInvalidInputComponentHandle; + vr::EVRSkeletalTrackingLevel m_skeletonLevel; vr::DriverPose_t m_pose; @@ -69,4 +70,6 @@ class Controller : public TrackedDevice, public vr::ITrackedDeviceServerDriver { bool m_lastTriggerTouch = false; float m_triggerValue = 0; float m_gripValue = 0; + + bool isEnabled() { return m_pose.deviceIsConnected; } }; diff --git a/alvr/server/cpp/alvr_server/FakeViveTracker.cpp b/alvr/server_openvr/cpp/alvr_server/FakeViveTracker.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/FakeViveTracker.cpp rename to alvr/server_openvr/cpp/alvr_server/FakeViveTracker.cpp diff --git a/alvr/server/cpp/alvr_server/FakeViveTracker.h b/alvr/server_openvr/cpp/alvr_server/FakeViveTracker.h similarity index 100% rename from alvr/server/cpp/alvr_server/FakeViveTracker.h rename to alvr/server_openvr/cpp/alvr_server/FakeViveTracker.h diff --git a/alvr/server/cpp/alvr_server/HMD.cpp b/alvr/server_openvr/cpp/alvr_server/HMD.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/HMD.cpp rename to alvr/server_openvr/cpp/alvr_server/HMD.cpp diff --git a/alvr/server/cpp/alvr_server/HMD.h b/alvr/server_openvr/cpp/alvr_server/HMD.h similarity index 100% rename from alvr/server/cpp/alvr_server/HMD.h rename to alvr/server_openvr/cpp/alvr_server/HMD.h diff --git a/alvr/server/cpp/alvr_server/IDRScheduler.cpp b/alvr/server_openvr/cpp/alvr_server/IDRScheduler.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/IDRScheduler.cpp rename to alvr/server_openvr/cpp/alvr_server/IDRScheduler.cpp diff --git a/alvr/server/cpp/alvr_server/IDRScheduler.h b/alvr/server_openvr/cpp/alvr_server/IDRScheduler.h similarity index 100% rename from alvr/server/cpp/alvr_server/IDRScheduler.h rename to alvr/server_openvr/cpp/alvr_server/IDRScheduler.h diff --git a/alvr/server/cpp/alvr_server/Logger.cpp b/alvr/server_openvr/cpp/alvr_server/Logger.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/Logger.cpp rename to alvr/server_openvr/cpp/alvr_server/Logger.cpp diff --git a/alvr/server/cpp/alvr_server/Logger.h b/alvr/server_openvr/cpp/alvr_server/Logger.h similarity index 100% rename from alvr/server/cpp/alvr_server/Logger.h rename to alvr/server_openvr/cpp/alvr_server/Logger.h diff --git a/alvr/server/cpp/alvr_server/NalParsing.cpp b/alvr/server_openvr/cpp/alvr_server/NalParsing.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/NalParsing.cpp rename to alvr/server_openvr/cpp/alvr_server/NalParsing.cpp diff --git a/alvr/server/cpp/alvr_server/Paths.cpp b/alvr/server_openvr/cpp/alvr_server/Paths.cpp similarity index 98% rename from alvr/server/cpp/alvr_server/Paths.cpp rename to alvr/server_openvr/cpp/alvr_server/Paths.cpp index b0ec1379bf..643d96d4f3 100644 --- a/alvr/server/cpp/alvr_server/Paths.cpp +++ b/alvr/server_openvr/cpp/alvr_server/Paths.cpp @@ -4,6 +4,8 @@ uint64_t HEAD_ID; uint64_t HAND_LEFT_ID; uint64_t HAND_RIGHT_ID; +uint64_t HAND_TRACKER_LEFT_ID; +uint64_t HAND_TRACKER_RIGHT_ID; std::map LEFT_CONTROLLER_BUTTON_MAPPING; std::map RIGHT_CONTROLLER_BUTTON_MAPPING; @@ -32,10 +34,8 @@ void init_paths() { HEAD_ID = PathStringToHash("/user/head"); HAND_LEFT_ID = PathStringToHash("/user/hand/left"); HAND_RIGHT_ID = PathStringToHash("/user/hand/right"); - - HEAD_ID = PathStringToHash("/user/head"); - HAND_LEFT_ID = PathStringToHash("/user/hand/left"); - HAND_RIGHT_ID = PathStringToHash("/user/hand/right"); + HAND_TRACKER_LEFT_ID = PathStringToHash("/user/hand_tracker/left"); + HAND_TRACKER_RIGHT_ID = PathStringToHash("/user/hand_tracker/right"); LEFT_CONTROLLER_BUTTON_MAPPING.insert({ PathStringToHash("/user/hand/left/input/system/click"), { { "/input/system/click" }, ButtonType::Binary } }); diff --git a/alvr/server/cpp/alvr_server/Paths.h b/alvr/server_openvr/cpp/alvr_server/Paths.h similarity index 95% rename from alvr/server/cpp/alvr_server/Paths.h rename to alvr/server_openvr/cpp/alvr_server/Paths.h index 55fccd8180..2297f3c5b4 100644 --- a/alvr/server/cpp/alvr_server/Paths.h +++ b/alvr/server_openvr/cpp/alvr_server/Paths.h @@ -9,6 +9,8 @@ extern uint64_t HEAD_ID; extern uint64_t HAND_LEFT_ID; extern uint64_t HAND_RIGHT_ID; +extern uint64_t HAND_TRACKER_LEFT_ID; +extern uint64_t HAND_TRACKER_RIGHT_ID; enum class ButtonType { Binary, diff --git a/alvr/server/cpp/alvr_server/PoseHistory.cpp b/alvr/server_openvr/cpp/alvr_server/PoseHistory.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/PoseHistory.cpp rename to alvr/server_openvr/cpp/alvr_server/PoseHistory.cpp diff --git a/alvr/server/cpp/alvr_server/PoseHistory.h b/alvr/server_openvr/cpp/alvr_server/PoseHistory.h similarity index 100% rename from alvr/server/cpp/alvr_server/PoseHistory.h rename to alvr/server_openvr/cpp/alvr_server/PoseHistory.h diff --git a/alvr/server/cpp/alvr_server/Settings.cpp b/alvr/server_openvr/cpp/alvr_server/Settings.cpp similarity index 98% rename from alvr/server/cpp/alvr_server/Settings.cpp rename to alvr/server_openvr/cpp/alvr_server/Settings.cpp index 2ffec2447e..da6c3149a8 100644 --- a/alvr/server/cpp/alvr_server/Settings.cpp +++ b/alvr/server_openvr/cpp/alvr_server/Settings.cpp @@ -118,6 +118,8 @@ void Settings::Load() { m_enableBodyTrackingFakeVive = config.get("body_tracking_vive_enabled").get(); m_bodyTrackingHasLegs = config.get("body_tracking_has_legs").get(); + m_useSeparateHandTrackers = config.get("use_separate_hand_trackers").get(); + Info("Render Target: %d %d\n", m_renderWidth, m_renderHeight); Info("Refresh Rate: %d\n", m_refreshRate); m_loaded = true; diff --git a/alvr/server/cpp/alvr_server/Settings.h b/alvr/server_openvr/cpp/alvr_server/Settings.h similarity index 98% rename from alvr/server/cpp/alvr_server/Settings.h rename to alvr/server_openvr/cpp/alvr_server/Settings.h index ae30d95aa7..b1724a0791 100644 --- a/alvr/server/cpp/alvr_server/Settings.h +++ b/alvr/server_openvr/cpp/alvr_server/Settings.h @@ -91,4 +91,5 @@ class Settings { int m_controllerIsTracker = false; int m_enableBodyTrackingFakeVive = false; int m_bodyTrackingHasLegs = false; + bool m_useSeparateHandTrackers = false; }; diff --git a/alvr/server/cpp/alvr_server/TrackedDevice.cpp b/alvr/server_openvr/cpp/alvr_server/TrackedDevice.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/TrackedDevice.cpp rename to alvr/server_openvr/cpp/alvr_server/TrackedDevice.cpp diff --git a/alvr/server/cpp/alvr_server/TrackedDevice.h b/alvr/server_openvr/cpp/alvr_server/TrackedDevice.h similarity index 100% rename from alvr/server/cpp/alvr_server/TrackedDevice.h rename to alvr/server_openvr/cpp/alvr_server/TrackedDevice.h diff --git a/alvr/server/cpp/alvr_server/Utils.h b/alvr/server_openvr/cpp/alvr_server/Utils.h similarity index 100% rename from alvr/server/cpp/alvr_server/Utils.h rename to alvr/server_openvr/cpp/alvr_server/Utils.h diff --git a/alvr/server/cpp/alvr_server/ViveTrackerProxy.cpp b/alvr/server_openvr/cpp/alvr_server/ViveTrackerProxy.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/ViveTrackerProxy.cpp rename to alvr/server_openvr/cpp/alvr_server/ViveTrackerProxy.cpp diff --git a/alvr/server/cpp/alvr_server/ViveTrackerProxy.h b/alvr/server_openvr/cpp/alvr_server/ViveTrackerProxy.h similarity index 100% rename from alvr/server/cpp/alvr_server/ViveTrackerProxy.h rename to alvr/server_openvr/cpp/alvr_server/ViveTrackerProxy.h diff --git a/alvr/server/cpp/alvr_server/alvr_server.cpp b/alvr/server_openvr/cpp/alvr_server/alvr_server.cpp similarity index 76% rename from alvr/server/cpp/alvr_server/alvr_server.cpp rename to alvr/server_openvr/cpp/alvr_server/alvr_server.cpp index fb9e0b64f7..62c94ef68a 100644 --- a/alvr/server/cpp/alvr_server/alvr_server.cpp +++ b/alvr/server_openvr/cpp/alvr_server/alvr_server.cpp @@ -81,6 +81,7 @@ class DriverProvider : public vr::IServerTrackedDeviceProvider { public: std::unique_ptr hmd; std::unique_ptr left_controller, right_controller; + std::unique_ptr left_hand_tracker, right_hand_tracker; std::vector> generic_trackers; bool shutdown_called = false; @@ -100,8 +101,13 @@ class DriverProvider : public vr::IServerTrackedDeviceProvider { } if (Settings::Instance().m_enableControllers) { - this->left_controller = std::make_unique(HAND_LEFT_ID); - this->right_controller = std::make_unique(HAND_RIGHT_ID); + auto controllerSkeletonLevel = Settings::Instance().m_useSeparateHandTrackers + ? vr::VRSkeletalTracking_Estimated + : vr::VRSkeletalTracking_Partial; + this->left_controller + = std::make_unique(HAND_LEFT_ID, controllerSkeletonLevel); + this->right_controller + = std::make_unique(HAND_RIGHT_ID, controllerSkeletonLevel); this->tracked_devices.insert({ HAND_LEFT_ID, (TrackedDevice*)this->left_controller.get() }); @@ -122,6 +128,35 @@ class DriverProvider : public vr::IServerTrackedDeviceProvider { )) { Warn("Failed to register right controller"); } + + if (Settings::Instance().m_useSeparateHandTrackers) { + this->left_hand_tracker = std::make_unique( + HAND_TRACKER_LEFT_ID, vr::VRSkeletalTracking_Full + ); + this->right_hand_tracker = std::make_unique( + HAND_TRACKER_RIGHT_ID, vr::VRSkeletalTracking_Full + ); + + this->tracked_devices.insert({ HAND_TRACKER_LEFT_ID, + (TrackedDevice*)this->left_hand_tracker.get() }); + this->tracked_devices.insert({ HAND_TRACKER_RIGHT_ID, + (TrackedDevice*)this->right_hand_tracker.get() }); + + if (!vr::VRServerDriverHost()->TrackedDeviceAdded( + this->left_hand_tracker->get_serial_number().c_str(), + this->left_hand_tracker->getControllerDeviceClass(), + this->left_hand_tracker.get() + )) { + Warn("Failed to register left full skeletal controller"); + } + if (!vr::VRServerDriverHost()->TrackedDeviceAdded( + this->right_hand_tracker->get_serial_number().c_str(), + this->right_hand_tracker->getControllerDeviceClass(), + this->right_hand_tracker.get() + )) { + Warn("Failed to register right full skeletal controller"); + } + } } if (Settings::Instance().m_enableBodyTrackingFakeVive) { @@ -211,6 +246,8 @@ class DriverProvider : public vr::IServerTrackedDeviceProvider { return vr::VRInitError_None; } virtual void Cleanup() override { + this->left_hand_tracker.reset(); + this->right_hand_tracker.reset(); this->left_controller.reset(); this->right_controller.reset(); this->hmd.reset(); @@ -362,9 +399,11 @@ void SetTracking( float controllerPoseTimeOffsetS, const FfiDeviceMotion* deviceMotions, int motionsCount, - const FfiHandSkeleton* leftHand, - const FfiHandSkeleton* rightHand, unsigned int controllersTracked, + bool useLeftHandTracker, + bool useRightHandTracker, + const FfiHandSkeleton* leftHandSkeleton, + const FfiHandSkeleton* rightHandSkeleton, const FfiBodyTracker* bodyTrackers, int bodyTrackersCount ) { @@ -372,15 +411,40 @@ void SetTracking( if (deviceMotions[i].deviceID == HEAD_ID && g_driver_provider.hmd) { g_driver_provider.hmd->OnPoseUpdated(targetTimestampNs, deviceMotions[i]); } else { - if (g_driver_provider.left_controller && deviceMotions[i].deviceID == HAND_LEFT_ID) { - g_driver_provider.left_controller->onPoseUpdate( - controllerPoseTimeOffsetS, deviceMotions[i], leftHand, controllersTracked - ); - } else if (g_driver_provider.right_controller - && deviceMotions[i].deviceID == HAND_RIGHT_ID) { - g_driver_provider.right_controller->onPoseUpdate( - controllerPoseTimeOffsetS, deviceMotions[i], rightHand, controllersTracked - ); + if (deviceMotions[i].deviceID == HAND_LEFT_ID) { + if (g_driver_provider.left_controller) { + g_driver_provider.left_controller->onPoseUpdate( + controllerPoseTimeOffsetS, + deviceMotions[i], + leftHandSkeleton, + controllersTracked && !useLeftHandTracker + ); + } + if (g_driver_provider.left_hand_tracker) { + g_driver_provider.left_hand_tracker->onPoseUpdate( + controllerPoseTimeOffsetS, + deviceMotions[i], + leftHandSkeleton, + controllersTracked && useLeftHandTracker + ); + } + } else if (deviceMotions[i].deviceID == HAND_RIGHT_ID) { + if (g_driver_provider.right_controller) { + g_driver_provider.right_controller->onPoseUpdate( + controllerPoseTimeOffsetS, + deviceMotions[i], + rightHandSkeleton, + controllersTracked && !useRightHandTracker + ); + } + if (g_driver_provider.right_hand_tracker) { + g_driver_provider.right_hand_tracker->onPoseUpdate( + controllerPoseTimeOffsetS, + deviceMotions[i], + rightHandSkeleton, + controllersTracked && useRightHandTracker + ); + } } } } @@ -422,14 +486,11 @@ void SetOpenvrProperty(unsigned long long deviceID, FfiOpenvrProperty prop) { } } -void RegisterButton(unsigned long long buttonID) { - if (g_driver_provider.left_controller - && LEFT_CONTROLLER_BUTTON_MAPPING.find(buttonID) != LEFT_CONTROLLER_BUTTON_MAPPING.end()) { - g_driver_provider.left_controller->RegisterButton(buttonID); - } else if (g_driver_provider.right_controller - && RIGHT_CONTROLLER_BUTTON_MAPPING.find(buttonID) - != RIGHT_CONTROLLER_BUTTON_MAPPING.end()) { - g_driver_provider.right_controller->RegisterButton(buttonID); +void RegisterButton(unsigned long long deviceID, unsigned long long buttonID) { + auto device_it = g_driver_provider.tracked_devices.find(deviceID); + if (device_it != g_driver_provider.tracked_devices.end()) { + // Todo: move RegisterButton to generic TrackedDevice interface + ((Controller*)device_it->second)->RegisterButton(buttonID); } } @@ -453,13 +514,21 @@ void SetBattery(unsigned long long deviceID, float gauge_value, bool is_plugged) } void SetButton(unsigned long long buttonID, FfiButtonValue value) { - if (g_driver_provider.left_controller - && LEFT_CONTROLLER_BUTTON_MAPPING.find(buttonID) != LEFT_CONTROLLER_BUTTON_MAPPING.end()) { - g_driver_provider.left_controller->SetButton(buttonID, value); - } else if (g_driver_provider.right_controller - && RIGHT_CONTROLLER_BUTTON_MAPPING.find(buttonID) - != RIGHT_CONTROLLER_BUTTON_MAPPING.end()) { - g_driver_provider.right_controller->SetButton(buttonID, value); + if (LEFT_CONTROLLER_BUTTON_MAPPING.find(buttonID) != LEFT_CONTROLLER_BUTTON_MAPPING.end()) { + if (g_driver_provider.left_controller) { + g_driver_provider.left_controller->SetButton(buttonID, value); + } + if (g_driver_provider.left_hand_tracker) { + g_driver_provider.left_hand_tracker->SetButton(buttonID, value); + } + } else if (RIGHT_CONTROLLER_BUTTON_MAPPING.find(buttonID) + != RIGHT_CONTROLLER_BUTTON_MAPPING.end()) { + if (g_driver_provider.right_controller) { + g_driver_provider.right_controller->SetButton(buttonID, value); + } + if (g_driver_provider.right_hand_tracker) { + g_driver_provider.right_hand_tracker->SetButton(buttonID, value); + } } } diff --git a/alvr/server/cpp/alvr_server/bindings.h b/alvr/server_openvr/cpp/alvr_server/bindings.h similarity index 97% rename from alvr/server/cpp/alvr_server/bindings.h rename to alvr/server_openvr/cpp/alvr_server/bindings.h index f70bd7d6d9..b814ebda60 100644 --- a/alvr/server/cpp/alvr_server/bindings.h +++ b/alvr/server_openvr/cpp/alvr_server/bindings.h @@ -143,9 +143,11 @@ extern "C" void SetTracking( float controllerPoseTimeOffsetS, const FfiDeviceMotion* deviceMotions, int motionsCount, + unsigned int controllersTracked, + bool useLeftHandTracker, + bool useRightHandTracker, const FfiHandSkeleton* leftHand, const FfiHandSkeleton* rightHand, - unsigned int controllersTracked, const FfiBodyTracker* bodyTrackers, int bodyTrackersCount ); @@ -154,7 +156,7 @@ extern "C" void RequestDriverResync(); extern "C" void ShutdownSteamvr(); extern "C" void SetOpenvrProperty(unsigned long long deviceID, FfiOpenvrProperty prop); -extern "C" void RegisterButton(unsigned long long buttonID); +extern "C" void RegisterButton(unsigned long long deviceID, unsigned long long buttonID); extern "C" void SetViewsConfig(FfiViewsConfig config); extern "C" void SetBattery(unsigned long long deviceID, float gauge_value, bool is_plugged); extern "C" void SetButton(unsigned long long buttonID, FfiButtonValue value); diff --git a/alvr/server/cpp/alvr_server/driverlog.cpp b/alvr/server_openvr/cpp/alvr_server/driverlog.cpp similarity index 100% rename from alvr/server/cpp/alvr_server/driverlog.cpp rename to alvr/server_openvr/cpp/alvr_server/driverlog.cpp diff --git a/alvr/server/cpp/alvr_server/driverlog.h b/alvr/server_openvr/cpp/alvr_server/driverlog.h similarity index 100% rename from alvr/server/cpp/alvr_server/driverlog.h rename to alvr/server_openvr/cpp/alvr_server/driverlog.h diff --git a/alvr/server/cpp/alvr_server/include/openvr_math.h b/alvr/server_openvr/cpp/alvr_server/include/openvr_math.h similarity index 100% rename from alvr/server/cpp/alvr_server/include/openvr_math.h rename to alvr/server_openvr/cpp/alvr_server/include/openvr_math.h diff --git a/alvr/server/cpp/alvr_server/include/picojson.h b/alvr/server_openvr/cpp/alvr_server/include/picojson.h similarity index 100% rename from alvr/server/cpp/alvr_server/include/picojson.h rename to alvr/server_openvr/cpp/alvr_server/include/picojson.h diff --git a/alvr/server/cpp/alvr_server/nvEncodeAPI.h b/alvr/server_openvr/cpp/alvr_server/nvEncodeAPI.h similarity index 100% rename from alvr/server/cpp/alvr_server/nvEncodeAPI.h rename to alvr/server_openvr/cpp/alvr_server/nvEncodeAPI.h diff --git a/alvr/server/cpp/alvr_server/shader/ColorCorrectionPixelShader.hlsl b/alvr/server_openvr/cpp/alvr_server/shader/ColorCorrectionPixelShader.hlsl similarity index 100% rename from alvr/server/cpp/alvr_server/shader/ColorCorrectionPixelShader.hlsl rename to alvr/server_openvr/cpp/alvr_server/shader/ColorCorrectionPixelShader.hlsl diff --git a/alvr/server/cpp/alvr_server/shader/CompressAxisAlignedPixelShader.hlsl b/alvr/server_openvr/cpp/alvr_server/shader/CompressAxisAlignedPixelShader.hlsl similarity index 100% rename from alvr/server/cpp/alvr_server/shader/CompressAxisAlignedPixelShader.hlsl rename to alvr/server_openvr/cpp/alvr_server/shader/CompressAxisAlignedPixelShader.hlsl diff --git a/alvr/server/cpp/alvr_server/shader/FoveatedRendering.hlsli b/alvr/server_openvr/cpp/alvr_server/shader/FoveatedRendering.hlsli similarity index 100% rename from alvr/server/cpp/alvr_server/shader/FoveatedRendering.hlsli rename to alvr/server_openvr/cpp/alvr_server/shader/FoveatedRendering.hlsli diff --git a/alvr/server/cpp/alvr_server/shader/FrameRender.fx b/alvr/server_openvr/cpp/alvr_server/shader/FrameRender.fx similarity index 100% rename from alvr/server/cpp/alvr_server/shader/FrameRender.fx rename to alvr/server_openvr/cpp/alvr_server/shader/FrameRender.fx diff --git a/alvr/server/cpp/alvr_server/shader/FrameRenderPS.hlsl b/alvr/server_openvr/cpp/alvr_server/shader/FrameRenderPS.hlsl similarity index 100% rename from alvr/server/cpp/alvr_server/shader/FrameRenderPS.hlsl rename to alvr/server_openvr/cpp/alvr_server/shader/FrameRenderPS.hlsl diff --git a/alvr/server/cpp/alvr_server/shader/FrameRenderVS.hlsl b/alvr/server_openvr/cpp/alvr_server/shader/FrameRenderVS.hlsl similarity index 100% rename from alvr/server/cpp/alvr_server/shader/FrameRenderVS.hlsl rename to alvr/server_openvr/cpp/alvr_server/shader/FrameRenderVS.hlsl diff --git a/alvr/server/cpp/alvr_server/shader/rgbtoyuv420.hlsl b/alvr/server_openvr/cpp/alvr_server/shader/rgbtoyuv420.hlsl similarity index 100% rename from alvr/server/cpp/alvr_server/shader/rgbtoyuv420.hlsl rename to alvr/server_openvr/cpp/alvr_server/shader/rgbtoyuv420.hlsl diff --git a/alvr/server/cpp/bin/.gitignore b/alvr/server_openvr/cpp/bin/.gitignore similarity index 100% rename from alvr/server/cpp/bin/.gitignore rename to alvr/server_openvr/cpp/bin/.gitignore diff --git a/alvr/server/cpp/bin/windows/vcruntime140_1.dll b/alvr/server_openvr/cpp/bin/windows/vcruntime140_1.dll similarity index 100% rename from alvr/server/cpp/bin/windows/vcruntime140_1.dll rename to alvr/server_openvr/cpp/bin/windows/vcruntime140_1.dll diff --git a/alvr/server/cpp/platform/linux/CEncoder.cpp b/alvr/server_openvr/cpp/platform/linux/CEncoder.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/CEncoder.cpp rename to alvr/server_openvr/cpp/platform/linux/CEncoder.cpp diff --git a/alvr/server/cpp/platform/linux/CEncoder.h b/alvr/server_openvr/cpp/platform/linux/CEncoder.h similarity index 100% rename from alvr/server/cpp/platform/linux/CEncoder.h rename to alvr/server_openvr/cpp/platform/linux/CEncoder.h diff --git a/alvr/server/cpp/platform/linux/CrashHandler.cpp b/alvr/server_openvr/cpp/platform/linux/CrashHandler.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/CrashHandler.cpp rename to alvr/server_openvr/cpp/platform/linux/CrashHandler.cpp diff --git a/alvr/server/cpp/platform/linux/EncodePipeline.cpp b/alvr/server_openvr/cpp/platform/linux/EncodePipeline.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipeline.cpp rename to alvr/server_openvr/cpp/platform/linux/EncodePipeline.cpp diff --git a/alvr/server/cpp/platform/linux/EncodePipeline.h b/alvr/server_openvr/cpp/platform/linux/EncodePipeline.h similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipeline.h rename to alvr/server_openvr/cpp/platform/linux/EncodePipeline.h diff --git a/alvr/server/cpp/platform/linux/EncodePipelineNvEnc.cpp b/alvr/server_openvr/cpp/platform/linux/EncodePipelineNvEnc.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipelineNvEnc.cpp rename to alvr/server_openvr/cpp/platform/linux/EncodePipelineNvEnc.cpp diff --git a/alvr/server/cpp/platform/linux/EncodePipelineNvEnc.h b/alvr/server_openvr/cpp/platform/linux/EncodePipelineNvEnc.h similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipelineNvEnc.h rename to alvr/server_openvr/cpp/platform/linux/EncodePipelineNvEnc.h diff --git a/alvr/server/cpp/platform/linux/EncodePipelineSW.cpp b/alvr/server_openvr/cpp/platform/linux/EncodePipelineSW.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipelineSW.cpp rename to alvr/server_openvr/cpp/platform/linux/EncodePipelineSW.cpp diff --git a/alvr/server/cpp/platform/linux/EncodePipelineSW.h b/alvr/server_openvr/cpp/platform/linux/EncodePipelineSW.h similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipelineSW.h rename to alvr/server_openvr/cpp/platform/linux/EncodePipelineSW.h diff --git a/alvr/server/cpp/platform/linux/EncodePipelineVAAPI.cpp b/alvr/server_openvr/cpp/platform/linux/EncodePipelineVAAPI.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipelineVAAPI.cpp rename to alvr/server_openvr/cpp/platform/linux/EncodePipelineVAAPI.cpp diff --git a/alvr/server/cpp/platform/linux/EncodePipelineVAAPI.h b/alvr/server_openvr/cpp/platform/linux/EncodePipelineVAAPI.h similarity index 100% rename from alvr/server/cpp/platform/linux/EncodePipelineVAAPI.h rename to alvr/server_openvr/cpp/platform/linux/EncodePipelineVAAPI.h diff --git a/alvr/server/cpp/platform/linux/FormatConverter.cpp b/alvr/server_openvr/cpp/platform/linux/FormatConverter.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/FormatConverter.cpp rename to alvr/server_openvr/cpp/platform/linux/FormatConverter.cpp diff --git a/alvr/server/cpp/platform/linux/FormatConverter.h b/alvr/server_openvr/cpp/platform/linux/FormatConverter.h similarity index 100% rename from alvr/server/cpp/platform/linux/FormatConverter.h rename to alvr/server_openvr/cpp/platform/linux/FormatConverter.h diff --git a/alvr/server/cpp/platform/linux/FrameRender.cpp b/alvr/server_openvr/cpp/platform/linux/FrameRender.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/FrameRender.cpp rename to alvr/server_openvr/cpp/platform/linux/FrameRender.cpp diff --git a/alvr/server/cpp/platform/linux/FrameRender.h b/alvr/server_openvr/cpp/platform/linux/FrameRender.h similarity index 100% rename from alvr/server/cpp/platform/linux/FrameRender.h rename to alvr/server_openvr/cpp/platform/linux/FrameRender.h diff --git a/alvr/server/cpp/platform/linux/Renderer.cpp b/alvr/server_openvr/cpp/platform/linux/Renderer.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/Renderer.cpp rename to alvr/server_openvr/cpp/platform/linux/Renderer.cpp diff --git a/alvr/server/cpp/platform/linux/Renderer.h b/alvr/server_openvr/cpp/platform/linux/Renderer.h similarity index 100% rename from alvr/server/cpp/platform/linux/Renderer.h rename to alvr/server_openvr/cpp/platform/linux/Renderer.h diff --git a/alvr/server/cpp/platform/linux/ffmpeg_helper.cpp b/alvr/server_openvr/cpp/platform/linux/ffmpeg_helper.cpp similarity index 100% rename from alvr/server/cpp/platform/linux/ffmpeg_helper.cpp rename to alvr/server_openvr/cpp/platform/linux/ffmpeg_helper.cpp diff --git a/alvr/server/cpp/platform/linux/ffmpeg_helper.h b/alvr/server_openvr/cpp/platform/linux/ffmpeg_helper.h similarity index 100% rename from alvr/server/cpp/platform/linux/ffmpeg_helper.h rename to alvr/server_openvr/cpp/platform/linux/ffmpeg_helper.h diff --git a/alvr/server/cpp/platform/linux/protocol.h b/alvr/server_openvr/cpp/platform/linux/protocol.h similarity index 100% rename from alvr/server/cpp/platform/linux/protocol.h rename to alvr/server_openvr/cpp/platform/linux/protocol.h diff --git a/alvr/server/cpp/platform/linux/shader/color.comp b/alvr/server_openvr/cpp/platform/linux/shader/color.comp similarity index 100% rename from alvr/server/cpp/platform/linux/shader/color.comp rename to alvr/server_openvr/cpp/platform/linux/shader/color.comp diff --git a/alvr/server/cpp/platform/linux/shader/color.comp.spv b/alvr/server_openvr/cpp/platform/linux/shader/color.comp.spv similarity index 100% rename from alvr/server/cpp/platform/linux/shader/color.comp.spv rename to alvr/server_openvr/cpp/platform/linux/shader/color.comp.spv diff --git a/alvr/server/cpp/platform/linux/shader/ffr.comp b/alvr/server_openvr/cpp/platform/linux/shader/ffr.comp similarity index 100% rename from alvr/server/cpp/platform/linux/shader/ffr.comp rename to alvr/server_openvr/cpp/platform/linux/shader/ffr.comp diff --git a/alvr/server/cpp/platform/linux/shader/ffr.comp.spv b/alvr/server_openvr/cpp/platform/linux/shader/ffr.comp.spv similarity index 100% rename from alvr/server/cpp/platform/linux/shader/ffr.comp.spv rename to alvr/server_openvr/cpp/platform/linux/shader/ffr.comp.spv diff --git a/alvr/server/cpp/platform/linux/shader/quad.comp b/alvr/server_openvr/cpp/platform/linux/shader/quad.comp similarity index 100% rename from alvr/server/cpp/platform/linux/shader/quad.comp rename to alvr/server_openvr/cpp/platform/linux/shader/quad.comp diff --git a/alvr/server/cpp/platform/linux/shader/quad.comp.spv b/alvr/server_openvr/cpp/platform/linux/shader/quad.comp.spv similarity index 100% rename from alvr/server/cpp/platform/linux/shader/quad.comp.spv rename to alvr/server_openvr/cpp/platform/linux/shader/quad.comp.spv diff --git a/alvr/server/cpp/platform/linux/shader/rgbtoyuv420.comp b/alvr/server_openvr/cpp/platform/linux/shader/rgbtoyuv420.comp similarity index 100% rename from alvr/server/cpp/platform/linux/shader/rgbtoyuv420.comp rename to alvr/server_openvr/cpp/platform/linux/shader/rgbtoyuv420.comp diff --git a/alvr/server/cpp/platform/linux/shader/rgbtoyuv420.comp.spv b/alvr/server_openvr/cpp/platform/linux/shader/rgbtoyuv420.comp.spv similarity index 100% rename from alvr/server/cpp/platform/linux/shader/rgbtoyuv420.comp.spv rename to alvr/server_openvr/cpp/platform/linux/shader/rgbtoyuv420.comp.spv diff --git a/alvr/server/cpp/platform/macos/CEncoder.h b/alvr/server_openvr/cpp/platform/macos/CEncoder.h similarity index 100% rename from alvr/server/cpp/platform/macos/CEncoder.h rename to alvr/server_openvr/cpp/platform/macos/CEncoder.h diff --git a/alvr/server/cpp/platform/macos/CrashHandler.cpp b/alvr/server_openvr/cpp/platform/macos/CrashHandler.cpp similarity index 100% rename from alvr/server/cpp/platform/macos/CrashHandler.cpp rename to alvr/server_openvr/cpp/platform/macos/CrashHandler.cpp diff --git a/alvr/server/cpp/platform/win32/CEncoder.cpp b/alvr/server_openvr/cpp/platform/win32/CEncoder.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/CEncoder.cpp rename to alvr/server_openvr/cpp/platform/win32/CEncoder.cpp diff --git a/alvr/server/cpp/platform/win32/CEncoder.h b/alvr/server_openvr/cpp/platform/win32/CEncoder.h similarity index 100% rename from alvr/server/cpp/platform/win32/CEncoder.h rename to alvr/server_openvr/cpp/platform/win32/CEncoder.h diff --git a/alvr/server/cpp/platform/win32/ColorCorrectionPixelShader.cso b/alvr/server_openvr/cpp/platform/win32/ColorCorrectionPixelShader.cso similarity index 100% rename from alvr/server/cpp/platform/win32/ColorCorrectionPixelShader.cso rename to alvr/server_openvr/cpp/platform/win32/ColorCorrectionPixelShader.cso diff --git a/alvr/server/cpp/platform/win32/CompressAxisAlignedPixelShader.cso b/alvr/server_openvr/cpp/platform/win32/CompressAxisAlignedPixelShader.cso similarity index 100% rename from alvr/server/cpp/platform/win32/CompressAxisAlignedPixelShader.cso rename to alvr/server_openvr/cpp/platform/win32/CompressAxisAlignedPixelShader.cso diff --git a/alvr/server/cpp/platform/win32/CrashHandler.cpp b/alvr/server_openvr/cpp/platform/win32/CrashHandler.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/CrashHandler.cpp rename to alvr/server_openvr/cpp/platform/win32/CrashHandler.cpp diff --git a/alvr/server/cpp/platform/win32/FFR.cpp b/alvr/server_openvr/cpp/platform/win32/FFR.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/FFR.cpp rename to alvr/server_openvr/cpp/platform/win32/FFR.cpp diff --git a/alvr/server/cpp/platform/win32/FFR.h b/alvr/server_openvr/cpp/platform/win32/FFR.h similarity index 100% rename from alvr/server/cpp/platform/win32/FFR.h rename to alvr/server_openvr/cpp/platform/win32/FFR.h diff --git a/alvr/server/cpp/platform/win32/FrameRender.cpp b/alvr/server_openvr/cpp/platform/win32/FrameRender.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/FrameRender.cpp rename to alvr/server_openvr/cpp/platform/win32/FrameRender.cpp diff --git a/alvr/server/cpp/platform/win32/FrameRender.h b/alvr/server_openvr/cpp/platform/win32/FrameRender.h similarity index 100% rename from alvr/server/cpp/platform/win32/FrameRender.h rename to alvr/server_openvr/cpp/platform/win32/FrameRender.h diff --git a/alvr/server/cpp/platform/win32/FrameRenderPS.cso b/alvr/server_openvr/cpp/platform/win32/FrameRenderPS.cso similarity index 100% rename from alvr/server/cpp/platform/win32/FrameRenderPS.cso rename to alvr/server_openvr/cpp/platform/win32/FrameRenderPS.cso diff --git a/alvr/server/cpp/platform/win32/FrameRenderVS.cso b/alvr/server_openvr/cpp/platform/win32/FrameRenderVS.cso similarity index 100% rename from alvr/server/cpp/platform/win32/FrameRenderVS.cso rename to alvr/server_openvr/cpp/platform/win32/FrameRenderVS.cso diff --git a/alvr/server/cpp/platform/win32/NvCodecUtils.h b/alvr/server_openvr/cpp/platform/win32/NvCodecUtils.h similarity index 100% rename from alvr/server/cpp/platform/win32/NvCodecUtils.h rename to alvr/server_openvr/cpp/platform/win32/NvCodecUtils.h diff --git a/alvr/server/cpp/platform/win32/NvEncoder.cpp b/alvr/server_openvr/cpp/platform/win32/NvEncoder.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/NvEncoder.cpp rename to alvr/server_openvr/cpp/platform/win32/NvEncoder.cpp diff --git a/alvr/server/cpp/platform/win32/NvEncoder.h b/alvr/server_openvr/cpp/platform/win32/NvEncoder.h similarity index 100% rename from alvr/server/cpp/platform/win32/NvEncoder.h rename to alvr/server_openvr/cpp/platform/win32/NvEncoder.h diff --git a/alvr/server/cpp/platform/win32/NvEncoderD3D11.cpp b/alvr/server_openvr/cpp/platform/win32/NvEncoderD3D11.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/NvEncoderD3D11.cpp rename to alvr/server_openvr/cpp/platform/win32/NvEncoderD3D11.cpp diff --git a/alvr/server/cpp/platform/win32/NvEncoderD3D11.h b/alvr/server_openvr/cpp/platform/win32/NvEncoderD3D11.h similarity index 100% rename from alvr/server/cpp/platform/win32/NvEncoderD3D11.h rename to alvr/server_openvr/cpp/platform/win32/NvEncoderD3D11.h diff --git a/alvr/server/cpp/platform/win32/OvrDirectModeComponent.cpp b/alvr/server_openvr/cpp/platform/win32/OvrDirectModeComponent.cpp similarity index 98% rename from alvr/server/cpp/platform/win32/OvrDirectModeComponent.cpp rename to alvr/server_openvr/cpp/platform/win32/OvrDirectModeComponent.cpp index d038fc4024..cd290de970 100644 --- a/alvr/server/cpp/platform/win32/OvrDirectModeComponent.cpp +++ b/alvr/server_openvr/cpp/platform/win32/OvrDirectModeComponent.cpp @@ -37,7 +37,8 @@ void OvrDirectModeComponent::CreateSwapTextureSet( } SharedTextureDesc.ArraySize = 1; SharedTextureDesc.MipLevels = 1; - SharedTextureDesc.SampleDesc.Count = pSwapTextureSetDesc->nSampleCount; + SharedTextureDesc.SampleDesc.Count + = pSwapTextureSetDesc->nSampleCount == 0 ? 1 : pSwapTextureSetDesc->nSampleCount; SharedTextureDesc.SampleDesc.Quality = 0; SharedTextureDesc.Usage = D3D11_USAGE_DEFAULT; SharedTextureDesc.Format = format; diff --git a/alvr/server/cpp/platform/win32/OvrDirectModeComponent.h b/alvr/server_openvr/cpp/platform/win32/OvrDirectModeComponent.h similarity index 100% rename from alvr/server/cpp/platform/win32/OvrDirectModeComponent.h rename to alvr/server_openvr/cpp/platform/win32/OvrDirectModeComponent.h diff --git a/alvr/server/cpp/platform/win32/QuadVertexShader.cso b/alvr/server_openvr/cpp/platform/win32/QuadVertexShader.cso similarity index 100% rename from alvr/server/cpp/platform/win32/QuadVertexShader.cso rename to alvr/server_openvr/cpp/platform/win32/QuadVertexShader.cso diff --git a/alvr/server/cpp/platform/win32/VideoEncoder.cpp b/alvr/server_openvr/cpp/platform/win32/VideoEncoder.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoder.cpp rename to alvr/server_openvr/cpp/platform/win32/VideoEncoder.cpp diff --git a/alvr/server/cpp/platform/win32/VideoEncoder.h b/alvr/server_openvr/cpp/platform/win32/VideoEncoder.h similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoder.h rename to alvr/server_openvr/cpp/platform/win32/VideoEncoder.h diff --git a/alvr/server/cpp/platform/win32/VideoEncoderAMF.cpp b/alvr/server_openvr/cpp/platform/win32/VideoEncoderAMF.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoderAMF.cpp rename to alvr/server_openvr/cpp/platform/win32/VideoEncoderAMF.cpp diff --git a/alvr/server/cpp/platform/win32/VideoEncoderAMF.h b/alvr/server_openvr/cpp/platform/win32/VideoEncoderAMF.h similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoderAMF.h rename to alvr/server_openvr/cpp/platform/win32/VideoEncoderAMF.h diff --git a/alvr/server/cpp/platform/win32/VideoEncoderNVENC.cpp b/alvr/server_openvr/cpp/platform/win32/VideoEncoderNVENC.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoderNVENC.cpp rename to alvr/server_openvr/cpp/platform/win32/VideoEncoderNVENC.cpp diff --git a/alvr/server/cpp/platform/win32/VideoEncoderNVENC.h b/alvr/server_openvr/cpp/platform/win32/VideoEncoderNVENC.h similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoderNVENC.h rename to alvr/server_openvr/cpp/platform/win32/VideoEncoderNVENC.h diff --git a/alvr/server/cpp/platform/win32/VideoEncoderSW.cpp b/alvr/server_openvr/cpp/platform/win32/VideoEncoderSW.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoderSW.cpp rename to alvr/server_openvr/cpp/platform/win32/VideoEncoderSW.cpp diff --git a/alvr/server/cpp/platform/win32/VideoEncoderSW.h b/alvr/server_openvr/cpp/platform/win32/VideoEncoderSW.h similarity index 100% rename from alvr/server/cpp/platform/win32/VideoEncoderSW.h rename to alvr/server_openvr/cpp/platform/win32/VideoEncoderSW.h diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/QuadVertexShader.hlsl b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/QuadVertexShader.hlsl similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/QuadVertexShader.hlsl rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/QuadVertexShader.hlsl diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipeline.cpp b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipeline.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipeline.cpp rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipeline.cpp diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipeline.h b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipeline.h similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipeline.h rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipeline.h diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.cpp b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.cpp rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.cpp diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.h b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.h similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.h rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderPipelineYUV.h diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/RenderUtils.cpp b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderUtils.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/RenderUtils.cpp rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderUtils.cpp diff --git a/alvr/server/cpp/platform/win32/d3d-render-utils/RenderUtils.h b/alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderUtils.h similarity index 100% rename from alvr/server/cpp/platform/win32/d3d-render-utils/RenderUtils.h rename to alvr/server_openvr/cpp/platform/win32/d3d-render-utils/RenderUtils.h diff --git a/alvr/server/cpp/platform/win32/rgbtoyuv420.cso b/alvr/server_openvr/cpp/platform/win32/rgbtoyuv420.cso similarity index 100% rename from alvr/server/cpp/platform/win32/rgbtoyuv420.cso rename to alvr/server_openvr/cpp/platform/win32/rgbtoyuv420.cso diff --git a/alvr/server/cpp/platform/win32/shared/d3drender.cpp b/alvr/server_openvr/cpp/platform/win32/shared/d3drender.cpp similarity index 100% rename from alvr/server/cpp/platform/win32/shared/d3drender.cpp rename to alvr/server_openvr/cpp/platform/win32/shared/d3drender.cpp diff --git a/alvr/server/cpp/platform/win32/shared/d3drender.h b/alvr/server_openvr/cpp/platform/win32/shared/d3drender.h similarity index 100% rename from alvr/server/cpp/platform/win32/shared/d3drender.h rename to alvr/server_openvr/cpp/platform/win32/shared/d3drender.h diff --git a/alvr/server/cpp/shared/amf/public/common/AMFFactory.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/AMFFactory.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/AMFFactory.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/AMFFactory.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/AMFFactory.h b/alvr/server_openvr/cpp/shared/amf/public/common/AMFFactory.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/AMFFactory.h rename to alvr/server_openvr/cpp/shared/amf/public/common/AMFFactory.h diff --git a/alvr/server/cpp/shared/amf/public/common/AMFMath.h b/alvr/server_openvr/cpp/shared/amf/public/common/AMFMath.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/AMFMath.h rename to alvr/server_openvr/cpp/shared/amf/public/common/AMFMath.h diff --git a/alvr/server/cpp/shared/amf/public/common/AMFSTL.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/AMFSTL.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/AMFSTL.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/AMFSTL.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/AMFSTL.h b/alvr/server_openvr/cpp/shared/amf/public/common/AMFSTL.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/AMFSTL.h rename to alvr/server_openvr/cpp/shared/amf/public/common/AMFSTL.h diff --git a/alvr/server/cpp/shared/amf/public/common/ByteArray.h b/alvr/server_openvr/cpp/shared/amf/public/common/ByteArray.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/ByteArray.h rename to alvr/server_openvr/cpp/shared/amf/public/common/ByteArray.h diff --git a/alvr/server/cpp/shared/amf/public/common/CPUCaps.h b/alvr/server_openvr/cpp/shared/amf/public/common/CPUCaps.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/CPUCaps.h rename to alvr/server_openvr/cpp/shared/amf/public/common/CPUCaps.h diff --git a/alvr/server/cpp/shared/amf/public/common/CurrentTimeImpl.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/CurrentTimeImpl.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/CurrentTimeImpl.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/CurrentTimeImpl.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/CurrentTimeImpl.h b/alvr/server_openvr/cpp/shared/amf/public/common/CurrentTimeImpl.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/CurrentTimeImpl.h rename to alvr/server_openvr/cpp/shared/amf/public/common/CurrentTimeImpl.h diff --git a/alvr/server/cpp/shared/amf/public/common/DataStream.h b/alvr/server_openvr/cpp/shared/amf/public/common/DataStream.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/DataStream.h rename to alvr/server_openvr/cpp/shared/amf/public/common/DataStream.h diff --git a/alvr/server/cpp/shared/amf/public/common/DataStreamFactory.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/DataStreamFactory.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/DataStreamFactory.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/DataStreamFactory.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/DataStreamFile.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/DataStreamFile.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/DataStreamFile.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/DataStreamFile.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/DataStreamFile.h b/alvr/server_openvr/cpp/shared/amf/public/common/DataStreamFile.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/DataStreamFile.h rename to alvr/server_openvr/cpp/shared/amf/public/common/DataStreamFile.h diff --git a/alvr/server/cpp/shared/amf/public/common/DataStreamMemory.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/DataStreamMemory.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/DataStreamMemory.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/DataStreamMemory.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/DataStreamMemory.h b/alvr/server_openvr/cpp/shared/amf/public/common/DataStreamMemory.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/DataStreamMemory.h rename to alvr/server_openvr/cpp/shared/amf/public/common/DataStreamMemory.h diff --git a/alvr/server/cpp/shared/amf/public/common/IOCapsImpl.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/IOCapsImpl.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/IOCapsImpl.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/IOCapsImpl.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/IOCapsImpl.h b/alvr/server_openvr/cpp/shared/amf/public/common/IOCapsImpl.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/IOCapsImpl.h rename to alvr/server_openvr/cpp/shared/amf/public/common/IOCapsImpl.h diff --git a/alvr/server/cpp/shared/amf/public/common/InterfaceImpl.h b/alvr/server_openvr/cpp/shared/amf/public/common/InterfaceImpl.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/InterfaceImpl.h rename to alvr/server_openvr/cpp/shared/amf/public/common/InterfaceImpl.h diff --git a/alvr/server/cpp/shared/amf/public/common/ObservableImpl.h b/alvr/server_openvr/cpp/shared/amf/public/common/ObservableImpl.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/ObservableImpl.h rename to alvr/server_openvr/cpp/shared/amf/public/common/ObservableImpl.h diff --git a/alvr/server/cpp/shared/amf/public/common/PropertyStorageExImpl.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/PropertyStorageExImpl.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/PropertyStorageExImpl.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/PropertyStorageExImpl.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/PropertyStorageExImpl.h b/alvr/server_openvr/cpp/shared/amf/public/common/PropertyStorageExImpl.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/PropertyStorageExImpl.h rename to alvr/server_openvr/cpp/shared/amf/public/common/PropertyStorageExImpl.h diff --git a/alvr/server/cpp/shared/amf/public/common/PropertyStorageImpl.h b/alvr/server_openvr/cpp/shared/amf/public/common/PropertyStorageImpl.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/PropertyStorageImpl.h rename to alvr/server_openvr/cpp/shared/amf/public/common/PropertyStorageImpl.h diff --git a/alvr/server/cpp/shared/amf/public/common/Thread.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/Thread.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/Thread.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/Thread.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/Thread.h b/alvr/server_openvr/cpp/shared/amf/public/common/Thread.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/Thread.h rename to alvr/server_openvr/cpp/shared/amf/public/common/Thread.h diff --git a/alvr/server/cpp/shared/amf/public/common/TraceAdapter.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/TraceAdapter.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/TraceAdapter.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/TraceAdapter.cpp diff --git a/alvr/server/cpp/shared/amf/public/common/TraceAdapter.h b/alvr/server_openvr/cpp/shared/amf/public/common/TraceAdapter.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/TraceAdapter.h rename to alvr/server_openvr/cpp/shared/amf/public/common/TraceAdapter.h diff --git a/alvr/server/cpp/shared/amf/public/common/Windows/ThreadWindows.cpp b/alvr/server_openvr/cpp/shared/amf/public/common/Windows/ThreadWindows.cpp similarity index 100% rename from alvr/server/cpp/shared/amf/public/common/Windows/ThreadWindows.cpp rename to alvr/server_openvr/cpp/shared/amf/public/common/Windows/ThreadWindows.cpp diff --git a/alvr/server/cpp/shared/amf/public/include/components/Ambisonic2SRenderer.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/Ambisonic2SRenderer.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/Ambisonic2SRenderer.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/Ambisonic2SRenderer.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/AudioCapture.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/AudioCapture.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/AudioCapture.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/AudioCapture.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/Capture.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/Capture.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/Capture.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/Capture.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/ChromaKey.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/ChromaKey.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/ChromaKey.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/ChromaKey.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/ColorSpace.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/ColorSpace.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/ColorSpace.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/ColorSpace.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/Component.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/Component.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/Component.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/Component.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/ComponentCaps.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/ComponentCaps.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/ComponentCaps.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/ComponentCaps.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/CursorCapture.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/CursorCapture.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/CursorCapture.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/CursorCapture.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/DisplayCapture.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/DisplayCapture.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/DisplayCapture.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/DisplayCapture.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGAudioConverter.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGAudioConverter.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGAudioConverter.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGAudioConverter.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGAudioDecoder.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGAudioDecoder.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGAudioDecoder.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGAudioDecoder.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGAudioEncoder.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGAudioEncoder.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGAudioEncoder.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGAudioEncoder.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGComponents.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGComponents.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGComponents.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGComponents.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGEncoderAV1.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGEncoderAV1.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGEncoderAV1.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGEncoderAV1.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGEncoderH264.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGEncoderH264.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGEncoderH264.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGEncoderH264.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGEncoderHEVC.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGEncoderHEVC.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGEncoderHEVC.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGEncoderHEVC.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGFileDemuxer.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGFileDemuxer.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGFileDemuxer.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGFileDemuxer.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGFileMuxer.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGFileMuxer.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGFileMuxer.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGFileMuxer.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FFMPEGVideoDecoder.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGVideoDecoder.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FFMPEGVideoDecoder.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FFMPEGVideoDecoder.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/FRC.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/FRC.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/FRC.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/FRC.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/HQScaler.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/HQScaler.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/HQScaler.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/HQScaler.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/MediaSource.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/MediaSource.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/MediaSource.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/MediaSource.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/PreAnalysis.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/PreAnalysis.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/PreAnalysis.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/PreAnalysis.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/PreProcessing.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/PreProcessing.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/PreProcessing.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/PreProcessing.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/SupportedCodecs.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/SupportedCodecs.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/SupportedCodecs.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/SupportedCodecs.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VQEnhancer.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VQEnhancer.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VQEnhancer.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VQEnhancer.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoCapture.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoCapture.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoCapture.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoCapture.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoConverter.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoConverter.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoConverter.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoConverter.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoDecoderUVD.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoDecoderUVD.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoDecoderUVD.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoDecoderUVD.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoEncoderAV1.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoEncoderAV1.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoEncoderAV1.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoEncoderAV1.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoEncoderHEVC.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoEncoderHEVC.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoEncoderHEVC.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoEncoderHEVC.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoEncoderVCE.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoEncoderVCE.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoEncoderVCE.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoEncoderVCE.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/VideoStitch.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/VideoStitch.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/VideoStitch.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/VideoStitch.h diff --git a/alvr/server/cpp/shared/amf/public/include/components/ZCamLiveStream.h b/alvr/server_openvr/cpp/shared/amf/public/include/components/ZCamLiveStream.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/components/ZCamLiveStream.h rename to alvr/server_openvr/cpp/shared/amf/public/include/components/ZCamLiveStream.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/AudioBuffer.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/AudioBuffer.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/AudioBuffer.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/AudioBuffer.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Buffer.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Buffer.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Buffer.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Buffer.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Compute.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Compute.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Compute.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Compute.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/ComputeFactory.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/ComputeFactory.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/ComputeFactory.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/ComputeFactory.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Context.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Context.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Context.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Context.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/CurrentTime.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/CurrentTime.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/CurrentTime.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/CurrentTime.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/D3D12AMF.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/D3D12AMF.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/D3D12AMF.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/D3D12AMF.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Data.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Data.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Data.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Data.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Debug.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Debug.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Debug.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Debug.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Dump.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Dump.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Dump.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Dump.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Factory.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Factory.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Factory.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Factory.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Interface.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Interface.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Interface.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Interface.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Plane.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Plane.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Plane.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Plane.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Platform.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Platform.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Platform.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Platform.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/PropertyStorage.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/PropertyStorage.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/PropertyStorage.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/PropertyStorage.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/PropertyStorageEx.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/PropertyStorageEx.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/PropertyStorageEx.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/PropertyStorageEx.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Result.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Result.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Result.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Result.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Surface.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Surface.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Surface.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Surface.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Trace.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Trace.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Trace.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Trace.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Variant.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Variant.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Variant.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Variant.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/Version.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/Version.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/Version.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/Version.h diff --git a/alvr/server/cpp/shared/amf/public/include/core/VulkanAMF.h b/alvr/server_openvr/cpp/shared/amf/public/include/core/VulkanAMF.h similarity index 100% rename from alvr/server/cpp/shared/amf/public/include/core/VulkanAMF.h rename to alvr/server_openvr/cpp/shared/amf/public/include/core/VulkanAMF.h diff --git a/alvr/server/cpp/shared/backward.cpp b/alvr/server_openvr/cpp/shared/backward.cpp similarity index 100% rename from alvr/server/cpp/shared/backward.cpp rename to alvr/server_openvr/cpp/shared/backward.cpp diff --git a/alvr/server/cpp/shared/backward.hpp b/alvr/server_openvr/cpp/shared/backward.hpp similarity index 100% rename from alvr/server/cpp/shared/backward.hpp rename to alvr/server_openvr/cpp/shared/backward.hpp diff --git a/alvr/server/cpp/shared/threadtools.cpp b/alvr/server_openvr/cpp/shared/threadtools.cpp similarity index 100% rename from alvr/server/cpp/shared/threadtools.cpp rename to alvr/server_openvr/cpp/shared/threadtools.cpp diff --git a/alvr/server/cpp/shared/threadtools.h b/alvr/server_openvr/cpp/shared/threadtools.h similarity index 100% rename from alvr/server/cpp/shared/threadtools.h rename to alvr/server_openvr/cpp/shared/threadtools.h diff --git a/alvr/server/src/graphics.rs b/alvr/server_openvr/src/graphics.rs similarity index 100% rename from alvr/server/src/graphics.rs rename to alvr/server_openvr/src/graphics.rs diff --git a/alvr/server/src/openvr/mod.rs b/alvr/server_openvr/src/lib.rs similarity index 58% rename from alvr/server/src/openvr/mod.rs rename to alvr/server_openvr/src/lib.rs index 8e476f604a..58dbc0a3ca 100644 --- a/alvr/server/src/openvr/mod.rs +++ b/alvr/server_openvr/src/lib.rs @@ -1,34 +1,60 @@ +mod graphics; mod props; mod tracking; -use crate::{ - input_mapping, logging_backend, FfiButtonValue, FfiDynamicEncoderParams, FfiFov, - FfiViewsConfig, ServerCoreContext, ServerCoreEvent, SERVER_DATA_MANAGER, +#[allow( + non_camel_case_types, + non_upper_case_globals, + dead_code, + non_snake_case, + clippy::unseparated_literal_suffix +)] +mod bindings { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} +use bindings::*; + +use alvr_common::{ + error, + once_cell::sync::Lazy, + parking_lot::{Mutex, RwLock}, + settings_schema::Switch, + warn, BUTTON_INFO, HAND_LEFT_ID, HAND_RIGHT_ID, HAND_TRACKER_LEFT_ID, HAND_TRACKER_RIGHT_ID, }; -use alvr_common::{once_cell::sync::Lazy, parking_lot::RwLock, warn, HAND_LEFT_ID, HAND_RIGHT_ID}; +use alvr_filesystem as afs; use alvr_packets::{ButtonValue, Haptics}; -use alvr_session::CodecType; +use alvr_server_core::{ServerCoreContext, ServerCoreEvent, REGISTERED_BUTTON_SET}; +use alvr_session::{CodecType, ControllersConfig}; use std::{ - ffi::{c_char, c_void}, - ptr, thread, + ffi::{c_char, c_void, CString}, + ptr, + sync::{mpsc, Once}, + thread, time::{Duration, Instant}, }; -static SERVER_CORE_CONTEXT: Lazy>> = Lazy::new(|| { - logging_backend::init_logging(); - - RwLock::new(Some(ServerCoreContext::new())) +static FILESYSTEM_LAYOUT: Lazy = Lazy::new(|| { + afs::filesystem_layout_from_openvr_driver_root_dir( + &alvr_server_io::get_driver_dir_from_registered().unwrap(), + ) }); +static SERVER_CORE_CONTEXT: Lazy>> = + Lazy::new(|| RwLock::new(None)); +static EVENTS_RECEIVER: Lazy>>> = + Lazy::new(|| Mutex::new(None)); + extern "C" fn driver_ready_idle(set_default_chap: bool) { thread::spawn(move || { - unsafe { crate::InitOpenvrClient() }; + let events_receiver = EVENTS_RECEIVER.lock().take().unwrap(); + + unsafe { InitOpenvrClient() }; if set_default_chap { // call this when inside a new thread. Calling this on the parent thread will crash // SteamVR unsafe { - crate::SetChaperoneArea(2.0, 2.0); + SetChaperoneArea(2.0, 2.0); } } @@ -38,37 +64,31 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { let mut last_resync = Instant::now(); loop { - let event = if let Some(context) = &*SERVER_CORE_CONTEXT.read() { - match context.poll_event() { - Some(event) => event, - None => { - thread::sleep(Duration::from_millis(5)); - continue; - } - } - } else { - break; + let event = match events_receiver.recv_timeout(Duration::from_millis(5)) { + Ok(event) => event, + Err(mpsc::RecvTimeoutError::Timeout) => continue, + Err(mpsc::RecvTimeoutError::Disconnected) => break, }; match event { ServerCoreEvent::SetOpenvrProperty { device_id, prop } => unsafe { - crate::SetOpenvrProperty(device_id, props::to_ffi_openvr_prop(prop)) + SetOpenvrProperty(device_id, props::to_ffi_openvr_prop(prop)) }, ServerCoreEvent::ClientConnected => { unsafe { - crate::InitializeStreaming(); - crate::RequestDriverResync(); + InitializeStreaming(); + RequestDriverResync(); }; } - ServerCoreEvent::ClientDisconnected => unsafe { crate::DeinitializeStreaming() }, + ServerCoreEvent::ClientDisconnected => unsafe { DeinitializeStreaming() }, ServerCoreEvent::Battery(info) => unsafe { - crate::SetBattery(info.device_id, info.gauge_value, info.is_plugged) + SetBattery(info.device_id, info.gauge_value, info.is_plugged) }, ServerCoreEvent::PlayspaceSync(bounds) => unsafe { - crate::SetChaperoneArea(bounds.x, bounds.y) + SetChaperoneArea(bounds.x, bounds.y) }, ServerCoreEvent::ViewsConfig(config) => unsafe { - crate::SetViewsConfig(FfiViewsConfig { + SetViewsConfig(FfiViewsConfig { fov: [ FfiFov { left: config.fov[0].left, @@ -95,8 +115,7 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { let controllers_config; let track_body; { - let data_lock = SERVER_DATA_MANAGER.read(); - let headset_config = &data_lock.settings().headset; + let headset_config = &alvr_server_core::settings().headset; controllers_config = headset_config.controllers.clone().into_option(); track_body = headset_config.body_tracking.enabled(); @@ -110,8 +129,7 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { let left_openvr_hand_skeleton; let right_openvr_hand_skeleton; { - let data_manager_lock = SERVER_DATA_MANAGER.read(); - let headset_config = &data_manager_lock.settings().headset; + let headset_config = &alvr_server_core::settings().headset; left_openvr_hand_skeleton = tracking.hand_skeletons[0].map(|s| { tracking::to_openvr_hand_skeleton(headset_config, *HAND_LEFT_ID, s) @@ -121,18 +139,23 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { }); } - let enable_skeleton = controllers_config - .as_ref() - .map(|c| c.enable_skeleton) - .unwrap_or(false); - let ffi_left_hand_skeleton = enable_skeleton - .then_some(left_openvr_hand_skeleton) - .flatten() - .map(tracking::to_ffi_skeleton); - let ffi_right_hand_skeleton = enable_skeleton - .then_some(right_openvr_hand_skeleton) - .flatten() - .map(tracking::to_ffi_skeleton); + let ( + use_separate_hand_trackers, + ffi_left_hand_skeleton, + ffi_right_hand_skeleton, + ) = if let Some(ControllersConfig { + hand_skeleton: Switch::Enabled(hand_skeleton_config), + .. + }) = controllers_config + { + ( + hand_skeleton_config.use_separate_trackers, + left_openvr_hand_skeleton.map(tracking::to_ffi_skeleton), + right_openvr_hand_skeleton.map(tracking::to_ffi_skeleton), + ) + } else { + (false, None, None) + }; let ffi_motions = tracking .device_motions @@ -143,12 +166,19 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { let ffi_body_trackers = tracking::to_ffi_body_trackers(&tracking.device_motions, track_body); + // There are two pairs of controllers/hand tracking devices registered in + // OpenVR, two lefts and two rights. If enabled with use_separate_hand_trackers, + // we select at runtime which device to use (selected for left and right hand + // independently. Selection is done by setting deviceIsConnected. unsafe { - crate::SetTracking( + SetTracking( tracking.target_timestamp.as_nanos() as _, controllers_pose_time_offset.as_secs_f32(), ffi_motions.as_ptr(), ffi_motions.len() as _, + track_controllers.into(), + use_separate_hand_trackers && tracking.hand_skeletons[0].is_some(), + use_separate_hand_trackers && tracking.hand_skeletons[1].is_some(), if let Some(skeleton) = &ffi_left_hand_skeleton { skeleton } else { @@ -159,7 +189,6 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { } else { ptr::null() }, - track_controllers.into(), if let Some(body_trackers) = &ffi_body_trackers { body_trackers.as_ptr() } else { @@ -177,23 +206,22 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { for entry in entries { let value = match entry.value { ButtonValue::Binary(value) => FfiButtonValue { - type_: crate::FfiButtonType_BUTTON_TYPE_BINARY, - __bindgen_anon_1: crate::FfiButtonValue__bindgen_ty_1 { + type_: FfiButtonType_BUTTON_TYPE_BINARY, + __bindgen_anon_1: FfiButtonValue__bindgen_ty_1 { binary: value.into(), }, }, ButtonValue::Scalar(value) => FfiButtonValue { - type_: crate::FfiButtonType_BUTTON_TYPE_SCALAR, - __bindgen_anon_1: crate::FfiButtonValue__bindgen_ty_1 { - scalar: value, - }, + type_: FfiButtonType_BUTTON_TYPE_SCALAR, + __bindgen_anon_1: FfiButtonValue__bindgen_ty_1 { scalar: value }, }, }; - unsafe { crate::SetButton(entry.path_id, value) }; + unsafe { SetButton(entry.path_id, value) }; } } - ServerCoreEvent::RequestIDR => unsafe { crate::RequestIDR() }, + ServerCoreEvent::RequestIDR => unsafe { RequestIDR() }, + ServerCoreEvent::CaptureFrame => unsafe { CaptureFrame() }, ServerCoreEvent::GameRenderLatencyFeedback(game_latency) => { if cfg!(target_os = "linux") && game_latency.as_secs_f32() > 0.25 { let now = Instant::now(); @@ -201,7 +229,7 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { last_resync = now; warn!("Desync detected. Attempting recovery."); unsafe { - crate::RequestDriverResync(); + RequestDriverResync(); } } } @@ -209,22 +237,42 @@ extern "C" fn driver_ready_idle(set_default_chap: bool) { ServerCoreEvent::ShutdownPending => { SERVER_CORE_CONTEXT.write().take(); - unsafe { crate::ShutdownSteamvr() }; + unsafe { ShutdownSteamvr() }; } ServerCoreEvent::RestartPending => { if let Some(context) = SERVER_CORE_CONTEXT.write().take() { context.restart(); } - unsafe { crate::ShutdownSteamvr() }; + unsafe { ShutdownSteamvr() }; } } } - unsafe { crate::ShutdownOpenvrClient() }; + unsafe { ShutdownOpenvrClient() }; }); } +pub extern "C" fn register_buttons(device_id: u64) { + let mapped_device_id = if device_id == *HAND_TRACKER_LEFT_ID { + *HAND_LEFT_ID + } else if device_id == *HAND_TRACKER_RIGHT_ID { + *HAND_RIGHT_ID + } else { + device_id + }; + + for id in &*REGISTERED_BUTTON_SET { + if let Some(info) = BUTTON_INFO.get(id) { + if info.device_id == mapped_device_id { + unsafe { RegisterButton(device_id, *id) }; + } + } else { + error!("Cannot register unrecognized button ID {id}"); + } + } +} + extern "C" fn send_haptics(device_id: u64, duration_s: f32, frequency: f32, amplitude: f32) { if let Some(context) = &*SERVER_CORE_CONTEXT.read() { let haptics = Haptics { @@ -299,9 +347,7 @@ extern "C" fn report_present(timestamp_ns: u64, offset_ns: u64) { extern "C" fn wait_for_vsync() { // NB: don't sleep while locking SERVER_DATA_MANAGER or SERVER_CORE_CONTEXT - let sleep_duration = if SERVER_DATA_MANAGER - .read() - .settings() + let sleep_duration = if alvr_server_core::settings() .video .optimize_game_render_latency { @@ -329,21 +375,54 @@ pub unsafe extern "C" fn HmdDriverFactory( interface_name: *const c_char, return_code: *mut i32, ) -> *mut c_void { - // Make sure the context is initialized, and initialize logging - SERVER_CORE_CONTEXT.read().as_ref(); - - crate::GetSerialNumber = Some(props::get_serial_number); - crate::SetOpenvrProps = Some(props::set_device_openvr_props); - crate::RegisterButtons = Some(input_mapping::register_buttons); - crate::DriverReadyIdle = Some(driver_ready_idle); - crate::HapticsSend = Some(send_haptics); - crate::SetVideoConfigNals = Some(set_video_config_nals); - crate::VideoSend = Some(send_video); - crate::GetDynamicEncoderParams = Some(get_dynamic_encoder_params); - crate::ReportComposed = Some(report_composed); - crate::ReportPresent = Some(report_present); - crate::WaitForVSync = Some(wait_for_vsync); - crate::ShutdownRuntime = Some(shutdown_driver); - - crate::CppOpenvrEntryPoint(interface_name, return_code) + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + alvr_server_core::init_logging(); + + unsafe { + g_sessionPath = CString::new(FILESYSTEM_LAYOUT.session().to_string_lossy().to_string()) + .unwrap() + .into_raw(); + g_driverRootDir = CString::new( + FILESYSTEM_LAYOUT + .openvr_driver_root_dir + .to_string_lossy() + .to_string(), + ) + .unwrap() + .into_raw(); + }; + + graphics::initialize_shaders(); + + unsafe { + LogError = Some(alvr_server_core::alvr_log_error); + LogWarn = Some(alvr_server_core::alvr_log_warn); + LogInfo = Some(alvr_server_core::alvr_log_info); + LogDebug = Some(alvr_server_core::alvr_log_debug); + LogPeriodically = Some(alvr_server_core::alvr_log_periodically); + PathStringToHash = Some(alvr_server_core::alvr_path_to_id); + GetSerialNumber = Some(props::get_serial_number); + SetOpenvrProps = Some(props::set_device_openvr_props); + RegisterButtons = Some(register_buttons); + DriverReadyIdle = Some(driver_ready_idle); + HapticsSend = Some(send_haptics); + SetVideoConfigNals = Some(set_video_config_nals); + VideoSend = Some(send_video); + GetDynamicEncoderParams = Some(get_dynamic_encoder_params); + ReportComposed = Some(report_composed); + ReportPresent = Some(report_present); + WaitForVSync = Some(wait_for_vsync); + ShutdownRuntime = Some(shutdown_driver); + + CppInit(); + } + + let (context, events_receiver) = ServerCoreContext::new(); + + *SERVER_CORE_CONTEXT.write() = Some(context); + *EVENTS_RECEIVER.lock() = Some(events_receiver); + }); + + CppOpenvrEntryPoint(interface_name, return_code) } diff --git a/alvr/server/src/openvr/props.rs b/alvr/server_openvr/src/props.rs similarity index 91% rename from alvr/server/src/openvr/props.rs rename to alvr/server_openvr/src/props.rs index 61f27387df..fd81892352 100644 --- a/alvr/server/src/openvr/props.rs +++ b/alvr/server_openvr/src/props.rs @@ -2,8 +2,15 @@ // todo: fill out more properties for headset and controllers // todo: add more emulation modes -use crate::{FfiOpenvrProperty, FfiOpenvrPropertyValue, SERVER_DATA_MANAGER}; -use alvr_common::{info, settings_schema::Switch, HAND_LEFT_ID, HAND_RIGHT_ID, HEAD_ID}; +use crate::{ + FfiOpenvrProperty, FfiOpenvrPropertyType_Bool, FfiOpenvrPropertyType_Double, + FfiOpenvrPropertyType_Float, FfiOpenvrPropertyType_Int32, FfiOpenvrPropertyType_String, + FfiOpenvrPropertyType_Uint64, FfiOpenvrPropertyType_Vector3, FfiOpenvrPropertyValue, +}; +use alvr_common::{ + info, settings_schema::Switch, HAND_LEFT_ID, HAND_RIGHT_ID, HAND_TRACKER_LEFT_ID, + HAND_TRACKER_RIGHT_ID, HEAD_ID, +}; use alvr_session::{ ControllersEmulationMode, HeadsetEmulationMode, OpenvrPropValue, OpenvrProperty, }; @@ -16,13 +23,13 @@ pub fn to_ffi_openvr_prop(prop: OpenvrProperty) -> FfiOpenvrProperty { let (key, value) = prop.into_key_value(); let type_ = match value { - OpenvrPropValue::Bool(_) => crate::FfiOpenvrPropertyType_Bool, - OpenvrPropValue::Float(_) => crate::FfiOpenvrPropertyType_Float, - OpenvrPropValue::Int32(_) => crate::FfiOpenvrPropertyType_Int32, - OpenvrPropValue::Uint64(_) => crate::FfiOpenvrPropertyType_Uint64, - OpenvrPropValue::Vector3(_) => crate::FfiOpenvrPropertyType_Vector3, - OpenvrPropValue::Double(_) => crate::FfiOpenvrPropertyType_Double, - OpenvrPropValue::String(_) => crate::FfiOpenvrPropertyType_String, + OpenvrPropValue::Bool(_) => FfiOpenvrPropertyType_Bool, + OpenvrPropValue::Float(_) => FfiOpenvrPropertyType_Float, + OpenvrPropValue::Int32(_) => FfiOpenvrPropertyType_Int32, + OpenvrPropValue::Uint64(_) => FfiOpenvrPropertyType_Uint64, + OpenvrPropValue::Vector3(_) => FfiOpenvrPropertyType_Vector3, + OpenvrPropValue::Double(_) => FfiOpenvrPropertyType_Double, + OpenvrPropValue::String(_) => FfiOpenvrPropertyType_String, }; let value = match value { @@ -54,8 +61,7 @@ pub fn to_ffi_openvr_prop(prop: OpenvrProperty) -> FfiOpenvrProperty { } fn serial_number(device_id: u64) -> String { - let data_manager_lock = SERVER_DATA_MANAGER.read(); - let settings = data_manager_lock.settings(); + let settings = alvr_server_core::settings(); if device_id == *HEAD_ID { match &settings.headset.emulation_mode { @@ -84,6 +90,16 @@ fn serial_number(device_id: u64) -> String { } else { "Unknown".into() } + } else if device_id == *HAND_TRACKER_LEFT_ID || device_id == *HAND_TRACKER_RIGHT_ID { + if let Switch::Enabled(_) = &settings.headset.controllers { + if device_id == *HAND_TRACKER_LEFT_ID { + "ALVR_Left_Hand_Full_Skeletal".into() + } else { + "ALVR_Right_Hand_Full_Skeletal".into() + } + } else { + "Unknown".into() + } } else { "Unknown".into() } @@ -108,8 +124,7 @@ pub extern "C" fn get_serial_number(device_id: u64, out_str: *mut c_char) -> u64 pub extern "C" fn set_device_openvr_props(device_id: u64) { use OpenvrProperty::*; - let data_manager_lock = SERVER_DATA_MANAGER.read(); - let settings = data_manager_lock.settings(); + let settings = alvr_server_core::settings(); if device_id == *HEAD_ID { fn set_prop(prop: OpenvrProperty) { @@ -221,16 +236,18 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { for prop in &settings.headset.extra_openvr_props { set_prop(prop.clone()); } - } else if device_id == *HAND_LEFT_ID || device_id == *HAND_RIGHT_ID { + } else if device_id == *HAND_LEFT_ID + || device_id == *HAND_RIGHT_ID + || device_id == *HAND_TRACKER_LEFT_ID + || device_id == *HAND_TRACKER_RIGHT_ID + { + let left_hand = device_id == *HAND_LEFT_ID || device_id == *HAND_TRACKER_LEFT_ID; + let right_hand = device_id == *HAND_RIGHT_ID || device_id == *HAND_TRACKER_RIGHT_ID; if let Switch::Enabled(config) = &settings.headset.controllers { let set_prop = |prop| { info!( "Setting {} controller OpenVR prop: {prop:?}", - if device_id == *HAND_LEFT_ID { - "left" - } else { - "right" - } + if left_hand { "left" } else { "right" } ); unsafe { crate::SetOpenvrProperty(device_id, to_ffi_openvr_prop(prop)); @@ -241,13 +258,13 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { ControllersEmulationMode::Quest2Touch => { set_prop(TrackingSystemName("oculus".into())); set_prop(ManufacturerName("Oculus".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(ModelNumber("Miramar (Left Controller)".into())); set_prop(RenderModelName("oculus_quest2_controller_left".into())); set_prop(RegisteredDeviceType( "oculus/1WMHH000X00000_Controller_Left".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(ModelNumber("Miramar (Right Controller)".into())); set_prop(RenderModelName("oculus_quest2_controller_right".into())); set_prop(RegisteredDeviceType( @@ -257,7 +274,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(ControllerType("oculus_touch".into())); set_prop(InputProfilePath("{oculus}/input/touch_profile.json".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(NamedIconPathDeviceOff( "{oculus}/icons/rifts_left_controller_off.png".into(), )); @@ -276,7 +293,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(NamedIconPathDeviceAlertLow( "{oculus}/icons/rifts_left_controller_ready_low.png".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(NamedIconPathDeviceOff( "{oculus}/icons/rifts_right_controller_off.png".into(), )); @@ -300,13 +317,13 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { ControllersEmulationMode::Quest3Plus => { set_prop(TrackingSystemName("oculus".into())); set_prop(ManufacturerName("Oculus".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(ModelNumber("Meta Quest 3 (Left Controller)".into())); set_prop(RenderModelName("oculus_quest_plus_controller_left".into())); set_prop(RegisteredDeviceType( "oculus/1WMHH000X00000_Controller_Left".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(ModelNumber("Meta Quest 3 (Right Controller)".into())); set_prop(RenderModelName("oculus_quest_plus_controller_right".into())); set_prop(RegisteredDeviceType( @@ -316,7 +333,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(ControllerType("oculus_touch".into())); set_prop(InputProfilePath("{oculus}/input/touch_profile.json".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(NamedIconPathDeviceOff( "{oculus}/icons/rifts_left_controller_off.png".into(), )); @@ -335,7 +352,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(NamedIconPathDeviceAlertLow( "{oculus}/icons/rifts_left_controller_ready_low.png".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(NamedIconPathDeviceOff( "{oculus}/icons/rifts_right_controller_off.png".into(), )); @@ -359,13 +376,13 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { ControllersEmulationMode::RiftSTouch => { set_prop(TrackingSystemName("oculus".into())); set_prop(ManufacturerName("Oculus".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(ModelNumber("Oculus Rift S (Left Controller)".into())); set_prop(RenderModelName("oculus_rifts_controller_left".into())); set_prop(RegisteredDeviceType( "oculus/1WMGH000XX0000_Controller_Left".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(ModelNumber("Oculus Rift S (Right Controller)".into())); set_prop(RenderModelName("oculus_rifts_controller_right".into())); set_prop(RegisteredDeviceType( @@ -375,7 +392,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(ControllerType("oculus_touch".into())); set_prop(InputProfilePath("{oculus}/input/touch_profile.json".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(NamedIconPathDeviceOff( "{oculus}/icons/rifts_left_controller_off.png".into(), )); @@ -394,7 +411,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(NamedIconPathDeviceAlertLow( "{oculus}/icons/rifts_left_controller_ready_low.png".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(NamedIconPathDeviceOff( "{oculus}/icons/rifts_right_controller_off.png".into(), )); @@ -418,7 +435,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { ControllersEmulationMode::ValveIndex => { set_prop(TrackingSystemName("indexcontroller".into())); set_prop(ManufacturerName("Valve".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(ModelNumber("Knuckles (Left Controller)".into())); set_prop(RenderModelName( "{indexcontroller}valve_controller_knu_1_0_left".into(), @@ -426,7 +443,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(RegisteredDeviceType( "valve/index_controllerLHR-E217CD00_Left".into(), )); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(ModelNumber("Knuckles (Right Controller)".into())); set_prop(RenderModelName( "{indexcontroller}valve_controller_knu_1_0_right".into(), @@ -444,12 +461,12 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { set_prop(TrackingSystemName("htc".into())); set_prop(ManufacturerName("HTC".into())); set_prop(RenderModelName("vr_controller_vive_1_5".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(ModelNumber( "ALVR Remote Controller (Left Controller)".into(), )); set_prop(RegisteredDeviceType("vive_controller_Left".into())); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(ModelNumber( "ALVR Remote Controller (Right Controller)".into(), )); @@ -461,11 +478,11 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { ControllersEmulationMode::ViveTracker => { set_prop(TrackingSystemName("lighthouse".into())); set_prop(RenderModelName("{htc}vr_tracker_vive_1_0".into())); - if device_id == *HAND_LEFT_ID { + if left_hand { set_prop(ModelNumber("Vive Tracker Pro MV (Left Controller)".into())); set_prop(RegisteredDeviceType("ALVR/tracker/left_foot".into())); set_prop(ControllerType("vive_tracker_left_foot".into())); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { set_prop(ModelNumber("Vive Tracker Pro MV (Right Controller)".into())); set_prop(RegisteredDeviceType("ALVR/tracker/right_foot".into())); set_prop(ControllerType("vive_tracker_right_foot".into())); @@ -562,10 +579,10 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) { if matches!(config.emulation_mode, ControllersEmulationMode::ViveTracker) { // TrackedControllerRole_Invalid set_prop(ControllerRoleHint(0)); - } else if device_id == *HAND_LEFT_ID { + } else if left_hand { // TrackedControllerRole_LeftHand set_prop(ControllerRoleHint(1)); - } else if device_id == *HAND_RIGHT_ID { + } else if right_hand { // TrackedControllerRole_RightHand set_prop(ControllerRoleHint(2)); } diff --git a/alvr/server/src/openvr/tracking.rs b/alvr/server_openvr/src/tracking.rs similarity index 98% rename from alvr/server/src/openvr/tracking.rs rename to alvr/server_openvr/src/tracking.rs index df1322a476..64bc36a0bb 100644 --- a/alvr/server/src/openvr/tracking.rs +++ b/alvr/server_openvr/src/tracking.rs @@ -1,4 +1,4 @@ -use crate::{tracking, FfiBodyTracker, FfiDeviceMotion, FfiHandSkeleton, FfiQuat}; +use crate::{FfiBodyTracker, FfiDeviceMotion, FfiHandSkeleton, FfiQuat}; use alvr_common::{ glam::{EulerRot, Quat, Vec3}, once_cell::sync::Lazy, @@ -26,7 +26,7 @@ pub fn to_openvr_hand_skeleton( hand_skeleton: [Pose; 26], ) -> [Pose; 31] { let (left_hand_skeleton_offset, right_hand_skeleton_offset) = - tracking::get_hand_skeleton_offsets(config); + alvr_server_core::get_hand_skeleton_offsets(config); let id = device_id; // global joints diff --git a/alvr/session/src/lib.rs b/alvr/session/src/lib.rs index f4fc785b28..6dfe9c593a 100644 --- a/alvr/session/src/lib.rs +++ b/alvr/session/src/lib.rs @@ -105,6 +105,7 @@ pub struct OpenvrConfig { pub nvenc_enable_weighted_prediction: bool, pub capture_frame_dir: String, pub amd_bitrate_corruption_fix: bool, + pub use_separate_hand_trackers: bool, // these settings are not used on the C++ side, but we need them to correctly trigger a SteamVR // restart @@ -176,7 +177,7 @@ impl SessionConfig { } // Note: unwrap is safe because current session is expected to serialize correctly - let old_session_json = json::to_value(&self).unwrap(); + let old_session_json = json::to_value(self.clone()).unwrap(); let old_session_fields = old_session_json.as_object().unwrap(); let maybe_session_settings_json = diff --git a/alvr/session/src/settings.rs b/alvr/session/src/settings.rs index 0aa8c1fe4e..6ae5a994e6 100644 --- a/alvr/session/src/settings.rs +++ b/alvr/session/src/settings.rs @@ -455,11 +455,11 @@ pub struct FoveatedEncodingConfig { #[repr(C)] #[derive(SettingsSchema, Clone, Copy, Serialize, Deserialize, Pod, Zeroable)] pub struct ColorCorrectionConfig { - #[schema(gui(slider(min = -1.0, max = 1.0, step = 0.01)))] + #[schema(gui(slider(min = -1.0, max = 1.0, step = 0.001)))] #[schema(flag = "steamvr-restart")] pub brightness: f32, - #[schema(gui(slider(min = -1.0, max = 1.0, step = 0.01)))] + #[schema(gui(slider(min = -1.0, max = 1.0, step = 0.001)))] #[schema(flag = "steamvr-restart")] pub contrast: f32, @@ -774,8 +774,7 @@ pub struct AutomaticButtonMappingConfig { } #[derive(SettingsSchema, Serialize, Deserialize, Clone)] -#[schema(collapsible)] -pub struct HandGestureConfig { +pub struct HandTrackingInteractionConfig { #[schema(flag = "real-time")] pub only_touch: bool, @@ -865,6 +864,15 @@ pub struct HapticsConfig { pub min_duration_s: f32, } +#[derive(SettingsSchema, Serialize, Deserialize, Clone)] +pub struct HandSkeletonConfig { + #[schema(flag = "steamvr-restart")] + #[schema(strings( + help = r"Enabling this will use separate tracker objects with the full skeletal tracking level when hand tracking is detected. This is required for VRChat hand tracking." + ))] + pub use_separate_trackers: bool, +} + #[derive(SettingsSchema, Serialize, Deserialize, Clone)] #[schema(collapsible)] pub struct ControllersConfig { @@ -872,17 +880,17 @@ pub struct ControllersConfig { #[schema(flag = "real-time")] pub tracked: bool, - #[schema(flag = "real-time")] + #[schema(flag = "steamvr-restart")] #[schema(strings( help = "Enabling this passes skeletal hand data (finger tracking) to SteamVR." ))] - pub enable_skeleton: bool, + pub hand_skeleton: Switch, #[schema(flag = "real-time")] #[schema(strings( help = "Enabling this allows using hand gestures to emulate controller inputs." ))] - pub gestures: Switch, + pub hand_tracking_interaction: Switch, #[schema(strings( display_name = "Prediction", @@ -1519,7 +1527,12 @@ pub fn session_settings_default() -> SettingsDefault { content: ControllersConfigDefault { gui_collapsed: false, tracked: true, - enable_skeleton: true, + hand_skeleton: SwitchDefault { + enabled: true, + content: HandSkeletonConfigDefault { + use_separate_trackers: true, + }, + }, emulation_mode: ControllersEmulationModeDefault { Custom: ControllersEmulationModeCustomDefault { serial_number: "ALVR Controller".into(), @@ -1576,11 +1589,10 @@ pub fn session_settings_default() -> SettingsDefault { }, force_threshold: 0.8, }, - gestures: SwitchDefault { - enabled: true, - content: HandGestureConfigDefault { - gui_collapsed: true, - only_touch: true, + hand_tracking_interaction: SwitchDefault { + enabled: false, + content: HandTrackingInteractionConfigDefault { + only_touch: false, pinch_touch_distance: 0.0, pinch_trigger_distance: 0.25, curl_touch_distance: 2.0, diff --git a/alvr/sockets/src/backend/udp.rs b/alvr/sockets/src/backend/udp.rs index f0071106de..623899c1ac 100644 --- a/alvr/sockets/src/backend/udp.rs +++ b/alvr/sockets/src/backend/udp.rs @@ -6,7 +6,7 @@ use alvr_session::{DscpTos, SocketBufferSize}; use socket2::{MaybeUninitSlice, Socket}; use std::{ ffi::c_int, - mem, + mem::{self, MaybeUninit}, net::{IpAddr, UdpSocket}, time::Duration, }; @@ -50,7 +50,10 @@ impl SocketWriter for UdpSocket { impl SocketReader for Socket { fn recv(&mut self, buffer: &mut [u8]) -> ConResult { - Socket::recv(self, unsafe { mem::transmute(buffer) }).handle_try_again() + Socket::recv(self, unsafe { + mem::transmute::<&mut [u8], &mut [MaybeUninit]>(buffer) + }) + .handle_try_again() } fn peek(&self, buffer: &mut [u8]) -> ConResult { @@ -59,7 +62,9 @@ impl SocketReader for Socket { #[cfg(not(windows))] const FLAGS: c_int = 0x02 | 0x20; // MSG_PEEK | MSG_TRUNC - let buffer = MaybeUninitSlice::new(unsafe { mem::transmute(buffer) }); + let buffer = MaybeUninitSlice::new(unsafe { + mem::transmute::<&mut [u8], &mut [MaybeUninit]>(buffer) + }); Ok(self .recv_vectored_with_flags(&mut [buffer], FLAGS) .handle_try_again()? diff --git a/alvr/vrcompositor_wrapper/drm-lease-shim.cpp b/alvr/vrcompositor_wrapper/drm-lease-shim.cpp index 6b174d98de..6d2a49c43b 100644 --- a/alvr/vrcompositor_wrapper/drm-lease-shim.cpp +++ b/alvr/vrcompositor_wrapper/drm-lease-shim.cpp @@ -10,7 +10,7 @@ #include #define PICOJSON_USE_INT64 -#include "../server/cpp/alvr_server/include/picojson.h" +#include "../server_openvr/cpp/alvr_server/include/picojson.h" #define LOAD_FN(f) \ if (!real_##f) { \ diff --git a/alvr/vulkan_layer/build.rs b/alvr/vulkan_layer/build.rs index d4db862492..905aa01980 100644 --- a/alvr/vulkan_layer/build.rs +++ b/alvr/vulkan_layer/build.rs @@ -5,7 +5,7 @@ fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let cpp_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let server_cpp_dir = - PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("../server/cpp"); + PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("../server_openvr/cpp"); let vulkan = pkg_config::Config::new().probe("vulkan").unwrap(); let libunwind = pkg_config::Config::new().probe("libunwind").unwrap(); diff --git a/alvr/xtask/flatpak/audio-flatpak-setup.sh b/alvr/xtask/flatpak/audio-flatpak-setup.sh deleted file mode 100644 index 0d2f2324c4..0000000000 --- a/alvr/xtask/flatpak/audio-flatpak-setup.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -# Set either to 0 to prevent from creating audio or microphone sinks and instead you using own headset or microphone -USE_HEADSET_AUDIO=1 -USE_HEADSET_MIC=1 - -function get_playback_sink_input_id() { - get_playback_id sink-inputs 'Sink Input' "$1" -} - -function get_playback_source_output_id() { - get_playback_id source-outputs 'Source Output' "$1" -} - -function get_playback_id() { - local last_node_name='' - local last_node_id='' - pactl list "$1" | while read -r line; do - node_id=$(echo "$line" | grep -oP "$2 #\K.+" | sed -e 's/^[ \t]*//') - node_name=$(echo "$line" | grep -oP 'node.name = "\K[^"]+' | sed -e 's/^[ \t]*//') - if [[ "$node_id" != '' ]] && [[ "$last_node_id" != "$node_id" ]]; then - last_node_id="$node_id" - fi - if [[ -n "$node_name" ]] && [[ "$last_node_name" != "$node_name" ]]; then - last_node_name="$node_name" - if [[ "$last_node_name" == "$3" ]]; then - echo "$last_node_id" - return - fi - fi - done -} - -function get_sink_id_by_name() { - local sink_name - sink_name=$1 - pactl list short sinks | grep "$sink_name" | cut -d$'\t' -f1 -} - -function setup_mic() { - if [[ $USE_HEADSET_MIC == 1 ]]; then - echo "Creating microphone sink & source and linking alvr playback to it" - # This sink is required so that it persistently auto-connects to alvr playback later - pactl load-module module-null-sink sink_name=ALVR-MIC-Sink media.class=Audio/Sink | tee -a /run/user/1000/alvr-audio - # This source is required so that any app can use it as microphone - pactl load-module module-null-sink sink_name=ALVR-MIC-Source media.class=Audio/Source/Virtual | tee -a /run/user/1000/alvr-audio - # We link them together - pw-link ALVR-MIC-Sink:monitor_FL ALVR-MIC-Source:input_FL - pw-link ALVR-MIC-Sink:monitor_FR ALVR-MIC-Source:input_FR - # And we assign playback of pipewire alsa playback to created alvr sink - pactl move-sink-input "$(get_playback_sink_input_id 'ALSA plug-in [vrserver]')" "$(get_sink_id_by_name ALVR-MIC-Sink)" - pactl set-default-source ALVR-MIC-Source - fi -} - -function unload_modules() { - echo "Unloading audio, microphone sink & source" - while read -r line; do - pactl unload-module "$line" - done <"/run/user/1000/alvr-audio" - >/run/user/1000/alvr-audio -} - -function setup_audio() { - if [[ $USE_HEADSET_AUDIO == 1 ]]; then - echo "Setting up audio" - pactl load-module module-null-sink sink_name=ALVR-AUDIO-Sink media.class=Audio/Sink | tee -a /run/user/1000/alvr-audio - pactl set-default-sink ALVR-AUDIO-Sink - pactl move-source-output "$(get_playback_source_output_id 'ALSA plug-in [vrserver]')" "$(get_sink_id_by_name ALVR-AUDIO-Sink)" - fi -} - -case $ACTION in -connect) - unload_modules - setup_audio - setup_mic - ;; -disconnect) - unload_modules - ;; -esac diff --git a/alvr/xtask/src/build.rs b/alvr/xtask/src/build.rs index c98605fd11..c47c2a1476 100644 --- a/alvr/xtask/src/build.rs +++ b/alvr/xtask/src/build.rs @@ -30,7 +30,6 @@ impl Display for Profile { pub fn build_server_lib( profile: Profile, enable_messagebox: bool, - gpl: bool, root: Option, reproducible: bool, ) { @@ -49,10 +48,6 @@ pub fn build_server_lib( flags.push("--features"); flags.push("alvr_common/enable-messagebox"); } - if gpl { - flags.push("--features"); - flags.push("gpl"); - } if reproducible { flags.push("--locked"); } @@ -67,11 +62,11 @@ pub fn build_server_lib( sh.set_var("ALVR_ROOT_DIR", root); } - let _push_guard = sh.push_dir(afs::crate_dir("server")); + let _push_guard = sh.push_dir(afs::crate_dir("server_core")); cmd!(sh, "cargo build {flags_ref...}").run().unwrap(); sh.copy_file( - artifacts_dir.join(afs::dynlib_fname("alvr_server")), + artifacts_dir.join(afs::dynlib_fname("alvr_server_core")), &build_dir, ) .unwrap(); @@ -140,10 +135,10 @@ pub fn build_streamer( { let gpl_flag = gpl.then(|| vec!["--features", "gpl"]).unwrap_or_default(); let profiling_flag = profiling - .then(|| vec!["--features", "trace-performance"]) + .then(|| vec!["--features", "alvr_server_core/trace-performance"]) .unwrap_or_default(); - let _push_guard = sh.push_dir(afs::crate_dir("server")); + let _push_guard = sh.push_dir(afs::crate_dir("server_openvr")); cmd!( sh, "cargo build {common_flags_ref...} {gpl_flag...} {profiling_flag...}" @@ -152,14 +147,14 @@ pub fn build_streamer( .unwrap(); sh.copy_file( - artifacts_dir.join(afs::dynlib_fname("alvr_server")), + artifacts_dir.join(afs::dynlib_fname("alvr_server_openvr")), build_layout.openvr_driver_lib(), ) .unwrap(); if cfg!(windows) { sh.copy_file( - artifacts_dir.join("alvr_server.pdb"), + artifacts_dir.join("alvr_server_openvr.pdb"), build_layout .openvr_driver_lib_dir() .join("driver_alvr_server.pdb"), @@ -191,7 +186,7 @@ pub fn build_streamer( // Bring along the c++ runtime command::copy_recursive( &sh, - &afs::crate_dir("server").join("cpp/bin/windows"), + &afs::crate_dir("server_openvr").join("cpp/bin/windows"), &build_layout.openvr_driver_lib_dir(), ) .unwrap(); @@ -310,22 +305,14 @@ pub fn build_launcher(profile: Profile, enable_messagebox: bool, reproducible: b .unwrap(); } -fn build_android_lib_impl(dir_name: &str, profile: Profile, link_stdcpp: bool) { +fn build_android_lib_impl(dir_name: &str, profile: Profile, link_stdcpp: bool, all_targets: bool) { let sh = Shell::new().unwrap(); - let ndk_flags = &[ - "-t", - "arm64-v8a", - "-t", - "armeabi-v7a", - "-t", - "x86_64", - "-t", - "x86", - "-p", - "26", - "--no-strip", - ]; + let mut ndk_flags = vec!["--no-strip", "-p", "26", "-t", "arm64-v8a"]; + + if all_targets { + ndk_flags.extend(["-t", "armeabi-v7a", "-t", "x86_64", "-t", "x86"]); + } let mut rust_flags = vec![]; match profile { @@ -356,15 +343,15 @@ fn build_android_lib_impl(dir_name: &str, profile: Profile, link_stdcpp: bool) { cmd!(sh, "cbindgen --output {out}").run().unwrap(); } -pub fn build_android_client_core_lib(profile: Profile, link_stdcpp: bool) { - build_android_lib_impl("client_core", profile, link_stdcpp) +pub fn build_android_client_core_lib(profile: Profile, link_stdcpp: bool, all_targets: bool) { + build_android_lib_impl("client_core", profile, link_stdcpp, all_targets) } pub fn build_android_client_openxr_lib(profile: Profile, link_stdcpp: bool) { - build_android_lib_impl("client_openxr", profile, link_stdcpp) + build_android_lib_impl("client_openxr", profile, link_stdcpp, false) } -pub fn build_android_client(profile: Profile) { +pub fn build_android_client(profile: Profile, for_meta_store: bool) { let sh = Shell::new().unwrap(); let mut flags = vec![]; @@ -423,6 +410,20 @@ pub fn build_android_client(profile: Profile) { } } + if for_meta_store { + let manifest_path = afs::crate_dir("client_openxr").join("Cargo.toml"); + let mut manifest_string = fs::read_to_string(&manifest_path).unwrap(); + + manifest_string = manifest_string.replace( + r#"package = "alvr.client.stable""#, + r#"package = "alvr.client""#, + ); + manifest_string = + manifest_string.replace(r#"value = "all""#, r#"value = "quest2|questpro|quest3""#); + + fs::write(manifest_path, manifest_string).unwrap(); + } + let _push_guard = sh.push_dir(afs::crate_dir("client_openxr")); cmd!( sh, diff --git a/alvr/xtask/src/dependencies.rs b/alvr/xtask/src/dependencies.rs index 030feb34f3..379719822a 100644 --- a/alvr/xtask/src/dependencies.rs +++ b/alvr/xtask/src/dependencies.rs @@ -315,14 +315,14 @@ fn get_android_openxr_loaders() { "", &format!( "https://github.com/KhronosGroup/OpenXR-SDK-Source/releases/download/{}", - "release-1.0.27/openxr_loader_for_android-1.0.27.aar", + "release-1.0.34/openxr_loader_for_android-1.0.34.aar", ), "prefab/modules/openxr_loader/libs/android.arm64-v8a", ); get_openxr_loader( - "_quest", - "https://securecdn.oculus.com/binaries/download/?id=7092833820755144", // version 60 + "_quest1", + "https://securecdn.oculus.com/binaries/download/?id=7577210995650755", // Version 64 "OpenXR/Libs/Android/arm64-v8a/Release", ); @@ -334,8 +334,8 @@ fn get_android_openxr_loaders() { get_openxr_loader( "_yvr", - "https://developer.yvrdream.com/yvrdoc/sdk/openxr/yvr_openxr_mobile_sdk_1.0.0.zip", - "yvr_openxr_mobile_sdk_1.0.0/OpenXR/Libs/Android/arm64-v8a", + "https://developer.yvrdream.com/yvrdoc/sdk/openxr/yvr_openxr_mobile_sdk_2.0.0.zip", + "yvr_openxr_mobile_sdk_2.0.0/OpenXR/Libs/Android/arm64-v8a", ); get_openxr_loader( @@ -345,7 +345,7 @@ fn get_android_openxr_loaders() { ); } -pub fn build_android_deps(skip_admin_priv: bool) { +pub fn build_android_deps(skip_admin_priv: bool, all_targets: bool) { let sh = Shell::new().unwrap(); update_submodules(&sh); @@ -357,15 +357,17 @@ pub fn build_android_deps(skip_admin_priv: bool) { cmd!(sh, "rustup target add aarch64-linux-android") .run() .unwrap(); - cmd!(sh, "rustup target add armv7-linux-androideabi") - .run() - .unwrap(); - cmd!(sh, "rustup target add x86_64-linux-android") - .run() - .unwrap(); - cmd!(sh, "rustup target add i686-linux-android") - .run() - .unwrap(); + if all_targets { + cmd!(sh, "rustup target add armv7-linux-androideabi") + .run() + .unwrap(); + cmd!(sh, "rustup target add x86_64-linux-android") + .run() + .unwrap(); + cmd!(sh, "rustup target add i686-linux-android") + .run() + .unwrap(); + } cmd!(sh, "cargo install cargo-ndk cbindgen").run().unwrap(); cmd!( sh, diff --git a/alvr/xtask/src/format.rs b/alvr/xtask/src/format.rs index ee91c52878..ef457bf0b8 100644 --- a/alvr/xtask/src/format.rs +++ b/alvr/xtask/src/format.rs @@ -6,7 +6,7 @@ use walkdir::WalkDir; use xshell::{cmd, Shell}; fn files_to_format_paths() -> Vec { - let cpp_dir = afs::crate_dir("server").join("cpp"); + let cpp_dir = afs::crate_dir("server_openvr").join("cpp"); WalkDir::new(cpp_dir) .into_iter() diff --git a/alvr/xtask/src/main.rs b/alvr/xtask/src/main.rs index d13ede79df..2446b3ee84 100644 --- a/alvr/xtask/src/main.rs +++ b/alvr/xtask/src/main.rs @@ -32,7 +32,8 @@ SUBCOMMANDS: format Autoformat all code check-format Check if code is correctly formatted package-streamer Build streamer with distribution profile, make archive - package-launcher Build launcher in release mode, make portable and installer versions + package-launcher Build launcher with distribution profile, make archive + package-client Build client with distribution profile package-client-lib Build client library then zip it clean Removes all build artifacts and dependencies bump Bump streamer and client package versions @@ -52,6 +53,8 @@ FLAGS: --no-rebuild Do not rebuild the streamer with run-streamer --ci Do some CI related tweaks. Depends on the other flags and subcommand --no-stdcpp Disable linking to libc++_shared with build-client-lib + --all-targets For prepare-deps and build-client-lib subcommand, will build for all android supported ABI targets + --meta-store Tweak manifest for Applab compatibility. For package-client subcommand ARGS: --platform Name of the platform (operative system or hardware name). snake_case @@ -167,6 +170,8 @@ fn main() { let appimage = args.contains("--appimage"); let zsync = args.contains("--zsync"); let link_stdcpp = !args.contains("--no-stdcpp"); + let all_targets = args.contains("--all-targets"); + let for_meta_store = args.contains("--meta-store"); let platform: Option = args.opt_value_from_str("--platform").unwrap(); let version: Option = args.opt_value_from_str("--version").unwrap(); @@ -180,7 +185,7 @@ fn main() { "windows" => dependencies::prepare_windows_deps(for_ci), "linux" => dependencies::prepare_linux_deps(!no_nvidia), "macos" => dependencies::prepare_macos_deps(), - "android" => dependencies::build_android_deps(for_ci), + "android" => dependencies::build_android_deps(for_ci, all_targets), _ => panic!("Unrecognized platform."), } } else { @@ -190,16 +195,18 @@ fn main() { dependencies::prepare_linux_deps(!no_nvidia); } - dependencies::build_android_deps(for_ci); + dependencies::build_android_deps(for_ci, all_targets); } } "build-streamer" => { build::build_streamer(profile, true, gpl, None, false, profiling, keep_config) } "build-launcher" => build::build_launcher(profile, true, false), - "build-server-lib" => build::build_server_lib(profile, true, gpl, None, false), - "build-client" => build::build_android_client(profile), - "build-client-lib" => build::build_android_client_core_lib(profile, link_stdcpp), + "build-server-lib" => build::build_server_lib(profile, true, None, false), + "build-client" => build::build_android_client(profile, false), + "build-client-lib" => { + build::build_android_client_core_lib(profile, link_stdcpp, all_targets) + } "build-client-xr-lib" => { build::build_android_client_openxr_lib(profile, link_stdcpp) } @@ -225,8 +232,10 @@ fn main() { } "package-streamer" => packaging::package_streamer(gpl, root, appimage, zsync), "package-launcher" => packaging::package_launcher(appimage), - "package-client" => build::build_android_client(Profile::Distribution), - "package-client-lib" => packaging::package_client_lib(link_stdcpp), + "package-client" => { + build::build_android_client(Profile::Distribution, for_meta_store) + } + "package-client-lib" => packaging::package_client_lib(link_stdcpp, all_targets), "format" => format::format(), "check-format" => format::check_format(), "clean" => clean(), diff --git a/alvr/xtask/src/packaging.rs b/alvr/xtask/src/packaging.rs index 0cfdc9f2cb..ffab3e1f73 100644 --- a/alvr/xtask/src/packaging.rs +++ b/alvr/xtask/src/packaging.rs @@ -123,7 +123,7 @@ pub fn include_licenses(root_path: &Path, gpl: bool) { ) .unwrap(); sh.copy_file( - afs::crate_dir("server").join("LICENSE-Valve"), + afs::crate_dir("server_openvr").join("LICENSE-Valve"), licenses_dir.join("Valve.txt"), ) .unwrap(); @@ -193,10 +193,10 @@ pub fn package_launcher(appimage: bool) { } } -pub fn package_client_lib(link_stdcpp: bool) { +pub fn package_client_lib(link_stdcpp: bool, all_targets: bool) { let sh = Shell::new().unwrap(); - build::build_android_client_core_lib(Profile::Distribution, link_stdcpp); + build::build_android_client_core_lib(Profile::Distribution, link_stdcpp, all_targets); command::zip(&sh, &afs::build_dir().join("alvr_client_core")).unwrap(); } diff --git a/alvr/xtask/src/version.rs b/alvr/xtask/src/version.rs index 7a3967ea28..64f199b49f 100644 --- a/alvr/xtask/src/version.rs +++ b/alvr/xtask/src/version.rs @@ -63,7 +63,7 @@ pub fn check_msrv() { .unwrap(); cmd!( sh, - "cargo msrv verify --output-format json --path alvr/server" + "cargo msrv verify --output-format json --path alvr/server_openvr" ) .run() .unwrap(); @@ -73,4 +73,16 @@ pub fn check_msrv() { ) .run() .unwrap(); + cmd!( + sh, + "cargo msrv verify --output-format json --path alvr/launcher" + ) + .run() + .unwrap(); + cmd!( + sh, + "cargo msrv verify --output-format json --path alvr/client_openxr" + ) + .run() + .unwrap(); } diff --git a/wiki/ALVR-Checklist.md b/wiki/ALVR-Checklist.md index 7e3b1a0faf..64fce47876 100644 --- a/wiki/ALVR-Checklist.md +++ b/wiki/ALVR-Checklist.md @@ -1,5 +1,3 @@ -# ALVR Checklist - ## Hardware Requirements * [ ] Intel Core i5-4590/AMD FX 8350 equivalent or better diff --git a/wiki/ALVR-in-distrobox.md b/wiki/ALVR-in-distrobox.md deleted file mode 100644 index 98c0cc791e..0000000000 --- a/wiki/ALVR-in-distrobox.md +++ /dev/null @@ -1,112 +0,0 @@ -## Installing ALVR and using SteamVR on Linux through Distrobox - -## Disclaimer - -1. This is just an attempt to make things easier for Linux users to use ALVR, SteamVR. By no means it's a comprehensive, fully featured and 100% working guide. Please open new issues and pull requests to correct this guide, scripts, etc etc. - -2. Slimevr, OpenVRAS, Open Space Calibrator are all possible to launch and use on Linux, but this guide/script is not adjusted yet (Medium priority TODO). - -3. Firewall configuration is skipped entirely and setup firewall configuration is broken, so it might not work in case you have strict firewall (alvr docs should have info about that) (Low priority TODO). - -4. This script unlikely to work on external disks. - -## Installing alvr distrobox - -For installing you only really need couple of dependencies on host: - -1. `wget` + `curl` (to download podman/distrobox/alvr/etc) -2. `xhost` (on X11 to allow rootless podman to work with graphical applications) -3. `sed` (for removing color in logs) -4. `pipewire` for fully automatic microphone, `pulseaudio` for basic audio support (automatic microphone is unsupported with it) -5. For nvidia - `CUDA` (distrobox passes through it and driver as well into the container and CUDA contains NVENC encoder for streaming) - -After you have installed required dependencies for your installation from above, open terminal in this repository folder and do: - -1. `./setup.sh` - - That's it. **Follow all green and especially red text carefully from the scripts.** - - In case if have errors during installation, please report the full log as-is (remove private info if you happen to have some) as an Issue. - - After full installation, you can use `./start-alvr.sh` to launch alvr automatically. - - Script also downloads related apk file to install to headset into `installation` folder for you. Use Sidequest or ADB to install it. - -## Post-install ALVR & SteamVR Configuration - -After installing ALVR you may want to configure it and steamvr to run at best quality for your given hardware/gpu. Open up ALVR using `./start-alvr.sh` script and do the following (each field with input value needs enter to confirm): - -### Common configuration: - -1. **Resolution:** If you have 6600 XT, 5700 XT, 2060S level GPU you can select Low, and in case you don't mind lower FPS - Medium - -2. **Preferred framerate:** If you know that you will have lower fps than usual (for instance, VRChat), run at lower fps. This is because when reprojection (this is what allows for smooth view despite being at low fps) goes lower than twice the amount of specified framerate - it fails to reproject and will look worse. So for example, you can run at 72hz if you know you're expecting low framerate, and 120hz if you are going to play something like Beat Saber, which is unlikely to run at low fps. - -3. **Encoder preset:** Speed - -4. **Bitrate:** Constant, bitrate: 350-450 mbps for h264 wireless/700 mbit-1 gbit cabled, 100-150 mbps for HEVC (On Pico 4 you can set up to 220 mbps). - -5. **Foveated rendering:** This highly depends on given headset, but generally default settings should be OK for Quest 2. - - For **pico neo 3** and **pico 4** i would recommend setting center region width to 0.8 and height to 0.75, shifts to 0 and edge ratios can be set at 6-7, and for the same **pico neo 3** disable oculus foveation level and dynamic oculus foveation. - -6. **Color correction:** Set sharpening to 1and if you like oversaturated image, bump saturation to 0.6. - -7. For **pico neo 3** and **pico 4** left controller offsets (from top to bottom): - - Position -0.06, -0.03, -0.1; - - Rotation: 0, 3, 17. - -8. **Connection -> Stream Protocol:** TCP. This ensures that there would be no heavy artifacts if packet loss happens (until it's too severe), only slowdowns. - -### AMD-specific configuration: - -1. Preferred codec: HEVC, h264 works too. - -2. Reduce color banding: turn on, might make image smoother. - -### Nvidia-specific configuration (needs feedback): - -1. Preferred codec: h264, HEVC works too - -After that, restart your headset using power button and it will automatically restart steamvr once, applying all changes. - -### SteamVR configuration: - -Inside SteamVR you also may need to change settings to improve experience. Open settings by clicking on triple stripe on SteamVR window and expand Advanced Settings (Hide -> Show) - -1. **Disable SteamVR Home.** It can be laggy, crashes often and generally not working nice on linux, so it is recommend disabling it altogether. - -2. **Render Resolution:** - Custom and keep it at 100%. This is to ensure that SteamVR won't try to supersample resolution given by ALVR - -3. **Video tab: Fade To Grid** on app hang - this will lock your view to last frame when app hangs instead of dropping you into steamvr void, completely optional but you may prefer that. - -4. **Video tab: Disable Advanced Supersample Filtering** - -5. **Video tab: Per-application video settings** - Use Legacy Reprojection Mode for specific game. **This can drastically change experience from being very uncomfortable, rubber-banding, to straight up perfect**. This essentially disables reprojection on SteamVR side and leaves it to the client. Make sure to enable it for each game you will play. - -6. **Developer tab: Set steamvr as openxr runtime** - this ensures that games using openxr (such as Bonelab, or Beat Saber) will use SteamVR. - But do note that Nvidia owners can't launch openxr unity games due to bug in SteamVR Unity plugin - -### Distrobox note: - -* Do note that `sudo` inside container doesn't have privliges to do anything as `root`, but that container has almost exactly the same rights as regular user, so deleting user files from that container **is** possible. - -* You can add your steam library from outside the container after alvr installation as for container, `/home/user` folder is the same as on your host, so you can add it from inside distrobox steam. - -* Do note though, there has been mentioned some issues with mounted devices, symlinks and containers, so in case you have them, please report them to discover if it's the case. - -## Updating ALVR & WlxOverlay - -In case there was an update for ALVR or WlxOverlay in the repository, you can run `./update-vr-apps.sh` with or without prefix. In case you want to manually update ALVR or WlxOverlay versions, you can change `env.sh` file accordingly and run the same script. - -If you want to switch to Nightly version, all you need to do is set `IS_NIGHTLY` in `env.sh` file and re-run `./update-vr-apps.sh` - -## Uninstalling - -To uninstall this, simply run `./uninstall.sh` and it will automatically remove everything related to locally installed distrobox, it's containers, lilipod and everything inside in `installation-lilipod` or prefixed folder. - -## Additional info - -Highly recommend using CoreCtrl (install it using your distribution package management) and setting settings to VR profile for **AMD** gpus, as well as cpu to performance profile (if it's old Ryzen cpu). Without setting those gpu profiles, it's highly likely you will have serious shutters/wobbles/possibly crashes (sway users) at random point while playing ([[PERF] Subpar GPU performance due to wrong power profile mode · Issue #469 · ValveSoftware/SteamVR-for-Linux · GitHub](https://github.com/ValveSoftware/SteamVR-for-Linux/issues/469)). diff --git a/wiki/Use-ALVR-through-a-USB-connection.md b/wiki/ALVR-wired-setup-(ALVR-over-USB).md similarity index 90% rename from wiki/Use-ALVR-through-a-USB-connection.md rename to wiki/ALVR-wired-setup-(ALVR-over-USB).md index 98b5a63b67..9ab6ca35bd 100644 --- a/wiki/Use-ALVR-through-a-USB-connection.md +++ b/wiki/ALVR-wired-setup-(ALVR-over-USB).md @@ -1,6 +1,4 @@ -# ALVR wired setup (ALVR over USB) - -## ALVR Streamer (PC) Configuration: +## ALVR Streamer (PC) Configuration * **Switch the connection streaming protocol to TCP** in Settings > Connection. * If your headset is detected, click "Trust." Click "Edit", "Add new" and change the IP address to `127.0.0.1`. @@ -12,7 +10,7 @@ The Quest, Pico HMDs are Android devices, therefore, we can use [Android Device You can accomplish this with some pre-made applications/scripts (just below), or run the commands manually with [SideQuest](https://sidequestvr.com/setup-howto) -If you haven't already, connect a USB cable from your PC to your headset. USB 2.0 will work fine but 3.0 and higher is best. +If you haven't already, connect a USB cable from your PC to your headset. USB 2.0 will work fine but 3.0 and higher is best. **Make sure to enable dev account and authorize the computer in your headset if you're on quest or enable USB Debug on Pico in settings.** @@ -26,7 +24,7 @@ The following programs serve to wrap and simplify the process of doing manual AD * Downloads ADB for you * Cross-platform (Windows & Linux) -* [**Python Script**](https://gist.github.com/Bad-At-Usernames/684784f42cbb69e22688a21173ec263d) +* [**Python Script**](https://gist.github.com/Bad-At-Usernames/684784f42cbb69e22688a21173ec263d) * Lightweight and simple * Requires [Python 3](https://www.python.org/downloads/) and [PyWin32](https://pypi.org/project/pywin32/) @@ -38,11 +36,11 @@ The following programs serve to wrap and simplify the process of doing manual AD * Requires [ADB Platform Tools](https://developer.android.com/studio/releases/platform-tools), edit the path in line 2 to point to the directory where you extracted `platform-tools` * Needs to be run every time you (re)connect your headset -### Option 2 - [SideQuest](https://sidequestvr.com/setup-howto): +### Option 2 - [SideQuest](https://sidequestvr.com/setup-howto) * Ensure SideQuest is running, and the headset has authorized the USB connection to the PC * Open the 'Run ADB Commands' menu in SideQuest (top-right, box with an arrow inside it) -* Click 'Custom Command' and run these adb commands: +* Click 'Custom Command' and run these adb commands: * `adb forward tcp:9943 tcp:9943` * `adb forward tcp:9944 tcp:9944` * These commands will need to be run every time you (re)connect your headset. diff --git a/wiki/Building-From-Source.md b/wiki/Building-From-Source.md index 7dd8fe9869..90eb7b8bbd 100644 --- a/wiki/Building-From-Source.md +++ b/wiki/Building-From-Source.md @@ -29,22 +29,19 @@ If you are on Linux, install these additional packages: * `dev-lang/rust >= 1.72` * `media-video/pipewire [jacksdk]` -* **Nix(OS)** - - * Use the `shell.nix` in `packaging/nix`. - * **Debian 12 / Ubuntu 20.04 / Pop!\_OS 20.04** ```bash sudo apt install pulseaudio-utils build-essential pkg-config libclang-dev libssl-dev libasound2-dev libjack-dev libgtk-3-dev libvulkan-dev libunwind-dev gcc yasm nasm curl libx264-dev libx265-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libspeechd-dev libxkbcommon-dev libdrm-dev libva-dev libvulkan-dev vulkan-headers libpipewire-0.3-dev libspa-0.3-dev git ``` - * Note: Libpipewire/libspa must be at least 0.3.49 version - make sure to use upstream pipewire https://github.com/pipewire-debian/pipewire-debian + + * Note: Libpipewire/libspa must be at least 0.3.49 version - make sure to use upstream pipewire * **Fedora** ```bash sudo dnf groupinstall 'Development Tools' | For c++ and build tools - sudo dnf install nasm yasm libdrm-devel vulkan-headers pipewire-jack-audio-connection-kit-devel atk-devel gdk-pixbuf2-devel cairo-devel rust-gdk0.15-devel x264-devel vulkan-devel libunwind-devel clang openssl-devel alsa-lib-devel libva-devel pipewire-devel + sudo dnf install nasm yasm libdrm-devel vulkan-headers pipewire-jack-audio-connection-kit-devel atk-devel gdk-pixbuf2-devel cairo-devel rust-gdk0.15-devel x264-devel vulkan-devel libunwind-devel clang openssl-devel alsa-lib-devel libva-devel pipewire-devel git ``` If you are using Nvidia, see [Fedora cuda installation](https://github.com/alvr-org/ALVR/wiki/Building-From-Source#fedora-cuda-installation) @@ -73,7 +70,7 @@ If you want to edit and rebuild the code, you can skip the `prepare-deps` comman ## Fedora CUDA installation -If you are here for CUDA installation on Fedora you're at the right place! Else continue down to [Client Building](https://github.com/alvr-org/ALVR/wiki/Building-From-Source#client-building) +If you are here for CUDA installation on Fedora you're at the right place! Else continue down to [Android App Building](https://github.com/alvr-org/ALVR/wiki/Building-From-Source#android-app-building) ### 1. Install Nvidia drivers and Fedora CUDA driver @@ -109,7 +106,7 @@ export PATH=/usr/local/cuda-12.3/bin${PATH:+:${PATH}} If your cuda version is different, change it to the version that is installed. You can check installed versions by doing ```ls /usr/local/ | grep "cuda"``` in your terminal -**Comments** +#### Note about Nvidia's CUDA * Disabling the nvidia-driver doesn't disable Nvidia drivers but prevents nvidia dkms from installing over the akmod driver @@ -128,7 +125,7 @@ Then install gcc11 brew install gcc@11 ``` -**Comments** +#### Notes on installing gcc11 with homebrew * If brew is not found in your path, run the following separately to add brew to your path: @@ -148,11 +145,11 @@ From the ALVR directory edit the ./alvr/xtask/src/dependencies.rs, and change tw You should be good to go! Refer to [Streamer Building](https://github.com/alvr-org/ALVR/wiki/Building-From-Source#streamer-building) for the commands to build ALVR -# Client Building +# Android App Building ## 1. Installing necessary packages -For the client you need install: +For the app you need install: * [Android Studio](https://developer.android.com/studio) or the [sdkmanager](https://developer.android.com/studio/command-line/sdkmanager) * Android SDK Platform-Tools 29 (Android 10) @@ -161,13 +158,13 @@ For the client you need install: On Linux, the specific package names for the android tools can differ from distro to distro, see up on the wiki for more information: * Gentoo: - * https://wiki.gentoo.org/wiki/Android + * * Arch: - * https://wiki.archlinux.org/title/Android + * * Debian: - * https://wiki.debian.org/AndroidStudio + * * Ubuntu: - * https://help.ubuntu.com/community/AndroidSDK + * * Pop!\_OS: * N/A @@ -188,7 +185,7 @@ For Debian, it requires to have the `non-free` repository to be enabled: sudo apt install android-sdk-platform-tools-common sdkmanager google-android-ndk-r26b-installer ``` - ## 2. Setting environment variables +## 2. Setting environment variables For Windows, set the environment variables: @@ -202,9 +199,9 @@ For Windows, set the environment variables: For Linux, the correct directories for the environment variables can greatly differ depending on the type of install. See the wiki page of your distro for more information: * Gentoo: - * https://wiki.gentoo.org/wiki/Android + * * Ubuntu: - * https://help.ubuntu.com/community/AndroidSDK#Post-Installation_Configuration + * Distro wikis that weren't listed above does not mention of environment variables, although generally they would be as: @@ -227,7 +224,7 @@ Move to the root directory of the project, then run this command: cargo xtask prepare-deps --platform android ``` -Before building the client, Android has to have us to agree to the licenses otherwise building the client will halt and fail. To accept the agreements, follow the instructions for your corresponding OS: +Before building the app, Android has to have us to agree to the licenses otherwise building the app will halt and fail. To accept the agreements, follow the instructions for your corresponding OS: * Windows: @@ -235,6 +232,7 @@ Before building the client, Android has to have us to agree to the licenses othe cd "%ANDROID_SDK_ROOT%\tools\bin" sdkmanager.bat --licenses ``` + * Linux: ```bash @@ -242,7 +240,7 @@ Before building the client, Android has to have us to agree to the licenses othe sdkmanager --licenses ``` -Next up is the proper build of the client. Run the following: +Next up is the proper build of the app. Run the following: ```bash cargo xtask build-client --release diff --git a/wiki/Hardware-Video-Encoding.md b/wiki/FFmpeg-Hardware-Encoding-Testing.md similarity index 65% rename from wiki/Hardware-Video-Encoding.md rename to wiki/FFmpeg-Hardware-Encoding-Testing.md index 9ac6aca1ea..31abc2a162 100644 --- a/wiki/Hardware-Video-Encoding.md +++ b/wiki/FFmpeg-Hardware-Encoding-Testing.md @@ -1,90 +1,90 @@ -# FFmpeg Hardware Encoding Testing - FFmpeg hardware video offloading test commands to validate hardware encoding offloading is working. -Learn more at: https://trac.ffmpeg.org/wiki/HWAccelIntro +Learn more at: -### Codecs +## Codecs -* **Advanced Video Coding (AVC/h264)** - https://en.wikipedia.org/wiki/Advanced_Video_Coding +* **Advanced Video Coding (AVC/h264)** - - Advanced Video Coding (AVC), also referred to as H.264 or MPEG-4 Part 10, is a video compression standard based on block-oriented, motion-compensated coding. It is by far the most commonly used format for the recording, compression, and distribution of video content. It supports a maximum resolution of 8K UHD. Hardware encoding support is widely available. + Advanced Video Coding (AVC), also referred to as H.264 or MPEG-4 Part 10, is a video compression standard based on block-oriented, motion-compensated coding. It is by far the most commonly used format for the recording, compression, and distribution of video content. It supports a maximum resolution of 8K UHD. Hardware encoding support is widely available. -* **High Efficiency Video Coding (HEVC/h265)** - https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding +* **High Efficiency Video Coding (HEVC/h265)** - - High Efficiency Video Coding (HEVC), also known as H.265 and MPEG-H Part 2, is a video compression standard designed as part of the MPEG-H project as a successor to the widely used Advanced Video Coding (AVC, H.264, or MPEG-4 Part 10). In comparison to AVC, HEVC offers from 25% to 50% better data compression at the same level of video quality, or substantially improved video quality at the same bit rate. It supports resolutions up to 8192×4320, including 8K UHD, and unlike the primarily 8-bit AVC, HEVC's higher fidelity Main 10 profile has been incorporated into nearly all supporting hardware. Hardware encoding support is widely available. + High Efficiency Video Coding (HEVC), also known as H.265 and MPEG-H Part 2, is a video compression standard designed as part of the MPEG-H project as a successor to the widely used Advanced Video Coding (AVC, H.264, or MPEG-4 Part 10). In comparison to AVC, HEVC offers from 25% to 50% better data compression at the same level of video quality, or substantially improved video quality at the same bit rate. It supports resolutions up to 8192×4320, including 8K UHD, and unlike the primarily 8-bit AVC, HEVC's higher fidelity Main 10 profile has been incorporated into nearly all supporting hardware. Hardware encoding support is widely available. -* **AOMedia Video 1 (AV1)** - https://en.wikipedia.org/wiki/AV1 +* **AOMedia Video 1 (AV1)** - - AOMedia Video 1 (AV1) is an open, royalty-free video coding format initially designed for video transmissions over the Internet. It was developed as a successor to VP9 by the Alliance for Open Media (AOMedia). The AV1 bitstream specification includes a reference video codec. Hardware encoding support is limited to latest generation hardware. + AOMedia Video 1 (AV1) is an open, royalty-free video coding format initially designed for video transmissions over the Internet. It was developed as a successor to VP9 by the Alliance for Open Media (AOMedia). The AV1 bitstream specification includes a reference video codec. Hardware encoding support is limited to latest generation hardware. ### Graphics Encoding APIs -* **Video Acceleration API** - https://en.wikipedia.org/wiki/Video_Acceleration_API +* **Video Acceleration API** - + + Video Acceleration API (VA-API) is an open source application programming interface that allows applications such as VLC media player or GStreamer to use hardware video acceleration capabilities, usually provided by the graphics processing unit (GPU). It is implemented by the free and open-source library libva, combined with a hardware-specific driver, usually provided together with the GPU driver. - Video Acceleration API (VA-API) is an open source application programming interface that allows applications such as VLC media player or GStreamer to use hardware video acceleration capabilities, usually provided by the graphics processing unit (GPU). It is implemented by the free and open-source library libva, combined with a hardware-specific driver, usually provided together with the GPU driver. - - Check your current VA-API status with `vainfo`. + Check your current VA-API status with `vainfo`. -* **Vulkan Video** - https://en.wikipedia.org/wiki/Vulkan +* **Vulkan Video** - - Vulkan is a low-level low-overhead, cross-platform API and open standard for 3D graphics and computing. It was intended to address the shortcomings of OpenGL, and allow developers more control over the GPU. It is designed to support a wide variety of GPUs, CPUs and operating systems, it is also designed to work with modern multi-core CPUs. Support is upcoming. See: https://www.khronos.org/blog/khronos-releases-vulkan-video-av1-decode-extension-vulkan-sdk-now-supports-h.264-h.265-encode + Vulkan is a low-level low-overhead, cross-platform API and open standard for 3D graphics and computing. It was intended to address the shortcomings of OpenGL, and allow developers more control over the GPU. It is designed to support a wide variety of GPUs, CPUs and operating systems, it is also designed to work with modern multi-core CPUs. Support is upcoming. See: -* **NVENC** - https://en.wikipedia.org/wiki/Nvidia_NVENC +* **NVENC** - - Nvidia NVENC is a feature in Nvidia graphics cards that performs video encoding, offloading this compute-intensive task from the CPU to a dedicated part of the GPU. + Nvidia NVENC is a feature in Nvidia graphics cards that performs video encoding, offloading this compute-intensive task from the CPU to a dedicated part of the GPU. -* **AMD Advanced Media Framework**- https://gpuopen.com/advanced-media-framework/ +* **AMD Advanced Media Framework**- - AMD AMF is a SDK for optimal access to AMD GPUs for multimedia processing. + AMD AMF is a SDK for optimal access to AMD GPUs for multimedia processing. ### Test Source Input Generation + Please note that using the test source for input generation induces CPU load. When monitoring for proper GPU offloading, there will still be expected CPU load from FFmpeg. -``` +```sh ffmpeg -hide_banner -f lavfi -i testsrc2=duration=30:size=1280x720:rate=90 ``` -* **lavfi** - https://ffmpeg.org/ffmpeg-devices.html#toc-lavfi +* **lavfi** - + + Libavfilter input virtual device. This input device reads data from the open output pads of a libavfilter filtergraph. For each filtergraph open output, the input device will create a corresponding stream which is mapped to the generated output. The filtergraph is specified through the option graph. - Libavfilter input virtual device. This input device reads data from the open output pads of a libavfilter filtergraph. For each filtergraph open output, the input device will create a corresponding stream which is mapped to the generated output. The filtergraph is specified through the option graph. +* **testsrc2** - -* **testsrc2** - https://ffmpeg.org/ffmpeg-filters.html#allrgb_002c-allyuv_002c-color_002c-colorchart_002c-colorspectrum_002c-haldclutsrc_002c-nullsrc_002c-pal75bars_002c-pal100bars_002c-rgbtestsrc_002c-smptebars_002c-smptehdbars_002c-testsrc_002c-testsrc2_002c-yuvtestsrc + The `testsrc2` source generates a test video pattern, showing a color pattern, a scrolling gradient and a timestamp. This is mainly intended for testing purposes. The `testsrc2` source is similar to `testsrc`, but supports more pixel formats instead of just `rgb24`. This allows using it as an input for other tests without requiring a format conversion. - The `testsrc2` source generates a test video pattern, showing a color pattern, a scrolling gradient and a timestamp. This is mainly intended for testing purposes. The `testsrc2` source is similar to `testsrc`, but supports more pixel formats instead of just `rgb24`. This allows using it as an input for other tests without requiring a format conversion. - - 1) duration - how long of a clip in seconds - 2) size - dimensions of the video - 3) rate - frame rate per second + 1) duration - how long of a clip in seconds + 2) size - dimensions of the video + 3) rate - frame rate per second ### Render Playback + Use your favorite video player to verify the video was rendered correctly. -* MPV - https://en.wikipedia.org/wiki/Mpv_(media_player) +* MPV - - mpv is free and open-source media player software based on MPlayer, mplayer2 and FFmpeg. It runs on several operating systems, including Unix-like operating systems (Linux, BSD-based, macOS) and Microsoft Windows, along with having an Android port called mpv-android. It is cross-platform, running on ARM, PowerPC, x86/IA-32, x86-64, and MIPS architecture. + mpv is free and open-source media player software based on MPlayer, mplayer2 and FFmpeg. It runs on several operating systems, including Unix-like operating systems (Linux, BSD-based, macOS) and Microsoft Windows, along with having an Android port called mpv-android. It is cross-platform, running on ARM, PowerPC, x86/IA-32, x86-64, and MIPS architecture. -* VLC - https://en.wikipedia.org/wiki/VLC_media_player +* VLC - - VLC media player (previously the VideoLAN Client and commonly known as simply VLC) is a free and open-source, portable, cross-platform media player software and streaming media server developed by the VideoLAN project. VLC is available for desktop operating systems and mobile platforms, such as Android, iOS and iPadOS. VLC is also available on digital distribution platforms such as Apple's App Store, Google Play, and Microsoft Store. + VLC media player (previously the VideoLAN Client and commonly known as simply VLC) is a free and open-source, portable, cross-platform media player software and streaming media server developed by the VideoLAN project. VLC is available for desktop operating systems and mobile platforms, such as Android, iOS and iPadOS. VLC is also available on digital distribution platforms such as Apple's App Store, Google Play, and Microsoft Store. ### Nvidia GPU -Test the Nvidia hardware encoding pipeline. Only NVENC is supported as the current Nvidia VA-API driver (https://github.com/elFarto/nvidia-vaapi-driver) only supports NVDEC. Check your hardware support at https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new for NVENC support. -Monitoring utilities: +Test the Nvidia hardware encoding pipeline. Only NVENC is supported as the current Nvidia VA-API driver () only supports NVDEC. Check your hardware support at for NVENC support. -* **nvtop** - https://github.com/Syllo/nvtop +Monitoring utilities: - NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel and NVIDIA GPUs. It can handle multiple GPUs and print information about them in a htop-familiar way. +* **nvtop** - -* **nvidia-smi pmon** - https://developer.nvidia.com/nvidia-system-management-interface + NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel and NVIDIA GPUs. It can handle multiple GPUs and print information about them in a htop-familiar way. - The NVIDIA System Management Interface (nvidia-smi) is a command line utility, based on top of the NVIDIA Management Library (NVML), intended to aid in the management and monitoring of NVIDIA GPU devices. The `pmon` command lists the statistics for all the compute and graphics processes running on each device. +* **nvidia-smi pmon** - + The NVIDIA System Management Interface (nvidia-smi) is a command line utility, based on top of the NVIDIA Management Library (NVML), intended to aid in the management and monitoring of NVIDIA GPU devices. The `pmon` command lists the statistics for all the compute and graphics processes running on each device. Nvenc AVC (h264) hardware encoding: -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -c:v h264_nvenc -qp 18 \ @@ -93,7 +93,7 @@ nvidia-h264_nvec-90fps-300s.mp4 Nvenc HEVC (h265) hardware encoding: -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -c:v hevc_nvenc -qp 18 \ @@ -102,7 +102,7 @@ nvidia-hevc_nvec-90fps-300s.mp4 Nvenc AV1 hardware encoding (Ada Lovelace or newer hardware): -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -c:v av1_nvenc -qp 18 \ @@ -110,17 +110,18 @@ nvidia-av1_nvec-90fps-300s.mp4 ``` ### Intel GPU -Test the Intel hardware encoding pipeline. Only VA-API is supported with the intel-media-driver (https://github.com/intel/media-driver) on GEN based graphics hardware. Check your hardware support at https://www.intel.com/content/www/us/en/docs/onevpl/developer-reference-media-intel-hardware/1-1/overview.html for encoding codec support. + +Test the Intel hardware encoding pipeline. Only VA-API is supported with the intel-media-driver () on GEN based graphics hardware. Check your hardware support at for encoding codec support. Monitoring utilities: -* **nvtop** - https://github.com/Syllo/nvtop +* **nvtop** - - NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel and NVIDIA GPUs. It can handle multiple GPUs and print information about them in a htop-familiar way. + NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel and NVIDIA GPUs. It can handle multiple GPUs and print information about them in a htop-familiar way. VA-API AVC (h264) hardware encoding: -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \ @@ -130,7 +131,7 @@ intel-h264_vaapi-90fps-300s.mp4 VA-API HEVC (h265) hardware encoding: -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \ @@ -140,7 +141,7 @@ intel-hevc_vaapi-90fps-300s.mp4 VA-API AV1 hardware encoding (Arc A-Series only): -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \ @@ -149,17 +150,18 @@ intel-av1_vaapi-90fps-300s.mp4 ``` ### AMD GPU -Test the AMD hardware encoding pipeline. Only VA-API is supported with the mesa-va-drivers (https://mesa3d.org/) on AMD based graphics hardware. Check your hardware support at https://en.wikipedia.org/wiki/Unified_Video_Decoder for encoding codec support. Video Core Next (VCN) hardware is required for hardware encoding. + +Test the AMD hardware encoding pipeline. Only VA-API is supported with the mesa-va-drivers () on AMD based graphics hardware. Check your hardware support at for encoding codec support. Video Core Next (VCN) hardware is required for hardware encoding. Monitoring utilities: -* **nvtop** - https://github.com/Syllo/nvtop +* **nvtop** - - NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel and NVIDIA GPUs. It can handle multiple GPUs and print information about them in a htop-familiar way. + NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel and NVIDIA GPUs. It can handle multiple GPUs and print information about them in a htop-familiar way. VA-API AVC (h264) hardware encoding: -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \ @@ -169,7 +171,7 @@ amd-h264_vaapi-90fps-300s.mp4 VA-API HEVC (h265) hardware encoding: -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \ @@ -179,11 +181,10 @@ amd-hevc_vaapi-90fps-300s.mp4 VA-API AV1 hardware encoding (VCN 4.0+, Navi 3x only): -``` +```sh ffmpeg -hide_banner \ -f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \ -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \ -c:v av1_vaapi -qp 18 \ amd-av1_vaapi-90fps-300s.mp4 ``` - diff --git a/wiki/Fixed-Foveated-Rendering-(FFR).md b/wiki/Fixed-Foveated-Rendering-(FFR).md index b7752144d8..c93e355a80 100644 --- a/wiki/Fixed-Foveated-Rendering-(FFR).md +++ b/wiki/Fixed-Foveated-Rendering-(FFR).md @@ -1,5 +1,3 @@ -# Fixed Foveated Rendering (FFR) - ## What is it, why do I need it In short: The human eye can only see sharp in a very small area (the fovea). That's why we move our eyes constantly to get the feeling that our whole view is a sharp image. diff --git a/wiki/ALVR-client-and-streamer-on-separate-networks.md b/wiki/Headset-and-ALVR-streamer-on-separate-networks.md similarity index 70% rename from wiki/ALVR-client-and-streamer-on-separate-networks.md rename to wiki/Headset-and-ALVR-streamer-on-separate-networks.md index 81ad535817..69e877be22 100644 --- a/wiki/ALVR-client-and-streamer-on-separate-networks.md +++ b/wiki/Headset-and-ALVR-streamer-on-separate-networks.md @@ -1,9 +1,14 @@ -# Headset and ALVR streamer on separate networks - -# ALVR v14 and Above +## ALVR v14 and Above Here are explained two methods to connect PC and headset remotely, port-forwarding and ZeroTier. The primary purpose of this is connecting the headset to a Cloud PC (like ShadowPC). +## Important notes on security + +* ALVR protocol does not have any encryption or authentication (apart from ALVR device IP address shown in ALVR streamer and the requirement to add devices on ALVR streamer). +* It is recommended to run ALVR via encrypted tunnel (VPN) over the internet. In case VPN is not an option, access to ALVR streamer (UDP ports 9943 and 9944) should be restricted by Windows Firewall (only connections from known IP addresses of ALVR devices should be allowed) and ALVR streamer should not be left running unattended. +* **Warning!** SteamVR allows to control desktop from VR headset (i.e. a **malicious ALVR device could take over the PC**). +* As the license states ALVR IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND (see the file `LICENSE` in this GitHub repository for legal text/definition). You are on your own (especially if you run ALVR over the Internet without VPN). + ## Port-forwarding Port-forwarding allows to connect devices that are behind different NATs, i.e. local networks. You need to have administrator access to your router. This method has the best streaming performance. @@ -16,7 +21,7 @@ Port-forwarding allows to connect devices that are behind different NATs, i.e. l You can now use ALVR to connect to your remote PC. -**Note**: The public IP can change often. Every time you want to use ALVR you need to check that your current public IP is the same as the last time. If the IP changed, you can update it using the "Configure client" interface, accessed with the `Configure` button next to your headset name on the streamer. +**Note**: The public IP can change often. Every time you want to use ALVR you need to check that your current public IP is the same as the last time. If the IP changed, you can update it using the "Edit connection" interface, accessed with the `Edit` button next to your headset name on the streamer. ## ZeroTier @@ -30,39 +35,39 @@ Pros: * You don't need to update the public IP often on the streamer. * The connection in encrypted. -Cons: +Cons: * The streaming performance is worse. You may experience more glitches and loss of quality in the image and audio. ### Requirements -- [ZeroTier](https://www.zerotier.com/) for your PC -- ZeroTier APK for your Quest (you can find it online) -- SideQuest or some other method to install the ZeroTier APK onto your headset +* [ZeroTier](https://www.zerotier.com/) for your PC +* ZeroTier APK for your Quest (you can find it online) +* SideQuest or some other method to install the ZeroTier APK onto your headset ### Installation -Use the "Install APK" function of SideQuest to install the ZeroTier APK to your Quest, and also download and install ZeroTier on your PC. After you've installed ZeroTier, follow Zerotier's official [Getting Started](https://zerotier.atlassian.net/wiki/spaces/SD/pages/8454145/Getting+Started+with+ZeroTier) guide to setup a network for ALVR. Join the network on both the Quest and the PC. On the Quest, make sure that the network is enabled by switching on the slider on the network in the list in the ZeroTier app (you may be prompted to allow ZeroTier to create a VPN connection). +Use the "Install APK" function of SideQuest to install the ZeroTier APK to your Quest, and also download and install ZeroTier on your PC. After you've installed ZeroTier, follow Zerotier's official [Getting Started](https://zerotier.atlassian.net/wiki/spaces/SD/pages/8454145/Getting+Started+with+ZeroTier) guide to setup a network for ALVR. Join the network on both the Quest and the PC. On the Quest, make sure that the network is enabled by switching on the slider on the network in the list in the ZeroTier app (you may be prompted to allow ZeroTier to create a VPN connection). -After both your PC and your Quest are connected to the same ZeroTier network, we'll need to manually add your quest to the ALVR dashboard. To do so, we'll need to find your Quest's ZeroTier IP. There are two ways to do this. +After both your PC and your Quest are connected to the same ZeroTier network, we'll need to manually add your quest to the ALVR dashboard. To do so, we'll need to find your Quest's ZeroTier IP. There are two ways to do this. -- Go the the ZeroTier network page, find your quest under "Members", and copy the managed IP from there -- Or, in the ZeroTier app on your quest, click on the network you created. The IP is under the "Managed IPs" section at the bottom. +* Go the the ZeroTier network page, find your quest under "Members", and copy the managed IP from there +* Or, in the ZeroTier app on your quest, click on the network you created. The IP is under the "Managed IPs" section at the bottom. -The IP should look something like this `192.168.143.195`. If there's a `/` at the end with a couple numbers following it, remove them along with the slash. +The IP should look something like this `192.168.143.195`. If there's a `/` at the end with a couple numbers following it, remove them along with the slash. -Next, we'll need to add the Quest to the ALVR dashboard. On your headset, launch ALVR. The on the ALVR dashboard on your PC, click the "Add device manually" button, provide a name and hostname (You can get this from the "trust" screen of ALVR on your Quest), then put in the IP address that we got from ZeroTier. +Next, we'll need to add the Quest to the ALVR dashboard. On your headset, launch ALVR. The on the ALVR dashboard on your PC, click the "Add device manually" button, provide a name and hostname (You can get this from the "trust" screen of ALVR on your Quest), then put in the IP address that we got from ZeroTier. At this point, you should be ready to go. Have fun in VR! ### Troubleshooting -- If you can't get your Quest to connect to ALVR, and are stuck on the "Trust" screen, try to ping your Quest's managed IP address (the one we got earlier). If it says "no route to host" or something similar, your Quest can't see your PC. Try running through the steps above to make sure you didn't miss anything. +* If you can't get your Quest to connect to ALVR, and are stuck on the "Trust" screen, try to ping your Quest's managed IP address (the one we got earlier). If it says "no route to host" or something similar, your Quest can't see your PC. Try running through the steps above to make sure you didn't miss anything. ## Tailscale An alternative to ZeroTier with practically the same setup procedure. This could have better latency, depending on your distance to the datacenter. -https://tailscale.com/ + ## n2n @@ -72,46 +77,39 @@ Its pros and cons are similar to ZeroTier, but it's self-hosted and open-source ### Requirements -- Compile [n2n](https://github.com/ntop/n2n) from source - - Or you can grab pre-built binaries from [here](https://github.com/lucktu/n2n) directly, compiled by lucktu. - - Some Linux distribution may have n2n, but be sure you're using the same version. Since the source code is v3, the following steps will also use v3 in the example below. -- [TAP-Windows driver](https://community.openvpn.net/openvpn/wiki/GettingTapWindows) or [OpenVPN](https://openvpn.net/community/) (includes TAP-Windows) if you're using Windows PC -- [hin2n](https://github.com/switch-iot/hin2n) APK -- A server with public IP and allow public ports -- SideQuest or some other method to install the hin2n APK onto your headset +* Compile [n2n](https://github.com/ntop/n2n) from source + * Or you can grab pre-built binaries from [here](https://github.com/lucktu/n2n) directly, compiled by lucktu. + * Some Linux distribution may have n2n, but be sure you're using the same version. Since the source code is v3, the following steps will also use v3 in the example below. +* [TAP-Windows driver](https://community.openvpn.net/openvpn/wiki/GettingTapWindows) or [OpenVPN](https://openvpn.net/community/) (includes TAP-Windows) if you're using Windows PC +* [hin2n](https://github.com/switch-iot/hin2n) APK +* A server with public IP and allow public ports +* SideQuest or some other method to install the hin2n APK onto your headset ### Installation We're going to use n2n v3, and set the port of _supernode_ to `1234` as the example. You can change `1234` to any port, but below `1024` requires root. -- Open port `1234` on your server's firewall (usually `iptables`, if you don't know what to do, ask Google). -- Upload _supernode_ binary to your server, run `./supernode -p 1234`. -- Install TAP-Windows driver or OpenVPN on your PC if you're using Windows. -- Upload _edge_ binary to your PC, run `./edge -c [network-name] -k [secret-password] -a 192.168.100.1 -l [your-server-ip]:1234` to connect to the _supernode_, assign the IP `192.168.100.1` to the PC, and use the password you provided for data encryption. -- Once you see `[OK] edge <<< ================ >>> supernode`, your PC is done, or you need to follow the error logs to see what's wrong. -- Install _hin2n_ on your Quest and open it, click the plus button at the top-right corner to add a new configuration and assign `192.168.100.2` to your Quest: - - N2N version: v3 - - Supernode: `[your-server-ip]:1234` - - Community: `[network-name]` - - Encrypt key: `[secret-password]` - - IP address: `192.168.100.2` - - Subnet mask: `255.255.255.0` -- Click "Current Setting" under the connect button, select the configuration we created just now, then click the connect button. If you're asked to allow hin2n to create a VPN connection, allow it. -- Once you see `[OK] edge <<< ================ >>> supernode`, your Quest is done. -- Open ALVR on your headset, record the hostname it shows. -- Open ALVR dashboard on your PC, click "Add device manually" button, put the hostname you just recorded, and set IP address to `192.168.100.2` which is assigned to Quest just now. -- Once it's done, you're all set. +* Open port `1234` on your server's firewall (usually `iptables`, if you don't know what to do, ask Google). +* Upload _supernode_ binary to your server, run `./supernode -p 1234`. +* Install TAP-Windows driver or OpenVPN on your PC if you're using Windows. +* Upload _edge_ binary to your PC, run `./edge -c [network-name] -k [secret-password] -a 192.168.100.1 -l [your-server-ip]:1234` to connect to the _supernode_, assign the IP `192.168.100.1` to the PC, and use the password you provided for data encryption. +* Once you see `[OK] edge <<< ================ >>> supernode`, your PC is done, or you need to follow the error logs to see what's wrong. +* Install _hin2n_ on your Quest and open it, click the plus button at the top-right corner to add a new configuration and assign `192.168.100.2` to your Quest: + * N2N version: v3 + * Supernode: `[your-server-ip]:1234` + * Community: `[network-name]` + * Encrypt key: `[secret-password]` + * IP address: `192.168.100.2` + * Subnet mask: `255.255.255.0` +* Click "Current Setting" under the connect button, select the configuration we created just now, then click the connect button. If you're asked to allow hin2n to create a VPN connection, allow it. +* Once you see `[OK] edge <<< ================ >>> supernode`, your Quest is done. +* Open ALVR on your headset, record the hostname it shows. +* Open ALVR dashboard on your PC, click "Add device manually" button, put the hostname you just recorded, and set IP address to `192.168.100.2` which is assigned to Quest just now. +* Once it's done, you're all set. ### Troubleshooting -- Make sure you can access to the supernode, your supernode should be run on a server with public IP, and you can ping it on your PC. -- If your Quest cannot connect to ALVR dashboard, ping the IP you assigned to Quest in hin2n. If it fails, try redoing the setup steps. -- If the edge binary or hin2n says the IP has already been assigned and not released by supernode, you can set IP address to another one in the same subnet like `192.168.100.123` to reassign a new IP to the device. -- If you're playing over WAN, you may see more glitches, higher stream latency, or lagger response with TCP. Use adaptive bitrate and UDP may improve your experience. - -**Important notes on security!** - -* ALVR protocol does not have any encryption or authentication (apart from ALVR client IP address shown in ALVR streamer and the requirement to click _Connect_ on ALVR streamer). -* It is recommended to run ALVR via encrypted tunnel (VPN) over the internet. In case VPN is not an option, access to ALVR streamer (UDP ports 9943 and 9944) should be restricted by Windows Firewall (only connections from known IP addresses of ALVR clients should be allowed) and ALVR streamer should not be left running unattended. -* **Warning!** SteamVR allows to control desktop from VR headset (i.e. a **malicious ALVR client could take over the PC**). -* As the license states ALVR IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND (see the file `LICENSE` in this GitHub repository for legal text/definition). You are on your own (especially if you run ALVR over the Internet without VPN). +* Make sure you can access to the supernode, your supernode should be run on a server with public IP, and you can ping it on your PC. +* If your Quest cannot connect to ALVR dashboard, ping the IP you assigned to Quest in hin2n. If it fails, try redoing the setup steps. +* If the edge binary or hin2n says the IP has already been assigned and not released by supernode, you can set IP address to another one in the same subnet like `192.168.100.123` to reassign a new IP to the device. +* If you're playing over WAN, you may see more glitches, higher stream latency, or lagger response with TCP. Use adaptive bitrate and UDP may improve your experience. diff --git a/wiki/Home.md b/wiki/Home.md index d09dedb107..9f03e12f58 100644 --- a/wiki/Home.md +++ b/wiki/Home.md @@ -1,3 +1,3 @@ -ALVR is a piece of software to stream SteamVR games to your standalone VR headset. +ALVR is a vr streaming software that allows you to stream SteamVR games to your standalone VR headset. Use the sidebar to navigate the wiki. diff --git a/wiki/How-ALVR-works.md b/wiki/How-ALVR-works.md index 6ad5cec08f..a0b3ef0c57 100644 --- a/wiki/How-ALVR-works.md +++ b/wiki/How-ALVR-works.md @@ -1,5 +1,3 @@ -# How ALVR works - This document details some technologies used by ALVR. If you have any doubt about what is (or isn't) written in here you can contact @zarik5, preferably on Discord. diff --git a/wiki/Configuration-Information-and-Recommendations.md b/wiki/Information-and-Recommendations.md similarity index 71% rename from wiki/Configuration-Information-and-Recommendations.md rename to wiki/Information-and-Recommendations.md index bed16f3f19..8ed632bccd 100644 --- a/wiki/Configuration-Information-and-Recommendations.md +++ b/wiki/Information-and-Recommendations.md @@ -1,40 +1,38 @@ -# Information and Recommendations - -# PC +## PC - A high-end PC is a requirement; ALVR is not a cheap alternative to a PCVR HMD -- ALVR resolution configuration and SteamVR multi-sampling may be used to influence quality in favor of performance or vice-versa -- Frequent dropped frames can cause a poor experience on ALVR; this can be verified using a tool such as [OVR Advanced Settings](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings) -- Higher bit-rates will cause higher latency -- Ensure all relevant software is up to date; especially graphics and network drivers -- A good starting point is 100% resolution and 30mbit- 200kb buffer settings. In this config it should be butter smooth with almost no lag or packet loss; packet loss seen at this point is likely a result of network issues +- ALVR resolution configuration and SteamVR multi-sampling may be used to influence quality in favor of performance or vice-versa. +- Frequent dropped frames can cause a poor experience on ALVR; this can be verified using a tool such as [OVR Advanced Settings](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings). +- Higher bit-rates will cause higher latency. +- Ensure all relevant software is up to date - especially graphics and network drivers. +- A good starting point is 100% resolution (`Very low` resolution preset) and 30mbit constant bitrate. In this config it should be very smooth with almost no lag or packet loss; packet loss seen at this point is likely a result of network issues. -# Network +## Network -- A wired connection from the PC to the network is **strongly recommended** -- A modern mid to high-end router and / or access point supporting at least 802.11AC (ideally 802.11AX) with regularly updated firmware is recommended +- A wired connection from the PC to the network is **strongly recommended**. +- A modern mid to high-end router and / or access point supporting at least 802.11ac (ideally 802.11ax) is recommended. ## Wireless -### General WiFi configuration best practices: +### General WiFi configuration best practices -- Any device that can be wired should be; each wireless device slows down the overall wireless network -- Devices should have the fewest obstructions and be as close to the access point or router as possible +- Any device that can be wired should be - each wireless device slows down the overall wireless network +- Devices should have the least amount of obstructions and be as close to the access point or router as possible - Any other wireless networks (ex: a printer's default wireless network) should be disabled; each network slows others down - Any devices that do not need high speeds but support them (ex: a thermostat) should use 2.4Ghz; often middle and higher end access points and routers support methods to "force" clients to use 2.4Ghz, and some can even perform this automatically based on signal strength and connection speed -- Only WiFi revisions which are necessary should be enabled; older standards such as 802.11B, 802.11G, and to a lesser extent, 802.11N, will slow down all clients -- Devices that require high speeds should use: - - 5Ghz only - - The newest WiFi specifications (802.11AX, followed by 802.11AC) - - In most environments, the largest channel width possible (160MHz for 802.11AX, 80MHz in practice for 802.11AC) (**note: some vendors do not set this to the maximum by default**) +- Only WiFi revisions which are necessary should be enabled; older standards such as 802.11b, 802.11g, and to a lesser extent, 802.11n, will slow down all clients +- Devices that require high speeds (such as standalone headset) should use: + - 5GHz only + - The newest WiFi specifications (802.11ax, followed by 802.11ac) + - In most environments, the largest channel width possible (160MHz for 802.11ax, 80MHz in practice for 802.11ac) (**note: some vendors do not set this to the maximum by default**) - The lowest utilization, followed by the lowest channel number (sub-frequency) possible -- **Manually selecting channels should only be done in places with extreme noise, or on older, lower quality, or ISP provided access points or routers** ; modern mid to high-end routers and access points should optimize their channels fairly well, and as a result of other routers and clients "channel hopping", static settings are often less optimal -- If a specific WiFi channel range is absolutely necessary, use a WiFi scanning tool on a phone or PC to determine the least used channels; mid to high-end access points and routers may provide an interface for this as well, however, this sometimes causes a disconnect when scanning -- **Manually selecting wifi signal strength should only be done in places with extreme noise**; modern routers and access points do this well, and it is a complex task -- If a specific transmit power is necessary, keep in mind that stronger is not always better; as transmit power increases, distortion may increase (leading to *lower* speeds), battery life of clients may increase (due to the higher power requested by the access point or router), and issues with sticky clients (devices which stay connected to wifi even with bad signal) may appear +- **Manually selecting channels should only be done in places with extreme noise, or on older, lower quality, or ISP provided access points or routers** - modern mid to high-end routers and access points should optimize their channels fairly well, and as a result of other routers and clients "channel hopping", static settings are often less optimal +- If a specific WiFi channel range is absolutely necessary, use a WiFi scanning tool on a phone or PC to determine the least used channels - mid to high-end access points and routers may provide an interface for this as well, however, this sometimes causes a disconnect when scanning +- **Manually selecting wifi signal strength should only be done in places with extreme noise** - modern routers and access points do this well, and it is a complex task +- If a specific transmit power is necessary, keep in mind that stronger is not always better - as transmit power increases, distortion may increase (leading to *lower* speeds), battery life of clients may increase (due to the higher power requested by the access point or router), and issues with sticky clients (devices which stay connected to wifi even with bad signal) may appear - If you have a significant number of devices, some routers and access points support features such as airtime fairness, which help to limit the amount of airtime slower clients take, improving the performance of higher speed clients -### Things to keep in mind when configuring a wireless network and devices: +### Things to keep in mind when configuring a wireless network and devices - All devices on the same frequency impact each other (**including other WiFi networks on the same channel**) because only one device can transmit or receive data at a time, meaning that: - If one device utilizes WiFi heavily it will impact the latency and throughput of all other clients @@ -47,22 +45,22 @@ ## Routing / Switching / Firewalling / General Info -- Ideally client and streamer should live on the same logical (layer 2) network and subnet; this allows for no routing overhead, and the correct function of client discovery via mDNS -- Twisted pair (normal copper ethernet cables) should never be run alongside power cables; this can cause signal noise and result in frame loss and lowered auto-negotiation speeds -- High quality CAT5E or higher (ideally CAT6A or CAT7) cabling should be used for modern networks -- In some cases firewall, anti-virus, malware, or EDR (enhanced detection and response) software may interfere with network traffic; Windows Defender and Sophos Endpoint Protection are reported to work without issue +- Ideally the headset and streamer should exist on the same logical (layer 2) network and subnet - this allows for no routing overhead, and the correct function of device discovery via [mDNS](https://en.wikipedia.org/wiki/Multicast_DNS) +- Twisted pair (normal copper ethernet cables) should never be run alongside power cables - this can cause signal noise and result in frame loss and lowered auto-negotiation speeds +- High quality CAT5E or higher (ideally CAT6A or CAT7) gigabit+ cabling should be used for modern networks +- In some cases firewall, anti-virus, malware, or EDR (enhanced detection and response) software may interfere with network traffic - Windows Defender and Sophos Endpoint Protection are reported to work without issue - Pause frames should be disabled where possible, as these introduce additional latency and buffering *** Someone did a few blog-posts on some of the points: -https://imaginevr.home.blog/author/imaginevrresearch/ + Some points came from [FingrMastr](https://github.com/FingrMastr) -# Linux +## Linux -## Encoder requirements +### Encoder requirements ALVR uses FFmpeg for all encoders, so you will need to make sure the encoder of your choice works with FFmpeg. Always consult Log tab in dashboard, it will tell you the reason why an encoder failed to initialize. @@ -97,7 +95,7 @@ vainfo: Supported profile and entrypoints *VAProfileH264High, VAProfileHEVCMain, VAProfileHEVCMain10* encoders (VAEntrypointEncSlice) required. If you don't see those in your output, your driver install is incorrect or your distribution decided to build *mesa* without non-free codecs. -**Test ffmpeg commands** +#### Test ffmpeg commands (VAAPI) ```sh # H264 @@ -107,11 +105,11 @@ ffmpeg -vaapi_device /dev/dri/renderD128 -f lavfi -i testsrc -t 30 -vf 'format=n ffmpeg -vaapi_device /dev/dri/renderD128 -f lavfi -i testsrc -t 30 -vf 'format=nv12,hwupload' -c:v hevc_vaapi vaapi-hevc.mp4 ``` -### NVENC (NVidia) +### NVENC (Nvidia) Requires *libcuda*. -**Test ffmpeg commands** +#### Test ffmpeg commands (Nvidia) ```sh # H264 @@ -121,18 +119,7 @@ ffmpeg -f lavfi -i testsrc -t 30 -vf 'format=nv12,hwupload' -c:v h264_nvenc nven ffmpeg -f lavfi -i testsrc -t 30 -vf 'format=nv12,hwupload' -c:v hevc_nvenc nvenc-hevc.mp4 ``` -### Software (all GPUs) +### Software (any GPUs) Software encoder is mainly used as a fallback and as such should work on all GPUs without any requirements. Only H264 encoding is currently supported. - -## Legacy Reprojection - -SteamVR by default will still use async reprojection for all games, which can cause issues such as: - -- Ghosting -- Jumpy framerate -- Jittery movement -- General unsmoothness - And all other sorts of issues. Turning on Legacy Reprojection in the per game video settings inside SteamVR will effectively disable - any reprojection making the experience far better. diff --git a/wiki/Installation-guide.md b/wiki/Installation-guide.md index 352d56b516..0d6b761494 100644 --- a/wiki/Installation-guide.md +++ b/wiki/Installation-guide.md @@ -1,114 +1,86 @@ -# Installation guide +## Launcher (BETA) -## Basic installation +Launcher will allow you to manage old, current and new installations of ALVR streamer and allow to automatically install and upgrade to specific ALVR app version on headset -PC side: +### Installation -* Install SteamVR, **launch it once** then close it. This is to make sure it sets the environment correctly for ALVR. -* Go to the latest release [download page](https://github.com/alvr-org/ALVR/releases/latest). In the "Assets" section at the bottom download the ALVR Installer. -* Run the installer. If prompted, allow the execution in the SmartScreen popup. You need to give administrator permissions to install ALVR. For best compatibility do not change the installation folder. -* Once the installation finished, launch ALVR. You are greeted with a setup wizard. Follow the setup to set the firewall rules and presets. - -**If you have problems launching ALVR, follow the guide below to use the portable version** - -Headset side: - -* Install SideQuest on your PC and enable developer mode on the headset. You can follow [this guide](https://sidequestvr.com/setup-howto). -* Connect your headset to Sidequest. If you have an Oculus Quest 1/2 download the ALVR app [here](https://sidequestvr.com/app/9), if you have an Oculus Go download it [here](https://sidequestvr.com/app/2658) +* Download `alvr_launcher_windows.zip` (on Windows) or `alvr_launcher_linux.tar.gz` (on Linux) from the release [download page](https://github.com/alvr-org/ALVR/releases/latest) and extract into a path that contains only ASCII characters (english only) and has edit permissions without administrator or root rights. +* Run `ALVR Launcher.exe` (on Windows) or `alvr_launcher_linux/ALVR Launcher` (on Linux) +* Press `Add version` button +* For default installation keep channel and version as is and press `Install` +* Wait until it finishes downloading, installing (depends on your connection) +* To install ALVR app on headset, use button `Install APK` +* In the list, to open streamer app (PC) press `Launch`. You will be greeted with a setup wizard. Follow the setup to set the firewall rules and other settings. ### Usage -* Launch ALVR on your headset. While the headset screen is on, click `Trust` next to the client entry (on the PC) to start streaming. +* Before launching SteamVR through ALVR, please install it. First time launch will result in steamvr being blank and alvr will not work - close it and start again. It will have registered driver and should work. +* Launch ALVR app on your headset. While the headset screen is on, click `Trust` next to the device entry (in the ALVR streamer app on PC, in the `Devices` tab) to start streaming. * You can change settings on the PC in the `Settings` tab. Most of the settings require to restart SteamVR to be applied. Use the apposite button on the bottom right corner. For any problem visit the [Troubleshooting page](https://github.com/alvr-org/ALVR/wiki/Troubleshooting). -## Advanced installation - -### Portable version - -There is also a portable version for the PC that requires more manual steps to make it work. +### Windows microphone streaming -* Install SteamVR and launch it once. -* Download `alvr_streamer_windows.zip` from the latest release [download page](https://github.com/alvr-org/ALVR/releases/latest). -* Unzip into a path that contains only ASCII characters and has edit permissions without administrator rights. +To use the microphone you need to install the [VB-CABLE driver](https://vb-audio.com/Cable/). +Set "CABLE Output" as the default microphone. +Then you can enable the microphone in the ALVR setting, leave "Virtual microphone input" to Default. -### Nightly +## Advanced installation -If you want to get new features early or you want to help with testing you can install a nightly version. +### Installing app using Sidequest -Download the latest nightly streamer [here](https://github.com/alvr-org/ALVR-nightly/releases/latest). Download the latest nightly client from Sidequest ([download](https://sidequestvr.com/app/2281)). +* Install SideQuest on your PC and enable developer mode on the headset. You can follow [this guide](https://sidequestvr.com/setup-howto). +* Connect your headset to Sidequest. If you have Quest, Pico, and other compatible device download the ALVR app [here](https://sidequestvr.com/app/9) -Since nightly releases can be unstable, always use matching versions for PC and headset. They are updated once a day. +### Manually installing ALVR streamer -### Windows microphone streaming +There is also a portable version for the PC that requires more manual steps to make it work. -To use the microphone you need to install the [VB-CABLE driver](https://vb-audio.com/Cable/). Set "CABLE Output" as the default microphone. Then you can enable the microphone in the ALVR setting, leave "Virtual microphone input" to Default. +#### Windows -### Use ALVR together with third-party drivers +* Download `alvr_streamer_windows.zip` from the latest release [download page](https://github.com/alvr-org/ALVR/releases/latest). +* Unzip into a path that contains only ASCII characters and has edit permissions without administrator rights. +* Run -By default ALVR disables other SteamVR drivers before starting. Among these drivers there is [Driver4VR](https://www.driver4vr.com/) for full body tracking. ALVR disables these drivers to maximize compatibility with every PC setup. You can disable this behavior by manually registering the ALVR driver. Go to the `installation` tab and click on `Register ALVR driver`. The next time you launch ALVR you will be able to use the other drivers concurrently. +#### Linux -### Launch ALVR together with SteamVR +* Download `alvr_streamer_linux.tar.gz` from the release [download page](https://github.com/alvr-org/ALVR/releases/latest), extract it. +* Run `bin/alvr_dashboard` -You can skip the ALVR Dashboard and open ALVR automatically together with SteamVR. Open ALVR, go to the `Installation` tab and click on `Register ALVR driver`. +#### Nightly -### Connect headset and PC via a USB Cable +If you want to get new features early or you want to help with testing you can install a nightly version. -Check out the guide [here](https://github.com/alvr-org/ALVR/wiki/Using-ALVR-through-a-USB-connection). +Download the latest nightly streamer [here](https://github.com/alvr-org/ALVR-nightly/releases/latest). -## Linux +Since nightly releases can be unstable, always use matching versions for PC and headset. They are updated once a day. ### Arch Linux (AUR) * Install `rustup` and a rust toolchain, if you don't have it: . -* Install [alvr](https://aur.archlinux.org/packages/alvr)AUR (recommended), or [alvr-git](https://aur.archlinux.org/packages/alvr-git)AUR +* Install [alvr](https://aur.archlinux.org/packages/alvr)AUR (stable, amdgpu), or [alvr-nvidia](https://aur.archlinux.org/packages/alvr-nvidia)AUR (stable, nvidia), or [alvr-git](https://aur.archlinux.org/packages/alvr-git)AUR(nightly, unstable) * Install SteamVR, **launch it once** then close it. * Run `alvr_dashboard` or ALVR from your DE's application launcher. -### Semi-Automatic Distrobox installation and guidance - -Notes: - -* This should be used in case you can't install or have issues with ALVR on your system. Do note that on Nvidia it uses host drivers and cuda nvenc, so if you're on older distribution like Debian and having older driver and cuda version, it will not work properly either way. - -* Guide also contains fixes, tweaks, additional software like desktop overlay to help you run with steamvr better and workaround it's issues. - -Installation: - -1. Download zip from https://github.com/alvr-org/ALVR-Distrobox-Linux-Guide, unpack it somewhere in your home directory (steam doesn't like long paths) or `git clone https://github.com/alvr-org/ALVR-Distrobox-Linux-Guide.git`. - - If you want to use nightly (potentially unstable, but fresh) builds, set `IS_NIGHTLY=0` variable in `env.sh` to `IS_NIGHTLY=1`. - -2. `cd ALVR-Distrobox-Linux-Guide` +### Flatpak -3. Carefully follow the [guide](ALVR-in-distrobox.md). +For Flatpak users, refer to the instructions [here](https://github.com/alvr-org/ALVR/wiki/Installing-ALVR-and-using-SteamVR-on-Linux-through-Flatpak) -4. Any issues related to this installer/various tweaks/bugs should be reported as issue [here](https://github.com/alvr-org/ALVR-Distrobox-Linux-Guide/issues) +## Advanced usage -### Other - -#### AppImage - -You can get appimage for latest stable version from [here](https://github.com/alvr-org/ALVR/releases/latest). - -#### Flatpak - -For Flatpak users, refer to the instructions [here](https://github.com/alvr-org/ALVR/wiki/Flatpak) +### Use ALVR together with third-party drivers -#### Portable tar.gz +By default ALVR disables other SteamVR drivers before starting. Among these drivers there is [Driver4VR](https://www.driver4vr.com/) for full body tracking. ALVR disables these drivers to maximize compatibility with every PC setup. You can disable this behavior by manually registering the ALVR driver. Go to the `installation` tab and click on `Register ALVR driver`. The next time you launch ALVR you will be able to use the other drivers concurrently. -* Install FFmpeg with VAAPI/NVENC + DRM + Vulkan + x264/x265 support. You can use this [ppa:savoury1/ffmpeg5](https://launchpad.net/~savoury1/+archive/ubuntu/ffmpeg5) under Ubuntu. -* Install SteamVR, **launch it once** then close it. -* Download `alvr_streamer_linux.tar.gz` from the release [download page](https://github.com/alvr-org/ALVR/releases/latest). -* Run `bin/alvr_dashboard` +### Launch ALVR together with SteamVR -### Automatic Audio & Microphone Setup +You can skip the ALVR Dashboard and open ALVR automatically together with SteamVR. -* Must be on v20.5.0+ +**Note:** You can only do that while SteamVR is not already running. Otherwise driver might be unregistered on shutdown. -* Pipewire required +Open ALVR, go to the `Installation` tab and click on `Register ALVR driver`. -* Open installation -> Run setup wizard, skip to part with automatic audio setup +### Connect headset to PC via a USB Cable -* Press the button to automatically download and set it +Check out the guide [here](https://github.com/alvr-org/ALVR/wiki/Using-ALVR-through-a-USB-connection). diff --git a/wiki/Flatpak.md b/wiki/Installing-ALVR-and-using-SteamVR-on-Linux-through-Flatpak.md similarity index 75% rename from wiki/Flatpak.md rename to wiki/Installing-ALVR-and-using-SteamVR-on-Linux-through-Flatpak.md index 7085328169..e47ca4851b 100644 --- a/wiki/Flatpak.md +++ b/wiki/Installing-ALVR-and-using-SteamVR-on-Linux-through-Flatpak.md @@ -1,10 +1,8 @@ -## Installing ALVR and using SteamVR on Linux through Flatpak - ## Disclaimer 1. This is not a fully-featured version of ALVR! It lacks Nvidia support and has bugs related to Flatpak sandboxing -2. Nvidia GPUs are currently not supported +2. Nvidia GPUs are currently not supported (but might be supported with [this PR](https://github.com/alvr-org/ALVR/pull/2207)) 3. Native Linux SteamVR utility applications such as OpenVRAS are not supported nor tested, use at your own risk @@ -16,11 +14,11 @@ 7. The ALVR Dashboard is not available in the Applications menu. To run the dashboard, run the following command to run `alvr_dashboard` in the Steam Flatpak environment: -``` +```sh flatpak run --command=alvr_dashboard com.valvesoftware.Steam ``` -8. This only works with the Steam Flatpak. For non-Flatpak Steam, use the AppImage instead +8. This only works with the Steam Flatpak. For non-Flatpak Steam, use the launcher or tar.gz ## Dependencies @@ -35,7 +33,7 @@ Once Flatpak is installed, the flatpak dependencies must also be installed. They These can be installed like so: -``` +```sh flatpak install flathub org.freedesktop.Sdk//23.08 \ org.freedesktop.Sdk.Extension.llvm16//23.08 \ org.freedesktop.Sdk.Extension.rust-stable//23.08 \ @@ -44,7 +42,7 @@ flatpak install flathub org.freedesktop.Sdk//23.08 \ AMD users may need to install the appropriate Mesa codec extensions as well: -``` +```sh flatpak install flathub org.freedesktop.Platform.GL.default//23.08-extra \ org.freedesktop.Platform.GL32.default//23.08-extra ``` @@ -53,7 +51,7 @@ flatpak install flathub org.freedesktop.Platform.GL.default//23.08-extra \ Install SteamVR via the Steam Flatpak. After installing SteamVR, run the following command: -``` +```sh sudo setcap CAP_SYS_NICE+eip ~/.var/app/com.valvesoftware.Steam/data/Steam/steamapps/common/SteamVR/bin/linux64/vrcompositor-launcher ``` @@ -63,7 +61,7 @@ This command is normally run by SteamVR, but due to the lack of sudo access with Download `com.valvesoftware.Steam.Utility.alvr.flatpak` file from one of the latest [nightly](https://github.com/alvr-org/ALVR-nightly/releases) that contains flatpak bundle and install like so: -``` +```sh flatpak --user install --bundle com.valvesoftware.Steam.Utility.alvr.flatpak ``` @@ -75,26 +73,26 @@ Alternatively, if the file is not available or a newer version is needed, the fl First, the dependencies from above must be fulfilled. Then, install `flatpak-builder` like so: -``` +```sh flatpak install flathub org.flatpak.Builder ``` Once the dependencies are fulfilled, clone and enter the repository. -``` +```sh git clone https://github.com/alvr-org/ALVR.git cd ALVR ``` Once inside the repository, simply run the following command to build and install the Flatpak. -``` +```sh flatpak run org.flatpak.Builder --user --install --force-clean .flatpak-build-dir alvr/xtask/flatpak/com.valvesoftware.Steam.Utility.alvr.json ``` If ALVR is not cloned under the home directory, permission to access the directory may need to be given to the build command. An example of this is given below. -``` +```sh flatpak run --filesystem="$(pwd)" org.flatpak.Builder --user --install --force-clean .flatpak-build-dir alvr/xtask/flatpak/com.valvesoftware.Steam.Utility.alvr.json ``` @@ -104,28 +102,12 @@ flatpak run --filesystem="$(pwd)" org.flatpak.Builder --user --install --force-c To run the ALVR Dashboard, run the following command: -``` +```sh flatpak run --command=alvr_dashboard com.valvesoftware.Steam ``` A desktop file named `com.valvesoftware.Steam.Utility.alvr.desktop` is supplied within the `alvr/xtask/flatpak` directory. Move this to where other desktop files are located on your system in order to run the dashboard without the terminal. -### Automatic Audio & Microphone setup - -Currently the game audio and microphone to and from the headset isn't routed automatically. The setup of this script will therefore run every time the headset connects or disconnects to the ALVR dashboard. This is based on [the steps](Installation-guide.md#automatic-audio--microphone-setup) in the installation guide, modified for the Flatpak. - -1. In the ALVR Dashboard under All Settings (Advanced) > Audio, enable Game Audio and Microphone. - -2. In the same place under Microphone, click Expand and set Devices to custom. Enter `default` for the name for both Sink and Source. - -3. Download the [audio-flatpak-setup.sh](../alvr/xtask/flatpak/audio-flatpak-setup.sh) script and place it into the Flatpak app data directory located at `~/.var/app/com.valvesoftware.Steam/`. Make sure it has execute permissions (e.g. `chmod +x audio-flatpak-setup.sh`). - -5. In the ALVR Dashboard, under All Settings (Advanced) > Connection, set the On connect script and On disconnect script to the absolute path of the script (relative to the Flatpak environment), e.g. `/home/$USER/.var/app/com.valvesoftware.Steam/audio-flatpak-setup.sh`. - -6. In a terminal, run `flatpak override --user --filesystem=xdg-run/pipewire-0 com.valvesoftware.Steam` to allow the script to set and map your headset's microphone - -7. Restart both Steam and the ALVR Dashboard - ### Other Applications The support for other applications that are not launched via Steam is non-existent due to the Flatpak sandbox. diff --git a/wiki/Linux-Support-development-progress.md b/wiki/Linux-Support-development-progress.md deleted file mode 100644 index 898be240e6..0000000000 --- a/wiki/Linux-Support-development-progress.md +++ /dev/null @@ -1,92 +0,0 @@ -**Warning:** This page is very outdated, see [Building From Source](https://github.com/alvr-org/ALVR/wiki/Building-From-Source) instead. - -## 2022-01-04 - -An experimental NVENC fork has successfully been created by [Toxblh](https://github.com/Toxblh), helping fix one of the larger bottlenecks on NVIDIA GPUs. [Pull Request here](https://github.com/alvr-org/ALVR/pull/906) - -## 2021-05-18 - -No special build steps are required for users who can acquire the correct ffmpeg version, read more [here](https://github.com/alvr-org/ALVR/wiki/Build-from-source#linux-experimental-build). - -## 2021-04-22 - -The PR in the last log was proceeded by [#604](https://github.com/alvr-org/ALVR/pull/604) and this new PR was merged into the main branch. Build instructions remain the same, but the `vrenv.sh` patching is no longer needed. - -## 2021-04-01 - -A [PR](https://github.com/alvr-org/ALVR/pull/569) has been made integrating Xytovl's vulkan layer into the main ALVR tree. It doesn't actually stream video yet but it provides a solid base for future work and is compatible with nVidia GPUs. - -After you've checked the PR's branch out and [built the streamer](https://github.com/alvr-org/ALVR/wiki/Build-from-source#build-streamer), you can build and install the Vulkan layer like this: - -``` -cd alvr/server/cpp/tools/vulkan-layer -mkdir build && cd build -cmake .. -make -j -``` - -Add this line: `source "$(cat $XDG_RUNTIME_DIR/alvr_dir.txt | rev | cut -d'/' -f3- | rev)/alvr/server/cpp/tools/vulkan-layer/layer/vrenv.sh"` **before** the last one (`exec "$@"`) to `/path/to/your/SteamLibrary/steamapps/common/SteamVR/bin/vrenv.sh`. - -## 2021-03-15 - -Xytovl's branch has been merged into the main repository. The build steps are unchanged. -Work has started towards a new frame capturing method using a Vulkan debug layer. - -## 2021-03-10 - -An experimental branch is available at https://github.com/xytovl/ALVR/tree/linux-port-openvr with many limitations - -### Adopted solution - -We use SteamVR direct rendering mode on a fake screen, and capture the output of the screen. Current implementation only works for AMD (and probably Intel) open source drivers. - -### Limitations - -- audio streaming is not working -- foveated encoding is not implemented -- requires superuser access for setup -- mostly untested -- requires a free port on the graphic card -- TCP streaming seems not to be working -- position is stuttering -- only supports open source drivers - -### Setup - -See [build from source](Build-from-source) - -## Usage - -Run `build/alvr_streamer_linux/ALVR Dashboard` - -On first setup, SteamVR will probably show the VR display on your screen, with the configuration window. If you have dual screen, you can move the configuration window to a visible area (with Alt + drag on most desktop environments). - -In the setup, deactivate audio streaming, switch connection to UDP, and deactivate foveated encoding. - -On the headset, launch the application, then click trust on the configuration window, which will quit. - -The headset says that the streamer will restart, but it will not. You must relaunch it manually. - -If you are here, once it is all restarted, you should be able to get the stream on the headset. - -## 2021-01-15 - -The development road has been defined, but we are not completely sure everything will work. - -* We can try to extract frames from the VR game using a custom Vulkan validation layer. Examples are: - * Vulkan tools screenshot: https://github.com/LunarG/VulkanTools/blob/master/layersvt/screenshot.cpp - * RenderDoc: https://github.com/baldurk/renderdoc -* For the compositor (layering, color correction and foveated rendering) we are going to use Vulkan as the underlying API. We can use the backend agnostic library gfx-hal, that supports Vulkan and DirectX. Reference: https://github.com/gfx-rs/gfx -* For the encoder we can use FFmpeg. FFmpeg's hardware acceleration API supports passing pointers to GPU memory buffers directly. FFmpeg supports various acceleration APIs (hardware agnostic or not) but to minimize the effort we can go with Vulkan for Linux and DirectX 11 for Windows. Reference: https://ffmpeg.org/doxygen/trunk/hwcontext_8h.html -* For audio we are going to use the Rust library CPAL, which is an audio backend abstraction layer. We can switch (maybe even at runtime) between ALSA and JACK. CPAL supports also Windows (WASAPI, ASIO), Android (OpenSL, AAudio), Web (Emscripten) and even macOS (Core Audio) if we need that in the future. Reference: https://github.com/RustAudio/cpal - -## Earlier - -We cannot find a way of obtaining the frames rendered by the VR game from SteamVR. The OpenVR API exposes methods to do this but they don't work on Linux (at least we were not able to make them work). The two methods to obtain frames with OpenVR are by implementing the interfaces `IVRVirtualDisplay` and `IVRDriverDirectModeComponent`. On Windows, ALVR uses `IVRDriverDirectModeComponent`. On Linux, `IVRVirtualDisplay` crashes on Nvidia GPUs and does nothing on AMD. Similarly `IVRDriverDirectModeComponent` does not work on Linux. We tried to get help from Valve through multiple channels but we were not successful. - -References: - -* OpenVR driver header: https://github.com/ValveSoftware/openvr/blob/master/headers/openvr_driver.h -* Main OpenVR issue tracker: https://github.com/ValveSoftware/openvr/issues -* Virtual display sample issue tracker: https://github.com/ValveSoftware/virtual_display/issues -* Linux SteamVR issue tracker: https://github.com/ValveSoftware/steam-for-linux/issues diff --git a/wiki/Linux-Troubleshooting.md b/wiki/Linux-Troubleshooting.md index 95836b75c6..55d63fc729 100644 --- a/wiki/Linux-Troubleshooting.md +++ b/wiki/Linux-Troubleshooting.md @@ -1,54 +1,127 @@ -# Linux Troubleshooting +## Black screen even when SteamVR shows movement -## SteamVR The steam runtimes SteamVR runs in break the alvr driver loaded by SteamVR. -This causes the screen to stay black on the client or an error to be reported that the pipewire device is missing or can even result in SteamVR crashing. +This causes the screen to stay black on the headset or an error to be reported that the pipewire device is missing or can even result in SteamVR crashing. ### Fix + Add `~/.local/share/Steam/steamapps/common/SteamVR/bin/vrmonitor.sh %command%` to the commandline options of SteamVR (SteamVR -> Manage/Right Click -> Properties -> General -> Launch Options). This path might differ based on your Steam installation, in that case SteamVR will not start at all. If this is the case you can figure out the actual path by going to Steam Settings -> Storage. Then pick the storage location with the star emoji (⭐) and take the path directly above the usage statistics. Prepend this path to `steamapps/common/SteamVR/bin/vrmonitor.sh`. Finally put this entire path into the SteamVR commandline options instead of the other one. -## Amdvlk/AMD +### Hyprland/Sway/Wlroots Fix + +If you're on hyprland, sway, or other wlroots-based wayland compositor, you might have to prepend `QT_QPA_PLATFORM=xcb` before commandline, which results in full commandline for steamvr being something like this: +`QT_QPA_PLATFORM=xcb ~/.local/share/Steam/steamapps/common/SteamVR/bin/vrmonitor.sh %command%`. + +Related issue: +[[BUG] No SteamVR UI on wlroots-based wayland compositors (sway, hyprland, ...) with workaround](https://github.com/ValveSoftware/SteamVR-for-Linux/issues/637). + +## Artifacting, no SteamVR Overlay or graphical glitches in streaming view + +Could be related to AMD amdvlk driver being present on your system. + If you have Amdvlk installed on your system, it overrides other vulkan drivers and causes SteamVR to break. Use the `vulkan-radeon` driver (aka radv) instead. ### Fix + Check if Amdvlk is installed by seeing if `ls /usr/share/vulkan/icd.d/ | grep amd_icd` shows anything. If so, uninstall Amdvlk from your system. -## Nvidia +## Failed to create VAAPI encoder (fedora) + +Blocky or crashing streams of gameplay and then an error window on your desktop saying: +> Failed to create VAAPI encoder: Cannot open video encoder codec: Function not implemented. Please make sure you have installed VAAPI runtime. + +This seems to be an issue for AMD GPU fedora 39+ users, but maybe others. + +### Fix + +Switch from `mesa-va-drivers` to `mesa-va-drivers-freeworld`. [Guide on how to do so](https://fostips.com/hardware-acceleration-video-fedora/) or [the RPM docs](https://rpmfusion.org/Howto/Multimedia). Then reboot your machine. + +## Nvidia driver version requirements + Alvr requires at least driver version 535 and CUDA version 12.1. If this is not the case SteamVR or the encoder might not work. ### Fix + Install at least the required versions of the driver and ensure you have CUDA installed with at least version 12.1. If an error saying CUDA was not detected persists, try using the latest alvr nightly release. -## Hybrid graphics +## Hybrid graphics advices + +### General advise + +If you have PC and can disable your integrated gpu from BIOS/UEFI, it's highly advised to do so to avoid multiple problems of handling hybrid graphics. +If you're on laptop and it doesn't allow disabling integrated graphics (in most cases) you have to resort to methods bellow. + ### Amd/Intel integrated gpu + Amd/Intel discrete gpu + Put `DRI_PRIME=1 %command%` into SteamVR's commandline options and in those of all VR games you intend to play with ALVR. ### Amd/Intel integrated gpu + Nvidia discrete gpu + Put `__NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia %command%` into SteamVR's commandline options and in those of all VR games you intend to play with ALVR. ## Wayland + When using hyprland or Gnome Wayland you need to put `WAYLAND_DISPLAY='' %command%` into the SteamVR commandline options to force XWayland. -## SlimeVR -The view shakes. +## The view shakes + +SlimeVR related, will be fixed in future updates of ALVR ### Fix + Start the SlimeVR Server only after you connected and got an image to alvr at least once. ## 109 Error + The 109 error or others appear. ### Fix + Start Steam first before starting SteamVR through alvr. If SteamVR is already started, restart it. -## Arch AUR -The alvr driver doesn't get detected by SteamVR. +## No audio or microphone + +Even though audio or microphone are enabled in presets, neither seems to appear in devices list + +### Fix + +Check if you have `pipewire` installed and it's at least version `0.3.49` by using command `pipewire --version` +For older (<=22.04 or debian <=11) ubuntu or debian based distributions you can check [pipewire-upstream](https://github.com/pipewire-debian/pipewire-debian) page for installing newer pipewire version + +## The alvr driver doesn't get detected by SteamVR + +Could be related to Arch AUR package. ### Fix -Try using a portable .tar.gz release from the Releases page. + +Try using a launcher or portable .tar.gz release from the Releases page. + +## Low AMDGPU performance and shutters + +This might be caused by [[PERF] Subpar GPU performance due to wrong power profile mode · Issue #469 · ValveSoftware/SteamVR-for-Linux · GitHub](https://github.com/ValveSoftware/SteamVR-for-Linux/issues/469). + +### Fix + +Using CoreCtrl is highly advised (install it using your distribution package management) and in settings set your GPU to VR profile, as well as cpu to performance profile (if it's old Ryzen cpu). + +## OVR Advanced Settings + +Disable the OVR Advanced Settings driver and don't use it with ALVR. +It's incompatible and will produce ladder-like latency graph with very bad shifting vision. + + +## Bindings not working/high cpu usage due to bindings ui + +Steamvr can't properly update bindings, open menus, and possibly eats too much cpu. + +This issue is caused by SteamVR's webserver spamming requests that stall the chromium ui and causes it to use a lot of cpu. + +### Fix + +Apply the following patch: `https://github.com/alvr-org/ALVR-Distrobox-Linux-Guide/blob/main/patch_bindings_spam.sh` diff --git a/wiki/My-game-is-not-working-properly!-Help!.md b/wiki/My-game-is-not-working-properly!-Help!.md index 843045eba8..0af691633c 100644 --- a/wiki/My-game-is-not-working-properly!-Help!.md +++ b/wiki/My-game-is-not-working-properly!-Help!.md @@ -10,6 +10,6 @@ Most of the time its the overly specific initialization of the game towards a sp For example, Vivecraft broke because ALVR reported the headset manufacturer as "Oculus driver 1.38.0" and not as "Oculus". In general, this is a rather bad practice as all relevant data can be accessed trough SteamVR and the game should not make assumptions based on the manufacturer of the hmd. There are many different fields that a game could require to run. -Nonetheless, we want to play and support those games. +Nonetheless, we want to play and support those games. Problem is, that we don't own all games. This is a Open Source without any funding. We can not buy any games just to fix a bug. In the case of Vivecraft, one user (thanks @Avencore) was generous to gift us a copy and the bug could be fixed. There are no guaranties! Neither on the time it will take nor if the bug will ever be fixed! Please contact us before buying anything. diff --git a/wiki/Real-time-video-upscaling-experiments.md b/wiki/Real-time-video-upscaling-experiments.md index e23034207c..e269c5e5bc 100644 --- a/wiki/Real-time-video-upscaling-experiments.md +++ b/wiki/Real-time-video-upscaling-experiments.md @@ -1,6 +1,4 @@ -# Real time video upscaling experiments - -# Why? +## Why? The Quest can display a resolution close to 4k. Rendering a game, encoding and decoding these kinds of resolutions is very taxing on both the PC and the Quest. So usually a lower resolution image displayed on the Quest. @@ -8,19 +6,19 @@ Ideally the output of such an upscaled image should match the screens pixels 1:1 Currently ALVR does no upscaling prior to the image being mapped to an OpenGL texture. This texture gets interpolated to match the screen pixels by OVR. For this process video resolutions above 100% it use bilinear interpolation and for resolutions below 100% it uses nearest neighbor. -There's a lot of good info on this topic in this issue: https://github.com/alvr-org/ALVR/issues/39 +There's a lot of good info on this topic in this issue: -# Lanczos resampling +## Lanczos resampling This traditional upscaling method seems like a good step up from basic bilinear interpolation and is relatively light on GPU resources. -A GPL 2 implementation of a Lanczos shader can be found here: https://github.com/obsproject/obs-studio/blob/6943d9a973aa3dc935b39f99d06f4540ea79da61/libobs/data/lanczos_scale.effect +A GPL 2 implementation of a Lanczos shader can be found here: -# Neural net image super resolution +## Neural net image super resolution I did some basic investigations on the feasibility of using AI upscalers to get even better results than traditional signal processing methods. -## Hardware acceleration on the XR2 +### Hardware acceleration on the XR2 There seem to be 3 paths towards getting fast NNs running on the Quest's SoC. There is the [Qualcomm Neural Processing SDK](https://developer.qualcomm.com/software/qualcomm-neural-processing-sdk/tools), which automatically detects what the capabilities of the system are and picks the right hardware to run the NN on (GPU, DSP, AI accelerator). @@ -31,7 +29,7 @@ Then there is also the [TensorFlow Lite Hexagon delegate](https://www.tensorflow I only tested an example image super-resolution app from the [tensorflow respository](https://github.com/tensorflow/examples/tree/master/lite/examples/super_resolution) in CPU and generic GPU (OpenCL) accelerated modes. Even upscaling tiny 50x50 images took around 500ms with this. Even though better hardware acceleration could improve this I do not expect 100x improvements. The only hope for NN super-resolution to be viable would be to find a significantly faster neural net, which leads us into the next topic. -## Existing neural nets +### Existing neural nets A well established real-time upscaler is [Anime4K](https://github.com/bloc97/Anime4K/). It states that it can achieve 1080p to 2160p upscaling in 3ms on a Vega64 GPU. A [rough estimate](https://uploadvr.com/oculus-quest-2-benchmarks/) puts the Quest 2 at a 10x performance disadvantage compared to such high end desktop GPUs. It doesn't seem entirely impossible to get this to work with some optimizations and lowering of the upscaling quality, but there is more bad news. Anime4K has a rather bad Peak signal-to-noise ratio (PSNR). It can get away with this because the stylized look anime is quite forgiving in being heavily filtered. diff --git a/wiki/Roadmap.md b/wiki/Roadmap.md index 09d3b816a5..452e48089b 100644 --- a/wiki/Roadmap.md +++ b/wiki/Roadmap.md @@ -1,10 +1,8 @@ -# Roadmap - This post will continue to evolve during ALVR development. ## Long-term goal -Create a universal bridge between XR devices. +Create a universal bridge between XR devices. ## What is coming next diff --git a/wiki/Settings-tutorial.md b/wiki/Settings-tutorial.md index d32bd9130b..60c4c1b502 100644 --- a/wiki/Settings-tutorial.md +++ b/wiki/Settings-tutorial.md @@ -1,24 +1,24 @@ -# Settings tutorial - -Written as of 2023/02, should be applicable to ALVR v19 and v20. +Applicable to ALVR v20. This tutorial will help you find optimal settings for your hardware and network as well as give you some pointers to troubleshoot common configuration issues. ## Prerequisites -* You have installed the ALVR streamer on your PC, and the ALVR client on your HMD. -* You can reach the SteamVR void (or the SteamVR home) and are able to launch games. +* You have installed the ALVR streamer on your PC, and the ALVR app on your HMD. +* You can launch up to the SteamVR void (or up to the SteamVR home) and are able to launch games. ## Step 1: choose resolution, refresh rate, codec -To get a sharp image, the HMD's native resolution should be used. In ALVR, use the "absolute" setting and type in your HMD's native resolution. For example, the Quest 2 has 1832x1920 pixels per eye, so use a width of 3664 and a height of 1920. Individual games can still have their render scale changed from within the SteamVR overlay setting. +To get a sharp image, you need combination of high resolution, enough sharpening, good bitrate with chosen codec. +For example, on good wireless router you can use medium resolution preset (default) with 1.0 sharpening (higher than default) with H.264 set at constant 400-500 mbps, or hevc at costant 100-150 mbps. In wired case, you can go all the way to 800-1000 mbps constant bitrate on H.264. Next, choose a refresh rate. Obviously higher is better, but on weaker/older hardware it's often preferable to use a lower setting that gives consistent results. For the Quest 2, 120 Hz has to be enabled in its settings. A few notes on codec choices: -* HEVC/H.265 is usually best on AMD hardware, and in bitrate constrained scenarios. +* AV1 works only on latest gen gpus (Nvidia RTX 4xxx and AMD Radeon RX 7xxx) and on Quest 3 only. +* HEVC/H.265 is usually best for bitrate cosntained scenarious. * AVC/H.264 (with CAVLC) may save a few milliseconds of decode latency, but needs a much higher bitrate to reach similar image quality. * Software encoding (x264) can give good results on a beefy high core-count CPU and a very high bitrate. Will require playing with a USB3 cable. The only choice if you don't have a hardware encoder (eg, RX6500). @@ -40,7 +40,7 @@ Slowly increase bitrate until one of two things happen: ## Step 4: tweak frame buffering -If you notice micro-stuttering in the client, especially in busy scenes with fast motion, slowly increase maxBufferingFrames until the playback is smooth. +If you notice micro-stuttering on the headset, especially in busy scenes with fast motion, slowly increase maxBufferingFrames until the playback is smooth. Keep in mind that increasing maxBufferingFrames will linearly increase latency; if the value that gives a smooth playback results in too high of a latency for diff --git a/wiki/Troubleshooting.md b/wiki/Troubleshooting.md index 86efd61806..b89c7cdaf8 100644 --- a/wiki/Troubleshooting.md +++ b/wiki/Troubleshooting.md @@ -1,5 +1,3 @@ -# Troubleshooting - For ALVR 20.0.0 and later === @@ -25,14 +23,14 @@ Trouble starting ALVR ALVR needs a working graphics driver to be installed in order to work. -**On linux**, you also need to make sure you have `x264` for base software encoding to work and either `vaapi` on AMD or `cuda` on NVIDIA for hardware encoders to work. +**On linux**, you also need to make sure you have either `vaapi` on AMD or `cuda` on NVIDIA for hardware encoders to work. ALVR starts launching, but gets stuck on "ALVR is not responding..." === With ALVR versions >= 20.0, some antivirus software can prevent ALVR from launching SteamVR. Try disabling any antivirus other than Windows Defender (McAfee, Norton, etc.), reboot, then try again. If the issue persists, make sure you don't have an instance of ALVR or SteamVR running in the background (check in Task Manager). If you continue having issues, hop in the [ALVR Discord server](https://discord.gg/KbKk3UM), and we'll do our best to help you get it sorted out. -ALVR starts fine, but... +ALVR starts fine, but === This section has some advice for when ALVR shows an error (or sometimes warning) pop-up. This could be either a yellow pop-up in the setup window (`ALVR Dashboard.exe`) or a separate pop-up when you connect with a headset. @@ -46,7 +44,7 @@ The latest release can be found [here](https://github.com/alvr-org/ALVR/releases The version of ALVR available on the SideQuest store is compatible with the latest release on GitHub (the previous link). Keep in mind that the version on SideQuest might take us a while to update after a new version is released on GitHub. -Failed to initialize CEncoder. +Failed to initialize CEncoder --- ALVR currently needs a recent AMD or Nvidia GPU to run, since it utilizes hardware video encoding (see [requirements](https://github.com/alvr-org/ALVR#requirements)). If you get an error saying something like @@ -78,14 +76,14 @@ ALVR on the headset stuck on `Searching for streamer...` This issue can have multiple causes. It is likely that the issue is with the PC ALVR application. See below for more specific issues. -ALVR client list is empty +ALVR device list is empty --- -![Empty ALVR client list](images/ALVRexe-no-clients.png) +![Empty ALVR device list](images/ALVRexe-no-devices.png) -Check that the PC app and the headset app run on the latest version of ALVR. At the time of writing, the latest version is v20.4.3. If your version is v2.3.1 or v2.4.0-alpha5 then you downloaded ALVR from the wrong link. The correct link is https://github.com/alvr-org/ALVR. +Check that the PC app and the headset app run on the latest version of ALVR. If your version is v2.3.1 or v2.4.0-alpha5 then you downloaded ALVR from the wrong link. The correct link is . -Make sure ALVR is running both on the PC and on the headset. To be visible in the client list, ALVR on the headset sends broadcast packets which the PC application listens for. These can be blocked by your firewall or possibly your router, if both headset and PC are connected wirelessly, having AP isolation enabled on the router will cause this. +Make sure ALVR is running both on the PC and on the headset. To be visible in the device list, ALVR on the headset sends broadcast packets which the PC application listens for. These can be blocked by your firewall or possibly your router, if both headset and PC are connected wirelessly, having AP isolation enabled on the router will cause this. To fix this, you can try the following: @@ -94,7 +92,7 @@ To fix this, you can try the following: * Open ports 9943 and 9944 on your firewall * Disable the PMF (Protected Management Frames) setting on your Router -If pinging works but you still don't see the client on the streamer app, then headset and PC might be on separate subnets. To solve this you can add the client manually. +If pinging works but you still don't see the device on the streamer app, then headset and PC might be on separate subnets. To solve this you can add the device manually. In the Devices tab press `Add device manually`. Fill in the fields with a name for your headset (you can use the name you want), the hostname (you can read it in the welcome screen in your headset when you open the ALVR app), the IP of the headset and then press `Save`. SteamVR says "headset not detected" @@ -112,7 +110,7 @@ Check that SteamVR isn't blocking ALVR (see SteamVR settings, enable advanced se If you're still getting this message (or otherwise not getting a headset icon in the SteamVR window), a SteamVR log (vrserver.txt) will have some information on why the driver isn't loading. You can find it where you installed Steam, in `Steam\logs\vrserver.txt`. -#### Some lines to look for and tips for them: +### Some lines to look for and tips for them `Unable to load driver alvr_server because of error VRInitError_Init_FileNotFound(103). Skipping.` - This usually means a library that ALVR needs is missing. Make sure you followed installation instructions carefully, installed the latest Visual C++ Redistributable x64 package and no files are missing where you extracted ALVR (especially in the bin\win64 directory). @@ -127,7 +125,7 @@ ALVR sees the headset, SteamVR shows headset icon ![SteamVR waiting...](images/SteamVR-waiting.png) -This is a situation where you have ALVR open on both headset and PC, you can see the headset in the client list and trust it. ALVR then starts SteamVR automatically when you try connecting and SteamVR shows an icon for the headset (and controllers). +This is a situation where you have ALVR open on both headset and PC, you can see the headset in the device list and trust it. ALVR then starts SteamVR automatically when you try connecting and SteamVR shows an icon for the headset (and controllers). First make sure that SteamVR (more specifically, vrserver.exe) is allowed incoming connections (UDP, port 9944) in your firewall. You can also try disabling your firewall for testing, but you keep it disabled to use ALVR. @@ -139,7 +137,7 @@ You can try restarting ALVR on both the headset and the PC. On the headset, when ![latency graph of overloaded encoder](images/latency-graphs/overloaded-encoder.png) -Symptoms: stuttery playback in the client, streamer FPS is stable but below the target refresh rate. +Symptoms: stuttery playback on the headset, streamer FPS is stable but below the target refresh rate. Solution: increase foveation settings or decrease refresh rate. @@ -163,7 +161,7 @@ Solution: check that HMD is using 5G frequency and that no other device is conne ![latency graph of overloaded streamer](images/latency-graphs/overloaded-streamer.png) -Symptoms: stuttery playback in the client, streamer FPS dips or fluctuates below the target refresh rate. +Symptoms: stuttery playback on the headset, streamer FPS dips or fluctuates below the target refresh rate. Solution: @@ -174,7 +172,7 @@ Solution: ### Micro-stuttering -![latency graph of client stuttering](images/latency-graphs/not-enough-buffering.png) +![latency graph of headset stuttering](images/latency-graphs/not-enough-buffering.png) Symptoms: image is not always smooth especially in high motion or fast scenes. diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md index b5823cc3b2..045f72fb3b 100644 --- a/wiki/_Sidebar.md +++ b/wiki/_Sidebar.md @@ -1,4 +1,4 @@ -**Start here** +#### Start here * [Installation guide](https://github.com/alvr-org/ALVR/wiki/Installation-guide) @@ -8,13 +8,13 @@ *** -**Configuration** +#### Configuration * [Settings tutorial](https://github.com/alvr-org/ALVR/wiki/Settings-tutorial) * [Information and Recommendations](https://github.com/alvr-org/ALVR/wiki/Information-and-Recommendations) -* [ALVR client and streamer on separate networks](https://github.com/alvr-org/ALVR/wiki/ALVR-client-and-streamer-on-separate-networks) +* [ALVR headset and streamer on separate networks](https://github.com/alvr-org/ALVR/wiki/Headset-and-ALVR-streamer-on-separate-networks) * [Fixed Foveated Rendering (FFR)](https://github.com/alvr-org/ALVR/wiki/Fixed-Foveated-Rendering-(FFR)) @@ -22,7 +22,7 @@ *** -**Troubleshooting** +#### Troubleshooting * [Troubleshooting](https://github.com/alvr-org/ALVR/wiki/Troubleshooting) @@ -34,11 +34,11 @@ * [My game is not working properly! Help](https://github.com/alvr-org/ALVR/wiki/My-game-is-not-working-properly!-Help!) -* [Hardware Video Encoding](https://github.com/alvr-org/ALVR/wiki/Hardware-Video-Encoding) +* [Hardware Video Encoding Testing](https://github.com/alvr-org/ALVR/wiki/FFmpeg-Hardware-Encoding-Testing) *** -**Development** +#### Development * [Roadmap](https://github.com/alvr-org/ALVR/wiki/Roadmap) @@ -46,6 +46,4 @@ * [How ALVR works](https://github.com/alvr-org/ALVR/wiki/How-ALVR-works) -* [Linux support](https://github.com/alvr-org/ALVR/wiki/Linux-Support-development-progress) - * [Real time video upscaling experiments](https://github.com/alvr-org/ALVR/wiki/Real-time-video-upscaling-experiments) diff --git a/wiki/images/ALVRexe-no-clients.png b/wiki/images/ALVRexe-no-clients.png deleted file mode 100644 index 6daef18f03..0000000000 Binary files a/wiki/images/ALVRexe-no-clients.png and /dev/null differ diff --git a/wiki/images/ALVRexe-no-devices.png b/wiki/images/ALVRexe-no-devices.png new file mode 100644 index 0000000000..8d4292877c Binary files /dev/null and b/wiki/images/ALVRexe-no-devices.png differ