From 1e604e8f381031dfeb6d6dc4b980e1c7d409f562 Mon Sep 17 00:00:00 2001 From: Matthew Endsley Date: Tue, 2 Jun 2015 17:00:36 -0700 Subject: [PATCH] VR: Add device resolution to HMD. Init at startup. BREAKING: bgfx::getHMD() now returns a valid pointer if the VR runtime was initialized. This is different from existing behavior where getHMD returned NULL until a bgfx::reset(... BGFX_RESET_HMD) was issued. Applications must now check HMD::flags for the current state of the VR runtime. The following code has the code change required: `const bgfx::HMD* hmd = bgfx::getHMD() if (NULL != hmd)` becomes: `const bgfx::HMD* hmd = bgfx::getHMD() if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDRERING)) { // rendering logic }` See the updated examples for details. This allows applications to create the appropriately sized back buffer for the HMD device by using the new device resolution fields HMD::deviceHeight and HMD::deviceWidth. These values report the pixel resolution of the attached HMD hardware. This also allows applications to query the reported HMD resolution immediately after bgfx::init. This prevents the device from being cycled which generates rendring artifacts on startup - namely flashing back to a black screen and reseting the Health+Warning disaply. This involves initialization the ovrHmd device on initialization, but deferring rendering until postReset has been called. This adds an addiional memory overhead of 32k to builds defining BGFX_CONFIG_USE_OVR. The overhead for current builds is ~1.9MB for calls to ovr_Initialize, so the additional overhead is pretty trivial (+1.8%) --- examples/01-cubes/cubes.cpp | 2 +- examples/02-metaballs/metaballs.cpp | 2 +- examples/04-mesh/mesh.cpp | 2 +- examples/05-instancing/instancing.cpp | 2 +- examples/06-bump/bump.cpp | 2 +- examples/10-font/font.cpp | 2 +- examples/11-fontsdf/fontsdf.cpp | 2 +- examples/12-lod/lod.cpp | 2 +- examples/14-shadowvolumes/shadowvolumes.cpp | 2 +- examples/24-nbody/nbody.cpp | 2 +- examples/common/imgui/imgui.cpp | 2 +- include/bgfx.c99.h | 3 + include/bgfx.h | 7 +- include/bgfxdefines.h | 5 ++ src/bgfx_p.h | 6 +- src/ovr.cpp | 93 ++++++++++++--------- src/ovr.h | 7 +- src/renderer_d3d11.cpp | 4 +- src/renderer_gl.cpp | 4 +- 19 files changed, 88 insertions(+), 63 deletions(-) diff --git a/examples/01-cubes/cubes.cpp b/examples/01-cubes/cubes.cpp index e6eb82ca..48ecc5e2 100644 --- a/examples/01-cubes/cubes.cpp +++ b/examples/01-cubes/cubes.cpp @@ -119,7 +119,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float view[16]; bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); diff --git a/examples/02-metaballs/metaballs.cpp b/examples/02-metaballs/metaballs.cpp index 7578433b..fd511b95 100644 --- a/examples/02-metaballs/metaballs.cpp +++ b/examples/02-metaballs/metaballs.cpp @@ -548,7 +548,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float view[16]; bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); diff --git a/examples/04-mesh/mesh.cpp b/examples/04-mesh/mesh.cpp index 615e9d09..7848de01 100644 --- a/examples/04-mesh/mesh.cpp +++ b/examples/04-mesh/mesh.cpp @@ -65,7 +65,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float view[16]; bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); diff --git a/examples/05-instancing/instancing.cpp b/examples/05-instancing/instancing.cpp index bac9b685..7d8f4f6b 100644 --- a/examples/05-instancing/instancing.cpp +++ b/examples/05-instancing/instancing.cpp @@ -135,7 +135,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float view[16]; bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); diff --git a/examples/06-bump/bump.cpp b/examples/06-bump/bump.cpp index 8d2b6a28..ef880fff 100644 --- a/examples/06-bump/bump.cpp +++ b/examples/06-bump/bump.cpp @@ -195,7 +195,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float view[16]; bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); diff --git a/examples/10-font/font.cpp b/examples/10-font/font.cpp index d25ef264..1cd00126 100644 --- a/examples/10-font/font.cpp +++ b/examples/10-font/font.cpp @@ -203,7 +203,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Setup a top-left ortho matrix for screen space drawing. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float proj[16]; bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f); diff --git a/examples/11-fontsdf/fontsdf.cpp b/examples/11-fontsdf/fontsdf.cpp index 149206a5..bf60dd8d 100644 --- a/examples/11-fontsdf/fontsdf.cpp +++ b/examples/11-fontsdf/fontsdf.cpp @@ -201,7 +201,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Setup a top-left ortho matrix for screen space drawing. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float proj[16]; bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f); diff --git a/examples/12-lod/lod.cpp b/examples/12-lod/lod.cpp index 1901a261..2a6775ea 100644 --- a/examples/12-lod/lod.cpp +++ b/examples/12-lod/lod.cpp @@ -163,7 +163,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float view[16]; bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); diff --git a/examples/14-shadowvolumes/shadowvolumes.cpp b/examples/14-shadowvolumes/shadowvolumes.cpp index e27b16da..f9e4afa7 100644 --- a/examples/14-shadowvolumes/shadowvolumes.cpp +++ b/examples/14-shadowvolumes/shadowvolumes.cpp @@ -2107,7 +2107,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float eye[3]; cameraGetPosition(eye); diff --git a/examples/24-nbody/nbody.cpp b/examples/24-nbody/nbody.cpp index ad086aa5..52dfce19 100644 --- a/examples/24-nbody/nbody.cpp +++ b/examples/24-nbody/nbody.cpp @@ -294,7 +294,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { float viewHead[16]; float eye[3] = {}; diff --git a/examples/common/imgui/imgui.cpp b/examples/common/imgui/imgui.cpp index 9fbe5137..dd2a9ad7 100644 --- a/examples/common/imgui/imgui.cpp +++ b/examples/common/imgui/imgui.cpp @@ -832,7 +832,7 @@ struct Imgui bgfx::setViewSeq(_view, true); const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd) + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING)) { m_viewWidth = _width / 2; m_surfaceWidth = _surfaceWidth / 2; diff --git a/include/bgfx.c99.h b/include/bgfx.c99.h index 82b5eeb4..338e09cb 100644 --- a/include/bgfx.c99.h +++ b/include/bgfx.c99.h @@ -211,6 +211,9 @@ typedef struct bgfx_hmd bgfx_hmd_eye_t eye[2]; uint16_t width; uint16_t height; + uint32_t deviceWidth; + uint32_t deviceHeight; + uint8_t flags; } bgfx_hmd_t; diff --git a/include/bgfx.h b/include/bgfx.h index 9370f6f5..9d00be6c 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -414,8 +414,11 @@ namespace bgfx }; Eye eye[2]; - uint16_t width; //!< Framebuffer width. - uint16_t height; //!< Framebuffer width. + uint16_t width; //!< Framebuffer width. + uint16_t height; //!< Framebuffer width. + uint32_t deviceWidth; //!< Device resolution width + uint32_t deviceHeight; //!< Device resolution height + uint8_t flags; //!< Status flags }; /// Vertex declaration. diff --git a/include/bgfxdefines.h b/include/bgfxdefines.h index cadb1d1a..3944870c 100644 --- a/include/bgfxdefines.h +++ b/include/bgfxdefines.h @@ -370,4 +370,9 @@ #define BGFX_PCI_ID_INTEL UINT16_C(0x8086) #define BGFX_PCI_ID_NVIDIA UINT16_C(0x10de) +/// +#define BGFX_HMD_NONE UINT8_C(0x00) +#define BGFX_HMD_DEVICE_RESOLUTION UINT8_C(0x01) +#define BGFX_HMD_RENDERING UINT8_C(0x02) + #endif // BGFX_DEFINES_H_HEADER_GUARD diff --git a/src/bgfx_p.h b/src/bgfx_p.h index e5786c29..0d78baf0 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -1203,7 +1203,7 @@ namespace bgfx BX_ALIGN_DECL_CACHE_LINE(struct) Frame { Frame() - : m_hmdEnabled(false) + : m_hmdInitialized(false) , m_waitSubmit(0) , m_waitRender(0) { @@ -1645,7 +1645,7 @@ namespace bgfx UniformHandle m_freeUniformHandle[BGFX_CONFIG_MAX_UNIFORMS]; TextVideoMem* m_textVideoMem; HMD m_hmd; - bool m_hmdEnabled; + bool m_hmdInitialized; int64_t m_waitSubmit; int64_t m_waitRender; @@ -1987,7 +1987,7 @@ namespace bgfx BGFX_API_FUNC(const HMD* getHMD() ) { - if (m_submit->m_hmdEnabled) + if (m_submit->m_hmdInitialized) { return &m_submit->m_hmd; } diff --git a/src/ovr.cpp b/src/ovr.cpp index 8a00608a..493c8dfc 100644 --- a/src/ovr.cpp +++ b/src/ovr.cpp @@ -11,26 +11,56 @@ namespace bgfx { OVR::OVR() : m_hmd(NULL) - , m_initialized(false) + , m_isenabled(false) , m_debug(false) { } OVR::~OVR() { - BX_CHECK(!m_initialized, "OVR not shutdown properly."); + BX_CHECK(NULL == m_hmd, "OVR not shutdown properly."); } void OVR::init() { - m_initialized = !!ovr_Initialize(); + bool initialized = !!ovr_Initialize(); + BX_WARN(initialized, "Unable to create OVR device."); + if (!initialized) + { + return; + } + + m_hmd = ovrHmd_Create(0); + if (NULL == m_hmd) + { + m_hmd = ovrHmd_CreateDebug(ovrHmd_DK2); + BX_WARN(NULL != m_hmd, "Unable to create OVR device."); + if (NULL == m_hmd) + { + return; + } + } + + BX_TRACE("HMD: %s, %s, firmware: %d.%d" + , m_hmd->ProductName + , m_hmd->Manufacturer + , m_hmd->FirmwareMajor + , m_hmd->FirmwareMinor + ); + + ovrSizei sizeL = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmd->DefaultEyeFov[0], 1.0f); + ovrSizei sizeR = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmd->DefaultEyeFov[1], 1.0f); + m_rtSize.w = sizeL.w + sizeR.w; + m_rtSize.h = bx::uint32_max(sizeL.h, sizeR.h); + m_warning = true; } void OVR::shutdown() { - BX_CHECK(NULL == m_hmd, "HMD not destroyed."); + BX_CHECK(!m_isenabled, "HMD not disabled."); + ovrHmd_Destroy(m_hmd); + m_hmd = NULL; ovr_Shutdown(); - m_initialized = false; } bool OVR::postReset(void* _nwh, ovrRenderAPIConfig* _config, bool _debug) @@ -75,33 +105,12 @@ namespace bgfx return false; } - if (!m_initialized) + if (NULL == m_hmd) { return false; } - if (!_debug) - { - m_hmd = ovrHmd_Create(0); - } - - if (NULL == m_hmd) - { - m_hmd = ovrHmd_CreateDebug(ovrHmd_DK2); - BX_WARN(NULL != m_hmd, "Unable to initialize OVR."); - - if (NULL == m_hmd) - { - return false; - } - } - - BX_TRACE("HMD: %s, %s, firmware: %d.%d" - , m_hmd->ProductName - , m_hmd->Manufacturer - , m_hmd->FirmwareMajor - , m_hmd->FirmwareMinor - ); + m_isenabled = true; ovrBool result; result = ovrHmd_AttachToWindow(m_hmd, _nwh, NULL, NULL); @@ -142,18 +151,11 @@ namespace bgfx { ovrError: BX_TRACE("Failed to initialize OVR."); - ovrHmd_Destroy(m_hmd); - m_hmd = NULL; + m_isenabled = false; return false; } - ovrSizei sizeL = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmd->DefaultEyeFov[0], 1.0f); - ovrSizei sizeR = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmd->DefaultEyeFov[1], 1.0f); - m_rtSize.w = sizeL.w + sizeR.w; - m_rtSize.h = bx::uint32_max(sizeL.h, sizeR.h); - m_warning = true; - return true; } @@ -188,11 +190,12 @@ ovrError: void OVR::preReset() { - if (NULL != m_hmd) + if (m_isenabled) { ovrHmd_EndFrame(m_hmd, m_pose, m_texture); - ovrHmd_Destroy(m_hmd); - m_hmd = NULL; + ovrHmd_AttachToWindow(m_hmd, NULL, NULL, NULL); + ovrHmd_ConfigureRendering(m_hmd, NULL, 0, NULL, NULL); + m_isenabled = false; } m_debug = false; @@ -200,11 +203,21 @@ ovrError: bool OVR::swap(HMD& _hmd) { - if (NULL == m_hmd) + _hmd.flags = BGFX_HMD_NONE; + + if (NULL != m_hmd) + { + _hmd.flags |= BGFX_HMD_DEVICE_RESOLUTION; + _hmd.deviceWidth = m_hmd->Resolution.w; + _hmd.deviceHeight = m_hmd->Resolution.h; + } + + if (!m_isenabled) { return false; } + _hmd.flags |= BGFX_HMD_RENDERING; ovrHmd_EndFrame(m_hmd, m_pose, m_texture); if (m_warning) diff --git a/src/ovr.h b/src/ovr.h index 52eaa591..6fe1c188 100644 --- a/src/ovr.h +++ b/src/ovr.h @@ -51,12 +51,12 @@ namespace bgfx bool isInitialized() const { - return m_initialized; + return NULL != m_hmd; } bool isEnabled() const { - return NULL != m_hmd; + return m_isenabled; } bool isDebug() const @@ -87,7 +87,7 @@ namespace bgfx ovrTexture m_texture[2]; ovrSizei m_rtSize; bool m_warning; - bool m_initialized; + bool m_isenabled; bool m_debug; }; @@ -132,6 +132,7 @@ namespace bgfx bool swap(HMD& _hmd) { + _hmd.flags = BGFX_HMD_NONE; getEyePose(_hmd); return false; } diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 965a6f3a..fe8f3324 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -3736,9 +3736,9 @@ BX_PRAGMA_DIAGNOSTIC_POP(); currentState.m_flags = BGFX_STATE_NONE; currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); - const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug(); - _render->m_hmdEnabled = hmdEnabled; + _render->m_hmdInitialized = m_ovr.isInitialized(); + const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug(); ViewState& viewState = m_viewState; viewState.reset(_render, hmdEnabled); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 7c066bc1..772d6bd3 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -4838,9 +4838,9 @@ namespace bgfx { namespace gl currentState.m_flags = BGFX_STATE_NONE; currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); - const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug(); - _render->m_hmdEnabled = hmdEnabled; + _render->m_hmdInitialized = m_ovr.isInitialized(); + const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug(); ViewState viewState(_render, hmdEnabled); uint16_t programIdx = invalidHandle;