From eec95aeef6ea0821581194595f52ada2d38118fe Mon Sep 17 00:00:00 2001 From: Matthew Endsley Date: Wed, 14 Sep 2016 17:08:14 -0700 Subject: [PATCH] Combine OVRBufferI and OVRMirrorI into a single interface Simplify the renderer interface for VR to separate the OVR implementation from the overall HMD foundation. Part of merging OpenVR back upstream. --- src/hmd_ovr.cpp | 39 ++--- src/hmd_ovr.h | 36 ++--- src/renderer_d3d11.cpp | 342 +++++++++++++++++++++-------------------- src/renderer_d3d11.h | 29 ++-- src/renderer_gl.cpp | 317 ++++++++++++++++++++------------------ src/renderer_gl.h | 34 ++-- 6 files changed, 399 insertions(+), 398 deletions(-) diff --git a/src/hmd_ovr.cpp b/src/hmd_ovr.cpp index b8765b4a9..ec25a9501 100644 --- a/src/hmd_ovr.cpp +++ b/src/hmd_ovr.cpp @@ -24,11 +24,10 @@ namespace bgfx OVR::OVR() : m_hmd(NULL) , m_enabled(false) - , m_mirror(NULL) + , m_render(NULL) , m_frameIndex(0) , m_sensorSampleTime(0) { - memset(m_eyeBuffers, 0, sizeof(m_eyeBuffers)); } OVR::~OVR() @@ -73,19 +72,10 @@ namespace bgfx { BX_CHECK(!m_enabled, "HMD not disabled."); - for (uint32_t ii = 0; ii < 2; ++ii) + if (NULL != m_render) { - if (NULL != m_eyeBuffers[ii]) - { - m_eyeBuffers[ii]->destroy(m_hmd); - m_eyeBuffers[ii] = NULL; - } - } - - if (NULL != m_mirror) - { - m_mirror->destroy(m_hmd); - m_mirror = NULL; + m_render->destroy(m_hmd); + m_render = NULL; } ovr_Destroy(m_hmd); @@ -97,13 +87,13 @@ namespace bgfx { _viewport->m_x = 0; _viewport->m_y = 0; - _viewport->m_width = m_eyeBuffers[_eye]->m_eyeTextureSize.w; - _viewport->m_height = m_eyeBuffers[_eye]->m_eyeTextureSize.h; + _viewport->m_width = m_render->m_eyeTextureSize[_eye].w; + _viewport->m_height = m_render->m_eyeTextureSize[_eye].h; } void OVR::renderEyeStart(uint8_t _eye) { - m_eyeBuffers[_eye]->render(m_hmd); + m_render->startEyeRender(m_hmd, _eye); } bool OVR::postReset() @@ -128,8 +118,7 @@ namespace bgfx if (m_enabled) { // on window resize this will recreate the mirror texture in ovrPostReset - m_mirror->destroy(m_hmd); - m_mirror = NULL; + m_render->preReset(m_hmd); m_enabled = false; } } @@ -154,8 +143,8 @@ namespace bgfx for (uint32_t ii = 0; ii < 2; ++ii) { - m_eyeBuffers[ii]->postRender(m_hmd); - result = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[ii]->m_textureSwapChain); + m_render->postRender(m_hmd, ii); + result = ovr_CommitTextureSwapChain(m_hmd, m_render->m_textureSwapChain[ii]); if (!OVR_SUCCESS(result) ) { return DeviceLost; @@ -177,11 +166,11 @@ namespace bgfx for (uint32_t ii = 0; ii < 2; ++ii) { - eyeLayer.ColorTexture[ii] = m_eyeBuffers[ii]->m_textureSwapChain; + eyeLayer.ColorTexture[ii] = m_render->m_textureSwapChain[ii]; eyeLayer.Viewport[ii].Pos.x = 0; eyeLayer.Viewport[ii].Pos.y = 0; - eyeLayer.Viewport[ii].Size.w = m_eyeBuffers[ii]->m_eyeTextureSize.w; - eyeLayer.Viewport[ii].Size.h = m_eyeBuffers[ii]->m_eyeTextureSize.h; + eyeLayer.Viewport[ii].Size.w = m_render->m_eyeTextureSize[ii].w; + eyeLayer.Viewport[ii].Size.h = m_render->m_eyeTextureSize[ii].h; eyeLayer.Fov[ii] = m_hmdDesc.DefaultEyeFov[ii]; eyeLayer.RenderPose[ii] = m_pose[ii]; eyeLayer.SensorSampleTime = m_sensorSampleTime; @@ -199,7 +188,7 @@ namespace bgfx // perform mirror texture blit right after the entire frame is submitted to HMD if (result != ovrSuccess_NotVisible) { - m_mirror->blit(m_hmd); + m_render->blitMirror(m_hmd); } m_hmdToEyeOffset[0] = m_erd[0].HmdToEyeOffset; diff --git a/src/hmd_ovr.h b/src/hmd_ovr.h index 675e711c0..9184713e0 100644 --- a/src/hmd_ovr.h +++ b/src/hmd_ovr.h @@ -27,30 +27,27 @@ namespace bgfx { - // single eye buffer - struct OVRBufferI + // render data for both eyes and mirrored output + struct BX_NO_VTABLE OVRRenderI { - virtual ~OVRBufferI() {}; - virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) = 0; + virtual ~OVRRenderI() = 0; + virtual void create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) = 0; virtual void destroy(const ovrSession& _session) = 0; - virtual void render(const ovrSession& _session) = 0; - virtual void postRender(const ovrSession& _session) = 0; - ovrSizei m_eyeTextureSize; - ovrTextureSwapChain m_textureSwapChain; - }; + virtual void preReset(const ovrSession& _session) = 0; + virtual void startEyeRender(const ovrSession& _session, int _eyeIdx) = 0; + virtual void postRender(const ovrSession& _session, int _eyeIdx) = 0; + virtual void blitMirror(const ovrSession& _session) = 0; - // mirrored window output - struct OVRMirrorI - { - virtual ~OVRMirrorI() {}; - virtual void create(const ovrSession& _session, int windowWidth, int windowHeight) = 0; - virtual void destroy(const ovrSession& _session) = 0; - virtual void blit(const ovrSession& _session) = 0; - - ovrMirrorTexture m_mirrorTexture; + ovrSizei m_eyeTextureSize[2]; + ovrTextureSwapChain m_textureSwapChain[2]; + ovrMirrorTexture m_mirrorTexture; ovrMirrorTextureDesc m_mirrorTextureDesc; }; + inline OVRRenderI::~OVRRenderI() + { + } + struct OVR { enum Enum @@ -93,8 +90,7 @@ namespace bgfx ovrPosef m_pose[2]; ovrVector3f m_hmdToEyeOffset[2]; ovrSizei m_hmdSize; - OVRBufferI *m_eyeBuffers[2]; - OVRMirrorI *m_mirror; + OVRRenderI *m_render; uint64_t m_frameIndex; double m_sensorSampleTime; bool m_enabled; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index f58487b4b..014a6d101 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -3152,19 +3152,8 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); - 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); - } - } - - // 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); + m_ovr.m_render = &m_ovrRender; + m_ovr.m_render->create(m_ovr.m_hmd, msaaSamples, m_resolution.m_width, m_resolution.m_height); } } #endif // BGFX_CONFIG_USE_OVR @@ -3566,8 +3555,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); OVR m_ovr; #if BGFX_CONFIG_USE_OVR - OVRMirrorD3D11 m_ovrMirror; - OVRBufferD3D11 m_ovrBuffers[2]; + OVRRenderD3D11 m_ovrRender; #endif // BGFX_CONFIG_USE_OVR }; @@ -3622,204 +3610,228 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } #if BGFX_CONFIG_USE_OVR - void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) + OVRRenderD3D11::OVRRenderD3D11() + { + m_mirrorTexture = NULL; + memset(m_textureSwapChain, 0, sizeof(m_textureSwapChain)); + } + + void OVRRenderD3D11::create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) { ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session); - m_eyeTextureSize = ovr_GetFovTextureSize(_session, (ovrEyeType)_eyeIdx, hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f); - m_msaaTexture = NULL; - m_msaaRtv = NULL; - m_msaaSv = NULL; - ovrTextureSwapChainDesc desc = {}; - desc.Type = ovrTexture_2D; - desc.ArraySize = 1; - desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; - desc.Width = m_eyeTextureSize.w; - desc.Height = m_eyeTextureSize.h; - desc.MipLevels = 1; - desc.SampleCount = 1; - desc.MiscFlags = ovrTextureMisc_DX_Typeless; - desc.BindFlags = ovrTextureBind_DX_RenderTarget; - desc.StaticImage = ovrFalse; - - ID3D11Device* device = s_renderD3D11->m_device; - - ovrResult result = ovr_CreateTextureSwapChainDX(_session, device, &desc, &m_textureSwapChain); - - if (!OVR_SUCCESS(result) ) + for (int eye = 0; eye < 2; ++eye) { - BX_CHECK(false, "Could not create D3D11 OVR swap texture"); + if (NULL == m_textureSwapChain[eye]) + { + m_eyeTextureSize[eye] = ovr_GetFovTextureSize(_session, (ovrEyeType)eye, hmdDesc.DefaultEyeFov[eye], 1.0f); + m_msaaTexture[eye] = NULL; + m_msaaRtv[eye] = NULL; + m_msaaSv[eye] = NULL; + + ovrTextureSwapChainDesc desc = {}; + desc.Type = ovrTexture_2D; + desc.ArraySize = 1; + desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + desc.Width = m_eyeTextureSize[eye].w; + desc.Height = m_eyeTextureSize[eye].h; + desc.MipLevels = 1; + desc.SampleCount = 1; + desc.MiscFlags = ovrTextureMisc_DX_Typeless; + desc.BindFlags = ovrTextureBind_DX_RenderTarget; + desc.StaticImage = ovrFalse; + + ID3D11Device* device = s_renderD3D11->m_device; + + ovrResult result = ovr_CreateTextureSwapChainDX(_session, device, &desc, &m_textureSwapChain[eye]); + + if (!OVR_SUCCESS(result) ) + { + BX_CHECK(false, "Could not create D3D11 OVR swap texture"); + } + + memset(m_eyeRtv[eye], 0, sizeof(m_eyeRtv[eye]) ); + int textureCount = 0; + ovr_GetTextureSwapChainLength(_session, m_textureSwapChain[eye], &textureCount); + + for (int ii = 0; ii < textureCount; ++ii) + { + ID3D11Texture2D* tex = NULL; + ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain[eye], ii, IID_PPV_ARGS(&tex) ); + D3D11_RENDER_TARGET_VIEW_DESC rtvd = {}; + rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + + ID3D11RenderTargetView* rtv; + DX_CHECK(device->CreateRenderTargetView(tex, &rtvd, &rtv) ); + m_eyeRtv[eye][ii] = rtv; + DX_RELEASE(tex, 1); + } + + // setup depth buffer + D3D11_TEXTURE2D_DESC dbDesc; + dbDesc.Width = m_eyeTextureSize[eye].w; + dbDesc.Height = m_eyeTextureSize[eye].h; + dbDesc.MipLevels = 1; + dbDesc.ArraySize = 1; + dbDesc.Format = DXGI_FORMAT_D32_FLOAT; + dbDesc.SampleDesc.Count = _msaaSamples; + dbDesc.SampleDesc.Quality = 0; + dbDesc.Usage = D3D11_USAGE_DEFAULT; + dbDesc.CPUAccessFlags = 0; + dbDesc.MiscFlags = 0; + dbDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + ID3D11Texture2D* tex; + DX_CHECK(device->CreateTexture2D(&dbDesc, NULL, &tex) ); + DX_CHECK(device->CreateDepthStencilView(tex, NULL, &m_depthBuffer[eye]) ); + DX_RELEASE(tex, 0); + + // create MSAA render target + if (_msaaSamples > 1) + { + D3D11_TEXTURE2D_DESC dsDesc; + dsDesc.Width = m_eyeTextureSize[eye].w; + dsDesc.Height = m_eyeTextureSize[eye].h; + dsDesc.MipLevels = 1; + dsDesc.ArraySize = 1; + dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dsDesc.SampleDesc.Count = _msaaSamples; + dsDesc.SampleDesc.Quality = 0; + dsDesc.Usage = D3D11_USAGE_DEFAULT; + dsDesc.CPUAccessFlags = 0; + dsDesc.MiscFlags = 0; + dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + + ID3D11Device* device = s_renderD3D11->m_device; + DX_CHECK(device->CreateTexture2D(&dsDesc, NULL, &m_msaaTexture[eye])); + DX_CHECK(device->CreateShaderResourceView(m_msaaTexture[eye], NULL, &m_msaaSv[eye])); + DX_CHECK(device->CreateRenderTargetView(m_msaaTexture[eye], NULL, &m_msaaRtv[eye])); + } + } } - memset(m_eyeRtv, 0, sizeof(m_eyeRtv) ); - int textureCount = 0; - ovr_GetTextureSwapChainLength(_session, m_textureSwapChain, &textureCount); - - for (int ii = 0; ii < textureCount; ++ii) + if (NULL == m_mirrorTexture) { - ID3D11Texture2D* tex = NULL; - ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, ii, IID_PPV_ARGS(&tex) ); - D3D11_RENDER_TARGET_VIEW_DESC rtvd = {}; - rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - - ID3D11RenderTargetView* rtv; - DX_CHECK(device->CreateRenderTargetView(tex, &rtvd, &rtv) ); - m_eyeRtv[ii] = rtv; - DX_RELEASE(tex, 1); - } - - // setup depth buffer - D3D11_TEXTURE2D_DESC dbDesc; - dbDesc.Width = m_eyeTextureSize.w; - dbDesc.Height = m_eyeTextureSize.h; - dbDesc.MipLevels = 1; - dbDesc.ArraySize = 1; - dbDesc.Format = DXGI_FORMAT_D32_FLOAT; - dbDesc.SampleDesc.Count = _msaaSamples; - dbDesc.SampleDesc.Quality = 0; - dbDesc.Usage = D3D11_USAGE_DEFAULT; - dbDesc.CPUAccessFlags = 0; - dbDesc.MiscFlags = 0; - dbDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - ID3D11Texture2D* tex; - DX_CHECK(device->CreateTexture2D(&dbDesc, NULL, &tex) ); - DX_CHECK(device->CreateDepthStencilView(tex, NULL, &m_depthBuffer) ); - DX_RELEASE(tex, 0); - - // create MSAA render target - if (_msaaSamples > 1) - { - D3D11_TEXTURE2D_DESC dsDesc; - dsDesc.Width = m_eyeTextureSize.w; - dsDesc.Height = m_eyeTextureSize.h; - dsDesc.MipLevels = 1; - dsDesc.ArraySize = 1; - dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - dsDesc.SampleDesc.Count = _msaaSamples; - dsDesc.SampleDesc.Quality = 0; - dsDesc.Usage = D3D11_USAGE_DEFAULT; - dsDesc.CPUAccessFlags = 0; - dsDesc.MiscFlags = 0; - dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - - ID3D11Device* device = s_renderD3D11->m_device; - DX_CHECK(device->CreateTexture2D(&dsDesc, NULL, &m_msaaTexture)); - DX_CHECK(device->CreateShaderResourceView(m_msaaTexture, NULL, &m_msaaSv)); - DX_CHECK(device->CreateRenderTargetView(m_msaaTexture, NULL, &m_msaaRtv)); + m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + m_mirrorTextureDesc.Width = _mirrorWidth; + m_mirrorTextureDesc.Height = _mirrorHeight; + ovrResult result = ovr_CreateMirrorTextureDX(_session, s_renderD3D11->m_device, &m_mirrorTextureDesc, &m_mirrorTexture); + BX_WARN(OVR_SUCCESS(result), "Could not create D3D11 OVR mirror texture"); + BX_UNUSED(result); } } - void OVRBufferD3D11::render(const ovrSession& _session) + void OVRRenderD3D11::startEyeRender(const ovrSession& _session, int _eyeIdx) { ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Important that alpha=0, if want pixels to be transparent, for manual layers // render to MSAA target - if (NULL != m_msaaTexture) + if (NULL != m_msaaTexture[_eyeIdx]) { - deviceCtx->OMSetRenderTargets(1, &m_msaaRtv, m_depthBuffer); - deviceCtx->ClearRenderTargetView(m_msaaRtv, black); - deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); + deviceCtx->OMSetRenderTargets(1, &m_msaaRtv[_eyeIdx], m_depthBuffer[_eyeIdx]); + deviceCtx->ClearRenderTargetView(m_msaaRtv[_eyeIdx], black); + deviceCtx->ClearDepthStencilView(m_depthBuffer[_eyeIdx], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); } else // MSAA disabled? render directly to eye buffer { int texIndex = 0; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex); + ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &texIndex); - deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer); - deviceCtx->ClearRenderTargetView(m_eyeRtv[texIndex], black); - deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); + deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[_eyeIdx][texIndex], m_depthBuffer[_eyeIdx]); + deviceCtx->ClearRenderTargetView(m_eyeRtv[_eyeIdx][texIndex], black); + deviceCtx->ClearDepthStencilView(m_depthBuffer[_eyeIdx], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); D3D11_VIEWPORT D3Dvp; D3Dvp.TopLeftX = 0; D3Dvp.TopLeftY = 0; - D3Dvp.Width = (FLOAT)m_eyeTextureSize.w; - D3Dvp.Height = (FLOAT)m_eyeTextureSize.h; + D3Dvp.Width = (FLOAT)m_eyeTextureSize[_eyeIdx].w; + D3Dvp.Height = (FLOAT)m_eyeTextureSize[_eyeIdx].h; D3Dvp.MinDepth = 0; D3Dvp.MaxDepth = 1; deviceCtx->RSSetViewports(1, &D3Dvp); } } - void OVRBufferD3D11::postRender(const ovrSession& _session) + void OVRRenderD3D11::postRender(const ovrSession& _session, int _eyeIdx) { - if (NULL != m_msaaTexture) + if (NULL != m_msaaTexture[_eyeIdx]) { ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; int destIndex = 0; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &destIndex); + ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &destIndex); ID3D11Resource* dstTex = NULL; - ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, destIndex, IID_PPV_ARGS(&dstTex)); - deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture, 0, DXGI_FORMAT_R8G8B8A8_UNORM); + ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain[_eyeIdx], destIndex, IID_PPV_ARGS(&dstTex)); + deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture[_eyeIdx], 0, DXGI_FORMAT_R8G8B8A8_UNORM); dstTex->Release(); } } - void OVRBufferD3D11::destroy(const ovrSession& _session) + void OVRRenderD3D11::destroy(const ovrSession& _session) { - for (uint32_t ii = 0; ii < BX_COUNTOF(m_eyeRtv); ++ii) + for (int eye = 0; eye < 2; ++eye) { - DX_RELEASE(m_eyeRtv[ii], 0); - } - - ovr_DestroyTextureSwapChain(_session, m_textureSwapChain); - m_depthBuffer->Release(); - - if (NULL != m_msaaTexture) - { - m_msaaTexture->Release(); - m_msaaTexture = NULL; - } - - if (NULL != m_msaaSv) - { - m_msaaSv->Release(); - m_msaaSv = NULL; - } - - if (NULL != m_msaaRtv) - { - m_msaaRtv->Release(); - m_msaaRtv = NULL; - } - } - - void OVRMirrorD3D11::create(const ovrSession& _session, int _width, int _height) - { - m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; - m_mirrorTextureDesc.Width = _width; - m_mirrorTextureDesc.Height = _height; - ovrResult result = ovr_CreateMirrorTextureDX(_session, s_renderD3D11->m_device, &m_mirrorTextureDesc, &m_mirrorTexture); - BX_WARN(OVR_SUCCESS(result), "Could not create D3D11 OVR mirror texture"); - BX_UNUSED(result); - } - - void OVRMirrorD3D11::destroy(const ovrSession& session) - { - if (NULL != m_mirrorTexture) + for (uint32_t ii = 0; ii < BX_COUNTOF(m_eyeRtv); ++ii) { - ovr_DestroyMirrorTexture(session, m_mirrorTexture); - m_mirrorTexture = NULL; + DX_RELEASE(m_eyeRtv[eye][ii], 0); + } + + ovr_DestroyTextureSwapChain(_session, m_textureSwapChain[eye]); + m_textureSwapChain[eye] = NULL; + m_depthBuffer[eye]->Release(); + + if (NULL != m_msaaTexture[eye]) + { + m_msaaTexture[eye]->Release(); + m_msaaTexture[eye] = NULL; + } + + if (NULL != m_msaaSv[eye]) + { + m_msaaSv[eye]->Release(); + m_msaaSv[eye] = NULL; + } + + if (NULL != m_msaaRtv[eye]) + { + m_msaaRtv[eye]->Release(); + m_msaaRtv[eye] = NULL; } } - void OVRMirrorD3D11::blit(const ovrSession& _session) + if (NULL != m_mirrorTexture) { - if (NULL != m_mirrorTexture) - { - ID3D11Texture2D* tex = NULL; - ovr_GetMirrorTextureBufferDX(_session, m_mirrorTexture, IID_PPV_ARGS(&tex) ); - ID3D11Texture2D* backBuffer; - DX_CHECK(s_renderD3D11->m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); - - s_renderD3D11->m_deviceCtx->CopyResource(backBuffer, tex); - DX_CHECK(s_renderD3D11->m_swapChain->Present(0, 0) ); - - DX_RELEASE(tex, 1); - DX_RELEASE(backBuffer, 0); - } + ovr_DestroyMirrorTexture(_session, m_mirrorTexture); + m_mirrorTexture = NULL; } + } + + void OVRRenderD3D11::blitMirror(const ovrSession& _session) + { + if (NULL != m_mirrorTexture) + { + ID3D11Texture2D* tex = NULL; + ovr_GetMirrorTextureBufferDX(_session, m_mirrorTexture, IID_PPV_ARGS(&tex) ); + ID3D11Texture2D* backBuffer; + DX_CHECK(s_renderD3D11->m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); + + s_renderD3D11->m_deviceCtx->CopyResource(backBuffer, tex); + DX_CHECK(s_renderD3D11->m_swapChain->Present(0, 0) ); + + DX_RELEASE(tex, 1); + DX_RELEASE(backBuffer, 0); + } + } + + void OVRRenderD3D11::preReset(const ovrSession& _session) + { + if (NULL != m_mirrorTexture) + { + ovr_DestroyMirrorTexture(_session, m_mirrorTexture); + m_mirrorTexture = NULL; + } + } + #endif // BGFX_CONFIG_USE_OVR struct UavFormat diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 5d8614a73..5cf52c710 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -61,26 +61,23 @@ BX_PRAGMA_DIAGNOSTIC_POP() namespace bgfx { namespace d3d11 { #if BGFX_CONFIG_USE_OVR - struct OVRBufferD3D11 : public OVRBufferI + struct OVRRenderD3D11 : public OVRRenderI { - virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE; - virtual void destroy(const ovrSession& _session) BX_OVERRIDE; - virtual void render(const ovrSession& _session) BX_OVERRIDE; - virtual void postRender(const ovrSession& _session) BX_OVERRIDE; + OVRRenderD3D11(); + virtual void create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight); + virtual void destroy(const ovrSession& _session); + virtual void preReset(const ovrSession& _session); + virtual void startEyeRender(const ovrSession& _session, int _eyeIdx); + virtual void postRender(const ovrSession& _session, int _eyeIdx); + virtual void blitMirror(const ovrSession& _session); - ID3D11RenderTargetView* m_eyeRtv[4]; - ID3D11DepthStencilView* m_depthBuffer; - ID3D11Texture2D* m_msaaTexture; - ID3D11ShaderResourceView* m_msaaSv; - ID3D11RenderTargetView* m_msaaRtv; + ID3D11RenderTargetView* m_eyeRtv[2][4]; + ID3D11DepthStencilView* m_depthBuffer[2]; + ID3D11Texture2D* m_msaaTexture[2]; + ID3D11ShaderResourceView* m_msaaSv[2]; + ID3D11RenderTargetView* m_msaaRtv[2]; }; - struct OVRMirrorD3D11 : public OVRMirrorI - { - virtual void create(const ovrSession& _session, int _width, int _height) BX_OVERRIDE; - virtual void destroy(const ovrSession& session) BX_OVERRIDE; - virtual void blit(const ovrSession& session) BX_OVERRIDE; - }; #endif // BGFX_CONFIG_USE_OVR struct BufferD3D11 diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index ad5fd6d78..a5cc47261 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2961,19 +2961,8 @@ namespace bgfx { namespace gl { const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); - 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); - } - } - - // 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); + m_ovr.m_render = &m_ovrRender; + m_ovr.m_render->create(m_ovr.m_hmd, msaaSamples, m_resolution.m_width, m_resolution.m_height); } } #endif // BGFX_CONFIG_USE_OVR @@ -3407,8 +3396,7 @@ namespace bgfx { namespace gl OVR m_ovr; #if BGFX_CONFIG_USE_OVR - OVRMirrorGL m_ovrMirror; - OVRBufferGL m_ovrBuffers[2]; + OVRRenderGL m_ovrRender; #endif // BGFX_CONFIG_USE_OVR }; @@ -3429,194 +3417,207 @@ namespace bgfx { namespace gl } #if BGFX_CONFIG_USE_OVR - void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) + OVRRenderGL::OVRRenderGL() { - m_eyeFbo = 0; - m_eyeTexId = 0; - m_depthBuffer = 0; - m_msaaEyeFbo = 0; - m_msaaEyeTexId = 0; - m_msaaDepthBuffer = 0; + memset(&m_eyeFbo, 0, sizeof(m_eyeFbo)); + m_mirrorFBO = 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) + void OVRRenderGL::create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) + { + for (int eye = 0; eye < 2; ++eye) { - GLuint chainTexId; - ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, j, &chainTexId); - GL_CHECK(glBindTexture(GL_TEXTURE_2D, chainTexId) ); + if (NULL == m_textureSwapChain[eye]) + { + m_eyeFbo[eye] = 0; + m_eyeTexId[eye] = 0; + m_depthBuffer[eye] = 0; + m_msaaEyeFbo[eye] = 0; + m_msaaEyeTexId[eye] = 0; + m_msaaDepthBuffer[eye] = 0; - 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) ); + ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session); + m_eyeTextureSize[eye] = ovr_GetFovTextureSize(_session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1.0f); + + ovrTextureSwapChainDesc desc = {}; + desc.Type = ovrTexture_2D; + desc.ArraySize = 1; + desc.Width = m_eyeTextureSize[eye].w; + desc.Height = m_eyeTextureSize[eye].h; + desc.MipLevels = 1; + desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + desc.SampleCount = 1; + desc.StaticImage = ovrFalse; + + ovr_CreateTextureSwapChainGL(_session, &desc, &m_textureSwapChain[eye]); + + int textureCount = 0; + ovr_GetTextureSwapChainLength(_session, m_textureSwapChain[eye], &textureCount); + + for (int j = 0; j < textureCount; ++j) + { + GLuint chainTexId; + ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain[eye], 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[eye]) ); + + // create depth buffer + GL_CHECK(glGenTextures(1, &m_depthBuffer[eye]) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer[eye]) ); + 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[eye].w, m_eyeTextureSize[eye].h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) ); + + // create MSAA buffers + if (_msaaSamples > 1) + { + GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo[eye]) ); + + // create color MSAA texture + GL_CHECK(glGenTextures(1, &m_msaaEyeTexId[eye]) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[eye]) ); + + GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_RGBA, m_eyeTextureSize[eye].w, m_eyeTextureSize[eye].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[eye]) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer[eye]) ); + + GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, m_eyeTextureSize[eye].w, m_eyeTextureSize[eye].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) ); + } + } } - 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) + if (NULL == m_mirrorTexture) { - GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo) ); + memset(&m_mirrorTextureDesc, 0, sizeof(m_mirrorTextureDesc) ); + m_mirrorTextureDesc.Width = _mirrorWidth; + m_mirrorTextureDesc.Height = _mirrorHeight; + m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; - // create color MSAA texture - GL_CHECK(glGenTextures(1, &m_msaaEyeTexId) ); - GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId) ); + ovr_CreateMirrorTextureGL(_session, &m_mirrorTextureDesc, &m_mirrorTexture); - 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) ); + // Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes + if (!m_mirrorTexture) + return; - // create MSAA depth buffer - GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer) ); - GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer) ); + // 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) ); - 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) ); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); + BX_CHECK(false, "Could not initialize VR buffers!"); + } } } - void OVRBufferGL::render(const ovrSession& _session) + void OVRRenderGL::startEyeRender(const ovrSession& _session, int _eyeIdx) { // set the current eye texture in swap chain int curIndex; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex); - ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId); + ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &curIndex); + ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain[_eyeIdx], curIndex, &m_eyeTexId[_eyeIdx]); 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) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo[_eyeIdx]) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[_eyeIdx], 0) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer[_eyeIdx], 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(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo[_eyeIdx]) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[_eyeIdx], 0) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer[_eyeIdx], 0) ); } - GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h) ); + GL_CHECK(glViewport(0, 0, m_eyeTextureSize[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h) ); GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ); } - void OVRBufferGL::postRender(const ovrSession& /*_sesion*/) + void OVRRenderGL::postRender(const ovrSession& /*_sesion*/, int _eyeIdx) { - if (0 != m_msaaEyeFbo && 0 != m_eyeTexId) + if (0 != m_msaaEyeFbo[_eyeIdx] && 0 != m_eyeTexId[_eyeIdx]) { // 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(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo[_eyeIdx])); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[_eyeIdx], 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(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo[_eyeIdx])); + GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[_eyeIdx], 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(glBlitFramebuffer(0, 0, m_eyeTextureSize[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h, + 0, 0, m_eyeTextureSize[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h, GL_COLOR_BUFFER_BIT, GL_NEAREST) ); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); } } - void OVRBufferGL::destroy(const ovrSession& _session) + void OVRRenderGL::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) + for (int eye = 0; eye < 2; ++eye) { - GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) ); - m_msaaEyeFbo = 0; + GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo[eye]) ); + GL_CHECK(glDeleteTextures(1, &m_depthBuffer[eye]) ); + + ovr_DestroyTextureSwapChain(_session, m_textureSwapChain[eye]); + m_textureSwapChain[eye] = NULL; + + if (0 != m_msaaEyeFbo[eye]) + { + GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo[eye]) ); + m_msaaEyeFbo[eye] = 0; + } + + if (0 != m_msaaEyeTexId[eye]) + { + GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId[eye])); + m_msaaEyeTexId[eye] = 0; + } + + if (0 != m_msaaDepthBuffer[eye]) + { + GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer[eye])); + m_msaaDepthBuffer[eye] = 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) ); @@ -3625,7 +3626,7 @@ namespace bgfx { namespace gl } } - void OVRMirrorGL::blit(const ovrSession& /*_session*/) + void OVRRenderGL::blitMirror(const ovrSession& /*_session*/) { if (NULL != m_mirrorTexture) { @@ -3638,6 +3639,16 @@ namespace bgfx { namespace gl GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ); } } + + void OVRRenderGL::preReset(const ovrSession& _session) + { + if (NULL != m_mirrorTexture) + { + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); + ovr_DestroyMirrorTexture(_session, m_mirrorTexture); + m_mirrorTexture = NULL; + } + } #endif // BGFX_CONFIG_USE_OVR const char* glslTypeName(GLuint _type) diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 9227d0e00..a4f0e6fdc 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -951,29 +951,25 @@ namespace bgfx namespace bgfx { namespace gl { #if BGFX_CONFIG_USE_OVR - struct OVRBufferGL : public OVRBufferI + struct OVRRenderGL : public OVRRenderI { - virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE; - virtual void destroy(const ovrSession& _session) BX_OVERRIDE; - virtual void render(const ovrSession& _session) BX_OVERRIDE; - virtual void postRender(const ovrSession& _sesion) BX_OVERRIDE; - - GLuint m_eyeFbo; - GLuint m_eyeTexId; - GLuint m_depthBuffer; - GLuint m_msaaEyeFbo; - GLuint m_msaaEyeTexId; - GLuint m_msaaDepthBuffer; - }; - - struct OVRMirrorGL : public OVRMirrorI - { - virtual void create(const ovrSession& _session, int _width, int _height) BX_OVERRIDE; - virtual void destroy(const ovrSession& _session) BX_OVERRIDE; - virtual void blit(const ovrSession& _session) BX_OVERRIDE; + OVRRenderGL(); + virtual void create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight); + virtual void destroy(const ovrSession& _session); + virtual void preReset(const ovrSession& _session); + virtual void startEyeRender(const ovrSession& _session, int _eyeIdx); + virtual void postRender(const ovrSession& _session, int _eyeIdx); + virtual void blitMirror(const ovrSession& _session); + GLuint m_eyeFbo[2]; + GLuint m_eyeTexId[2]; + GLuint m_depthBuffer[2]; + GLuint m_msaaEyeFbo[2]; + GLuint m_msaaEyeTexId[2]; + GLuint m_msaaDepthBuffer[2]; GLuint m_mirrorFBO; }; + #endif // BGFX_CONFIG_USE_OVR void dumpExtensions(const char* _extensions);