mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 19:14:59 +02:00
Threaded Oculus support
This commit is contained in:
parent
a0cc6f8817
commit
d0912c6063
7 changed files with 92 additions and 156 deletions
|
@ -6,7 +6,6 @@
|
|||
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
if (FALSE)
|
||||
if (WIN32)
|
||||
|
||||
# we're using static GLEW, so define GLEW_STATIC
|
||||
|
@ -14,7 +13,7 @@ if (WIN32)
|
|||
|
||||
set(TARGET_NAME oculus)
|
||||
setup_hifi_plugin(Multimedia)
|
||||
link_hifi_libraries(shared gl gpu controllers ui plugins ui-plugins display-plugins input-plugins audio-client networking)
|
||||
link_hifi_libraries(shared gl gpu gpu-gl controllers ui plugins ui-plugins display-plugins input-plugins audio-client networking)
|
||||
|
||||
include_hifi_library_headers(octree)
|
||||
|
||||
|
@ -25,4 +24,3 @@ if (WIN32)
|
|||
target_link_libraries(${TARGET_NAME} Winmm.lib)
|
||||
|
||||
endif()
|
||||
endif()
|
|
@ -10,6 +10,7 @@
|
|||
#include <ViewFrustum.h>
|
||||
#include <controllers/Pose.h>
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include <gpu/Frame.h>
|
||||
|
||||
#include "OculusHelpers.h"
|
||||
|
||||
|
@ -21,7 +22,7 @@ void OculusBaseDisplayPlugin::resetSensors() {
|
|||
|
||||
bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
_currentRenderFrameInfo = FrameInfo();
|
||||
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();;
|
||||
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||
auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue);
|
||||
_currentRenderFrameInfo.renderPose = toGlm(trackingState.HeadPose.ThePose);
|
||||
|
@ -40,7 +41,7 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
handPoses[hand] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
||||
});
|
||||
|
||||
withRenderThreadLock([&] {
|
||||
withNonPresentThreadLock([&] {
|
||||
_uiModelTransform = DependencyManager::get<CompositorHelper>()->getModelTransform();
|
||||
_handPoses = handPoses;
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
|
@ -112,3 +113,12 @@ void OculusBaseDisplayPlugin::internalDeactivate() {
|
|||
releaseOculusSession();
|
||||
_session = nullptr;
|
||||
}
|
||||
|
||||
void OculusBaseDisplayPlugin::updatePresentPose() {
|
||||
//mat4 sensorResetMat;
|
||||
//_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||
//_currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, _currentFrame->frameIndex);
|
||||
//auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse);
|
||||
//_currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose);
|
||||
_currentPresentFrameInfo.presentPose = _currentPresentFrameInfo.renderPose;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ protected:
|
|||
void customizeContext() override;
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
void updatePresentPose() override;
|
||||
|
||||
protected:
|
||||
ovrSession _session { nullptr };
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include <OVR_CAPI_Audio.h>
|
||||
|
||||
#include <shared/NsightHelpers.h>
|
||||
#include <gpu/Frame.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
|
||||
#include "OculusHelpers.h"
|
||||
|
||||
|
@ -43,67 +46,107 @@ void OculusDisplayPlugin::cycleDebugOutput() {
|
|||
|
||||
void OculusDisplayPlugin::customizeContext() {
|
||||
Parent::customizeContext();
|
||||
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_session));
|
||||
_sceneFbo->Init(getRecommendedRenderSize());
|
||||
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y));
|
||||
ovrTextureSwapChainDesc desc = { };
|
||||
desc.Type = ovrTexture_2D;
|
||||
desc.ArraySize = 1;
|
||||
desc.Width = _renderTargetSize.x;
|
||||
desc.Height = _renderTargetSize.y;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
desc.SampleCount = 1;
|
||||
desc.StaticImage = ovrFalse;
|
||||
|
||||
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &_textureSwapChain);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
logFatal("Failed to create swap textures");
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
result = ovr_GetTextureSwapChainLength(_session, _textureSwapChain, &length);
|
||||
if (!OVR_SUCCESS(result) || !length) {
|
||||
qFatal("Unable to count swap chain textures");
|
||||
}
|
||||
for (int i = 0; i < length; ++i) {
|
||||
GLuint chainTexId;
|
||||
ovr_GetTextureSwapChainBufferGL(_session, _textureSwapChain, i, &chainTexId);
|
||||
glBindTexture(GL_TEXTURE_2D, chainTexId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// We're rendering both eyes to the same texture, so only one of the
|
||||
// pointers is populated
|
||||
_sceneLayer.ColorTexture[0] = _sceneFbo->color;
|
||||
_sceneLayer.ColorTexture[0] = _textureSwapChain;
|
||||
// not needed since the structure was zeroed on init, but explicit
|
||||
_sceneLayer.ColorTexture[1] = nullptr;
|
||||
|
||||
enableVsync(false);
|
||||
// Only enable mirroring if we know vsync is disabled
|
||||
_enablePreview = !isVsyncEnabled();
|
||||
|
||||
}
|
||||
|
||||
void OculusDisplayPlugin::uncustomizeContext() {
|
||||
using namespace oglplus;
|
||||
|
||||
#if 0
|
||||
// Present a final black frame to the HMD
|
||||
_compositeFramebuffer->Bound(FramebufferTarget::Draw, [] {
|
||||
Context::ClearColor(0, 0, 0, 1);
|
||||
Context::Clear().ColorBuffer();
|
||||
});
|
||||
|
||||
hmdPresent();
|
||||
|
||||
#if (OVR_MAJOR_VERSION >= 6)
|
||||
_sceneFbo.reset();
|
||||
#endif
|
||||
|
||||
ovr_DestroyTextureSwapChain(_session, _textureSwapChain);
|
||||
_textureSwapChain = nullptr;
|
||||
Parent::uncustomizeContext();
|
||||
}
|
||||
|
||||
|
||||
template <typename SrcFbo, typename DstFbo>
|
||||
void blit(const SrcFbo& srcFbo, const DstFbo& dstFbo) {
|
||||
using namespace oglplus;
|
||||
srcFbo->Bound(FramebufferTarget::Read, [&] {
|
||||
dstFbo->Bound(FramebufferTarget::Draw, [&] {
|
||||
Context::BlitFramebuffer(
|
||||
0, 0, srcFbo->size.x, srcFbo->size.y,
|
||||
0, 0, dstFbo->size.x, dstFbo->size.y,
|
||||
BufferSelectBit::ColorBuffer, BlitFilter::Linear);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void OculusDisplayPlugin::hmdPresent() {
|
||||
|
||||
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentPresentFrameIndex)
|
||||
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
|
||||
|
||||
if (!_currentSceneTexture) {
|
||||
return;
|
||||
// Manually bind the texture to the FBO
|
||||
auto& glBackend = dynamic_cast<gpu::gl::GLBackend&>(*_backend);
|
||||
auto fbo = glBackend.getFramebufferID(_outputFramebuffer);
|
||||
{
|
||||
int curIndex;
|
||||
ovr_GetTextureSwapChainCurrentIndex(_session, _textureSwapChain, &curIndex);
|
||||
GLuint curTexId;
|
||||
ovr_GetTextureSwapChainBufferGL(_session, _textureSwapChain, curIndex, &curTexId);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
blit(_compositeFramebuffer, _sceneFbo);
|
||||
_sceneFbo->Commit();
|
||||
{
|
||||
gpu::Batch batch;
|
||||
batch.enableStereo(false);
|
||||
auto source = _currentFrame->framebuffer;
|
||||
auto sourceRect = ivec4(ivec2(0), source->getSize());
|
||||
auto dest = _outputFramebuffer;
|
||||
auto destRect = ivec4(ivec2(0), dest->getSize());
|
||||
batch.blit(source, sourceRect, dest, destRect);
|
||||
_backend->render(batch);
|
||||
}
|
||||
|
||||
{
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain);
|
||||
Q_ASSERT(OVR_SUCCESS(result));
|
||||
_sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
|
||||
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
|
||||
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
|
||||
ovrLayerHeader* layers = &_sceneLayer.Header;
|
||||
ovrResult result = ovr_SubmitFrame(_session, _currentPresentFrameIndex, &_viewScaleDesc, &layers, 1);
|
||||
result = ovr_SubmitFrame(_session, _currentFrame->frameIndex, &_viewScaleDesc, &layers, 1);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
logWarning("Failed to present");
|
||||
}
|
||||
|
@ -112,11 +155,11 @@ void OculusDisplayPlugin::hmdPresent() {
|
|||
|
||||
bool OculusDisplayPlugin::isHmdMounted() const {
|
||||
ovrSessionStatus status;
|
||||
return (OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)) &&
|
||||
return (OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)) &&
|
||||
(ovrFalse != status.HmdMounted));
|
||||
}
|
||||
|
||||
QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
|
||||
QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
|
||||
WCHAR buffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE];
|
||||
if (!OVR_SUCCESS(ovr_GetAudioDeviceInGuidStr(buffer))) {
|
||||
return QString();
|
||||
|
@ -124,11 +167,10 @@ QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
|
|||
return AudioClient::friendlyNameForAudioDevice(buffer);
|
||||
}
|
||||
|
||||
QString OculusDisplayPlugin::getPreferredAudioOutDevice() const {
|
||||
QString OculusDisplayPlugin::getPreferredAudioOutDevice() const {
|
||||
WCHAR buffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE];
|
||||
if (!OVR_SUCCESS(ovr_GetAudioDeviceOutGuidStr(buffer))) {
|
||||
return QString();
|
||||
}
|
||||
return AudioClient::friendlyNameForAudioDevice(buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
|
||||
#include "OculusBaseDisplayPlugin.h"
|
||||
|
||||
struct SwapFramebufferWrapper;
|
||||
using SwapFboPtr = QSharedPointer<SwapFramebufferWrapper>;
|
||||
|
||||
class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||
using Parent = OculusBaseDisplayPlugin;
|
||||
public:
|
||||
|
@ -34,7 +31,7 @@ private:
|
|||
static const QString NAME;
|
||||
bool _enablePreview { false };
|
||||
bool _monoPreview { true };
|
||||
|
||||
SwapFboPtr _sceneFbo;
|
||||
ovrTextureSwapChain _textureSwapChain;
|
||||
gpu::FramebufferPointer _outputFramebuffer;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <controllers/Input.h>
|
||||
#include <controllers/Pose.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
|
@ -116,94 +117,6 @@ void releaseOculusSession() {
|
|||
}
|
||||
|
||||
|
||||
// A wrapper for constructing and using a swap texture set,
|
||||
// where each frame you draw to a texture via the FBO,
|
||||
// then submit it and increment to the next texture.
|
||||
// The Oculus SDK manages the creation and destruction of
|
||||
// the textures
|
||||
|
||||
SwapFramebufferWrapper::SwapFramebufferWrapper(const ovrSession& session)
|
||||
: _session(session) {
|
||||
color = nullptr;
|
||||
depth = nullptr;
|
||||
}
|
||||
|
||||
SwapFramebufferWrapper::~SwapFramebufferWrapper() {
|
||||
destroyColor();
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::Commit() {
|
||||
auto result = ovr_CommitTextureSwapChain(_session, color);
|
||||
Q_ASSERT(OVR_SUCCESS(result));
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::Resize(const uvec2 & size) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo));
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
this->size = size;
|
||||
initColor();
|
||||
initDone();
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::destroyColor() {
|
||||
if (color) {
|
||||
ovr_DestroyTextureSwapChain(_session, color);
|
||||
color = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::initColor() {
|
||||
destroyColor();
|
||||
|
||||
ovrTextureSwapChainDesc desc = {};
|
||||
desc.Type = ovrTexture_2D;
|
||||
desc.ArraySize = 1;
|
||||
desc.Width = size.x;
|
||||
desc.Height = size.y;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
desc.SampleCount = 1;
|
||||
desc.StaticImage = ovrFalse;
|
||||
|
||||
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &color);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
logFatal("Failed to create swap textures");
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
result = ovr_GetTextureSwapChainLength(_session, color, &length);
|
||||
if (!OVR_SUCCESS(result) || !length) {
|
||||
qFatal("Unable to count swap chain textures");
|
||||
}
|
||||
for (int i = 0; i < length; ++i) {
|
||||
GLuint chainTexId;
|
||||
ovr_GetTextureSwapChainBufferGL(_session, color, i, &chainTexId);
|
||||
glBindTexture(GL_TEXTURE_2D, chainTexId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::initDone() {
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::onBind(oglplus::Framebuffer::Target target) {
|
||||
int curIndex;
|
||||
ovr_GetTextureSwapChainCurrentIndex(_session, color, &curIndex);
|
||||
GLuint curTexId;
|
||||
ovr_GetTextureSwapChainBufferGL(_session, color, curIndex, &curTexId);
|
||||
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
|
||||
}
|
||||
|
||||
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {
|
||||
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
controller::Pose ovrControllerPoseToHandPose(
|
||||
ovrHandType hand,
|
||||
const ovrPoseStatef& handPose) {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <gl/OglplusHelpers.h>
|
||||
#include <controllers/Forward.h>
|
||||
|
||||
void logWarning(const char* what);
|
||||
|
@ -106,30 +105,6 @@ inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
// A wrapper for constructing and using a swap texture set,
|
||||
// where each frame you draw to a texture via the FBO,
|
||||
// then submit it and increment to the next texture.
|
||||
// The Oculus SDK manages the creation and destruction of
|
||||
// the textures
|
||||
struct SwapFramebufferWrapper : public FramebufferWrapper<ovrTextureSwapChain, void*> {
|
||||
SwapFramebufferWrapper(const ovrSession& session);
|
||||
~SwapFramebufferWrapper();
|
||||
void Commit();
|
||||
void Resize(const uvec2 & size);
|
||||
protected:
|
||||
void initColor() override final;
|
||||
void initDepth() override final {}
|
||||
void initDone() override final;
|
||||
void onBind(oglplus::Framebuffer::Target target) override final;
|
||||
void onUnbind(oglplus::Framebuffer::Target target) override final;
|
||||
|
||||
void destroyColor();
|
||||
|
||||
private:
|
||||
ovrSession _session;
|
||||
};
|
||||
|
||||
controller::Pose ovrControllerPoseToHandPose(
|
||||
ovrHandType hand,
|
||||
const ovrPoseStatef& handPose);
|
||||
|
|
Loading…
Reference in a new issue