Proof-of-concept of getting OpenXR rendering support for Bevy game engine using gfx-rs abstractions

Overview

Introduction

Proof-of-concept of getting OpenXR rendering support for Bevy game engine using gfx-rs abstractions.

Example

(hand interaction with boxes missing from current commit)

Targets:

  1. Demonstrate that OpenXR rendering is possible on Rust/GFX-RS/Bevy -ecosystem
  2. Start the discussion with ecosystem participants about proper way to implement OpenXR support for Rust
  3. Eventually have the basic building blocks in an easy-to-use state for building XR apps on top of bevy, or implementing XR support for other rendering engines

For technical details, see docs/architecture.md:


Tracked pull requests at upstream:

Getting started

Notes:

  1. This has only been tested on Oculus Quest 2, but should also work on Monado
  2. These quideline steps below haven't been validated by anyone yet, so expect challenges on the way...

Ubuntu packages

Prequisite installation:

sudo apt-get install make openjdk-11-jre g++ libudev-dev libasound2-dev gcc

TODO: document if all are really necessary...

Download dependency crates & patch them

Currently this example depends on a lot of changes for multitude of crates that bevy depends on. To download & patch them (mostly paths instead of crates.io crates) for local building, run a make command. This will download repos to repos/ folder, and patch them with patch files in patches/ folder (most changes are in repo-git source code though):

make download_dependencies

Prequisite Rust packages (optional)

For faster linking:

sudo apt-get install lld

And add this to ~/.cargo/config

[target.x86_64-unknown-linux-gnu]
rustflags = [
  "-C", "link-arg=-fuse-ld=lld",
]

Building for Oculus Quest 2

Prequisites

Currently a patched version of cargo-apk is required. Install it like this:

NOTE! THIS WILL REPLACE PREVIOUSLY INSTALLED cargo-apk IN GLOBAL PATH!

cargo install --path repos/android-ndk-rs/cargo-apk

or

install_cargo_apk

If you have not setup udev yet, copy udev rules for Oculus Quest 2

# run both as root
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="2833", ATTR{idProduct}=="0186", MODE="0660", GROUP="plugdev"' > /etc/udev/rules.d/51-android.rules
udevadm control --reload-rules && udevadm trigger

Oculus OpenXR plugin

You must download libopenxr_loader.so from Oculus OpenXR Mobile SDK file. It should be stored to libs/aarch64-linux-android folder. It is at path OpenXR/Libs/Android/arm64-v8a/Release in the zip file.

$ ls -al libs/aarch64-linux-android/libopenxr_loader.so
-rwxrwxr-x 1 user user 10639048 feb  13 14:46 libs/aarch64-linux-android/libopenxr_loader.so

$ file libs/aarch64-linux-android/libopenxr_loader.so
ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=..., with debug_info, not stripped

Android SDK

You need android SDK & NDK to build .apk.

Append to .bashrc (and change paths if versions have changed...)

export ANDROID_SDK_ROOT="$HOME/Android/Sdk"
export ANDROID_NDK_ROOT="$HOME/Android/Sdk/ndk/22.0.7026061"

Unzip https://developer.android.com/studio/command-line/sdkmanager to $ANDROID_SDK_ROOT/cmdline-tools

After that, install required sdk's:

./cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "ndk;22.0.7026061"
./cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "build-tools;30.0.3"
./cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "platforms;android-30"
./cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "platforms;android-29"

Run the example

cargo apk run --example xr_apk_scene --release

or

make run_xr_apk

If successful, it should output something like this:

    Finished release [optimized] target(s) in 32.78s
 'lib/arm64-v8a/libxr_apk_scene.so'...
 'lib/arm64-v8a/libc++_shared.so'...
 'lib/arm64-v8a/libopenxr_loader.so'...
Verifying alignment of /.../Bevy OpenXR wgpu.apk (4)...
      49 AndroidManifest.xml (OK - compressed)
    1152 assets/textures/uv-small.png (OK)
  319920 lib/arm64-v8a/libxr_apk_scene.so (OK - compressed)
15689936 lib/arm64-v8a/libc++_shared.so (OK - compressed)
17515002 lib/arm64-v8a/libopenxr_loader.so (OK - compressed)
Verification succesful
Performing Incremental Install
Serving...
Unknown command: install-incremental
Performing Streamed Install
Success
Starting: Intent { act=android.intent.action.MAIN cmp=rust.example.xr_apk_scene/android.app.NativeActivity }

Building for PC

Monado

(this example has been undocumented, please make a pull request to improve)

https://monado.freedesktop.org/packages-ubuntu.html

sudo add-apt-repository ppa:monado-xr/monado
sudo apt-get update
sudo apt-get install libopenxr-loader1 libopenxr1-monado

See Monado docs for using it.

Run the example

cargo run --example xr_pc_scene

or

make run_xr_pc

(untested! please make a pull req if this works - it should be working though)

Patched dependencies

See pull requests above. Also:

openxrs

  • branched from 63e80e30b0d37a4203fc103978cd146edb89f2dc (Dec 17), because the vulkan2 change is currently incompatible
  • added a few changes in order to handle Oculus Quest 2 case

android-ndk-rs

Related material

Further reading - some links that have helped in getting this PoC working:

Comments
  • Setup android manifest for VR

    Setup android manifest for VR

    As documented here: https://developer.oculus.com/documentation/native/android/mobile-native-manifest/

    Using the syntax of cargo-apk 0.7 https://crates.io/crates/cargo-apk

    This fixes a few lifecyle issues. In particular, the app can be launched again through the oculus menu.

    opened by agrande 6
  • Poor performance - FPS halved from what's possible

    Poor performance - FPS halved from what's possible

    It seems that currently the reported FPS numbers are exactly 50% of what the devices are capable. E.g. on oculus quest 2 with 72fps the example runs at 36fps, and with quest 2 set to 90fps, example reports 45 fps.

    Also detectable with monado:

     WARN [log_frame_time_diff] Frame late by 16.67ms!
     WARN [log_frame_time_diff] Frame late by 16.67ms!
     WARN [log_frame_time_diff] Frame late by 33.33ms!
     WARN [log_frame_time_diff] Frame late by 16.67ms!
     WARN [log_frame_time_diff] Frame late by 33.33ms!
    

    Possibly every 2nd frame is waited for, but not rendered?

    opened by blaind 3
  • Android activity lifecycle

    Android activity lifecycle

    Currently the android (Oculus Quest 2) lifecycle has problems. Especially after the initial startup, if user navigates back to the application. Seems like that Oculus may also initialize apps before actually displaying them to user?

    Some pointers for investigation:

    • main() at https://github.com/blaind/xrbevy/blob/df535495d100697857cfcbe4a58f135b488082b1/examples/xr_apk_scene.rs#L6 can be called multiple times, each from different thread. See https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_OCULUS_android_session_state_enable
    • event loop handling happens at https://github.com/blaind/bevy_openxr/blob/e48bd27130cfb3b735edf2d6ce6355bb5c2490f0/crates/bevy_openxr_core/src/lib.rs#L124. The process::exit(0) at line 135 should be eventually removed
    • Session states explanied at https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#session-states

    For running the example, in case of problems current "quick fix" is to just run make run_xr_apk a few times until Oculus kills all remaining instances and launches a new one.

    opened by blaind 2
  • Use predicted frametime as a bevy time in the render graph

    Use predicted frametime as a bevy time in the render graph

    From OpenXR docs:

    The engine simulation should advance based on the display time. Every stage in the engine pipeline should use the exact same display time for one particular application-generated frame. An accurate and consistent display time across all stages and threads in the engine pipeline is important to avoid object motion judder. If the application has multiple pipeline stages, the application should pass its computed display time through its pipeline, as xrWaitFrame must be called only once per frame.

    opened by blaind 0
  • Using swapchain in bevy render graph

    Using swapchain in bevy render graph

    OpenXR runtime reports the possible swapchain texture format (see https://github.com/blaind/bevy_openxr/blob/e48bd27130cfb3b735edf2d6ce6355bb5c2490f0/crates/bevy_openxr_core/src/swapchain.rs#L100).

    The same format should be used in bevy render graph in order not to lose precision during conversions.

    At least repos\bevy\crates\bevy_pbr\src\render_graph\pbr_pipeline\mod.rs should be configured.

    Maybe window creation flow can be used? Since swapchain is configured late in the process. Alternatively, texture formats could be enumerated immediately after the openxr session has been created.

    could look at the window creation flow to figure out how to do this. The normal graphics context is also created after the window is, and this is in a way a similar flow. Alternatively look at the multiple window example, that deals with late creation of windows and the swapchain for that.

    opened by blaind 0
  • Use submodules

    Use submodules

    I've added the repos from install_dependencies as submodules instead. This means users only have to do git clone --recursive or git submodule update --init instead of running a batch file.

    opened by mtsr 0
  • Better integration with gfx-hal

    Better integration with gfx-hal

    Hi blaind, I'm really interested in your work since I wanted to make ALVR switch its graphics code and VR runtime to bevy and OpenXR. I saw your PRs and I wanted to give you some suggestions and and also a hand with the implementations. About gfx-hal, I think the OpenXR integration should be made into another crate. Currently there is no way of accessing gfx-hal internals, so I wanted to contribute an API to get backend-specific handles (like VkInstance and VkDevice) and to create gfx-hal objects from these handles. About wgpu, a similar API could be propagated, but I don't know if this is the right call, since the point of wgpu is to have a safe API. The best thing would be for bevy to switch from wgpu to gfx-hal directly, but this easier said than done.

    opened by zarik5 7
Owner
Mika
Mika
State of the art "build your own engine" kit powered by gfx-hal

A rendering engine based on gfx-hal, which mimics the Vulkan API. Building This library requires standard build tools for the target platforms, except

Amethyst Foundation 801 Dec 28, 2022
A barebones example of how to integrate OpenXR with wgpu (Vulkan-only)

wgpu-openxr-example a barebones example of how to integrate OpenXR with wgpu (Vulkan-only) It has four modes: cargo run --no-default-features: desktop

Philpax 21 Dec 15, 2022
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.

vx_bevy A voxel engine prototype made using the Bevy game engine. Goals and features Very basic worldgen Animated chunk loading (ala cube world) Optim

Lucas Arriesse 125 Dec 31, 2022
Guide for using gfx-rs's wgpu library.

Introduction What is wgpu? Wgpu is a Rust implementation of the WebGPU API spec. WebGPU is a specification published by the GPU for the Web Community

sotrh 1k Dec 29, 2022
Self Study on developing a game engine using wgpu as the rendering API. Learning as I go.

Fabled Engine Any issues, enhancement, features, or bugs report are always welcome in Issues. The obj branch is where frequent development and up to d

Khalid 20 Jan 5, 2023
A proof of concept Linux screen reader, with minimal features.

Odilia A proof of concept Linux screen reader, with minimal features. Status: prototype We're breaking things daily. This is not usable whatsoever, an

Odilia 43 Aug 15, 2022
A game of snake written in Rust using the Bevy game engine, targeting WebGL2

Snake using the Bevy Game Engine Prerequisites cargo install cargo-make Build and serve WASM version Set your local ip address in Makefile.toml (loca

Michael Dorst 0 Dec 26, 2021
A Client/Server game networking plugin using QUIC, for the Bevy game engine.

Bevy Quinnet A Client/Server game networking plugin using QUIC, for the Bevy game engine. Bevy Quinnet QUIC as a game networking protocol Features Roa

Gilles Henaux 65 Feb 20, 2023
A light-weight Anchor-Offset based 2D sprite rendering system for the bevy engine.

Bevy AoUI A light-weight anchor-offset based 2D sprite layout system for the bevy engine. Bevy AoUI provides a light-weight rectangular anchor-offset

Mincong Lu 4 Nov 22, 2023
Bevy Simple Portals is a Bevy game engine plugin aimed to create portals.

Portals for Bevy Bevy Simple Portals is a Bevy game engine plugin aimed to create portals. Those portals are (for now) purely visual and can be used t

Sélène Amanita 11 May 28, 2023
Vulkan and Rust rendering~game engine which creation is covered with YouTube videos

Vulkan and Rust rendering~game engine which creation is covered with YouTube videos

小鳥 11 Dec 4, 2022
2d Endless Runner Game made with Bevy Game Engine

Cute-runner A 2d Endless Runner Game made with Bevy Game Engine. Table of contents Project Infos Usage Screenshots Disclaimer Project Infos Date: Sept

JoaoMarinho 2 Jul 15, 2022
A game made in one week for the Bevy engine's first game jam

¿Quien es el MechaBurro? An entry for the first Bevy game jam following the theme of "Unfair Advantage." It was made in one week using the wonderful B

mike 20 Dec 23, 2022
Brine is my attempt at writing a Minecraft client in Rust using the Bevy game engine.

Brine Brine is my attempt at writing a Minecraft client in Rust using the Bevy game engine. It's EXTREMELY work-in-progress. The thing that makes Brin

Ben Reeves 34 Dec 26, 2022
🌎 Demo for Minecraft-like procedural generation using the Bevy game engine

infinigen This is a demo for Minecraft-like procedural generation using the Bevy game engine. chunks along all axes (X, Y and Z) adjustable zoom level

James Hiew 16 Jun 11, 2023
A simple extension for `bevy-editor-pls` to support tilemap editing right inside the bevy app.

What is this This is a simple tilemap editor plugin, that hooks right into bevy_editor_pls to work with bevy_ecs_tilemap. It works completely within i

null 3 May 8, 2023
A tilemap rendering crate for bevy which is more ECS friendly.

bevy_ecs_tilemap A tilemap rendering plugin for bevy which is more ECS friendly by having an entity per tile. Features A tile per entity Fast renderin

John 414 Dec 30, 2022
Basic first-person fly camera for the Bevy game engine

bevy_flycam A basic first-person fly camera for Bevy 0.4 Controls WASD to move horizontally SPACE to ascend LSHIFT to descend ESC to grab/release curs

Spencer Burris 85 Dec 23, 2022
Inspector plugin for the bevy game engine

bevy-inspector-egui This crate provides the ability to annotate structs with a #[derive(Inspectable)], which opens a debug interface using egui where

Jakob Hellermann 517 Dec 31, 2022