mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 12:00:29 +02:00
Added Vulkan PC OpenXR Support
This commit is contained in:
1 parent
fbc9ce7217
commit
e7b670b2cc
23 files changed
+2174
-22
No files matched your search
@@ -106,6 +106,23 @@ public:
|
||||
OpenXRRuntime(OpenXRRuntime&&) = delete;
|
||||
OpenXRRuntime& operator=(OpenXRRuntime&&) = delete;
|
||||
|
||||
// Same-device Vulkan runtimes may touch Dawn's queue in frame/swapchain
|
||||
// calls. Share Dawn's device guard; never hold it across xrWaitFrame.
|
||||
struct GraphicsQueueGuard {
|
||||
GraphicsQueueGuard(void* value, void (*release)(void*)) : token(value), unlock(release) {}
|
||||
GraphicsQueueGuard(const GraphicsQueueGuard&) = delete;
|
||||
GraphicsQueueGuard& operator=(const GraphicsQueueGuard&) = delete;
|
||||
void* token;
|
||||
void (*unlock)(void*);
|
||||
~GraphicsQueueGuard() { if (token && unlock) unlock(token); }
|
||||
};
|
||||
void SetGraphicsQueueGuard(void* (*lock)(), void (*unlock)(void*)) {
|
||||
m_queue_lock = lock; m_queue_unlock = unlock;
|
||||
}
|
||||
GraphicsQueueGuard LockGraphicsQueue() const {
|
||||
return {m_queue_lock ? m_queue_lock() : nullptr, m_queue_unlock};
|
||||
}
|
||||
|
||||
// Creates the instance, resolves the HMD system, and enumerates the stereo
|
||||
// view configuration. Returns false without terminating the application;
|
||||
// the caller should continue in non-VR mode.
|
||||
@@ -214,6 +231,8 @@ public:
|
||||
const OpenXRError& LastError() const { return m_last_error; }
|
||||
|
||||
private:
|
||||
void* (*m_queue_lock)() = nullptr;
|
||||
void (*m_queue_unlock)(void*) = nullptr;
|
||||
enum class FramePhase {
|
||||
Idle,
|
||||
Waited,
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
||||
|
||||
#include "vr/openxr_backend.h"
|
||||
#include "vr/openxr_runtime.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace mkw::vr {
|
||||
|
||||
// Shared frame vocabulary for the Windows pacing and replay paths.
|
||||
using OpenXRWindowsVulkanFrameMode = OpenXRFrameMode;
|
||||
using OpenXRWindowsVulkanBeginStatus = OpenXRBeginStatus;
|
||||
using OpenXRWindowsVulkanSubmissionStatus = OpenXRSubmissionStatus;
|
||||
using OpenXRWindowsVulkanPresentation = OpenXRPresentation;
|
||||
using OpenXRWindowsVulkanFrame = OpenXRBackendFrame;
|
||||
|
||||
struct OpenXRWindowsVulkanGraphicsRequirements {
|
||||
XrVersion min_api_version = 0;
|
||||
XrVersion max_api_version = 0;
|
||||
};
|
||||
|
||||
// Same-device Dawn/OpenXR Vulkan backend.
|
||||
//
|
||||
// Startup is deliberately split in two. QueryGraphicsRequirements() runs
|
||||
// after OpenXRRuntime::Initialize() but before aurora_initialize(), allowing
|
||||
// OpenXR to create Dawn's Vulkan instance/device and select the physical GPU.
|
||||
// BindAurora() runs afterwards and checks the device before creating a session.
|
||||
//
|
||||
// All methods from BeginFrame() through FinishFrame(), plus PollEvents on the
|
||||
// associated OpenXRRuntime, belong to one XR pacing thread. Aurora's frame
|
||||
// worker never calls OpenXR: its post-submit callback only publishes a token
|
||||
// that WaitForSubmission() consumes. This is the synchronization boundary
|
||||
// required by the asynchronous sealed-frame renderer.
|
||||
class OpenXRWindowsVulkanBackend final {
|
||||
public:
|
||||
explicit OpenXRWindowsVulkanBackend(OpenXRLogCallback logger = {});
|
||||
~OpenXRWindowsVulkanBackend();
|
||||
|
||||
OpenXRWindowsVulkanBackend(const OpenXRWindowsVulkanBackend&) = delete;
|
||||
OpenXRWindowsVulkanBackend& operator=(const OpenXRWindowsVulkanBackend&) = delete;
|
||||
OpenXRWindowsVulkanBackend(OpenXRWindowsVulkanBackend&&) = delete;
|
||||
OpenXRWindowsVulkanBackend& operator=(OpenXRWindowsVulkanBackend&&) = delete;
|
||||
|
||||
bool QueryGraphicsRequirements(OpenXRRuntime& runtime);
|
||||
bool BindAurora(OpenXRRuntime& runtime);
|
||||
|
||||
OpenXRWindowsVulkanBeginStatus BeginFrame(const OpenXRWindowsVulkanPresentation& presentation,
|
||||
OpenXRWindowsVulkanFrame& frame);
|
||||
|
||||
// timeout_ms == UINT32_MAX waits until Aurora publishes this token or
|
||||
// Shutdown() interrupts the wait. A timeout does not release XR images;
|
||||
// the caller may keep pacing with RepeatFrame while Aurora still owns them.
|
||||
OpenXRWindowsVulkanSubmissionStatus WaitForSubmission(const OpenXRWindowsVulkanFrame& frame,
|
||||
uint32_t timeout_ms = UINT32_MAX);
|
||||
|
||||
// Withdraws this token only if Aurora has not encoded it. On success no GPU
|
||||
// command can reference the acquired images, and FinishFrame(frame, false)
|
||||
// is required to release them and close the compositor frame.
|
||||
bool TryCancelPendingFrame(OpenXRWindowsVulkanFrame& frame);
|
||||
|
||||
// Ends the current compositor cycle with the last completed layer and starts
|
||||
// another, without releasing or changing Aurora's pending images/render token.
|
||||
// The original render poses remain attached to the pending and retained images.
|
||||
bool RepeatFrame(const OpenXRWindowsVulkanFrame& frame);
|
||||
|
||||
// Releases acquired images and calls xrEndFrame. submit_layer must only be
|
||||
// true after WaitForSubmission returned Success. Immersive frames submit
|
||||
// XrCompositionLayerProjection; virtual-screen frames submit an
|
||||
// XrCompositionLayerQuad using the single mono target, placed as the
|
||||
// presentation's quad_anchored/quad_pose describe. If no new usable layer is
|
||||
// available, resubmits the retained layer using the current display time.
|
||||
bool FinishFrame(OpenXRWindowsVulkanFrame& frame, bool submit_layer);
|
||||
|
||||
// Render-first path when interpolation is off. Aurora renders into acquired
|
||||
// non-retained XR images while no compositor frame is open. BeginFrameForPacket
|
||||
// accepts only a completed packet; CopyRenderedEyes verifies the already queued
|
||||
// bridge copy. FinishFrame releases the images and submits their original poses.
|
||||
OpenXRBeginStatus PreparePacket(const OpenXRPresentation& presentation, OpenXRBackendFrame& packet);
|
||||
bool TryCancelPendingPacket(OpenXRBackendFrame& packet);
|
||||
OpenXRBeginStatus BeginFrameForPacket(const OpenXRBackendFrame& packet, OpenXRBackendFrame& frame);
|
||||
OpenXRSubmissionStatus CopyRenderedEyes(const OpenXRBackendFrame& frame);
|
||||
OpenXRBeginStatus KeepAliveCycle();
|
||||
|
||||
// Call on the XR owner thread after Aurora's worker is idle and before
|
||||
// aurora_shutdown(). Safe to repeat. False means a submitted Vulkan command
|
||||
// could not be fenced; the caller must retain this backend and its runtime
|
||||
// for the process lifetime instead of destroying possibly live resources.
|
||||
bool Shutdown();
|
||||
|
||||
bool IsBound() const;
|
||||
const OpenXRWindowsVulkanGraphicsRequirements& GraphicsRequirements() const;
|
||||
int64_t SwapchainFormat() const;
|
||||
const std::string& LastError() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
};
|
||||
|
||||
} // namespace mkw::vr
|
||||
|
||||
#endif // defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
||||
@@ -0,0 +1,64 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#pragma once
|
||||
#include "vr/openxr_d3d12.h"
|
||||
#include "vr/openxr_vulkan_win32.h"
|
||||
#include <variant>
|
||||
namespace mkw::vr {
|
||||
// Runtime API selection; both backends expose the same pacing/ownership contract.
|
||||
class OpenXRWindowsBackend {
|
||||
std::variant<std::unique_ptr<OpenXRD3D12Backend>, std::unique_ptr<OpenXRWindowsVulkanBackend>> backend_;
|
||||
public:
|
||||
OpenXRWindowsBackend(OpenXRLogCallback logger, bool vulkan) {
|
||||
if (vulkan) backend_ = std::make_unique<OpenXRWindowsVulkanBackend>(logger);
|
||||
else backend_ = std::make_unique<OpenXRD3D12Backend>(logger);
|
||||
}
|
||||
const OpenXRD3D12GraphicsRequirements& GraphicsRequirements() {
|
||||
return std::get<0>(backend_)->GraphicsRequirements();
|
||||
}
|
||||
bool QueryGraphicsRequirements(OpenXRRuntime& runtime) {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->QueryGraphicsRequirements(runtime); }, backend_);
|
||||
}
|
||||
bool BindAurora(OpenXRRuntime& runtime) {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->BindAurora(runtime); }, backend_);
|
||||
}
|
||||
OpenXRBeginStatus BeginFrame(const OpenXRPresentation& presentation, OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> OpenXRBeginStatus { return backend->BeginFrame(presentation, frame); }, backend_);
|
||||
}
|
||||
OpenXRSubmissionStatus WaitForSubmission(const OpenXRBackendFrame& frame, uint32_t timeout) {
|
||||
return std::visit([&](auto& backend) -> OpenXRSubmissionStatus { return backend->WaitForSubmission(frame, timeout); }, backend_);
|
||||
}
|
||||
bool TryCancelPendingFrame(OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->TryCancelPendingFrame(frame); }, backend_);
|
||||
}
|
||||
bool RepeatFrame(const OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->RepeatFrame(frame); }, backend_);
|
||||
}
|
||||
bool FinishFrame(OpenXRBackendFrame& frame, bool submit) {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->FinishFrame(frame, submit); }, backend_);
|
||||
}
|
||||
OpenXRBeginStatus PreparePacket(const OpenXRPresentation& presentation, OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> OpenXRBeginStatus { return backend->PreparePacket(presentation, frame); }, backend_);
|
||||
}
|
||||
bool TryCancelPendingPacket(OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->TryCancelPendingPacket(frame); }, backend_);
|
||||
}
|
||||
OpenXRBeginStatus BeginFrameForPacket(const OpenXRBackendFrame& packet, OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> OpenXRBeginStatus { return backend->BeginFrameForPacket(packet, frame); }, backend_);
|
||||
}
|
||||
OpenXRSubmissionStatus CopyRenderedEyes(const OpenXRBackendFrame& frame) {
|
||||
return std::visit([&](auto& backend) -> OpenXRSubmissionStatus { return backend->CopyRenderedEyes(frame); }, backend_);
|
||||
}
|
||||
OpenXRBeginStatus KeepAliveCycle() {
|
||||
return std::visit([&](auto& backend) -> OpenXRBeginStatus { return backend->KeepAliveCycle(); }, backend_);
|
||||
}
|
||||
bool Shutdown() {
|
||||
return std::visit([&](auto& backend) -> bool { return backend->Shutdown(); }, backend_);
|
||||
}
|
||||
int64_t SwapchainFormat() {
|
||||
return std::visit([&](auto& backend) -> int64_t { return backend->SwapchainFormat(); }, backend_);
|
||||
}
|
||||
const std::string& LastError() {
|
||||
return std::visit([&](auto& backend) -> const std::string& { return backend->LastError(); }, backend_);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user