OpenXR integration fixes

This commit is contained in:
Lubos 2022-04-26 22:02:04 +02:00
parent c321b97894
commit 65e2031e95
6 changed files with 128 additions and 51 deletions

View file

@ -18,7 +18,9 @@ const char* const requiredExtensionNames[] = {
XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME,
XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME,
XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME,
XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME};
XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME,
XR_FB_FOVEATION_EXTENSION_NAME,
XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME};
const uint32_t numRequiredExtensions =
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);

View file

@ -1103,8 +1103,8 @@ static void IN_VRJoystick( qboolean isRightController, float joystickX, float jo
else
{
//Positional movement speed correction for when we are not hitting target framerate
//TODO:int refresh = vrapi_GetSystemPropertyInt(&(VR_GetEngine()->java), VRAPI_SYS_PROP_DISPLAY_REFRESH_RATE);
int refresh = 72;
float refresh;
VR_GetEngine()->appState.pfnGetDisplayRefreshRate(VR_GetEngine()->appState.Session, &refresh);
float multiplier = (float)((1000.0 / refresh) / (in_vrEventTime - lastframetime));
float factor = (refresh / 72.0F) * 10.0f; // adjust positional factor based on refresh rate

View file

@ -270,6 +270,14 @@ void VR_InitRenderer( engine_t* engine ) {
&engine->appState.Renderer,
engine->appState.ViewConfigurationView[0].recommendedImageRectWidth,
engine->appState.ViewConfigurationView[0].recommendedImageRectHeight);
ovrRenderer_SetFoveation(
&engine->appState.Instance,
&engine->appState.Session,
&engine->appState.Renderer,
XR_FOVEATION_LEVEL_HIGH_FB,
0,
XR_FOVEATION_DYNAMIC_DISABLED_FB);
}
void VR_DestroyRenderer( engine_t* engine )
@ -284,6 +292,29 @@ void VR_ReInitRenderer()
VR_InitRenderer( VR_GetEngine() );
}
void VR_ClearFrameBuffer( int width, int height)
{
glEnable( GL_SCISSOR_TEST );
glViewport( 0, 0, width, height );
if (Cvar_VariableIntegerValue("vr_thirdPersonSpectator"))
{
//Blood red.. ish
glClearColor( 0.12f, 0.0f, 0.05f, 1.0f );
}
else
{
//Black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
}
glScissor( 0, 0, width, height );
glClear( GL_COLOR_BUFFER_BIT );
glScissor( 0, 0, 0, 0 );
glDisable( GL_SCISSOR_TEST );
}
void VR_DrawFrame( engine_t* engine ) {
if (vr.weapon_zoomed) {
vr.weapon_zoomLevel += 0.05;
@ -375,39 +406,39 @@ void VR_DrawFrame( engine_t* engine ) {
vr.fov_y = (fabs(fov.angleUp) + fabs(fov.angleDown)) * 180.0f / M_PI;
}
// Set-up the compositor layers for this frame.
// NOTE: Multiple independent layers are allowed, but they need to be added
// in a depth consistent order.
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
engine->appState.LayerCount = 0;
memset(engine->appState.Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount);
if (Cvar_VariableIntegerValue("vr_thirdPersonSpectator"))
{
//Blood red.. ish
glClearColor( 0.12f, 0.0f, 0.05f, 1.0f );
}
else
{
//Black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
}
glClear( GL_COLOR_BUFFER_BIT );
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
int swapchainIndex = engine->appState.Renderer.FrameBuffer.TextureSwapChainIndex;
int glFramebuffer = engine->appState.Renderer.FrameBuffer.FrameBuffers[swapchainIndex];
re.SetVRHeadsetParms(projectionMatrix.M, monoVRMatrix.M, glFramebuffer);
ovrFramebuffer_Acquire(frameBuffer);
ovrFramebuffer_SetCurrent(frameBuffer);
re.SetVRHeadsetParms(projectionMatrix.M, monoVRMatrix.M,
engine->appState.Renderer.FrameBuffer.FrameBuffers[engine->appState.Renderer.FrameBuffer.TextureSwapChainIndex]);
VR_ClearFrameBuffer(frameBuffer->ColorSwapChain.Width, frameBuffer->ColorSwapChain.Height);
Com_Frame();
ovrFramebuffer_Resolve(frameBuffer);
ovrFramebuffer_Release(frameBuffer);
ovrFramebuffer_SetNone();
if (!VR_useScreenLayer() && !(cl.snap.ps.pm_flags & PMF_FOLLOW && vr.follow_mode == VRFM_FIRSTPERSON)) {
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]);
projection_layer_elements[eye].fov = projections[eye].fov;
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
projection_layer_elements[eye].subImage.swapchain = frameBuffer->ColorSwapChain.Handle;
projection_layer_elements[eye].subImage.imageRect.offset.x = 0;
projection_layer_elements[eye].subImage.imageRect.offset.y = 0;
projection_layer_elements[eye].subImage.imageRect.extent.width = frameBuffer->ColorSwapChain.Width;
projection_layer_elements[eye].subImage.imageRect.extent.height = frameBuffer->ColorSwapChain.Height;
projection_layer_elements[eye].subImage.imageArrayIndex = eye;
}
XrCompositionLayerProjection projection_layer = {};
projection_layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
projection_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
@ -416,28 +447,6 @@ void VR_DrawFrame( engine_t* engine ) {
projection_layer.viewCount = ovrMaxNumEyes;
projection_layer.views = projection_layer_elements;
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
memset(
&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]);
projection_layer_elements[eye].fov = projections[eye].fov;
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
projection_layer_elements[eye].subImage.swapchain =
frameBuffer->ColorSwapChain.Handle;
projection_layer_elements[eye].subImage.imageRect.offset.x = 0;
projection_layer_elements[eye].subImage.imageRect.offset.y = 0;
projection_layer_elements[eye].subImage.imageRect.extent.width =
frameBuffer->ColorSwapChain.Width;
projection_layer_elements[eye].subImage.imageRect.extent.height =
frameBuffer->ColorSwapChain.Height;
projection_layer_elements[eye].subImage.imageArrayIndex = 0;
}
engine->appState.Layers[engine->appState.LayerCount++].Projection = projection_layer;
} else {
@ -481,4 +490,7 @@ void VR_DrawFrame( engine_t* engine ) {
endFrameInfo.layers = layers;
OXR(xrEndFrame(engine->appState.Session, &endFrameInfo));
ovrFramebuffer_Resolve(frameBuffer);
ovrFramebuffer_Release(frameBuffer);
ovrFramebuffer_SetNone();
}

View file

@ -73,6 +73,12 @@ bool ovrFramebuffer_Create(
swapChainCreateInfo.arraySize = 2;
swapChainCreateInfo.mipCount = 1;
// Enable Foveation on this swapchain
XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo;
memset(&swapChainFoveationCreateInfo, 0, sizeof(swapChainFoveationCreateInfo));
swapChainFoveationCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB;
swapChainCreateInfo.next = &swapChainFoveationCreateInfo;
frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width;
frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height;
@ -220,6 +226,57 @@ void ovrRenderer_Destroy(ovrRenderer* renderer) {
ovrFramebuffer_Destroy(&renderer->FrameBuffer);
}
void ovrRenderer_SetFoveation(
XrInstance* instance,
XrSession* session,
ovrRenderer* renderer,
XrFoveationLevelFB level,
float verticalOffset,
XrFoveationDynamicFB dynamic) {
PFN_xrCreateFoveationProfileFB pfnCreateFoveationProfileFB;
OXR(xrGetInstanceProcAddr(
*instance,
"xrCreateFoveationProfileFB",
(PFN_xrVoidFunction*)(&pfnCreateFoveationProfileFB)));
PFN_xrDestroyFoveationProfileFB pfnDestroyFoveationProfileFB;
OXR(xrGetInstanceProcAddr(
*instance,
"xrDestroyFoveationProfileFB",
(PFN_xrVoidFunction*)(&pfnDestroyFoveationProfileFB)));
PFN_xrUpdateSwapchainFB pfnUpdateSwapchainFB;
OXR(xrGetInstanceProcAddr(
*instance, "xrUpdateSwapchainFB", (PFN_xrVoidFunction*)(&pfnUpdateSwapchainFB)));
XrFoveationLevelProfileCreateInfoFB levelProfileCreateInfo;
memset(&levelProfileCreateInfo, 0, sizeof(levelProfileCreateInfo));
levelProfileCreateInfo.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
levelProfileCreateInfo.level = level;
levelProfileCreateInfo.verticalOffset = verticalOffset;
levelProfileCreateInfo.dynamic = dynamic;
XrFoveationProfileCreateInfoFB profileCreateInfo;
memset(&profileCreateInfo, 0, sizeof(profileCreateInfo));
profileCreateInfo.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
profileCreateInfo.next = &levelProfileCreateInfo;
XrFoveationProfileFB foveationProfile;
pfnCreateFoveationProfileFB(*session, &profileCreateInfo, &foveationProfile);
XrSwapchainStateFoveationFB foveationUpdateState;
memset(&foveationUpdateState, 0, sizeof(foveationUpdateState));
foveationUpdateState.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB;
foveationUpdateState.profile = foveationProfile;
pfnUpdateSwapchainFB(
renderer->FrameBuffer.ColorSwapChain.Handle,
(XrSwapchainStateBaseHeaderFB*)(&foveationUpdateState));
pfnDestroyFoveationProfileFB(foveationProfile);
}
/*
================================================================================

View file

@ -10,7 +10,6 @@
#endif
//OpenXR
#define XR_EYES_COUNT 2
#define XR_USE_GRAPHICS_API_OPENGL_ES 1
#define XR_USE_PLATFORM_ANDROID 1
#include <EGL/egl.h>
@ -33,7 +32,7 @@ typedef union {
XrCompositionLayerCylinderKHR Cylinder;
} ovrCompositorLayer_Union;
enum { ovrMaxLayerCount = 16 };
enum { ovrMaxLayerCount = 1 };
enum { ovrMaxNumEyes = 2 };
#define GL(func) func;
@ -174,6 +173,13 @@ void ovrRenderer_Create(
int suggestedEyeTextureWidth,
int suggestedEyeTextureHeight);
void ovrRenderer_Destroy(ovrRenderer* renderer);
void ovrRenderer_SetFoveation(
XrInstance* instance,
XrSession* session,
ovrRenderer* renderer,
XrFoveationLevelFB level,
float verticalOffset,
XrFoveationDynamicFB dynamic);
void ovrTrackedController_Clear(ovrTrackedController* controller);

View file

@ -81,7 +81,7 @@ int main(int argc, char* argv[]) {
VR_InitRenderer(engine);
qboolean hasFocus = qtrue;
qboolean paused = qfalse;
qboolean paused = qfalse;
while (1) {
if (hasFocus != g_HasFocus) {
hasFocus = g_HasFocus;