Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenXR - Stereoscopic rendering #15901

Merged
merged 50 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
c7410d4
OpenXR - Framebuffer multiview used
lvonasek Aug 14, 2022
caac012
OpenXR - VR renderer adjustments
lvonasek Aug 14, 2022
c71ecd7
OpenXR - Unused parameter removed
lvonasek Aug 14, 2022
f5d053f
Merge branch 'feature_openxr_6dof' into feature_openxr_stereo
lvonasek Aug 14, 2022
e76a686
OpenXR - Config for stereoscopic vision added
lvonasek Aug 14, 2022
47349b2
Merge branch 'master' into feature_openxr_stereo
lvonasek Aug 14, 2022
ab6c91c
OpenXR - Integrate multiview into system
lvonasek Aug 14, 2022
43bd9b9
Merge branch 'feature_openxr_6dof' into feature_openxr_stereo
lvonasek Aug 15, 2022
f8e68a4
Merge branch 'feature_openxr_6dof' into feature_openxr_stereo
lvonasek Aug 15, 2022
4a53054
Merge branch 'feature_openxr_6dof' into feature_openxr_stereo
lvonasek Aug 15, 2022
e4a65c5
Merge branch 'feature_openxr_6dof' into feature_openxr_stereo
lvonasek Aug 16, 2022
71df50a
OpenXR - GL and OXR logging added
lvonasek Aug 16, 2022
22e7f87
OpenXR - Disable multiview for now
lvonasek Aug 16, 2022
d570a19
Merge branch 'feature_openxr_6dof' into feature_openxr_stereo
lvonasek Aug 17, 2022
4026d49
OpenXR - Multiview uniforms working
lvonasek Aug 17, 2022
c508f66
OpenXR - Multiview in progress
lvonasek Aug 18, 2022
4603ccd
OpenXR - Initialization errors fixed
lvonasek Aug 19, 2022
98f726a
OpenXR - Use OpenGL ES 3 and ensure FBO pair calls
lvonasek Aug 19, 2022
af011c2
OpenXR - Step closer to identify multiview FBO issue
lvonasek Aug 19, 2022
11a6318
Merge branch 'hrydgard:master' into feature_openxr_stereo
lvonasek Aug 24, 2022
8885600
Merge branch 'hrydgard:master' into feature_openxr_stereo
lvonasek Aug 24, 2022
ce55449
Assert removed
lvonasek Aug 24, 2022
723d641
OpenXR - Enable performance mode
lvonasek Aug 27, 2022
5e434bc
Merge branch 'hrydgard:master' into feature_openxr_stereo
lvonasek Aug 27, 2022
c2c0561
OpenXR - OPENXR ifdef removal
lvonasek Aug 27, 2022
9e20820
OpenXR - Dummy integration compile fix
lvonasek Aug 27, 2022
ca92f80
Merge branch 'master' into feature_openxr_stereo
lvonasek Aug 28, 2022
2d0e426
OpenXR - Keep using GLES2 headers for now
lvonasek Aug 28, 2022
4bd5a28
OpenXR - Flag to easily disable multiview shaders added
lvonasek Aug 28, 2022
aa150a8
OpenXR - Swapchain acquiring fixed
lvonasek Aug 28, 2022
2adc726
Merge branch 'master' into feature_openxr_stereo
lvonasek Aug 28, 2022
6adabd8
OpenXR - Compile fix
lvonasek Aug 28, 2022
94968c3
Merge branch 'master' into feature_openxr_stereo
lvonasek Aug 29, 2022
462174f
OpenXR - Multiview refactor to make it optional
lvonasek Aug 29, 2022
044d9a4
OpenXR - Emulate mouse cursor
lvonasek Sep 1, 2022
00aaf9e
Merge branch 'master' into feature_openxr_stereo
lvonasek Sep 1, 2022
22db37d
OpenXR - Viewport init better
lvonasek Sep 1, 2022
bda42e5
compile fix
lvonasek Sep 1, 2022
5e2ecb5
OpenXR - FBO intialization better
lvonasek Sep 2, 2022
1df1d79
OpenXR - Stereo without multiview added
lvonasek Sep 4, 2022
5be6665
Merge branch 'master' into feature_openxr_stereo
lvonasek Sep 4, 2022
fb875b9
OpenXR - Multipass rendering fixed
lvonasek Sep 4, 2022
2195f4b
OpenXR - Mismatched call order fixed
lvonasek Sep 4, 2022
4ce0579
OpenXR - Split projection matrix for color and depth buffer
lvonasek Sep 4, 2022
81de46c
OpenXR - Do not include lens projection in nonVR builds
lvonasek Sep 4, 2022
5b47d22
OpenXR - Mismatch in stereo and normal uniform fixed
lvonasek Sep 4, 2022
0e4f93d
OpenXR - Fixing FOV better
lvonasek Sep 5, 2022
3a0e6c7
Merge branch 'master' into feature_openxr_stereo
lvonasek Sep 5, 2022
08226d8
OpenXR - Stereo matrices fixed
lvonasek Sep 5, 2022
93202e4
OpenXR - Config for stereo separation added
lvonasek Sep 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ include_directories(ext/glslang)
# Anyway, glew will be going away anyway.
include_directories(ext/glew)

if(NOT OPENGL_LIBRARIES AND USING_GLES2)
if(OPENXR)
set(OPENGL_LIBRARIES GLESv3 EGL)
elseif(NOT OPENGL_LIBRARIES AND USING_GLES2)
set(OPENGL_LIBRARIES GLESv2 EGL)
endif()

Expand Down
3 changes: 3 additions & 0 deletions Common/GPU/OpenGL/GLCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#if PPSSPP_PLATFORM(IOS)
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#elif defined(OPEXR)
lvonasek marked this conversation as resolved.
Show resolved Hide resolved
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#elif defined(USING_GLES2)
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
Expand Down
51 changes: 50 additions & 1 deletion Common/GPU/OpenGL/GLQueueRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ static std::string GetInfoLog(GLuint name, Getiv getiv, GetLog getLog) {
return infoLog;
}

int GLQueueRunner::GetStereoBufferIndex(const char *uniformName) {
if (!uniformName) return -1;
else if (strcmp(uniformName, "u_view") == 0) return 0;
else if (strcmp(uniformName, "u_proj") == 0) return 1;
else return -1;
}

std::string GLQueueRunner::GetStereoBufferLayout(const char *uniformName) {
if (strcmp(uniformName, "u_view") == 0) return "ViewMatrices";
else if (strcmp(uniformName, "u_proj") == 0) return "ProjectionMatrix";
else return "undefined";
}

void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls) {
if (skipGLCalls) {
// Some bookkeeping still needs to be done.
Expand Down Expand Up @@ -263,7 +276,25 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
for (size_t j = 0; j < program->queries_.size(); j++) {
auto &query = program->queries_[j];
_dbg_assert_(query.name);
#ifdef OPENXR
int location = -1;
int index = GetStereoBufferIndex(query.name);
if (index >= 0) {
std::string layout = GetStereoBufferLayout(query.name);
glUniformBlockBinding(program->program, glGetUniformBlockIndex(program->program, layout.c_str()), index);

GLuint buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER,2 * 16 * sizeof(float),NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
location = buffer;
} else {
location = glGetUniformLocation(program->program, query.name);
}
#else
int location = glGetUniformLocation(program->program, query.name);
#endif
if (location < 0 && query.required) {
WARN_LOG(G3D, "Required uniform query for '%s' failed", query.name);
}
Expand Down Expand Up @@ -995,6 +1026,24 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
CHECK_GL_ERROR_IF_DEBUG();
break;
}
#ifdef OPENXR
case GLRRenderCommand::UNIFORMSTEREOMATRIX:
{
_dbg_assert_(curProgram);
int layout = GetStereoBufferIndex(c.uniformMatrix4.name);
if (layout >= 0) {
int size = 2 * 16 * sizeof(float);
glBindBufferBase(GL_UNIFORM_BUFFER, layout, *c.uniformMatrix4.loc);
glBindBuffer(GL_UNIFORM_BUFFER, *c.uniformMatrix4.loc);
void *viewMatrices = glMapBufferRange(GL_UNIFORM_BUFFER, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
memcpy(viewMatrices, c.uniformMatrix4.m, size);
glUnmapBuffer(GL_UNIFORM_BUFFER);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
CHECK_GL_ERROR_IF_DEBUG();
break;
}
#endif
case GLRRenderCommand::UNIFORMMATRIX:
{
_dbg_assert_(curProgram);
Expand Down Expand Up @@ -1666,7 +1715,7 @@ void GLQueueRunner::fbo_unbind() {
#endif

#ifdef OPENXR
VR_BindFramebuffer(VR_GetEngine(), 0);
VR_BindFramebuffer(VR_GetEngine());
#endif

currentDrawHandle_ = 0;
Expand Down
6 changes: 5 additions & 1 deletion Common/GPU/OpenGL/GLQueueRunner.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ enum class GLRRenderCommand : uint8_t {
UNIFORM4UI,
UNIFORM4F,
UNIFORMMATRIX,
UNIFORMSTEREOMATRIX,
TEXTURESAMPLER,
TEXTURELOD,
VIEWPORT,
Expand Down Expand Up @@ -128,7 +129,7 @@ struct GLRRenderData {
struct {
const char *name; // if null, use loc
const GLint *loc;
float m[16];
float m[32];
} uniformMatrix4;
struct {
uint32_t clearColor;
Expand Down Expand Up @@ -357,6 +358,9 @@ class GLQueueRunner {
caps_ = caps;
}

int GetStereoBufferIndex(const char *uniformName);
std::string GetStereoBufferLayout(const char *uniformName);

void RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls);

void RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls);
Expand Down
43 changes: 24 additions & 19 deletions Common/GPU/OpenGL/GLRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,22 +203,6 @@ bool GLRenderManager::ThreadFrame() {
std::unique_lock<std::mutex> lock(mutex_);
if (!run_)
return false;
#ifdef OPENXR
VR_BeginFrame(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)) {
VR_SetConfig(VR_CONFIG_MODE, VR_MODE_MONO_6DOF);
} else {
VR_SetConfig(VR_CONFIG_MODE, VR_MODE_FLAT_SCREEN);
}
VR_SetConfig(VR_CONFIG_3D_GEOMETRY_COUNT, VR_GetConfig(VR_CONFIG_3D_GEOMETRY_COUNT) / 2);

// Set customizations
VR_SetConfig(VR_CONFIG_6DOF_ENABLED, g_Config.bEnable6DoF);
VR_SetConfig(VR_CONFIG_CANVAS_DISTANCE, g_Config.iCanvasDistance);
VR_SetConfig(VR_CONFIG_FOV_SCALE, g_Config.iFieldOfViewPercentage);
#endif

// In case of syncs or other partial completion, we keep going until we complete a frame.
do {
Expand Down Expand Up @@ -254,12 +238,33 @@ bool GLRenderManager::ThreadFrame() {
INFO_LOG(G3D, "Running first frame (%d)", threadFrame_);
firstFrame = false;
}

#ifdef OPENXR
if (VR_BeginFrame(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)) {
VR_SetConfig(VR_CONFIG_MODE, g_Config.bEnableStereo ? VR_MODE_STEREO_6DOF : VR_MODE_MONO_6DOF);
} else {
VR_SetConfig(VR_CONFIG_MODE, VR_MODE_FLAT_SCREEN);
}
VR_SetConfig(VR_CONFIG_3D_GEOMETRY_COUNT, VR_GetConfig(VR_CONFIG_3D_GEOMETRY_COUNT) / 2);

// Set customizations
VR_SetConfig(VR_CONFIG_6DOF_ENABLED, g_Config.bEnable6DoF);
VR_SetConfig(VR_CONFIG_CANVAS_DISTANCE, g_Config.iCanvasDistance);
VR_SetConfig(VR_CONFIG_FOV_SCALE, g_Config.iFieldOfViewPercentage);

// Render scene
GL(Run(threadFrame_));
VR_EndFrame(VR_GetEngine());
}
#else
Run(threadFrame_);
#endif
VLOG("PULL: Finished frame %d", threadFrame_);
} while (!nextFrame);
#ifdef OPENXR
VR_EndFrame(VR_GetEngine());
#endif

return true;
}

Expand Down
15 changes: 15 additions & 0 deletions Common/GPU/OpenGL/GLRenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,21 @@ class GLRenderManager {
curRenderStep_->commands.push_back(data);
}

#ifdef OPENXR
void SetUniformM4x4Stereo(const char *name, const GLint *loc, const float *left, const float *right) {
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
#ifdef _DEBUG
_dbg_assert_(curProgram_);
#endif
GLRRenderData data{ GLRRenderCommand::UNIFORMSTEREOMATRIX };
data.uniformMatrix4.name = name;
data.uniformMatrix4.loc = loc;
memcpy(&data.uniformMatrix4.m[0], left, sizeof(float) * 16);
memcpy(&data.uniformMatrix4.m[16], right, sizeof(float) * 16);
curRenderStep_->commands.push_back(data);
}
#endif

void SetUniformM4x4(const char *name, const float *udata) {
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
#ifdef _DEBUG
Expand Down
2 changes: 1 addition & 1 deletion Common/UI/UIScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void UIScreen::preRender() {
screenManager()->getUIContext()->BeginFrame();

#ifdef OPENXR
VR_BindFramebuffer(VR_GetEngine(), 0);
VR_BindFramebuffer(VR_GetEngine());
#endif

Draw::Viewport viewport;
Expand Down
147 changes: 146 additions & 1 deletion Common/VR/VRBase.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,155 @@
#pragma once

#include "VRFramebuffer.h"
#ifdef ANDROID
#include <android/log.h>
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, "OpenXR", __VA_ARGS__);
#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "OpenXR", __VA_ARGS__);
#else
#define ALOGE(...) printf(__VA_ARGS__)
#define ALOGV(...) printf(__VA_ARGS__)
#endif

//OpenXR
#define XR_USE_PLATFORM_ANDROID 1
#define XR_USE_GRAPHICS_API_OPENGL_ES 1
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <jni.h>
#include <math.h>
#include <openxr.h>
#include <openxr_platform.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>

#ifdef _DEBUG
static const char* GlErrorString(GLenum error) {
switch (error) {
case GL_NO_ERROR:
return "GL_NO_ERROR";
case GL_INVALID_ENUM:
return "GL_INVALID_ENUM";
case GL_INVALID_VALUE:
return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION:
return "GL_INVALID_OPERATION";
case GL_INVALID_FRAMEBUFFER_OPERATION:
return "GL_INVALID_FRAMEBUFFER_OPERATION";
case GL_OUT_OF_MEMORY:
return "GL_OUT_OF_MEMORY";
default:
return "unknown";
}
}

static void GLCheckErrors(char* file, int line) {
for (int i = 0; i < 10; i++) {
const GLenum error = glGetError();
if (error == GL_NO_ERROR) {
break;
}
ALOGE("GL error on line %s:%d %s", file, line, GlErrorString(error));
}
}

#define GL(func) func; GLCheckErrors(__FILE__ , __LINE__);
#else
#define GL(func) func;
#endif

#if defined(_DEBUG)
static void OXR_CheckErrors(XrInstance instance, XrResult result, const char* function, bool failOnError) {
if (XR_FAILED(result)) {
char errorBuffer[XR_MAX_RESULT_STRING_SIZE];
xrResultToString(instance, result, errorBuffer);
if (failOnError) {
ALOGE("OpenXR error: %s: %s\n", function, errorBuffer);
} else {
ALOGV("OpenXR error: %s: %s\n", function, errorBuffer);
}
}
}
#define OXR(func) OXR_CheckErrors(VR_GetEngine()->appState.Instance, func, #func, true);
#else
#define OXR(func) func;
#endif

enum { ovrMaxLayerCount = 1 };
enum { ovrMaxNumEyes = 2 };

typedef union {
XrCompositionLayerProjection Projection;
XrCompositionLayerCylinderKHR Cylinder;
} ovrCompositorLayer_Union;

typedef struct {
XrSwapchain Handle;
uint32_t Width;
uint32_t Height;
} ovrSwapChain;

typedef struct {
int Width;
int Height;
uint32_t TextureSwapChainLength;
uint32_t TextureSwapChainIndex;
ovrSwapChain ColorSwapChain;
ovrSwapChain DepthSwapChain;
XrSwapchainImageOpenGLESKHR* ColorSwapChainImage;
XrSwapchainImageOpenGLESKHR* DepthSwapChainImage;
unsigned int* FrameBuffers;
bool Acquired;
} ovrFramebuffer;

typedef struct {
ovrFramebuffer FrameBuffer;
} ovrRenderer;

typedef struct {
int Focused;

XrInstance Instance;
XrSession Session;
XrViewConfigurationProperties ViewportConfig;
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
XrSystemId SystemId;
XrSpace HeadSpace;
XrSpace StageSpace;
XrSpace FakeStageSpace;
XrSpace CurrentSpace;
int SessionActive;

int SwapInterval;
// These threads will be marked as performance threads.
int MainThreadTid;
int RenderThreadTid;
ovrCompositorLayer_Union Layers[ovrMaxLayerCount];
int LayerCount;

ovrRenderer Renderer;
} ovrApp;

typedef struct {
JavaVM* Vm;
jobject ActivityObject;
JNIEnv* Env;
char AppName[64];
int AppVersion;
} ovrJava;

typedef struct {
uint64_t frameIndex;
ovrApp appState;
ovrJava java;
float predictedDisplayTime;
} engine_t;

void VR_Init( ovrJava java );
void VR_Destroy( engine_t* engine );
void VR_EnterVR( engine_t* engine );
void VR_LeaveVR( engine_t* engine );

engine_t* VR_GetEngine( void );

void ovrApp_Clear(ovrApp* app);
void ovrApp_Destroy(ovrApp* app);
int ovrApp_HandleXrEvents(ovrApp* app);
Loading