mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-19 13:32:59 +01:00
Merge pull request #920 from mendsley/vr_reorg
Add a new platform agnostic bgfx::VR internal class
This commit is contained in:
205
src/hmd.cpp
Normal file
205
src/hmd.cpp
Normal file
@@ -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
|
||||
102
src/hmd.h
Normal file
102
src/hmd.h
Normal file
@@ -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
|
||||
323
src/hmd_ovr.cpp
323
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<ovrEyeType>(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
|
||||
|
||||
168
src/hmd_ovr.h
168
src/hmd_ovr.h
@@ -10,6 +10,7 @@
|
||||
|
||||
#if BGFX_CONFIG_USE_OVR
|
||||
|
||||
# include "hmd.h"
|
||||
# include <OVR_Version.h>
|
||||
|
||||
# define OVR_VERSION_(_a, _b, _c) (_a * 10000 + _b * 100 + _c)
|
||||
@@ -25,160 +26,41 @@
|
||||
# include <OVR_CAPI_GL.h>
|
||||
# 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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
# include "renderer_gl.h"
|
||||
# include <bx/timer.h>
|
||||
# include <bx/uint32_t.h>
|
||||
# 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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user