diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 6d6e6529e3..9c6cac4640 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -90,7 +90,7 @@ void EnterVR(bool firstStart) { VR_EnterVR(VR_GetEngine()); IN_VRInit(VR_GetEngine()); } - VR_InitRenderer(VR_GetEngine()); + VR_InitRenderer(VR_GetEngine(), IsMultiviewSupported()); } void GetVRResolutionPerEye(int* width, int* height) { diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index ec42749424..138c8f09f4 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -92,14 +92,14 @@ typedef struct { typedef struct { int Width; int Height; + bool Multiview; uint32_t TextureSwapChainLength; uint32_t TextureSwapChainIndex; ovrSwapChain ColorSwapChain; - ovrSwapChain DepthSwapChain; XrSwapchainImageOpenGLESKHR* ColorSwapChainImage; - XrSwapchainImageOpenGLESKHR* DepthSwapChainImage; + unsigned int* DepthBuffers; unsigned int* FrameBuffers; - bool Acquired[2]; + bool Acquired; } ovrFramebuffer; typedef struct { diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 4ee3fae477..df9b4eebea 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -33,23 +33,17 @@ void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) { frameBuffer->ColorSwapChain.Handle = XR_NULL_HANDLE; frameBuffer->ColorSwapChain.Width = 0; frameBuffer->ColorSwapChain.Height = 0; - frameBuffer->DepthSwapChain.Handle = XR_NULL_HANDLE; - frameBuffer->DepthSwapChain.Width = 0; - frameBuffer->DepthSwapChain.Height = 0; + frameBuffer->DepthBuffers = NULL; frameBuffer->FrameBuffers = NULL; - frameBuffer->Acquired[0] = false; - frameBuffer->Acquired[1] = false; + frameBuffer->Acquired = false; } -bool ovrFramebuffer_Create( - XrSession session, - ovrFramebuffer* frameBuffer, - const int width, - const int height) { +bool ovrFramebuffer_Create(XrSession session, ovrFramebuffer* frameBuffer, int width, int height, bool multiview) { frameBuffer->Width = width; frameBuffer->Height = height; + frameBuffer->Multiview = multiview; if (strstr((const char*)glGetString(GL_EXTENSIONS), "GL_OVR_multiview2") == nullptr) { @@ -68,37 +62,27 @@ bool ovrFramebuffer_Create( XrSwapchainCreateInfo swapChainCreateInfo; memset(&swapChainCreateInfo, 0, sizeof(swapChainCreateInfo)); swapChainCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; + swapChainCreateInfo.format = GL_RGBA8; + swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; swapChainCreateInfo.sampleCount = 1; swapChainCreateInfo.width = width; swapChainCreateInfo.height = height; swapChainCreateInfo.faceCount = 1; swapChainCreateInfo.mipCount = 1; - swapChainCreateInfo.arraySize = 1; //TODO:set to 2 to enable multiview + swapChainCreateInfo.arraySize = multiview ? 2 : 1; frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; - frameBuffer->DepthSwapChain.Width = swapChainCreateInfo.width; - frameBuffer->DepthSwapChain.Height = swapChainCreateInfo.height; // Create the color swapchain. - swapChainCreateInfo.format = GL_RGBA8; - swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->ColorSwapChain.Handle)); OXR(xrEnumerateSwapchainImages(frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); frameBuffer->ColorSwapChainImage = (XrSwapchainImageOpenGLESKHR*)malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); - // Create the depth swapchain. - swapChainCreateInfo.format = GL_DEPTH24_STENCIL8; - swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->DepthSwapChain.Handle)); - frameBuffer->DepthSwapChainImage = (XrSwapchainImageOpenGLESKHR*)malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); - // Populate the swapchain image array. for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { frameBuffer->ColorSwapChainImage[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; frameBuffer->ColorSwapChainImage[i].next = NULL; - frameBuffer->DepthSwapChainImage[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; - frameBuffer->DepthSwapChainImage[i].next = NULL; } OXR(xrEnumerateSwapchainImages( frameBuffer->ColorSwapChain.Handle, @@ -106,25 +90,52 @@ bool ovrFramebuffer_Create( &frameBuffer->TextureSwapChainLength, (XrSwapchainImageBaseHeader*)frameBuffer->ColorSwapChainImage)); - OXR(xrEnumerateSwapchainImages( - frameBuffer->DepthSwapChain.Handle, - frameBuffer->TextureSwapChainLength, - &frameBuffer->TextureSwapChainLength, - (XrSwapchainImageBaseHeader*)frameBuffer->DepthSwapChainImage)); - + 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++) { const GLuint colorTexture = frameBuffer->ColorSwapChainImage[i].image; - const GLuint depthTexture = frameBuffer->DepthSwapChainImage[i].image; + if (multiview) { + // Create the color buffer texture. + GLenum textureTarget = GL_TEXTURE_2D_ARRAY; + GL(glBindTexture(textureTarget, colorTexture)); + GL(glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL(glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GL(glBindTexture(textureTarget, 0)); - // Create the frame buffer. - GL(glGenFramebuffers(1, &frameBuffer->FrameBuffers[i])); - GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer->FrameBuffers[i])); - if (swapChainCreateInfo.arraySize > 1) { - GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0, 2)); + // Create depth buffer. + GL(glGenTextures(1, &frameBuffer->DepthBuffers[i])); + GL(glBindTexture(textureTarget, frameBuffer->DepthBuffers[i])); + GL(glTexStorage3D(textureTarget, 1, GL_DEPTH_COMPONENT24, width, height, 2)); + GL(glBindTexture(textureTarget, 0)); + + // Create the frame buffer. + GL(glGenFramebuffers(1, &frameBuffer->FrameBuffers[i])); + GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer->FrameBuffers[i])); + GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, frameBuffer->DepthBuffers[i], 0, 0, 2)); GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, 0, 2)); } else { - GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0)); + // Create the color buffer texture. + GLenum colorTextureTarget = GL_TEXTURE_2D; + GL(glBindTexture(colorTextureTarget, colorTexture)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GL(glBindTexture(colorTextureTarget, 0)); + + // Create depth buffer. + GL(glGenRenderbuffers(1, &frameBuffer->DepthBuffers[i])); + GL(glBindRenderbuffer(GL_RENDERBUFFER, frameBuffer->DepthBuffers[i])); + GL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height)); + GL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + + // Create the frame buffer. + GL(glGenFramebuffers(1, &frameBuffer->FrameBuffers[i])); + GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer->FrameBuffers[i])); + GL(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, frameBuffer->DepthBuffers[i])); + GL(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, frameBuffer->DepthBuffers[i])); GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0)); } GL(GLenum renderFramebufferStatus = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); @@ -140,10 +151,14 @@ bool ovrFramebuffer_Create( void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer) { GL(glDeleteFramebuffers(frameBuffer->TextureSwapChainLength, frameBuffer->FrameBuffers)); - OXR(xrDestroySwapchain(frameBuffer->DepthSwapChain.Handle)); + if (frameBuffer->Multiview) { + GL(glDeleteFramebuffers(frameBuffer->TextureSwapChainLength, frameBuffer->DepthBuffers)); + } else { + GL(glDeleteRenderbuffers(frameBuffer->TextureSwapChainLength, frameBuffer->DepthBuffers)); + } OXR(xrDestroySwapchain(frameBuffer->ColorSwapChain.Handle)); - free(frameBuffer->DepthSwapChainImage); free(frameBuffer->ColorSwapChainImage); + free(frameBuffer->DepthBuffers); free(frameBuffer->FrameBuffers); ovrFramebuffer_Clear(frameBuffer); @@ -164,38 +179,31 @@ void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer) { } void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) { - ovrSwapChain swapChains[2] = {frameBuffer->ColorSwapChain, frameBuffer->DepthSwapChain}; + XrSwapchainImageAcquireInfo acquireInfo = {XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, NULL}; + OXR(xrAcquireSwapchainImage(frameBuffer->ColorSwapChain.Handle, &acquireInfo, &frameBuffer->TextureSwapChainIndex)); - for (int index = 0; index < 2; index++) { - XrSwapchainImageAcquireInfo acquireInfo = {XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, NULL}; - OXR(xrAcquireSwapchainImage(swapChains[index].Handle, &acquireInfo, &frameBuffer->TextureSwapChainIndex)); - - XrSwapchainImageWaitInfo waitInfo; - waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO; - waitInfo.next = NULL; - waitInfo.timeout = 1000; /* timeout in nanoseconds */ - XrResult res = xrWaitSwapchainImage(swapChains[index].Handle, &waitInfo); - int i = 0; - while ((res != XR_SUCCESS) && (i < 10)) { - res = xrWaitSwapchainImage(swapChains[index].Handle, &waitInfo); - i++; - ALOGV( - " Retry xrWaitSwapchainImage %d times due to XR_TIMEOUT_EXPIRED (duration %f micro seconds)", - i, - waitInfo.timeout * (1E-9)); - } - frameBuffer->Acquired[index] = res == XR_SUCCESS; + XrSwapchainImageWaitInfo waitInfo; + waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO; + waitInfo.next = NULL; + waitInfo.timeout = 1000; /* timeout in nanoseconds */ + XrResult res = xrWaitSwapchainImage(frameBuffer->ColorSwapChain.Handle, &waitInfo); + int i = 0; + while ((res != XR_SUCCESS) && (i < 10)) { + res = xrWaitSwapchainImage(frameBuffer->ColorSwapChain.Handle, &waitInfo); + i++; + ALOGV( + " Retry xrWaitSwapchainImage %d times due to XR_TIMEOUT_EXPIRED (duration %f micro seconds)", + i, + waitInfo.timeout * (1E-9)); } + frameBuffer->Acquired = res == XR_SUCCESS; } void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { - ovrSwapChain swapChains[2] = {frameBuffer->ColorSwapChain, frameBuffer->DepthSwapChain}; - for (int index = 0; index < 2; index++) { - if (frameBuffer->Acquired[index]) { - XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; - OXR(xrReleaseSwapchainImage(swapChains[index].Handle, &releaseInfo)); - frameBuffer->Acquired[index] = false; - } + if (frameBuffer->Acquired) { + XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; + OXR(xrReleaseSwapchainImage(frameBuffer->ColorSwapChain.Handle, &releaseInfo)); + frameBuffer->Acquired = false; } } @@ -211,17 +219,8 @@ void ovrRenderer_Clear(ovrRenderer* renderer) { ovrFramebuffer_Clear(&renderer->FrameBuffer); } -void ovrRenderer_Create( - XrSession session, - ovrRenderer* renderer, - int suggestedEyeTextureWidth, - int suggestedEyeTextureHeight) { - // Create the frame buffers. - ovrFramebuffer_Create( - session, - &renderer->FrameBuffer, - suggestedEyeTextureWidth, - suggestedEyeTextureHeight); +void ovrRenderer_Create(XrSession session, ovrRenderer* renderer, int width, int height, bool multiview) { + ovrFramebuffer_Create(session, &renderer->FrameBuffer, width, height, multiview); } void ovrRenderer_Destroy(ovrRenderer* renderer) { diff --git a/Common/VR/VRFramebuffer.h b/Common/VR/VRFramebuffer.h index 21b193b7a4..dcedad580f 100644 --- a/Common/VR/VRFramebuffer.h +++ b/Common/VR/VRFramebuffer.h @@ -12,9 +12,5 @@ void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer); void ovrFramebuffer_SetCurrent(ovrFramebuffer* frameBuffer); void ovrFramebuffer_SetNone(); -void ovrRenderer_Create( - XrSession session, - ovrRenderer* renderer, - int suggestedEyeTextureWidth, - int suggestedEyeTextureHeight); +void ovrRenderer_Create(XrSession session, ovrRenderer* renderer, int width, int height, bool multiview); void ovrRenderer_Destroy(ovrRenderer* renderer); diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 0a952de4a8..343a496620 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -175,7 +175,7 @@ void VR_Recenter(engine_t* engine) { menuYaw = 0; } -void VR_InitRenderer( engine_t* engine ) { +void VR_InitRenderer( engine_t* engine, bool multiview ) { if (initialized) { VR_DestroyRenderer(engine); } @@ -185,18 +185,12 @@ void VR_InitRenderer( engine_t* engine ) { // Get the viewport configuration info for the chosen viewport configuration type. engine->appState.ViewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES; - - OXR(xrGetViewConfigurationProperties( - engine->appState.Instance, engine->appState.SystemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, &engine->appState.ViewportConfig)); + OXR(xrGetViewConfigurationProperties(engine->appState.Instance, engine->appState.SystemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, &engine->appState.ViewportConfig)); uint32_t numOutputSpaces = 0; OXR(xrEnumerateReferenceSpaces(engine->appState.Session, 0, &numOutputSpaces, NULL)); - - XrReferenceSpaceType* referenceSpaces = - (XrReferenceSpaceType*)malloc(numOutputSpaces * sizeof(XrReferenceSpaceType)); - - OXR(xrEnumerateReferenceSpaces( - engine->appState.Session, numOutputSpaces, &numOutputSpaces, referenceSpaces)); + XrReferenceSpaceType* referenceSpaces = (XrReferenceSpaceType*)malloc(numOutputSpaces * sizeof(XrReferenceSpaceType)); + OXR(xrEnumerateReferenceSpaces(engine->appState.Session, numOutputSpaces, &numOutputSpaces, referenceSpaces)); for (uint32_t i = 0; i < numOutputSpaces; i++) { if (referenceSpaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) { @@ -217,7 +211,8 @@ void VR_InitRenderer( engine_t* engine ) { engine->appState.Session, &engine->appState.Renderer, engine->appState.ViewConfigurationView[0].recommendedImageRectWidth, - engine->appState.ViewConfigurationView[0].recommendedImageRectHeight); + engine->appState.ViewConfigurationView[0].recommendedImageRectHeight, + multiview); initialized = GL_TRUE; } @@ -432,9 +427,9 @@ void VR_SetConfig( VRConfig config, int value) { void VR_BindFramebuffer(engine_t *engine) { if (!initialized) return; ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer; - int swapchainIndex = frameBuffer->TextureSwapChainIndex; - int glFramebuffer = frameBuffer->FrameBuffers[swapchainIndex]; - GL(glBindFramebuffer(GL_FRAMEBUFFER, glFramebuffer)); + unsigned int swapchainIndex = frameBuffer->TextureSwapChainIndex; + unsigned int glFramebuffer = frameBuffer->FrameBuffers[swapchainIndex]; + GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, glFramebuffer)); } ovrMatrix4f VR_GetMatrix( VRMatrix matrix ) { diff --git a/Common/VR/VRRenderer.h b/Common/VR/VRRenderer.h index 01905b15c9..872bda7772 100644 --- a/Common/VR/VRRenderer.h +++ b/Common/VR/VRRenderer.h @@ -35,7 +35,7 @@ enum VRMode { }; void VR_GetResolution( engine_t* engine, int *pWidth, int *pHeight ); -void VR_InitRenderer( engine_t* engine ); +void VR_InitRenderer( engine_t* engine, bool multiview ); void VR_DestroyRenderer( engine_t* engine ); bool VR_BeginFrame( engine_t* engine );