diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index b0c2ab370b..2ead5cb95d 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -23,7 +23,6 @@ #include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/Log.h" #include "Common/System/System.h" -#include "Common/VR/PPSSPPVR.h" #if !PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(SWITCH) #include @@ -309,11 +308,6 @@ void VulkanSetAvailable(bool available) { bool VulkanMayBeAvailable() { - //unsupported in VR at the moment - if (IsVRBuild()) { - return false; - } - if (g_vulkanAvailabilityChecked) { return g_vulkanMayBeAvailable; } diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 71b4919bf1..23712db954 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -97,12 +97,14 @@ bool IsVRBuild() { } void InitVROnAndroid(void* vm, void* activity, int version, const char* name) { + bool useVulkan = (GPUBackend)g_Config.iGPUBackend == GPUBackend::VULKAN; + ovrJava java; java.Vm = (JavaVM*)vm; java.ActivityObject = (jobject)activity; java.AppVersion = version; strcpy(java.AppName, name); - VR_Init(java); + VR_Init(java, useVulkan); __DisplaySetFramerate(72); } diff --git a/Common/VR/VRBase.cpp b/Common/VR/VRBase.cpp index 9932d09553..bedc6b1e0c 100644 --- a/Common/VR/VRBase.cpp +++ b/Common/VR/VRBase.cpp @@ -4,21 +4,12 @@ #include #include #include +#include static engine_t vr_engine; int vr_initialized = 0; -const char* const requiredExtensionNames[] = { - XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME, -#ifdef OPENXR_HAS_PERFORMANCE_EXTENSION - XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME, - XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME, -#endif - XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME}; -const uint32_t numRequiredExtensions = - sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]); - -void VR_Init( ovrJava java ) { +void VR_Init( ovrJava java, bool useVulkan ) { if (vr_initialized) return; @@ -37,6 +28,18 @@ void VR_Init( ovrJava java ) { xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loaderInitializeInfoAndroid); } + std::vector extensions; + if (useVulkan) { + extensions.push_back(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME); + } else { + extensions.push_back(XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME); + } + extensions.push_back(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME); +#ifdef OPENXR_HAS_PERFORMANCE_EXTENSION + extensions.push_back(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME); + extensions.push_back(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME); +#endif + // Create the OpenXR instance. XrApplicationInfo appInfo; memset(&appInfo, 0, sizeof(appInfo)); @@ -54,8 +57,8 @@ void VR_Init( ovrJava java ) { instanceCreateInfo.applicationInfo = appInfo; instanceCreateInfo.enabledApiLayerCount = 0; instanceCreateInfo.enabledApiLayerNames = NULL; - instanceCreateInfo.enabledExtensionCount = numRequiredExtensions; - instanceCreateInfo.enabledExtensionNames = requiredExtensionNames; + instanceCreateInfo.enabledExtensionCount = extensions.size(); + instanceCreateInfo.enabledExtensionNames = extensions.data(); XrResult initResult; OXR(initResult = xrCreateInstance(&instanceCreateInfo, &vr_engine.appState.Instance)); @@ -89,15 +92,27 @@ void VR_Init( ovrJava java ) { } // Get the graphics requirements. - PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL; - OXR(xrGetInstanceProcAddr( - vr_engine.appState.Instance, - "xrGetOpenGLESGraphicsRequirementsKHR", - (PFN_xrVoidFunction*)(&pfnGetOpenGLESGraphicsRequirementsKHR))); + if (useVulkan) { + PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR = NULL; + OXR(xrGetInstanceProcAddr( + vr_engine.appState.Instance, + "xrGetVulkanGraphicsRequirementsKHR", + (PFN_xrVoidFunction*)(&pfnGetVulkanGraphicsRequirementsKHR))); - XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = {}; - graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR; - OXR(pfnGetOpenGLESGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); + XrGraphicsRequirementsVulkanKHR graphicsRequirements = {}; + graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR; + OXR(pfnGetVulkanGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); + } else { + PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL; + OXR(xrGetInstanceProcAddr( + vr_engine.appState.Instance, + "xrGetOpenGLESGraphicsRequirementsKHR", + (PFN_xrVoidFunction*)(&pfnGetOpenGLESGraphicsRequirementsKHR))); + + XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = {}; + graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR; + OXR(pfnGetOpenGLESGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); + } vr_engine.appState.MainThreadTid = gettid(); vr_engine.appState.SystemId = systemId; diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index fffd234868..4d5138e40f 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -12,10 +12,12 @@ //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 #include +#include #include #include #include @@ -146,7 +148,7 @@ typedef struct { float predictedDisplayTime; } engine_t; -void VR_Init( ovrJava java ); +void VR_Init( ovrJava java, bool useVulkan ); void VR_Destroy( engine_t* engine ); void VR_EnterVR( engine_t* engine ); void VR_LeaveVR( engine_t* engine ); diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 70f2ad02aa..007a21cee8 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -9,8 +9,6 @@ #include #include #include -#include -#include double FromXrTime(const XrTime time) { return (time * 1e-9); @@ -178,6 +176,15 @@ void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) { waitInfo.timeout * (1E-9)); } frameBuffer->Acquired = res == XR_SUCCESS; + + ovrFramebuffer_SetCurrent(frameBuffer); + GL(glEnable( GL_SCISSOR_TEST )); + GL(glViewport( 0, 0, frameBuffer->Width, frameBuffer->Height )); + GL(glClearColor( 0.0f, 0.0f, 0.0f, 1.0f )); + GL(glScissor( 0, 0, frameBuffer->Width, frameBuffer->Height )); + GL(glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )); + GL(glScissor( 0, 0, 0, 0 )); + GL(glDisable( GL_SCISSOR_TEST )); } void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { @@ -185,6 +192,12 @@ void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; OXR(xrReleaseSwapchainImage(frameBuffer->ColorSwapChain.Handle, &releaseInfo)); frameBuffer->Acquired = false; + + // Clear the alpha channel, other way OpenXR would not transfer the framebuffer fully + 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)); + GL(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); } } @@ -217,6 +230,15 @@ void ovrRenderer_Destroy(ovrRenderer* renderer) { } } +void ovrRenderer_MouseCursor(ovrRenderer* renderer, int x, int y, int size) { + GL(glEnable(GL_SCISSOR_TEST)); + GL(glScissor(x, y, size, size)); + GL(glViewport(x, y, size, size)); + GL(glClearColor(1.0f, 1.0f, 1.0f, 1.0f)); + GL(glClear(GL_COLOR_BUFFER_BIT)); + GL(glDisable(GL_SCISSOR_TEST)); +} + /* ================================================================================ diff --git a/Common/VR/VRFramebuffer.h b/Common/VR/VRFramebuffer.h index dcedad580f..20b9004190 100644 --- a/Common/VR/VRFramebuffer.h +++ b/Common/VR/VRFramebuffer.h @@ -14,3 +14,4 @@ void ovrFramebuffer_SetNone(); void ovrRenderer_Create(XrSession session, ovrRenderer* renderer, int width, int height, bool multiview); void ovrRenderer_Destroy(ovrRenderer* renderer); +void ovrRenderer_MouseCursor(ovrRenderer* renderer, int x, int y, int size); diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 79e6114a61..1d421c2fa3 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -6,14 +6,11 @@ #include #include -#include -#include - XrView* projections; XrPosef invViewTransform[2]; XrFrameState frameState = {}; -GLboolean initialized = GL_FALSE; -GLboolean stageSupported = GL_FALSE; +bool initialized = false; +bool stageSupported = false; int vrConfig[VR_CONFIG_MAX] = {}; XrVector3f hmdorientation; @@ -194,7 +191,7 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { for (uint32_t i = 0; i < numOutputSpaces; i++) { if (referenceSpaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) { - stageSupported = GL_TRUE; + stageSupported = true; break; } } @@ -213,40 +210,27 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { engine->appState.ViewConfigurationView[0].recommendedImageRectWidth, engine->appState.ViewConfigurationView[0].recommendedImageRectHeight, multiview); - initialized = GL_TRUE; + initialized = true; } void VR_DestroyRenderer( engine_t* engine ) { ovrRenderer_Destroy(&engine->appState.Renderer); free(projections); - initialized = GL_FALSE; -} - -void VR_ClearFrameBuffer( int width, int height) { - glEnable( GL_SCISSOR_TEST ); - glViewport( 0, 0, width, height ); - - glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - - glScissor( 0, 0, width, height ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - glScissor( 0, 0, 0, 0 ); - glDisable( GL_SCISSOR_TEST ); + initialized = false; } bool VR_InitFrame( engine_t* engine ) { - GLboolean stageBoundsDirty = GL_TRUE; + bool stageBoundsDirty = true; if (ovrApp_HandleXrEvents(&engine->appState)) { VR_Recenter(engine); } - if (engine->appState.SessionActive == GL_FALSE) { + if (engine->appState.SessionActive == false) { return false; } if (stageBoundsDirty) { VR_UpdateStageBounds(&engine->appState); - stageBoundsDirty = GL_FALSE; + stageBoundsDirty = false; } // NOTE: OpenXR does not use the concept of frame indices. Instead, @@ -309,32 +293,19 @@ bool VR_InitFrame( engine_t* engine ) { void VR_BeginFrame( engine_t* engine, int fboIndex ) { vrConfig[VR_CONFIG_CURRENT_FBO] = fboIndex; - ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[fboIndex]; - ovrFramebuffer_Acquire(frameBuffer); - ovrFramebuffer_SetCurrent(frameBuffer); - VR_ClearFrameBuffer(frameBuffer->ColorSwapChain.Width, frameBuffer->ColorSwapChain.Height); + ovrFramebuffer_Acquire(&engine->appState.Renderer.FrameBuffer[fboIndex]); } void VR_EndFrame( engine_t* engine ) { - int fboIndex = vrConfig[VR_CONFIG_CURRENT_FBO]; - - // Clear the alpha channel, other way OpenXR would not transfer the framebuffer fully VR_BindFramebuffer(engine); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Show mouse cursor int size = vrConfig[VR_CONFIG_MOUSE_SIZE]; if ((vrConfig[VR_CONFIG_MODE] == VR_MODE_FLAT_SCREEN) && (size > 0)) { - glEnable(GL_SCISSOR_TEST); - glScissor(vrConfig[VR_CONFIG_MOUSE_X], vrConfig[VR_CONFIG_MOUSE_Y], size, size); - glViewport(vrConfig[VR_CONFIG_MOUSE_X], vrConfig[VR_CONFIG_MOUSE_Y], size, size); - glClearColor(1, 1, 1, 1); - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_SCISSOR_TEST); + int x = vrConfig[VR_CONFIG_MOUSE_X]; + int y = vrConfig[VR_CONFIG_MOUSE_Y]; + ovrRenderer_MouseCursor(&engine->appState.Renderer, x, y, size); } ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[fboIndex]; @@ -454,10 +425,7 @@ void VR_SetConfig( VRConfig config, int value) { void VR_BindFramebuffer(engine_t *engine) { if (!initialized) return; int fboIndex = vrConfig[VR_CONFIG_CURRENT_FBO]; - ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[fboIndex]; - unsigned int swapchainIndex = frameBuffer->TextureSwapChainIndex; - unsigned int glFramebuffer = frameBuffer->FrameBuffers[swapchainIndex]; - GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, glFramebuffer)); + ovrFramebuffer_SetCurrent(&engine->appState.Renderer.FrameBuffer[fboIndex]); } ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) {