diff --git a/CMakeLists.txt b/CMakeLists.txt index b9084bea3a76..12c75eaff35c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -507,6 +507,8 @@ if(WIN32) endif() set(CommonVR + Common/VR/OpenXRLoader.cpp + Common/VR/OpenXRLoader.h Common/VR/PPSSPPVR.cpp Common/VR/PPSSPPVR.h Common/VR/VRBase.cpp diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 5c085bd0edd0..39e804db7960 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -557,6 +557,7 @@ + @@ -995,6 +996,7 @@ + @@ -1015,4 +1017,4 @@ - + \ No newline at end of file diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 5c58a6453f16..33468b43d8cc 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -443,6 +443,9 @@ VR + + VR + @@ -839,6 +842,9 @@ VR + + VR + @@ -952,4 +958,4 @@ ext\libpng17 - + \ No newline at end of file diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 84f1b1a37575..bf27a4fcfaa8 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -280,7 +280,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski _dbg_assert_(query.name); int location = -1; - if (IsVRBuild() && IsMultiviewSupported()) { + if (IsVREnabled() && IsMultiviewSupported()) { int index = GetStereoBufferIndex(query.name); if (index >= 0) { std::string layout = GetStereoBufferLayout(query.name); @@ -707,7 +707,7 @@ void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCal switch (step.stepType) { case GLRStepType::RENDER: renderCount++; - if (IsVRBuild()) { + if (IsVREnabled()) { GLRStep vrStep = step; PreprocessStepVR(&vrStep); PerformRenderPass(vrStep, renderCount == 1, renderCount == totalRenderCount); @@ -1603,7 +1603,7 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { fbo_bind_fb_target(false, curFB_->handle); } else { fbo_unbind(); - if (IsVRBuild()) { + if (IsVREnabled()) { BindVRFramebuffer(); } // Backbuffer is now bound. diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index 23c133272ddc..f3eb5f59ebc5 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -577,7 +577,7 @@ void GLRenderManager::Run(int frame) { } } - if (IsVRBuild()) { + if (IsVREnabled()) { int passes = GetVRPassesCount(); for (int i = 0; i < passes; i++) { PreVRFrameRender(i); diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 8a69c0f03721..389eb6dbbe68 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1372,37 +1372,6 @@ void finalize_glslang() { glslang::FinalizeProcess(); } -const char *VulkanResultToString(VkResult res) { - switch (res) { - case VK_NOT_READY: return "VK_NOT_READY"; - case VK_TIMEOUT: return "VK_TIMEOUT"; - case VK_EVENT_SET: return "VK_EVENT_SET"; - case VK_EVENT_RESET: return "VK_EVENT_RESET"; - case VK_INCOMPLETE: return "VK_INCOMPLETE"; - case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY"; - case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; - case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED"; - case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST"; - case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED"; - case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT"; - case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT"; - case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT"; - case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER"; - case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS"; - case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED"; - case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR"; - case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR"; - case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR"; - case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; - case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; - case VK_ERROR_OUT_OF_POOL_MEMORY_KHR: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR"; - case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR: return "VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR"; - - default: - return "VK_ERROR_...(unknown)"; - } -} - void VulkanDeleteList::Take(VulkanDeleteList &del) { _dbg_assert_(cmdPools_.empty()); _dbg_assert_(descPools_.empty()); diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index 7baf795717ea..a6f568aa5f52 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -461,7 +461,6 @@ enum class GLSLVariant { bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *sourceCode, GLSLVariant variant, std::vector &spirv, std::string *errorMessage); -const char *VulkanResultToString(VkResult res); const char *VulkanColorSpaceToString(VkColorSpaceKHR colorSpace); const char *VulkanFormatToString(VkFormat format); diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 52ece6573123..c6012f001e51 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -239,7 +239,6 @@ static VulkanLibraryHandle vulkanLibrary; typedef void *VulkanLibraryHandle; static VulkanLibraryHandle vulkanLibrary; #endif -const char *VulkanResultToString(VkResult res); bool g_vulkanAvailabilityChecked = false; bool g_vulkanMayBeAvailable = false; @@ -274,6 +273,8 @@ static VulkanLibraryHandle VulkanLoadLibrary(const char *logname) { #if PPSSPP_PLATFORM(SWITCH) // Always unavailable, for now. return nullptr; +#elif PPSSPP_PLATFORM(UWP) + return nullptr; #elif PPSSPP_PLATFORM(WINDOWS) return LoadLibrary(L"vulkan-1.dll"); #else @@ -309,7 +310,7 @@ void VulkanSetAvailable(bool available) { bool VulkanMayBeAvailable() { // Unsupported in VR at the moment - if (IsVRBuild()) { + if (IsVREnabled()) { return false; } @@ -724,3 +725,34 @@ void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledE void VulkanFree() { VulkanFreeLibrary(vulkanLibrary); } + +const char *VulkanResultToString(VkResult res) { + switch (res) { + case VK_NOT_READY: return "VK_NOT_READY"; + case VK_TIMEOUT: return "VK_TIMEOUT"; + case VK_EVENT_SET: return "VK_EVENT_SET"; + case VK_EVENT_RESET: return "VK_EVENT_RESET"; + case VK_INCOMPLETE: return "VK_INCOMPLETE"; + case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR"; + case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_ERROR_OUT_OF_POOL_MEMORY_KHR: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR: return "VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR"; + + default: + return "VK_ERROR_...(unknown)"; + } +} diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index b0c14570da26..4f2d97d045b2 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -254,3 +254,5 @@ bool VulkanLoad(); void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &enabledExtensions); void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledExtensions); void VulkanFree(); + +const char *VulkanResultToString(VkResult res); diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 4038c991d124..ae231d63df9f 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -1711,7 +1711,7 @@ VKRRenderPass *VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKR }; renderPass = GetRenderPass(key); - if (IsVRBuild()) { + if (IsVREnabled()) { framebuf = (VkFramebuffer)BindVRFramebuffer(); } else { framebuf = backbuffer_; diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 3c1ea6f07f26..732aa2a0fd30 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -1325,7 +1325,7 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { if (task.steps.empty() && !frameData.hasAcquired) frameData.skipSwap = true; //queueRunner_.LogSteps(stepsOnThread, false); - if (IsVRBuild()) { + if (IsVREnabled()) { int passes = GetVRPassesCount(); for (int i = 0; i < passes; i++) { PreVRFrameRender(i); diff --git a/Common/VR/OpenXRLoader.cpp b/Common/VR/OpenXRLoader.cpp new file mode 100644 index 000000000000..4d5f8fb2466c --- /dev/null +++ b/Common/VR/OpenXRLoader.cpp @@ -0,0 +1,160 @@ +#include "Common/VR/OpenXRLoader.h" +#ifdef _WIN32 +#include "Common/CommonWindows.h" +#endif + +#ifdef XR_NO_PROTOTYPES + +PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr; +PFN_xrEnumerateApiLayerProperties xrEnumerateApiLayerProperties; +PFN_xrEnumerateInstanceExtensionProperties xrEnumerateInstanceExtensionProperties; +PFN_xrCreateInstance xrCreateInstance; +PFN_xrDestroyInstance xrDestroyInstance; +PFN_xrGetInstanceProperties xrGetInstanceProperties; +PFN_xrPollEvent xrPollEvent; +PFN_xrResultToString xrResultToString; +PFN_xrStructureTypeToString xrStructureTypeToString; +PFN_xrGetSystem xrGetSystem; +PFN_xrGetSystemProperties xrGetSystemProperties; +PFN_xrEnumerateEnvironmentBlendModes xrEnumerateEnvironmentBlendModes; +PFN_xrCreateSession xrCreateSession; +PFN_xrDestroySession xrDestroySession; +PFN_xrEnumerateReferenceSpaces xrEnumerateReferenceSpaces; +PFN_xrCreateReferenceSpace xrCreateReferenceSpace; +PFN_xrGetReferenceSpaceBoundsRect xrGetReferenceSpaceBoundsRect; +PFN_xrCreateActionSpace xrCreateActionSpace; +PFN_xrLocateSpace xrLocateSpace; +PFN_xrDestroySpace xrDestroySpace; +PFN_xrEnumerateViewConfigurations xrEnumerateViewConfigurations; +PFN_xrGetViewConfigurationProperties xrGetViewConfigurationProperties; +PFN_xrEnumerateViewConfigurationViews xrEnumerateViewConfigurationViews; +PFN_xrEnumerateSwapchainFormats xrEnumerateSwapchainFormats; +PFN_xrCreateSwapchain xrCreateSwapchain; +PFN_xrDestroySwapchain xrDestroySwapchain; +PFN_xrEnumerateSwapchainImages xrEnumerateSwapchainImages; +PFN_xrAcquireSwapchainImage xrAcquireSwapchainImage; +PFN_xrWaitSwapchainImage xrWaitSwapchainImage; +PFN_xrReleaseSwapchainImage xrReleaseSwapchainImage; +PFN_xrBeginSession xrBeginSession; +PFN_xrEndSession xrEndSession; +PFN_xrRequestExitSession xrRequestExitSession; +PFN_xrWaitFrame xrWaitFrame; +PFN_xrBeginFrame xrBeginFrame; +PFN_xrEndFrame xrEndFrame; +PFN_xrLocateViews xrLocateViews; +PFN_xrStringToPath xrStringToPath; +PFN_xrPathToString xrPathToString; +PFN_xrCreateActionSet xrCreateActionSet; +PFN_xrDestroyActionSet xrDestroyActionSet; +PFN_xrCreateAction xrCreateAction; +PFN_xrDestroyAction xrDestroyAction; +PFN_xrSuggestInteractionProfileBindings xrSuggestInteractionProfileBindings; +PFN_xrAttachSessionActionSets xrAttachSessionActionSets; +PFN_xrGetCurrentInteractionProfile xrGetCurrentInteractionProfile; +PFN_xrGetActionStateBoolean xrGetActionStateBoolean; +PFN_xrGetActionStateFloat xrGetActionStateFloat; +PFN_xrGetActionStateVector2f xrGetActionStateVector2f; +PFN_xrGetActionStatePose xrGetActionStatePose; +PFN_xrSyncActions xrSyncActions; +PFN_xrEnumerateBoundSourcesForAction xrEnumerateBoundSourcesForAction; +PFN_xrGetInputSourceLocalizedName xrGetInputSourceLocalizedName; +PFN_xrApplyHapticFeedback xrApplyHapticFeedback; +PFN_xrStopHapticFeedback xrStopHapticFeedback; + +#ifdef XR_USE_PLATFORM_WIN32 +#define dlsym(x, y) GetProcAddress(x, y) +static HMODULE g_xrLibrary; +#else +#define dlsym(x, y) nullptr +void *g_xrLibrary; +#endif + +#define LOAD_INSTANCE_FUNC(name) (PFN_ ## name)xrGetInstanceProcAddr(instance, #name, (PFN_xrVoidFunction *)(&name)) + + +bool XRLoad() { + if (g_xrLibrary) { + // Already loaded. That's OK. + return true; + } + +#ifdef XR_USE_PLATFORM_WIN32 + g_xrLibrary = LoadLibrary(L"openxr_loader.dll"); + if (!g_xrLibrary) { + return false; + } +#else + return false; +#endif + + // Load the three basic functions. + xrGetInstanceProcAddr = (PFN_xrGetInstanceProcAddr)dlsym(g_xrLibrary, "xrGetInstanceProcAddr"); + xrEnumerateApiLayerProperties = (PFN_xrEnumerateApiLayerProperties)dlsym(g_xrLibrary, "xrEnumerateApiLayerProperties"); + xrEnumerateInstanceExtensionProperties = (PFN_xrEnumerateInstanceExtensionProperties)dlsym(g_xrLibrary, "xrEnumerateInstanceExtensionProperties"); + + // Load the rest. + return true; +} + +void XRLoadInstanceFunctions(XrInstance instance) { + LOAD_INSTANCE_FUNC(xrCreateInstance); + LOAD_INSTANCE_FUNC(xrGetInstanceProcAddr); + LOAD_INSTANCE_FUNC(xrEnumerateApiLayerProperties); + LOAD_INSTANCE_FUNC(xrEnumerateInstanceExtensionProperties); + LOAD_INSTANCE_FUNC(xrCreateInstance); + LOAD_INSTANCE_FUNC(xrDestroyInstance); + LOAD_INSTANCE_FUNC(xrGetInstanceProperties); + LOAD_INSTANCE_FUNC(xrPollEvent); + LOAD_INSTANCE_FUNC(xrResultToString); + LOAD_INSTANCE_FUNC(xrStructureTypeToString); + LOAD_INSTANCE_FUNC(xrGetSystem); + LOAD_INSTANCE_FUNC(xrGetSystemProperties); + LOAD_INSTANCE_FUNC(xrEnumerateEnvironmentBlendModes); + LOAD_INSTANCE_FUNC(xrCreateSession); + LOAD_INSTANCE_FUNC(xrDestroySession); + LOAD_INSTANCE_FUNC(xrEnumerateReferenceSpaces); + LOAD_INSTANCE_FUNC(xrCreateReferenceSpace); + LOAD_INSTANCE_FUNC(xrGetReferenceSpaceBoundsRect); + LOAD_INSTANCE_FUNC(xrCreateActionSpace); + LOAD_INSTANCE_FUNC(xrLocateSpace); + LOAD_INSTANCE_FUNC(xrDestroySpace); + LOAD_INSTANCE_FUNC(xrEnumerateViewConfigurations); + LOAD_INSTANCE_FUNC(xrGetViewConfigurationProperties); + LOAD_INSTANCE_FUNC(xrEnumerateViewConfigurationViews); + LOAD_INSTANCE_FUNC(xrEnumerateSwapchainFormats); + LOAD_INSTANCE_FUNC(xrCreateSwapchain); + LOAD_INSTANCE_FUNC(xrDestroySwapchain); + LOAD_INSTANCE_FUNC(xrEnumerateSwapchainImages); + LOAD_INSTANCE_FUNC(xrAcquireSwapchainImage); + LOAD_INSTANCE_FUNC(xrWaitSwapchainImage); + LOAD_INSTANCE_FUNC(xrReleaseSwapchainImage); + LOAD_INSTANCE_FUNC(xrBeginSession); + LOAD_INSTANCE_FUNC(xrEndSession); + LOAD_INSTANCE_FUNC(xrRequestExitSession); + LOAD_INSTANCE_FUNC(xrWaitFrame); + LOAD_INSTANCE_FUNC(xrBeginFrame); + LOAD_INSTANCE_FUNC(xrEndFrame); + LOAD_INSTANCE_FUNC(xrLocateViews); + LOAD_INSTANCE_FUNC(xrStringToPath); + LOAD_INSTANCE_FUNC(xrPathToString); + LOAD_INSTANCE_FUNC(xrCreateActionSet); + LOAD_INSTANCE_FUNC(xrDestroyActionSet); + LOAD_INSTANCE_FUNC(xrCreateAction); + LOAD_INSTANCE_FUNC(xrDestroyAction); + LOAD_INSTANCE_FUNC(xrSuggestInteractionProfileBindings); + LOAD_INSTANCE_FUNC(xrAttachSessionActionSets); + LOAD_INSTANCE_FUNC(xrGetCurrentInteractionProfile); + LOAD_INSTANCE_FUNC(xrGetActionStateBoolean); + LOAD_INSTANCE_FUNC(xrGetActionStateFloat); + LOAD_INSTANCE_FUNC(xrGetActionStateVector2f); + LOAD_INSTANCE_FUNC(xrGetActionStatePose); + LOAD_INSTANCE_FUNC(xrSyncActions); + LOAD_INSTANCE_FUNC(xrEnumerateBoundSourcesForAction); + LOAD_INSTANCE_FUNC(xrGetInputSourceLocalizedName); + LOAD_INSTANCE_FUNC(xrApplyHapticFeedback); + LOAD_INSTANCE_FUNC(xrStopHapticFeedback); + + // TODO: Load any extensions we need, too. +} + +#endif diff --git a/Common/VR/OpenXRLoader.h b/Common/VR/OpenXRLoader.h new file mode 100644 index 000000000000..ce6613ec5ec3 --- /dev/null +++ b/Common/VR/OpenXRLoader.h @@ -0,0 +1,122 @@ +#pragma once + +//Vulkan +#ifdef VK_USE_NATIVE_LIB +#include +#else +#include "Common/GPU/Vulkan/VulkanLoader.h" +using namespace PPSSPP_VK; +#endif + +#ifdef ANDROID +#include +#define XR_USE_PLATFORM_ANDROID 1 +#define XR_USE_GRAPHICS_API_OPENGL_ES 1 +#define XR_USE_GRAPHICS_API_VULKAN 1 +#include +#include + +#if OPENXR +// One of the Android-based headsets. We're linking with a static OpenXR loader. +#else +// Normal Android app, we don't have a loader so use our own dynamic loader, which won't load anything. +#define XR_NO_PROTOTYPES 1 +#endif + +#elif defined(_WIN32) +#include "Common/CommonWindows.h" +#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION) +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP +#if defined(_M_IX86) || defined(_M_X64) +#include "Common/GPU/OpenGL/GLCommon.h" +#define XR_USE_GRAPHICS_API_OPENGL 1 +#endif +#define XR_USE_PLATFORM_WIN32 1 +#endif +#endif +#define XR_USE_GRAPHICS_API_VULKAN 1 +#include "Common/VR/OpenXRLoader.h" +#include +#define XR_NO_PROTOTYPES 1 +#else +#define XR_USE_GRAPHICS_API_VULKAN 1 +#define XR_NO_PROTOTYPES 1 +#endif + +#include +#include + +#ifdef XR_NO_PROTOTYPES + +extern PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr; +extern PFN_xrEnumerateApiLayerProperties xrEnumerateApiLayerProperties; +extern PFN_xrEnumerateInstanceExtensionProperties xrEnumerateInstanceExtensionProperties; +extern PFN_xrCreateInstance xrCreateInstance; +extern PFN_xrDestroyInstance xrDestroyInstance; +extern PFN_xrGetInstanceProperties xrGetInstanceProperties; +extern PFN_xrPollEvent xrPollEvent; +extern PFN_xrResultToString xrResultToString; +extern PFN_xrStructureTypeToString xrStructureTypeToString; +extern PFN_xrGetSystem xrGetSystem; +extern PFN_xrGetSystemProperties xrGetSystemProperties; +extern PFN_xrEnumerateEnvironmentBlendModes xrEnumerateEnvironmentBlendModes; +extern PFN_xrCreateSession xrCreateSession; +extern PFN_xrDestroySession xrDestroySession; +extern PFN_xrEnumerateReferenceSpaces xrEnumerateReferenceSpaces; +extern PFN_xrCreateReferenceSpace xrCreateReferenceSpace; +extern PFN_xrGetReferenceSpaceBoundsRect xrGetReferenceSpaceBoundsRect; +extern PFN_xrCreateActionSpace xrCreateActionSpace; +extern PFN_xrLocateSpace xrLocateSpace; +extern PFN_xrDestroySpace xrDestroySpace; +extern PFN_xrEnumerateViewConfigurations xrEnumerateViewConfigurations; +extern PFN_xrGetViewConfigurationProperties xrGetViewConfigurationProperties; +extern PFN_xrEnumerateViewConfigurationViews xrEnumerateViewConfigurationViews; +extern PFN_xrEnumerateSwapchainFormats xrEnumerateSwapchainFormats; +extern PFN_xrCreateSwapchain xrCreateSwapchain; +extern PFN_xrDestroySwapchain xrDestroySwapchain; +extern PFN_xrEnumerateSwapchainImages xrEnumerateSwapchainImages; +extern PFN_xrAcquireSwapchainImage xrAcquireSwapchainImage; +extern PFN_xrWaitSwapchainImage xrWaitSwapchainImage; +extern PFN_xrReleaseSwapchainImage xrReleaseSwapchainImage; +extern PFN_xrBeginSession xrBeginSession; +extern PFN_xrEndSession xrEndSession; +extern PFN_xrRequestExitSession xrRequestExitSession; +extern PFN_xrWaitFrame xrWaitFrame; +extern PFN_xrBeginFrame xrBeginFrame; +extern PFN_xrEndFrame xrEndFrame; +extern PFN_xrLocateViews xrLocateViews; +extern PFN_xrStringToPath xrStringToPath; +extern PFN_xrPathToString xrPathToString; +extern PFN_xrCreateActionSet xrCreateActionSet; +extern PFN_xrDestroyActionSet xrDestroyActionSet; +extern PFN_xrCreateAction xrCreateAction; +extern PFN_xrDestroyAction xrDestroyAction; +extern PFN_xrSuggestInteractionProfileBindings xrSuggestInteractionProfileBindings; +extern PFN_xrAttachSessionActionSets xrAttachSessionActionSets; +extern PFN_xrGetCurrentInteractionProfile xrGetCurrentInteractionProfile; +extern PFN_xrGetActionStateBoolean xrGetActionStateBoolean; +extern PFN_xrGetActionStateFloat xrGetActionStateFloat; +extern PFN_xrGetActionStateVector2f xrGetActionStateVector2f; +extern PFN_xrGetActionStatePose xrGetActionStatePose; +extern PFN_xrSyncActions xrSyncActions; +extern PFN_xrEnumerateBoundSourcesForAction xrEnumerateBoundSourcesForAction; +extern PFN_xrGetInputSourceLocalizedName xrGetInputSourceLocalizedName; +extern PFN_xrApplyHapticFeedback xrApplyHapticFeedback; +extern PFN_xrStopHapticFeedback xrStopHapticFeedback; + +// Dynamic loader for OpenXR on desktop platforms. +// On Quest/Pico, we use statically linked loaders provided by the platform owners. +// On Windows (and Linux etc), we're not so lucky - we could link to static libraries, but we really +// don't want to as we still want to function when one is not present. +// +// Similar to our dynamic Vulkan loader. + +bool XRLoad(); +void XRLoadInstanceFunctions(XrInstance instance); + +#else + +inline bool XRLoad() { return true; } +inline void XRLoadInstanceFunctions(XrInstance instance) {} + +#endif diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index ec20865e7bc7..537844b0731f 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -1,14 +1,14 @@ -#ifdef OPENXR - -#include "Common/GPU/OpenGL/GLRenderManager.h" -#include "Common/GPU/Vulkan/VulkanContext.h" - #include "Common/VR/PPSSPPVR.h" #include "Common/VR/VRBase.h" #include "Common/VR/VRInput.h" #include "Common/VR/VRMath.h" #include "Common/VR/VRRenderer.h" +#if XR_USE_GRAPHICS_API_OPENGL +#include "Common/GPU/OpenGL/GLRenderManager.h" +#endif +#include "Common/GPU/Vulkan/VulkanContext.h" + #include "Core/HLE/sceDisplay.h" #include "Core/Config.h" #include "Core/KeyMap.h" @@ -98,8 +98,14 @@ VR app flow integration ================================================================================ */ -bool IsVRBuild() { +bool IsVREnabled() { + // For now, let the OPENXR build flag control enablement. + // This will change. +#ifdef OPENXR return true; +#else + return false; +#endif } #if PPSSPP_PLATFORM(ANDROID) @@ -333,6 +339,8 @@ void UpdateVRSpecialKeys(const KeyInput &key) { ================================================================================ */ +#if XR_USE_GRAPHICS_API_OPENGL + void PreprocessSkyplane(GLRStep* step) { // Do not do anything if the scene is not in VR. @@ -374,6 +382,12 @@ void PreprocessStepVR(void* step) { if (vrCompat[VR_COMPAT_SKYPLANE]) PreprocessSkyplane(glrStep); } +#else + +void PreprocessStepVR(void* step) {} + +#endif + void SetVRCompat(VRCompatFlag flag, long value) { vrCompat[flag] = value; } @@ -390,6 +404,12 @@ void* BindVRFramebuffer() { return VR_BindFramebuffer(VR_GetEngine()); } +inline float clampFloat(float x, float minValue, float maxValue) { + if (x < minValue) return minValue; + if (x > maxValue) return maxValue; + return x; +} + bool StartVRRender() { if (!VR_GetConfig(VR_CONFIG_VIEWPORT_VALID)) { VR_InitRenderer(VR_GetEngine(), IsMultiviewSupported()); @@ -424,8 +444,8 @@ bool StartVRRender() { height = 0; side = 0; } - g_Config.fCameraHeight = std::clamp(height, -10.0f, 10.0f); - g_Config.fCameraSide = std::clamp(side, -10.0f, 10.0f); + g_Config.fCameraHeight = clampFloat(height, -10.0f, 10.0f); + g_Config.fCameraSide = clampFloat(side, -10.0f, 10.0f); //right joystick controls distance and fov float dst = g_Config.fCameraDistance; @@ -439,8 +459,8 @@ bool StartVRRender() { fov = 100; dst = 0; } - g_Config.fCameraDistance = std::clamp(dst, -10.0f, 10.0f); - g_Config.fFieldOfViewPercentage = std::clamp(fov, 100.0f, 200.0f); + g_Config.fCameraDistance = clampFloat(dst, -10.0f, 10.0f); + g_Config.fFieldOfViewPercentage = clampFloat(fov, 100.0f, 200.0f); } // Set customizations @@ -593,5 +613,3 @@ void UpdateVRView(float* leftEye, float* rightEye) { memcpy(dst[index], renderView.M, 16 * sizeof(float)); } } - -#endif diff --git a/Common/VR/PPSSPPVR.h b/Common/VR/PPSSPPVR.h index 65a14158ffd9..2dd2d1c11f2c 100644 --- a/Common/VR/PPSSPPVR.h +++ b/Common/VR/PPSSPPVR.h @@ -17,10 +17,8 @@ enum VRCompatFlag { VR_COMPAT_MAX }; -#ifdef OPENXR - // VR app flow integration -bool IsVRBuild(); +bool IsVREnabled(); void InitVROnAndroid(void* vm, void* activity, const char* system, int version, const char* name); void EnterVR(bool firstStart, void* vulkanContext); void GetVRResolutionPerEye(int* width, int* height); @@ -45,34 +43,3 @@ bool Is2DVRObject(float* projMatrix, bool ortho); void UpdateVRParams(float* projMatrix); void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye); void UpdateVRView(float* leftEye, float* rightEye); - -#else //dummy integration - -// VR app flow integration -inline bool IsVRBuild() { return false; } -inline void InitVROnAndroid(void* vm, void* activity, const char* system, int version, const char* name) {} -inline void EnterVR(bool firstTime, void* vulkanContext) {} -inline void GetVRResolutionPerEye(int* width, int* height) {} -inline void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool(*NativeTouch)(const TouchInput &touch), bool haptics, float dp_xscale, float dp_yscale) {} -inline void UpdateVRSpecialKeys(const KeyInput &key) {} - -// VR games compatibility -inline void PreprocessStepVR(void* step) {} -inline void SetVRCompat(VRCompatFlag flag, long value) {} - -// VR rendering integration -inline void* BindVRFramebuffer() { return nullptr; } -inline bool StartVRRender() { return false; } -inline void FinishVRRender() {} -inline void PreVRFrameRender(int fboIndex) {} -inline void PostVRFrameRender() {} -inline int GetVRFBOIndex() { return 0; } -inline int GetVRPassesCount() { return 1; } -inline bool IsMultiviewSupported() { return false; } -inline bool IsFlatVRScene() { return true; } -inline bool Is2DVRObject(float* projMatrix, bool ortho) { return false; } -inline void UpdateVRParams(float* projMatrix) {} -inline void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye) {} -inline void UpdateVRView(float* leftEye, float* rightEye) {} - -#endif diff --git a/Common/VR/VRBase.cpp b/Common/VR/VRBase.cpp index 9c36fab0db66..2855a75e1af8 100644 --- a/Common/VR/VRBase.cpp +++ b/Common/VR/VRBase.cpp @@ -5,9 +5,9 @@ #include #include -#if defined(OPENXR) - +#ifndef _WIN32 #include +#endif enum ConfigsSetEXT { UNREAL_VERSION = 0, @@ -30,7 +30,7 @@ enum PxrTrackingDof { typedef XrResult (XRAPI_PTR *PFN_xrSetEngineVersionPico)(XrInstance instance,const char* version); typedef XrResult (XRAPI_PTR *PFN_xrStartCVControllerThreadPico)(XrInstance instance,int headSensorState, int handSensorState); typedef XrResult (XRAPI_PTR *PFN_xrStopCVControllerThreadPico)(XrInstance instance,int headSensorState, int handSensorState); -typedef XrResult (XRAPI_PTR *PFN_xrSetConfigPICO) (XrSession instance, enum ConfigsSetEXT configIndex, char* configData); +typedef XrResult (XRAPI_PTR *PFN_xrSetConfigPICO) (XrSession instance, enum ConfigsSetEXT configIndex, const char *configData); PFN_xrSetConfigPICO pfnXrSetConfigPICO = nullptr; PFN_xrSetEngineVersionPico pfnXrSetEngineVersionPico = nullptr; @@ -45,6 +45,10 @@ void VR_Init( void* system, const char* name, int version ) { if (vr_initialized) return; + if (!XRLoad()) { + return; + } + ovrApp_Clear(&vr_engine.appState); #ifdef ANDROID @@ -63,17 +67,20 @@ void VR_Init( void* system, const char* name, int version ) { #endif std::vector extensions; - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { extensions.push_back(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME); } else { +#ifdef XR_USE_GRAPHICS_API_OPENGL_ES extensions.push_back(XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME); +#endif } extensions.push_back(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME); - if (VR_GetPlatformFLag(VR_PLATFORM_PERFORMANCE_EXT)) { +#ifdef ANDROID + if (VR_GetPlatformFlag(VR_PLATFORM_PERFORMANCE_EXT)) { extensions.push_back(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME); extensions.push_back(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME); } - if (VR_GetPlatformFLag(VR_PLATFORM_PICO_INIT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_PICO_INIT)) { extensions.push_back(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME); extensions.push_back("XR_PICO_android_controller_function_ext_enable"); extensions.push_back("XR_PICO_view_state_ext_enable"); @@ -81,6 +88,7 @@ void VR_Init( void* system, const char* name, int version ) { extensions.push_back("XR_PICO_configs_ext"); extensions.push_back("XR_PICO_reset_sensor"); } +#endif // Create the OpenXR instance. XrApplicationInfo appInfo; @@ -99,12 +107,12 @@ void VR_Init( void* system, const char* name, int version ) { instanceCreateInfo.applicationInfo = appInfo; instanceCreateInfo.enabledApiLayerCount = 0; instanceCreateInfo.enabledApiLayerNames = NULL; - instanceCreateInfo.enabledExtensionCount = extensions.size(); + instanceCreateInfo.enabledExtensionCount = (uint32_t)extensions.size(); instanceCreateInfo.enabledExtensionNames = extensions.data(); #ifdef ANDROID XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR}; - if (VR_GetPlatformFLag(VR_PLATFORM_PICO_INIT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_PICO_INIT)) { ovrJava* java = (ovrJava*)system; instanceCreateInfoAndroid.applicationVM = java->Vm; instanceCreateInfoAndroid.applicationActivity = java->ActivityObject; @@ -119,7 +127,9 @@ void VR_Init( void* system, const char* name, int version ) { exit(1); } - if (VR_GetPlatformFLag(VR_PLATFORM_PICO_INIT)) { + XRLoadInstanceFunctions(vr_engine.appState.Instance); + + if (VR_GetPlatformFlag(VR_PLATFORM_PICO_INIT)) { xrGetInstanceProcAddr(vr_engine.appState.Instance, "xrSetEngineVersionPico", (PFN_xrVoidFunction*)(&pfnXrSetEngineVersionPico)); xrGetInstanceProcAddr(vr_engine.appState.Instance, "xrStartCVControllerThreadPico", (PFN_xrVoidFunction*)(&pfnXrStartCVControllerThreadPico)); xrGetInstanceProcAddr(vr_engine.appState.Instance, "xrStopCVControllerThreadPico", (PFN_xrVoidFunction*)(&pfnXrStopCVControllerThreadPico)); @@ -153,7 +163,7 @@ void VR_Init( void* system, const char* name, int version ) { } // Get the graphics requirements. - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR = NULL; OXR(xrGetInstanceProcAddr( vr_engine.appState.Instance, @@ -164,6 +174,7 @@ void VR_Init( void* system, const char* name, int version ) { graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR; OXR(pfnGetVulkanGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); } else { +#ifdef XR_USE_GRAPHICS_API_OPENGL_ES PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL; OXR(xrGetInstanceProcAddr( vr_engine.appState.Instance, @@ -173,16 +184,19 @@ void VR_Init( void* system, const char* name, int version ) { XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = {}; graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR; OXR(pfnGetOpenGLESGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); +#endif } +#ifdef ANDROID vr_engine.appState.MainThreadTid = gettid(); +#endif vr_engine.appState.SystemId = systemId; vr_initialized = 1; } void VR_Destroy( engine_t* engine ) { if (engine == &vr_engine) { - if (VR_GetPlatformFLag(VR_PLATFORM_PICO_INIT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_PICO_INIT)) { if (pfnXrStopCVControllerThreadPico != nullptr) { pfnXrStopCVControllerThreadPico(engine->appState.Instance, PXR_TRACKING_6DOF, PXR_TRACKING_6DOF); } @@ -204,11 +218,11 @@ void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVu XrSessionCreateInfo sessionCreateInfo = {}; #ifdef ANDROID XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingGL = {}; -#else +#elif XR_USE_GRAPHICS_API_OPENGL XrGraphicsBindingOpenGLWin32KHR graphicsBindingGL = {}; #endif memset(&sessionCreateInfo, 0, sizeof(sessionCreateInfo)); - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { sessionCreateInfo.next = graphicsBindingVulkan; } else { #ifdef ANDROID @@ -217,10 +231,10 @@ void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVu graphicsBindingGL.display = eglGetCurrentDisplay(); graphicsBindingGL.config = eglGetCurrentSurface(EGL_DRAW); graphicsBindingGL.context = eglGetCurrentContext(); + sessionCreateInfo.next = &graphicsBindingGL; #else //TODO:PCVR definition #endif - sessionCreateInfo.next = &graphicsBindingGL; } sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO; sessionCreateInfo.createFlags = 0; @@ -232,7 +246,7 @@ void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVu ALOGE("Failed to create XR session: %d.", initResult); exit(1); } - if (VR_GetPlatformFLag(VR_PLATFORM_PICO_INIT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_PICO_INIT)) { pfnXrSetConfigPICO(engine->appState.Session, TRACKING_ORIGIN, "1"); } @@ -262,12 +276,10 @@ engine_t* VR_GetEngine( void ) { return &vr_engine; } -bool VR_GetPlatformFLag(VRPlatformFlag flag) { +bool VR_GetPlatformFlag(VRPlatformFlag flag) { return vr_platform[flag]; } void VR_SetPlatformFLag(VRPlatformFlag flag, bool value) { vr_platform[flag] = value; } - -#endif diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index 73870ab7dda1..34e52908d4f5 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -10,36 +10,10 @@ #define ALOGV(...) printf(__VA_ARGS__) #endif -//Vulkan -#ifdef VK_USE_NATIVE_LIB -#include -#else -#include "Common/GPU/Vulkan/VulkanLoader.h" -using namespace PPSSPP_VK; -#endif - -#ifdef ANDROID -//OpenXR -#define XR_USE_PLATFORM_ANDROID 1 -#define XR_USE_GRAPHICS_API_OPENGL_ES 1 -#define XR_USE_GRAPHICS_API_VULKAN 1 -#include -#include -#include -#elif defined(_WIN32) -#include "Common/CommonWindows.h" -#include -#define XR_USE_PLATFORM_WIN32 1 -#define XR_USE_GRAPHICS_API_OPENGL_ES 1 -#define XR_USE_GRAPHICS_API_VULKAN 1 -#else -#define XR_USE_GRAPHICS_API_OPENGL_ES 1 -#define XR_USE_GRAPHICS_API_VULKAN 1 -#endif +#include "Common/VR/OpenXRLoader.h" -#include -#include -#include +#define _USE_MATH_DEFINES +#include #ifdef ANDROID @@ -172,7 +146,7 @@ typedef struct { typedef struct { uint64_t frameIndex; ovrApp appState; - float predictedDisplayTime; + XrTime predictedDisplayTime; XrGraphicsBindingVulkanKHR graphicsBindingVulkan; } engine_t; @@ -192,7 +166,7 @@ void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVu void VR_LeaveVR( engine_t* engine ); engine_t* VR_GetEngine( void ); -bool VR_GetPlatformFLag(VRPlatformFlag flag); +bool VR_GetPlatformFlag(VRPlatformFlag flag); void VR_SetPlatformFLag(VRPlatformFlag flag, bool value); void ovrApp_Clear(ovrApp* app); diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index be4b14c3e0f4..a3986ee7d4fb 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -43,9 +43,9 @@ void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) { frameBuffer->Acquired = false; } -#ifdef OPENXR +#if XR_USE_GRAPHICS_API_OPENGL_ES -bool ovrFramebuffer_CreateGL(XrSession session, ovrFramebuffer* frameBuffer, int width, int height, bool multiview) { +static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBuffer, int width, int height, bool multiview) { frameBuffer->Width = width; frameBuffer->Height = height; @@ -56,12 +56,11 @@ bool ovrFramebuffer_CreateGL(XrSession session, ovrFramebuffer* frameBuffer, int } typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei); - auto glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)eglGetProcAddress ("glFramebufferTextureMultiviewOVR"); - if (!glFramebufferTextureMultiviewOVR) - { + PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR glFramebufferTextureMultiviewOVR = nullptr; + glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)eglGetProcAddress ("glFramebufferTextureMultiviewOVR"); + if (!glFramebufferTextureMultiviewOVR) { ALOGE("Can not get proc address for glFramebufferTextureMultiviewOVR.\n"); } - XrSwapchainCreateInfo swapChainCreateInfo; memset(&swapChainCreateInfo, 0, sizeof(swapChainCreateInfo)); swapChainCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; @@ -136,8 +135,12 @@ bool ovrFramebuffer_CreateGL(XrSession session, ovrFramebuffer* frameBuffer, int return true; } -bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuffer, int width, int height, - bool multiview, void* context) { +#endif + +#if XR_USE_GRAPHICS_API_VULKAN + +static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuffer, int width, int height, + bool multiview, void* context) { frameBuffer->Width = width; frameBuffer->Height = height; @@ -239,9 +242,11 @@ bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuffer, int return true; } +#endif + void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer) { - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { - for (int i = 0; i < frameBuffer->TextureSwapChainLength; i++) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { + for (int i = 0; i < (int)frameBuffer->TextureSwapChainLength; i++) { vkDestroyImageView(frameBuffer->VKContext->device, frameBuffer->VKColorImages[i], nullptr); vkDestroyImageView(frameBuffer->VKContext->device, frameBuffer->VKDepthImages[i], nullptr); vkDestroyFramebuffer(frameBuffer->VKContext->device, frameBuffer->VKFrameBuffers[i], nullptr); @@ -250,7 +255,7 @@ void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer) { delete[] frameBuffer->VKDepthImages; delete[] frameBuffer->VKFrameBuffers; } else { -#ifdef XR_USE_GRAPHICS_API_OPENGL_ES +#if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL GL(glDeleteFramebuffers(frameBuffer->TextureSwapChainLength, frameBuffer->GLFrameBuffers)); free(frameBuffer->GLFrameBuffers); #endif @@ -264,10 +269,10 @@ void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer) { } void* ovrFramebuffer_SetCurrent(ovrFramebuffer* frameBuffer) { - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { return (void *)frameBuffer->VKFrameBuffers[frameBuffer->TextureSwapChainIndex]; } else { -#ifdef XR_USE_GRAPHICS_API_OPENGL_ES +#if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer->GLFrameBuffers[frameBuffer->TextureSwapChainIndex])); #endif return nullptr; @@ -296,10 +301,10 @@ void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) { ovrFramebuffer_SetCurrent(frameBuffer); - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { //TODO:implement } else { -#ifdef XR_USE_GRAPHICS_API_OPENGL_ES +#if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL GL(glEnable( GL_SCISSOR_TEST )); GL(glViewport( 0, 0, frameBuffer->Width, frameBuffer->Height )); GL(glClearColor( 0.0f, 0.0f, 0.0f, 1.0f )); @@ -318,10 +323,10 @@ void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { frameBuffer->Acquired = false; // Clear the alpha channel, other way OpenXR would not transfer the framebuffer fully - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { //TODO:implement } else { -#ifdef XR_USE_GRAPHICS_API_OPENGL_ES +#if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL GL(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE)); GL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); GL(glClear(GL_COLOR_BUFFER_BIT)); @@ -352,8 +357,10 @@ void ovrRenderer_Create(XrSession session, ovrRenderer* renderer, int width, int if (vulkanContext) { ovrFramebuffer_CreateVK(session, &renderer->FrameBuffer[i], width, height, multiview, vulkanContext); } else { -#ifdef XR_USE_GRAPHICS_API_OPENGL_ES - ovrFramebuffer_CreateGL(session, &renderer->FrameBuffer[i], width, height, multiview); +#if XR_USE_GRAPHICS_API_OPENGL_ES + ovrFramebuffer_CreateGLES(session, &renderer->FrameBuffer[i], width, height, multiview); +#elif XR_USE_GRAPHICS_API_OPENGL + // TODO #endif } } @@ -367,10 +374,10 @@ void ovrRenderer_Destroy(ovrRenderer* renderer) { } void ovrRenderer_MouseCursor(ovrRenderer* renderer, int x, int y, int size) { - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { //TODO:implement } else { -#ifdef XR_USE_GRAPHICS_API_OPENGL_ES +#if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL GL(glEnable(GL_SCISSOR_TEST)); GL(glScissor(x, y, size, size)); GL(glViewport(x, y, size, size)); @@ -414,6 +421,7 @@ void ovrApp_Destroy(ovrApp* app) { ovrApp_Clear(app); } + void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) { if (state == XR_SESSION_STATE_READY) { assert(app->SessionActive == false); @@ -428,7 +436,8 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) { OXR(result = xrBeginSession(app->Session, &sessionBeginInfo)); app->SessionActive = (result == XR_SUCCESS); - if (app->SessionActive && VR_GetPlatformFLag(VR_PLATFORM_PERFORMANCE_EXT)) { +#ifdef ANDROID + if (app->SessionActive && VR_GetPlatformFlag(VR_PLATFORM_PERFORMANCE_EXT)) { XrPerfSettingsLevelEXT cpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT; XrPerfSettingsLevelEXT gpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT; @@ -450,6 +459,7 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) { OXR(pfnSetAndroidApplicationThreadKHR(app->Session, XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, app->MainThreadTid)); OXR(pfnSetAndroidApplicationThreadKHR(app->Session, XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, app->RenderThreadTid)); } +#endif } else if (state == XR_SESSION_STATE_STOPPING) { assert(app->SessionActive); @@ -538,5 +548,3 @@ int ovrApp_HandleXrEvents(ovrApp* app) { } return recenter; } - -#endif diff --git a/Common/VR/VRInput.cpp b/Common/VR/VRInput.cpp index 27cf0eb2fdd2..dec132ab34f3 100644 --- a/Common/VR/VRInput.cpp +++ b/Common/VR/VRInput.cpp @@ -1,8 +1,6 @@ #include "VRInput.h" #include -#ifdef OPENXR - //OpenXR XrPath leftHandPath; XrPath rightHandPath; @@ -268,9 +266,9 @@ void IN_VRInit( engine_t *engine ) { handPoseRightAction = CreateAction(runningActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_right", NULL, 1, &rightHandPath); XrPath interactionProfilePath = XR_NULL_PATH; - if (VR_GetPlatformFLag(VR_PLATFORM_CONTROLLER_QUEST)) { + if (VR_GetPlatformFlag(VR_PLATFORM_CONTROLLER_QUEST)) { OXR(xrStringToPath(engine->appState.Instance, "/interaction_profiles/oculus/touch_controller", &interactionProfilePath)); - } else if (VR_GetPlatformFLag(VR_PLATFORM_CONTROLLER_PICO)) { + } else if (VR_GetPlatformFlag(VR_PLATFORM_CONTROLLER_PICO)) { OXR(xrStringToPath(engine->appState.Instance, "/interaction_profiles/pico/neo3_controller", &interactionProfilePath)); } @@ -279,11 +277,11 @@ void IN_VRInit( engine_t *engine ) { int currBinding = 0; - if (VR_GetPlatformFLag(VR_PLATFORM_CONTROLLER_QUEST)) { + if (VR_GetPlatformFlag(VR_PLATFORM_CONTROLLER_QUEST)) { bindings[currBinding++] = ActionSuggestedBinding(indexLeftAction, "/user/hand/left/input/trigger"); bindings[currBinding++] = ActionSuggestedBinding(indexRightAction, "/user/hand/right/input/trigger"); bindings[currBinding++] = ActionSuggestedBinding(menuAction, "/user/hand/left/input/menu/click"); - } else if (VR_GetPlatformFLag(VR_PLATFORM_CONTROLLER_PICO)) { + } else if (VR_GetPlatformFlag(VR_PLATFORM_CONTROLLER_PICO)) { bindings[currBinding++] = ActionSuggestedBinding(indexLeftAction, "/user/hand/left/input/trigger/click"); bindings[currBinding++] = ActionSuggestedBinding(indexRightAction, "/user/hand/right/input/trigger/click"); bindings[currBinding++] = ActionSuggestedBinding(menuAction, "/user/hand/left/input/back/click"); @@ -464,5 +462,3 @@ XrPosef IN_VRGetPose( int controllerIndex ) { xrLocateSpace(aimSpace[controllerIndex], engine->appState.CurrentSpace, (XrTime)(engine->predictedDisplayTime), &loc); return loc.pose; } - -#endif diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index f04a3c15c807..e67d4ecd6205 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -4,6 +4,7 @@ #include "VRBase.h" #include "VRInput.h" #include "VRRenderer.h" +#include "OpenXRLoader.h" #include #include @@ -22,8 +23,6 @@ float vrConfigFloat[VR_CONFIG_FLOAT_MAX] = {}; XrVector3f hmdorientation; XrVector3f hmdposition; -#ifdef OPENXR - void VR_UpdateStageBounds(ovrApp* pappState) { XrExtent2Df stageBounds = {}; @@ -156,7 +155,7 @@ void VR_Recenter(engine_t* engine) { // Create a default stage space to use if SPACE_TYPE_STAGE is not // supported, or calls to xrGetReferenceSpaceBoundsRect fail. spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL; - if (VR_GetPlatformFLag(VR_PLATFORM_TRACKING_FLOOR)) { + if (VR_GetPlatformFlag(VR_PLATFORM_TRACKING_FLOOR)) { spaceCreateInfo.poseInReferenceSpace.position.y = -1.6750f; } OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.FakeStageSpace)); @@ -168,7 +167,7 @@ void VR_Recenter(engine_t* engine) { spaceCreateInfo.poseInReferenceSpace.position.y = 0.0; OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.StageSpace)); ALOGV("Created stage space"); - if (VR_GetPlatformFLag(VR_PLATFORM_TRACKING_FLOOR)) { + if (VR_GetPlatformFlag(VR_PLATFORM_TRACKING_FLOOR)) { engine->appState.CurrentSpace = engine->appState.StageSpace; } } @@ -213,7 +212,7 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView))); void* vulkanContext = nullptr; - if (VR_GetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN)) { + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { vulkanContext = &engine->graphicsBindingVulkan; } ovrRenderer_Create(engine->appState.Session, &engine->appState.Renderer, @@ -554,5 +553,3 @@ void* VR_BindFramebuffer(engine_t *engine) { ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) { return vrMatrix[matrix]; } - -#endif diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index f59a0da45b97..4ce6b322e5e6 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -17,6 +17,7 @@ #include +#include "Common/Log.h" #include "Common/Data/Format/IniFile.h" #include "Common/StringUtils.h" #include "Core/Compatibility.h" @@ -122,6 +123,8 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "Skyplane", &vrCompat_.Skyplane); CheckSetting(iniFile, gameID, "UnitsPerMeter", &vrCompat_.UnitsPerMeter); + + NOTICE_LOG(G3D, "UnitsPerMeter for %s: %f", gameID.c_str(), vrCompat_.UnitsPerMeter); } void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) { diff --git a/Core/Config.cpp b/Core/Config.cpp index b8d140814422..b1f22523f405 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -697,7 +697,7 @@ const char * const vulkanDefaultBlacklist[] = { }; static int DefaultGPUBackend() { - if (IsVRBuild()) { + if (IsVREnabled()) { return (int)GPUBackend::OPENGL; } diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 0be4dd718263..8c84be11e1ee 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -667,7 +667,7 @@ void RestoreDefault() { g_controllerMap.clear(); g_controllerMapGeneration++; - if (IsVRBuild()) { + if (IsVREnabled()) { SetDefaultKeyMap(DEFAULT_MAPPING_VR_HEADSET, false); return; } diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index b4e05d8d50bb..aec95318ec4e 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -77,7 +77,7 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &f SmallDisplayZoom zoomType = (SmallDisplayZoom)g_Config.iSmallDisplayZoomType; - if (IsVRBuild()) { + if (IsVREnabled()) { if (IsFlatVRScene()) { zoomType = SmallDisplayZoom::AUTO; } else { diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b6b2b6a6611b..f67e90d335ad 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -210,7 +210,7 @@ u32 GPU_GLES::CheckGPUFeatures() const { features |= GPU_USE_FRAGMENT_TEST_CACHE; } - if (IsVRBuild()) { + if (IsVREnabled()) { features |= GPU_USE_VIRTUAL_REALITY; } if (IsMultiviewSupported()) { diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 118c8c3fedd9..04a1a85974c9 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -457,7 +457,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu } if (dirty & DIRTY_FOGCOLOR) { SetColorUniform3(render_, &u_fogcolor, gstate.fogcolor); - if (IsVRBuild()) { + if (IsVREnabled()) { SetVRCompat(VR_COMPAT_FOG_COLOR, gstate.fogcolor); } } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 0f4cac7f3700..d387e7064b5a 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1297,7 +1297,7 @@ bool NativeTouch(const TouchInput &touch) { bool NativeKey(const KeyInput &key) { // Special key VR actions - if (IsVRBuild()) { + if (IsVREnabled()) { UpdateVRSpecialKeys(key); } diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 90a1c1649c01..0415092a9dfe 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -387,6 +387,7 @@ + @@ -502,6 +503,7 @@ + @@ -526,6 +528,7 @@ + @@ -618,6 +621,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index dd2f6d6fda82..15c00bcbfa67 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -88,6 +88,9 @@ {a5bfc343-9c3a-43ff-a033-7b0406e13816} + + {096c3d00-fcfa-4877-8cf0-3b10d56b5d72} + @@ -396,6 +399,12 @@ VR + + VR + + + GPU\Vulkan + @@ -733,6 +742,12 @@ VR + + VR + + + GPU\Vulkan + diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index e4ed18b8f203..b734f6e3d203 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -406,10 +406,6 @@ float System_GetPropertyFloat(SystemProperty prop) { } } -bool VulkanMayBeAvailable() { - return false; -} - void System_Toast(const char *str) {} bool System_GetPropertyBool(SystemProperty prop) { diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 8913f641e50a..2f3887c3e232 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -72,6 +72,7 @@ SPIRV_CROSS_FILES := \ $(SRC)/ext/SPIRV-Cross/spirv_cross_parsed_ir.cpp VR_FILES := \ + $(SRC)/Common/VR/OpenXRLoader.cpp \ $(SRC)/Common/VR/PPSSPPVR.cpp \ $(SRC)/Common/VR/VRBase.cpp \ $(SRC)/Common/VR/VRFramebuffer.cpp \ diff --git a/android/jni/AndroidEGLContext.cpp b/android/jni/AndroidEGLContext.cpp index 9507c217e65b..0cddc2b7f3a0 100644 --- a/android/jni/AndroidEGLContext.cpp +++ b/android/jni/AndroidEGLContext.cpp @@ -47,7 +47,7 @@ bool AndroidEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int des } gl->MakeCurrent(); if (gl->GetMode() == GLInterfaceMode::MODE_OPENGL) - SetGLCoreContext(!IsVRBuild()); + SetGLCoreContext(!IsVREnabled()); CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(); SetGPUBackend(GPUBackend::OPENGL); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 9e685cfaafc2..b74d345dc42e 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -757,7 +757,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init EmuThreadStart(); } - if (IsVRBuild()) { + if (IsVREnabled()) { Version gitVer(PPSSPP_GIT_VERSION); InitVROnAndroid(gJvm, nativeActivity, systemName.c_str(), gitVer.ToInteger(), "PPSSPP"); } @@ -939,7 +939,7 @@ extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, } NativeMessageReceived("recreateviews", ""); - if (IsVRBuild()) { + if (IsVREnabled()) { EnterVR(firstStart, graphicsContext->GetAPIContext()); } @@ -982,7 +982,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv pixel_yres = bufh; backbuffer_format = format; - if (IsVRBuild()) { + if (IsVREnabled()) { GetVRResolutionPerEye(&pixel_xres, &pixel_yres); } @@ -1057,7 +1057,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, SetCurrentThreadName("AndroidRender"); } - if (IsVRBuild() && !StartVRRender()) + if (IsVREnabled() && !StartVRRender()) return; if (useCPUThread) { @@ -1068,7 +1068,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, UpdateRunLoopAndroid(env); } - if (IsVRBuild()) { + if (IsVREnabled()) { UpdateVRInput(NativeKey, NativeTouch, g_Config.bHapticFeedback, dp_xscale, dp_yscale); FinishVRRender(); } @@ -1291,7 +1291,7 @@ void getDesiredBackbufferSize(int &sz_x, int &sz_y) { extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_setDisplayParameters(JNIEnv *, jclass, jint xres, jint yres, jint dpi, jfloat refreshRate) { INFO_LOG(G3D, "NativeApp.setDisplayParameters(%d x %d, dpi=%d, refresh=%0.2f)", xres, yres, dpi, refreshRate); - if (IsVRBuild()) { + if (IsVREnabled()) { int width, height; GetVRResolutionPerEye(&width, &height); xres = width; diff --git a/assets/compatvr.ini b/assets/compatvr.ini index 430fb80e472c..bc4e1a6dd100 100644 --- a/assets/compatvr.ini +++ b/assets/compatvr.ini @@ -313,15 +313,6 @@ ULUS10319 = 10.0 # Bowling 3D NPUZ00002 = 1.0 -# Burnout Legends -NPJH50305 = 1.0 -ULAS42019 = 1.0 -ULES00125 = 1.0 -ULJM05049 = 1.0 -ULJM05228 = 1.0 -ULKS46027 = 1.0 -ULUS10025 = 1.0 - # Brain Challenge NPEH00003 = 30.0 NPJH00002 = 30.0 @@ -335,6 +326,15 @@ NPUZ00031 = 1.0 NPEZ00023 = 1.0 NPUZ00007 = 1.0 +# Burnout Legends +ULES00125 = 2.0 +ULUS10025 = 2.0 +ULJM05228 = 2.0 +NPJH50305 = 2.0 +ULJM05049 = 2.0 +ULKS46027 = 2.0 +ULAS42019 = 2.0 + # Bust-A-Move Deluxe NPJH50087 = 1.0 ULES00233 = 1.0 diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 7d858e0129a0..27540dc86f19 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -314,6 +314,7 @@ SOURCES_CXX += \ $(COMMONDIR)/TimeUtil.cpp SOURCES_CXX += \ + $(COMMONDIR)/VR/OpenXRLoader.cpp \ $(COMMONDIR)/VR/PPSSPPVR.cpp \ $(COMMONDIR)/VR/VRBase.cpp \ $(COMMONDIR)/VR/VRMath.cpp \