OpenXR - Initial work on Vulkan support

This commit is contained in:
Lubos 2022-09-13 01:39:44 +02:00
parent c6ff56d4a3
commit fea2ace548
7 changed files with 80 additions and 76 deletions

View File

@ -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 <dlfcn.h>
@ -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;
}

View File

@ -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);
}

View File

@ -4,21 +4,12 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <vector>
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<char*> 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;

View File

@ -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 <EGL/egl.h>
#include <EGL/eglext.h>
#include <jni.h>
#include <math.h>
#include <vulkan/vulkan.h>
#include <openxr.h>
#include <openxr_platform.h>
#include <GLES3/gl3.h>
@ -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 );

View File

@ -9,8 +9,6 @@
#include <pthread.h>
#include <sys/prctl.h>
#include <assert.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
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));
}
/*
================================================================================

View File

@ -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);

View File

@ -6,14 +6,11 @@
#include <stdlib.h>
#include <string.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
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 ) {