OpenXR - Stereo without multiview added

This commit is contained in:
Lubos 2022-09-04 12:36:52 +02:00
parent 5e2ecb5ebb
commit 1df1d79b9e
10 changed files with 103 additions and 45 deletions

View File

@ -5,6 +5,8 @@
#include "Common/Thread/ThreadUtil.h"
#include "Common/VR/PPSSPPVR.h"
#include "Core/Config.h"
#include "Common/Log.h"
#include "Common/MemoryUtil.h"
#include "Common/Math/math_util.h"
@ -233,15 +235,7 @@ bool GLRenderManager::ThreadFrame() {
INFO_LOG(G3D, "Running first frame (%d)", threadFrame_);
firstFrame = false;
}
if (IsVRBuild()) {
if (PreVRRender()) {
Run(threadFrame_);
PostVRRender();
}
} else {
Run(threadFrame_);
}
VLOG("PULL: Finished frame %d", threadFrame_);
} while (!nextFrame);
@ -564,8 +558,7 @@ void GLRenderManager::EndSubmitFrame(int frame) {
}
// Render thread
void GLRenderManager::Run(int frame) {
BeginSubmitFrame(frame);
void GLRenderManager::Render(int frame) {
FrameData &frameData = frameData_[frame];
@ -584,6 +577,7 @@ void GLRenderManager::Run(int frame) {
}
queueRunner_.RunSteps(stepsOnThread, skipGLCalls_);
stepsOnThread.clear();
if (!skipGLCalls_) {
@ -591,8 +585,30 @@ void GLRenderManager::Run(int frame) {
iter->MapDevice(bufferStrategy_);
}
}
}
switch (frameData.type) {
// Render thread
void GLRenderManager::Run(int frame) {
BeginSubmitFrame(frame);
if (IsVRBuild()) {
if (PreVRRender()) {
int passes = 1;
if (!IsMultiviewSupported() && g_Config.bEnableStereo) {
passes = 2;
}
for (int i = 0; i < passes; i++) {
PreVRFrameRender(i);
Render(frame);
PostVRFrameRender();
}
PostVRRender();
}
} else {
Render(frame);
}
switch (frameData_[frame].type) {
case GLRRunType::END:
EndSubmitFrame(frame);
break;

View File

@ -377,6 +377,7 @@ public:
void BeginFrame();
// Can run on a different thread!
void Finish();
void Render(int frame);
void Run(int frame);
// Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown.

View File

@ -225,7 +225,7 @@ bool PreVRRender() {
VR_SetConfig(VR_CONFIG_VIEWPORT_VALID, true);
}
if (VR_BeginFrame(VR_GetEngine())) {
if (VR_InitFrame(VR_GetEngine())) {
// Decide if the scene is 3D or not
if (g_Config.bEnableVR && !VR_GetConfig(VR_CONFIG_FORCE_2D) && (VR_GetConfig(VR_CONFIG_3D_GEOMETRY_COUNT) > 15)) {
@ -245,9 +245,21 @@ bool PreVRRender() {
}
void PostVRRender() {
VR_FinishFrame(VR_GetEngine());
}
void PreVRFrameRender(int fboIndex) {
VR_BeginFrame(VR_GetEngine(), fboIndex);
}
void PostVRFrameRender() {
VR_EndFrame(VR_GetEngine());
}
int GetVRFBOIndex() {
return VR_GetConfig(VR_CONFIG_CURRENT_FBO);
}
bool IsMultiviewSupported() {
return false;
}

View File

@ -17,6 +17,9 @@ void UpdateVRScreenKey(const KeyInput &key);
void BindVRFramebuffer();
bool PreVRRender();
void PostVRRender();
void PreVRFrameRender(int fboIndex);
void PostVRFrameRender();
int GetVRFBOIndex();
bool IsMultiviewSupported();
bool IsFlatVRScene();
bool Is2DVRObject(float* projMatrix, bool ortho);
@ -37,6 +40,9 @@ inline void UpdateVRScreenKey(const KeyInput &key) {}
inline void BindVRFramebuffer() {}
inline bool PreVRRender() { return false; }
inline void PostVRRender() {}
inline void PreVRFrameRender(int fboIndex) {}
inline void PostVRFrameRender() {}
inline int GetVRFBOIndex() { return 0; }
inline bool IsMultiviewSupported() { return false; }
inline bool IsFlatVRScene() { return true; }
inline bool Is2DVRObject(float* projMatrix, bool ortho) { return false; }

View File

@ -92,7 +92,6 @@ typedef struct {
typedef struct {
int Width;
int Height;
bool Multiview;
uint32_t TextureSwapChainLength;
uint32_t TextureSwapChainIndex;
ovrSwapChain ColorSwapChain;
@ -104,7 +103,8 @@ typedef struct {
} ovrFramebuffer;
typedef struct {
ovrFramebuffer FrameBuffer;
bool Multiview;
ovrFramebuffer FrameBuffer[ovrMaxNumEyes];
} ovrRenderer;
typedef struct {

View File

@ -47,12 +47,10 @@ bool ovrFramebuffer_Create(XrSession session, ovrFramebuffer* frameBuffer, int w
frameBuffer->Width = width;
frameBuffer->Height = height;
frameBuffer->Multiview = multiview;
if (strstr((const char*)glGetString(GL_EXTENSIONS), "GL_OVR_multiview2") == nullptr)
{
ALOGE("OpenGL implementation does not support GL_OVR_multiview2 extension.\n");
exit(EXIT_FAILURE);
}
typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei);
@ -60,7 +58,6 @@ bool ovrFramebuffer_Create(XrSession session, ovrFramebuffer* frameBuffer, int w
if (!glFramebufferTextureMultiviewOVR)
{
ALOGE("Can not get proc address for glFramebufferTextureMultiviewOVR.\n");
exit(EXIT_FAILURE);
}
XrSwapchainCreateInfo swapChainCreateInfo;
@ -200,15 +197,24 @@ ovrRenderer
*/
void ovrRenderer_Clear(ovrRenderer* renderer) {
ovrFramebuffer_Clear(&renderer->FrameBuffer);
for (int i = 0; i < ovrMaxNumEyes; i++) {
ovrFramebuffer_Clear(&renderer->FrameBuffer[i]);
}
}
void ovrRenderer_Create(XrSession session, ovrRenderer* renderer, int width, int height, bool multiview) {
ovrFramebuffer_Create(session, &renderer->FrameBuffer, width, height, multiview);
renderer->Multiview = multiview;
int instances = renderer->Multiview ? 1 : ovrMaxNumEyes;
for (int i = 0; i < instances; i++) {
ovrFramebuffer_Create(session, &renderer->FrameBuffer[i], width, height, multiview);
}
}
void ovrRenderer_Destroy(ovrRenderer* renderer) {
ovrFramebuffer_Destroy(&renderer->FrameBuffer);
int instances = renderer->Multiview ? 1 : ovrMaxNumEyes;
for (int i = 0; i < instances; i++) {
ovrFramebuffer_Destroy(&renderer->FrameBuffer[i]);
}
}
/*

View File

@ -235,7 +235,7 @@ void VR_ClearFrameBuffer( int width, int height) {
glDisable( GL_SCISSOR_TEST );
}
bool VR_BeginFrame( engine_t* engine ) {
bool VR_InitFrame( engine_t* engine ) {
GLboolean stageBoundsDirty = GL_TRUE;
if (ovrApp_HandleXrEvents(&engine->appState)) {
VR_Recenter(engine);
@ -304,16 +304,21 @@ bool VR_BeginFrame( engine_t* engine ) {
engine->appState.LayerCount = 0;
memset(engine->appState.Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount);
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
ovrFramebuffer_Acquire(frameBuffer);
ovrFramebuffer_SetCurrent(frameBuffer);
VR_ClearFrameBuffer(frameBuffer->ColorSwapChain.Width, frameBuffer->ColorSwapChain.Height);
return true;
}
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);
}
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);
@ -322,9 +327,8 @@ void VR_EndFrame( engine_t* engine ) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// Show mouse cursor
int vrMode = vrConfig[VR_CONFIG_MODE];
int size = vrConfig[VR_CONFIG_MOUSE_SIZE];
if ((vrMode == VR_MODE_FLAT_SCREEN) && (size > 0)) {
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);
@ -333,21 +337,27 @@ void VR_EndFrame( engine_t* engine ) {
glDisable(GL_SCISSOR_TEST);
}
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[fboIndex];
//ovrFramebuffer_Resolve(frameBuffer);
ovrFramebuffer_Release(frameBuffer);
ovrFramebuffer_SetNone();
}
void VR_FinishFrame( engine_t* engine ) {
int vrMode = vrConfig[VR_CONFIG_MODE];
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
if ((vrMode == VR_MODE_MONO_6DOF) || (vrMode == VR_MODE_STEREO_6DOF)) {
vrConfig[VR_CONFIG_MENU_YAW] = (int)hmdorientation.y;
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
int imageLayer = eye;
int imageLayer = engine->appState.Renderer.Multiview ? eye : 0;
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[0];
XrFovf fov = projections[eye].fov;
if (vrMode == VR_MODE_MONO_6DOF) {
fov = projections[0].fov;
imageLayer = 0;
} else if (!engine->appState.Renderer.Multiview) {
frameBuffer = &engine->appState.Renderer.FrameBuffer[eye];
}
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
@ -376,15 +386,15 @@ void VR_EndFrame( engine_t* engine ) {
} else if (vrMode == VR_MODE_FLAT_SCREEN) {
// Build the cylinder layer
int width = engine->appState.Renderer.FrameBuffer.ColorSwapChain.Width;
int height = engine->appState.Renderer.FrameBuffer.ColorSwapChain.Height;
int width = engine->appState.Renderer.FrameBuffer[0].ColorSwapChain.Width;
int height = engine->appState.Renderer.FrameBuffer[0].ColorSwapChain.Height;
XrCompositionLayerCylinderKHR cylinder_layer = {};
cylinder_layer.type = XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR;
cylinder_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
cylinder_layer.space = engine->appState.CurrentSpace;
cylinder_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
memset(&cylinder_layer.subImage, 0, sizeof(XrSwapchainSubImage));
cylinder_layer.subImage.swapchain = engine->appState.Renderer.FrameBuffer.ColorSwapChain.Handle;
cylinder_layer.subImage.swapchain = engine->appState.Renderer.FrameBuffer[0].ColorSwapChain.Handle;
cylinder_layer.subImage.imageRect.offset.x = 0;
cylinder_layer.subImage.imageRect.offset.y = 0;
cylinder_layer.subImage.imageRect.extent.width = width;
@ -425,9 +435,13 @@ void VR_EndFrame( engine_t* engine ) {
endFrameInfo.layers = layers;
OXR(xrEndFrame(engine->appState.Session, &endFrameInfo));
int instances = engine->appState.Renderer.Multiview ? 1 : ovrMaxNumEyes;
for (int i = 0; i < instances; i++) {
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[instances];
frameBuffer->TextureSwapChainIndex++;
frameBuffer->TextureSwapChainIndex %= frameBuffer->TextureSwapChainLength;
}
}
int VR_GetConfig( VRConfig config ) {
return vrConfig[config];
@ -439,7 +453,8 @@ void VR_SetConfig( VRConfig config, int value) {
void VR_BindFramebuffer(engine_t *engine) {
if (!initialized) return;
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
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));

View File

@ -18,6 +18,8 @@ enum VRConfig {
VR_CONFIG_MOUSE_SIZE, VR_CONFIG_MOUSE_X, VR_CONFIG_MOUSE_Y,
//viewport setup
VR_CONFIG_VIEWPORT_WIDTH, VR_CONFIG_VIEWPORT_HEIGHT, VR_CONFIG_VIEWPORT_VALID,
//render status
VR_CONFIG_CURRENT_FBO,
//end
VR_CONFIG_MAX
@ -41,8 +43,10 @@ void VR_GetResolution( engine_t* engine, int *pWidth, int *pHeight );
void VR_InitRenderer( engine_t* engine, bool multiview );
void VR_DestroyRenderer( engine_t* engine );
bool VR_BeginFrame( engine_t* engine );
bool VR_InitFrame( engine_t* engine );
void VR_BeginFrame( engine_t* engine, int fboIndex );
void VR_EndFrame( engine_t* engine );
void VR_FinishFrame( engine_t* engine );
int VR_GetConfig( VRConfig config );
void VR_SetConfig( VRConfig config, int value);

View File

@ -410,7 +410,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
if (IsMultiviewSupported()) {
render_->SetUniformM4x4Stereo("u_proj", &u_proj, leftEyeMatrix.m, rightEyeMatrix.m);
} else {
render_->SetUniformM4x4(&u_proj, leftEyeMatrix.m);
render_->SetUniformM4x4(&u_proj, GetVRFBOIndex() == 0 ? leftEyeMatrix.m : rightEyeMatrix.m);
}
} else {
Matrix4x4 flippedMatrix;
@ -537,7 +537,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
if (IsMultiviewSupported()) {
render_->SetUniformM4x4Stereo("u_view", &u_view, leftEyeView, rightEyeView);
} else {
render_->SetUniformM4x4(&u_view, leftEyeView);
render_->SetUniformM4x4(&u_view, GetVRFBOIndex() == 0 ? leftEyeView : rightEyeView);
}
} else {
SetMatrix4x3(render_, &u_view, gstate.viewMatrix);

View File

@ -1120,10 +1120,8 @@ void GameSettingsScreen::CreateViews() {
vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Enable virtual reality")));
CheckBox *vr6DoF = vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("Enable 6 degrees of freedom movement")));
vr6DoF->SetEnabledPtr(&g_Config.bEnableVR);
if (IsMultiviewSupported()) {
CheckBox *vrStereo = vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Enable stereoscopic vision")));
vrStereo->SetEnabledPtr(&g_Config.bEnableVR);
}
PopupSliderChoice *vrFieldOfView = vrSettings->Add(new PopupSliderChoice(&g_Config.iFieldOfViewPercentage, 100, 150, vr->T("Field of view scale", "Headset's field of view scale"), 10, screenManager(), vr->T("% of native FoV")));
vrFieldOfView->SetEnabledPtr(&g_Config.bEnableVR);
vrSettings->Add(new PopupSliderChoice(&g_Config.iCanvasDistance, 1, 10, vr->T("Distance to 2D menus and scenes", "Distance to 2D menus and scenes"), 1, screenManager(), ""));