From d9dd4bceb55dadb6aadda4c5d3898c1ef8992480 Mon Sep 17 00:00:00 2001 From: Matthew Endsley Date: Thu, 15 Sep 2016 13:54:34 -0700 Subject: [PATCH] Add platform agnostic bgfx::VR for renderers to interface The new platform agnositic class bgfx::VR manages the functionality that is shared across the various VR platforms. The individual platform renderers no longer need to interface with the internal VR tpyes (OVRRenderI) directly This greatly simplifies the OVR object's surface area which is now provided by the VRImplI interface. bgfx::VR now manages core lifecycle issues of the headset. The notable renderer API changes are the separation of sensor sampling and rendering. We need these separate so we can control the timing (later commit) of camera sampling with finer granularity than at the start of the video frame. --- src/hmd.cpp | 205 +++++++++++++++++++++ src/hmd.h | 102 ++++++++++ src/hmd_ovr.cpp | 323 +++++++++++++------------------- src/hmd_ovr.h | 168 +++-------------- src/renderer_d3d11.cpp | 292 ++++++++++++++++------------- src/renderer_d3d11.h | 21 +-- src/renderer_gl.cpp | 409 ++++++++++++++++++++++------------------- src/renderer_gl.h | 24 +-- 8 files changed, 845 insertions(+), 699 deletions(-) create mode 100644 src/hmd.cpp create mode 100644 src/hmd.h diff --git a/src/hmd.cpp b/src/hmd.cpp new file mode 100644 index 000000000..6361d8b12 --- /dev/null +++ b/src/hmd.cpp @@ -0,0 +1,205 @@ +/* + * Copyright 2011-2016 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "hmd.h" + +namespace bgfx +{ + VR::VR() + : m_framesUntilReconnect(0) + , m_enabled(false) + { + } + + void VR::init(VRImplI* _impl) + { + if (!_impl) + { + return; + } + + if (!_impl->init()) + { + return; + } + + m_impl = _impl; + m_impl->connect(&m_desc); + if (!m_impl->isConnected()) + { + connectFailed(); + return; + } + + m_hmdSize.m_w = m_desc.m_eyeSize[0].m_w + m_desc.m_eyeSize[1].m_w; + m_hmdSize.m_h = bx::uint32_max(m_desc.m_eyeSize[0].m_h, m_desc.m_eyeSize[1].m_h); + } + + void VR::shutdown() + { + if (!m_impl) + { + return; + } + + m_impl->destroySwapChain(); + if (m_impl->isConnected()) + { + m_impl->disconnect(); + } + + m_impl->shutdown(); + m_impl = NULL; + m_enabled = false; + } + + void VR::renderEyeStart(uint8_t _eye, Rect* _viewport) + { + BX_CHECK(m_enabled, "VR::renderEyeStart called while not enabled - render usage error"); + + _viewport->m_x = 0; + _viewport->m_y = 0; + _viewport->m_width = m_desc.m_eyeSize[_eye].m_w; + _viewport->m_height = m_desc.m_eyeSize[_eye].m_h; + + m_impl->renderEyeStart(m_desc, _eye); + } + + void VR::recenter() + { + if (m_impl) + { + m_impl->recenter(); + } + } + + void VR::preReset() + { + if (m_impl) + { + m_impl->destroyMirror(); + } + + m_enabled = false; + } + + void VR::postReset(int _msaaSamples, int _mirrorWidth, int _mirrorHeight) + { + if (m_impl && m_impl->createSwapChain(m_desc, _msaaSamples, _mirrorWidth, _mirrorHeight)) + { + m_enabled = true; + } + } + + void VR::flip() + { + if (!m_impl || !m_enabled) + { + return; + } + else if (!m_impl->isConnected() && !tryReconnect()) + { + return; + } + + if (!m_impl->submitSwapChain(m_desc)) + { + m_impl->destroySwapChain(); + m_impl->disconnect(); + return; + } + } + + void VR::swap(HMD& _hmd) + { + _hmd.flags = BGFX_HMD_NONE; + + if (!m_impl) + { + return; + } + + _hmd.flags = BGFX_HMD_DEVICE_RESOLUTION; + _hmd.deviceWidth = m_desc.m_deviceSize.m_w; + _hmd.deviceHeight = m_desc.m_deviceSize.m_h; + _hmd.width = m_hmdSize.m_w; + _hmd.height = m_hmdSize.m_h; + + if (!m_impl->updateTracking(_hmd)) + { + m_impl->destroySwapChain(); + m_impl->disconnect(); + } + + if (!m_impl->isConnected()) + { + return; + } + + for (int eye = 0; eye < 2; ++eye) + { + _hmd.eye[eye].fov[0] = m_desc.m_eyeFov[eye].m_up; + _hmd.eye[eye].fov[1] = m_desc.m_eyeFov[eye].m_down; + _hmd.eye[eye].fov[2] = m_desc.m_eyeFov[eye].m_left; + _hmd.eye[eye].fov[3] = m_desc.m_eyeFov[eye].m_right; + } + + m_impl->updateInput(_hmd); + if (m_enabled) + { + _hmd.flags |= BGFX_HMD_RENDERING; + } + } + + bool VR::tryReconnect() + { + if (!m_impl) + { + return false; + } + + BX_CHECK(!m_impl->isConnected(), "VR::tryReconnect called when already connected. Usage error"); + + --m_framesUntilReconnect; + if (m_framesUntilReconnect > 0) + { + return false; + } + + m_framesUntilReconnect = 90; + m_impl->connect(&m_desc); + if (!m_impl->isConnected()) + { + connectFailed(); + return false; + } + + m_hmdSize.m_w = m_desc.m_eyeSize[0].m_w + m_desc.m_eyeSize[1].m_w; + m_hmdSize.m_h = bx::uint32_max(m_desc.m_eyeSize[0].m_h, m_desc.m_eyeSize[1].m_h); + return true; + } + + void VR::connectFailed() + { + // sane defaults + m_desc.m_deviceSize.m_w = 2160; + m_desc.m_deviceSize.m_h = 1200; + m_desc.m_deviceType = 0; + m_desc.m_refreshRate = 90.0f; + m_desc.m_neckOffset[0] = 0.0805f; + m_desc.m_neckOffset[1] = 0.075f; + + for (int eye = 0; eye < 2; ++eye) + { + m_desc.m_eyeFov[eye].m_up = 1.32928634f; + m_desc.m_eyeFov[eye].m_down = 1.32928634f; + } + m_desc.m_eyeFov[0].m_left = 1.05865765f; + m_desc.m_eyeFov[0].m_right = 1.09236801f; + m_desc.m_eyeFov[1].m_left = 1.09236801f; + m_desc.m_eyeFov[1].m_right = 1.05865765f; + } + +} // namesapce bgfx diff --git a/src/hmd.h b/src/hmd.h new file mode 100644 index 000000000..5b2813f92 --- /dev/null +++ b/src/hmd.h @@ -0,0 +1,102 @@ +/* + * Copyright 2011-2016 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#ifndef BGFX_HMD_H_HEADER_GUARD +#define BGFX_HMD_H_HEADER_GUARD + +#include "bgfx_p.h" + +namespace bgfx +{ + struct VRSize + { + uint32_t m_w; + uint32_t m_h; + }; + + struct VRFovTan + { + float m_up; + float m_down; + float m_left; + float m_right; + }; + + struct VRDesc + { + uint64_t m_adapterLuid; + uint32_t m_deviceType; + float m_refreshRate; + VRSize m_deviceSize; + VRSize m_eyeSize[2]; + VRFovTan m_eyeFov[2]; + float m_neckOffset[2]; + }; + + struct BX_NO_VTABLE VRImplI + { + virtual ~VRImplI() = 0; + + virtual bool init() = 0; + virtual void shutdown() = 0; + virtual void connect(VRDesc* _desc) = 0; + virtual void disconnect() = 0; + virtual bool isConnected() const = 0; + + virtual bool updateTracking(HMD& _hmd) = 0; + virtual void updateInput(HMD& _hmd) = 0; + virtual void recenter() = 0; + + virtual bool createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight); + virtual void destroySwapChain() = 0; + virtual void destroyMirror() = 0; + virtual void renderEyeStart(const VRDesc& _desc, uint8_t _eye) = 0; + virtual bool submitSwapChain(const VRDesc& _desc) = 0; + }; + + inline VRImplI::~VRImplI() + { + } + + class VR + { + public: + VR(); + + void init(VRImplI* _impl); + void shutdown(); + + bool isInitialized() const + { + return NULL != m_impl; + } + + bool isEnabled() const + { + return m_enabled; + } + + void renderEyeStart(uint8_t _eye, Rect* _viewport); + void recenter(); + + void preReset(); + void postReset(int _msaaSamples, int _mirrorWidth, int _mirrorHeight); + void flip(); + void swap(HMD& _hmd); + + private: + bool tryReconnect(); + void connectFailed(); + + VRDesc m_desc; + VRSize m_hmdSize; + VRImplI* m_impl; + uint32_t m_framesUntilReconnect; + bool m_enabled; + }; + +} // namespace bgfx + +#endif // BGFX_HMD_H_HEADER_GUARD diff --git a/src/hmd_ovr.cpp b/src/hmd_ovr.cpp index ec25a9501..960db032c 100644 --- a/src/hmd_ovr.cpp +++ b/src/hmd_ovr.cpp @@ -3,10 +3,12 @@ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause */ -#include "hmd_ovr.h" +#include "bgfx_p.h" #if BGFX_CONFIG_USE_OVR +#include "hmd_ovr.h" + namespace bgfx { #define _OVR_CHECK(_call) \ @@ -21,236 +23,159 @@ namespace bgfx # define OVR_CHECK(_call) _call #endif // BGFX_CONFIG_DEBUG - OVR::OVR() - : m_hmd(NULL) - , m_enabled(false) - , m_render(NULL) - , m_frameIndex(0) - , m_sensorSampleTime(0) + VRImplOVR::VRImplOVR() + : m_session(NULL) { } - OVR::~OVR() + VRImplOVR::~VRImplOVR() { - BX_CHECK(NULL == m_hmd, "OVR not shutdown properly."); + BX_CHECK(NULL == m_session, "OVR not shutdown properly."); } - void OVR::init() + bool VRImplOVR::init() { - ovrResult result = ovr_Initialize(NULL); - - if (result != ovrSuccess) - { - BX_TRACE("Unable to create OVR device."); - return; - } - - ovrGraphicsLuid luid; - result = ovr_Create(&m_hmd, &luid); - if (result != ovrSuccess) - { - BX_TRACE("Unable to create OVR device."); - return; - } - - m_hmdDesc = ovr_GetHmdDesc(m_hmd); - - BX_TRACE("HMD: %s, %s, firmware: %d.%d" - , m_hmdDesc.ProductName - , m_hmdDesc.Manufacturer - , m_hmdDesc.FirmwareMajor - , m_hmdDesc.FirmwareMinor - ); - - ovrSizei sizeL = ovr_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmdDesc.DefaultEyeFov[0], 1.0f); - ovrSizei sizeR = ovr_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmdDesc.DefaultEyeFov[1], 1.0f); - m_hmdSize.w = sizeL.w + sizeR.w; - m_hmdSize.h = bx::uint32_max(sizeL.h, sizeR.h); - } - - void OVR::shutdown() - { - BX_CHECK(!m_enabled, "HMD not disabled."); - - if (NULL != m_render) - { - m_render->destroy(m_hmd); - m_render = NULL; - } - - ovr_Destroy(m_hmd); - m_hmd = NULL; - ovr_Shutdown(); - } - - void OVR::getViewport(uint8_t _eye, Rect* _viewport) - { - _viewport->m_x = 0; - _viewport->m_y = 0; - _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_render->startEyeRender(m_hmd, _eye); - } - - bool OVR::postReset() - { - if (NULL == m_hmd) + ovrResult initialized = ovr_Initialize(NULL); + if (!OVR_SUCCESS(initialized)) { + BX_TRACE("Unable to initialize OVR runtime."); return false; } - for (uint32_t ii = 0; ii < 2; ++ii) - { - m_erd[ii] = ovr_GetRenderDesc(m_hmd, ovrEyeType(ii), m_hmdDesc.DefaultEyeFov[ii]); - } - - m_enabled = true; - return true; } - void OVR::preReset() + void VRImplOVR::shutdown() { - if (m_enabled) + ovr_Shutdown(); + } + + void VRImplOVR::connect(VRDesc* _desc) + { + ovrGraphicsLuid luid; + ovrResult result = ovr_Create(&m_session, &luid); + if (!OVR_SUCCESS(result)) { - // on window resize this will recreate the mirror texture in ovrPostReset - m_render->preReset(m_hmd); - m_enabled = false; + BX_TRACE("Failed to create OVR device."); + return; + } + + BX_STATIC_ASSERT(sizeof(_desc->m_adapterLuid) >= sizeof(luid)); + memcpy(&_desc->m_adapterLuid, &luid, sizeof(luid)); + + ovrHmdDesc hmdDesc = ovr_GetHmdDesc(m_session); + _desc->m_deviceType = hmdDesc.Type; + _desc->m_refreshRate = hmdDesc.DisplayRefreshRate; + _desc->m_deviceSize.m_w = hmdDesc.Resolution.w; + _desc->m_deviceSize.m_h = hmdDesc.Resolution.h; + + BX_TRACE("OVR HMD: %s, %s, firmware: %d.%d" + , hmdDesc.ProductName + , hmdDesc.Manufacturer + , hmdDesc.FirmwareMajor + , hmdDesc.FirmwareMinor + ); + + ovrSizei eyeSize[2] = + { + ovr_GetFovTextureSize(m_session, ovrEye_Left, hmdDesc.DefaultEyeFov[0], 1.0f), + ovr_GetFovTextureSize(m_session, ovrEye_Right, hmdDesc.DefaultEyeFov[0], 1.0f), + }; + + for (int eye = 0; eye < 2; ++eye) + { + BX_STATIC_ASSERT(sizeof(_desc->m_eyeFov[eye]) == sizeof(hmdDesc.DefaultEyeFov[eye])); + memcpy(&_desc->m_eyeFov[eye], &hmdDesc.DefaultEyeFov[eye], sizeof(_desc->m_eyeFov[eye])); + _desc->m_eyeSize[eye].m_w = eyeSize[eye].w; + _desc->m_eyeSize[eye].m_h = eyeSize[eye].h; + } + + float neckOffset[2] = {OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL}; + ovr_GetFloatArray(m_session, OVR_KEY_NECK_TO_EYE_DISTANCE, neckOffset, 2); + _desc->m_neckOffset[0] = neckOffset[0]; + _desc->m_neckOffset[1] = neckOffset[1]; + + // build constant layer settings + m_renderLayer.Header.Type = ovrLayerType_EyeFov; + m_renderLayer.Header.Flags = 0; + for (int eye = 0; eye < 2; ++eye) + { + m_renderLayer.Fov[eye] = hmdDesc.DefaultEyeFov[eye]; + m_renderLayer.Viewport[eye].Pos.x = 0; + m_renderLayer.Viewport[eye].Pos.y = 0; + m_renderLayer.Viewport[eye].Size = eyeSize[eye]; + } + + m_viewScale.HmdSpaceToWorldScaleInMeters = 1.0f; + for (int eye = 0; eye < 2; ++eye) + { + ovrEyeRenderDesc erd = ovr_GetRenderDesc(m_session, static_cast(eye), hmdDesc.DefaultEyeFov[eye]); + m_viewScale.HmdToEyeOffset[eye] = erd.HmdToEyeOffset; + m_eyeFov[eye] = erd.Fov; + m_pixelsPerTanAngleAtCenter[eye] = erd.PixelsPerTanAngleAtCenter; } } - OVR::Enum OVR::swap(HMD& _hmd, bool originBottomLeft) + void VRImplOVR::disconnect() { - _hmd.flags = BGFX_HMD_NONE; - - if (NULL != m_hmd) + if (NULL != m_session) { - _hmd.flags |= BGFX_HMD_DEVICE_RESOLUTION; - _hmd.deviceWidth = m_hmdDesc.Resolution.w; - _hmd.deviceHeight = m_hmdDesc.Resolution.h; + ovr_Destroy(m_session); + m_session = NULL; + } + } + + bool VRImplOVR::updateTracking(HMD& _hmd) + { + if (NULL == m_session) + { + return false; } - if (!m_enabled) - { - return NotEnabled; - } + ovr_GetEyePoses(m_session, 0, ovrTrue, m_viewScale.HmdToEyeOffset, m_renderLayer.RenderPose, &m_renderLayer.SensorSampleTime); - ovrResult result; - - for (uint32_t ii = 0; ii < 2; ++ii) + for (int eye = 0; eye < 2; ++eye) { - m_render->postRender(m_hmd, ii); - result = ovr_CommitTextureSwapChain(m_hmd, m_render->m_textureSwapChain[ii]); - if (!OVR_SUCCESS(result) ) + const ovrPosef& pose = m_renderLayer.RenderPose[eye]; + HMD::Eye& hmdEye = _hmd.eye[eye]; + + hmdEye.rotation[0] = pose.Orientation.x; + hmdEye.rotation[1] = pose.Orientation.y; + hmdEye.rotation[2] = pose.Orientation.z; + hmdEye.rotation[3] = pose.Orientation.w; + hmdEye.translation[0] = pose.Position.x; + hmdEye.translation[1] = pose.Position.y; + hmdEye.translation[2] = pose.Position.z; + hmdEye.viewOffset[0] = -m_viewScale.HmdToEyeOffset[eye].x; + hmdEye.viewOffset[1] = -m_viewScale.HmdToEyeOffset[eye].y; + hmdEye.viewOffset[2] = -m_viewScale.HmdToEyeOffset[eye].z; + + hmdEye.pixelsPerTanAngle[0] = m_pixelsPerTanAngleAtCenter[eye].x; + hmdEye.pixelsPerTanAngle[1] = m_pixelsPerTanAngleAtCenter[eye].y; + + ovrMatrix4f projection = ovrMatrix4f_Projection(m_eyeFov[eye], 0.1f, 1000.0f, ovrProjection_LeftHanded); + for (uint32_t ii = 0; ii < 4; ++ii) { - return DeviceLost; - } - } - - _hmd.flags |= BGFX_HMD_RENDERING; - - // finish frame for current eye - ovrViewScaleDesc viewScaleDesc; - viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; - viewScaleDesc.HmdToEyeOffset[0] = m_hmdToEyeOffset[0]; - viewScaleDesc.HmdToEyeOffset[1] = m_hmdToEyeOffset[1]; - - // create the main eye layer - ovrLayerEyeFov eyeLayer; - eyeLayer.Header.Type = ovrLayerType_EyeFov; - eyeLayer.Header.Flags = originBottomLeft ? ovrLayerFlag_TextureOriginAtBottomLeft : 0; - - for (uint32_t ii = 0; ii < 2; ++ii) - { - 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_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; - } - - // append all the layers to global list - ovrLayerHeader* layerList = &eyeLayer.Header; - - result = ovr_SubmitFrame(m_hmd, m_frameIndex, NULL, &layerList, 1); - if (!OVR_SUCCESS(result) ) - { - return DeviceLost; - } - - // perform mirror texture blit right after the entire frame is submitted to HMD - if (result != ovrSuccess_NotVisible) - { - m_render->blitMirror(m_hmd); - } - - m_hmdToEyeOffset[0] = m_erd[0].HmdToEyeOffset; - m_hmdToEyeOffset[1] = m_erd[1].HmdToEyeOffset; - - ovr_GetEyePoses(m_hmd, m_frameIndex, ovrTrue, m_hmdToEyeOffset, m_pose, &m_sensorSampleTime); - - getEyePose(_hmd); - - return Success; - } - - void OVR::recenter() - { - if (NULL != m_hmd) - { - OVR_CHECK(ovr_RecenterTrackingOrigin(m_hmd) ); - } - } - - void OVR::getEyePose(HMD& _hmd) - { - if (NULL != m_hmd) - { - for (uint32_t ii = 0; ii < 2; ++ii) - { - const ovrPosef& pose = m_pose[ii]; - HMD::Eye& eye = _hmd.eye[ii]; - eye.rotation[0] = pose.Orientation.x; - eye.rotation[1] = pose.Orientation.y; - eye.rotation[2] = pose.Orientation.z; - eye.rotation[3] = pose.Orientation.w; - eye.translation[0] = pose.Position.x; - eye.translation[1] = pose.Position.y; - eye.translation[2] = pose.Position.z; - - const ovrEyeRenderDesc& erd = m_erd[ii]; - eye.fov[0] = erd.Fov.UpTan; - eye.fov[1] = erd.Fov.DownTan; - eye.fov[2] = erd.Fov.LeftTan; - eye.fov[3] = erd.Fov.RightTan; - - ovrMatrix4f eyeProj = ovrMatrix4f_Projection(m_erd[ii].Fov, 0.01f, 1000.0f, ovrProjection_LeftHanded); for (uint32_t jj = 0; jj < 4; ++jj) { - for (uint32_t kk = 0; kk < 4; ++kk) - { - eye.projection[4 * jj + kk] = eyeProj.M[kk][jj]; - } + hmdEye.projection[4*ii + jj] = projection.M[jj][ii]; } - - eye.viewOffset[0] = -erd.HmdToEyeOffset.x; - eye.viewOffset[1] = -erd.HmdToEyeOffset.y; - eye.viewOffset[2] = -erd.HmdToEyeOffset.z; - - eye.pixelsPerTanAngle[0] = erd.PixelsPerTanAngleAtCenter.x; - eye.pixelsPerTanAngle[1] = erd.PixelsPerTanAngleAtCenter.y; } } - _hmd.width = uint16_t(m_hmdSize.w); - _hmd.height = uint16_t(m_hmdSize.h); + return true; + } + + void VRImplOVR::updateInput(HMD& /* _hmd */) + { + } + + void VRImplOVR::recenter() + { + if (NULL != m_session) + { + ovr_RecenterTrackingOrigin(m_session); + } } } // namespace bgfx diff --git a/src/hmd_ovr.h b/src/hmd_ovr.h index eb275c4ea..0dbe388d0 100644 --- a/src/hmd_ovr.h +++ b/src/hmd_ovr.h @@ -10,6 +10,7 @@ #if BGFX_CONFIG_USE_OVR +# include "hmd.h" # include # define OVR_VERSION_(_a, _b, _c) (_a * 10000 + _b * 100 + _c) @@ -25,160 +26,41 @@ # include # endif // BGFX_CONFIG_RENDERER_OPENGL -namespace bgfx -{ - // render data for both eyes and mirrored output - struct BX_NO_VTABLE OVRRenderI - { - OVRRenderI(); - 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 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; - - ovrSizei m_eyeTextureSize[2]; - ovrTextureSwapChain m_textureSwapChain[2]; - ovrMirrorTexture m_mirrorTexture; - ovrMirrorTextureDesc m_mirrorTextureDesc; - }; - - inline OVRRenderI::OVRRenderI() - : m_mirrorTexture(NULL) - { - memset(&m_textureSwapChain, 0, sizeof(m_textureSwapChain)); - } - - inline OVRRenderI::~OVRRenderI() - { - } - - struct OVR - { - enum Enum - { - NotEnabled, - DeviceLost, - Success, - - Count - }; - - OVR(); - ~OVR(); - - bool isInitialized() const - { - return NULL != m_hmd; - } - - bool isEnabled() const - { - return m_enabled; - } - - void init(); - void shutdown(); - - void getViewport(uint8_t _eye, Rect* _viewport); - void renderEyeStart(uint8_t _eye); - bool postReset(); - void preReset(); - Enum swap(HMD& _hmd, bool originBottomLeft); - void recenter(); - void getEyePose(HMD& _hmd); - - ovrSession m_hmd; - ovrHmdDesc m_hmdDesc; - ovrEyeRenderDesc m_erd[2]; - ovrRecti m_rect[2]; - ovrPosef m_pose[2]; - ovrVector3f m_hmdToEyeOffset[2]; - ovrSizei m_hmdSize; - OVRRenderI *m_render; - uint64_t m_frameIndex; - double m_sensorSampleTime; - bool m_enabled; - }; - -} // namespace bgfx - -#else namespace bgfx { - struct OVR + class VRImplOVR : public VRImplI { - enum Enum - { - NotEnabled, - DeviceLost, - Success, + public: + VRImplOVR(); + virtual ~VRImplOVR() = 0; - Count - }; + virtual bool init(); + virtual void shutdown(); + virtual void connect(VRDesc* _desc); + virtual void disconnect(); - OVR() + virtual bool isConnected() const { + return NULL != m_session; } - ~OVR() - { - } + virtual bool updateTracking(HMD& _hmd); + virtual void updateInput(HMD& _hmd); + virtual void recenter(); - bool isInitialized() const - { - return false; - } + virtual bool createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) = 0; + virtual void destroySwapChain() = 0; + virtual void destroyMirror() = 0; + virtual void renderEyeStart(const VRDesc& _desc, uint8_t _eye) = 0; + virtual bool submitSwapChain(const VRDesc& _desc) = 0; - bool isEnabled() const - { - return false; - } - - bool isDebug() const - { - return false; - } - - void init() - { - } - - void shutdown() - { - } - - void getViewport(uint8_t /*_eye*/, Rect* _viewport) - { - _viewport->m_x = 0; - _viewport->m_y = 0; - _viewport->m_width = 0; - _viewport->m_height = 0; - } - - void renderEyeStart(uint8_t /*_eye*/) - { - } - - Enum swap(HMD& _hmd, bool /*originBottomLeft*/) - { - _hmd.flags = BGFX_HMD_NONE; - getEyePose(_hmd); - return NotEnabled; - } - - void recenter() - { - } - - void getEyePose(HMD& _hmd) - { - _hmd.width = 0; - _hmd.height = 0; - } + protected: + ovrSession m_session; + ovrLayerEyeFov m_renderLayer; + ovrViewScaleDesc m_viewScale; + ovrFovPort m_eyeFov[2]; + ovrVector2f m_pixelsPerTanAngleAtCenter[2]; }; } // namespace bgfx diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 786ab304d..09a757a80 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -29,6 +29,10 @@ # define BGFX_GPU_PROFILER_END() BX_NOOP() #endif +#if BGFX_CONFIG_USE_OVR +# include "hmd_ovr.h" +#endif // BGFX_CONFIG_USE_OVR + namespace bgfx { namespace d3d11 { static wchar_t s_viewNameW[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME]; @@ -601,6 +605,30 @@ namespace bgfx { namespace d3d11 static PFN_GET_DEBUG_INTERFACE1 DXGIGetDebugInterface1; #endif // USE_D3D11_DYNAMIC_LIB +#if BGFX_CONFIG_USE_OVR + class VRImplOVRD3D11 : public VRImplOVR + { + public: + VRImplOVRD3D11(); + + virtual bool createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight); + virtual void destroySwapChain(); + virtual void destroyMirror(); + virtual void renderEyeStart(const VRDesc& _desc, uint8_t _eye); + virtual bool submitSwapChain(const VRDesc& _desc); + + private: + ID3D11RenderTargetView* m_eyeRtv[2][4]; + ID3D11DepthStencilView* m_depthBuffer[2]; + ID3D11Texture2D* m_msaaTexture[2]; + ID3D11ShaderResourceView* m_msaaSv[2]; + ID3D11RenderTargetView* m_msaaRtv[2]; + + ovrTextureSwapChain m_textureSwapChain[2]; + ovrMirrorTexture m_mirrorTexture; + }; +#endif // BGFX_CONFIG_USE_OVR + struct RendererContextD3D11 : public RendererContextI { RendererContextD3D11() @@ -662,7 +690,11 @@ namespace bgfx { namespace d3d11 ErrorState::Enum errorState = ErrorState::Default; // Must be before device creation, and before RenderDoc. - m_ovr.init(); + VRImplI* vrImpl = NULL; +#if BGFX_CONFIG_USE_OVR + vrImpl = &m_ovrRender; +#endif // BGFX_CONFIG_USE_OVR + m_ovr.init(vrImpl); if (!m_ovr.isInitialized() ) { @@ -2226,18 +2258,12 @@ BX_PRAGMA_DIAGNOSTIC_POP(); if (SUCCEEDED(hr) ) { - switch (m_ovr.swap(_hmd, false) ) + m_ovr.flip(); + m_ovr.swap(_hmd); // TODO - move this out of end-of-frame + + if (!m_ovr.isEnabled()) { - case OVR::NotEnabled: hr = m_swapChain->Present(syncInterval, 0); - break; - - case OVR::DeviceLost: - ovrPreReset(); - break; - - default: - break; } } @@ -3148,13 +3174,8 @@ BX_PRAGMA_DIAGNOSTIC_POP(); #if BGFX_CONFIG_USE_OVR if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) ) { - if (m_ovr.postReset() ) - { - const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); - - m_ovr.m_render = &m_ovrRender; - m_ovr.m_render->create(m_ovr.m_hmd, msaaSamples, m_resolution.m_width, m_resolution.m_height); - } + const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); + m_ovr.postReset(msaaSamples, m_resolution.m_width, m_resolution.m_height); } #endif // BGFX_CONFIG_USE_OVR } @@ -3553,9 +3574,9 @@ BX_PRAGMA_DIAGNOSTIC_POP(); bool m_rtMsaa; bool m_timerQuerySupport; - OVR m_ovr; + VR m_ovr; #if BGFX_CONFIG_USE_OVR - OVRRenderD3D11 m_ovrRender; + VRImplOVRD3D11 m_ovrRender; #endif // BGFX_CONFIG_USE_OVR }; @@ -3610,62 +3631,66 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } #if BGFX_CONFIG_USE_OVR - void OVRRenderD3D11::create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) + + VRImplOVRD3D11::VRImplOVRD3D11() + : m_mirrorTexture(NULL) { - ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session); + memset(m_textureSwapChain, 0, sizeof(m_textureSwapChain)); + } + + bool VRImplOVRD3D11::createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) + { + ID3D11Device* device = s_renderD3D11->m_device; for (int eye = 0; eye < 2; ++eye) { 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; + 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; + ovrTextureSwapChainDesc swapchainDesc = {}; + swapchainDesc.Type = ovrTexture_2D; + swapchainDesc.ArraySize = 1; + swapchainDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + swapchainDesc.Width = _desc.m_eyeSize[eye].m_w; + swapchainDesc.Height = _desc.m_eyeSize[eye].m_h; + swapchainDesc.MipLevels = 1; + swapchainDesc.SampleCount = 1; + swapchainDesc.MiscFlags = ovrTextureMisc_DX_Typeless; + swapchainDesc.BindFlags = ovrTextureBind_DX_RenderTarget; + swapchainDesc.StaticImage = ovrFalse; - ID3D11Device* device = s_renderD3D11->m_device; - - ovrResult result = ovr_CreateTextureSwapChainDX(_session, device, &desc, &m_textureSwapChain[eye]); - - if (!OVR_SUCCESS(result) ) + ovrResult result = ovr_CreateTextureSwapChainDX(m_session, device, &swapchainDesc, &m_textureSwapChain[eye]); + if (!OVR_SUCCESS(result)) { - BX_CHECK(false, "Could not create D3D11 OVR swap texture"); + destroySwapChain(); + return false; } - memset(m_eyeRtv[eye], 0, sizeof(m_eyeRtv[eye]) ); - int textureCount = 0; - ovr_GetTextureSwapChainLength(_session, m_textureSwapChain[eye], &textureCount); + memset(m_eyeRtv[eye], 0, sizeof(m_eyeRtv[eye])); + int textureCount; + ovr_GetTextureSwapChainLength(m_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) ); + ovr_GetTextureSwapChainBufferDX(m_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) ); + 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.Width = _desc.m_eyeSize[eye].m_w; + dbDesc.Height = _desc.m_eyeSize[eye].m_h; dbDesc.MipLevels = 1; dbDesc.ArraySize = 1; dbDesc.Format = DXGI_FORMAT_D32_FLOAT; @@ -3676,16 +3701,16 @@ BX_PRAGMA_DIAGNOSTIC_POP(); 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_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.Width = _desc.m_eyeSize[eye].m_w; + dsDesc.Height = _desc.m_eyeSize[eye].m_h; dsDesc.MipLevels = 1; dsDesc.ArraySize = 1; dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -3696,7 +3721,6 @@ BX_PRAGMA_DIAGNOSTIC_POP(); 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])); @@ -3706,124 +3730,147 @@ BX_PRAGMA_DIAGNOSTIC_POP(); if (NULL == m_mirrorTexture) { - 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); + ovrMirrorTextureDesc mirrorDesc = {}; + mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + mirrorDesc.Width = _mirrorWidth; + mirrorDesc.Height = _mirrorHeight; + ovrResult result = ovr_CreateMirrorTextureDX(m_session, device, &mirrorDesc, &m_mirrorTexture); BX_WARN(OVR_SUCCESS(result), "Could not create D3D11 OVR mirror texture"); BX_UNUSED(result); } + + m_renderLayer.ColorTexture[0] = m_textureSwapChain[0]; + m_renderLayer.ColorTexture[1] = m_textureSwapChain[1]; + return true; } - void OVRRenderD3D11::startEyeRender(const ovrSession& _session, int _eyeIdx) + void VRImplOVRD3D11::destroySwapChain() + { + for (int eye = 0; eye < 2; ++eye) + { + if (m_textureSwapChain[eye]) + { + for (uint32_t ii = 0; ii < BX_COUNTOF(m_eyeRtv[eye]); ++ii) + { + DX_RELEASE(m_eyeRtv[eye][ii], 0); + } + + ovr_DestroyTextureSwapChain(m_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; + } + } + } + + destroyMirror(); + } + + void VRImplOVRD3D11::destroyMirror() + { + if (NULL != m_mirrorTexture) + { + ovr_DestroyMirrorTexture(m_session, m_mirrorTexture); + m_mirrorTexture = NULL; + } + } + + void VRImplOVRD3D11::renderEyeStart(const VRDesc& _desc, uint8_t _eye) { 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[_eyeIdx]) + if (NULL != m_msaaTexture[_eye]) { - 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); + deviceCtx->OMSetRenderTargets(1, &m_msaaRtv[_eye], m_depthBuffer[_eye]); + deviceCtx->ClearRenderTargetView(m_msaaRtv[_eye], black); + deviceCtx->ClearDepthStencilView(m_depthBuffer[_eye], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); } else // MSAA disabled? render directly to eye buffer { int texIndex = 0; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &texIndex); + ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureSwapChain[_eye], &texIndex); - 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); + deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[_eye][texIndex], m_depthBuffer[_eye]); + deviceCtx->ClearRenderTargetView(m_eyeRtv[_eye][texIndex], black); + deviceCtx->ClearDepthStencilView(m_depthBuffer[_eye], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); D3D11_VIEWPORT D3Dvp; D3Dvp.TopLeftX = 0; D3Dvp.TopLeftY = 0; - D3Dvp.Width = (FLOAT)m_eyeTextureSize[_eyeIdx].w; - D3Dvp.Height = (FLOAT)m_eyeTextureSize[_eyeIdx].h; + D3Dvp.Width = (FLOAT)_desc.m_eyeSize[_eye].m_w; + D3Dvp.Height = (FLOAT)_desc.m_eyeSize[_eye].m_h; D3Dvp.MinDepth = 0; D3Dvp.MaxDepth = 1; deviceCtx->RSSetViewports(1, &D3Dvp); } } - void OVRRenderD3D11::postRender(const ovrSession& _session, int _eyeIdx) + bool VRImplOVRD3D11::submitSwapChain(const VRDesc& /* _desc */) { - if (NULL != m_msaaTexture[_eyeIdx]) - { - ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; - int destIndex = 0; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &destIndex); - ID3D11Resource* dstTex = NULL; - 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(); - } - } + ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; + IDXGISwapChain* swapChain = s_renderD3D11->m_swapChain; - void OVRRenderD3D11::destroy(const ovrSession& _session) - { + // resolve MSAA render targets for (int eye = 0; eye < 2; ++eye) { - for (uint32_t ii = 0; ii < BX_COUNTOF(m_eyeRtv[eye]); ++ii) - { - 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; + int destIndex = 0; + ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureSwapChain[eye], &destIndex); + + ID3D11Resource* dstTex = NULL; + ovr_GetTextureSwapChainBufferDX(m_session, m_textureSwapChain[eye], destIndex, IID_PPV_ARGS(&dstTex)); + deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture[eye], 0, DXGI_FORMAT_R8G8B8A8_UNORM); + dstTex->Release(); } - if (NULL != m_msaaSv[eye]) + ovrResult result = ovr_CommitTextureSwapChain(m_session, m_textureSwapChain[eye]); + if (!OVR_SUCCESS(result)) { - m_msaaSv[eye]->Release(); - m_msaaSv[eye] = NULL; - } - - if (NULL != m_msaaRtv[eye]) - { - m_msaaRtv[eye]->Release(); - m_msaaRtv[eye] = NULL; + return false; } } - if (NULL != m_mirrorTexture) + ovrLayerHeader* layerList = &m_renderLayer.Header; + ovrResult result = ovr_SubmitFrame(m_session, 0, NULL, &layerList, 1); + if (!OVR_SUCCESS(result)) { - ovr_DestroyMirrorTexture(_session, m_mirrorTexture); - m_mirrorTexture = NULL; + return false; } - } - void OVRRenderD3D11::blitMirror(const ovrSession& _session) - { - if (NULL != m_mirrorTexture) + if (result != ovrSuccess_NotVisible && NULL != m_mirrorTexture) { ID3D11Texture2D* tex = NULL; - ovr_GetMirrorTextureBufferDX(_session, m_mirrorTexture, IID_PPV_ARGS(&tex) ); + ovr_GetMirrorTextureBufferDX(m_session, m_mirrorTexture, IID_PPV_ARGS(&tex)); ID3D11Texture2D* backBuffer; - DX_CHECK(s_renderD3D11->m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); + DX_CHECK(swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))); - s_renderD3D11->m_deviceCtx->CopyResource(backBuffer, tex); - DX_CHECK(s_renderD3D11->m_swapChain->Present(0, 0) ); + deviceCtx->CopyResource(backBuffer, tex); + DX_CHECK(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; - } + return true; } #endif // BGFX_CONFIG_USE_OVR @@ -5307,8 +5354,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); if (m_ovr.isEnabled() ) { - m_ovr.getViewport(eye, &viewState.m_rect); - m_ovr.renderEyeStart(eye); + m_ovr.renderEyeStart(eye, &viewState.m_rect); } else { diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index f929c480e..796e99c39 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -32,7 +32,7 @@ BX_PRAGMA_DIAGNOSTIC_POP() #include "renderer.h" #include "renderer_d3d.h" #include "shader_dxbc.h" -#include "hmd_ovr.h" +#include "hmd.h" #include "hmd_openvr.h" #include "debug_renderdoc.h" @@ -60,25 +60,6 @@ BX_PRAGMA_DIAGNOSTIC_POP() namespace bgfx { namespace d3d11 { -#if BGFX_CONFIG_USE_OVR - struct OVRRenderD3D11 : public OVRRenderI - { - 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[2][4]; - ID3D11DepthStencilView* m_depthBuffer[2]; - ID3D11Texture2D* m_msaaTexture[2]; - ID3D11ShaderResourceView* m_msaaSv[2]; - ID3D11RenderTargetView* m_msaaRtv[2]; - }; - -#endif // BGFX_CONFIG_USE_OVR - struct BufferD3D11 { BufferD3D11() diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 829840ad3..22c9a9e19 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -9,6 +9,7 @@ # include "renderer_gl.h" # include # include +# include "hmd_ovr.h" #if BGFX_CONFIG_PROFILER_REMOTERY # define BGFX_GPU_PROFILER_BIND() rmt_BindOpenGL() @@ -1352,6 +1353,34 @@ namespace bgfx { namespace gl BX_UNUSED(supported); } +#if BGFX_CONFIG_USE_OVR + class VRImplOVRGL : public VRImplOVR + { + public: + VRImplOVRGL(); + + virtual bool createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight); + virtual void destroySwapChain(); + virtual void destroyMirror(); + virtual void renderEyeStart(const VRDesc& _desc, uint8_t _eye); + virtual bool submitSwapChain(const VRDesc& _desc); + + private: + GLuint m_eyeFbo[2]; + GLuint m_eyeTexId[2][4]; + GLuint m_depthBuffer[2]; + GLuint m_msaaEyeFbo[2]; + GLuint m_msaaEyeTexId[2]; + GLuint m_msaaDepthBuffer[2]; + GLuint m_mirrorFbo; + GLint m_mirrorWidth; + GLint m_mirrorHeight; + + ovrTextureSwapChain m_textureSwapChain[2]; + ovrMirrorTexture m_mirrorTexture; + }; +#endif // BGFX_CONFIG_USE_OVR + struct RendererContextGL : public RendererContextI { RendererContextGL() @@ -1401,7 +1430,11 @@ namespace bgfx { namespace gl setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); // Must be after context is initialized?! - m_ovr.init(); + VRImplI* vrImpl = NULL; +#if BGFX_CONFIG_USE_OVR + vrImpl = &m_ovrRender; +#endif + m_ovr.init(vrImpl); m_vendor = getGLString(GL_VENDOR); m_renderer = getGLString(GL_RENDERER); @@ -2205,15 +2238,8 @@ namespace bgfx { namespace gl m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain); } - switch (m_ovr.swap(_hmd, true) ) - { - case OVR::DeviceLost: - ovrPreReset(); - break; - - default: - break; - } + m_ovr.flip(); + m_ovr.swap(_hmd); // TODO - move this out of end-of-frame // need to swap GL render context even if OVR is enabled to get the mirror texture in the output m_glctx.swap(); @@ -2957,13 +2983,8 @@ namespace bgfx { namespace gl #if BGFX_CONFIG_USE_OVR if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) ) { - if (m_ovr.postReset() ) - { - const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); - - m_ovr.m_render = &m_ovrRender; - m_ovr.m_render->create(m_ovr.m_hmd, msaaSamples, m_resolution.m_width, m_resolution.m_height); - } + const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); + m_ovr.postReset(msaaSamples, m_resolution.m_width, m_resolution.m_height); } #endif // BGFX_CONFIG_USE_OVR } @@ -3394,9 +3415,9 @@ namespace bgfx { namespace gl const char* m_version; const char* m_glslVersion; - OVR m_ovr; + VR m_ovr; #if BGFX_CONFIG_USE_OVR - OVRRenderGL m_ovrRender; + VRImplOVRGL m_ovrRender; #endif // BGFX_CONFIG_USE_OVR }; @@ -3417,238 +3438,245 @@ namespace bgfx { namespace gl } #if BGFX_CONFIG_USE_OVR - OVRRenderGL::OVRRenderGL() + + VRImplOVRGL::VRImplOVRGL() + : m_mirrorTexture(NULL) { - memset(&m_eyeFbo, 0, sizeof(m_eyeFbo)); - m_mirrorFBO = 0; + memset(&m_textureSwapChain, 0, sizeof(m_textureSwapChain)); } - void OVRRenderGL::create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) + static void setDefaultSamplerState() + { + 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)); + } + + bool VRImplOVRGL::createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) { for (int eye = 0; eye < 2; ++eye) { 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; + memset(&m_eyeTexId[eye], 0, sizeof(m_eyeTexId[eye])); - ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session); - m_eyeTextureSize[eye] = ovr_GetFovTextureSize(_session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1.0f); + ovrTextureSwapChainDesc swapchainDesc = {}; + swapchainDesc.Type = ovrTexture_2D; + swapchainDesc.ArraySize = 1; + swapchainDesc.Width = _desc.m_eyeSize[eye].m_w; + swapchainDesc.Height = _desc.m_eyeSize[eye].m_h; + swapchainDesc.MipLevels = 1; + swapchainDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + swapchainDesc.SampleCount = 1; + swapchainDesc.StaticImage = ovrFalse; - 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]); + ovrResult result = ovr_CreateTextureSwapChainGL(m_session, &swapchainDesc, &m_textureSwapChain[eye]); + if (!OVR_SUCCESS(result)) + { + destroySwapChain(); + return false; + } int textureCount = 0; - ovr_GetTextureSwapChainLength(_session, m_textureSwapChain[eye], &textureCount); - - for (int j = 0; j < textureCount; ++j) + ovr_GetTextureSwapChainLength(m_session, m_textureSwapChain[eye], &textureCount); + for (int ii = 0; ii < textureCount; ++ii) { - 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) ); + ovr_GetTextureSwapChainBufferGL(m_session, m_textureSwapChain[eye], ii, &m_eyeTexId[eye][ii]); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_eyeTexId[eye][ii])); + setDefaultSamplerState(); } - GL_CHECK(glGenFramebuffers(1, &m_eyeFbo[eye]) ); + 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(glGenTextures(1, &m_depthBuffer[eye])); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer[eye])); + setDefaultSamplerState(); - 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) ); + GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); - // create MSAA buffers + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_eyeFbo[eye])); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer[eye], 0)); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); + + // create MSAA targets if needed if (_msaaSamples > 1) { - GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo[eye]) ); + 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) ); + 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, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, false)); + setDefaultSamplerState(); // create MSAA depth buffer - GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer[eye]) ); - GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer[eye]) ); + GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer[eye])); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_depthBuffer[eye])); + GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, false)); + setDefaultSamplerState(); - 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(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo[eye])); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[eye], 0)); + GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0)); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); } + + m_renderLayer.ColorTexture[eye] = m_textureSwapChain[eye]; } } + m_renderLayer.Header.Flags |= ovrLayerFlag_TextureOriginAtBottomLeft; + if (NULL == m_mirrorTexture) { - memset(&m_mirrorTextureDesc, 0, sizeof(m_mirrorTextureDesc) ); - m_mirrorTextureDesc.Width = _mirrorWidth; - m_mirrorTextureDesc.Height = _mirrorHeight; - m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + m_mirrorFbo = 0; - ovr_CreateMirrorTextureGL(_session, &m_mirrorTextureDesc, &m_mirrorTexture); + ovrMirrorTextureDesc mirrorDesc = {}; + mirrorDesc.Width = _mirrorWidth; + mirrorDesc.Height = _mirrorHeight; + mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; // 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) + ovr_CreateMirrorTextureGL(m_session, &mirrorDesc, &m_mirrorTexture); + if (m_mirrorTexture) { - GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); - BX_CHECK(false, "Could not initialize VR buffers!"); + m_mirrorWidth = _mirrorWidth; + m_mirrorHeight = _mirrorHeight; + + // Configure the mirror read buffer + GLuint texId; + ovr_GetMirrorTextureBufferGL(m_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)); + ovr_DestroyMirrorTexture(m_session, m_mirrorTexture); + m_mirrorTexture = NULL; + BX_CHECK(false, "Could not initialize VR mirror buffers!"); + } } } + + return true; } - void OVRRenderGL::startEyeRender(const ovrSession& _session, int _eyeIdx) - { - // set the current eye texture in swap chain - int curIndex; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &curIndex); - ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain[_eyeIdx], curIndex, &m_eyeTexId[_eyeIdx]); - - if (0 != m_msaaEyeFbo[_eyeIdx]) - { - 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[_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[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h) ); - GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ); - } - - void OVRRenderGL::postRender(const ovrSession& /*_sesion*/, int _eyeIdx) - { - 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[_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[_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[_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 OVRRenderGL::destroy(const ovrSession& _session) + void VRImplOVRGL::destroySwapChain() { for (int eye = 0; eye < 2; ++eye) { - GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo[eye]) ); - GL_CHECK(glDeleteTextures(1, &m_depthBuffer[eye]) ); + if (NULL != m_textureSwapChain[eye]) + { + GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo[eye])); + GL_CHECK(glDeleteTextures(1, &m_depthBuffer[eye])); - ovr_DestroyTextureSwapChain(_session, m_textureSwapChain[eye]); - m_textureSwapChain[eye] = NULL; + ovr_DestroyTextureSwapChain(m_session, m_textureSwapChain[eye]); + m_textureSwapChain[eye] = NULL; + if (0 != m_msaaEyeFbo[eye]) + { + GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo[eye])); + GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId[eye])); + GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer[eye])); + m_msaaEyeFbo[eye] = 0; + } + } + } + + destroyMirror(); + } + + void VRImplOVRGL::destroyMirror() + { + if (NULL != m_mirrorTexture) + { + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFbo)); + ovr_DestroyMirrorTexture(m_session, m_mirrorTexture); + m_mirrorTexture = NULL; + } + } + + void VRImplOVRGL::renderEyeStart(const VRDesc& _desc, uint8_t _eye) + { + // set the current eye texture in the swap chain + if (0 != m_msaaEyeFbo[_eye]) + { + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo[_eye])); + } + else + { + int texIndex; + ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureSwapChain[_eye], &texIndex); + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo[_eye])); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[_eye][texIndex], 0)); + } + + GL_CHECK(glViewport(0, 0, _desc.m_eyeSize[_eye].m_w, _desc.m_eyeSize[_eye].m_h)); + GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); + } + + bool VRImplOVRGL::submitSwapChain(const VRDesc& _desc) + { + for (int eye = 0; eye < 2; ++eye) + { if (0 != m_msaaEyeFbo[eye]) { - GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo[eye]) ); - m_msaaEyeFbo[eye] = 0; + // blit the contents of MSAA FBO to the regulare eye buffer "connected" to the HMD + int destIndex; + ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureSwapChain[eye], &destIndex); + + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo[eye])); + 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[eye])); + GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[eye][destIndex], 0)); + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); + + GL_CHECK(glBlitFramebuffer(0, 0, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, 0, 0, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, GL_COLOR_BUFFER_BIT, GL_NEAREST)); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); } - if (0 != m_msaaEyeTexId[eye]) + ovrResult result = ovr_CommitTextureSwapChain(m_session, m_textureSwapChain[eye]); + if (!OVR_SUCCESS(result)) { - 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; + return false; } } - if (NULL != m_mirrorTexture) + ovrLayerHeader* layerList = &m_renderLayer.Header; + ovrResult result = ovr_SubmitFrame(m_session, 0, &m_viewScale, &layerList, 1); + if (!OVR_SUCCESS(result)) { - GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); - ovr_DestroyMirrorTexture(_session, m_mirrorTexture); - m_mirrorTexture = NULL; + return false; } + + if (result != ovrSuccess_NotVisible && NULL != m_mirrorTexture) + { + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFbo)); + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0)); + GL_CHECK(glBlitFramebuffer(0, m_mirrorHeight, m_mirrorWidth, 0, 0, 0, m_mirrorWidth, m_mirrorHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST)); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); + } + + return true; } - void OVRRenderGL::blitMirror(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) ); - } - } - - 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) @@ -6183,8 +6211,7 @@ namespace bgfx { namespace gl if (m_ovr.isEnabled() ) { - m_ovr.getViewport(eye, &viewState.m_rect); - m_ovr.renderEyeStart(eye); + m_ovr.renderEyeStart(eye, &viewState.m_rect); } else { diff --git a/src/renderer_gl.h b/src/renderer_gl.h index a4f0e6fdc..733d55062 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -107,7 +107,7 @@ typedef uint64_t GLuint64; #endif // BGFX_CONFIG_RENDERER_OPENGL #include "renderer.h" -#include "hmd_ovr.h" +#include "hmd.h" #include "hmd_openvr.h" #include "debug_renderdoc.h" @@ -950,28 +950,6 @@ namespace bgfx namespace bgfx { namespace gl { -#if BGFX_CONFIG_USE_OVR - struct OVRRenderGL : public OVRRenderI - { - 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); const char* glEnumName(GLenum _enum);