-
Notifications
You must be signed in to change notification settings - Fork 546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: OpenXR integration #3761
WIP: OpenXR integration #3761
Conversation
Fixes linking issues when QuartzCore is not linked by some other means
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for prototyping this! Excited to see XR integration forming 🚀
@@ -1,5 +1,8 @@ | |||
# Change Log | |||
|
|||
### backend-metal-0.8.2 (08-05-2021) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something is off here, these commits shouldn't be showing up in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems not come after blaind/wgpu@d90b30e, not entirely sure what caused it... will try to fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the PR is still off the base
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you try rebasing properly on master?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I branched off from hal-0.8 (specifically commit e625940, 0.8.2). Had to do that because otherwise I had hard-to-debug problems with syncing gfx/wgpu/wgpu-rs to compatible versions.
Seems like if I change the gfx base to hal-0.8, those commits aren't visible here.
However, the underlying code is used by https://github.com/blaind/xrbevy and people are actively testing, I may not be able to base the gfx/wgpu/wgpu-rs all to latest commits...
I guess one option would be to branch the pull request from the bevy_openxr
branch to a separate pull request branch, and update the latest commits when the bevy_openxr
branch develops further.
Especially now that people are testing, some changes are to be expected.
Furthermore, I do not know if this pull request is eventually the best approach to land the code. One option is to use the raw handles (#3762) from gfx and expose them through wgpu-layers, I did some experimenting last week but that's quite complex. That, and other alternatives probably good to investigate still.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. This code should definitely target gfx master, not 0.8 branch.
Had to do that because otherwise I had hard-to-debug problems with syncing gfx/wgpu/wgpu-rs to compatible versions.
Let us help with this. We override gfx stuff locally all the time. There are even commented out sections of this override in Cargo toml for both wgpu and wgpu-rs.
@@ -15,6 +15,7 @@ edition = "2018" | |||
[features] | |||
default = [] | |||
use-rtld-next = ["libc"] | |||
use-openxr = ["openxr", "once_cell"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe just xr
instead of use-openxr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially went with "use-openxr" because "openxr" clashed with the crate with same name, but I guess that's doable as a name as well.
I like the 'xr', can make the change. Although, that might make the name ambiguous with other possible xr implementations in the future.
.attachments(&attachments) | ||
.subpasses(&subpasses) | ||
.dependencies(&dependencies); | ||
const VIEW_COUNT: u32 = 2; // FIXME get from xr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it says "get from xr", but shouldn't this be given by the user? I.e. the user would need to check if multi-view is available, enable it as a feature, and then request the view count explicitly here (orthogonal to XR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure about how and at what level this should be handled.
From OpenXR spec: A typical head-mounted VR system has a view configuration with two views, while a typical phone-based AR system has a view configuration with a single view. A simple multi-wall projection-based (CAVE-like) VR system may have a view configuration with at least one view for each display surface (wall, floor, ceiling) in the room.
(link). Also Varjo headset seems to have 4 views in total, two screens per eye.
Probably the screens might have different resolutions, so the selection of multiview count and different textures should be left for the application?
I tried to pull the configuration info through the wgpu
<--> gfx
barrier, but did not manage yet (link to code section)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gfx-hal can't abstract away multi-viewport rendering entirely, it's too low level for this. The most it can offer is exposing the viewport geometry and providing the way to control the multi-viewport swapchain. The user of gfx-hal, which is wgpu in our case, would then be responsible for using this API and actually do the rendering.
@@ -1156,6 +1172,36 @@ impl d::Device<B> for super::Device { | |||
} | |||
} | |||
|
|||
#[cfg(feature = "use-openxr")] | |||
unsafe fn create_image_from_openxr_raw_image( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be more general, i.e. wrap_raw_image
or something like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I guess the feature gate can also be removed?
This is part of pub trait Device<B>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I think adding trait methods behind a cfg flag is an anti-pattern. Since features are additive, if one crate uses X and implements its trait T, but another crate uses X with feature F, then this first implementation will fail at compile time, since an extra method would be unimplemented.
.api_version(vk::make_version(1, 1, 0)) | ||
} else {*/ | ||
|
||
vk::ApplicationInfo::builder() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the difference here? the fact that we are requesting 1.0 only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For openxr, there's some initialization code to be done with vk::Entry
. See example on android. E.g. platform specific initialization and / or querying and enabling/disabling extensions or extra layers.
I guess at least three options could be investigated here:
- Can the
try_enumerate_instance_version
above use entry provided by an app? - Could the incoming xr configuration data have the driver api version?
- Should the entry-creation be moved from app to gfx, and raw handle moved back and forth for extra configuration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, not sure I see anything about vk::Entry
in this link. I only see openxr::Entry
there.
let mut instance_guard = xr::INSTANCE.lock().unwrap(); | ||
let openxr_instance = instance_guard.as_mut().unwrap(); | ||
let vk_physical_device = openxr_instance.get_device(self.raw.inner.handle()); | ||
devices = vec![vk_physical_device]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems to me that we should just enumerate this together with the other devices, but have some way to check if a particular physical device is XR or not
if xr::in_use() { | ||
queue_families | ||
.filter(|(_, info)| { | ||
if info.queue_flags.contains(vk::QueueFlags::GRAPHICS) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similarly, this should be a decision of the user of gfx-hal, not the library itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would that mean e.g. wgpu?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, that would be wgpu
frame_waiter: Option<openxr::FrameWaiter>, | ||
frame_stream: Option<openxr::FrameStream<openxr::Vulkan>>, | ||
space: Option<openxr::Space>, | ||
// FIXME add field for all -validations state, that'd track separate parts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what kind of validation is supposed to be done here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a while since I wrote this part of code, but I'm somewhat sure I meant an enum
that'd track the initialization state (DeviceCreated
, ReadyForRendering
, or something similar), that would reflect in the result of xr-related calls. For example, return an error from handles getter (get_session_handles
) if the creation process hasn't been finalized yet.
} | ||
|
||
#[cfg(feature = "use-openxr")] | ||
pub(crate) static INSTANCE: Lazy<Mutex<Option<Instance>>> = Lazy::new(|| Mutex::new(None)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't need this. Instead, one of the two approaches should be taken:
- this data is a part of the main
Instance
- it's managed by the user, and gfx-backend-vulkan just understands it and knows how to cooperate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was the biggest hurdle I got into. Been a while since I made this decision, but:
- avoid changing the
hal
structs (which would require changes to all dependents) - could not access instance from device-specific code (
impl hal::Backend for Backend
), but now it seems thatArc<RawDevice>
containsArc<RawInstance>
, so in theory the required openxr data could be stored in those? Maybe some changes have occured between 0.7 and 0.8?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, we should store the openxr data in RawDevice
or RawInstance
if it's needed in multiple places.
Even though this renders, there might be some parts from OpenXR api that are missing currently:
|
|
||
#[cfg(feature = "use-openxr")] | ||
impl OpenXR { | ||
pub fn configure(instance: openxr::Instance) -> Result<OpenXR, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the definition of openxr::Instance
:
pub struct Instance {
inner: Arc<InstanceInner>,
}
its cloneable, and transferred from app to the gfx through wgpu. See:
However, this brings a problem when dropping the instance. openxr::Instance
has a impl Drop
that goes through FFI to C code.
Firstly, I wonder what happens on the app code, is the Arc
-reference kept even though the instance is on GFX side? Where should it be dropped?
Currently getting a segfault in integration test, since wgpu is trying to drop resources even though the openxr runtime still thinks its running. I guess this also brings out the question about desired safety level of openxr in gfx- and what steps can be documented for end-users to ensure the safeness even if the api is unsafe?
Same applies to all dependent openxr-structs that are instantiated. Although, currently all except session are .take()
:n away in the get_session_handles()
below. Session can also be taken away in current implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this also brings out the question about desired safety level of openxr in gfx- and what steps can be documented for end-users to ensure the safeness even if the api is unsafe?
gfx-hal is totally unsafe, no need to bother with trying to make things safe at this level. But at least it should have a clear way for users to write safe abstractions. I.e. like in Vulkan, you have to destroy device resources before destroying the device itself.
3762: Low level interop with Vulkan backend r=kvark a=zarik5 Related issues: #3698 #3761 blaind/xrbevy#1 This PR exposes some Vulkan-backend-specific details needed for interop with other low level APIs. In particular this PR aims to implement a minimum viable API to allow OpenXR integration as a separate crate. This PR is nowhere complete. I opened it to get some feedback; this is my first PR on a project the size of gfx-hal. This is the first of multiple PRs needed for OpenXR support in wgpu. PR checklist: - [ ] `make` succeeds (on *nix) - [ ] `make reftests` succeeds - [ ] tested examples with the following backends: Vulkan EDIT: To make things clear, this is another take on #3761. Me and @blaind are working together on this route. Co-authored-by: zarik5 <[email protected]>
I'll close this - there's a better encapsulation approach with raw handles that's being continued at gfx-rs/wgpu#1415 && gfx-rs/wgpu#1609 |
One take at issue #3219
PR checklist:
make
succeeds (on *nix)make reftests
succeedsI've made a proof-of-concept for OpenXR rendering on Bevy engine, using wgpu & underlying stack. See https://github.com/blaind/xrbevy
The code in this pull request is not even close to merge-able, but I thought its good idea to open it for further discussion.
For architecture of the pull request, see https://github.com/blaind/xrbevy/blob/main/docs/architecture.md (evolving document)
See also gfx-rs/wgpu-rs#910 and gfx-rs/wgpu#1387