diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cf7548188..cece57f20d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 64d9884014..479ab91f97 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -111,7 +111,8 @@ static std::string GetInfoLog(GLuint name, Getiv getiv, GetLog getLog) { } int GLQueueRunner::GetStereoBufferIndex(const char *uniformName) { - if (strcmp(uniformName, "u_view") == 0) return 0; + 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; } @@ -281,7 +282,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski #ifdef OPENXR int location = -1; int index = GetStereoBufferIndex(query.name); - if (index) { + if (index >= 0) { std::string layout = GetStereoBufferLayout(query.name); glUniformBlockBinding(program->program, glGetUniformBlockIndex(program->program, layout.c_str()), index); diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index 6aac2486c6..9470d6bff1 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -1,6 +1,145 @@ #pragma once -#include "VRFramebuffer.h" +#ifdef ANDROID +#include +#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 +#include +#include +#include +#include +#include +#include +#include + +#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; + XrSwapchainImageOpenGLESKHR* ColorSwapChainImage; + unsigned int* DepthBuffers; + unsigned int* FrameBuffers; +} 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 ); @@ -8,3 +147,7 @@ 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); diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 9f637a5037..0154bbaca7 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -16,14 +16,6 @@ double FromXrTime(const XrTime time) { return (time * 1e-9); } -typedef void(GL_APIENTRY* PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)( - GLenum target, - GLenum attachment, - GLuint texture, - GLint level, - GLint baseViewIndex, - GLsizei numViews); - /* ================================================================================ @@ -55,9 +47,19 @@ bool ovrFramebuffer_Create( frameBuffer->Width = width; frameBuffer->Height = height; - PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR = - (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)eglGetProcAddress( - "glFramebufferTextureMultiviewOVR"); + if (strstr((const char*)glGetString(GL_EXTENSIONS), "GL_OVR_multiview") == nullptr) + { + ALOGE("OpenGL ES 3.0 implementation does not support GL_OVR_multiview extension.\n"); + exit(EXIT_FAILURE); + } + + typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei); + auto glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVR)eglGetProcAddress ("glFramebufferTextureMultiviewOVR"); + if (!glFramebufferTextureMultiviewOVR) + { + ALOGE("Can not get proc address for glFramebufferTextureMultiviewOVR.\n"); + exit(EXIT_FAILURE); + } XrSwapchainCreateInfo swapChainCreateInfo; memset(&swapChainCreateInfo, 0, sizeof(swapChainCreateInfo)); @@ -77,11 +79,9 @@ bool ovrFramebuffer_Create( // Create the swapchain. OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->ColorSwapChain.Handle)); // Get the number of swapchain images. - OXR(xrEnumerateSwapchainImages( - frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); + OXR(xrEnumerateSwapchainImages(frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); // Allocate the swapchain images array. - frameBuffer->ColorSwapChainImage = (XrSwapchainImageOpenGLESKHR*)malloc( - frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); + frameBuffer->ColorSwapChainImage = (XrSwapchainImageOpenGLESKHR*)malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); // Populate the swapchain image array. for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { @@ -94,10 +94,8 @@ bool ovrFramebuffer_Create( &frameBuffer->TextureSwapChainLength, (XrSwapchainImageBaseHeader*)frameBuffer->ColorSwapChainImage)); - frameBuffer->DepthBuffers = - (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); - frameBuffer->FrameBuffers = - (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); + frameBuffer->DepthBuffers = (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); + frameBuffer->FrameBuffers = (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { // Create the color buffer texture. diff --git a/Common/VR/VRFramebuffer.h b/Common/VR/VRFramebuffer.h index ae4344009b..21b193b7a4 100644 --- a/Common/VR/VRFramebuffer.h +++ b/Common/VR/VRFramebuffer.h @@ -1,88 +1,6 @@ #pragma once -//OpenXR -#define XR_USE_GRAPHICS_API_OPENGL_ES 1 -#define XR_USE_PLATFORM_ANDROID 1 -#include -#include -#include -#include -#include -#include - -#define ALOGE(...) printf(__VA_ARGS__) -#define ALOGV(...) printf(__VA_ARGS__) - -typedef union { - XrCompositionLayerProjection Projection; - XrCompositionLayerCylinderKHR Cylinder; -} ovrCompositorLayer_Union; - -enum { ovrMaxLayerCount = 1 }; -enum { ovrMaxNumEyes = 2 }; - -#define GL(func) func; -#define OXR(func) func; - -typedef struct { - JavaVM* Vm; - jobject ActivityObject; - JNIEnv* Env; - char AppName[64]; - int AppVersion; -} ovrJava; - -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; - XrSwapchainImageOpenGLESKHR* ColorSwapChainImage; - unsigned int* DepthBuffers; - unsigned int* FrameBuffers; -} 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 { - uint64_t frameIndex; - ovrApp appState; - ovrJava java; - float predictedDisplayTime; -} engine_t; +#include "VR/VRBase.h" void ovrApp_Clear(ovrApp* app); void ovrApp_Destroy(ovrApp* app); diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index a2cecae45e..cb6cf3c24a 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -232,7 +232,7 @@ 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 ); + glClearColor( 0.0f, 0.5f, 1.0f, 1.0f ); glScissor( 0, 0, width, height ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 52483fcb21..a360c7fa8f 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -151,6 +151,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag gl_exts.push_back("#extension GL_ARB_cull_distance : enable"); } } +#ifdef OPENXR + gl_exts.push_back("#extension GL_OVR_multiview2 : enable\nlayout(num_views=2) in;"); +#endif ShaderWriter p(buffer, compat, ShaderStage::Vertex, gl_exts.data(), gl_exts.size()); bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); @@ -421,10 +424,6 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } WRITE(p, "};\n"); } else { -#ifdef OPENXR - WRITE(p, "#define NUM_VIEWS 2\n"); - WRITE(p, "#extension GL_OVR_multiview2 : enable\n"); -#endif if (enableBones) { const char * const * boneWeightDecl = boneWeightAttrDecl; if (!strcmp(compat.attribute, "in")) { diff --git a/android/QuestManifest.xml b/android/QuestManifest.xml index 7501b9eabc..8958156f22 100644 --- a/android/QuestManifest.xml +++ b/android/QuestManifest.xml @@ -1,7 +1,7 @@ - + +