This commit is contained in:
Krzysztof Kondrak 2016-04-02 11:41:40 +02:00
Родитель ea613785e4
Коммит bea6e81d12
15 изменённых файлов: 534 добавлений и 486 удалений

Просмотреть файл

@ -27,7 +27,7 @@ Supported rendering backends:
Supported HMD:
* OculusVR (0.4.2+)
* OculusVR (1.3.0)
Supported platforms:

Просмотреть файл

@ -143,11 +143,7 @@ class ExampleCubes : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -577,11 +577,7 @@ class ExampleMetaballs : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -91,11 +91,7 @@ class ExampleMesh : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -160,11 +160,7 @@ class ExampleInstancing : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -225,11 +225,7 @@ class ExampleBump : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -174,11 +174,7 @@ class ExampleLod : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -305,11 +305,7 @@ int _main_(int _argc, char** _argv)
float tmp[16];
bx::mtxMul(tmp, view, viewHead);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);
bgfx::setViewTransform(0, tmp, proj);
bgfx::setViewTransform(0, tmp, hmd->eye[0].projection);
// Set view 0 default viewport.
//

Просмотреть файл

@ -181,13 +181,10 @@ class ExampleOcclusion : public entry::AppI
float tmp[16];
bx::mtxMul(tmp, view, viewHead);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);
bgfx::setViewTransform(0, tmp, proj);
bgfx::setViewTransform(0, tmp, hmd->eye[0].projection);
bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);
bgfx::setViewTransform(1, tmp, proj);
bgfx::setViewTransform(1, tmp, hmd->eye[1].projection);
bgfx::setViewRect(1, 0, 0, hmd->width, hmd->height);
}
else

Просмотреть файл

@ -615,6 +615,7 @@ namespace bgfx
float translation[3]; //!< Eye translation.
float fov[4]; //!< Field of view (up, down, left, right).
float viewOffset[3]; //!< Eye view matrix translation adjustment.
float projection[16]; //!< Eye projection matrix
float pixelsPerTanAngle[2]; //!<
};
@ -1914,7 +1915,7 @@ namespace bgfx
///
void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height);
/// @attention C99 equivalent is `bgfx_set_view_rect_auto`.
/// @attention C99 equivalent is `bgfx_set_view_rect_auto`.
///
void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, BackbufferRatio::Enum _ratio);

Просмотреть файл

@ -178,42 +178,20 @@ function exampleProject(_name)
"ws2_32",
}
-- Check for LibOVR 5.0+
if os.isdir(path.join(os.getenv("OVR_DIR"), "LibOVR/Lib/Windows/Win32/Debug/VS2012")) then
configuration { "x32", "Debug" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Debug", _ACTION) }
configuration { "x32", "Debug" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Debug", _ACTION) }
configuration { "x32", "Release" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Release", _ACTION) }
configuration { "x32", "Release" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Release", _ACTION) }
configuration { "x64", "Debug" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Debug", _ACTION) }
configuration { "x64", "Debug" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Debug", _ACTION) }
configuration { "x64", "Release" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Release", _ACTION) }
configuration { "x64", "Release" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Release", _ACTION) }
configuration { "x32 or x64" }
links { "libovr" }
else
configuration { "x32" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Win32", _ACTION) }
configuration { "x64" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/x64", _ACTION) }
configuration { "x32", "Debug" }
links { "libovrd" }
configuration { "x32", "Release" }
links { "libovr" }
configuration { "x64", "Debug" }
links { "libovr64d" }
configuration { "x64", "Release" }
links { "libovr64" }
end
configuration { "x32 or x64" }
links { "libovr" }
configuration {}
end

Просмотреть файл

@ -9,17 +9,15 @@
namespace bgfx
{
#if OVR_VERSION <= OVR_VERSION_050
# define OVR_EYE_BUFFER 100
#else
# define OVR_EYE_BUFFER 8
#endif // OVR_VERSION...
OVR::OVR()
: m_hmd(NULL)
, m_isenabled(false)
, m_debug(false)
, m_mirror(NULL)
, m_hmdFrameReady(-1)
, m_frameIndex(0)
, m_sensorSampleTime(0)
{
memset(m_eyeBuffers, 0, sizeof(m_eyeBuffers));
}
OVR::~OVR()
@ -29,225 +27,162 @@ namespace bgfx
void OVR::init()
{
bool initialized = !!ovr_Initialize();
BX_WARN(initialized, "Unable to create OVR device.");
if (!initialized)
ovrResult initialized = ovr_Initialize(NULL);
ovrGraphicsLuid luid;
BX_WARN(initialized == ovrSuccess, "Unable to create OVR device.");
if (initialized != ovrSuccess)
{
return;
}
m_hmd = ovrHmd_Create(0);
if (NULL == m_hmd)
initialized = ovr_Create(&m_hmd, &luid);
if (initialized != ovrSuccess)
{
m_hmd = ovrHmd_CreateDebug(ovrHmd_DK2);
BX_WARN(NULL != m_hmd, "Unable to create OVR device.");
if (NULL == m_hmd)
{
return;
}
BX_WARN(initialized == ovrSuccess, "Unable to create OVR device.");
return;
}
m_hmdDesc = ovr_GetHmdDesc(m_hmd);
BX_TRACE("HMD: %s, %s, firmware: %d.%d"
, m_hmd->ProductName
, m_hmd->Manufacturer
, m_hmd->FirmwareMajor
, m_hmd->FirmwareMinor
, m_hmdDesc.ProductName
, m_hmdDesc.Manufacturer
, m_hmdDesc.FirmwareMajor
, m_hmdDesc.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 + OVR_EYE_BUFFER;
m_rtSize.h = bx::uint32_max(sizeL.h, sizeR.h);
m_warning = true;
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_isenabled, "HMD not disabled.");
ovrHmd_Destroy(m_hmd);
for (int i = 0; i < 2; i++)
{
if (m_eyeBuffers[i])
{
m_eyeBuffers[i]->destroy(m_hmd);
BX_DELETE(g_allocator, m_eyeBuffers[i]);
}
}
if (m_mirror)
{
m_mirror->destroy(m_hmd);
BX_DELETE(g_allocator, m_mirror);
}
ovr_Destroy(m_hmd);
m_hmd = NULL;
ovr_Shutdown();
}
void OVR::getViewport(uint8_t _eye, Rect* _viewport)
{
_viewport->m_x = _eye * (m_rtSize.w + OVR_EYE_BUFFER + 1)/2;
_viewport->m_x = 0;
_viewport->m_y = 0;
_viewport->m_width = (m_rtSize.w - OVR_EYE_BUFFER)/2;
_viewport->m_height = m_rtSize.h;
_viewport->m_width = m_eyeBuffers[_eye]->m_eyeTextureSize.w;
_viewport->m_height = m_eyeBuffers[_eye]->m_eyeTextureSize.h;
}
bool OVR::postReset(void* _nwh, ovrRenderAPIConfig* _config, bool _debug)
void OVR::renderEyeStart(uint8_t _eye)
{
if (_debug)
{
switch (_config->Header.API)
{
#if BGFX_CONFIG_RENDERER_DIRECT3D11
case ovrRenderAPI_D3D11:
{
ovrD3D11ConfigData* data = (ovrD3D11ConfigData*)_config;
# if OVR_VERSION > OVR_VERSION_043
m_rtSize = data->Header.BackBufferSize;
# else
m_rtSize = data->Header.RTSize;
# endif // OVR_VERSION > OVR_VERSION_043
}
break;
#endif // BGFX_CONFIG_RENDERER_DIRECT3D11
#if BGFX_CONFIG_RENDERER_OPENGL
case ovrRenderAPI_OpenGL:
{
ovrGLConfigData* data = (ovrGLConfigData*)_config;
# if OVR_VERSION > OVR_VERSION_043
m_rtSize = data->Header.BackBufferSize;
# else
m_rtSize = data->Header.RTSize;
# endif // OVR_VERSION > OVR_VERSION_043
}
break;
#endif // BGFX_CONFIG_RENDERER_OPENGL
case ovrRenderAPI_None:
default:
BX_CHECK(false, "You should not be here!");
break;
}
m_debug = true;
return false;
}
m_eyeBuffers[_eye]->onRender(m_hmd);
}
bool OVR::postReset()
{
if (NULL == m_hmd)
{
return false;
}
for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
{
m_erd[eyeIdx] = ovr_GetRenderDesc(m_hmd, (ovrEyeType)eyeIdx, m_hmdDesc.DefaultEyeFov[eyeIdx]);
}
m_isenabled = true;
ovrBool result;
result = ovrHmd_AttachToWindow(m_hmd, _nwh, NULL, NULL);
if (!result) { goto ovrError; }
ovrFovPort eyeFov[2] = { m_hmd->DefaultEyeFov[0], m_hmd->DefaultEyeFov[1] };
result = ovrHmd_ConfigureRendering(m_hmd
, _config
, 0
#if OVR_VERSION < OVR_VERSION_050
| ovrDistortionCap_Chromatic // permanently enabled >= v5.0
#endif
| ovrDistortionCap_Vignette
| ovrDistortionCap_TimeWarp
| ovrDistortionCap_Overdrive
| ovrDistortionCap_NoRestore
| ovrDistortionCap_HqDistortion
, eyeFov
, m_erd
);
if (!result) { goto ovrError; }
ovrHmd_SetEnabledCaps(m_hmd
, 0
| ovrHmdCap_LowPersistence
| ovrHmdCap_DynamicPrediction
);
result = ovrHmd_ConfigureTracking(m_hmd
, 0
| ovrTrackingCap_Orientation
| ovrTrackingCap_MagYawCorrection
| ovrTrackingCap_Position
, 0
);
if (!result)
{
ovrError:
BX_TRACE("Failed to initialize OVR.");
m_isenabled = false;
return false;
}
m_warning = true;
return true;
}
void OVR::postReset(const ovrTexture& _texture)
{
if (NULL != m_hmd)
{
m_texture[0] = _texture;
m_texture[1] = _texture;
ovrRecti rect;
rect.Pos.x = 0;
rect.Pos.y = 0;
rect.Size.w = (m_rtSize.w - OVR_EYE_BUFFER)/2;
rect.Size.h = m_rtSize.h;
m_texture[0].Header.RenderViewport = rect;
rect.Pos.x += rect.Size.w + OVR_EYE_BUFFER;
m_texture[1].Header.RenderViewport = rect;
m_timing = ovrHmd_BeginFrame(m_hmd, 0);
#if OVR_VERSION > OVR_VERSION_042
m_pose[0] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Right);
#else
m_pose[0] = ovrHmd_GetEyePose(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetEyePose(m_hmd, ovrEye_Right);
#endif // OVR_VERSION > OVR_VERSION_042
}
}
void OVR::preReset()
{
if (m_isenabled)
{
ovrHmd_EndFrame(m_hmd, m_pose, m_texture);
ovrHmd_AttachToWindow(m_hmd, NULL, NULL, NULL);
ovrHmd_ConfigureRendering(m_hmd, NULL, 0, NULL, NULL);
// on window resize this will recreate the mirror texture in ovrPostReset
m_mirror->destroy(m_hmd);
BX_DELETE(g_allocator, m_mirror);
m_mirror = NULL;
m_isenabled = false;
}
m_debug = false;
}
bool OVR::swap(HMD& _hmd)
void OVR::commitEye(uint8_t _eye)
{
if (m_isenabled)
{
m_hmdFrameReady = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[_eye]->m_swapTextureChain);
}
}
bool OVR::swap(HMD& _hmd, bool originBottomLeft)
{
_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;
_hmd.deviceWidth = m_hmdDesc.Resolution.w;
_hmd.deviceHeight = m_hmdDesc.Resolution.h;
}
if (!m_isenabled)
if (!m_isenabled || !OVR_SUCCESS(m_hmdFrameReady))
{
return false;
}
_hmd.flags |= BGFX_HMD_RENDERING;
ovrHmd_EndFrame(m_hmd, m_pose, m_texture);
if (m_warning)
// 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 (int eye = 0; eye < ovrEye_Count; eye++)
{
m_warning = !ovrHmd_DismissHSWDisplay(m_hmd);
eyeLayer.ColorTexture[eye] = m_eyeBuffers[eye]->m_swapTextureChain;
eyeLayer.Viewport[eye] = ::OVR::Recti(m_eyeBuffers[eye]->m_eyeTextureSize);
eyeLayer.Fov[eye] = m_hmdDesc.DefaultEyeFov[eye];
eyeLayer.RenderPose[eye] = m_pose[eye];
eyeLayer.SensorSampleTime = m_sensorSampleTime;
}
m_timing = ovrHmd_BeginFrame(m_hmd, 0);
// append all the layers to global list
ovrLayerHeader* layerList = &eyeLayer.Header;
#if OVR_VERSION > OVR_VERSION_042
m_pose[0] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Right);
#else
m_pose[0] = ovrHmd_GetEyePose(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetEyePose(m_hmd, ovrEye_Right);
#endif // OVR_VERSION > OVR_VERSION_042
ovr_SubmitFrame(m_hmd, m_frameIndex, NULL, &layerList, 1);
// perform mirror texture blit right after the entire frame is submitted to HMD
m_mirror->blit(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);
@ -258,7 +193,7 @@ ovrError:
{
if (NULL != m_hmd)
{
ovrHmd_RecenterPose(m_hmd);
ovr_RecenterTrackingOrigin(m_hmd);
}
}
@ -283,44 +218,27 @@ ovrError:
eye.fov[1] = erd.Fov.DownTan;
eye.fov[2] = erd.Fov.LeftTan;
eye.fov[3] = erd.Fov.RightTan;
#if OVR_VERSION > OVR_VERSION_042
eye.viewOffset[0] = erd.HmdToEyeViewOffset.x;
eye.viewOffset[1] = erd.HmdToEyeViewOffset.y;
eye.viewOffset[2] = erd.HmdToEyeViewOffset.z;
#else
eye.viewOffset[0] = erd.ViewAdjust.x;
eye.viewOffset[1] = erd.ViewAdjust.y;
eye.viewOffset[2] = erd.ViewAdjust.z;
#endif // OVR_VERSION > OVR_VERSION_042
ovrMatrix4f eyeProj = ovrMatrix4f_Projection(m_erd[ii].Fov, 0.01f, 1000.0f, ovrProjection_LeftHanded);
for (int jj = 0; jj < 4; ++jj)
{
for (int kk = 0; kk < 4; ++kk)
{
eye.projection[4 * jj + kk] = eyeProj.M[kk][jj];
}
}
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;
}
}
else
{
for (int ii = 0; ii < 2; ++ii)
{
_hmd.eye[ii].rotation[0] = 0.0f;
_hmd.eye[ii].rotation[1] = 0.0f;
_hmd.eye[ii].rotation[2] = 0.0f;
_hmd.eye[ii].rotation[3] = 1.0f;
_hmd.eye[ii].translation[0] = 0.0f;
_hmd.eye[ii].translation[1] = 0.0f;
_hmd.eye[ii].translation[2] = 0.0f;
_hmd.eye[ii].fov[0] = 1.32928634f;
_hmd.eye[ii].fov[1] = 1.32928634f;
_hmd.eye[ii].fov[2] = 0 == ii ? 1.05865765f : 1.09236801f;
_hmd.eye[ii].fov[3] = 0 == ii ? 1.09236801f : 1.05865765f;
_hmd.eye[ii].viewOffset[0] = 0 == ii ? 0.0355070010f : -0.0375000015f;
_hmd.eye[ii].viewOffset[1] = 0.0f;
_hmd.eye[ii].viewOffset[2] = 0 == ii ? 0.00150949787f : -0.00150949787f;
_hmd.eye[ii].pixelsPerTanAngle[0] = 1;
_hmd.eye[ii].pixelsPerTanAngle[1] = 1;
}
}
_hmd.width = uint16_t(m_rtSize.w);
_hmd.height = uint16_t(m_rtSize.h);
_hmd.width = uint16_t(m_hmdSize.w);
_hmd.height = uint16_t(m_hmdSize.h);
}
} // namespace bgfx

100
src/ovr.h
Просмотреть файл

@ -14,36 +14,44 @@
# define OVR_VERSION_(_a, _b, _c) (_a * 10000 + _b * 100 + _c)
# define OVR_VERSION OVR_VERSION_(OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION, OVR_MINOR_VERSION)
# define OVR_VERSION_042 OVR_VERSION_(0, 4, 2)
# define OVR_VERSION_043 OVR_VERSION_(0, 4, 3)
# define OVR_VERSION_044 OVR_VERSION_(0, 4, 4)
# define OVR_VERSION_050 OVR_VERSION_(0, 5, 0)
# if OVR_VERSION < OVR_VERSION_050
# include <OVR.h>
# else
# include <OVR_CAPI.h>
# endif // OVR_VERSION < OVR_VERSION_050
# include <OVR_CAPI.h>
# if BGFX_CONFIG_RENDERER_DIRECT3D11
# if OVR_VERSION < OVR_VERSION_050
# define OVR_D3D_VERSION 11
# include <OVR_D3D.h>
# else
# include <OVR_CAPI_D3D.h>
# endif
# include <OVR_CAPI_D3D.h>
# endif // BGFX_CONFIG_RENDERER_DIRECT3D11
# if BGFX_CONFIG_RENDERER_OPENGL
# if OVR_VERSION < OVR_VERSION_050
# include <OVR_GL.h>
# else
# include <OVR_CAPI_GL.h>
# endif
# include <OVR_CAPI_GL.h>
# endif // BGFX_CONFIG_RENDERER_OPENGL
#include "Extras/OVR_Math.h"
namespace bgfx
{
// single eye buffer
struct OVRBufferI
{
virtual ~OVRBufferI() {};
virtual void onRender(const ovrSession &session) = 0;
virtual void destroy(const ovrSession &session) = 0;
ovrSizei m_eyeTextureSize;
ovrTextureSwapChain m_swapTextureChain;
};
// mirrored window output
struct OVRMirrorI
{
virtual ~OVRMirrorI() {};
virtual void init(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;
ovrMirrorTextureDesc m_mirrorDesc;
};
struct OVR
{
OVR();
@ -59,37 +67,31 @@ namespace bgfx
return m_isenabled;
}
bool isDebug() const
{
return m_debug;
}
void init();
void shutdown();
void getViewport(uint8_t _eye, Rect* _viewport);
bool postReset(void* _nwh, ovrRenderAPIConfig* _config, bool _debug = false);
void postReset(const ovrTexture& _texture);
void renderEyeStart(uint8_t _eye);
bool postReset();
void preReset();
bool swap(HMD& _hmd);
void commitEye(uint8_t _eye);
bool swap(HMD& _hmd, bool originBottomLeft);
void recenter();
void getEyePose(HMD& _hmd);
void getSize(uint32_t& _width, uint32_t& _height) const
{
_width = m_rtSize.w;
_height = m_rtSize.h;
}
ovrHmd m_hmd;
ovrFrameTiming m_timing;
ovrSession m_hmd;
ovrHmdDesc m_hmdDesc;
ovrEyeRenderDesc m_erd[2];
ovrRecti m_rect[2];
ovrPosef m_pose[2];
ovrTexture m_texture[2];
ovrSizei m_rtSize;
bool m_warning;
ovrRecti m_rect[2];
ovrPosef m_pose[2];
ovrVector3f m_hmdToEyeOffset[2];
ovrSizei m_hmdSize;
ovrResult m_hmdFrameReady;
OVRBufferI *m_eyeBuffers[2];
OVRMirrorI *m_mirror;
long long m_frameIndex;
double m_sensorSampleTime;
bool m_isenabled;
bool m_debug;
};
} // namespace bgfx
@ -139,7 +141,15 @@ namespace bgfx
_viewport->m_height = 0;
}
bool swap(HMD& _hmd)
void commitEye(uint8_t /*_eye*/)
{
}
void renderEyeStart(uint8_t /*_eye*/)
{
}
bool swap(HMD& _hmd, bool /*originBottomLeft*/)
{
_hmd.flags = BGFX_HMD_NONE;
getEyePose(_hmd);
@ -155,12 +165,6 @@ namespace bgfx
_hmd.width = 0;
_hmd.height = 0;
}
void getSize(uint32_t& _width, uint32_t& _height) const
{
_width = 0;
_height = 0;
}
};
} // namespace bgfx

Просмотреть файл

@ -601,6 +601,170 @@ namespace bgfx { namespace d3d11
static PFN_GET_DEBUG_INTERFACE1 DXGIGetDebugInterface1;
#endif // USE_D3D11_DYNAMIC_LIB
#if BGFX_CONFIG_USE_OVR
#include <tinystl/vector.h>
// Oculus Rift eye buffer
struct OVRBufferDX11 : public OVRBufferI
{
OVRBufferDX11(const ovrSession& session, int eyeIdx, ID3D11Device* d3dDevice, ID3D11DeviceContext* d3dCtx)
{
m_d3dDevice = d3dDevice;
m_d3dContext = d3dCtx;
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.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;
ovrResult result = ovr_CreateTextureSwapChainDX(session, d3dDevice, &desc, &m_swapTextureChain);
if (!OVR_SUCCESS(result))
{
BX_CHECK(false, "Could not create D3D11 OVR swap texture");
}
int textureCount = 0;
ovr_GetTextureSwapChainLength(session, m_swapTextureChain, &textureCount);
for (int i = 0; i < textureCount; ++i)
{
ID3D11Texture2D* tex = NULL;
ovr_GetTextureSwapChainBufferDX(session, m_swapTextureChain, i, 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(d3dDevice->CreateRenderTargetView(tex, &rtvd, &rtv));
m_eyeRtv.push_back(rtv);
tex->Release();
}
// 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 = 1;
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(d3dDevice->CreateTexture2D(&dbDesc, NULL, &tex));
DX_CHECK(d3dDevice->CreateDepthStencilView(tex, NULL, &m_depthBuffer));
tex->Release();
}
void onRender(const ovrSession& session)
{
// Clear and set up rendertarget
int texIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(session, m_swapTextureChain, &texIndex);
float black[] = { 0.f, 0.f, 0.f, 0.f }; // Important that alpha=0, if want pixels to be transparent, for manual layers
m_d3dContext->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
m_d3dContext->ClearRenderTargetView(m_eyeRtv[texIndex], black);
m_d3dContext->ClearDepthStencilView(m_depthBuffer, 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.MinDepth = 0;
D3Dvp.MaxDepth = 1;
m_d3dContext->RSSetViewports(1, &D3Dvp);
}
void destroy(const ovrSession& session)
{
for (size_t i = 0; i < m_eyeRtv.size(); ++i)
{
m_eyeRtv[i]->Release();
}
ovr_DestroyTextureSwapChain(session, m_swapTextureChain);
m_depthBuffer->Release();
}
ID3D11Device* m_d3dDevice;
ID3D11DeviceContext* m_d3dContext;
stl::vector<ID3D11RenderTargetView *> m_eyeRtv;
ID3D11DepthStencilView* m_depthBuffer;
};
// Oculus Rift mirror
struct OVRMirrorDX11 : public OVRMirrorI
{
OVRMirrorDX11(ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dCtx,
IDXGISwapChain* d3dSc) : m_d3dDevice(d3dDevice)
, m_d3dContext(d3dCtx)
, m_d3dSwapChain(d3dSc)
{
}
void init(const ovrSession& session, int windowWidth, int windowHeight)
{
m_mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
m_mirrorDesc.Width = windowWidth;
m_mirrorDesc.Height = windowHeight;
ovrResult result = ovr_CreateMirrorTextureDX(session, m_d3dDevice, &m_mirrorDesc, &m_mirrorTexture);
if (!OVR_SUCCESS(result))
{
BX_CHECK(false, "Could not create D3D11 OVR mirror texture");
}
}
void destroy(const ovrSession& session)
{
if (!m_mirrorTexture)
return;
ovr_DestroyMirrorTexture(session, m_mirrorTexture);
m_mirrorTexture = NULL;
}
void blit(const ovrSession& session)
{
if (!m_mirrorTexture)
return;
ID3D11Texture2D* tex = NULL;
ovr_GetMirrorTextureBufferDX(session, m_mirrorTexture, IID_PPV_ARGS(&tex));
ID3D11Texture2D* backBuffer;
DX_CHECK(m_d3dSwapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer));
m_d3dContext->CopyResource(backBuffer, tex);
DX_CHECK(m_d3dSwapChain->Present(0, 0));
tex->Release();
backBuffer->Release();
}
ID3D11Device* m_d3dDevice;
ID3D11DeviceContext* m_d3dContext;
IDXGISwapChain* m_d3dSwapChain;
};
#endif // BGFX_CONFIG_USE_OVR
struct RendererContextD3D11 : public RendererContextI
{
RendererContextD3D11()
@ -635,8 +799,6 @@ namespace bgfx { namespace d3d11
, m_fsChanges(0)
, m_rtMsaa(false)
, m_timerQuerySupport(false)
, m_ovrRtv(NULL)
, m_ovrDsv(NULL)
{
m_fbh.idx = invalidHandle;
memset(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
@ -2001,10 +2163,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t width = getBufferWidth();
uint32_t height = getBufferHeight();
if (m_ovr.isEnabled() )
{
m_ovr.getSize(width, height);
}
FrameBufferHandle fbh = BGFX_INVALID_HANDLE;
setFrameBuffer(fbh, false);
@ -2192,7 +2350,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (SUCCEEDED(hr) )
{
if (!m_ovr.swap(_hmd) )
if (!m_ovr.swap(_hmd, false) )
{
hr = m_swapChain->Present(syncInterval, 0);
}
@ -3083,77 +3241,22 @@ BX_PRAGMA_DIAGNOSTIC_POP();
void ovrPostReset()
{
#if BGFX_CONFIG_USE_OVR
if (m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) )
if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) )
{
ovrD3D11Config config;
config.D3D11.Header.API = ovrRenderAPI_D3D11;
# if OVR_VERSION > OVR_VERSION_043
config.D3D11.Header.BackBufferSize.w = m_scd.BufferDesc.Width;
config.D3D11.Header.BackBufferSize.h = m_scd.BufferDesc.Height;
config.D3D11.pBackBufferUAV = NULL;
# else
config.D3D11.Header.RTSize.w = m_scd.BufferDesc.Width;
config.D3D11.Header.RTSize.h = m_scd.BufferDesc.Height;
# endif // OVR_VERSION > OVR_VERSION_042
config.D3D11.Header.Multisample = 0;
config.D3D11.pDevice = m_device;
config.D3D11.pDeviceContext = m_deviceCtx;
config.D3D11.pBackBufferRT = m_backBufferColor;
config.D3D11.pSwapChain = m_swapChain;
if (m_ovr.postReset(g_platformData.nwh, &config.Config, !!(m_flags & BGFX_RESET_HMD_DEBUG) ) )
if (m_ovr.postReset())
{
uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);
const Memory* mem = alloc(size);
for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
{
// eye buffers need to be initialized only once during application lifetime
if (!m_ovr.m_eyeBuffers[eyeIdx])
{
m_ovr.m_eyeBuffers[eyeIdx] = BX_NEW(g_allocator, OVRBufferDX11(m_ovr.m_hmd, eyeIdx, m_device, m_deviceCtx));
}
}
bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic);
TextureCreate tc;
tc.m_flags = BGFX_TEXTURE_RT|( ((m_flags & BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT) << BGFX_TEXTURE_RT_MSAA_SHIFT);
tc.m_width = m_ovr.m_rtSize.w;
tc.m_height = m_ovr.m_rtSize.h;
tc.m_sides = 0;
tc.m_depth = 0;
tc.m_numMips = 1;
tc.m_format = uint8_t(bgfx::TextureFormat::BGRA8);
tc.m_cubeMap = false;
tc.m_mem = NULL;
bx::write(&writer, tc);
m_ovrRT.create(mem, tc.m_flags, 0);
release(mem);
DX_CHECK(m_device->CreateRenderTargetView(m_ovrRT.m_ptr, NULL, &m_ovrRtv) );
D3D11_TEXTURE2D_DESC dsd;
dsd.Width = m_ovr.m_rtSize.w;
dsd.Height = m_ovr.m_rtSize.h;
dsd.MipLevels = 1;
dsd.ArraySize = 1;
dsd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
dsd.SampleDesc = m_scd.SampleDesc;
dsd.Usage = D3D11_USAGE_DEFAULT;
dsd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
dsd.CPUAccessFlags = 0;
dsd.MiscFlags = 0;
ID3D11Texture2D* depthStencil;
DX_CHECK(m_device->CreateTexture2D(&dsd, NULL, &depthStencil) );
DX_CHECK(m_device->CreateDepthStencilView(depthStencil, NULL, &m_ovrDsv) );
DX_RELEASE(depthStencil, 0);
ovrD3D11Texture texture;
texture.D3D11.Header.API = ovrRenderAPI_D3D11;
texture.D3D11.Header.TextureSize = m_ovr.m_rtSize;
texture.D3D11.pTexture = m_ovrRT.m_texture2d;
texture.D3D11.pSRView = m_ovrRT.m_srv;
m_ovr.postReset(texture.Texture);
bx::xchg(m_ovrRtv, m_backBufferColor);
BX_CHECK(NULL == m_backBufferDepthStencil, "");
bx::xchg(m_ovrDsv, m_backBufferDepthStencil);
// recreate mirror texture
m_ovr.m_mirror = BX_NEW(g_allocator, OVRMirrorDX11(m_device, m_deviceCtx, m_swapChain));
m_ovr.m_mirror->init(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height);
}
}
#endif // BGFX_CONFIG_USE_OVR
@ -3163,16 +3266,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{
#if BGFX_CONFIG_USE_OVR
m_ovr.preReset();
if (NULL != m_ovrRtv)
{
bx::xchg(m_ovrRtv, m_backBufferColor);
bx::xchg(m_ovrDsv, m_backBufferDepthStencil);
BX_CHECK(NULL == m_backBufferDepthStencil, "");
DX_RELEASE(m_ovrRtv, 0);
DX_RELEASE(m_ovrDsv, 0);
m_ovrRT.destroy();
}
#endif // BGFX_CONFIG_USE_OVR
}
@ -3564,9 +3657,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
bool m_timerQuerySupport;
OVR m_ovr;
TextureD3D11 m_ovrRT;
ID3D11RenderTargetView* m_ovrRtv;
ID3D11DepthStencilView* m_ovrDsv;
};
static RendererContextD3D11* s_renderD3D11;
@ -4864,7 +4954,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
_render->m_hmdInitialized = m_ovr.isInitialized();
const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug();
const bool hmdEnabled = m_ovr.isEnabled();
ViewState viewState(_render, hmdEnabled);
bool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME);
@ -4987,6 +5077,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (m_ovr.isEnabled() )
{
m_ovr.getViewport(eye, &viewState.m_rect);
// commit previous eye to HMD and start rendering new frame
m_ovr.commitEye(eye);
m_ovr.renderEyeStart(eye);
}
else
{

Просмотреть файл

@ -1274,6 +1274,144 @@ namespace bgfx { namespace gl
BX_UNUSED(supported);
}
#if BGFX_CONFIG_USE_OVR
// Oculus Rift eye buffer
struct OVRBufferGL : public OVRBufferI
{
OVRBufferGL(const ovrSession& session, int eyeIdx)
{
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_swapTextureChain);
int textureCount = 0;
ovr_GetTextureSwapChainLength(session, m_swapTextureChain, &textureCount);
for (int j = 0; j < textureCount; ++j)
{
GLuint chainTexId;
ovr_GetTextureSwapChainBufferGL(session, m_swapTextureChain, j, &chainTexId);
GL_CHECK(glBindTexture(GL_TEXTURE_2D, chainTexId));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
GL_CHECK(glGenFramebuffers(1, &m_eyeFbo));
// create depth buffer
GL_CHECK(glGenTextures(1, &m_depthBuffer));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
}
void onRender(const ovrSession& session)
{
// set the current eye texture in swap chain
int curIndex;
ovr_GetTextureSwapChainCurrentIndex(session, m_swapTextureChain, &curIndex);
ovr_GetTextureSwapChainBufferGL(session, m_swapTextureChain, curIndex, &m_eyeTexId);
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo));
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0));
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0));
GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h));
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}
void destroy(const ovrSession& session)
{
GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo));
GL_CHECK(glDeleteTextures(1, &m_depthBuffer));
ovr_DestroyTextureSwapChain(session, m_swapTextureChain);
}
GLuint m_eyeFbo;
GLuint m_eyeTexId;
GLuint m_depthBuffer;
};
// Oculus Rift mirror
struct OVRMirrorGL : public OVRMirrorI
{
void init(const ovrSession& session, int windowWidth, int windowHeight)
{
memset(&m_mirrorDesc, 0, sizeof(m_mirrorDesc));
m_mirrorDesc.Width = windowWidth;
m_mirrorDesc.Height = windowHeight;
m_mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
ovr_CreateMirrorTextureGL(session, &m_mirrorDesc, &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 destroy(const ovrSession& session)
{
if (!m_mirrorTexture)
return;
GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO));
ovr_DestroyMirrorTexture(session, m_mirrorTexture);
m_mirrorTexture = NULL;
}
void blit(const ovrSession& /*session*/)
{
if (!m_mirrorTexture)
return;
// Blit mirror texture to back buffer
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO));
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
GLint w = m_mirrorDesc.Width;
GLint h = m_mirrorDesc.Height;
GL_CHECK(glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST));
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
}
GLuint m_mirrorFBO;
};
#endif // BGFX_CONFIG_USE_OVR
struct RendererContextGL : public RendererContextI
{
RendererContextGL()
@ -1304,7 +1442,6 @@ namespace bgfx { namespace gl
, m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT)
, m_backBufferFbo(0)
, m_msaaBackBufferFbo(0)
, m_ovrFbo(0)
{
memset(m_msaaBackBufferRbos, 0, sizeof(m_msaaBackBufferRbos) );
}
@ -2107,10 +2244,9 @@ namespace bgfx { namespace gl
m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain);
}
if (!m_ovr.swap(_hmd) )
{
m_glctx.swap();
}
m_ovr.swap(_hmd, true);
// need to swap GL render context even if OVR is enabled to get the mirror texture in the output
m_glctx.swap();
}
}
@ -2397,10 +2533,6 @@ namespace bgfx { namespace gl
uint32_t width = m_resolution.m_width;
uint32_t height = m_resolution.m_height;
if (m_ovr.isEnabled() )
{
m_ovr.getSize(width, height);
}
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) );
GL_CHECK(glViewport(0, 0, width, height) );
@ -2857,63 +2989,22 @@ namespace bgfx { namespace gl
void ovrPostReset()
{
#if BGFX_CONFIG_USE_OVR
if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) )
if (m_resolution.m_flags & (BGFX_RESET_HMD | BGFX_RESET_HMD_DEBUG))
{
ovrGLConfig config;
config.OGL.Header.API = ovrRenderAPI_OpenGL;
# if OVR_VERSION > OVR_VERSION_043
config.OGL.Header.BackBufferSize.w = m_resolution.m_width;
config.OGL.Header.BackBufferSize.h = m_resolution.m_height;
# else
config.OGL.Header.RTSize.w = m_resolution.m_width;
config.OGL.Header.RTSize.h = m_resolution.m_height;
# endif // OVR_VERSION > OVR_VERSION_043
config.OGL.Header.Multisample = 0;
config.OGL.Window = (HWND)g_platformData.nwh;
config.OGL.DC = GetDC(config.OGL.Window);
if (m_ovr.postReset(g_platformData.nwh, &config.Config, !!(m_resolution.m_flags & BGFX_RESET_HMD_DEBUG) ) )
if (m_ovr.postReset())
{
uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);
const Memory* mem = alloc(size);
for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
{
// eye buffers need to be initialized only once during application lifetime
if (!m_ovr.m_eyeBuffers[eyeIdx])
{
m_ovr.m_eyeBuffers[eyeIdx] = BX_NEW(g_allocator, OVRBufferGL(m_ovr.m_hmd, eyeIdx));
}
}
bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic);
TextureCreate tc;
tc.m_flags = BGFX_TEXTURE_RT|( ((m_resolution.m_flags & BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT) << BGFX_TEXTURE_RT_MSAA_SHIFT);;
tc.m_width = m_ovr.m_rtSize.w;
tc.m_height = m_ovr.m_rtSize.h;
tc.m_sides = 0;
tc.m_depth = 0;
tc.m_numMips = 1;
tc.m_format = uint8_t(bgfx::TextureFormat::BGRA8);
tc.m_cubeMap = false;
tc.m_mem = NULL;
bx::write(&writer, tc);
m_ovrRT.create(mem, tc.m_flags, 0);
release(mem);
m_ovrFbo = m_msaaBackBufferFbo;
GL_CHECK(glGenFramebuffers(1, &m_msaaBackBufferFbo) );
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, m_ovrRT.m_id
, 0
) );
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_ovrFbo) );
ovrGLTexture texture;
texture.OGL.Header.API = ovrRenderAPI_OpenGL;
texture.OGL.Header.TextureSize = m_ovr.m_rtSize;
texture.OGL.TexId = m_ovrRT.m_id;
m_ovr.postReset(texture.Texture);
// recreate mirror texture
m_ovr.m_mirror = BX_NEW(g_allocator, OVRMirrorGL);
m_ovr.m_mirror->init(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height);
}
}
#endif // BGFX_CONFIG_USE_OVR
@ -2923,14 +3014,6 @@ namespace bgfx { namespace gl
{
#if BGFX_CONFIG_USE_OVR
m_ovr.preReset();
if (m_ovr.isEnabled() )
{
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
GL_CHECK(glDeleteFramebuffers(1, &m_msaaBackBufferFbo) );
m_msaaBackBufferFbo = m_ovrFbo;
m_ovrFbo = 0;
m_ovrRT.destroy();
}
#endif // BGFX_CONFIG_USE_OVR
}
@ -3354,8 +3437,6 @@ namespace bgfx { namespace gl
const char* m_glslVersion;
OVR m_ovr;
TextureGL m_ovrRT;
GLint m_ovrFbo;
};
RendererContextGL* s_renderGL;
@ -3647,7 +3728,7 @@ namespace bgfx { namespace gl
}
m_numPredefined = 0;
m_numSamplers = 0;
m_numSamplers = 0;
BX_TRACE("Uniforms (%d):", activeUniforms);
for (int32_t ii = 0; ii < activeUniforms; ++ii)
@ -5439,7 +5520,7 @@ namespace bgfx { namespace gl
_render->m_hmdInitialized = m_ovr.isInitialized();
const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug();
const bool hmdEnabled = m_ovr.isEnabled();
ViewState viewState(_render, hmdEnabled);
uint16_t programIdx = invalidHandle;
@ -5491,12 +5572,13 @@ namespace bgfx { namespace gl
m_occlusionQuery.resolve(_render);
}
uint8_t eye = 0;
if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
{
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
bool viewRestart = false;
uint8_t eye = 0;
uint8_t restartState = 0;
viewState.m_rect = _render->m_rect[0];
@ -5578,6 +5660,9 @@ namespace bgfx { namespace gl
if (m_ovr.isEnabled() )
{
m_ovr.getViewport(eye, &viewState.m_rect);
// commit previous eye to HMD and start rendering new frame
m_ovr.commitEye(eye);
m_ovr.renderEyeStart(eye);
}
else
{
@ -5679,7 +5764,7 @@ namespace bgfx { namespace gl
const RenderCompute& compute = renderItem.compute;
ProgramGL& program = m_program[key.m_program];
GL_CHECK(glUseProgram(program.m_id) );
GL_CHECK(glUseProgram(program.m_id) );
GLbitfield barrier = 0;
for (uint32_t ii = 0; ii < BGFX_MAX_COMPUTE_BINDINGS; ++ii)