diff options
Diffstat (limited to '3rdparty/bgfx/src/renderer_gl.cpp')
-rw-r--r-- | 3rdparty/bgfx/src/renderer_gl.cpp | 333 |
1 files changed, 259 insertions, 74 deletions
diff --git a/3rdparty/bgfx/src/renderer_gl.cpp b/3rdparty/bgfx/src/renderer_gl.cpp index ca09b64eba1..10f5a1c3fd9 100644 --- a/3rdparty/bgfx/src/renderer_gl.cpp +++ b/3rdparty/bgfx/src/renderer_gl.cpp @@ -1304,7 +1304,6 @@ namespace bgfx { namespace gl , m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT) , m_backBufferFbo(0) , m_msaaBackBufferFbo(0) - , m_ovrFbo(0) { memset(m_msaaBackBufferRbos, 0, sizeof(m_msaaBackBufferRbos) ); } @@ -1818,6 +1817,17 @@ namespace bgfx { namespace gl ); } +// if (s_extension[Extension::ARB_clip_control].m_supported) +// { +// GL_CHECK(glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE) ); +// g_caps.originBottomLeft = true; +// } +// else + { + g_caps.homogeneousDepth = true; + g_caps.originBottomLeft = true; + } + m_vaoSupport = !!(BGFX_CONFIG_RENDERER_OPENGLES >= 30) || s_extension[Extension::ARB_vertex_array_object].m_supported || s_extension[Extension::OES_vertex_array_object].m_supported @@ -2096,10 +2106,18 @@ namespace bgfx { namespace gl m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain); } - if (!m_ovr.swap(_hmd) ) + switch (m_ovr.swap(_hmd, true) ) { - m_glctx.swap(); + case OVR::DeviceLost: + ovrPreReset(); + break; + + default: + break; } + + // need to swap GL render context even if OVR is enabled to get the mirror texture in the output + m_glctx.swap(); } } @@ -2386,10 +2404,6 @@ namespace bgfx { namespace gl uint32_t width = m_resolution.m_width; uint32_t height = m_resolution.m_height; - if (m_ovr.isEnabled() ) - { - m_ovr.getSize(width, height); - } GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) ); GL_CHECK(glViewport(0, 0, width, height) ); @@ -2848,61 +2862,23 @@ namespace bgfx { namespace gl #if BGFX_CONFIG_USE_OVR if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) ) { - ovrGLConfig config; - config.OGL.Header.API = ovrRenderAPI_OpenGL; -# if OVR_VERSION > OVR_VERSION_043 - config.OGL.Header.BackBufferSize.w = m_resolution.m_width; - config.OGL.Header.BackBufferSize.h = m_resolution.m_height; -# else - config.OGL.Header.RTSize.w = m_resolution.m_width; - config.OGL.Header.RTSize.h = m_resolution.m_height; -# endif // OVR_VERSION > OVR_VERSION_043 - config.OGL.Header.Multisample = 0; - config.OGL.Window = (HWND)g_platformData.nwh; - config.OGL.DC = GetDC(config.OGL.Window); - if (m_ovr.postReset(g_platformData.nwh, &config.Config, !!(m_resolution.m_flags & BGFX_RESET_HMD_DEBUG) ) ) + if (m_ovr.postReset() ) { - uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate); - const Memory* mem = alloc(size); - - bx::StaticMemoryBlockWriter writer(mem->data, mem->size); - uint32_t magic = BGFX_CHUNK_MAGIC_TEX; - bx::write(&writer, magic); - - TextureCreate tc; - tc.m_flags = BGFX_TEXTURE_RT|( ((m_resolution.m_flags & BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT) << BGFX_TEXTURE_RT_MSAA_SHIFT);; - tc.m_width = m_ovr.m_rtSize.w; - tc.m_height = m_ovr.m_rtSize.h; - tc.m_sides = 0; - tc.m_depth = 0; - tc.m_numMips = 1; - tc.m_format = uint8_t(bgfx::TextureFormat::BGRA8); - tc.m_cubeMap = false; - tc.m_mem = NULL; - bx::write(&writer, tc); - - m_ovrRT.create(mem, tc.m_flags, 0); - release(mem); - - m_ovrFbo = m_msaaBackBufferFbo; - - GL_CHECK(glGenFramebuffers(1, &m_msaaBackBufferFbo) ); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) ); - - GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER - , GL_COLOR_ATTACHMENT0 - , GL_TEXTURE_2D - , m_ovrRT.m_id - , 0 - ) ); + const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_ovrFbo) ); + for (uint32_t ii = 0; ii < 2; ++ii) + { + // eye buffers need to be initialized only once during application lifetime + if (NULL == m_ovr.m_eyeBuffers[ii]) + { + m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii]; + m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples); + } + } - ovrGLTexture texture; - texture.OGL.Header.API = ovrRenderAPI_OpenGL; - texture.OGL.Header.TextureSize = m_ovr.m_rtSize; - texture.OGL.TexId = m_ovrRT.m_id; - m_ovr.postReset(texture.Texture); + // recreate mirror texture + m_ovr.m_mirror = &m_ovrMirror; + m_ovr.m_mirror->create(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height); } } #endif // BGFX_CONFIG_USE_OVR @@ -2912,14 +2888,6 @@ namespace bgfx { namespace gl { #if BGFX_CONFIG_USE_OVR m_ovr.preReset(); - if (m_ovr.isEnabled() ) - { - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); - GL_CHECK(glDeleteFramebuffers(1, &m_msaaBackBufferFbo) ); - m_msaaBackBufferFbo = m_ovrFbo; - m_ovrFbo = 0; - m_ovrRT.destroy(); - } #endif // BGFX_CONFIG_USE_OVR } @@ -3343,8 +3311,10 @@ namespace bgfx { namespace gl const char* m_glslVersion; OVR m_ovr; - TextureGL m_ovrRT; - GLint m_ovrFbo; +#if BGFX_CONFIG_USE_OVR + OVRMirrorGL m_ovrMirror; + OVRBufferGL m_ovrBuffers[2]; +#endif // BGFX_CONFIG_USE_OVR }; RendererContextGL* s_renderGL; @@ -3363,6 +3333,219 @@ namespace bgfx { namespace gl s_renderGL = NULL; } +#if BGFX_CONFIG_USE_OVR + void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) + { + m_eyeFbo = 0; + m_eyeTexId = 0; + m_depthBuffer = 0; + m_msaaEyeFbo = 0; + m_msaaEyeTexId = 0; + m_msaaDepthBuffer = 0; + + ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session); + m_eyeTextureSize = ovr_GetFovTextureSize(_session, ovrEyeType(_eyeIdx), hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f); + + ovrTextureSwapChainDesc desc = {}; + desc.Type = ovrTexture_2D; + desc.ArraySize = 1; + desc.Width = m_eyeTextureSize.w; + desc.Height = m_eyeTextureSize.h; + desc.MipLevels = 1; + desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + desc.SampleCount = 1; + desc.StaticImage = ovrFalse; + + ovr_CreateTextureSwapChainGL(_session, &desc, &m_textureSwapChain); + + int textureCount = 0; + ovr_GetTextureSwapChainLength(_session, m_textureSwapChain, &textureCount); + + for (int j = 0; j < textureCount; ++j) + { + GLuint chainTexId; + ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, j, &chainTexId); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, chainTexId) ); + + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ); + } + + GL_CHECK(glGenFramebuffers(1, &m_eyeFbo) ); + + // create depth buffer + GL_CHECK(glGenTextures(1, &m_depthBuffer) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ); + + GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) ); + + // create MSAA buffers + if (_msaaSamples > 1) + { + GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo) ); + + // create color MSAA texture + GL_CHECK(glGenTextures(1, &m_msaaEyeTexId) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId) ); + + GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_RGBA, m_eyeTextureSize.w, m_eyeTextureSize.h, false) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) ); + + // create MSAA depth buffer + GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer) ); + + GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, m_eyeTextureSize.w, m_eyeTextureSize.h, false) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ); + + GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) ); + } + } + + void OVRBufferGL::render(const ovrSession& _session) + { + // set the current eye texture in swap chain + int curIndex; + ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex); + ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId); + + if (0 != m_msaaEyeFbo) + { + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer, 0) ); + } + else // MSAA disabled? render directly to eye buffer + { + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0) ); + } + GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h) ); + GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ); + } + + void OVRBufferGL::postRender(const ovrSession& /*_sesion*/) + { + if (0 != m_msaaEyeFbo && 0 != m_eyeTexId) + { + // blit the contents of MSAA FBO to the regular eye buffer "connected" to the HMD + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo)); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) ); + GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) ); + + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) ); + + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo)); + GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) ); + GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) ); + + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) ); + + GL_CHECK(glBlitFramebuffer(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h, + 0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h, GL_COLOR_BUFFER_BIT, GL_NEAREST) ); + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + } + } + + void OVRBufferGL::destroy(const ovrSession& _session) + { + GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo) ); + GL_CHECK(glDeleteTextures(1, &m_depthBuffer) ); + + ovr_DestroyTextureSwapChain(_session, m_textureSwapChain); + + if (0 != m_msaaEyeFbo) + { + GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) ); + m_msaaEyeFbo = 0; + } + + if (0 != m_msaaEyeTexId) + { + GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId)); + m_msaaEyeTexId = 0; + } + + if (0 != m_msaaDepthBuffer) + { + GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer)); + m_msaaDepthBuffer = 0; + } + } + + void OVRMirrorGL::create(const ovrSession& _session, int _width, int _height) + { + memset(&m_mirrorTextureDesc, 0, sizeof(m_mirrorTextureDesc) ); + m_mirrorTextureDesc.Width = _width; + m_mirrorTextureDesc.Height = _height; + m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + + ovr_CreateMirrorTextureGL(_session, &m_mirrorTextureDesc, &m_mirrorTexture); + + // Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes + if (!m_mirrorTexture) + return; + + // Configure the mirror read buffer + GLuint texId; + ovr_GetMirrorTextureBufferGL(_session, m_mirrorTexture, &texId); + GL_CHECK(glGenFramebuffers(1, &m_mirrorFBO) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO) ); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0) ); + GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); + BX_CHECK(false, "Could not initialize VR buffers!"); + } + } + + void OVRMirrorGL::destroy(const ovrSession& _session) + { + if (NULL != m_mirrorTexture) + { + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); + ovr_DestroyMirrorTexture(_session, m_mirrorTexture); + m_mirrorTexture = NULL; + } + } + + void OVRMirrorGL::blit(const ovrSession& /*_session*/) + { + if (NULL != m_mirrorTexture) + { + // Blit mirror texture to back buffer + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO) ); + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ); + GLint width = m_mirrorTextureDesc.Width; + GLint height = m_mirrorTextureDesc.Height; + GL_CHECK(glBlitFramebuffer(0, height, width, 0, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ); + } + } +#endif // BGFX_CONFIG_USE_OVR + const char* glslTypeName(GLuint _type) { #define GLSL_TYPE(_ty) case _ty: return #_ty @@ -3636,7 +3819,7 @@ namespace bgfx { namespace gl } m_numPredefined = 0; - m_numSamplers = 0; + m_numSamplers = 0; BX_TRACE("Uniforms (%d):", activeUniforms); for (int32_t ii = 0; ii < activeUniforms; ++ii) @@ -5428,7 +5611,7 @@ namespace bgfx { namespace gl _render->m_hmdInitialized = m_ovr.isInitialized(); - const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug(); + const bool hmdEnabled = m_ovr.isEnabled(); ViewState viewState(_render, hmdEnabled); uint16_t programIdx = invalidHandle; @@ -5478,12 +5661,13 @@ namespace bgfx { namespace gl m_occlusionQuery.resolve(_render); } + uint8_t eye = 0; + if (0 == (_render->m_debug&BGFX_DEBUG_IFH) ) { GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) ); bool viewRestart = false; - uint8_t eye = 0; uint8_t restartState = 0; viewState.m_rect = _render->m_rect[0]; @@ -5565,6 +5749,7 @@ namespace bgfx { namespace gl if (m_ovr.isEnabled() ) { m_ovr.getViewport(eye, &viewState.m_rect); + m_ovr.renderEyeStart(eye); } else { @@ -5584,7 +5769,7 @@ namespace bgfx { namespace gl } const Rect& scissorRect = _render->m_scissor[view]; - viewHasScissor = !scissorRect.isZero(); + viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : viewState.m_rect; GL_CHECK(glViewport(viewState.m_rect.m_x @@ -5666,7 +5851,7 @@ namespace bgfx { namespace gl const RenderCompute& compute = renderItem.compute; ProgramGL& program = m_program[key.m_program]; - GL_CHECK(glUseProgram(program.m_id) ); + GL_CHECK(glUseProgram(program.m_id) ); GLbitfield barrier = 0; for (uint32_t ii = 0; ii < BGFX_MAX_COMPUTE_BINDINGS; ++ii) |