mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 01:00:14 +02:00
Run the same-device Vulkan OpenXR backend on desktop Linux
Lepton's Vulkan driver has no external memory or sync fd extensions, so the Steam Frame gets a native SteamOS build instead. Its backend is the PC's: OpenXR creates Dawn's own Vulkan instance and device, and the eyes are copied into the swapchain on Dawn's queue, with nothing shared between devices. - openxr_vulkan_win32 and Aurora's vulkan_win32_interop now compile on desktop Linux. Dawn links statically there, so the bridge calls the patched package's hooks directly, and exists only when the package's aurora-dawn.json declares the Vulkan hook ABI (AuroraDawnProvider turns AuroraVulkanAbi into AURORA_DAWN_VULKAN_HOOKS); a stock Dawn keeps the stubs and VR falls back to the desktop. - openxr_integration.cpp gains a Linux branch: XR_KHR_vulkan_enable2, the timespec clock, refresh rate, performance level, the Frame controllers and eye gaze; fragment density maps are requested on Linux as on the Quest (fdm.cpp and gpu.cpp, AURORA_FDM=0/1 overrides). - Controller motion uses XR_KHR_convert_timespec_time on any Linux. - CMake: Vulkan headers are fetched for Linux OpenXR builds, the headset option is MKW_HEADSET on Android and Linux, and Linux aarch64 builds take MKW_LINUX_CPU (cortex-x4 for the Steam Frame, else native). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
This commit is contained in:
13 files changed
+137
-36
No files matched your search
@@ -187,7 +187,7 @@ android {
|
|||||||
}
|
}
|
||||||
// Valve's Steam Frame, through Lepton (SteamOS's Android layer) and SteamVR's Android
|
// Valve's Steam Frame, through Lepton (SteamOS's Android layer) and SteamVR's Android
|
||||||
// OpenXR runtime. Its manifest (src/steamFrame) drops the Horizon OS entries, and
|
// OpenXR runtime. Its manifest (src/steamFrame) drops the Horizon OS entries, and
|
||||||
// MKW_ANDROID_HEADSET gives the runtime the Frame's defaults (runtime_config.h).
|
// MKW_HEADSET gives the runtime the Frame's defaults (runtime_config.h).
|
||||||
create("steamFrame") {
|
create("steamFrame") {
|
||||||
dimension = "headset"
|
dimension = "headset"
|
||||||
// Horizon OS only; src/steamFrame/AndroidManifest.xml removes the entry.
|
// Horizon OS only; src/steamFrame/AndroidManifest.xml removes the entry.
|
||||||
@@ -199,7 +199,7 @@ android {
|
|||||||
cmake {
|
cmake {
|
||||||
arguments += listOf(
|
arguments += listOf(
|
||||||
"-DMKW_ANDROID_CPU=${headsetCpus.getValue("steamFrame")}",
|
"-DMKW_ANDROID_CPU=${headsetCpus.getValue("steamFrame")}",
|
||||||
"-DMKW_ANDROID_HEADSET=steam_frame",
|
"-DMKW_HEADSET=steam_frame",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,7 +268,10 @@ elseif (_aurora_dawn_provider STREQUAL "package")
|
|||||||
# A package built with Aurora's patches (android/Build-QuestDawn.ps1) describes them in
|
# A package built with Aurora's patches (android/Build-QuestDawn.ps1) describes them in
|
||||||
# aurora-dawn.json. Only such a package has the fragment density map ABI
|
# aurora-dawn.json. Only such a package has the fragment density map ABI
|
||||||
# (include/aurora/dawn_fdm_abi.h); aurora_core compiles its callers against it.
|
# (include/aurora/dawn_fdm_abi.h); aurora_core compiles its callers against it.
|
||||||
|
# The Vulkan hook ABI (include/aurora/dawn_vulkan_abi.h) is the other half: a package built by
|
||||||
|
# Launcher/build-dawn-linux.sh carries it, and the Linux OpenXR backend needs it.
|
||||||
set(AURORA_DAWN_FDM_ABI 0 PARENT_SCOPE)
|
set(AURORA_DAWN_FDM_ABI 0 PARENT_SCOPE)
|
||||||
|
set(AURORA_DAWN_VULKAN_HOOKS_ABI 0 PARENT_SCOPE)
|
||||||
if (EXISTS "${_dawn_pkg_dir}/aurora-dawn.json")
|
if (EXISTS "${_dawn_pkg_dir}/aurora-dawn.json")
|
||||||
file(READ "${_dawn_pkg_dir}/aurora-dawn.json" _aurora_dawn_manifest)
|
file(READ "${_dawn_pkg_dir}/aurora-dawn.json" _aurora_dawn_manifest)
|
||||||
string(JSON _aurora_dawn_fdm_abi ERROR_VARIABLE _aurora_dawn_manifest_error
|
string(JSON _aurora_dawn_fdm_abi ERROR_VARIABLE _aurora_dawn_manifest_error
|
||||||
@@ -277,6 +280,12 @@ elseif (_aurora_dawn_provider STREQUAL "package")
|
|||||||
set(AURORA_DAWN_FDM_ABI ${_aurora_dawn_fdm_abi} PARENT_SCOPE)
|
set(AURORA_DAWN_FDM_ABI ${_aurora_dawn_fdm_abi} PARENT_SCOPE)
|
||||||
message(STATUS "aurora: Dawn package carries the fragment density map ABI ${_aurora_dawn_fdm_abi}")
|
message(STATUS "aurora: Dawn package carries the fragment density map ABI ${_aurora_dawn_fdm_abi}")
|
||||||
endif ()
|
endif ()
|
||||||
|
string(JSON _aurora_dawn_vulkan_abi ERROR_VARIABLE _aurora_dawn_manifest_error
|
||||||
|
GET "${_aurora_dawn_manifest}" AuroraVulkanAbi)
|
||||||
|
if (NOT _aurora_dawn_manifest_error AND _aurora_dawn_vulkan_abi GREATER 0)
|
||||||
|
set(AURORA_DAWN_VULKAN_HOOKS_ABI ${_aurora_dawn_vulkan_abi} PARENT_SCOPE)
|
||||||
|
message(STATUS "aurora: Dawn package carries the Vulkan hook ABI ${_aurora_dawn_vulkan_abi}")
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
_aurora_dawn_set_platform_backends()
|
_aurora_dawn_set_platform_backends()
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ if (AURORA_ENABLE_GX)
|
|||||||
# of producing unresolved interop references.
|
# of producing unresolved interop references.
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
|
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
|
||||||
target_sources(aurora_core PRIVATE lib/webgpu/d3d12_interop.cpp lib/webgpu/vulkan_win32_interop.cpp)
|
target_sources(aurora_core PRIVATE lib/webgpu/d3d12_interop.cpp lib/webgpu/vulkan_win32_interop.cpp)
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||||
|
# The same-device Vulkan bridge, for the desktop Linux OpenXR backend (SteamOS on the Steam
|
||||||
|
# Frame). Static Dawn on Linux is linked directly, so the bridge is compiled in only against
|
||||||
|
# a package with Aurora's Vulkan hooks; otherwise the file is its C ABI stubs.
|
||||||
|
target_sources(aurora_core PRIVATE lib/webgpu/vulkan_win32_interop.cpp)
|
||||||
|
if (AURORA_DAWN_VULKAN_HOOKS_ABI)
|
||||||
|
target_compile_definitions(aurora_core PRIVATE AURORA_DAWN_VULKAN_HOOKS=${AURORA_DAWN_VULKAN_HOOKS_ABI})
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
# Android/Vulkan counterpart: the AHardwareBuffer stereo bridge. The file
|
# Android/Vulkan counterpart: the AHardwareBuffer stereo bridge. The file
|
||||||
# compiles to C ABI stubs on every other platform so the runtime's OpenXR
|
# compiles to C ABI stubs on every other platform so the runtime's OpenXR
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
||||||
// AURORA_DAWN_FDM carries the ABI version of the Dawn package's patches (AuroraDawnProvider.cmake).
|
// AURORA_DAWN_FDM carries the ABI version of the Dawn package's patches (AuroraDawnProvider.cmake):
|
||||||
#if defined(__ANDROID__) && defined(AURORA_DAWN_FDM)
|
// the Quest's (android/Build-QuestDawn.ps1) or desktop Linux's (Launcher/build-dawn-linux.sh), both
|
||||||
|
// linked statically.
|
||||||
|
#if (defined(__ANDROID__) || defined(__linux__)) && defined(AURORA_DAWN_FDM)
|
||||||
#include <aurora/dawn_fdm_abi.h>
|
#include <aurora/dawn_fdm_abi.h>
|
||||||
static_assert(AURORA_DAWN_FDM == AURORA_DAWN_FDM_ABI,
|
static_assert(AURORA_DAWN_FDM == AURORA_DAWN_FDM_ABI,
|
||||||
"The Dawn package's fragment density map ABI does not match include/aurora/dawn_fdm_abi.h");
|
"The Dawn package's fragment density map ABI does not match include/aurora/dawn_fdm_abi.h");
|
||||||
@@ -53,7 +55,7 @@ void device_created() noexcept {
|
|||||||
#else
|
#else
|
||||||
if (g_requested) {
|
if (g_requested) {
|
||||||
Log.warn("Fragment density maps: unavailable; this build links a Dawn without Aurora's patches "
|
Log.warn("Fragment density maps: unavailable; this build links a Dawn without Aurora's patches "
|
||||||
"(android/Build-QuestDawn.ps1)");
|
"(android/Build-QuestDawn.ps1, Launcher/build-dawn-linux.sh)");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -830,6 +830,13 @@ bool initialize(AuroraBackend auroraBackend) {
|
|||||||
const int fdmOverride = android_debug::property_int("debug.wiicompiled.fdm", -1);
|
const int fdmOverride = android_debug::property_int("debug.wiicompiled.fdm", -1);
|
||||||
fdm::request(g_backendType == wgpu::BackendType::Vulkan &&
|
fdm::request(g_backendType == wgpu::BackendType::Vulkan &&
|
||||||
(fdmOverride >= 0 ? fdmOverride == 1 : g_config.xrFragmentDensityMap));
|
(fdmOverride >= 0 ? fdmOverride == 1 : g_config.xrFragmentDensityMap));
|
||||||
|
#elif defined(__linux__)
|
||||||
|
// Desktop Linux (SteamOS on the Steam Frame), with a Dawn built by Launcher/build-dawn-linux.sh.
|
||||||
|
// AURORA_FDM=0 or 1 overrides the settings, as debug.wiicompiled.fdm does on the Quest.
|
||||||
|
const char* fdmOverride = std::getenv("AURORA_FDM");
|
||||||
|
fdm::request(g_backendType == wgpu::BackendType::Vulkan &&
|
||||||
|
(fdmOverride != nullptr && *fdmOverride != '\0' ? std::strcmp(fdmOverride, "1") == 0
|
||||||
|
: g_config.xrFragmentDensityMap));
|
||||||
#endif
|
#endif
|
||||||
const auto future =
|
const auto future =
|
||||||
g_adapter.RequestDevice(&deviceDescriptor, wgpu::CallbackMode::WaitAnyOnly,
|
g_adapter.RequestDevice(&deviceDescriptor, wgpu::CallbackMode::WaitAnyOnly,
|
||||||
|
|||||||
@@ -4,8 +4,27 @@
|
|||||||
#include "../stereo.hpp"
|
#include "../stereo.hpp"
|
||||||
#include "../stereo_overlay.hpp"
|
#include "../stereo_overlay.hpp"
|
||||||
#include "gpu.hpp"
|
#include "gpu.hpp"
|
||||||
#if defined(_WIN32) && defined(WEBGPU_DAWN) && defined(DAWN_ENABLE_BACKEND_VULKAN)
|
// Windows loads the patched webgpu_dawn.dll's exports at run time. Desktop Linux (SteamOS on the
|
||||||
|
// Steam Frame) links Dawn statically, so there the bridge exists only against a package built with
|
||||||
|
// the hooks (AURORA_DAWN_VULKAN_HOOKS, from its aurora-dawn.json) and calls them directly.
|
||||||
|
#if defined(WEBGPU_DAWN) && defined(DAWN_ENABLE_BACKEND_VULKAN) && \
|
||||||
|
(defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__) && defined(AURORA_DAWN_VULKAN_HOOKS)))
|
||||||
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
static_assert(AURORA_DAWN_VULKAN_HOOKS == AURORA_DAWN_VULKAN_ABI,
|
||||||
|
"The Dawn package's Vulkan hook ABI does not match include/aurora/dawn_vulkan_abi.h");
|
||||||
|
extern "C" {
|
||||||
|
uint32_t AuroraDawnVulkanVersion(void);
|
||||||
|
int AuroraDawnVulkanConfigure(const AuroraDawnVulkanHooks* hooks);
|
||||||
|
int AuroraDawnVulkanGetHandles(void* device, AuroraDawnVulkanHandles* handles);
|
||||||
|
void* AuroraDawnVulkanWrap(void* device, const void* textureDescriptor, uint64_t image);
|
||||||
|
int AuroraDawnVulkanRelease(void* device, void* const* textures, uint32_t count);
|
||||||
|
void* AuroraDawnVulkanLock(void* device);
|
||||||
|
void AuroraDawnVulkanUnlock(void* guard);
|
||||||
|
int AuroraDawnVulkanDrain(void* device);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -23,6 +42,17 @@ struct Api {
|
|||||||
AuroraDawnVulkanUnlockFn unlock = nullptr;
|
AuroraDawnVulkanUnlockFn unlock = nullptr;
|
||||||
AuroraDawnVulkanDrainFn drain = nullptr;
|
AuroraDawnVulkanDrainFn drain = nullptr;
|
||||||
bool Load() {
|
bool Load() {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
if (AuroraDawnVulkanVersion() != AURORA_DAWN_VULKAN_ABI) return false;
|
||||||
|
configure = &AuroraDawnVulkanConfigure;
|
||||||
|
handles = &AuroraDawnVulkanGetHandles;
|
||||||
|
wrap = &AuroraDawnVulkanWrap;
|
||||||
|
release = &AuroraDawnVulkanRelease;
|
||||||
|
lock = &AuroraDawnVulkanLock;
|
||||||
|
unlock = &AuroraDawnVulkanUnlock;
|
||||||
|
drain = &AuroraDawnVulkanDrain;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
HMODULE module = GetModuleHandleW(L"webgpu_dawn.dll");
|
HMODULE module = GetModuleHandleW(L"webgpu_dawn.dll");
|
||||||
if (!module) return false;
|
if (!module) return false;
|
||||||
auto version = reinterpret_cast<AuroraDawnVulkanVersionFn>(GetProcAddress(module, "AuroraDawnVulkanVersion"));
|
auto version = reinterpret_cast<AuroraDawnVulkanVersionFn>(GetProcAddress(module, "AuroraDawnVulkanVersion"));
|
||||||
@@ -37,6 +67,7 @@ struct Api {
|
|||||||
LOAD(drain, AuroraDawnVulkanDrainFn, "AuroraDawnVulkanDrain");
|
LOAD(drain, AuroraDawnVulkanDrainFn, "AuroraDawnVulkanDrain");
|
||||||
#undef LOAD
|
#undef LOAD
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} api;
|
} api;
|
||||||
int64_t VkFormat(wgpu::TextureFormat format) {
|
int64_t VkFormat(wgpu::TextureFormat format) {
|
||||||
@@ -222,8 +253,9 @@ void* aurora_vulkan_win32_lock_queue() {
|
|||||||
void aurora_vulkan_win32_unlock_queue(void* guard) { aurora::vulkan_win32::api.unlock(guard); }
|
void aurora_vulkan_win32_unlock_queue(void* guard) { aurora::vulkan_win32::api.unlock(guard); }
|
||||||
#else
|
#else
|
||||||
// C ABI stubs keep the runtime's OpenXR integration linkable on Windows GX
|
// C ABI stubs keep the runtime's OpenXR integration linkable on Windows GX
|
||||||
// builds whose Dawn has no Vulkan backend; the backend then reports that the
|
// builds whose Dawn has no Vulkan backend, and on Linux against a Dawn without
|
||||||
// bridge is unavailable and the game falls back to the desktop renderer.
|
// Aurora's hooks; the backend then reports that the bridge is unavailable and
|
||||||
|
// the game falls back to the desktop renderer.
|
||||||
bool aurora_vulkan_win32_configure(const AuroraDawnVulkanHooks*) { return false; }
|
bool aurora_vulkan_win32_configure(const AuroraDawnVulkanHooks*) { return false; }
|
||||||
bool aurora_vulkan_win32_get_handles(AuroraDawnVulkanHandles* handles, int64_t* format) {
|
bool aurora_vulkan_win32_get_handles(AuroraDawnVulkanHandles* handles, int64_t* format) {
|
||||||
if (handles) *handles = {};
|
if (handles) *handles = {};
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ to a single shared device first.
|
|||||||
| | Quest flavours | `steamFrame` |
|
| | Quest flavours | `steamFrame` |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| CPU target (`kit.json` `androidCpu`) | `cortex-a77` (`kryo` on Quest 1) | `cortex-x4` |
|
| CPU target (`kit.json` `androidCpu`) | `cortex-a77` (`kryo` on Quest 1) | `cortex-x4` |
|
||||||
| `MKW_ANDROID_HEADSET` | `quest` | `steam_frame` (defines `MKW_HEADSET_STEAM_FRAME`) |
|
| `MKW_HEADSET` | empty | `steam_frame` (defines `MKW_HEADSET_STEAM_FRAME`) |
|
||||||
| Library entry | `LauncherActivity` (Quest 1: `QuestActivity`) | `FrameEntryActivity` |
|
| Library entry | `LauncherActivity` (Quest 1: `QuestActivity`) | `FrameEntryActivity` |
|
||||||
| Horizon OS manifest entries | present | removed |
|
| Horizon OS manifest entries | present | removed |
|
||||||
| `[vr] refresh_rate` default | `0` (the headset's own) | `120` |
|
| `[vr] refresh_rate` default | `0` (the headset's own) | `120` |
|
||||||
|
|||||||
+19
-16
@@ -37,18 +37,19 @@ option(MKW_BUILD_PRODUCTS "Build translated WiiCompiled product targets" ON)
|
|||||||
# aurora-main and its third-party tree stay unaffected.
|
# aurora-main and its third-party tree stay unaffected.
|
||||||
set(MKW_PROJECT_COMPILE_DEFINITIONS NOMINMAX)
|
set(MKW_PROJECT_COMPILE_DEFINITIONS NOMINMAX)
|
||||||
|
|
||||||
# The Android headset family the build is for (the Gradle flavour passes it). The
|
# The headset a standalone build is for: the Android app's Gradle flavour passes
|
||||||
# Steam Frame build runs under SteamVR's Android runtime rather than Horizon OS and
|
# it, and so does a native SteamOS build for the Steam Frame
|
||||||
# takes its own defaults (runtime_config.h) through MKW_HEADSET_STEAM_FRAME. The
|
# (Launcher/local-build.sh --headset steam_frame). The Steam Frame takes its own
|
||||||
# definition reaches every target below, so the game kit's recorded compile flags
|
# defaults (runtime_config.h) through MKW_HEADSET_STEAM_FRAME. The definition
|
||||||
# carry it too.
|
# reaches every target below, so the Quest game kit's recorded compile flags carry
|
||||||
if(MKW_PLATFORM_ANDROID)
|
# it too.
|
||||||
set(MKW_ANDROID_HEADSET "quest" CACHE STRING "Android headset family: quest (Meta Quest, any flavour) or steam_frame")
|
if(MKW_PLATFORM_ANDROID OR MKW_PLATFORM_LINUX)
|
||||||
set_property(CACHE MKW_ANDROID_HEADSET PROPERTY STRINGS quest steam_frame)
|
set(MKW_HEADSET "" CACHE STRING "Headset the build targets: empty (a Meta Quest on Android, any PC headset elsewhere) or steam_frame")
|
||||||
if(MKW_ANDROID_HEADSET STREQUAL "steam_frame")
|
set_property(CACHE MKW_HEADSET PROPERTY STRINGS "" steam_frame)
|
||||||
|
if(MKW_HEADSET STREQUAL "steam_frame")
|
||||||
list(APPEND MKW_PROJECT_COMPILE_DEFINITIONS MKW_HEADSET_STEAM_FRAME=1)
|
list(APPEND MKW_PROJECT_COMPILE_DEFINITIONS MKW_HEADSET_STEAM_FRAME=1)
|
||||||
elseif(NOT MKW_ANDROID_HEADSET STREQUAL "quest")
|
elseif(NOT MKW_HEADSET STREQUAL "")
|
||||||
message(FATAL_ERROR "MKW_ANDROID_HEADSET must be quest or steam_frame, not '${MKW_ANDROID_HEADSET}'")
|
message(FATAL_ERROR "MKW_HEADSET must be empty or steam_frame, not '${MKW_HEADSET}'")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -148,10 +149,10 @@ set(MKW_TRANSLATED_COMPILE_JOBS 0 CACHE STRING
|
|||||||
Scheduling only - never affects output bytes, so it is deliberately outside the canonical flag fingerprint.")
|
Scheduling only - never affects output bytes, so it is deliberately outside the canonical flag fingerprint.")
|
||||||
set(MKW_CPPWINRT_INCLUDE_DIR "" CACHE PATH "Optional self-contained C++/WinRT include directory")
|
set(MKW_CPPWINRT_INCLUDE_DIR "" CACHE PATH "Optional self-contained C++/WinRT include directory")
|
||||||
|
|
||||||
# The functional backend is currently Windows D3D12, so only Windows defaults
|
# Windows and Android carry the loader by default. Desktop Linux has the
|
||||||
# to carrying the loader. Linux keeps the capability-gated Vulkan scaffold
|
# same-device Vulkan backend too, but it needs a Dawn built with Aurora's patches
|
||||||
# available to explicit developer builds without making a nonfunctional SDK
|
# (Launcher/build-dawn-linux.sh), so it stays opt-in: Launcher/local-build.sh
|
||||||
# fetch part of every normal build.
|
# --openxr, as the Steam Frame's native SteamOS build uses it.
|
||||||
set(MKW_ENABLE_OPENXR_DEFAULT OFF)
|
set(MKW_ENABLE_OPENXR_DEFAULT OFF)
|
||||||
if(MKW_PLATFORM_WINDOWS OR MKW_PLATFORM_ANDROID)
|
if(MKW_PLATFORM_WINDOWS OR MKW_PLATFORM_ANDROID)
|
||||||
set(MKW_ENABLE_OPENXR_DEFAULT ON)
|
set(MKW_ENABLE_OPENXR_DEFAULT ON)
|
||||||
@@ -301,7 +302,9 @@ if(MKW_PROJECT_COMPILE_DEFINITIONS)
|
|||||||
add_compile_definitions(${MKW_PROJECT_COMPILE_DEFINITIONS})
|
add_compile_definitions(${MKW_PROJECT_COMPILE_DEFINITIONS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MKW_PLATFORM_WINDOWS AND MKW_ENABLE_OPENXR)
|
# The same-device Vulkan backend (openxr_vulkan_win32.cpp, on Windows and desktop
|
||||||
|
# Linux) includes vulkan.h; the pin keeps it independent of the build machine.
|
||||||
|
if((MKW_PLATFORM_WINDOWS OR MKW_PLATFORM_LINUX) AND MKW_ENABLE_OPENXR)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
FetchContent_Declare(vulkan_headers
|
FetchContent_Declare(vulkan_headers
|
||||||
URL "https://github.com/KhronosGroup/Vulkan-Headers/archive/015e25c3c91b70eb1a754d36fb14c4ba6ad9b0b9.tar.gz"
|
URL "https://github.com/KhronosGroup/Vulkan-Headers/archive/015e25c3c91b70eb1a754d36fb14c4ba6ad9b0b9.tar.gz"
|
||||||
|
|||||||
@@ -452,7 +452,14 @@ elseif(MKW_PLATFORM_ANDROID)
|
|||||||
set(MKW_ANDROID_CPU "cortex-a77" CACHE STRING "AArch64 -mcpu target for the Android products")
|
set(MKW_ANDROID_CPU "cortex-a77" CACHE STRING "AArch64 -mcpu target for the Android products")
|
||||||
set(MKW_BASELINE_ARCH_FLAG -mcpu=${MKW_ANDROID_CPU})
|
set(MKW_BASELINE_ARCH_FLAG -mcpu=${MKW_ANDROID_CPU})
|
||||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)$")
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)$")
|
||||||
set(MKW_BASELINE_ARCH_FLAG -mcpu=native)
|
# A cross-build names its CPU; the Steam Frame's Snapdragon 8 Gen 3 exposes SVE (cortex-x4).
|
||||||
|
if(MKW_HEADSET STREQUAL "steam_frame")
|
||||||
|
set(_mkw_linux_cpu_default "cortex-x4")
|
||||||
|
else()
|
||||||
|
set(_mkw_linux_cpu_default "native")
|
||||||
|
endif()
|
||||||
|
set(MKW_LINUX_CPU "${_mkw_linux_cpu_default}" CACHE STRING "AArch64 -mcpu target for the Linux products")
|
||||||
|
set(MKW_BASELINE_ARCH_FLAG -mcpu=${MKW_LINUX_CPU})
|
||||||
else()
|
else()
|
||||||
set(MKW_BASELINE_ARCH_FLAG "")
|
set(MKW_BASELINE_ARCH_FLAG "")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
// Despite the name, also the desktop Linux backend (SteamOS on the Steam Frame): nothing in it is
|
||||||
|
// Windows-specific. The Quest has its own two-device backend (openxr_vulkan.h).
|
||||||
|
#if defined(MKW_ENABLE_OPENXR) && (defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__)))
|
||||||
|
|
||||||
#include "vr/openxr_backend.h"
|
#include "vr/openxr_backend.h"
|
||||||
#include "vr/openxr_runtime.h"
|
#include "vr/openxr_runtime.h"
|
||||||
@@ -112,4 +114,4 @@ private:
|
|||||||
|
|
||||||
} // namespace mkw::vr
|
} // namespace mkw::vr
|
||||||
|
|
||||||
#endif // defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
#endif // defined(MKW_ENABLE_OPENXR) && (defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__)))
|
||||||
@@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#include <sys/system_properties.h>
|
#include <sys/system_properties.h>
|
||||||
|
#endif
|
||||||
|
#if defined(__linux__)
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -275,6 +277,9 @@ bool Injected(const char*) { return false; }
|
|||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
using ConvertNowToXrTime = XrResult(XRAPI_PTR*)(XrInstance, const LARGE_INTEGER*, XrTime*);
|
using ConvertNowToXrTime = XrResult(XRAPI_PTR*)(XrInstance, const LARGE_INTEGER*, XrTime*);
|
||||||
|
#elif defined(__linux__)
|
||||||
|
// Desktop Linux (SteamOS on the Steam Frame); Android declares it with its injection above.
|
||||||
|
using ConvertNowToXrTime = XrResult(XRAPI_PTR*)(XrInstance, const struct timespec*, XrTime*);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -666,7 +671,7 @@ void OpenXRInput::LoadInputClock() {
|
|||||||
if (enabled("XR_KHR_win32_convert_performance_counter_time")) {
|
if (enabled("XR_KHR_win32_convert_performance_counter_time")) {
|
||||||
m_runtime->GetInstanceProcAddress("xrConvertWin32PerformanceCounterToTimeKHR", &function);
|
m_runtime->GetInstanceProcAddress("xrConvertWin32PerformanceCounterToTimeKHR", &function);
|
||||||
}
|
}
|
||||||
#elif defined(__ANDROID__)
|
#elif defined(__linux__)
|
||||||
if (enabled("XR_KHR_convert_timespec_time")) {
|
if (enabled("XR_KHR_convert_timespec_time")) {
|
||||||
m_runtime->GetInstanceProcAddress("xrConvertTimespecTimeToTimeKHR", &function);
|
m_runtime->GetInstanceProcAddress("xrConvertTimespecTimeToTimeKHR", &function);
|
||||||
}
|
}
|
||||||
@@ -692,7 +697,7 @@ XrTime OpenXRInput::InputSampleTime(XrTime predicted_display_time) const {
|
|||||||
&counter, &now))) {
|
&counter, &now))) {
|
||||||
return predicted_display_time;
|
return predicted_display_time;
|
||||||
}
|
}
|
||||||
#elif defined(__ANDROID__)
|
#elif defined(__linux__)
|
||||||
timespec spec{};
|
timespec spec{};
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &spec) != 0 ||
|
if (clock_gettime(CLOCK_MONOTONIC, &spec) != 0 ||
|
||||||
XR_FAILED(reinterpret_cast<ConvertNowToXrTime>(m_convert_now_to_xr_time)(m_runtime->Instance(),
|
XR_FAILED(reinterpret_cast<ConvertNowToXrTime>(m_convert_now_to_xr_time)(m_runtime->Instance(),
|
||||||
|
|||||||
@@ -48,6 +48,14 @@
|
|||||||
#define XR_USE_TIMESPEC
|
#define XR_USE_TIMESPEC
|
||||||
#include <openxr/openxr_platform.h>
|
#include <openxr/openxr_platform.h>
|
||||||
#define MKW_OPENXR_GRAPHICS_BACKEND 1
|
#define MKW_OPENXR_GRAPHICS_BACKEND 1
|
||||||
|
#elif defined(__linux__)
|
||||||
|
// Desktop Linux, SteamOS on the Steam Frame above all: the PC's same-device Vulkan backend, with
|
||||||
|
// Dawn's own device bound to the session.
|
||||||
|
#include "vr/openxr_vulkan_win32.h"
|
||||||
|
#include <time.h>
|
||||||
|
#define XR_USE_TIMESPEC
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
#define MKW_OPENXR_GRAPHICS_BACKEND 1
|
||||||
#else
|
#else
|
||||||
#define MKW_OPENXR_GRAPHICS_BACKEND 0
|
#define MKW_OPENXR_GRAPHICS_BACKEND 0
|
||||||
#endif
|
#endif
|
||||||
@@ -85,9 +93,12 @@ void ConfigurePolicy(bool enabled) noexcept {
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
using GraphicsBackend = OpenXRWindowsBackend;
|
using GraphicsBackend = OpenXRWindowsBackend;
|
||||||
|
|
||||||
#else
|
#elif defined(__ANDROID__)
|
||||||
using GraphicsBackend = OpenXRVulkanBackend;
|
using GraphicsBackend = OpenXRVulkanBackend;
|
||||||
inline constexpr const char* kGraphicsBackendName = "Vulkan";
|
inline constexpr const char* kGraphicsBackendName = "Vulkan";
|
||||||
|
#else
|
||||||
|
using GraphicsBackend = OpenXRWindowsVulkanBackend;
|
||||||
|
inline constexpr const char* kGraphicsBackendName = "Vulkan";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Whether the immersive window's eyes can be aimed through the window, so that only the window is
|
// Whether the immersive window's eyes can be aimed through the window, so that only the window is
|
||||||
@@ -412,6 +423,16 @@ public:
|
|||||||
"XR_FB_display_refresh_rate", "XR_EXT_performance_settings",
|
"XR_FB_display_refresh_rate", "XR_EXT_performance_settings",
|
||||||
"XR_VALVE_frame_controller_interaction"};
|
"XR_VALVE_frame_controller_interaction"};
|
||||||
AddHandMeshExtensions(config);
|
AddHandMeshExtensions(config);
|
||||||
|
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||||
|
// As the PC's Vulkan binding, plus the clock conversion Linux uses and the Steam Frame's
|
||||||
|
// eye gaze for eye-tracked foveation.
|
||||||
|
config.required_extensions = {"XR_KHR_vulkan_enable2"};
|
||||||
|
config.optional_extensions = {"XR_KHR_convert_timespec_time", "XR_FB_display_refresh_rate",
|
||||||
|
"XR_EXT_performance_settings", "XR_VALVE_frame_controller_interaction"};
|
||||||
|
if (RuntimeConfigFile::VrEyeTrackedFoveation()) {
|
||||||
|
config.optional_extensions.push_back("XR_EXT_eye_gaze_interaction");
|
||||||
|
}
|
||||||
|
AddHandMeshExtensions(config);
|
||||||
#else
|
#else
|
||||||
// Either Vulkan binding extension is acceptable; the backend picks
|
// Either Vulkan binding extension is acceptable; the backend picks
|
||||||
// whichever the runtime enabled, preferring enable2.
|
// whichever the runtime enabled, preferring enable2.
|
||||||
@@ -718,9 +739,10 @@ private:
|
|||||||
void ApplyGraphicsRequirements(AuroraConfig& aurora_config) {
|
void ApplyGraphicsRequirements(AuroraConfig& aurora_config) {
|
||||||
aurora_config.desiredBackend = kRequiredAuroraBackend;
|
aurora_config.desiredBackend = kRequiredAuroraBackend;
|
||||||
aurora_config.xrInterop = true;
|
aurora_config.xrInterop = true;
|
||||||
#if defined(__ANDROID__)
|
#if !defined(_WIN32)
|
||||||
// Foveated rendering: fragment density maps are decided with the device. They put a flag on
|
// Foveated rendering (the Quest's and desktop Linux's patched Dawn): fragment density maps
|
||||||
// every render pipeline, so a session launched with foveation off does without them.
|
// are decided with the device. They put a flag on every render pipeline, so a session
|
||||||
|
// launched with foveation off does without them.
|
||||||
aurora_config.xrFragmentDensityMap = RuntimeConfigFile::VrFoveation() != "off";
|
aurora_config.xrFragmentDensityMap = RuntimeConfigFile::VrFoveation() != "off";
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#if defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
#if defined(MKW_ENABLE_OPENXR) && (defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__)))
|
||||||
|
|
||||||
// OpenXR's Vulkan structures are selected when openxr_platform.h is parsed.
|
// OpenXR's Vulkan structures are selected when openxr_platform.h is parsed.
|
||||||
#define XR_USE_GRAPHICS_API_VULKAN
|
#define XR_USE_GRAPHICS_API_VULKAN
|
||||||
@@ -180,7 +180,11 @@ public:
|
|||||||
if (XR_FAILED(get(runtime.Instance(), runtime.SystemId(), &requirements))) return Fail("Vulkan requirements query failed");
|
if (XR_FAILED(get(runtime.Instance(), runtime.SystemId(), &requirements))) return Fail("Vulkan requirements query failed");
|
||||||
requirements_ = {requirements.minApiVersionSupported, requirements.maxApiVersionSupported};
|
requirements_ = {requirements.minApiVersionSupported, requirements.maxApiVersionSupported};
|
||||||
AuroraDawnVulkanHooks hooks{this, CreateInstance, CreateDevice, GetPhysical};
|
AuroraDawnVulkanHooks hooks{this, CreateInstance, CreateDevice, GetPhysical};
|
||||||
|
#if defined(_WIN32)
|
||||||
if (!aurora_vulkan_win32_configure(&hooks)) return Fail("PC Vulkan OpenXR requires the custom Dawn library with Aurora Vulkan ABI 1; rebuild/install it with Launcher/Build-DawnVulkan.ps1");
|
if (!aurora_vulkan_win32_configure(&hooks)) return Fail("PC Vulkan OpenXR requires the custom Dawn library with Aurora Vulkan ABI 1; rebuild/install it with Launcher/Build-DawnVulkan.ps1");
|
||||||
|
#else
|
||||||
|
if (!aurora_vulkan_win32_configure(&hooks)) return Fail("Linux Vulkan OpenXR requires a Dawn built with Aurora's patches (Aurora Vulkan ABI 1); build it with Launcher/build-dawn-linux.sh");
|
||||||
|
#endif
|
||||||
hooks_installed_ = true;
|
hooks_installed_ = true;
|
||||||
{
|
{
|
||||||
std::lock_guard lock(submission_mutex_);
|
std::lock_guard lock(submission_mutex_);
|
||||||
@@ -1315,4 +1319,4 @@ const std::string& OpenXRWindowsVulkanBackend::LastError() const { return m_impl
|
|||||||
|
|
||||||
} // namespace mkw::vr
|
} // namespace mkw::vr
|
||||||
|
|
||||||
#endif // defined(MKW_ENABLE_OPENXR) && defined(_WIN32)
|
#endif // defined(MKW_ENABLE_OPENXR) && (defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__)))
|
||||||
Reference in new issue
Block a user