mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 08:53:10 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into report45hzTarget
This commit is contained in:
commit
c3f5df8f0b
12 changed files with 174 additions and 100 deletions
4
cmake/externals/openvr/CMakeLists.txt
vendored
4
cmake/externals/openvr/CMakeLists.txt
vendored
|
@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL https://github.com/ValveSoftware/openvr/archive/v1.0.2.zip
|
URL https://github.com/ValveSoftware/openvr/archive/v1.0.3.zip
|
||||||
URL_MD5 0d1cf5f579cf092e33f34759967b7046
|
URL_MD5 b484b12901917cc739e40389583c8b0d
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
|
@ -17,6 +17,12 @@ macro(SETUP_HIFI_PLUGIN)
|
||||||
set(PLUGIN_PATH "plugins")
|
set(PLUGIN_PATH "plugins")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
# produce PDB files for plugins as well
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
||||||
set(PLUGIN_FULL_PATH "${CMAKE_BINARY_DIR}/interface/${PLUGIN_PATH}/")
|
set(PLUGIN_FULL_PATH "${CMAKE_BINARY_DIR}/interface/${PLUGIN_PATH}/")
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -534,6 +534,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
|
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
|
||||||
_lastFaceTrackerUpdate(0)
|
_lastFaceTrackerUpdate(0)
|
||||||
{
|
{
|
||||||
|
setProperty("com.highfidelity.launchedFromSteam", SteamClient::isRunning());
|
||||||
|
|
||||||
_runningMarker.startRunningMarker();
|
_runningMarker.startRunningMarker();
|
||||||
|
|
||||||
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
|
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
|
||||||
|
|
|
@ -338,6 +338,9 @@ Menu::Menu() {
|
||||||
// Developer > Render > Throttle FPS If Not Focus
|
// Developer > Render > Throttle FPS If Not Focus
|
||||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true);
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true);
|
||||||
|
|
||||||
|
// Developer > Render > OpenVR threaded submit
|
||||||
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::OpenVrThreadedSubmit, 0, true);
|
||||||
|
|
||||||
// Developer > Render > Resolution
|
// Developer > Render > Resolution
|
||||||
MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution);
|
MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution);
|
||||||
QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu);
|
QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu);
|
||||||
|
@ -617,6 +620,14 @@ Menu::Menu() {
|
||||||
// Developer > Audio >>>
|
// Developer > Audio >>>
|
||||||
MenuWrapper* audioDebugMenu = developerMenu->addMenu("Audio");
|
MenuWrapper* audioDebugMenu = developerMenu->addMenu("Audio");
|
||||||
|
|
||||||
|
action = addActionToQMenuAndActionHash(audioDebugMenu, "Stats...");
|
||||||
|
connect(action, &QAction::triggered, [] {
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
|
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||||
|
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/audio/stats.js");
|
||||||
|
scriptEngines->loadScript(defaultScriptsLoc.toString());
|
||||||
|
});
|
||||||
|
|
||||||
action = addActionToQMenuAndActionHash(audioDebugMenu, "Buffers...");
|
action = addActionToQMenuAndActionHash(audioDebugMenu, "Buffers...");
|
||||||
connect(action, &QAction::triggered, [] {
|
connect(action, &QAction::triggered, [] {
|
||||||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AudioPreferencesDialog.qml"), "AudioPreferencesDialog");
|
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AudioPreferencesDialog.qml"), "AudioPreferencesDialog");
|
||||||
|
|
|
@ -136,6 +136,7 @@ namespace MenuOption {
|
||||||
const QString OctreeStats = "Entity Statistics";
|
const QString OctreeStats = "Entity Statistics";
|
||||||
const QString OnePointCalibration = "1 Point Calibration";
|
const QString OnePointCalibration = "1 Point Calibration";
|
||||||
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
||||||
|
const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit";
|
||||||
const QString OutputMenu = "Display";
|
const QString OutputMenu = "Display";
|
||||||
const QString Overlays = "Overlays";
|
const QString Overlays = "Overlays";
|
||||||
const QString PackageModel = "Package Model...";
|
const QString PackageModel = "Package Model...";
|
||||||
|
|
|
@ -32,6 +32,7 @@ using namespace udt;
|
||||||
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
_synTimer(new QTimer(this)),
|
_synTimer(new QTimer(this)),
|
||||||
|
_readyReadBackupTimer(new QTimer(this)),
|
||||||
_shouldChangeSocketOptions(shouldChangeSocketOptions)
|
_shouldChangeSocketOptions(shouldChangeSocketOptions)
|
||||||
{
|
{
|
||||||
connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams);
|
connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams);
|
||||||
|
@ -46,6 +47,11 @@ Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
||||||
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
|
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||||
this, SLOT(handleSocketError(QAbstractSocket::SocketError)));
|
this, SLOT(handleSocketError(QAbstractSocket::SocketError)));
|
||||||
connect(&_udpSocket, &QAbstractSocket::stateChanged, this, &Socket::handleStateChanged);
|
connect(&_udpSocket, &QAbstractSocket::stateChanged, this, &Socket::handleStateChanged);
|
||||||
|
|
||||||
|
// in order to help track down the zombie server bug, add a timer to check if we missed a readyRead
|
||||||
|
const int READY_READ_BACKUP_CHECK_MSECS = 10 * 1000;
|
||||||
|
connect(_readyReadBackupTimer, &QTimer::timeout, this, &Socket::checkForReadyReadBackup);
|
||||||
|
_readyReadBackupTimer->start(READY_READ_BACKUP_CHECK_MSECS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::bind(const QHostAddress& address, quint16 port) {
|
void Socket::bind(const QHostAddress& address, quint16 port) {
|
||||||
|
@ -296,9 +302,25 @@ void Socket::messageFailed(Connection* connection, Packet::MessageNumber message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::checkForReadyReadBackup() {
|
||||||
|
if (_udpSocket.hasPendingDatagrams()) {
|
||||||
|
qCDebug(networking) << "Socket::checkForReadyReadBackup() detected blocked readyRead signal. Flushing pending datagrams.";
|
||||||
|
|
||||||
|
// drop all of the pending datagrams on the floor
|
||||||
|
while (_udpSocket.hasPendingDatagrams()) {
|
||||||
|
_udpSocket.readDatagram(nullptr, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Socket::readPendingDatagrams() {
|
void Socket::readPendingDatagrams() {
|
||||||
int packetSizeWithHeader = -1;
|
int packetSizeWithHeader = -1;
|
||||||
|
|
||||||
while ((packetSizeWithHeader = _udpSocket.pendingDatagramSize()) != -1) {
|
while ((packetSizeWithHeader = _udpSocket.pendingDatagramSize()) != -1) {
|
||||||
|
|
||||||
|
// we're reading a packet so re-start the readyRead backup timer
|
||||||
|
_readyReadBackupTimer->start();
|
||||||
|
|
||||||
// grab a time point we can mark as the receive time of this packet
|
// grab a time point we can mark as the receive time of this packet
|
||||||
auto receiveTime = p_high_resolution_clock::now();
|
auto receiveTime = p_high_resolution_clock::now();
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ public slots:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
|
void checkForReadyReadBackup();
|
||||||
void rateControlSync();
|
void rateControlSync();
|
||||||
|
|
||||||
void handleSocketError(QAbstractSocket::SocketError socketError);
|
void handleSocketError(QAbstractSocket::SocketError socketError);
|
||||||
|
@ -136,6 +137,8 @@ private:
|
||||||
int _synInterval { 10 }; // 10ms
|
int _synInterval { 10 }; // 10ms
|
||||||
QTimer* _synTimer { nullptr };
|
QTimer* _synTimer { nullptr };
|
||||||
|
|
||||||
|
QTimer* _readyReadBackupTimer { nullptr };
|
||||||
|
|
||||||
int _maxBandwidth { -1 };
|
int _maxBandwidth { -1 };
|
||||||
|
|
||||||
std::unique_ptr<CongestionControlVirtualFactory> _ccFactory { new CongestionControlFactory<TCPVegasCC>() };
|
std::unique_ptr<CongestionControlVirtualFactory> _ccFactory { new CongestionControlFactory<TCPVegasCC>() };
|
||||||
|
|
|
@ -44,33 +44,40 @@ void BatchLoader::start() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (const auto& rawURL : _urls) {
|
for (const auto& rawURL : _urls) {
|
||||||
QUrl url = expandScriptUrl(normalizeScriptURL(rawURL));
|
QUrl url = expandScriptUrl(normalizeScriptURL(rawURL));
|
||||||
|
|
||||||
qCDebug(scriptengine) << "Loading script at " << url;
|
qCDebug(scriptengine) << "Loading script at " << url;
|
||||||
|
|
||||||
QPointer<BatchLoader> self = this;
|
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||||
DependencyManager::get<ScriptCache>()->getScriptContents(url.toString(), [this, self](const QString& url, const QString& contents, bool isURL, bool success) {
|
|
||||||
if (!self) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Because the ScriptCache may call this callback from differents threads,
|
// Use a proxy callback to handle the call and emit the signal in a thread-safe way.
|
||||||
// we need to make sure this is thread-safe.
|
// If BatchLoader is deleted before the callback is called, the subsequent "emit" call will not do
|
||||||
std::lock_guard<std::mutex> lock(_dataLock);
|
// anything.
|
||||||
|
ScriptCacheSignalProxy* proxy = new ScriptCacheSignalProxy(scriptCache.data());
|
||||||
|
scriptCache->getScriptContents(url.toString(), [proxy](const QString& url, const QString& contents, bool isURL, bool success) {
|
||||||
|
proxy->receivedContent(url, contents, isURL, success);
|
||||||
|
proxy->deleteLater();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
connect(proxy, &ScriptCacheSignalProxy::contentAvailable, this, [this](const QString& url, const QString& contents, bool isURL, bool success) {
|
||||||
if (isURL && success) {
|
if (isURL && success) {
|
||||||
_data.insert(url, contents);
|
_data.insert(url, contents);
|
||||||
qCDebug(scriptengine) << "Loaded: " << url;
|
qCDebug(scriptengine) << "Loaded: " << url;
|
||||||
} else {
|
} else {
|
||||||
_data.insert(url, QString());
|
_data.insert(url, QString());
|
||||||
qCDebug(scriptengine) << "Could not load" << url;
|
qCDebug(scriptengine) << "Could not load: " << url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_finished && _urls.size() == _data.size()) {
|
if (!_finished && _urls.size() == _data.size()) {
|
||||||
_finished = true;
|
_finished = true;
|
||||||
emit finished(_data);
|
emit finished(_data);
|
||||||
}
|
}
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptCacheSignalProxy::receivedContent(const QString& url, const QString& contents, bool isURL, bool success) {
|
||||||
|
emit contentAvailable(url, contents, isURL, success);
|
||||||
|
}
|
||||||
|
|
|
@ -21,10 +21,20 @@
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
class ScriptCacheSignalProxy : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ScriptCacheSignalProxy(QObject* parent) : QObject(parent) { }
|
||||||
|
void receivedContent(const QString& url, const QString& contents, bool isURL, bool success);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void contentAvailable(const QString& url, const QString& contents, bool isURL, bool success);
|
||||||
|
};
|
||||||
|
|
||||||
class BatchLoader : public QObject {
|
class BatchLoader : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BatchLoader(const QList<QUrl>& urls) ;
|
BatchLoader(const QList<QUrl>& urls);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
bool isFinished() const { return _finished; };
|
bool isFinished() const { return _finished; };
|
||||||
|
@ -39,7 +49,6 @@ private:
|
||||||
bool _finished;
|
bool _finished;
|
||||||
QSet<QUrl> _urls;
|
QSet<QUrl> _urls;
|
||||||
QMap<QUrl, QString> _data;
|
QMap<QUrl, QString> _data;
|
||||||
std::mutex _dataLock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_BatchLoader_h
|
#endif // hifi_BatchLoader_h
|
||||||
|
|
|
@ -35,6 +35,7 @@ Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||||
|
|
||||||
const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)");
|
const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)");
|
||||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
||||||
|
const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit"; // this probably shouldn't be hardcoded here
|
||||||
|
|
||||||
PoseData _nextRenderPoseData;
|
PoseData _nextRenderPoseData;
|
||||||
PoseData _nextSimPoseData;
|
PoseData _nextSimPoseData;
|
||||||
|
@ -48,8 +49,6 @@ bool _openVrDisplayActive { false };
|
||||||
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 };
|
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 };
|
||||||
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 };
|
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 };
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
|
||||||
|
|
||||||
#define REPROJECTION_BINDING 1
|
#define REPROJECTION_BINDING 1
|
||||||
|
|
||||||
static const char* HMD_REPROJECTION_VERT = R"SHADER(
|
static const char* HMD_REPROJECTION_VERT = R"SHADER(
|
||||||
|
@ -350,8 +349,6 @@ public:
|
||||||
OpenVrDisplayPlugin& _plugin;
|
OpenVrDisplayPlugin& _plugin;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool OpenVrDisplayPlugin::isSupported() const {
|
bool OpenVrDisplayPlugin::isSupported() const {
|
||||||
return openVrSupported();
|
return openVrSupported();
|
||||||
}
|
}
|
||||||
|
@ -379,6 +376,9 @@ void OpenVrDisplayPlugin::init() {
|
||||||
emit deviceConnected(getName());
|
emit deviceConnected(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME remove once OpenVR header is updated
|
||||||
|
#define VRCompositor_ReprojectionAsync 0x04
|
||||||
|
|
||||||
bool OpenVrDisplayPlugin::internalActivate() {
|
bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
if (!_system) {
|
if (!_system) {
|
||||||
_system = acquireOpenVrSystem();
|
_system = acquireOpenVrSystem();
|
||||||
|
@ -397,6 +397,15 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vr::Compositor_FrameTiming timing;
|
||||||
|
memset(&timing, 0, sizeof(timing));
|
||||||
|
timing.m_nSize = sizeof(vr::Compositor_FrameTiming);
|
||||||
|
vr::VRCompositor()->GetFrameTiming(&timing);
|
||||||
|
bool asyncReprojectionActive = timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync;
|
||||||
|
|
||||||
|
_threadedSubmit = !asyncReprojectionActive;
|
||||||
|
qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit;
|
||||||
|
|
||||||
_openVrDisplayActive = true;
|
_openVrDisplayActive = true;
|
||||||
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
||||||
|
|
||||||
|
@ -437,16 +446,16 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
if (_threadedSubmit) {
|
||||||
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
||||||
if (!_submitCanvas) {
|
if (!_submitCanvas) {
|
||||||
withMainThreadContext([&] {
|
withMainThreadContext([&] {
|
||||||
_submitCanvas = std::make_shared<gl::OffscreenContext>();
|
_submitCanvas = std::make_shared<gl::OffscreenContext>();
|
||||||
_submitCanvas->create();
|
_submitCanvas->create();
|
||||||
_submitCanvas->doneCurrent();
|
_submitCanvas->doneCurrent();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return Parent::internalActivate();
|
return Parent::internalActivate();
|
||||||
}
|
}
|
||||||
|
@ -476,27 +485,27 @@ void OpenVrDisplayPlugin::customizeContext() {
|
||||||
|
|
||||||
Parent::customizeContext();
|
Parent::customizeContext();
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
if (_threadedSubmit) {
|
||||||
_compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0);
|
_compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0);
|
||||||
for (size_t i = 0; i < COMPOSITING_BUFFER_SIZE; ++i) {
|
for (size_t i = 0; i < COMPOSITING_BUFFER_SIZE; ++i) {
|
||||||
if (0 != i) {
|
if (0 != i) {
|
||||||
_compositeInfos[i].texture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT)));
|
_compositeInfos[i].texture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT)));
|
||||||
|
}
|
||||||
|
_compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false);
|
||||||
}
|
}
|
||||||
_compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false);
|
_submitThread->_canvas = _submitCanvas;
|
||||||
|
_submitThread->start(QThread::HighPriority);
|
||||||
}
|
}
|
||||||
_submitThread->_canvas = _submitCanvas;
|
|
||||||
_submitThread->start(QThread::HighPriority);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::uncustomizeContext() {
|
void OpenVrDisplayPlugin::uncustomizeContext() {
|
||||||
Parent::uncustomizeContext();
|
Parent::uncustomizeContext();
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
if (_threadedSubmit) {
|
||||||
_submitThread->_quit = true;
|
_submitThread->_quit = true;
|
||||||
_submitThread->wait();
|
_submitThread->wait();
|
||||||
_submitThread.reset();
|
_submitThread.reset();
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::resetSensors() {
|
void OpenVrDisplayPlugin::resetSensors() {
|
||||||
|
@ -585,75 +594,76 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::compositeLayers() {
|
void OpenVrDisplayPlugin::compositeLayers() {
|
||||||
#if OPENVR_THREADED_SUBMIT
|
if (_threadedSubmit) {
|
||||||
++_renderingIndex;
|
++_renderingIndex;
|
||||||
_renderingIndex %= COMPOSITING_BUFFER_SIZE;
|
_renderingIndex %= COMPOSITING_BUFFER_SIZE;
|
||||||
|
|
||||||
auto& newComposite = _compositeInfos[_renderingIndex];
|
auto& newComposite = _compositeInfos[_renderingIndex];
|
||||||
newComposite.pose = _currentPresentFrameInfo.presentPose;
|
newComposite.pose = _currentPresentFrameInfo.presentPose;
|
||||||
_compositeFramebuffer->setRenderBuffer(0, newComposite.texture);
|
_compositeFramebuffer->setRenderBuffer(0, newComposite.texture);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
Parent::compositeLayers();
|
Parent::compositeLayers();
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
if (_threadedSubmit) {
|
||||||
newComposite.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
auto& newComposite = _compositeInfos[_renderingIndex];
|
||||||
// https://www.opengl.org/registry/specs/ARB/sync.txt:
|
newComposite.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
// > The simple flushing behavior defined by
|
// https://www.opengl.org/registry/specs/ARB/sync.txt:
|
||||||
// > SYNC_FLUSH_COMMANDS_BIT will not help when waiting for a fence
|
// > The simple flushing behavior defined by
|
||||||
// > command issued in another context's command stream to complete.
|
// > SYNC_FLUSH_COMMANDS_BIT will not help when waiting for a fence
|
||||||
// > Applications which block on a fence sync object must take
|
// > command issued in another context's command stream to complete.
|
||||||
// > additional steps to assure that the context from which the
|
// > Applications which block on a fence sync object must take
|
||||||
// > corresponding fence command was issued has flushed that command
|
// > additional steps to assure that the context from which the
|
||||||
// > to the graphics pipeline.
|
// > corresponding fence command was issued has flushed that command
|
||||||
glFlush();
|
// > to the graphics pipeline.
|
||||||
|
glFlush();
|
||||||
|
|
||||||
if (!newComposite.textureID) {
|
if (!newComposite.textureID) {
|
||||||
newComposite.textureID = getGLBackend()->getTextureID(newComposite.texture, false);
|
newComposite.textureID = getGLBackend()->getTextureID(newComposite.texture, false);
|
||||||
|
}
|
||||||
|
withPresentThreadLock([&] {
|
||||||
|
_submitThread->update(newComposite);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
withPresentThreadLock([&] {
|
|
||||||
_submitThread->update(newComposite);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::hmdPresent() {
|
void OpenVrDisplayPlugin::hmdPresent() {
|
||||||
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
|
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
if (_threadedSubmit) {
|
||||||
_submitThread->waitForPresent();
|
_submitThread->waitForPresent();
|
||||||
#else
|
} else {
|
||||||
GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0), false);
|
GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0), false);
|
||||||
vr::Texture_t vrTexture{ (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto };
|
vr::Texture_t vrTexture { (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto };
|
||||||
vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT);
|
vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT);
|
||||||
vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT);
|
vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT);
|
||||||
vr::VRCompositor()->PostPresentHandoff();
|
vr::VRCompositor()->PostPresentHandoff();
|
||||||
#endif
|
_presentRate.increment();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::postPreview() {
|
void OpenVrDisplayPlugin::postPreview() {
|
||||||
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
|
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
|
||||||
PoseData nextRender, nextSim;
|
PoseData nextRender, nextSim;
|
||||||
nextRender.frameIndex = presentCount();
|
nextRender.frameIndex = presentCount();
|
||||||
#if !OPENVR_THREADED_SUBMIT
|
|
||||||
vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount);
|
|
||||||
|
|
||||||
glm::mat4 resetMat;
|
|
||||||
withPresentThreadLock([&] {
|
|
||||||
resetMat = _sensorResetMat;
|
|
||||||
});
|
|
||||||
nextRender.update(resetMat);
|
|
||||||
nextSim.update(resetMat);
|
|
||||||
withPresentThreadLock([&] {
|
|
||||||
_nextSimPoseData = nextSim;
|
|
||||||
});
|
|
||||||
_nextRenderPoseData = nextRender;
|
|
||||||
|
|
||||||
// FIXME - this looks wrong!
|
|
||||||
_hmdActivityLevel = vr::k_EDeviceActivityLevel_UserInteraction; // _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd);
|
|
||||||
#else
|
|
||||||
_hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd);
|
_hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd);
|
||||||
#endif
|
|
||||||
|
if (!_threadedSubmit) {
|
||||||
|
vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount);
|
||||||
|
|
||||||
|
glm::mat4 resetMat;
|
||||||
|
withPresentThreadLock([&] {
|
||||||
|
resetMat = _sensorResetMat;
|
||||||
|
});
|
||||||
|
nextRender.update(resetMat);
|
||||||
|
nextSim.update(resetMat);
|
||||||
|
withPresentThreadLock([&] {
|
||||||
|
_nextSimPoseData = nextSim;
|
||||||
|
});
|
||||||
|
_nextRenderPoseData = nextRender;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenVrDisplayPlugin::isHmdMounted() const {
|
bool OpenVrDisplayPlugin::isHmdMounted() const {
|
||||||
|
@ -687,3 +697,7 @@ void OpenVrDisplayPlugin::unsuppressKeyboard() {
|
||||||
bool OpenVrDisplayPlugin::isKeyboardVisible() {
|
bool OpenVrDisplayPlugin::isKeyboardVisible() {
|
||||||
return isOpenVrKeyboardShown();
|
return isOpenVrKeyboardShown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OpenVrDisplayPlugin::getRequiredThreadCount() const {
|
||||||
|
return Parent::getRequiredThreadCount() + (_threadedSubmit ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
|
|
||||||
const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only.
|
const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only.
|
||||||
|
|
||||||
#define OPENVR_THREADED_SUBMIT 1
|
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
|
||||||
namespace gl {
|
namespace gl {
|
||||||
class OffscreenContext;
|
class OffscreenContext;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +31,6 @@ struct CompositeInfo {
|
||||||
glm::mat4 pose;
|
glm::mat4 pose;
|
||||||
GLsync fence{ 0 };
|
GLsync fence{ 0 };
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class OpenVrDisplayPlugin : public HmdDisplayPlugin {
|
class OpenVrDisplayPlugin : public HmdDisplayPlugin {
|
||||||
using Parent = HmdDisplayPlugin;
|
using Parent = HmdDisplayPlugin;
|
||||||
|
@ -58,8 +54,8 @@ public:
|
||||||
void unsuppressKeyboard() override;
|
void unsuppressKeyboard() override;
|
||||||
bool isKeyboardVisible() override;
|
bool isKeyboardVisible() override;
|
||||||
|
|
||||||
// Needs an additional thread for VR submission
|
// Possibly needs an additional thread for VR submission
|
||||||
int getRequiredThreadCount() const override { return Parent::getRequiredThreadCount() + 1; }
|
int getRequiredThreadCount() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool internalActivate() override;
|
bool internalActivate() override;
|
||||||
|
@ -71,7 +67,6 @@ protected:
|
||||||
bool isHmdMounted() const override;
|
bool isHmdMounted() const override;
|
||||||
void postPreview() override;
|
void postPreview() override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vr::IVRSystem* _system { nullptr };
|
vr::IVRSystem* _system { nullptr };
|
||||||
std::atomic<vr::EDeviceActivityLevel> _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown };
|
std::atomic<vr::EDeviceActivityLevel> _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown };
|
||||||
|
@ -80,12 +75,11 @@ private:
|
||||||
|
|
||||||
vr::HmdMatrix34_t _lastGoodHMDPose;
|
vr::HmdMatrix34_t _lastGoodHMDPose;
|
||||||
mat4 _sensorResetMat;
|
mat4 _sensorResetMat;
|
||||||
|
bool _threadedSubmit { true };
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
|
||||||
CompositeInfo::Array _compositeInfos;
|
CompositeInfo::Array _compositeInfos;
|
||||||
size_t _renderingIndex { 0 };
|
size_t _renderingIndex { 0 };
|
||||||
std::shared_ptr<OpenVrSubmitThread> _submitThread;
|
std::shared_ptr<OpenVrSubmitThread> _submitThread;
|
||||||
std::shared_ptr<gl::OffscreenContext> _submitCanvas;
|
std::shared_ptr<gl::OffscreenContext> _submitCanvas;
|
||||||
friend class OpenVrSubmitThread;
|
friend class OpenVrSubmitThread;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -210,6 +210,11 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch&
|
||||||
|
|
||||||
|
|
||||||
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
|
|
||||||
|
if (!_system) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
handleOpenVrEvents();
|
handleOpenVrEvents();
|
||||||
if (openVrQuitRequested()) {
|
if (openVrQuitRequested()) {
|
||||||
|
|
Loading…
Reference in a new issue