diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 8fe618b70d..56416809d1 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include "AssignmentClient.h" #include "AssignmentClientLogging.h" #include "avatars/ScriptableAvatar.h" +#include const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client"; const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000; @@ -49,8 +49,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri { LogUtils::init(); - QSettings::setDefaultFormat(QSettings::IniFormat); - + DependencyManager::set(); DependencyManager::set(); auto scriptableAvatar = DependencyManager::set(); diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 68e7b9b997..90d759dffa 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -40,11 +39,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : ShutdownEventListener::getInstance(); # endif - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); - setOrganizationDomain("highfidelity.io"); - setApplicationName("assignment-client"); - setApplicationVersion(BuildInfo::VERSION); - // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity Assignment Client"); diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index cf8d9ebe31..4f64bf8f7f 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -13,10 +13,16 @@ #include #include "AssignmentClientApp.h" +#include int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + QCoreApplication::setApplicationName(BuildInfo::ASSIGNMENT_CLIENT_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + qInstallMessageHandler(LogHandler::verboseMessageHandler); qInfo() << "Starting."; diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 3d388a907f..b0af1c0524 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -1,6 +1,6 @@ // // BuildInfo.h.in -// cmake/macros +// cmake/templates // // Created by Stephen Birarda on 1/14/16. // Copyright 2015 High Fidelity, Inc. @@ -11,10 +11,19 @@ #define USE_STABLE_GLOBAL_SERVICES @USE_STABLE_GLOBAL_SERVICES@ +#include + namespace BuildInfo { + // WARNING: This file has been auto-generated. + // Check cmake/templates/BuildInfo.h.in if you want to modify it. + + const QString INTERFACE_NAME = "Interface"; + const QString ASSIGNMENT_CLIENT_NAME = "assignment-client"; + const QString DOMAIN_SERVER_NAME = "domain-server"; + const QString AC_CLIENT_SERVER_NAME = "ac-client"; const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@"; + const QString ORGANIZATION_DOMAIN = "highfidelity.io"; const QString VERSION = "@BUILD_VERSION@"; const QString BUILD_BRANCH = "@BUILD_BRANCH@"; const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@"; } - diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6668ed54dc..e531812077 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -43,6 +43,7 @@ #include "DomainServerNodeData.h" #include "NodeConnectionData.h" +#include int const DomainServer::EXIT_CODE_REBOOT = 234923; @@ -73,17 +74,12 @@ DomainServer::DomainServer(int argc, char* argv[]) : { parseCommandLine(); + DependencyManager::set(); + LogUtils::init(); Setting::init(); - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); - setOrganizationDomain("highfidelity.io"); - setApplicationName("domain-server"); - setApplicationVersion(BuildInfo::VERSION); - QSettings::setDefaultFormat(QSettings::IniFormat); - qDebug() << "Setting up domain-server"; - qDebug() << "[VERSION] Build sequence:" << qPrintable(applicationVersion()); qDebug() << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION; qDebug() << "[VERSION] VERSION:" << BuildInfo::VERSION; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index c49e591e4c..5b862795b7 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainServerSettingsManager.h" + #include #include @@ -16,23 +18,21 @@ #include #include #include -#include #include #include #include -#include #include +#include #include #include #include #include #include +#include #include "DomainServerNodeData.h" -#include "DomainServerSettingsManager.h" - const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/describe-settings.json"; const QString DESCRIPTION_SETTINGS_KEY = "settings"; @@ -43,6 +43,8 @@ const QString DESCRIPTION_COLUMNS_KEY = "columns"; const QString SETTINGS_VIEWPOINT_KEY = "viewpoint"; +static Setting::Handle JSON_SETTING_VERSION("json-settings/version", 0.0); + DomainServerSettingsManager::DomainServerSettingsManager() : _descriptionArray(), _configMap() @@ -103,9 +105,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // What settings version were we before and what are we using now? // Do we need to do any re-mapping? - QSettings appSettings; - const QString JSON_SETTINGS_VERSION_KEY = "json-settings/version"; - double oldVersion = appSettings.value(JSON_SETTINGS_VERSION_KEY, 0.0).toDouble(); + double oldVersion = JSON_SETTING_VERSION.get(); if (oldVersion != _descriptionVersion) { const QString ALLOWED_USERS_SETTINGS_KEYPATH = "security.allowed_users"; @@ -301,7 +301,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList unpackPermissions(); // write the current description version to our settings - appSettings.setValue(JSON_SETTINGS_VERSION_KEY, _descriptionVersion); + JSON_SETTING_VERSION.set(_descriptionVersion); } QVariantMap& DomainServerSettingsManager::getDescriptorsMap() { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index ee62b213e6..1bc0235272 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -21,6 +22,8 @@ #include #include "NodePermissions.h" +#include + const QString SETTINGS_PATHS_KEY = "paths"; const QString SETTINGS_PATH = "/settings"; diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index fdf7a598aa..725a04ec46 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -17,12 +17,18 @@ #include #include +#include #include "DomainServer.h" int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + QCoreApplication::setApplicationName(BuildInfo::DOMAIN_SERVER_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index e32df6bc62..868a2cf933 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -166,6 +166,7 @@ if (WIN32) add_dependency_external_projects(OpenVR) add_dependency_external_projects(neuron) add_dependency_external_projects(wasapi) + add_dependency_external_projects(steamworks) endif() # disable /OPT:REF and /OPT:ICF for the Debug builds @@ -175,10 +176,6 @@ if (WIN32) set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "/OPT:NOREF /OPT:NOICF") endif() -if (NOT ANDROID) - set(NON_ANDROID_LIBRARIES steamworks-wrapper) -endif () - # link required hifi libraries link_hifi_libraries( shared octree gpu gl gpu-gl procedural model render diff --git a/interface/resources/info/ApplicationInfo.ini b/interface/resources/info/ApplicationInfo.ini deleted file mode 100644 index 1a7142cb76..0000000000 --- a/interface/resources/info/ApplicationInfo.ini +++ /dev/null @@ -1,4 +0,0 @@ -[INFO] -name=Interface -organizationName=High Fidelity -organizationDomain=highfidelity.io \ No newline at end of file diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml new file mode 100644 index 0000000000..ffb42d2fff --- /dev/null +++ b/interface/resources/qml/hifi/NameCard.qml @@ -0,0 +1,36 @@ +// +// NameCard.qml +// qml/hifi +// +// Created by Howard Stearns on 12/9/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.5 +import "../styles-uit" + + +Column { + property string displayName: ""; + property string userName: ""; + property int displayTextHeight: 18; + property int usernameTextHeight: 12; + + RalewaySemiBold { + text: parent.displayName; + size: parent.displayTextHeight; + elide: Text.ElideRight; + width: parent.width; + } + RalewayLight { + visible: parent.displayName; + text: parent.userName; + size: parent.usernameTextHeight; + elide: Text.ElideRight; + width: parent.width; + } +} diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml new file mode 100644 index 0000000000..382b8fc962 --- /dev/null +++ b/interface/resources/qml/hifi/Pal.qml @@ -0,0 +1,207 @@ +// +// Pal.qml +// qml/hifi +// +// People Action List +// +// Created by Howard Stearns on 12/12/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +/* TODO: + + prototype: + - only show kick/mute when canKick + - margins everywhere + - column head centering + - column head font + - proper button .svg on toolbar + + mvp: + - Show all participants, including ignored, and populate initial ignore/mute status. + - If name is elided, hover should scroll name left so the full name can be read. + + */ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Rectangle { + id: pal; + property int keepFromHorizontalScroll: 1; + width: parent.width - keepFromHorizontalScroll; + height: parent.height; + + property int nameWidth: width/2; + property int actionWidth: nameWidth / (table.columnCount - 1); + property int rowHeight: 50; + property var userData: []; + property var myData: ({displayName: "", userName: ""}); // valid dummy until set + property bool iAmAdmin: false; + function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml + var i, data = optionalData || userData, length = data.length; + for (var i = 0; i < length; i++) { + if (data[i].sessionId === sessionId) { + return i; + } + } + return -1; + } + function fromScript(message) { + switch (message.method) { + case 'users': + var data = message.params; + var myIndex = findSessionIndex('', data); + iAmAdmin = Users.canKick; + myData = data[myIndex]; + data.splice(myIndex, 1); + userData = data; + sortModel(); + break; + case 'select': + var sessionId = message.params[0]; + var selected = message.params[1]; + var userIndex = findSessionIndex(sessionId); + if (selected) { + table.selection.clear(); // for now, no multi-select + table.selection.select(userIndex); + } else { + table.selection.deselect(userIndex); + } + break; + default: + console.log('Unrecognized message:', JSON.stringify(message)); + } + } + ListModel { + id: userModel + } + function sortModel() { + var sortProperty = table.getColumn(table.sortIndicatorColumn).role; + var before = (table.sortIndicatorOrder === Qt.AscendingOrder) ? -1 : 1; + var after = -1 * before; + userData.sort(function (a, b) { + var aValue = a[sortProperty].toString().toLowerCase(), bValue = b[sortProperty].toString().toLowerCase(); + switch (true) { + case (aValue < bValue): return before; + case (aValue > bValue): return after; + default: return 0; + } + }); + table.selection.clear(); + userModel.clear(); + var userIndex = 0; + userData.forEach(function (datum) { + function init(property) { + if (datum[property] === undefined) { + datum[property] = false; + } + } + ['ignore', 'spacer', 'mute', 'kick'].forEach(init); + datum.userIndex = userIndex++; + userModel.append(datum); + }); + } + signal sendToScript(var message); + function noticeSelection() { + var userIds = []; + table.selection.forEach(function (userIndex) { + userIds.push(userData[userIndex].sessionId); + }); + pal.sendToScript({method: 'selected', params: userIds}); + } + Connections { + target: table.selection + onSelectionChanged: pal.noticeSelection() + } + + Column { + NameCard { + id: myCard; + width: nameWidth; + displayName: myData.displayName; + userName: myData.userName; + } + TableView { + id: table; + TableViewColumn { + role: "displayName"; + title: "Name"; + width: nameWidth + } + TableViewColumn { + role: "ignore"; + title: "Ignore" + width: actionWidth + } + TableViewColumn { + title: ""; + width: actionWidth + } + TableViewColumn { + visible: iAmAdmin; + role: "mute"; + title: "Mute"; + width: actionWidth + } + TableViewColumn { + visible: iAmAdmin; + role: "kick"; + title: "Ban" + width: actionWidth + } + model: userModel; + rowDelegate: Rectangle { // The only way I know to specify a row height. + height: rowHeight; + // The rest of this is cargo-culted to restore the default styling + SystemPalette { + id: myPalette; + colorGroup: SystemPalette.Active + } + color: { + var baseColor = styleData.alternate?myPalette.alternateBase:myPalette.base + return styleData.selected?myPalette.highlight:baseColor + } + } + itemDelegate: Item { + id: itemCell; + property bool isCheckBox: typeof(styleData.value) === 'boolean'; + NameCard { + id: nameCard; + visible: !isCheckBox; + width: nameWidth; + displayName: styleData.value; + userName: model.userName; + } + Rectangle { + radius: itemCell.height / 4; + visible: isCheckBox; + color: styleData.value ? "green" : "red"; + anchors.fill: parent; + MouseArea { + anchors.fill: parent; + acceptedButtons: Qt.LeftButton; + hoverEnabled: true; + onClicked: { + var newValue = !model[styleData.role]; + var datum = userData[model.userIndex]; + datum[styleData.role] = model[styleData.role] = newValue; + Users[styleData.role](model.sessionId); + // Just for now, while we cannot undo things: + userData.splice(model.userIndex, 1); + sortModel(); + } + } + } + } + height: pal.height - myCard.height; + width: pal.width; + sortIndicatorVisible: true; + onSortIndicatorColumnChanged: sortModel(); + onSortIndicatorOrderChanged: sortModel(); + } + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4ec29b636b..90f187784f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -46,6 +46,8 @@ #include #include +#include +#include #include #include #include @@ -90,20 +92,21 @@ #include #include #include +#include #include #include -#include +#include #include #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -416,10 +419,13 @@ bool setupEssentials(int& argc, char** argv) { const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); const int listenPort = portStr ? atoi(portStr) : INVALID_PORT; - // Set build version - QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + Setting::init(); - Setting::preInit(); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->init(); + } + + DependencyManager::set(); #if defined(Q_OS_WIN) // Select appropriate audio DLL @@ -441,10 +447,9 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); - Setting::init(); - // Set dependencies DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -551,11 +556,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _maxOctreePPS(maxOctreePacketsPerSecond.get()), _lastFaceTrackerUpdate(0) { - setProperty(hifi::properties::STEAM, SteamClient::isRunning()); + auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); + setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); { const QString TEST_SCRIPT = "--testScript"; + const QString TRACE_FILE = "--traceFile"; const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT) { @@ -563,6 +570,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); } + } else if (args.at(i) == TRACE_FILE) { + QString traceFilePath = args.at(i + 1); + setProperty(hifi::properties::TRACING, traceFilePath); + DependencyManager::get()->startTracing(); } } } @@ -606,7 +617,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _deadlockWatchdogThread = new DeadlockWatchdogThread(); _deadlockWatchdogThread->start(); - qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << SteamClient::getSteamVRBuildID(); + if (steamClient) { + qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID(); + } qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion()); qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION; qCDebug(interfaceapp) << "[VERSION] VERSION:" << BuildInfo::VERSION; @@ -1569,6 +1582,13 @@ void Application::cleanupBeforeQuit() { QString webengineRemoteDebugging = QProcessEnvironment::systemEnvironment().value("QTWEBENGINE_REMOTE_DEBUGGING", "false"); qCDebug(interfaceapp) << "QTWEBENGINE_REMOTE_DEBUGGING =" << webengineRemoteDebugging; + if (tracing::enabled()) { + auto tracer = DependencyManager::get(); + tracer->stopTracing(); + auto outputFile = property(hifi::properties::TRACING).toString(); + tracer->serialize(outputFile); + } + // Stop third party processes so that they're not left running in the event of a subsequent shutdown crash. #ifdef HAVE_DDE DependencyManager::get()->setEnabled(false); @@ -1695,6 +1715,10 @@ Application::~Application() { Leapmotion::destroy(); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->shutdown(); + } + #if 0 ConnexionClient::getInstance().destroy(); #endif @@ -1739,10 +1763,14 @@ void Application::initializeGL() { // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("RenderShadowTask", cullFunctor); - _renderEngine->addJob("RenderDeferredTask", cullFunctor); + static const QString RENDER_FORWARD = "RENDER_FORWARD"; + if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) { + _renderEngine->addJob("RenderForwardTask", cullFunctor); + } else { + _renderEngine->addJob("RenderDeferredTask", cullFunctor); + } _renderEngine->load(); _renderEngine->registerScene(_main3DScene); - // TODO: Load a cached config file // The UI can't be created until the primary OpenGL // context is created, because it needs to share @@ -1838,6 +1866,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Assets", new AssetMappingsScriptingInterface()); rootContext->setContextProperty("AvatarList", DependencyManager::get().data()); + rootContext->setContextProperty("Users", DependencyManager::get().data()); rootContext->setContextProperty("Camera", &_myCamera); @@ -1874,8 +1903,10 @@ void Application::initializeUi() { rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); - rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine)); - + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); + } + _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { @@ -1914,6 +1945,16 @@ void Application::initializeUi() { } void Application::paintGL() { + PROFILE_COUNTER(interfaceapp, "fps", { { "fps", _frameCounter.rate() } }); + PROFILE_COUNTER(interfaceapp, "downloads", { + { "current", ResourceCache::getLoadingRequests().length() }, + { "pending", ResourceCache::getPendingRequestCount() } + }); + PROFILE_COUNTER(interfaceapp, "processing", { + { "current", DependencyManager::get()->getStat("Processing") }, + { "pending", DependencyManager::get()->getStat("PendingProcessing") } + }); + // Some plugins process message events, allowing paintGL to be called reentrantly. if (_inPaint || _aboutToQuit) { return; @@ -1925,7 +1966,7 @@ void Application::paintGL() { _frameCount++; auto lastPaintBegin = usecTimestampNow(); - PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, (uint64_t)_frameCount); + PROFILE_RANGE_EX(interfaceapp, __FUNCTION__, 0xff0000ff, (uint64_t)_frameCount); PerformanceTimer perfTimer("paintGL"); if (nullptr == _displayPlugin) { @@ -2102,7 +2143,7 @@ void Application::paintGL() { auto finalFramebuffer = framebufferCache->getFramebuffer(); { - PROFILE_RANGE(__FUNCTION__ "/mainRender"); + PROFILE_RANGE(interfaceapp, "/mainRender"); PerformanceTimer perfTimer("mainRender"); renderArgs._boomOffset = boomOffset; // Viewport is assigned to the size of the framebuffer @@ -2157,7 +2198,7 @@ void Application::paintGL() { frame->overlay = _applicationOverlay.getOverlayTexture(); // deliver final scene rendering commands to the display plugin { - PROFILE_RANGE(__FUNCTION__ "/pluginOutput"); + PROFILE_RANGE(interfaceapp, "/pluginOutput"); PerformanceTimer perfTimer("pluginOutput"); _frameCounter.increment(); displayPlugin->submitFrame(frame); @@ -2245,7 +2286,7 @@ void Application::resizeEvent(QResizeEvent* event) { } void Application::resizeGL() { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); if (nullptr == _displayPlugin) { return; } @@ -2300,7 +2341,6 @@ bool Application::importSVOFromURL(const QString& urlString) { } bool Application::event(QEvent* event) { - if (!Menu::getInstance()) { return false; } @@ -2891,7 +2931,7 @@ void Application::maybeToggleMenuVisible(QMouseEvent* event) const { } void Application::mouseMoveEvent(QMouseEvent* event) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); if (_aboutToQuit) { return; @@ -3199,9 +3239,11 @@ void Application::idle(float nsecsElapsed) { connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop); } - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); - SteamClient::runCallbacks(); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->runCallbacks(); + } float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND; @@ -3533,12 +3575,16 @@ void Application::init() { _timerStart.start(); _lastTimeUpdated.start(); - // when +connect_lobby in command line, join steam lobby - const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby"; - int lobbyIndex = arguments().indexOf(STEAM_LOBBY_COMMAND_LINE_KEY); - if (lobbyIndex != -1) { - QString lobbyId = arguments().value(lobbyIndex + 1); - SteamClient::joinLobby(lobbyId); + + + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + // when +connect_lobby in command line, join steam lobby + const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby"; + int lobbyIndex = arguments().indexOf(STEAM_LOBBY_COMMAND_LINE_KEY); + if (lobbyIndex != -1) { + QString lobbyId = arguments().value(lobbyIndex + 1); + steamClient->joinLobby(lobbyId); + } } @@ -3910,9 +3956,11 @@ void Application::updateDialogs(float deltaTime) const { } } +static bool domainLoadingInProgress = false; + void Application::update(float deltaTime) { - PROFILE_RANGE_EX(__FUNCTION__, 0xffff0000, (uint64_t)_frameCount + 1); + PROFILE_RANGE_EX(interfaceapp, __FUNCTION__, 0xffff0000, (uint64_t)_frameCount + 1); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); @@ -3920,6 +3968,11 @@ void Application::update(float deltaTime) { updateLOD(); if (!_physicsEnabled) { + if (!domainLoadingInProgress) { + PROFILE_ASYNC_BEGIN(interfaceapp, "Scene Loading", ""); + domainLoadingInProgress = true; + } + // we haven't yet enabled physics. we wait until we think we have all the collision information // for nearby entities before starting bullet up. quint64 now = usecTimestampNow(); @@ -3949,6 +4002,9 @@ void Application::update(float deltaTime) { } } } + } else if (domainLoadingInProgress) { + domainLoadingInProgress = false; + PROFILE_ASYNC_END(interfaceapp, "Scene Loading", ""); } { @@ -4042,12 +4098,12 @@ void Application::update(float deltaTime) { QSharedPointer avatarManager = DependencyManager::get(); if (_physicsEnabled) { - PROFILE_RANGE_EX("Physics", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "Physics", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("physics"); { - PROFILE_RANGE_EX("UpdateStats", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "UpdateStats", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("updateStates)"); static VectorOfMotionStates motionStates; @@ -4081,14 +4137,14 @@ void Application::update(float deltaTime) { }); } { - PROFILE_RANGE_EX("StepSimulation", 0xffff8000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "StepSimulation", 0xffff8000, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("stepSimulation"); getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); } { - PROFILE_RANGE_EX("HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("harvestChanges"); if (_physicsEngine->hasOutgoingChanges()) { getEntities()->getTree()->withWriteLock([&] { @@ -4130,20 +4186,20 @@ void Application::update(float deltaTime) { _avatarSimCounter.increment(); { - PROFILE_RANGE_EX("OtherAvatars", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "OtherAvatars", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount()); avatarManager->updateOtherAvatars(deltaTime); } qApp->updateMyAvatarLookAtPosition(); { - PROFILE_RANGE_EX("MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount()); avatarManager->updateMyAvatar(deltaTime); } } { - PROFILE_RANGE_EX("Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("overlays"); _overlays.update(deltaTime); } @@ -4163,7 +4219,7 @@ void Application::update(float deltaTime) { // Update my voxel servers with my current voxel query... { - PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE_EX(interfaceapp, "QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); QMutexLocker viewLocker(&_viewMutex); PerformanceTimer perfTimer("queryOctree"); quint64 sinceLastQuery = now - _lastQueriedTime; @@ -4203,7 +4259,7 @@ void Application::update(float deltaTime) { avatarManager->postUpdate(deltaTime); { - PROFILE_RANGE_EX("PreRenderLambdas", 0xffff0000, (uint64_t)0); + PROFILE_RANGE_EX(interfaceapp, "PreRenderLambdas", 0xffff0000, (uint64_t)0); std::unique_lock guard(_postUpdateLambdasLock); for (auto& iter : _postUpdateLambdas) { @@ -4481,7 +4537,7 @@ QRect Application::getDesirableApplicationGeometry() const { // void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { PerformanceTimer perfTimer("loadViewFrustum"); - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); // We will use these below, from either the camera or head vectors calculated above viewFrustum.setProjection(camera.getProjection()); @@ -4657,7 +4713,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se myAvatar->preDisplaySide(renderArgs); activeRenderingThread = QThread::currentThread(); - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); PerformanceTimer perfTimer("display"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); @@ -5193,8 +5249,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine)); - + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine, steamClient.get())); + } auto scriptingInterface = DependencyManager::get(); scriptEngine->registerGlobalObject("Controller", scriptingInterface.data()); UserInputMapper::registerControllerTypes(scriptEngine); diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index 0c9698ffc3..b254cd58de 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -18,19 +18,18 @@ #include #include #include -#include #include #include #include #include "Application.h" #include "Menu.h" +#include #include bool CrashHandler::checkForResetSettings(bool suppressPrompt) { - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings settings; + Settings settings; settings.beginGroup("Developer"); QVariant displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions); QVariant askToResetSettingsOption = settings.value(MenuOption::AskToResetSettings); @@ -110,8 +109,7 @@ void CrashHandler::handleCrash(CrashHandler::Action action) { return; } - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings settings; + Settings settings; const QString ADDRESS_MANAGER_GROUP = "AddressManager"; const QString ADDRESS_KEY = "address"; const QString AVATAR_GROUP = "Avatar"; diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index eb9a7c7f6d..8fcc1e5477 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #include #include @@ -111,7 +112,9 @@ void DiscoverabilityManager::updateLocation() { } // Update Steam - SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentFacingShareableAddress()); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->updateLocation(domainHandler.getHostname(), addressManager->currentFacingShareableAddress()); + } } void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { diff --git a/interface/src/Util.h b/interface/src/Util.h index e3938502d2..60e38ae0ec 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -14,7 +14,6 @@ #include #include -#include #include diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c56d255201..5a31fdbbed 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -57,7 +57,6 @@ using namespace std; -const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f; const float MAX_WALKING_SPEED = 2.6f; // human walking speed diff --git a/interface/src/main.cpp b/interface/src/main.cpp index a88388050b..c83f7a989c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -15,14 +15,13 @@ #include #include #include -#include #include #include +#include #include #include -#include #include "AddressManager.h" #include "Application.h" @@ -32,7 +31,6 @@ #include #ifdef HAS_BUGSPLAT -#include #include #include #endif @@ -51,7 +49,13 @@ int main(int argc, const char* argv[]) { #endif disableQtBearerPoll(); // Fixes wifi ping spikes - + + // Set application infos + QCoreApplication::setApplicationName(BuildInfo::INTERFACE_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME"); bool instanceMightBeRunning = true; @@ -129,8 +133,10 @@ int main(int argc, const char* argv[]) { } QCommandLineParser parser; + QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications"); QCommandLineOption runServerOption("runServer", "Whether to run the server"); QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath"); + parser.addOption(checkMinSpecOption); parser.addOption(runServerOption); parser.addOption(serverContentPathOption); parser.parse(arguments); @@ -157,11 +163,9 @@ int main(int argc, const char* argv[]) { // or in the main window ctor, before GL startup. Application::initPlugins(arguments); - SteamClient::init(); - #ifdef Q_OS_WIN // If we're running in steam mode, we need to do an explicit check to ensure we're up to the required min spec - if (SteamClient::isRunning()) { + if (parser.isSet(checkMinSpecOption)) { QString appPath; { char filename[MAX_PATH]; @@ -183,7 +187,6 @@ int main(int argc, const char* argv[]) { int exitCode; { - QSettings::setDefaultFormat(QSettings::IniFormat); Application app(argc, const_cast(argv), startupTime, runServer, serverContentPathOptionValue); // If we failed the OpenGLVersion check, log it. @@ -245,8 +248,6 @@ int main(int argc, const char* argv[]) { Application::shutdownPlugins(); - SteamClient::shutdown(); - qCDebug(interfaceapp, "Normal exit."); #if !defined(DEBUG) && !defined(Q_OS_LINUX) // HACK: exit immediately (don't handle shutdown callbacks) for Release build diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index 46310c9e40..1e1a4d8d0c 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -10,6 +10,10 @@ #include "TestScriptingInterface.h" #include +#include + +#include +#include TestScriptingInterface* TestScriptingInterface::getInstance() { static TestScriptingInterface sharedInstance; @@ -28,3 +32,27 @@ void TestScriptingInterface::waitForDownloadIdle() { void TestScriptingInterface::waitIdle() { } + +bool TestScriptingInterface::startTracing(QString logrules) { + if (!logrules.isEmpty()) { + QLoggingCategory::setFilterRules(logrules); + } + + if (!DependencyManager::isSet()) { + return false; + } + + DependencyManager::get()->startTracing(); + return true; +} + +bool TestScriptingInterface::stopTracing(QString filename) { + if (!DependencyManager::isSet()) { + return false; + } + + auto tracer = DependencyManager::get(); + tracer->stopTracing(); + tracer->serialize(filename); + return true; +} \ No newline at end of file diff --git a/interface/src/scripting/TestScriptingInterface.h b/interface/src/scripting/TestScriptingInterface.h index 91277ebc78..0c6ab6baaa 100644 --- a/interface/src/scripting/TestScriptingInterface.h +++ b/interface/src/scripting/TestScriptingInterface.h @@ -38,6 +38,17 @@ public slots: */ void waitIdle(); + /**jsdoc + * Start recording Chrome compatible tracing events + * logRules can be used to specify a set of logging category rules to limit what gets captured + */ + bool startTracing(QString logrules = ""); + + /**jsdoc + * Stop recording Chrome compatible tracing events and serialize recorded events to a file + * Using a filename with a .gz extension will automatically compress the output file + */ + bool stopTracing(QString filename); }; #endif // hifi_TestScriptingInterface_h diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 32336fe3be..f7bbc1aa96 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -29,6 +29,7 @@ #include "ui/Stats.h" #include "ui/AvatarInputs.h" #include "OffscreenUi.h" +#include "InterfaceLogging.h" #include const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f }; @@ -56,7 +57,7 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); buildFramebufferObject(); @@ -95,7 +96,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { } void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); if (!_uiTexture) { _uiTexture = gpu::TexturePointer(gpu::Texture::createExternal2D(OffscreenQmlSurface::getDiscardLambda())); @@ -123,7 +124,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { } void ApplicationOverlay::renderAudioScope(RenderArgs* renderArgs) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); @@ -142,7 +143,7 @@ void ApplicationOverlay::renderAudioScope(RenderArgs* renderArgs) { } void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); @@ -261,7 +262,7 @@ static const auto DEFAULT_SAMPLER = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LI static const auto DEPTH_FORMAT = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); void ApplicationOverlay::buildFramebufferObject() { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); auto uiSize = qApp->getUiSize(); if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) { @@ -287,4 +288,4 @@ gpu::TexturePointer ApplicationOverlay::getOverlayTexture() { return gpu::TexturePointer(); } return _overlayFramebuffer->getRenderBuffer(0); -} \ No newline at end of file +} diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index d27c3e907a..e333bb1b88 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -17,7 +17,8 @@ #include #include -#include +#include +#include #include "AccountManager.h" #include "DependencyManager.h" @@ -56,7 +57,8 @@ void LoginDialog::toggleAction() { } bool LoginDialog::isSteamRunning() const { - return SteamClient::isRunning(); + auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); + return steamClient && steamClient->isRunning(); } void LoginDialog::login(const QString& username, const QString& password) const { @@ -66,69 +68,75 @@ void LoginDialog::login(const QString& username, const QString& password) const void LoginDialog::loginThroughSteam() { qDebug() << "Attempting to login through Steam"; - SteamClient::requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { - emit handleLoginFailed(); - return; - } + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } - DependencyManager::get()->requestAccessTokenWithSteam(ticket); - }); + DependencyManager::get()->requestAccessTokenWithSteam(ticket); + }); + } } void LoginDialog::linkSteam() { qDebug() << "Attempting to link Steam account"; - SteamClient::requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { - emit handleLoginFailed(); - return; - } + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "linkCompleted"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "linkFailed"; + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "linkCompleted"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "linkFailed"; - const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; + const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; - QJsonObject payload; - payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); + QJsonObject payload; + payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); - auto accountManager = DependencyManager::get(); - accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, - QNetworkAccessManager::PostOperation, callbackParams, - QJsonDocument(payload).toJson()); - }); + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); + }); + } } void LoginDialog::createAccountFromStream(QString username) { qDebug() << "Attempting to create account from Steam info"; - SteamClient::requestTicket([this, username](Ticket ticket) { - if (ticket.isNull()) { - emit handleLoginFailed(); - return; - } + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this, username](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "createCompleted"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "createFailed"; + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "createCompleted"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "createFailed"; - const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; + const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; - QJsonObject payload; - payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); - if (!username.isEmpty()) { - payload.insert("username", QJsonValue::fromVariant(QVariant(username))); - } + QJsonObject payload; + payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); + if (!username.isEmpty()) { + payload.insert("username", QJsonValue::fromVariant(QVariant(username))); + } - auto accountManager = DependencyManager::get(); - accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None, - QNetworkAccessManager::PostOperation, callbackParams, - QJsonDocument(payload).toJson()); - }); + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); + }); + } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 2c6440094b..a4cb62cc13 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -292,23 +292,24 @@ void setupPreferences() { { static const QString RENDER("Graphics"); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + if (renderConfig) { + auto ambientOcclusionConfig = renderConfig->getConfig(); + if (ambientOcclusionConfig) { + auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; + auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; + auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); + preference->setItems(ambientOcclusionConfig->getPresetList()); + preferences->addPreference(preference); + } - auto ambientOcclusionConfig = renderConfig->getConfig(); - { - auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; - auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); - preference->setItems(ambientOcclusionConfig->getPresetList()); - preferences->addPreference(preference); - } - - auto shadowConfig = renderConfig->getConfig(); - { - auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; - auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); - preference->setItems(shadowConfig->getPresetList()); - preferences->addPreference(preference); + auto shadowConfig = renderConfig->getConfig(); + if (shadowConfig) { + auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; + auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; + auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); + preference->setItems(shadowConfig->getPresetList()); + preferences->addPreference(preference); + } } } { diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index 62dbc7aea4..cf89504d92 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -55,10 +55,6 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio // Start the snapshotAnimatedTimer QTimer - argument for this is in milliseconds SnapshotAnimated::snapshotAnimatedTimerRunning = true; SnapshotAnimated::snapshotAnimatedTimer->start(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC); - // If we're already in the middle of capturing an animated snapshot... - } else { - // Just tell the dependency manager that the capture of the still snapshot has taken place. - emit dm->snapshotTaken(pathStill, "", false); } } @@ -88,9 +84,6 @@ void SnapshotAnimated::captureFrames() { // If that was the last frame... if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) { SnapshotAnimated::snapshotAnimatedTimerRunning = false; - // Reset the current frame timestamp - SnapshotAnimated::snapshotAnimatedTimestamp = 0; - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = 0; // Notify the user that we're processing the snapshot emit SnapshotAnimated::snapshotAnimatedDM->processingGif(); @@ -136,7 +129,10 @@ void SnapshotAnimated::processFrames() { SnapshotAnimated::snapshotAnimatedFrameVector.squeeze(); SnapshotAnimated::snapshotAnimatedFrameDelayVector.clear(); SnapshotAnimated::snapshotAnimatedFrameDelayVector.squeeze(); + // Reset the current frame timestamp + SnapshotAnimated::snapshotAnimatedTimestamp = 0; + SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = 0; - // Let the dependency manager know that the snapshots have been taken. + // Let the window scripting interface know that the snapshots have been taken. emit SnapshotAnimated::snapshotAnimatedDM->snapshotTaken(SnapshotAnimated::snapshotStillPath, SnapshotAnimated::snapshotAnimatedPath, false); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 242821234a..b1f2f60adc 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -19,6 +19,7 @@ #include #include "Application.h" +#include "InterfaceLogging.h" #include "Image3DOverlay.h" #include "Circle3DOverlay.h" #include "Cube3DOverlay.h" @@ -101,7 +102,7 @@ void Overlays::cleanupOverlaysToDelete() { } void Overlays::renderHUD(RenderArgs* renderArgs) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(interfaceapp, __FUNCTION__); QReadLocker lock(&_lock); gpu::Batch& batch = *renderArgs->_batch; diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 7985251002..c067157e98 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -394,7 +394,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars loadPoses(underPoses); } else { - PROFILE_RANGE_EX("ik/relax", 0xffff00ff, 0); + PROFILE_RANGE_EX(animation, "ik/relax", 0xffff00ff, 0); // relax toward underPoses // HACK: this relaxation needs to be constant per-frame rather than per-realtime @@ -433,7 +433,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars // build a list of targets from _targetVarVec std::vector targets; { - PROFILE_RANGE_EX("ik/computeTargets", 0xffff00ff, 0); + PROFILE_RANGE_EX(animation, "ik/computeTargets", 0xffff00ff, 0); computeTargets(animVars, targets, underPoses); } @@ -450,7 +450,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars } else { { - PROFILE_RANGE_EX("ik/shiftHips", 0xffff00ff, 0); + PROFILE_RANGE_EX(animation, "ik/shiftHips", 0xffff00ff, 0); // shift hips according to the _hipsOffset from the previous frame float offsetLength = glm::length(_hipsOffset); @@ -476,12 +476,12 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars } { - PROFILE_RANGE_EX("ik/ccd", 0xffff00ff, 0); + PROFILE_RANGE_EX(animation, "ik/ccd", 0xffff00ff, 0); solveWithCyclicCoordinateDescent(targets); } { - PROFILE_RANGE_EX("ik/measureHipsOffset", 0xffff00ff, 0); + PROFILE_RANGE_EX(animation, "ik/measureHipsOffset", 0xffff00ff, 0); // measure new _hipsOffset for next frame // by looking for discrepancies between where a targeted endEffector is diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 7601fbc782..09dda3671f 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -14,6 +14,9 @@ #include "AnimationCache.h" #include "AnimationLogging.h" +#include +#include +#include int animationPointerMetaTypeId = qRegisterMetaType(); @@ -45,9 +48,14 @@ Animation::Animation(const QUrl& url) : Resource(url) {} AnimationReader::AnimationReader(const QUrl& url, const QByteArray& data) : _url(url), _data(data) { + DependencyManager::get()->incrementStat("PendingProcessing"); } void AnimationReader::run() { + DependencyManager::get()->decrementStat("PendingProcessing"); + CounterStat counter("Processing"); + + PROFILE_RANGE_EX(animation, __FUNCTION__, 0xFF00FF00, 0, { { "url", _url.toString() } }); auto originalPriority = QThread::currentThread()->priority(); if (originalPriority == QThread::InheritPriority) { originalPriority = QThread::NormalPriority; diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 59e3de9bcb..0e6a94c1b8 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -65,6 +65,8 @@ public: explicit Animation(const QUrl& url); + QString getType() const override { return "Animation"; } + const FBXGeometry& getGeometry() const { return *_geometry; } virtual bool isLoaded() const override; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 45790524d1..ab07a9deb9 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -882,7 +882,7 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) { - PROFILE_RANGE_EX(__FUNCTION__, 0xffff00ff, 0); + PROFILE_RANGE_EX(animation, __FUNCTION__, 0xffff00ff, 0); setModelOffset(rootTransform); @@ -973,10 +973,6 @@ void Rig::updateFromEyeParameters(const EyeParameters& params) { params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); } -static const glm::vec3 X_AXIS(1.0f, 0.0f, 0.0f); -static const glm::vec3 Y_AXIS(0.0f, 1.0f, 0.0f); -static const glm::vec3 Z_AXIS(0.0f, 0.0f, 1.0f); - void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut, glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const { diff --git a/libraries/audio/src/AudioSRC.cpp b/libraries/audio/src/AudioSRC.cpp index 22e51200d1..3cd7a53b6b 100644 --- a/libraries/audio/src/AudioSRC.cpp +++ b/libraries/audio/src/AudioSRC.cpp @@ -10,12 +10,19 @@ // #include +#include #include -#include #include "AudioSRC.h" #include "AudioSRCData.h" +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + // high/low part of int64_t #define LO32(a) ((uint32_t)(a)) #define HI32(a) ((int32_t)((a) >> 32)) @@ -194,182 +201,224 @@ int AudioSRC::createIrrationalFilter(int upFactor, int downFactor, float gain) { } // -// on x86 architecture, assume that SSE2 is present +// scalar reference versions // +int AudioSRC::multirateFilter1_ref(const float* input0, float* output0, int inputFrames) { + int outputFrames = 0; + + if (_step == 0) { // rational + + int32_t i = HI32(_offset); + + while (i < inputFrames) { + + const float* c0 = &_polyphaseFilter[_numTaps * _phase]; + + float acc0 = 0.0f; + + for (int j = 0; j < _numTaps; j++) { + + float coef = c0[j]; + + acc0 += input0[i + j] * coef; + } + + output0[outputFrames] = acc0; + outputFrames += 1; + + i += _stepTable[_phase]; + if (++_phase == _upFactor) { + _phase = 0; + } + } + _offset = (int64_t)(i - inputFrames) << 32; + + } else { // irrational + + while (HI32(_offset) < inputFrames) { + + int32_t i = HI32(_offset); + uint32_t f = LO32(_offset); + + uint32_t phase = f >> SRC_FRACBITS; + float frac = (f & SRC_FRACMASK) * QFRAC_TO_FLOAT; + + const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; + const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; + + float acc0 = 0.0f; + + for (int j = 0; j < _numTaps; j++) { + + float coef = c0[j] + frac * (c1[j] - c0[j]); + + acc0 += input0[i + j] * coef; + } + + output0[outputFrames] = acc0; + outputFrames += 1; + + _offset += _step; + } + _offset -= (int64_t)inputFrames << 32; + } + + return outputFrames; +} + +int AudioSRC::multirateFilter2_ref(const float* input0, const float* input1, float* output0, float* output1, int inputFrames) { + int outputFrames = 0; + + if (_step == 0) { // rational + + int32_t i = HI32(_offset); + + while (i < inputFrames) { + + const float* c0 = &_polyphaseFilter[_numTaps * _phase]; + + float acc0 = 0.0f; + float acc1 = 0.0f; + + for (int j = 0; j < _numTaps; j++) { + + float coef = c0[j]; + + acc0 += input0[i + j] * coef; + acc1 += input1[i + j] * coef; + } + + output0[outputFrames] = acc0; + output1[outputFrames] = acc1; + outputFrames += 1; + + i += _stepTable[_phase]; + if (++_phase == _upFactor) { + _phase = 0; + } + } + _offset = (int64_t)(i - inputFrames) << 32; + + } else { // irrational + + while (HI32(_offset) < inputFrames) { + + int32_t i = HI32(_offset); + uint32_t f = LO32(_offset); + + uint32_t phase = f >> SRC_FRACBITS; + float frac = (f & SRC_FRACMASK) * QFRAC_TO_FLOAT; + + const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; + const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; + + float acc0 = 0.0f; + float acc1 = 0.0f; + + for (int j = 0; j < _numTaps; j++) { + + float coef = c0[j] + frac * (c1[j] - c0[j]); + + acc0 += input0[i + j] * coef; + acc1 += input1[i + j] * coef; + } + + output0[outputFrames] = acc0; + output1[outputFrames] = acc1; + outputFrames += 1; + + _offset += _step; + } + _offset -= (int64_t)inputFrames << 32; + } + + return outputFrames; +} + +int AudioSRC::multirateFilter4_ref(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames) { + int outputFrames = 0; + + if (_step == 0) { // rational + + int32_t i = HI32(_offset); + + while (i < inputFrames) { + + const float* c0 = &_polyphaseFilter[_numTaps * _phase]; + + float acc0 = 0.0f; + float acc1 = 0.0f; + float acc2 = 0.0f; + float acc3 = 0.0f; + + for (int j = 0; j < _numTaps; j++) { + + float coef = c0[j]; + + acc0 += input0[i + j] * coef; + acc1 += input1[i + j] * coef; + acc2 += input2[i + j] * coef; + acc3 += input3[i + j] * coef; + } + + output0[outputFrames] = acc0; + output1[outputFrames] = acc1; + output2[outputFrames] = acc2; + output3[outputFrames] = acc3; + outputFrames += 1; + + i += _stepTable[_phase]; + if (++_phase == _upFactor) { + _phase = 0; + } + } + _offset = (int64_t)(i - inputFrames) << 32; + + } else { // irrational + + while (HI32(_offset) < inputFrames) { + + int32_t i = HI32(_offset); + uint32_t f = LO32(_offset); + + uint32_t phase = f >> SRC_FRACBITS; + float frac = (f & SRC_FRACMASK) * QFRAC_TO_FLOAT; + + const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; + const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; + + float acc0 = 0.0f; + float acc1 = 0.0f; + float acc2 = 0.0f; + float acc3 = 0.0f; + + for (int j = 0; j < _numTaps; j++) { + + float coef = c0[j] + frac * (c1[j] - c0[j]); + + acc0 += input0[i + j] * coef; + acc1 += input1[i + j] * coef; + acc2 += input2[i + j] * coef; + acc3 += input3[i + j] * coef; + } + + output0[outputFrames] = acc0; + output1[outputFrames] = acc1; + output2[outputFrames] = acc2; + output3[outputFrames] = acc3; + outputFrames += 1; + + _offset += _step; + } + _offset -= (int64_t)inputFrames << 32; + } + + return outputFrames; +} + #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__) -#include - -int AudioSRC::multirateFilter1_SSE(const float* input0, float* output0, int inputFrames) { - int outputFrames = 0; - - assert(_numTaps % 4 == 0); // SIMD4 - - if (_step == 0) { // rational - - int32_t i = HI32(_offset); - - while (i < inputFrames) { - - const float* c0 = &_polyphaseFilter[_numTaps * _phase]; - - __m128 acc0 = _mm_setzero_ps(); - - for (int j = 0; j < _numTaps; j += 4) { - - //float coef = c0[j]; - __m128 coef0 = _mm_loadu_ps(&c0[j]); - - //acc += input[i + j] * coef; - acc0 = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(&input0[i + j]), coef0), acc0); - } - - // horizontal sum - acc0 = _mm_add_ps(acc0, _mm_movehl_ps(acc0, acc0)); - acc0 = _mm_add_ss(acc0, _mm_shuffle_ps(acc0, acc0, _MM_SHUFFLE(0,0,0,1))); - - _mm_store_ss(&output0[outputFrames], acc0); - outputFrames += 1; - - i += _stepTable[_phase]; - if (++_phase == _upFactor) { - _phase = 0; - } - } - _offset = (int64_t)(i - inputFrames) << 32; - - } else { // irrational - - while (HI32(_offset) < inputFrames) { - - int32_t i = HI32(_offset); - uint32_t f = LO32(_offset); - - uint32_t phase = f >> SRC_FRACBITS; - __m128 frac = _mm_set1_ps((f & SRC_FRACMASK) * QFRAC_TO_FLOAT); - - const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; - const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; - - __m128 acc0 = _mm_setzero_ps(); - - for (int j = 0; j < _numTaps; j += 4) { - - //float coef = c0[j] + frac * (c1[j] - c0[j]); - __m128 coef0 = _mm_loadu_ps(&c0[j]); - __m128 coef1 = _mm_loadu_ps(&c1[j]); - coef1 = _mm_sub_ps(coef1, coef0); - coef0 = _mm_add_ps(_mm_mul_ps(coef1, frac), coef0); - - //acc += input[i + j] * coef; - acc0 = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(&input0[i + j]), coef0), acc0); - } - - // horizontal sum - acc0 = _mm_add_ps(acc0, _mm_movehl_ps(acc0, acc0)); - acc0 = _mm_add_ss(acc0, _mm_shuffle_ps(acc0, acc0, _MM_SHUFFLE(0,0,0,1))); - - _mm_store_ss(&output0[outputFrames], acc0); - outputFrames += 1; - - _offset += _step; - } - _offset -= (int64_t)inputFrames << 32; - } - - return outputFrames; -} - -int AudioSRC::multirateFilter2_SSE(const float* input0, const float* input1, float* output0, float* output1, int inputFrames) { - int outputFrames = 0; - - assert(_numTaps % 4 == 0); // SIMD4 - - if (_step == 0) { // rational - - int32_t i = HI32(_offset); - - while (i < inputFrames) { - - const float* c0 = &_polyphaseFilter[_numTaps * _phase]; - - __m128 acc0 = _mm_setzero_ps(); - __m128 acc1 = _mm_setzero_ps(); - - for (int j = 0; j < _numTaps; j += 4) { - - //float coef = c0[j]; - __m128 coef0 = _mm_loadu_ps(&c0[j]); - - //acc += input[i + j] * coef; - acc0 = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(&input0[i + j]), coef0), acc0); - acc1 = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(&input1[i + j]), coef0), acc1); - } - - // horizontal sum - acc0 = _mm_add_ps(acc0, _mm_movehl_ps(acc0, acc0)); - acc1 = _mm_add_ps(acc1, _mm_movehl_ps(acc1, acc1)); - acc0 = _mm_add_ss(acc0, _mm_shuffle_ps(acc0, acc0, _MM_SHUFFLE(0,0,0,1))); - acc1 = _mm_add_ss(acc1, _mm_shuffle_ps(acc1, acc1, _MM_SHUFFLE(0,0,0,1))); - - _mm_store_ss(&output0[outputFrames], acc0); - _mm_store_ss(&output1[outputFrames], acc1); - outputFrames += 1; - - i += _stepTable[_phase]; - if (++_phase == _upFactor) { - _phase = 0; - } - } - _offset = (int64_t)(i - inputFrames) << 32; - - } else { // irrational - - while (HI32(_offset) < inputFrames) { - - int32_t i = HI32(_offset); - uint32_t f = LO32(_offset); - - uint32_t phase = f >> SRC_FRACBITS; - __m128 frac = _mm_set1_ps((f & SRC_FRACMASK) * QFRAC_TO_FLOAT); - - const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; - const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; - - __m128 acc0 = _mm_setzero_ps(); - __m128 acc1 = _mm_setzero_ps(); - - for (int j = 0; j < _numTaps; j += 4) { - - //float coef = c0[j] + frac * (c1[j] - c0[j]); - __m128 coef0 = _mm_loadu_ps(&c0[j]); - __m128 coef1 = _mm_loadu_ps(&c1[j]); - coef1 = _mm_sub_ps(coef1, coef0); - coef0 = _mm_add_ps(_mm_mul_ps(coef1, frac), coef0); - - //acc += input[i + j] * coef; - acc0 = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(&input0[i + j]), coef0), acc0); - acc1 = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(&input1[i + j]), coef0), acc1); - } - - // horizontal sum - acc0 = _mm_add_ps(acc0, _mm_movehl_ps(acc0, acc0)); - acc1 = _mm_add_ps(acc1, _mm_movehl_ps(acc1, acc1)); - acc0 = _mm_add_ss(acc0, _mm_shuffle_ps(acc0, acc0, _MM_SHUFFLE(0,0,0,1))); - acc1 = _mm_add_ss(acc1, _mm_shuffle_ps(acc1, acc1, _MM_SHUFFLE(0,0,0,1))); - - _mm_store_ss(&output0[outputFrames], acc0); - _mm_store_ss(&output1[outputFrames], acc1); - outputFrames += 1; - - _offset += _step; - } - _offset -= (int64_t)inputFrames << 32; - } - - return outputFrames; -} - // // Runtime CPU dispatch // @@ -377,223 +426,22 @@ int AudioSRC::multirateFilter2_SSE(const float* input0, const float* input1, flo #include "CPUDetect.h" int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFrames) { - - static auto f = cpuSupportsAVX2() ? &AudioSRC::multirateFilter1_AVX2 : &AudioSRC::multirateFilter1_SSE; + static auto f = cpuSupportsAVX2() ? &AudioSRC::multirateFilter1_AVX2 : &AudioSRC::multirateFilter1_ref; return (this->*f)(input0, output0, inputFrames); // dispatch } int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames) { - - static auto f = cpuSupportsAVX2() ? &AudioSRC::multirateFilter2_AVX2 : &AudioSRC::multirateFilter2_SSE; + static auto f = cpuSupportsAVX2() ? &AudioSRC::multirateFilter2_AVX2 : &AudioSRC::multirateFilter2_ref; return (this->*f)(input0, input1, output0, output1, inputFrames); // dispatch } -// convert int16_t to float, deinterleave stereo -void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) { - __m128 scale = _mm_set1_ps(1/32768.0f); - - if (_numChannels == 1) { - - int i = 0; - for (; i < numFrames - 3; i += 4) { - __m128i a0 = _mm_loadl_epi64((__m128i*)&input[i]); - - // sign-extend - a0 = _mm_srai_epi32(_mm_unpacklo_epi16(a0, a0), 16); - - __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); - - _mm_storeu_ps(&outputs[0][i], f0); - } - for (; i < numFrames; i++) { - __m128i a0 = _mm_insert_epi16(_mm_setzero_si128(), input[i], 0); - - // sign-extend - a0 = _mm_srai_epi32(_mm_unpacklo_epi16(a0, a0), 16); - - __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); - - _mm_store_ss(&outputs[0][i], f0); - } - - } else if (_numChannels == 2) { - - int i = 0; - for (; i < numFrames - 3; i += 4) { - __m128i a0 = _mm_loadu_si128((__m128i*)&input[2*i]); - __m128i a1 = a0; - - // deinterleave and sign-extend - a0 = _mm_madd_epi16(a0, _mm_set1_epi32(0x00000001)); - a1 = _mm_madd_epi16(a1, _mm_set1_epi32(0x00010000)); - - __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); - __m128 f1 = _mm_mul_ps(_mm_cvtepi32_ps(a1), scale); - - _mm_storeu_ps(&outputs[0][i], f0); - _mm_storeu_ps(&outputs[1][i], f1); - } - for (; i < numFrames; i++) { - __m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]); - __m128i a1 = a0; - - // deinterleave and sign-extend - a0 = _mm_madd_epi16(a0, _mm_set1_epi32(0x00000001)); - a1 = _mm_madd_epi16(a1, _mm_set1_epi32(0x00010000)); - - __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); - __m128 f1 = _mm_mul_ps(_mm_cvtepi32_ps(a1), scale); - - _mm_store_ss(&outputs[0][i], f0); - _mm_store_ss(&outputs[1][i], f1); - } - } +int AudioSRC::multirateFilter4(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames) { + static auto f = cpuSupportsAVX2() ? &AudioSRC::multirateFilter4_AVX2 : &AudioSRC::multirateFilter4_ref; + return (this->*f)(input0, input1, input2, input3, output0, output1, output2, output3, inputFrames); // dispatch } -// fast TPDF dither in [-1.0f, 1.0f] -static inline __m128 dither4() { - static __m128i rz; - - // update the 8 different maximum-length LCGs - rz = _mm_mullo_epi16(rz, _mm_set_epi16(25173, -25511, -5975, -23279, 19445, -27591, 30185, -3495)); - rz = _mm_add_epi16(rz, _mm_set_epi16(13849, -32767, 105, -19675, -7701, -32679, -13225, 28013)); - - // promote to 32-bit - __m128i r0 = _mm_unpacklo_epi16(rz, _mm_setzero_si128()); - __m128i r1 = _mm_unpackhi_epi16(rz, _mm_setzero_si128()); - - // return (r0 - r1) * (1/65536.0f); - __m128 d0 = _mm_cvtepi32_ps(_mm_sub_epi32(r0, r1)); - return _mm_mul_ps(d0, _mm_set1_ps(1/65536.0f)); -} - -// convert float to int16_t with dither, interleave stereo -void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { - __m128 scale = _mm_set1_ps(32768.0f); - - if (_numChannels == 1) { - - int i = 0; - for (; i < numFrames - 3; i += 4) { - __m128 f0 = _mm_mul_ps(_mm_loadu_ps(&inputs[0][i]), scale); - - f0 = _mm_add_ps(f0, dither4()); - - // round and saturate - __m128i a0 = _mm_cvtps_epi32(f0); - a0 = _mm_packs_epi32(a0, a0); - - _mm_storel_epi64((__m128i*)&output[i], a0); - } - for (; i < numFrames; i++) { - __m128 f0 = _mm_mul_ps(_mm_load_ss(&inputs[0][i]), scale); - - f0 = _mm_add_ps(f0, dither4()); - - // round and saturate - __m128i a0 = _mm_cvtps_epi32(f0); - a0 = _mm_packs_epi32(a0, a0); - - output[i] = (int16_t)_mm_extract_epi16(a0, 0); - } - - } else if (_numChannels == 2) { - - int i = 0; - for (; i < numFrames - 3; i += 4) { - __m128 f0 = _mm_mul_ps(_mm_loadu_ps(&inputs[0][i]), scale); - __m128 f1 = _mm_mul_ps(_mm_loadu_ps(&inputs[1][i]), scale); - - __m128 d0 = dither4(); - f0 = _mm_add_ps(f0, d0); - f1 = _mm_add_ps(f1, d0); - - // round and saturate - __m128i a0 = _mm_cvtps_epi32(f0); - __m128i a1 = _mm_cvtps_epi32(f1); - a0 = _mm_packs_epi32(a0, a0); - a1 = _mm_packs_epi32(a1, a1); - - // interleave - a0 = _mm_unpacklo_epi16(a0, a1); - _mm_storeu_si128((__m128i*)&output[2*i], a0); - } - for (; i < numFrames; i++) { - __m128 f0 = _mm_mul_ps(_mm_load_ss(&inputs[0][i]), scale); - __m128 f1 = _mm_mul_ps(_mm_load_ss(&inputs[1][i]), scale); - - __m128 d0 = dither4(); - f0 = _mm_add_ps(f0, d0); - f1 = _mm_add_ps(f1, d0); - - // round and saturate - __m128i a0 = _mm_cvtps_epi32(f0); - __m128i a1 = _mm_cvtps_epi32(f1); - a0 = _mm_packs_epi32(a0, a0); - a1 = _mm_packs_epi32(a1, a1); - - // interleave - a0 = _mm_unpacklo_epi16(a0, a1); - *(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0); - } - } -} - -// deinterleave stereo -void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) { - - if (_numChannels == 1) { - - memcpy(outputs[0], input, numFrames * sizeof(float)); - - } else if (_numChannels == 2) { - - int i = 0; - for (; i < numFrames - 3; i += 4) { - __m128 f0 = _mm_loadu_ps(&input[2*i + 0]); - __m128 f1 = _mm_loadu_ps(&input[2*i + 4]); - - // deinterleave - _mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(2,0,2,0))); - _mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(3,1,3,1))); - } - for (; i < numFrames; i++) { - // deinterleave - outputs[0][i] = input[2*i + 0]; - outputs[1][i] = input[2*i + 1]; - } - } -} - -// interleave stereo -void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) { - - if (_numChannels == 1) { - - memcpy(output, inputs[0], numFrames * sizeof(float)); - - } else if (_numChannels == 2) { - - int i = 0; - for (; i < numFrames - 3; i += 4) { - __m128 f0 = _mm_loadu_ps(&inputs[0][i]); - __m128 f1 = _mm_loadu_ps(&inputs[1][i]); - - // interleave - _mm_storeu_ps(&output[2*i + 0], _mm_unpacklo_ps(f0, f1)); - _mm_storeu_ps(&output[2*i + 4], _mm_unpackhi_ps(f0, f1)); - } - for (; i < numFrames; i++) { - // interleave - output[2*i + 0] = inputs[0][i]; - output[2*i + 1] = inputs[1][i]; - } - } -} - -#else - -#if defined(__ARM_NEON__) || defined(__ARM_NEON) +#elif defined(__ARM_NEON__) || defined(__ARM_NEON) #include @@ -714,6 +562,7 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* //acc += input[i + j] * coef; acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 0]), coef0); acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 0]), coef0); + acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 4]), coef1); acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 4]), coef1); } @@ -766,6 +615,7 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* //acc += input[i + j] * coef; acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 0]), coef0); acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 0]), coef0); + acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 4]), coef1); acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 4]), coef1); } @@ -787,11 +637,12 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* return outputFrames; } -#else - -int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFrames) { +int AudioSRC::multirateFilter4(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames) { int outputFrames = 0; + assert(_numTaps % 8 == 0); // SIMD8 + if (_step == 0) { // rational int32_t i = HI32(_offset); @@ -800,16 +651,41 @@ int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFra const float* c0 = &_polyphaseFilter[_numTaps * _phase]; - float acc0 = 0.0f; + float32x4_t acc0 = vdupq_n_f32(0); + float32x4_t acc1 = vdupq_n_f32(0); + float32x4_t acc2 = vdupq_n_f32(0); + float32x4_t acc3 = vdupq_n_f32(0); - for (int j = 0; j < _numTaps; j++) { + for (int j = 0; j < _numTaps; j += 8) { - float coef = c0[j]; + //float coef = c0[j]; + float32x4_t coef0 = vld1q_f32(&c0[j + 0]); // aligned + float32x4_t coef1 = vld1q_f32(&c0[j + 4]); // aligned - acc0 += input0[i + j] * coef; + //acc += input[i + j] * coef; + acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 0]), coef0); + acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 0]), coef0); + acc2 = vmlaq_f32(acc2, vld1q_f32(&input2[i + j + 0]), coef0); + acc3 = vmlaq_f32(acc3, vld1q_f32(&input3[i + j + 0]), coef0); + + acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 4]), coef1); + acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 4]), coef1); + acc2 = vmlaq_f32(acc2, vld1q_f32(&input2[i + j + 4]), coef1); + acc3 = vmlaq_f32(acc3, vld1q_f32(&input3[i + j + 4]), coef1); } - output0[outputFrames] = acc0; + // horizontal sum + float32x2_t t0 = vadd_f32(vget_low_f32(acc0), vget_high_f32(acc0)); + float32x2_t t1 = vadd_f32(vget_low_f32(acc1), vget_high_f32(acc1)); + float32x2_t t2 = vadd_f32(vget_low_f32(acc2), vget_high_f32(acc2)); + float32x2_t t3 = vadd_f32(vget_low_f32(acc3), vget_high_f32(acc3)); + t0 = vpadd_f32(t0, t1); + t2 = vpadd_f32(t2, t3); + + vst1_lane_f32(&output0[outputFrames], t0, 0); + vst1_lane_f32(&output1[outputFrames], t0, 1); + vst1_lane_f32(&output2[outputFrames], t2, 0); + vst1_lane_f32(&output3[outputFrames], t2, 1); outputFrames += 1; i += _stepTable[_phase]; @@ -827,21 +703,53 @@ int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFra uint32_t f = LO32(_offset); uint32_t phase = f >> SRC_FRACBITS; - float frac = (f & SRC_FRACMASK) * QFRAC_TO_FLOAT; + float32x4_t frac = vdupq_n_f32((f & SRC_FRACMASK) * QFRAC_TO_FLOAT); const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; - float acc0 = 0.0f; + float32x4_t acc0 = vdupq_n_f32(0); + float32x4_t acc1 = vdupq_n_f32(0); + float32x4_t acc2 = vdupq_n_f32(0); + float32x4_t acc3 = vdupq_n_f32(0); - for (int j = 0; j < _numTaps; j++) { + for (int j = 0; j < _numTaps; j += 8) { - float coef = c0[j] + frac * (c1[j] - c0[j]); + float32x4_t coef0 = vld1q_f32(&c0[j + 0]); // aligned + float32x4_t coef1 = vld1q_f32(&c0[j + 4]); // aligned + float32x4_t coef2 = vld1q_f32(&c1[j + 0]); // aligned + float32x4_t coef3 = vld1q_f32(&c1[j + 4]); // aligned - acc0 += input0[i + j] * coef; + //float coef = c0[j] + frac * (c1[j] - c0[j]); + coef2 = vsubq_f32(coef2, coef0); + coef3 = vsubq_f32(coef3, coef1); + coef0 = vmlaq_f32(coef0, coef2, frac); + coef1 = vmlaq_f32(coef1, coef3, frac); + + //acc += input[i + j] * coef; + acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 0]), coef0); + acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 0]), coef0); + acc2 = vmlaq_f32(acc2, vld1q_f32(&input2[i + j + 0]), coef0); + acc3 = vmlaq_f32(acc3, vld1q_f32(&input3[i + j + 0]), coef0); + + acc0 = vmlaq_f32(acc0, vld1q_f32(&input0[i + j + 4]), coef1); + acc1 = vmlaq_f32(acc1, vld1q_f32(&input1[i + j + 4]), coef1); + acc2 = vmlaq_f32(acc2, vld1q_f32(&input2[i + j + 4]), coef1); + acc3 = vmlaq_f32(acc3, vld1q_f32(&input3[i + j + 4]), coef1); } - output0[outputFrames] = acc0; + // horizontal sum + float32x2_t t0 = vadd_f32(vget_low_f32(acc0), vget_high_f32(acc0)); + float32x2_t t1 = vadd_f32(vget_low_f32(acc1), vget_high_f32(acc1)); + float32x2_t t2 = vadd_f32(vget_low_f32(acc2), vget_high_f32(acc2)); + float32x2_t t3 = vadd_f32(vget_low_f32(acc3), vget_high_f32(acc3)); + t0 = vpadd_f32(t0, t1); + t2 = vpadd_f32(t2, t3); + + vst1_lane_f32(&output0[outputFrames], t0, 0); + vst1_lane_f32(&output1[outputFrames], t0, 1); + vst1_lane_f32(&output2[outputFrames], t2, 0); + vst1_lane_f32(&output3[outputFrames], t2, 1); outputFrames += 1; _offset += _step; @@ -852,77 +760,409 @@ int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFra return outputFrames; } +#else // portable reference code + +int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFrames) { + return multirateFilter1_ref(input0, output0, inputFrames); +} + int AudioSRC::multirateFilter2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames) { - int outputFrames = 0; + return multirateFilter2_ref(input0, input1, output0, output1, inputFrames); +} - if (_step == 0) { // rational - - int32_t i = HI32(_offset); - - while (i < inputFrames) { - - const float* c0 = &_polyphaseFilter[_numTaps * _phase]; - - float acc0 = 0.0f; - float acc1 = 0.0f; - - for (int j = 0; j < _numTaps; j++) { - - float coef = c0[j]; - - acc0 += input0[i + j] * coef; - acc1 += input1[i + j] * coef; - } - - output0[outputFrames] = acc0; - output1[outputFrames] = acc1; - outputFrames += 1; - - i += _stepTable[_phase]; - if (++_phase == _upFactor) { - _phase = 0; - } - } - _offset = (int64_t)(i - inputFrames) << 32; - - } else { // irrational - - while (HI32(_offset) < inputFrames) { - - int32_t i = HI32(_offset); - uint32_t f = LO32(_offset); - - uint32_t phase = f >> SRC_FRACBITS; - float frac = (f & SRC_FRACMASK) * QFRAC_TO_FLOAT; - - const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; - const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; - - float acc0 = 0.0f; - float acc1 = 0.0f; - - for (int j = 0; j < _numTaps; j++) { - - float coef = c0[j] + frac * (c1[j] - c0[j]); - - acc0 += input0[i + j] * coef; - acc1 += input1[i + j] * coef; - } - - output0[outputFrames] = acc0; - output1[outputFrames] = acc1; - outputFrames += 1; - - _offset += _step; - } - _offset -= (int64_t)inputFrames << 32; - } - - return outputFrames; +int AudioSRC::multirateFilter4(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames) { + return multirateFilter4_ref(input0, input1, input2, input3, output0, output1, output2, output3, inputFrames); } #endif +// +// on x86 architecture, assume that SSE2 is present +// +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__) + +#include // SSE2 + +// convert int16_t to float, deinterleave stereo +void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) { + __m128 scale = _mm_set1_ps(1/32768.0f); + + if (_numChannels == 1) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128i a0 = _mm_loadl_epi64((__m128i*)&input[i]); + + // sign-extend + a0 = _mm_srai_epi32(_mm_unpacklo_epi16(a0, a0), 16); + + __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); + + _mm_storeu_ps(&outputs[0][i], f0); + } + for (; i < numFrames; i++) { + __m128i a0 = _mm_insert_epi16(_mm_setzero_si128(), input[i], 0); + + // sign-extend + a0 = _mm_srai_epi32(_mm_unpacklo_epi16(a0, a0), 16); + + __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); + + _mm_store_ss(&outputs[0][i], f0); + } + + } else if (_numChannels == 2) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128i a0 = _mm_loadu_si128((__m128i*)&input[2*i]); + __m128i a1 = a0; + + // deinterleave and sign-extend + a0 = _mm_madd_epi16(a0, _mm_set1_epi32(0x00000001)); + a1 = _mm_madd_epi16(a1, _mm_set1_epi32(0x00010000)); + + __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); + __m128 f1 = _mm_mul_ps(_mm_cvtepi32_ps(a1), scale); + + _mm_storeu_ps(&outputs[0][i], f0); + _mm_storeu_ps(&outputs[1][i], f1); + } + for (; i < numFrames; i++) { + __m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]); + __m128i a1 = a0; + + // deinterleave and sign-extend + a0 = _mm_madd_epi16(a0, _mm_set1_epi32(0x00000001)); + a1 = _mm_madd_epi16(a1, _mm_set1_epi32(0x00010000)); + + __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); + __m128 f1 = _mm_mul_ps(_mm_cvtepi32_ps(a1), scale); + + _mm_store_ss(&outputs[0][i], f0); + _mm_store_ss(&outputs[1][i], f1); + } + } else if (_numChannels == 4) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128i a0 = _mm_loadu_si128((__m128i*)&input[4*i+0]); + __m128i a1 = a0; + __m128i a2 = _mm_loadu_si128((__m128i*)&input[4*i+8]); + __m128i a3 = a2; + + // deinterleave and sign-extend + a0 = _mm_madd_epi16(a0, _mm_set1_epi32(0x00000001)); + a1 = _mm_madd_epi16(a1, _mm_set1_epi32(0x00010000)); + a2 = _mm_madd_epi16(a2, _mm_set1_epi32(0x00000001)); + a3 = _mm_madd_epi16(a3, _mm_set1_epi32(0x00010000)); + + __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); + __m128 f1 = _mm_mul_ps(_mm_cvtepi32_ps(a1), scale); + __m128 f2 = _mm_mul_ps(_mm_cvtepi32_ps(a2), scale); + __m128 f3 = _mm_mul_ps(_mm_cvtepi32_ps(a3), scale); + + _mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f2, _MM_SHUFFLE(2,0,2,0))); + _mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f1, f3, _MM_SHUFFLE(2,0,2,0))); + _mm_storeu_ps(&outputs[2][i], _mm_shuffle_ps(f0, f2, _MM_SHUFFLE(3,1,3,1))); + _mm_storeu_ps(&outputs[3][i], _mm_shuffle_ps(f1, f3, _MM_SHUFFLE(3,1,3,1))); + } + for (; i < numFrames; i++) { + __m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+0]); + __m128i a1 = a0; + __m128i a2 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+2]); + __m128i a3 = a2; + + // deinterleave and sign-extend + a0 = _mm_madd_epi16(a0, _mm_set1_epi32(0x00000001)); + a1 = _mm_madd_epi16(a1, _mm_set1_epi32(0x00010000)); + a2 = _mm_madd_epi16(a2, _mm_set1_epi32(0x00000001)); + a3 = _mm_madd_epi16(a3, _mm_set1_epi32(0x00010000)); + + __m128 f0 = _mm_mul_ps(_mm_cvtepi32_ps(a0), scale); + __m128 f1 = _mm_mul_ps(_mm_cvtepi32_ps(a1), scale); + __m128 f2 = _mm_mul_ps(_mm_cvtepi32_ps(a2), scale); + __m128 f3 = _mm_mul_ps(_mm_cvtepi32_ps(a3), scale); + + _mm_store_ss(&outputs[0][i], f0); + _mm_store_ss(&outputs[1][i], f1); + _mm_store_ss(&outputs[2][i], f2); + _mm_store_ss(&outputs[3][i], f3); + } + } +} + +// fast TPDF dither in [-1.0f, 1.0f] +static inline __m128 dither4() { + static __m128i rz; + + // update the 8 different maximum-length LCGs + rz = _mm_mullo_epi16(rz, _mm_set_epi16(25173, -25511, -5975, -23279, 19445, -27591, 30185, -3495)); + rz = _mm_add_epi16(rz, _mm_set_epi16(13849, -32767, 105, -19675, -7701, -32679, -13225, 28013)); + + // promote to 32-bit + __m128i r0 = _mm_unpacklo_epi16(rz, _mm_setzero_si128()); + __m128i r1 = _mm_unpackhi_epi16(rz, _mm_setzero_si128()); + + // return (r0 - r1) * (1/65536.0f); + __m128 d0 = _mm_cvtepi32_ps(_mm_sub_epi32(r0, r1)); + return _mm_mul_ps(d0, _mm_set1_ps(1/65536.0f)); +} + +// convert float to int16_t with dither, interleave stereo +void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { + __m128 scale = _mm_set1_ps(32768.0f); + + if (_numChannels == 1) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_mul_ps(_mm_loadu_ps(&inputs[0][i]), scale); + + f0 = _mm_add_ps(f0, dither4()); + + // round and saturate + __m128i a0 = _mm_cvtps_epi32(f0); + a0 = _mm_packs_epi32(a0, a0); + + _mm_storel_epi64((__m128i*)&output[i], a0); + } + for (; i < numFrames; i++) { + __m128 f0 = _mm_mul_ps(_mm_load_ss(&inputs[0][i]), scale); + + f0 = _mm_add_ps(f0, dither4()); + + // round and saturate + __m128i a0 = _mm_cvtps_epi32(f0); + a0 = _mm_packs_epi32(a0, a0); + + output[i] = (int16_t)_mm_extract_epi16(a0, 0); + } + + } else if (_numChannels == 2) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_mul_ps(_mm_loadu_ps(&inputs[0][i]), scale); + __m128 f1 = _mm_mul_ps(_mm_loadu_ps(&inputs[1][i]), scale); + + __m128 d0 = dither4(); + f0 = _mm_add_ps(f0, d0); + f1 = _mm_add_ps(f1, d0); + + // round and saturate + __m128i a0 = _mm_cvtps_epi32(f0); + __m128i a1 = _mm_cvtps_epi32(f1); + a0 = _mm_packs_epi32(a0, a0); + a1 = _mm_packs_epi32(a1, a1); + + // interleave + a0 = _mm_unpacklo_epi16(a0, a1); + _mm_storeu_si128((__m128i*)&output[2*i], a0); + } + for (; i < numFrames; i++) { + __m128 f0 = _mm_mul_ps(_mm_load_ss(&inputs[0][i]), scale); + __m128 f1 = _mm_mul_ps(_mm_load_ss(&inputs[1][i]), scale); + + __m128 d0 = dither4(); + f0 = _mm_add_ps(f0, d0); + f1 = _mm_add_ps(f1, d0); + + // round and saturate + __m128i a0 = _mm_cvtps_epi32(f0); + __m128i a1 = _mm_cvtps_epi32(f1); + a0 = _mm_packs_epi32(a0, a0); + a1 = _mm_packs_epi32(a1, a1); + + // interleave + a0 = _mm_unpacklo_epi16(a0, a1); + *(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0); + } + + } else if (_numChannels == 4) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_mul_ps(_mm_loadu_ps(&inputs[0][i]), scale); + __m128 f1 = _mm_mul_ps(_mm_loadu_ps(&inputs[1][i]), scale); + __m128 f2 = _mm_mul_ps(_mm_loadu_ps(&inputs[2][i]), scale); + __m128 f3 = _mm_mul_ps(_mm_loadu_ps(&inputs[3][i]), scale); + + __m128 d0 = dither4(); + f0 = _mm_add_ps(f0, d0); + f1 = _mm_add_ps(f1, d0); + f2 = _mm_add_ps(f2, d0); + f3 = _mm_add_ps(f3, d0); + + // round and saturate + __m128i a0 = _mm_cvtps_epi32(f0); + __m128i a1 = _mm_cvtps_epi32(f1); + __m128i a2 = _mm_cvtps_epi32(f2); + __m128i a3 = _mm_cvtps_epi32(f3); + a0 = _mm_packs_epi32(a0, a2); + a1 = _mm_packs_epi32(a1, a3); + + // interleave + a2 = _mm_unpacklo_epi16(a0, a1); + a3 = _mm_unpackhi_epi16(a0, a1); + a0 = _mm_unpacklo_epi32(a2, a3); + a1 = _mm_unpackhi_epi32(a2, a3); + + _mm_storeu_si128((__m128i*)&output[4*i+0], a0); + _mm_storeu_si128((__m128i*)&output[4*i+8], a1); + } + for (; i < numFrames; i++) { + __m128 f0 = _mm_mul_ps(_mm_load_ss(&inputs[0][i]), scale); + __m128 f1 = _mm_mul_ps(_mm_load_ss(&inputs[1][i]), scale); + __m128 f2 = _mm_mul_ps(_mm_load_ss(&inputs[2][i]), scale); + __m128 f3 = _mm_mul_ps(_mm_load_ss(&inputs[3][i]), scale); + + __m128 d0 = dither4(); + f0 = _mm_add_ps(f0, d0); + f1 = _mm_add_ps(f1, d0); + f2 = _mm_add_ps(f2, d0); + f3 = _mm_add_ps(f3, d0); + + // round and saturate + __m128i a0 = _mm_cvtps_epi32(f0); + __m128i a1 = _mm_cvtps_epi32(f1); + __m128i a2 = _mm_cvtps_epi32(f2); + __m128i a3 = _mm_cvtps_epi32(f3); + a0 = _mm_packs_epi32(a0, a2); + a1 = _mm_packs_epi32(a1, a3); + + // interleave + a2 = _mm_unpacklo_epi16(a0, a1); + a3 = _mm_unpackhi_epi16(a0, a1); + a0 = _mm_unpacklo_epi32(a2, a3); + a1 = _mm_unpackhi_epi32(a2, a3); + + _mm_storel_epi64((__m128i*)&output[4*i], a0); + } + } +} + +// deinterleave stereo +void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) { + + if (_numChannels == 1) { + + memcpy(outputs[0], input, numFrames * sizeof(float)); + + } else if (_numChannels == 2) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&input[2*i + 0]); + __m128 f1 = _mm_loadu_ps(&input[2*i + 4]); + + // deinterleave + _mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(2,0,2,0))); + _mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(3,1,3,1))); + } + for (; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[2*i + 0]; + outputs[1][i] = input[2*i + 1]; + } + + } else if (_numChannels == 4) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&input[4*i + 0]); + __m128 f1 = _mm_loadu_ps(&input[4*i + 4]); + __m128 f2 = _mm_loadu_ps(&input[4*i + 8]); + __m128 f3 = _mm_loadu_ps(&input[4*i + 12]); + + // deinterleave + __m128 t0 = _mm_unpacklo_ps(f0, f1); + __m128 t2 = _mm_unpacklo_ps(f2, f3); + __m128 t1 = _mm_unpackhi_ps(f0, f1); + __m128 t3 = _mm_unpackhi_ps(f2, f3); + + f0 = _mm_movelh_ps(t0, t2); + f1 = _mm_movehl_ps(t2, t0); + f2 = _mm_movelh_ps(t1, t3); + f3 = _mm_movehl_ps(t3, t1); + + _mm_storeu_ps(&outputs[0][i], f0); + _mm_storeu_ps(&outputs[1][i], f1); + _mm_storeu_ps(&outputs[2][i], f2); + _mm_storeu_ps(&outputs[3][i], f3); + } + for (; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[4*i + 0]; + outputs[1][i] = input[4*i + 1]; + outputs[2][i] = input[4*i + 2]; + outputs[3][i] = input[4*i + 3]; + } + } +} + +// interleave stereo +void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) { + + if (_numChannels == 1) { + + memcpy(output, inputs[0], numFrames * sizeof(float)); + + } else if (_numChannels == 2) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&inputs[0][i]); + __m128 f1 = _mm_loadu_ps(&inputs[1][i]); + + // interleave + _mm_storeu_ps(&output[2*i + 0], _mm_unpacklo_ps(f0, f1)); + _mm_storeu_ps(&output[2*i + 4], _mm_unpackhi_ps(f0, f1)); + } + for (; i < numFrames; i++) { + // interleave + output[2*i + 0] = inputs[0][i]; + output[2*i + 1] = inputs[1][i]; + } + + } else if (_numChannels == 4) { + + int i = 0; + for (; i < numFrames - 3; i += 4) { + __m128 f0 = _mm_loadu_ps(&inputs[0][i]); + __m128 f1 = _mm_loadu_ps(&inputs[1][i]); + __m128 f2 = _mm_loadu_ps(&inputs[2][i]); + __m128 f3 = _mm_loadu_ps(&inputs[3][i]); + + // interleave + __m128 t0 = _mm_unpacklo_ps(f0, f1); + __m128 t2 = _mm_unpacklo_ps(f2, f3); + __m128 t1 = _mm_unpackhi_ps(f0, f1); + __m128 t3 = _mm_unpackhi_ps(f2, f3); + + f0 = _mm_movelh_ps(t0, t2); + f1 = _mm_movehl_ps(t2, t0); + f2 = _mm_movelh_ps(t1, t3); + f3 = _mm_movehl_ps(t3, t1); + + _mm_storeu_ps(&output[4*i + 0], f0); + _mm_storeu_ps(&output[4*i + 4], f1); + _mm_storeu_ps(&output[4*i + 8], f2); + _mm_storeu_ps(&output[4*i + 12], f3); + } + for (; i < numFrames; i++) { + // interleave + output[4*i + 0] = inputs[0][i]; + output[4*i + 1] = inputs[1][i]; + output[4*i + 2] = inputs[2][i]; + output[4*i + 3] = inputs[3][i]; + } + } +} + +#else // portable reference code + // convert int16_t to float, deinterleave stereo void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) { const float scale = 1/32768.0f; @@ -936,6 +1176,13 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames outputs[0][i] = (float)input[2*i + 0] * scale; outputs[1][i] = (float)input[2*i + 1] * scale; } + } else if (_numChannels == 4) { + for (int i = 0; i < numFrames; i++) { + outputs[0][i] = (float)input[4*i + 0] * scale; + outputs[1][i] = (float)input[4*i + 1] * scale; + outputs[2][i] = (float)input[4*i + 2] * scale; + outputs[3][i] = (float)input[4*i + 3] * scale; + } } } @@ -961,7 +1208,7 @@ void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { // round and saturate f += (f < 0.0f ? -0.5f : +0.5f); - f = std::max(std::min(f, 32767.0f), -32768.0f); + f = MAX(MIN(f, 32767.0f), -32768.0f); output[i] = (int16_t)f; } @@ -978,13 +1225,43 @@ void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { // round and saturate f0 += (f0 < 0.0f ? -0.5f : +0.5f); f1 += (f1 < 0.0f ? -0.5f : +0.5f); - f0 = std::max(std::min(f0, 32767.0f), -32768.0f); - f1 = std::max(std::min(f1, 32767.0f), -32768.0f); + f0 = MAX(MIN(f0, 32767.0f), -32768.0f); + f1 = MAX(MIN(f1, 32767.0f), -32768.0f); // interleave output[2*i + 0] = (int16_t)f0; output[2*i + 1] = (int16_t)f1; } + } else if (_numChannels == 4) { + for (int i = 0; i < numFrames; i++) { + + float f0 = inputs[0][i] * scale; + float f1 = inputs[1][i] * scale; + float f2 = inputs[2][i] * scale; + float f3 = inputs[3][i] * scale; + + float d = dither(); + f0 += d; + f1 += d; + f2 += d; + f3 += d; + + // round and saturate + f0 += (f0 < 0.0f ? -0.5f : +0.5f); + f1 += (f1 < 0.0f ? -0.5f : +0.5f); + f2 += (f2 < 0.0f ? -0.5f : +0.5f); + f3 += (f3 < 0.0f ? -0.5f : +0.5f); + f0 = MAX(MIN(f0, 32767.0f), -32768.0f); + f1 = MAX(MIN(f1, 32767.0f), -32768.0f); + f2 = MAX(MIN(f2, 32767.0f), -32768.0f); + f3 = MAX(MIN(f3, 32767.0f), -32768.0f); + + // interleave + output[4*i + 0] = (int16_t)f0; + output[4*i + 1] = (int16_t)f1; + output[4*i + 2] = (int16_t)f2; + output[4*i + 3] = (int16_t)f3; + } } } @@ -1001,6 +1278,14 @@ void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) outputs[0][i] = input[2*i + 0]; outputs[1][i] = input[2*i + 1]; } + } else if (_numChannels == 4) { + for (int i = 0; i < numFrames; i++) { + // deinterleave + outputs[0][i] = input[4*i + 0]; + outputs[1][i] = input[4*i + 1]; + outputs[2][i] = input[4*i + 2]; + outputs[3][i] = input[4*i + 3]; + } } } @@ -1017,6 +1302,14 @@ void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) { output[2*i + 0] = inputs[0][i]; output[2*i + 1] = inputs[1][i]; } + } else if (_numChannels == 4) { + for (int i = 0; i < numFrames; i++) { + // interleave + output[4*i + 0] = inputs[0][i]; + output[4*i + 1] = inputs[1][i]; + output[4*i + 2] = inputs[2][i]; + output[4*i + 3] = inputs[3][i]; + } } } @@ -1025,8 +1318,8 @@ void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) { int AudioSRC::render(float** inputs, float** outputs, int inputFrames) { int outputFrames = 0; - int nh = std::min(_numHistory, inputFrames); // number of frames from history buffer - int ni = inputFrames - nh; // number of frames from remaining input + int nh = MIN(_numHistory, inputFrames); // number of frames from history buffer + int ni = inputFrames - nh; // number of frames from remaining input if (_numChannels == 1) { @@ -1070,6 +1363,43 @@ int AudioSRC::render(float** inputs, float** outputs, int inputFrames) { memmove(_history[0], _history[0] + nh, _numHistory * sizeof(float)); memmove(_history[1], _history[1] + nh, _numHistory * sizeof(float)); } + + } else if (_numChannels == 4) { + + // refill history buffers + memcpy(_history[0] + _numHistory, inputs[0], nh * sizeof(float)); + memcpy(_history[1] + _numHistory, inputs[1], nh * sizeof(float)); + memcpy(_history[2] + _numHistory, inputs[2], nh * sizeof(float)); + memcpy(_history[3] + _numHistory, inputs[3], nh * sizeof(float)); + + // process history buffer + outputFrames += multirateFilter4(_history[0], _history[1], _history[2], _history[3], + outputs[0], + outputs[1], + outputs[2], + outputs[3], nh); + + // process remaining input + if (ni) { + outputFrames += multirateFilter4(inputs[0], inputs[1], inputs[2], inputs[3], + outputs[0] + outputFrames, + outputs[1] + outputFrames, + outputs[2] + outputFrames, + outputs[3] + outputFrames, ni); + } + + // shift history buffers + if (ni) { + memcpy(_history[0], inputs[0] + ni, _numHistory * sizeof(float)); + memcpy(_history[1], inputs[1] + ni, _numHistory * sizeof(float)); + memcpy(_history[2], inputs[2] + ni, _numHistory * sizeof(float)); + memcpy(_history[3], inputs[3] + ni, _numHistory * sizeof(float)); + } else { + memmove(_history[0], _history[0] + nh, _numHistory * sizeof(float)); + memmove(_history[1], _history[1] + nh, _numHistory * sizeof(float)); + memmove(_history[2], _history[2] + nh, _numHistory * sizeof(float)); + memmove(_history[3], _history[3] + nh, _numHistory * sizeof(float)); + } } return outputFrames; @@ -1110,35 +1440,40 @@ AudioSRC::AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels) { //printf("up=%d down=%.3f taps=%d\n", _upFactor, _downFactor + (LO32(_step)<> 32); } } - -// the input frames that will produce exactly outputFrames -int AudioSRC::getExactInput(int outputFrames) { - // - // For upsampling, a correct implementation is more complicated - // because it requires early exit of the multirate filter. - // This is not currently supported. - // - if (_upFactor > _downFactor) { - return -1; - } - if (_step == 0) { - int64_t offset = ((int64_t)_phase * _downFactor) % _upFactor; - return (int)(((int64_t)outputFrames * _downFactor + offset) / _upFactor); - } else { - return (int)(((int64_t)outputFrames * _step + _offset) >> 32); - } -} diff --git a/libraries/audio/src/AudioSRC.h b/libraries/audio/src/AudioSRC.h index 5ae5318b5e..301786ee8f 100644 --- a/libraries/audio/src/AudioSRC.h +++ b/libraries/audio/src/AudioSRC.h @@ -14,7 +14,7 @@ #include -static const int SRC_MAX_CHANNELS = 2; +static const int SRC_MAX_CHANNELS = 4; // polyphase filter static const int SRC_PHASEBITS = 8; @@ -48,8 +48,6 @@ public: int getMinInput(int outputFrames); int getMaxInput(int outputFrames); - int getExactInput(int outputFrames); - private: float* _polyphaseFilter; int* _stepTable; @@ -77,12 +75,18 @@ private: int multirateFilter1(const float* input0, float* output0, int inputFrames); int multirateFilter2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames); + int multirateFilter4(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames); - int multirateFilter1_SSE(const float* input0, float* output0, int inputFrames); - int multirateFilter2_SSE(const float* input0, const float* input1, float* output0, float* output1, int inputFrames); + int multirateFilter1_ref(const float* input0, float* output0, int inputFrames); + int multirateFilter2_ref(const float* input0, const float* input1, float* output0, float* output1, int inputFrames); + int multirateFilter4_ref(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames); int multirateFilter1_AVX2(const float* input0, float* output0, int inputFrames); int multirateFilter2_AVX2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames); + int multirateFilter4_AVX2(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames); void convertInput(const int16_t* input, float** outputs, int numFrames); void convertOutput(float** inputs, int16_t* output, int numFrames); diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index f8dd4b9e27..d6607424db 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -97,54 +97,9 @@ void Sound::downSample(const QByteArray& rawAudioByteArray, int sampleRate) { // no resampling needed _byteArray = rawAudioByteArray; - } else if (_isAmbisonic) { - - // FIXME: add a proper Ambisonic resampler! - int numChannels = 4; - AudioSRC resampler[4] { {sampleRate, AudioConstants::SAMPLE_RATE, 1}, - {sampleRate, AudioConstants::SAMPLE_RATE, 1}, - {sampleRate, AudioConstants::SAMPLE_RATE, 1}, - {sampleRate, AudioConstants::SAMPLE_RATE, 1} }; - - // resize to max possible output - int numSourceFrames = rawAudioByteArray.size() / (numChannels * sizeof(AudioConstants::AudioSample)); - int maxDestinationFrames = resampler[0].getMaxOutput(numSourceFrames); - int maxDestinationBytes = maxDestinationFrames * numChannels * sizeof(AudioConstants::AudioSample); - _byteArray.resize(maxDestinationBytes); - - int numDestinationFrames = 0; - - // iterate over channels - int16_t* srcBuffer = new int16_t[numSourceFrames]; - int16_t* dstBuffer = new int16_t[maxDestinationFrames]; - for (int ch = 0; ch < 4; ch++) { - - int16_t* src = (int16_t*)rawAudioByteArray.data(); - int16_t* dst = (int16_t*)_byteArray.data(); - - // deinterleave samples - for (int i = 0; i < numSourceFrames; i++) { - srcBuffer[i] = src[4*i + ch]; - } - - // resample one channel - numDestinationFrames = resampler[ch].render(srcBuffer, dstBuffer, numSourceFrames); - - // reinterleave samples - for (int i = 0; i < numDestinationFrames; i++) { - dst[4*i + ch] = dstBuffer[i]; - } - } - delete[] srcBuffer; - delete[] dstBuffer; - - // truncate to actual output - int numDestinationBytes = numDestinationFrames * numChannels * sizeof(AudioConstants::AudioSample); - _byteArray.resize(numDestinationBytes); - } else { - int numChannels = _isStereo ? 2 : 1; + int numChannels = _isAmbisonic ? AudioConstants::AMBISONIC : (_isStereo ? AudioConstants::STEREO : AudioConstants::MONO); AudioSRC resampler(sampleRate, AudioConstants::SAMPLE_RATE, numChannels); // resize to max possible output diff --git a/libraries/audio/src/avx2/AudioSRC_avx2.cpp b/libraries/audio/src/avx2/AudioSRC_avx2.cpp index e634554bfb..693bad7fc6 100644 --- a/libraries/audio/src/avx2/AudioSRC_avx2.cpp +++ b/libraries/audio/src/avx2/AudioSRC_avx2.cpp @@ -198,4 +198,109 @@ int AudioSRC::multirateFilter2_AVX2(const float* input0, const float* input1, fl return outputFrames; } +int AudioSRC::multirateFilter4_AVX2(const float* input0, const float* input1, const float* input2, const float* input3, + float* output0, float* output1, float* output2, float* output3, int inputFrames) { + int outputFrames = 0; + + assert(_numTaps % 8 == 0); // SIMD8 + + if (_step == 0) { // rational + + int32_t i = HI32(_offset); + + while (i < inputFrames) { + + const float* c0 = &_polyphaseFilter[_numTaps * _phase]; + + __m256 acc0 = _mm256_setzero_ps(); + __m256 acc1 = _mm256_setzero_ps(); + __m256 acc2 = _mm256_setzero_ps(); + __m256 acc3 = _mm256_setzero_ps(); + + for (int j = 0; j < _numTaps; j += 8) { + + //float coef = c0[j]; + __m256 coef0 = _mm256_loadu_ps(&c0[j]); + + //acc += input[i + j] * coef; + acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j]), coef0, acc0); + acc1 = _mm256_fmadd_ps(_mm256_loadu_ps(&input1[i + j]), coef0, acc1); + acc2 = _mm256_fmadd_ps(_mm256_loadu_ps(&input2[i + j]), coef0, acc2); + acc3 = _mm256_fmadd_ps(_mm256_loadu_ps(&input3[i + j]), coef0, acc3); + } + + // horizontal sum + acc0 = _mm256_hadd_ps(acc0, acc1); + acc2 = _mm256_hadd_ps(acc2, acc3); + acc0 = _mm256_hadd_ps(acc0, acc2); + __m128 t0 = _mm_add_ps(_mm256_castps256_ps128(acc0), _mm256_extractf128_ps(acc0, 1)); + + _mm_store_ss(&output0[outputFrames], t0); + _mm_store_ss(&output1[outputFrames], _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0,0,0,1))); + _mm_store_ss(&output2[outputFrames], _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0,0,0,2))); + _mm_store_ss(&output3[outputFrames], _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0,0,0,3))); + outputFrames += 1; + + i += _stepTable[_phase]; + if (++_phase == _upFactor) { + _phase = 0; + } + } + _offset = (int64_t)(i - inputFrames) << 32; + + } else { // irrational + + while (HI32(_offset) < inputFrames) { + + int32_t i = HI32(_offset); + uint32_t f = LO32(_offset); + + uint32_t phase = f >> SRC_FRACBITS; + float ftmp = (f & SRC_FRACMASK) * QFRAC_TO_FLOAT; + + const float* c0 = &_polyphaseFilter[_numTaps * (phase + 0)]; + const float* c1 = &_polyphaseFilter[_numTaps * (phase + 1)]; + + __m256 acc0 = _mm256_setzero_ps(); + __m256 acc1 = _mm256_setzero_ps(); + __m256 acc2 = _mm256_setzero_ps(); + __m256 acc3 = _mm256_setzero_ps(); + __m256 frac = _mm256_broadcast_ss(&ftmp); + + for (int j = 0; j < _numTaps; j += 8) { + + //float coef = c0[j] + frac * (c1[j] - c0[j]); + __m256 coef0 = _mm256_loadu_ps(&c0[j]); + __m256 coef1 = _mm256_loadu_ps(&c1[j]); + coef1 = _mm256_sub_ps(coef1, coef0); + coef0 = _mm256_fmadd_ps(coef1, frac, coef0); + + //acc += input[i + j] * coef; + acc0 = _mm256_fmadd_ps(_mm256_loadu_ps(&input0[i + j]), coef0, acc0); + acc1 = _mm256_fmadd_ps(_mm256_loadu_ps(&input1[i + j]), coef0, acc1); + acc2 = _mm256_fmadd_ps(_mm256_loadu_ps(&input2[i + j]), coef0, acc2); + acc3 = _mm256_fmadd_ps(_mm256_loadu_ps(&input3[i + j]), coef0, acc3); + } + + // horizontal sum + acc0 = _mm256_hadd_ps(acc0, acc1); + acc2 = _mm256_hadd_ps(acc2, acc3); + acc0 = _mm256_hadd_ps(acc0, acc2); + __m128 t0 = _mm_add_ps(_mm256_castps256_ps128(acc0), _mm256_extractf128_ps(acc0, 1)); + + _mm_store_ss(&output0[outputFrames], t0); + _mm_store_ss(&output1[outputFrames], _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0,0,0,1))); + _mm_store_ss(&output2[outputFrames], _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0,0,0,2))); + _mm_store_ss(&output3[outputFrames], _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0,0,0,3))); + outputFrames += 1; + + _offset += _step; + } + _offset -= (int64_t)inputFrames << 32; + } + _mm256_zeroupper(); + + return outputFrames; +} + #endif diff --git a/libraries/auto-updater/src/AutoUpdater.h b/libraries/auto-updater/src/AutoUpdater.h index 70867e5a44..1e62ce0283 100644 --- a/libraries/auto-updater/src/AutoUpdater.h +++ b/libraries/auto-updater/src/AutoUpdater.h @@ -12,8 +12,6 @@ #ifndef hifi_AutoUpdater_h #define hifi_AutoUpdater_h - -#include #include #include #include diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 969c0a95a9..1c73e4dda2 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -16,7 +16,6 @@ #include #include - #if defined(Q_OS_MAC) #include #endif @@ -44,6 +43,7 @@ #include #include "CompositorHelper.h" +#include "Logging.h" const char* SRGB_TO_LINEAR_FRAG = R"SCRIBE( @@ -129,7 +129,7 @@ public: _context->makeCurrent(); while (!_shutdown) { if (_pendingMainThreadOperation) { - PROFILE_RANGE("MainThreadOp") + PROFILE_RANGE(displayPlugins, "MainThreadOp") { Lock lock(_mutex); _context->doneCurrent(); @@ -203,7 +203,7 @@ public: // Execute the frame and present it to the display device. _context->makeCurrent(); { - PROFILE_RANGE("PluginPresent") + PROFILE_RANGE(displayPlugins, "PluginPresent") currentPlugin->present(); CHECK_GL_ERROR(); } @@ -560,22 +560,22 @@ void OpenGLDisplayPlugin::compositeLayers() { updateCompositeFramebuffer(); { - PROFILE_RANGE_EX("compositeScene", 0xff0077ff, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "compositeScene", 0xff0077ff, (uint64_t)presentCount()) compositeScene(); } { - PROFILE_RANGE_EX("compositeOverlay", 0xff0077ff, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "compositeOverlay", 0xff0077ff, (uint64_t)presentCount()) compositeOverlay(); } auto compositorHelper = DependencyManager::get(); if (compositorHelper->getReticleVisible()) { - PROFILE_RANGE_EX("compositePointer", 0xff0077ff, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) compositePointer(); } { - PROFILE_RANGE_EX("compositeExtra", 0xff0077ff, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) compositeExtra(); } } @@ -595,12 +595,12 @@ void OpenGLDisplayPlugin::internalPresent() { } void OpenGLDisplayPlugin::present() { - PROFILE_RANGE_EX(__FUNCTION__, 0xffffff00, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, __FUNCTION__, 0xffffff00, (uint64_t)presentCount()) updateFrameData(); incrementPresentCount(); { - PROFILE_RANGE_EX("recycle", 0xff00ff00, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "recycle", 0xff00ff00, (uint64_t)presentCount()) _gpuContext->recycle(); } @@ -614,19 +614,19 @@ void OpenGLDisplayPlugin::present() { _lastFrame = _currentFrame.get(); }); // Execute the frame rendering commands - PROFILE_RANGE_EX("execute", 0xff00ff00, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "execute", 0xff00ff00, (uint64_t)presentCount()) _gpuContext->executeFrame(_currentFrame); } // Write all layers to a local framebuffer { - PROFILE_RANGE_EX("composite", 0xff00ffff, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "composite", 0xff00ffff, (uint64_t)presentCount()) compositeLayers(); } // Take the composite framebuffer and send it to the output device { - PROFILE_RANGE_EX("internalPresent", 0xff00ffff, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, "internalPresent", 0xff00ffff, (uint64_t)presentCount()) internalPresent(); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 9964c46c8d..1bfe73b687 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -206,7 +206,7 @@ float HmdDisplayPlugin::getLeftCenterPixel() const { } void HmdDisplayPlugin::internalPresent() { - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) + PROFILE_RANGE_EX(displayPlugins, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) // Composite together the scene, overlay and mouse cursor hmdPresent(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index dc5b6cd8d3..593e3e2aca 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -211,7 +211,7 @@ namespace render { template <> void payloadRender(const RenderableModelEntityItemMeta::Pointer& payload, RenderArgs* args) { if (args) { if (payload && payload->entity) { - PROFILE_RANGE("MetaModelRender"); + PROFILE_RANGE(renderlogging, "MetaModelRender"); payload->entity->render(args); } } diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXReader_Node.cpp index 44bb4ac48b..034070c9d7 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXReader_Node.cpp @@ -321,7 +321,7 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) { } FBXNode FBXReader::parseFBX(QIODevice* device) { - PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, device); + PROFILE_RANGE_EX(modelformat, __FUNCTION__, 0xff0000ff, device); // verify the prolog const QByteArray BINARY_PROLOG = "Kaydara FBX Binary "; if (device->peek(BINARY_PROLOG.size()) != BINARY_PROLOG) { diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 03e24c9046..8ea2c5fd38 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -420,7 +420,7 @@ done: FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, const QUrl& url) { - PROFILE_RANGE_EX(__FUNCTION__, 0xffff0000, nullptr); + PROFILE_RANGE_EX(modelformat, __FUNCTION__, 0xffff0000, nullptr); QBuffer buffer { &model }; buffer.open(QIODevice::ReadOnly); diff --git a/libraries/gl/src/gl/GLLogging.cpp b/libraries/gl/src/gl/GLLogging.cpp index 18d2023acd..26ef274616 100644 --- a/libraries/gl/src/gl/GLLogging.cpp +++ b/libraries/gl/src/gl/GLLogging.cpp @@ -11,4 +11,4 @@ #include "GLLogging.h" -Q_LOGGING_CATEGORY(glLogging, "hifi.glLogging") +Q_LOGGING_CATEGORY(glLogging, "hifi.gl") diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index cde779d101..e1e7d46570 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -284,7 +284,7 @@ void OffscreenQmlSurface::render() { GLuint texture = offscreenTextures.getNextTexture(_size); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); - PROFILE_RANGE("qml_render->rendercontrol") + PROFILE_RANGE(glLogging, "qml_render->rendercontrol") _renderControl->render(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, texture); @@ -622,7 +622,7 @@ void OffscreenQmlSurface::updateQuick() { } if (_render) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(glLogging, __FUNCTION__); render(); _render = false; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index dc49c0c4fd..ea9d421cba 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -30,6 +30,7 @@ #include "GLTexture.h" #include "GLShader.h" + using namespace gpu; using namespace gpu::gl; @@ -199,7 +200,7 @@ void GLBackend::renderPassTransfer(const Batch& batch) { _inRenderTransferPass = true; { // Sync all the buffers - PROFILE_RANGE("syncGPUBuffer"); + PROFILE_RANGE(gpugllogging, "syncGPUBuffer"); for (auto& cached : batch._buffers._items) { if (cached._data) { @@ -209,7 +210,7 @@ void GLBackend::renderPassTransfer(const Batch& batch) { } { // Sync all the buffers - PROFILE_RANGE("syncCPUTransform"); + PROFILE_RANGE(gpugllogging, "syncCPUTransform"); _transform._cameras.clear(); _transform._cameraOffsets.clear(); @@ -241,7 +242,7 @@ void GLBackend::renderPassTransfer(const Batch& batch) { } { // Sync the transform buffers - PROFILE_RANGE("syncGPUTransform"); + PROFILE_RANGE(gpugllogging, "syncGPUTransform"); transferTransformState(batch); } @@ -303,7 +304,7 @@ void GLBackend::render(const Batch& batch) { } { - PROFILE_RANGE("Transfer"); + PROFILE_RANGE(gpugllogging, "Transfer"); renderPassTransfer(batch); } @@ -313,7 +314,7 @@ void GLBackend::render(const Batch& batch) { } #endif { - PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render"); + PROFILE_RANGE(gpugllogging, _stereo._enable ? "Render Stereo" : "Render"); renderPassDraw(batch); } #ifdef GPU_STEREO_DRAWCALL_INSTANCED diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp index c7f4694f3c..f0e87184c1 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp @@ -10,6 +10,7 @@ // #include "GLBackend.h" #include "GLQuery.h" +#include "GLShared.h" using namespace gpu; using namespace gpu::gl; @@ -27,7 +28,7 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) { auto query = batch._queries.get(batch._params[paramOffset]._uint); GLQuery* glquery = syncGPUObject(*query); if (glquery) { - PROFILE_RANGE_BEGIN(glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00); + PROFILE_RANGE_BEGIN(gpugllogging, glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00); ++_queryStage._rangeQueryDepth; glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime); @@ -61,7 +62,7 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) { glGetInteger64v(GL_TIMESTAMP, &now); glquery->_batchElapsedTime = now - glquery->_batchElapsedTime; - PROFILE_RANGE_END(glquery->_profileRangeId); + PROFILE_RANGE_END(gpugllogging, glquery->_profileRangeId); (void)CHECK_GL_ERROR(); } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 5594be36b6..d7f1cc7fab 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -12,7 +12,6 @@ #include #include -#include #include "../gl/GLTexelFormat.h" @@ -123,7 +122,7 @@ void GL41Texture::transferMip(uint16_t mipLevel, uint8_t face) const { } void GL41Texture::startTransfer() { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(gpugllogging, __FUNCTION__); Parent::startTransfer(); glBindTexture(_target, _id); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 45aff54b8f..6098d816fb 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -17,6 +17,7 @@ #include #include +#include #include @@ -757,6 +758,9 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector< if(width != cubeTexture.getHeight()) { return false; } + + PROFILE_RANGE(gpulogging, "sphericalHarmonicsFromTexture"); + const uint sqOrder = order*order; // allocate memory for calculations @@ -788,6 +792,7 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector< // for each face of cube texture for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) { + PROFILE_RANGE(gpulogging, "ProcessFace"); auto numComponents = cubeTexture.accessStoredMipFace(0,face)->getFormat().getScalarCount(); auto data = cubeTexture.accessStoredMipFace(0,face)->readData(); @@ -995,4 +1000,4 @@ Texture::ExternalUpdates Texture::getUpdates() const { _externalUpdates.swap(result); } return result; -} \ No newline at end of file +} diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 6eacbab46a..427f307dc3 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -21,6 +21,8 @@ #include #include "ModelNetworkingLogging.h" +#include +#include class GeometryReader; @@ -39,6 +41,8 @@ class GeometryMappingResource : public GeometryResource { public: GeometryMappingResource(const QUrl& url) : GeometryResource(url) {}; + QString getType() const override { return "GeometryMapping"; } + virtual void downloadFinished(const QByteArray& data) override; private slots: @@ -50,6 +54,9 @@ private: }; void GeometryMappingResource::downloadFinished(const QByteArray& data) { + PROFILE_ASYNC_BEGIN(modelnetworking, "GeometryMappingResource::downloadFinished", _url.toString(), + { { "url", _url.toString() } }); + auto mapping = FSTReader::readMapping(data); QString filename = mapping.value("filename").toString(); @@ -113,6 +120,7 @@ void GeometryMappingResource::onGeometryMappingLoaded(bool success) { disconnect(_connection); // FIXME Should not have to do this } + PROFILE_ASYNC_END(modelnetworking, "GeometryMappingResource::downloadFinished", _url.toString()); finishedLoading(success); } @@ -120,8 +128,10 @@ class GeometryReader : public QRunnable { public: GeometryReader(QWeakPointer& resource, const QUrl& url, const QVariantHash& mapping, const QByteArray& data) : - _resource(resource), _url(url), _mapping(mapping), _data(data) {} - virtual ~GeometryReader() = default; + _resource(resource), _url(url), _mapping(mapping), _data(data) { + + DependencyManager::get()->incrementStat("PendingProcessing"); + } virtual void run() override; @@ -133,6 +143,9 @@ private: }; void GeometryReader::run() { + DependencyManager::get()->decrementStat("PendingProcessing"); + CounterStat counter("Processing"); + PROFILE_RANGE_EX(modelnetworking, "GeometryReader::run", 0xFF00FF00, 0, { { "url", _url.toString() } }); auto originalPriority = QThread::currentThread()->priority(); if (originalPriority == QThread::InheritPriority) { originalPriority = QThread::NormalPriority; @@ -197,6 +210,8 @@ public: GeometryDefinitionResource(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) : GeometryResource(url, resolveTextureBaseUrl(url, textureBaseUrl)), _mapping(mapping) {} + QString getType() const override { return "GeometryDefinition"; } + virtual void downloadFinished(const QByteArray& data) override; protected: diff --git a/libraries/model-networking/src/model-networking/ShaderCache.h b/libraries/model-networking/src/model-networking/ShaderCache.h index 4af12fdbfa..bd78e6e7e3 100644 --- a/libraries/model-networking/src/model-networking/ShaderCache.h +++ b/libraries/model-networking/src/model-networking/ShaderCache.h @@ -14,6 +14,9 @@ class NetworkShader : public Resource { public: NetworkShader(const QUrl& url); + + QString getType() const override { return "NetworkShader"; } + virtual void downloadFinished(const QByteArray& data) override; QString _source; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 215263661d..20c1be77c5 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -33,6 +33,8 @@ #include #include "ModelNetworkingLogging.h" +#include +#include TextureCache::TextureCache() { setUnusedResourceCacheSize(0); @@ -331,6 +333,7 @@ ImageReader::ImageReader(const QWeakPointer& resource, const QByteArra outFile.close(); } #endif + DependencyManager::get()->incrementStat("PendingProcessing"); } void ImageReader::listSupportedImageFormats() { @@ -342,7 +345,11 @@ void ImageReader::listSupportedImageFormats() { } void ImageReader::run() { - PROFILE_RANGE_EX(__FUNCTION__, 0xffff0000, nullptr); + DependencyManager::get()->decrementStat("PendingProcessing"); + + CounterStat counter("Processing"); + + PROFILE_RANGE_EX(modelnetworking, __FUNCTION__, 0xffff0000, 0, { { "url", _url.toString() } }); auto originalPriority = QThread::currentThread()->priority(); if (originalPriority == QThread::InheritPriority) { originalPriority = QThread::NormalPriority; @@ -356,7 +363,6 @@ void ImageReader::run() { qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref"; return; } - listSupportedImageFormats(); // Help the QImage loader by extracting the image file format from the url filename ext. @@ -378,7 +384,6 @@ void ImageReader::run() { } return; } - gpu::TexturePointer texture = nullptr; { // Double-check the resource still exists between long operations. @@ -390,7 +395,7 @@ void ImageReader::run() { auto url = _url.toString().toStdString(); - PROFILE_RANGE_EX(__FUNCTION__"::textureLoader", 0xffffff00, nullptr); + PROFILE_RANGE_EX(modelnetworking, __FUNCTION__, 0xffffff00, 0); texture.reset(resource.dynamicCast()->getTextureLoader()(image, url)); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index e1fa119e0d..8ccfe5364c 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -63,10 +63,13 @@ public: NetworkTexture(const QUrl& url, Type type, const QByteArray& content); NetworkTexture(const QUrl& url, const TextureLoaderFunc& textureLoader, const QByteArray& content); + QString getType() const override { return "NetworkTexture"; } + int getOriginalWidth() const { return _originalWidth; } int getOriginalHeight() const { return _originalHeight; } int getWidth() const { return _width; } int getHeight() const { return _height; } + Type getTextureType() const { return _type; } TextureLoaderFunc getTextureLoader() const; diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 3e346a564e..83914ae950 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include "ModelLogging.h" using namespace model; @@ -744,6 +746,8 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) { + PROFILE_RANGE(modelLog, "processCubeTextureColorFromImage"); + gpu::Texture* theTexture = nullptr; if ((srcImage.width() > 0) && (srcImage.height() > 0)) { QImage image = processSourceImage(srcImage, true); @@ -801,11 +805,13 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm } if (generateMips) { + PROFILE_RANGE(modelLog, "generateMips"); theTexture->autoGenerateMips(-1); } // Generate irradiance while we are at it if (generateIrradiance) { + PROFILE_RANGE(modelLog, "generateIrradiance"); theTexture->generateIrradiance(); } } diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 240c722872..8583b59c89 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -105,7 +105,7 @@ QUrl AddressManager::currentFacingShareableAddress() const { void AddressManager::loadSettings(const QString& lookupString) { if (lookupString.isEmpty()) { - handleUrl(currentAddressHandle.get().toString(), LookupTrigger::StartupFromSettings); + handleUrl(currentAddressHandle.get(), LookupTrigger::StartupFromSettings); } else { handleUrl(lookupString, LookupTrigger::StartupFromSettings); } diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 0563141511..37b1af0996 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -604,7 +604,7 @@ bool AssetClient::cancelGetAssetRequest(MessageID id) { for (auto& kv : _pendingRequests) { auto& messageCallbackMap = kv.second; auto requestIt = messageCallbackMap.find(id); - if (requestIt != kv.second.end()) { + if (requestIt != messageCallbackMap.end()) { auto& message = requestIt->second.message; if (message) { diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 4449531177..13caf87b8d 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -19,8 +19,12 @@ #include "NetworkLogging.h" #include "NodeList.h" #include "ResourceCache.h" +#include + +static int requestID = 0; AssetRequest::AssetRequest(const QString& hash) : + _requestID(++requestID), _hash(hash) { } diff --git a/libraries/networking/src/AssetRequest.h b/libraries/networking/src/AssetRequest.h index 0a6810b052..e5d9d119d7 100644 --- a/libraries/networking/src/AssetRequest.h +++ b/libraries/networking/src/AssetRequest.h @@ -56,6 +56,7 @@ signals: void progress(qint64 totalReceived, qint64 total); private: + int _requestID; State _state = NotStarted; Error _error = NoError; AssetInfo _info; diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index 11ced60ec4..9a89465e02 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -17,6 +17,8 @@ #include "AssetUtils.h" #include "MappingRequest.h" #include "NetworkLogging.h" +#include +#include static const int DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS = 5; @@ -27,12 +29,14 @@ AssetResourceRequest::AssetResourceRequest(const QUrl& url) : } AssetResourceRequest::~AssetResourceRequest() { - if (_assetMappingRequest) { - _assetMappingRequest->deleteLater(); - } - - if (_assetRequest) { - _assetRequest->deleteLater(); + if (_assetRequest || _assetMappingRequest) { + if (_assetMappingRequest) { + _assetMappingRequest->deleteLater(); + } + + if (_assetRequest) { + _assetRequest->deleteLater(); + } } } @@ -108,7 +112,6 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { } void AssetResourceRequest::requestHash(const AssetHash& hash) { - // Make request to atp auto assetClient = DependencyManager::get(); _assetRequest = assetClient->createRequest(hash); @@ -118,7 +121,7 @@ void AssetResourceRequest::requestHash(const AssetHash& hash) { Q_ASSERT(_state == InProgress); Q_ASSERT(req == _assetRequest); Q_ASSERT(req->getState() == AssetRequest::Finished); - + switch (req->getError()) { case AssetRequest::Error::NoError: _data = req->getData(); diff --git a/libraries/networking/src/Assignment.cpp b/libraries/networking/src/Assignment.cpp index 0114bcb708..028cdb95db 100644 --- a/libraries/networking/src/Assignment.cpp +++ b/libraries/networking/src/Assignment.cpp @@ -19,6 +19,7 @@ #include #include "Assignment.h" #include +#include Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) { switch (nodeType) { @@ -51,7 +52,7 @@ Assignment::Assignment() : } -Assignment::Assignment(Assignment::Command command, Assignment::Type type, const QString& pool, Assignment::Location location) : +Assignment::Assignment(Assignment::Command command, Assignment::Type type, const QString& pool, Assignment::Location location, QString dataDirectory) : _uuid(), _command(command), _type(type), @@ -60,7 +61,8 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, const _payload(), _isStatic(false), _walletUUID(), - _nodeVersion() + _nodeVersion(), + _dataDirectory(dataDirectory) { if (_command == Assignment::CreateCommand) { // this is a newly created assignment, generate a random UUID diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 97caedcfb3..906a89774c 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -55,7 +55,8 @@ public: Assignment(Assignment::Command command, Assignment::Type type, const QString& pool = emptyPool, - Assignment::Location location = Assignment::LocalLocation); + Assignment::Location location = Assignment::LocalLocation, + QString dataDirectory = QString()); Assignment(const Assignment& otherAssignment); Assignment& operator=(const Assignment &rhsAssignment); @@ -103,6 +104,7 @@ protected: bool _isStatic; /// defines if this assignment needs to be re-queued in the domain-server if it stops being fulfilled QUuid _walletUUID; /// the UUID for the wallet that should be paid for this assignment QString _nodeVersion; + QString _dataDirectory; }; uint qHash(const Assignment::Type& key, uint seed); diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index d6981f420d..217d3096f5 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -109,6 +109,10 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { } } +QString HifiSockAddr::toString() const { + return _address.toString() + ":" + QString::number(_port); +} + QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr) { debug.nospace() << sockAddr._address.toString().toLocal8Bit().constData() << ":" << sockAddr._port; return debug.space(); diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/HifiSockAddr.h index c4ff8cb246..af939de736 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/HifiSockAddr.h @@ -53,6 +53,8 @@ public: static int packSockAddr(unsigned char* packetData, const HifiSockAddr& packSockAddr); static int unpackSockAddr(const unsigned char* packetData, HifiSockAddr& unpackDestSockAddr); + QString toString() const; + friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr); friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr); friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index fa404b39d8..a5cf1d9527 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -37,6 +37,7 @@ #include "HifiSockAddr.h" #include "NetworkLogging.h" #include "udt/Packet.h" +#include static Setting::Handle LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0); @@ -1116,7 +1117,6 @@ void LimitedNodeList::flagTimeForConnectionStep(ConnectionStep connectionStep) { } void LimitedNodeList::flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp) { - if (connectionStep == ConnectionStep::LookupAddress) { QWriteLocker writeLock(&_connectionTimeLock); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index c635744512..0d54c843f6 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -103,8 +103,7 @@ public: ReceiveFirstAudioPacket }; - Q_ENUMS(ConnectionStep); - + Q_ENUM(ConnectionStep); const QUuid& getSessionUUID() const { return _sessionUUID; } void setSessionUUID(const QUuid& sessionUUID); diff --git a/libraries/networking/src/NetworkLogging.cpp b/libraries/networking/src/NetworkLogging.cpp index 01abd6ae19..834398694d 100644 --- a/libraries/networking/src/NetworkLogging.cpp +++ b/libraries/networking/src/NetworkLogging.cpp @@ -12,5 +12,6 @@ #include "NetworkLogging.h" Q_LOGGING_CATEGORY(networking, "hifi.networking") +Q_LOGGING_CATEGORY(resourceLog, "hifi.networking.resource") Q_LOGGING_CATEGORY(asset_client, "hifi.networking.asset_client") Q_LOGGING_CATEGORY(messages_client, "hifi.networking.messages_client") diff --git a/libraries/networking/src/NetworkLogging.h b/libraries/networking/src/NetworkLogging.h index 37ebc1933d..30116ff405 100644 --- a/libraries/networking/src/NetworkLogging.h +++ b/libraries/networking/src/NetworkLogging.h @@ -14,6 +14,7 @@ #include +Q_DECLARE_LOGGING_CATEGORY(resourceLog) Q_DECLARE_LOGGING_CATEGORY(networking) Q_DECLARE_LOGGING_CATEGORY(asset_client) Q_DECLARE_LOGGING_CATEGORY(messages_client) diff --git a/libraries/networking/src/NetworkPeer.cpp b/libraries/networking/src/NetworkPeer.cpp index 2ebee1b71f..abbd262f3d 100644 --- a/libraries/networking/src/NetworkPeer.cpp +++ b/libraries/networking/src/NetworkPeer.cpp @@ -20,6 +20,8 @@ #include "BandwidthRecorder.h" #include "NetworkLogging.h" +#include +#include "NodeType.h" NetworkPeer::NetworkPeer(QObject* parent) : @@ -156,6 +158,7 @@ void NetworkPeer::activateMatchingOrNewSymmetricSocket(const HifiSockAddr& match } void NetworkPeer::softReset() { + qDebug() << "Soft reset "; // a soft reset should clear the sockets and reset the number of connection attempts _localSocket.clear(); _publicSocket.clear(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 4686f49f16..a78ca073e3 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -32,6 +32,7 @@ #include "NetworkLogging.h" #include "udt/PacketHeaders.h" #include "SharedUtil.h" +#include const int KEEPALIVE_PING_INTERVAL_MS = 1000; diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 5fb686ca6f..db4bc35cd4 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -23,6 +23,8 @@ #include "NodeList.h" #include "ResourceCache.h" +#include +#include #define clamp(x, min, max) (((x) < (min)) ? (min) :\ (((x) > (max)) ? (max) :\ @@ -495,11 +497,12 @@ const int DEFAULT_REQUEST_LIMIT = 10; int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT; int ResourceCache::_requestsActive = 0; +static int requestID = 0; + Resource::Resource(const QUrl& url) : _url(url), _activeUrl(url), - _request(nullptr) { - + _requestID(++requestID) { init(); } @@ -647,20 +650,24 @@ void Resource::reinsert() { void Resource::makeRequest() { if (_request) { + PROFILE_ASYNC_END(resourceLog, "Resource:" + getType(), QString::number(_requestID)); _request->disconnect(); _request->deleteLater(); } + PROFILE_ASYNC_BEGIN(resourceLog, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } }); + _request = ResourceManager::createResourceRequest(this, _activeUrl); if (!_request) { qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); ResourceCache::requestCompleted(_self); finishedLoading(false); + PROFILE_ASYNC_END(resourceLog, "Resource:" + getType(), QString::number(_requestID)); return; } - qCDebug(networking).noquote() << "Starting request for:" << _url.toDisplayString(); + qCDebug(resourceLog).noquote() << "Starting request for:" << _url.toDisplayString(); emit loading(); connect(_request, &ResourceRequest::progress, this, &Resource::onProgress); @@ -681,6 +688,11 @@ void Resource::handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTota void Resource::handleReplyFinished() { Q_ASSERT_X(_request, "Resource::handleReplyFinished", "Request should not be null while in handleReplyFinished"); + PROFILE_ASYNC_END(resourceLog, "Resource:" + getType(), QString::number(_requestID), { + { "from_cache", _request->loadedFromCache() }, + { "size_mb", _bytesTotal / 1000000.0 } + }); + setSize(_bytesTotal); if (!_request || _request != sender()) { diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 48b21a1e98..4231785616 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -342,6 +342,8 @@ public: Resource(const QUrl& url); ~Resource(); + + virtual QString getType() const { return "Resource"; } /// Returns the key last used to identify this resource in the unused map. int getLRUKey() const { return _lruKey; } @@ -461,6 +463,7 @@ private: bool isInScript() const { return _isInScript; } void setInScript(bool isInScript) { _isInScript = isInScript; } + int _requestID; ResourceRequest* _request{ nullptr }; int _lruKey{ 0 }; QTimer* _replyTimer{ nullptr }; diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index a190fe3ddc..f42049f107 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -23,6 +23,7 @@ #include "Packet.h" #include "PacketList.h" #include "Socket.h" +#include using namespace udt; using namespace std::chrono; diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index f94550426e..c134081dde 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -58,7 +58,7 @@ public: using ControlPacketPointer = std::unique_ptr; Connection(Socket* parentSocket, HifiSockAddr destination, std::unique_ptr congestionControl); - ~Connection(); + virtual ~Connection(); void sendReliablePacket(std::unique_ptr packet); void sendReliablePacketList(std::unique_ptr packet); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index f42e2b77fb..8e32befe14 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -30,6 +30,8 @@ #include "PacketList.h" #include "../UserActivityLogger.h" #include "Socket.h" +#include +#include using namespace udt; using namespace std::chrono; @@ -84,6 +86,7 @@ SendQueue::SendQueue(Socket* socket, HifiSockAddr dest) : _socket(socket), _destination(dest) { + PROFILE_ASYNC_BEGIN(networking, "SendQueue", _destination.toString()); // setup psuedo-random number generation for all instances of SendQueue static std::random_device rd; @@ -102,6 +105,10 @@ SendQueue::SendQueue(Socket* socket, HifiSockAddr dest) : _lastReceiverResponse = QDateTime::currentMSecsSinceEpoch(); } +SendQueue::~SendQueue() { + PROFILE_ASYNC_END(networking, "SendQueue", _destination.toString()); +} + void SendQueue::queuePacket(std::unique_ptr packet) { _packets.queuePacket(std::move(packet)); @@ -220,6 +227,7 @@ void SendQueue::sendHandshake() { if (!_hasReceivedHandshakeACK) { // we haven't received a handshake ACK from the client, send another now auto handshakePacket = ControlPacket::create(ControlPacket::Handshake, sizeof(SequenceNumber)); + PROFILE_ASYNC_BEGIN(networking, "SendQueue:Handshake", _destination.toString()); handshakePacket->writePrimitive(_initialSequenceNumber); _socket->writeBasePacket(*handshakePacket, _destination); @@ -236,6 +244,7 @@ void SendQueue::handshakeACK(SequenceNumber initialSequenceNumber) { std::lock_guard locker { _handshakeMutex }; _hasReceivedHandshakeACK = true; } + PROFILE_ASYNC_END(networking, "SendQueue:Handshake", _destination.toString()); // Notify on the handshake ACK condition _handshakeACKCondition.notify_one(); diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 6e17c5b9c6..484afcb88e 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -51,6 +51,8 @@ public: }; static std::unique_ptr create(Socket* socket, HifiSockAddr destination); + + virtual ~SendQueue(); void queuePacket(std::unique_ptr packet); void queuePacketList(std::unique_ptr packetList); diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index d2583dce72..ae75e0fade 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -26,6 +26,7 @@ #include "../NLPacket.h" #include "../NLPacketList.h" #include "PacketList.h" +#include using namespace udt; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 48f6e08303..4eb59d0494 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -16,6 +16,8 @@ #include +#include + #include #include #include @@ -28,6 +30,7 @@ #include "OctreeLogging.h" #include "OctreeUtils.h" #include "SharedUtil.h" +#include AtomicUIntStat OctreeElement::_octreeMemoryUsage { 0 }; AtomicUIntStat OctreeElement::_octcodeMemoryUsage { 0 }; @@ -389,6 +392,7 @@ OctreeElementPointer OctreeElement::addChildAtIndex(int childIndex) { _isDirty = true; markWithChangedTime(); + PROFILE_INSTANT(octree, "EntityAdd", "g"); } return childAt; } diff --git a/libraries/plugins/src/plugins/Forward.h b/libraries/plugins/src/plugins/Forward.h index 723c4f321e..b95bf4c2e6 100644 --- a/libraries/plugins/src/plugins/Forward.h +++ b/libraries/plugins/src/plugins/Forward.h @@ -19,6 +19,7 @@ enum class PluginType { class DisplayPlugin; class InputPlugin; class CodecPlugin; +class SteamClientPlugin; class Plugin; class PluginContainer; class PluginManager; @@ -29,4 +30,4 @@ using InputPluginPointer = std::shared_ptr; using InputPluginList = std::vector; using CodecPluginPointer = std::shared_ptr; using CodecPluginList = std::vector; - +using SteamClientPluginPointer = std::shared_ptr; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 21e652dc40..75b0f1e3bc 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -147,6 +147,22 @@ const CodecPluginList& PluginManager::getCodecPlugins() { return codecPlugins; } +const SteamClientPluginPointer PluginManager::getSteamClientPlugin() { + static SteamClientPluginPointer steamClientPlugin; + static std::once_flag once; + std::call_once(once, [&] { + // Now grab the dynamic plugins + for (auto loader : getLoadedPlugins()) { + SteamClientProvider* steamClientProvider = qobject_cast(loader->instance()); + if (steamClientProvider) { + steamClientPlugin = steamClientProvider->getSteamClientPlugin(); + break; + } + } + }); + return steamClientPlugin; +} + #ifndef Q_OS_ANDROID // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class diff --git a/libraries/plugins/src/plugins/PluginManager.h b/libraries/plugins/src/plugins/PluginManager.h index 83aad7abcd..687e5c9e9b 100644 --- a/libraries/plugins/src/plugins/PluginManager.h +++ b/libraries/plugins/src/plugins/PluginManager.h @@ -19,6 +19,7 @@ public: const DisplayPluginList& getDisplayPlugins(); const InputPluginList& getInputPlugins(); const CodecPluginList& getCodecPlugins(); + const SteamClientPluginPointer getSteamClientPlugin(); DisplayPluginList getPreferredDisplayPlugins(); void setPreferredDisplayPlugins(const QStringList& displays); diff --git a/libraries/plugins/src/plugins/RuntimePlugin.h b/libraries/plugins/src/plugins/RuntimePlugin.h index bb6f0251c2..9a7d6e0638 100644 --- a/libraries/plugins/src/plugins/RuntimePlugin.h +++ b/libraries/plugins/src/plugins/RuntimePlugin.h @@ -45,3 +45,11 @@ public: #define CodecProvider_iid "com.highfidelity.plugins.codec" Q_DECLARE_INTERFACE(CodecProvider, CodecProvider_iid) +class SteamClientProvider { +public: + virtual ~SteamClientProvider() {} + virtual SteamClientPluginPointer getSteamClientPlugin() = 0; +}; + +#define SteamClientProvider_iid "com.highfidelity.plugins.steamclient" +Q_DECLARE_INTERFACE(SteamClientProvider, SteamClientProvider_iid) diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h new file mode 100644 index 0000000000..f87ebd2e66 --- /dev/null +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -0,0 +1,59 @@ +// +// SteamClientPlugin.h +// libraries/plugins/src/plugins +// +// Created by Clement Brisset on 12/14/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#ifndef hifi_SteamClientPlugin_h +#define hifi_SteamClientPlugin_h + +#include + +#include +#include + +using Ticket = QByteArray; +using TicketRequestCallback = std::function; + +class SteamClientPlugin { +public: + virtual ~SteamClientPlugin() {}; + + virtual bool init() = 0; + virtual void shutdown() = 0; + + virtual bool isRunning() = 0; + + virtual void runCallbacks() = 0; + + virtual void requestTicket(TicketRequestCallback callback) = 0; + virtual void updateLocation(QString status, QUrl locationUrl) = 0; + virtual void openInviteOverlay() = 0; + virtual void joinLobby(QString lobbyId) = 0; + + virtual int getSteamVRBuildID() = 0; +}; + +class SteamScriptingInterface : public QObject { + Q_OBJECT + + Q_PROPERTY(bool isRunning READ isRunning) + +public: + SteamScriptingInterface(QObject* parent, SteamClientPlugin* plugin) : QObject(parent) {} + + public slots: + bool isRunning() const { return _plugin->isRunning(); } + void openInviteOverlay() const { _plugin->openInviteOverlay(); } + +private: + SteamClientPlugin* _plugin; +}; + +#endif /* hifi_SteamClientPlugin_h */ diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 872aac974e..908fccaaf6 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -793,7 +793,7 @@ void RenderDeferred::configure(const Config& config) { } void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& inputs) { - PROFILE_RANGE("DeferredLighting"); + PROFILE_RANGE(renderlogging, "DeferredLighting"); auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index ed0ed8d04d..50499cf31a 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -58,7 +58,6 @@ float frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) return (-eposZ - rangeNear) / (rangeFar - rangeNear); } - vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) { vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0], epos.y * projection[1][1] + epos.z * projection[2][1], @@ -126,15 +125,11 @@ int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { } ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { - if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { - return ivec3(-2); - } - - if (eyePos.z > -frustumGrid.rangeNear) { - return ivec3(0,0,-1); - } - - vec3 volumePos = frustumGrid_eyeToVolume(eyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); + + // make sure the frontEyePos is always in the front to eval the grid pos correctly + vec3 frontEyePos = eyePos; + frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z); + vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); @@ -143,10 +138,20 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { gridPos.z = frustumGrid.dims.z; } + ivec3 igridPos = ivec3(floor(gridPos)); - return ivec3(floor(gridPos)); + if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { + return ivec3(igridPos.x, igridPos.y, - 2); + } + + if (eyePos.z > -frustumGrid.rangeNear) { + return ivec3(igridPos.x, igridPos.y, -1); + } + + return igridPos; } + int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { return (eyeDir.x > 0 ? frustumGrid.dims.x : -1); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 8dc95da65b..b9ba309fd5 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -279,6 +279,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan // FInd the light origin cluster auto centerCluster = grid.frustumGrid_eyeToClusterPos(glm::vec3(eyePosRadius)); + int center_z = centerCluster.z; int center_y = centerCluster.y; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6e1f57778b..77a3830599 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -27,6 +27,7 @@ #include "Model.h" #include "RenderUtilsLogging.h" +#include using namespace std; @@ -280,7 +281,7 @@ void Model::reset() { } bool Model::updateGeometry() { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(renderutils, __FUNCTION__); bool needFullUpdate = false; if (!isLoaded()) { @@ -474,7 +475,7 @@ bool Model::convexHullContains(glm::vec3 point) { // entity-scripts to call. I think it would be best to do the picking once-per-frame (in cpu, or gpu if possible) // and then the calls use the most recent such result. void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(renderutils, __FUNCTION__); bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded || (!_calculatedMeshPartBoxesValid && pickAgainstTriangles) ) { @@ -967,7 +968,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe } void Blender::run() { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE_EX(renderutils, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } }); QVector vertices, normals; if (_model) { int offset = 0; @@ -1088,7 +1089,7 @@ void Model::snapToRegistrationPoint() { } void Model::simulate(float deltaTime, bool fullUpdate) { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(renderutils, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp new file mode 100755 index 0000000000..da7fcf5cdd --- /dev/null +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -0,0 +1,163 @@ + +// +// RenderForwardTask.cpp +// render-utils/src/ +// +// Created by Zach Pomerantz on 12/13/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "RenderForwardTask.h" +#include "RenderDeferredTask.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "LightingModel.h" +#include "DebugDeferredBuffer.h" +#include "DeferredFramebuffer.h" +#include "DeferredLightingEffect.h" +#include "SurfaceGeometryPass.h" +#include "FramebufferCache.h" +#include "HitEffect.h" +#include "TextureCache.h" + +#include "AmbientOcclusionEffect.h" +#include "AntialiasingEffect.h" +#include "ToneMappingEffect.h" +#include "SubsurfaceScattering.h" + +#include + +#include "drawOpaqueStencil_frag.h" + + +using namespace render; +extern void initOverlay3DPipelines(render::ShapePlumber& plumber); +extern void initDeferredPipelines(render::ShapePlumber& plumber); + +RenderForwardTask::RenderForwardTask(CullFunctor cullFunctor) { + // Prepare the ShapePipelines + ShapePlumberPointer shapePlumber = std::make_shared(); + initDeferredPipelines(*shapePlumber); + + // CPU jobs: + // Fetch and cull the items from the scene + const auto spatialSelection = addJob("FetchSceneSelection"); + + cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; + auto spatialFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); + const auto culledSpatialSelection = addJob("CullSceneSelection", spatialSelection, cullFunctor, RenderDetails::ITEM, spatialFilter); + + // Overlays are not culled + const auto nonspatialSelection = addJob("FetchOverlaySelection"); + + // Multi filter visible items into different buckets + const int NUM_FILTERS = 3; + const int OPAQUE_SHAPE_BUCKET = 0; + const int TRANSPARENT_SHAPE_BUCKET = 1; + const int LIGHT_BUCKET = 2; + const int BACKGROUND_BUCKET = 2; + MultiFilterItem::ItemFilterArray spatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::light() + } }; + MultiFilterItem::ItemFilterArray nonspatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::background() + } }; + const auto filteredSpatialBuckets = addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters).get::ItemBoundsArray>(); + const auto filteredNonspatialBuckets = addJob>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters).get::ItemBoundsArray>(); + + // Extract / Sort opaques / Transparents / Lights / Overlays + const auto opaques = addJob("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto transparents = addJob("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto lights = filteredSpatialBuckets[LIGHT_BUCKET]; + + const auto overlayOpaques = addJob("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto overlayTransparents = addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; + + const auto framebuffer = addJob("PrepareFramebuffer"); + + // Blit! + addJob("Blit", framebuffer); +} + +void RenderForwardTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + // sanity checks + assert(sceneContext); + if (!sceneContext->_scene) { + return; + } + + + // Is it possible that we render without a viewFrustum ? + if (!(renderContext->args && renderContext->args->hasViewFrustum())) { + return; + } + + auto config = std::static_pointer_cast(renderContext->jobConfig); + + for (auto job : _jobs) { + job.run(sceneContext, renderContext); + } +} + +void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { + auto framebufferCache = DependencyManager::get(); + auto framebufferSize = framebufferCache->getFrameBufferSize(); + glm::uvec2 frameSize(framebufferSize.width(), framebufferSize.height()); + + // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering + if (_framebuffer && _framebuffer->getSize() != frameSize) { + _framebuffer.reset(); + } + + if (!_framebuffer) { + _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); + + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto colorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, defaultSampler)); + _framebuffer->setRenderBuffer(0, colorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format + auto depthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, defaultSampler)); + _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); + } + + auto args = renderContext->args; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + batch.setFramebuffer(_framebuffer); + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | + gpu::Framebuffer::BUFFER_COLOR1 | + gpu::Framebuffer::BUFFER_COLOR2 | + gpu::Framebuffer::BUFFER_COLOR3 | + gpu::Framebuffer::BUFFER_DEPTH | + gpu::Framebuffer::BUFFER_STENCIL, + vec4(vec3(0), 0), 1.0, 0.0, true); + }); + + framebuffer = _framebuffer; +} diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h new file mode 100755 index 0000000000..9c4634a8ee --- /dev/null +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -0,0 +1,42 @@ +// +// RenderForwardTask.h +// render-utils/src/ +// +// Created by Zach Pomerantz on 12/13/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderForwardTask_h +#define hifi_RenderForwardTask_h + +#include +#include +#include "LightingModel.h" + +using RenderForwardTaskConfig = render::GPUTaskConfig; + +class RenderForwardTask : public render::Task { +public: + using Config = RenderForwardTaskConfig; + RenderForwardTask(render::CullFunctor cullFunctor); + + void configure(const Config& config) {} + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + using JobModel = Model; +}; + +class PrepareFramebuffer { +public: + using JobModel = render::Job::ModelO; + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer); + +private: + gpu::FramebufferPointer _framebuffer; +}; + +#endif // hifi_RenderForwardTask_h diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv old mode 100755 new mode 100644 diff --git a/libraries/render/src/render/Logging.cpp b/libraries/render/src/render/Logging.cpp new file mode 100644 index 0000000000..eaa777096c --- /dev/null +++ b/libraries/render/src/render/Logging.cpp @@ -0,0 +1,11 @@ +// +// Created by Bradley Austin Davis on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Logging.h" + +Q_LOGGING_CATEGORY(renderlogging, "hifi.render") diff --git a/libraries/render/src/render/Logging.h b/libraries/render/src/render/Logging.h new file mode 100644 index 0000000000..e9fdd8a3c5 --- /dev/null +++ b/libraries/render/src/render/Logging.h @@ -0,0 +1,16 @@ +// +// Created by Bradley Austin Davis on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_Logging_h +#define hifi_render_Logging_h + +#include + +Q_DECLARE_LOGGING_CATEGORY(renderlogging) + +#endif // hifi_render_Engine_h diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 6bc42ac656..3cb9de7b77 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -11,7 +11,8 @@ #include "Scene.h" #include -#include "gpu/Batch.h" +#include +#include "Logging.h" using namespace render; @@ -77,7 +78,7 @@ void consolidateChangeQueue(PendingChangesQueue& queue, PendingChanges& singleBa } void Scene::processPendingChangesQueue() { - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(renderlogging, __FUNCTION__); _changeQueueMutex.lock(); PendingChanges consolidatedPendingChanges; consolidateChangeQueue(_changeQueue, consolidatedPendingChanges); diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 16315de523..067dc290d4 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -23,6 +23,7 @@ #include "SettingHandle.h" #include "Context.h" +#include "Logging.h" #include "gpu/Batch.h" #include @@ -571,7 +572,7 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { PerformanceTimer perfTimer(_name.c_str()); - PROFILE_RANGE(_name.c_str()); + PROFILE_RANGE(renderlogging, _name.c_str()); auto start = usecTimestampNow(); _concept->run(sceneContext, renderContext); diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index cb6291a8dc..b3092be55a 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -283,43 +283,6 @@ void ScriptEngines::loadScripts() { // loads all saved scripts Settings settings; - - - // START of backward compatibility code - // This following if statement is only meant to update the settings file still using the old setting key. - // If you read that comment and it has been more than a couple months since it was merged, - // then by all means, feel free to remove it. - if (!settings.childGroups().contains(SETTINGS_KEY)) { - qWarning() << "Detected old script settings config, loading from previous location"; - const QString oldKey = "Settings"; - - // Load old scripts array from settings - int size = settings.beginReadArray(oldKey); - for (int i = 0; i < size; ++i) { - settings.setArrayIndex(i); - QString string = settings.value("script").toString(); - if (!string.isEmpty()) { - loadScript(string); - } - } - settings.endArray(); - - // Cleanup old scripts array from settings - settings.beginWriteArray(oldKey); - for (int i = 0; i < size; ++i) { - settings.setArrayIndex(i); - settings.remove(""); - } - settings.endArray(); - settings.beginGroup(oldKey); - settings.remove("size"); - settings.endGroup(); - - return; - } - // END of backward compatibility code - - int size = settings.beginReadArray(SETTINGS_KEY); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index f9b835df5c..1fefda06b3 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -3,6 +3,8 @@ set(TARGET_NAME shared) # TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) setup_hifi_library(Gui Network Script Widgets) +target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes") + if (WIN32) target_link_libraries(${TARGET_NAME} Wbemuuid.lib) endif() diff --git a/libraries/shared/src/Profile.cpp b/libraries/shared/src/Profile.cpp new file mode 100644 index 0000000000..18e273a6bb --- /dev/null +++ b/libraries/shared/src/Profile.cpp @@ -0,0 +1,72 @@ +// +// Created by Ryan Huffman on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Profile.h" + + +#if defined(NSIGHT_FOUND) +#include "nvToolsExt.h" +#define NSIGHT_TRACING +#endif + +Duration::Duration(const QLoggingCategory& category, const QString& name, uint32_t argbColor, uint64_t payload, QVariantMap args) : _name(name), _category(category) { + if (_category.isDebugEnabled()) { + args["nv_payload"] = QVariant::fromValue(payload); + tracing::traceEvent(_category, _name, tracing::DurationBegin, "", args); + +#if defined(NSIGHT_TRACING) + nvtxEventAttributes_t eventAttrib { 0 }; + eventAttrib.version = NVTX_VERSION; + eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; + eventAttrib.colorType = NVTX_COLOR_ARGB; + eventAttrib.color = argbColor; + eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; + eventAttrib.message.ascii = name.toUtf8().data(); + eventAttrib.payload.llValue = payload; + eventAttrib.payloadType = NVTX_PAYLOAD_TYPE_UNSIGNED_INT64; + + nvtxRangePushEx(&eventAttrib); +#endif + } +} + +Duration::~Duration() { + if (_category.isDebugEnabled()) { + tracing::traceEvent(_category, _name, tracing::DurationEnd); +#ifdef NSIGHT_TRACING + nvtxRangePop(); +#endif + } +} + +// FIXME +uint64_t Duration::beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor) { +#ifdef NSIGHT_TRACING + if (category.isDebugEnabled()) { + nvtxEventAttributes_t eventAttrib = { 0 }; + eventAttrib.version = NVTX_VERSION; + eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; + eventAttrib.colorType = NVTX_COLOR_ARGB; + eventAttrib.color = argbColor; + eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; + eventAttrib.message.ascii = name; + return nvtxRangeStartEx(&eventAttrib); + } +#endif + return 0; +} + +// FIXME +void Duration::endRange(const QLoggingCategory& category, uint64_t rangeId) { +#ifdef NSIGHT_TRACING + if (category.isDebugEnabled()) { + nvtxRangeEnd(rangeId); + } +#endif +} + diff --git a/libraries/shared/src/Profile.h b/libraries/shared/src/Profile.h new file mode 100644 index 0000000000..a89b19e7c6 --- /dev/null +++ b/libraries/shared/src/Profile.h @@ -0,0 +1,63 @@ +// +// Created by Ryan Huffman on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#ifndef HIFI_PROFILE_ +#define HIFI_PROFILE_ + +#include "Trace.h" + +class Duration { +public: + Duration(const QLoggingCategory& category, const QString& name, uint32_t argbColor = 0xff0000ff, uint64_t payload = 0, QVariantMap args = QVariantMap()); + ~Duration(); + + static uint64_t beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor); + static void endRange(const QLoggingCategory& category, uint64_t rangeId); + +private: + QString _name; + const QLoggingCategory& _category; +}; + +inline void asyncBegin(const QLoggingCategory& category, const QString& name, const QString& id, const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()) { + if (category.isDebugEnabled()) { + tracing::traceEvent(category, name, tracing::AsyncNestableStart, id, args, extra); + } +} + + +inline void asyncEnd(const QLoggingCategory& category, const QString& name, const QString& id, const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()) { + if (category.isDebugEnabled()) { + tracing::traceEvent(category, name, tracing::AsyncNestableEnd, id, args, extra); + } +} + +inline void instant(const QLoggingCategory& category, const QString& name, const QString& scope = "t", const QVariantMap& args = QVariantMap(), QVariantMap extra = QVariantMap()) { + if (category.isDebugEnabled()) { + extra["s"] = scope; + tracing::traceEvent(category, name, tracing::Instant, "", args, extra); + } +} + +inline void counter(const QLoggingCategory& category, const QString& name, const QVariantMap& args, const QVariantMap& extra = QVariantMap()) { + if (category.isDebugEnabled()) { + tracing::traceEvent(category, name, tracing::Counter, "", args, extra); + } +} + +#define PROFILE_RANGE(category, name) Duration profileRangeThis(category(), name); +#define PROFILE_RANGE_EX(category, name, argbColor, payload, ...) Duration profileRangeThis(category(), name, argbColor, (uint64_t)payload, ##__VA_ARGS__); +#define PROFILE_RANGE_BEGIN(category, rangeId, name, argbColor) rangeId = Duration::beginRange(category(), name, argbColor) +#define PROFILE_RANGE_END(category, rangeId) Duration::endRange(category(), rangeId) +#define PROFILE_ASYNC_BEGIN(category, name, id, ...) asyncBegin(category(), name, id, ##__VA_ARGS__); +#define PROFILE_ASYNC_END(category, name, id, ...) asyncEnd(category(), name, id, ##__VA_ARGS__); +#define PROFILE_COUNTER(category, name, ...) counter(category(), name, ##__VA_ARGS__); +#define PROFILE_INSTANT(category, name, ...) instant(category(), name, ##__VA_ARGS__); + +#endif diff --git a/libraries/shared/src/SettingHandle.cpp b/libraries/shared/src/SettingHandle.cpp index 13f9ea48ce..626d7e7ef5 100644 --- a/libraries/shared/src/SettingHandle.cpp +++ b/libraries/shared/src/SettingHandle.cpp @@ -19,16 +19,12 @@ const QString Settings::firstRun { "firstRun" }; -Settings::Settings() : - _manager(DependencyManager::get()), - _locker(&(_manager->getLock())) +Settings::Settings() : _manager(DependencyManager::get()) { } -Settings::~Settings() { - if (_prefixes.size() != 0) { - qFatal("Unstable Settings Prefixes: You must call endGroup for every beginGroup and endArray for every begin*Array call"); - } +QString Settings::fileName() const { + return _manager->fileName(); } void Settings::remove(const QString& key) { @@ -53,18 +49,15 @@ bool Settings::contains(const QString& key) const { return _manager->contains(key); } -int Settings::beginReadArray(const QString & prefix) { - _prefixes.push(prefix); +int Settings::beginReadArray(const QString& prefix) { return _manager->beginReadArray(prefix); } void Settings::beginWriteArray(const QString& prefix, int size) { - _prefixes.push(prefix); _manager->beginWriteArray(prefix, size); } void Settings::endArray() { - _prefixes.pop(); _manager->endArray(); } @@ -73,19 +66,15 @@ void Settings::setArrayIndex(int i) { } void Settings::beginGroup(const QString& prefix) { - _prefixes.push(prefix); _manager->beginGroup(prefix); } void Settings::endGroup() { - _prefixes.pop(); _manager->endGroup(); } void Settings::setValue(const QString& name, const QVariant& value) { - if (_manager->value(name) != value) { - _manager->setValue(name, value); - } + _manager->setValue(name, value); } QVariant Settings::value(const QString& name, const QVariant& defaultValue) const { diff --git a/libraries/shared/src/SettingHandle.h b/libraries/shared/src/SettingHandle.h index 5133a9cb2a..54694dfd0a 100644 --- a/libraries/shared/src/SettingHandle.h +++ b/libraries/shared/src/SettingHandle.h @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -32,7 +31,8 @@ class Settings { public: static const QString firstRun; Settings(); - ~Settings(); + + QString fileName() const; void remove(const QString& key); QStringList childGroups() const; @@ -61,8 +61,6 @@ public: private: QSharedPointer _manager; - QWriteLocker _locker; - QStack _prefixes; }; namespace Setting { diff --git a/libraries/shared/src/SettingHelpers.cpp b/libraries/shared/src/SettingHelpers.cpp new file mode 100644 index 0000000000..f7d2510458 --- /dev/null +++ b/libraries/shared/src/SettingHelpers.cpp @@ -0,0 +1,283 @@ +// +// SettingHelpers.cpp +// libraries/shared/src +// +// Created by Clement on 9/13/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SettingHelpers.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +QSettings::SettingsMap jsonDocumentToVariantMap(const QJsonDocument& document); +QJsonDocument variantMapToJsonDocument(const QSettings::SettingsMap& map); + +bool readJSONFile(QIODevice& device, QSettings::SettingsMap& map) { + QJsonParseError jsonParseError; + + auto bytesRead = device.readAll(); + auto document = QJsonDocument::fromJson(bytesRead, &jsonParseError); + + if (jsonParseError.error != QJsonParseError::NoError) { + qDebug() << "Error parsing QSettings file:" << jsonParseError.errorString(); + return false; + } + + map = jsonDocumentToVariantMap(document); + + return true; +} + +bool writeJSONFile(QIODevice& device, const QSettings::SettingsMap& map) { + auto document = variantMapToJsonDocument(map); + auto jsonByteArray = document.toJson(QJsonDocument::Indented); + auto bytesWritten = device.write(jsonByteArray); + return bytesWritten == jsonByteArray.size(); +} + +void loadOldINIFile(QSettings& settings) { + QSettings::setDefaultFormat(QSettings::IniFormat); + + QSettings iniSettings; + if (!iniSettings.allKeys().isEmpty()) { + qDebug() << "No data in json settings file, trying to load old ini settings file."; + + for (auto key : iniSettings.allKeys()) { + auto variant = iniSettings.value(key); + + if (variant.type() == QVariant::String) { + auto string = variant.toString(); + if (string == "true") { + variant = true; + } else if (string == "false") { + variant = false; + } else { + bool ok; + double value = string.toDouble(&ok); + if (ok) { + variant = value; + } + } + } + settings.setValue(key, variant); + } + + qDebug() << "Loaded" << settings.allKeys().size() << "keys from ini settings file."; + } + + QSettings::setDefaultFormat(JSON_FORMAT); +} + +QStringList splitArgs(const QString& string, int idx) { + int length = string.length(); + Q_ASSERT(length > 0); + Q_ASSERT(string.at(idx) == QLatin1Char('(')); + Q_ASSERT(string.at(length - 1) == QLatin1Char(')')); + + QStringList result; + QString item; + + for (++idx; idx < length; ++idx) { + QChar c = string.at(idx); + if (c == QLatin1Char(')')) { + Q_ASSERT(idx == length - 1); + result.append(item); + } else if (c == QLatin1Char(' ')) { + result.append(item); + item.clear(); + } else { + item.append(c); + } + } + + return result; +} + +QJsonDocument variantMapToJsonDocument(const QSettings::SettingsMap& map) { + QJsonObject object; + for (auto it = map.cbegin(); it != map.cend(); ++it) { + auto& key = it.key(); + auto& variant = it.value(); + auto variantType = variant.type(); + + // Switch some types so they are readable/modifiable in the json file + if (variantType == QVariant(1.0f).type()) { // float + variantType = QVariant::Double; + } + if (variantType == QVariant((quint16)0).type()) { // uint16 + variantType = QVariant::UInt; + } + if (variantType == QVariant::Url) { // QUrl + variantType = QVariant::String; + } + + switch (variantType) { + case QVariant::Map: + case QVariant::List: + case QVariant::Hash: { + qCritical() << "Unsupported variant type" << variant.typeName(); + Q_ASSERT(false); + break; + } + + case QVariant::Invalid: + object.insert(key, QJsonValue()); + break; + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Int: + case QVariant::UInt: + case QVariant::Bool: + case QVariant::Double: + object.insert(key, QJsonValue::fromVariant(variant)); + break; + + case QVariant::String: { + QString result = variant.toString(); + if (result.startsWith(QLatin1Char('@'))) { + result.prepend(QLatin1Char('@')); + } + object.insert(key, result); + break; + } + + case QVariant::ByteArray: { + QByteArray a = variant.toByteArray(); + QString result = QLatin1String("@ByteArray("); + result += QString::fromLatin1(a.constData(), a.size()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + case QVariant::Rect: { + QRect r = qvariant_cast(variant); + QString result = QLatin1String("@Rect("); + result += QString::number(r.x()); + result += QLatin1Char(' '); + result += QString::number(r.y()); + result += QLatin1Char(' '); + result += QString::number(r.width()); + result += QLatin1Char(' '); + result += QString::number(r.height()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + case QVariant::Size: { + QSize s = qvariant_cast(variant); + QString result = QLatin1String("@Size("); + result += QString::number(s.width()); + result += QLatin1Char(' '); + result += QString::number(s.height()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + case QVariant::Point: { + QPoint p = qvariant_cast(variant); + QString result = QLatin1String("@Point("); + result += QString::number(p.x()); + result += QLatin1Char(' '); + result += QString::number(p.y()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + + default: { + QByteArray array; + { + QDataStream stream(&array, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_4_0); + stream << variant; + } + + QString result = QLatin1String("@Variant("); + result += QString::fromLatin1(array.constData(), array.size()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + } + } + + return QJsonDocument(object); +} + + +QSettings::SettingsMap jsonDocumentToVariantMap(const QJsonDocument& document) { + if (!document.isObject()) { + qWarning() << "Settings file does not contain a JSON object"; + return QSettings::SettingsMap(); + } + auto object = document.object(); + QSettings::SettingsMap map; + + for (auto it = object.begin(); it != object.end(); ++it) { + + QVariant result; + + if (!it->isString()) { + result = it->toVariant(); + } else { + auto string = it->toString(); + + if (string.startsWith(QLatin1String("@@"))) { // Standard string starting with '@' + result = QVariant(string.mid(1)); + + } else if (string.startsWith(QLatin1Char('@'))) { // Custom type to string + + if (string.endsWith(QLatin1Char(')'))) { + + if (string.startsWith(QLatin1String("@ByteArray("))) { + result = QVariant(string.toLatin1().mid(11, string.size() - 12)); + + } else if (string.startsWith(QLatin1String("@Variant("))) { + QByteArray a(string.toLatin1().mid(9)); + QDataStream stream(&a, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_4_0); + stream >> result; + + } else if (string.startsWith(QLatin1String("@Rect("))) { + QStringList args = splitArgs(string, 5); + if (args.size() == 4) { + result = QRect(args[0].toInt(), args[1].toInt(), + args[2].toInt(), args[3].toInt()); + } + + } else if (string.startsWith(QLatin1String("@Size("))) { + QStringList args = splitArgs(string, 5); + if (args.size() == 2) { + result = QSize(args[0].toInt(), args[1].toInt()); + } + + } else if (string.startsWith(QLatin1String("@Point("))) { + QStringList args = splitArgs(string, 6); + if (args.size() == 2) { + result = QPoint(args[0].toInt(), args[1].toInt()); + } + } + } + } else { // Standard string + result = string; + } + } + + map.insert(it.key(), result); + } + + return map; +} diff --git a/libraries/shared/src/SettingHelpers.h b/libraries/shared/src/SettingHelpers.h new file mode 100644 index 0000000000..122e56957c --- /dev/null +++ b/libraries/shared/src/SettingHelpers.h @@ -0,0 +1,25 @@ +// +// SettingHelpers.h +// libraries/shared/src +// +// Created by Clement on 9/13/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SettingHelpers_h +#define hifi_SettingHelpers_h + +#include + +bool readJSONFile(QIODevice& device, QSettings::SettingsMap& map); +bool writeJSONFile(QIODevice& device, const QSettings::SettingsMap& map); + +static const auto JSON_FORMAT = QSettings::registerFormat("json", readJSONFile, writeJSONFile); + +void loadOldINIFile(QSettings& settings); + + +#endif // hifi_SettingHelpers_h diff --git a/libraries/shared/src/SettingInterface.cpp b/libraries/shared/src/SettingInterface.cpp index 9db84055f7..01b9f3884f 100644 --- a/libraries/shared/src/SettingInterface.cpp +++ b/libraries/shared/src/SettingInterface.cpp @@ -17,13 +17,12 @@ #include #include "PathUtils.h" +#include "SettingHelpers.h" #include "SettingManager.h" #include "SharedLogging.h" namespace Setting { static QSharedPointer globalManager; - - const QString Interface::FIRST_RUN { "firstRun" }; // cleans up the settings private instance. Should only be run once at closing down. void cleanupPrivateInstance() { @@ -40,30 +39,27 @@ namespace Setting { settingsManagerThread->quit(); settingsManagerThread->wait(); } + + // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, + void init() { + // Set settings format + QSettings::setDefaultFormat(JSON_FORMAT); + QSettings settings; + qCDebug(shared) << "Settings file:" << settings.fileName(); - // Set up application settings. Should only be run once at startup. - void preInit() { - // read the ApplicationInfo.ini file for Name/Version/Domain information - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); - // set the associated application properties - applicationInfo.beginGroup("INFO"); - QCoreApplication::setApplicationName(applicationInfo.value("name").toString()); - QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); - QCoreApplication::setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); + if (settings.allKeys().isEmpty()) { + loadOldINIFile(settings); + } // Delete Interface.ini.lock file if it exists, otherwise Interface freezes. - QSettings settings; QString settingsLockFilename = settings.fileName() + ".lock"; QFile settingsLockFile(settingsLockFilename); if (settingsLockFile.exists()) { bool deleted = settingsLockFile.remove(); qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename; } - } - - // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, - void init() { + + // Let's set up the settings Private instance on its own thread QThread* thread = new QThread(); Q_CHECK_PTR(thread); diff --git a/libraries/shared/src/SettingInterface.h b/libraries/shared/src/SettingInterface.h index 5e23d42223..082adf3e54 100644 --- a/libraries/shared/src/SettingInterface.h +++ b/libraries/shared/src/SettingInterface.h @@ -20,14 +20,11 @@ namespace Setting { class Manager; - void preInit(); void init(); void cleanupSettings(); class Interface { public: - static const QString FIRST_RUN; - const QString& getKey() const { return _key; } bool isSet() const { return _isSet; } diff --git a/libraries/shared/src/SettingManager.cpp b/libraries/shared/src/SettingManager.cpp index a42e62c1c8..929fe2b0ff 100644 --- a/libraries/shared/src/SettingManager.cpp +++ b/libraries/shared/src/SettingManager.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SettingManager.h" + #include #include #include #include "SettingInterface.h" -#include "SettingManager.h" namespace Setting { @@ -32,7 +33,6 @@ namespace Setting { // Custom deleter does nothing, because we need to shutdown later than the dependency manager void Manager::customDeleter() { } - void Manager::registerHandle(Interface* handle) { const QString& key = handle->getKey(); withWriteLock([&] { diff --git a/libraries/shared/src/StatTracker.cpp b/libraries/shared/src/StatTracker.cpp new file mode 100644 index 0000000000..4ec4e31797 --- /dev/null +++ b/libraries/shared/src/StatTracker.cpp @@ -0,0 +1,34 @@ +// +// Created by Ryan Huffman on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "StatTracker.h" + +StatTracker::StatTracker() { + +} + +QVariant StatTracker::getStat(QString name) { + std::lock_guard lock(_statsLock); + return _stats[name]; +} + +void StatTracker::editStat(QString name, EditStatFunction fn) { + std::lock_guard lock(_statsLock); + _stats[name] = fn(_stats[name]); +} + +void StatTracker::incrementStat(QString name) { + std::lock_guard lock(_statsLock); + QVariant stat = _stats[name]; + _stats[name] = _stats[name].toInt() + 1; +} + +void StatTracker::decrementStat(QString name) { + std::lock_guard lock(_statsLock); + _stats[name] = _stats[name].toInt() - 1; +} \ No newline at end of file diff --git a/libraries/shared/src/StatTracker.h b/libraries/shared/src/StatTracker.h new file mode 100644 index 0000000000..b500d9a821 --- /dev/null +++ b/libraries/shared/src/StatTracker.h @@ -0,0 +1,42 @@ +// +// Created by Ryan Huffman on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#include +#include +#include +#include +#include "DependencyManager.h" +#include "Trace.h" + +using EditStatFunction = std::function; + +class StatTracker : public Dependency { +public: + StatTracker(); + QVariant getStat(QString name); + void editStat(QString name, EditStatFunction fn); + void incrementStat(QString name); + void decrementStat(QString name); +private: + std::mutex _statsLock; + QVariantMap _stats; +}; + +class CounterStat { +public: + CounterStat(QString name) : _name(name) { + DependencyManager::get()->incrementStat(_name); + } + ~CounterStat() { + DependencyManager::get()->decrementStat(_name); + } +private: + QString _name; +}; diff --git a/libraries/shared/src/Trace.cpp b/libraries/shared/src/Trace.cpp new file mode 100644 index 0000000000..0e2b2f213c --- /dev/null +++ b/libraries/shared/src/Trace.cpp @@ -0,0 +1,205 @@ +// +// Created by Ryan Huffman on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Trace.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "Gzip.h" +#include "PortableHighResolutionClock.h" +#include "shared/GlobalAppProperties.h" + +using namespace tracing; + +bool tracing::enabled() { + return DependencyManager::get()->isEnabled(); +} + +void Tracer::startTracing() { + std::lock_guard guard(_eventsMutex); + if (_enabled) { + qWarning() << "Tried to enable tracer, but already enabled"; + return; + } + + _events.clear(); + _enabled = true; +} + +void Tracer::stopTracing() { + std::lock_guard guard(_eventsMutex); + if (!_enabled) { + qWarning() << "Cannot stop tracing, already disabled"; + return; + } + _enabled = false; +} + +void TraceEvent::writeJson(QTextStream& out) const { +#if 0 + // FIXME QJsonObject serialization is very slow, so we should be using manual JSON serialization + out << "{"; + out << "\"name\":\"" << name << "\","; + out << "\"cat\":\"" << category.categoryName() << "\","; + out << "\"ph\":\"" << QString(type) << "\","; + out << "\"ts\":\"" << timestamp << "\","; + out << "\"pid\":\"" << processID << "\","; + out << "\"tid\":\"" << threadID << "\""; + //if (!extra.empty()) { + // auto it = extra.begin(); + // for (; it != extra.end(); it++) { + // ev[it.key()] = QJsonValue::fromVariant(it.value()); + // } + //} + //if (!args.empty()) { + // out << ",\"args\":' + //} + out << '}'; +#else + QJsonObject ev { + { "name", QJsonValue(name) }, + { "cat", category.categoryName() }, + { "ph", QString(type) }, + { "ts", timestamp }, + { "pid", processID }, + { "tid", threadID } + }; + if (!id.isEmpty()) { + ev["id"] = id; + } + if (!args.empty()) { + ev["args"] = QJsonObject::fromVariantMap(args); + } + if (!extra.empty()) { + auto it = extra.begin(); + for (; it != extra.end(); it++) { + ev[it.key()] = QJsonValue::fromVariant(it.value()); + } + } + out << QJsonDocument(ev).toJson(QJsonDocument::Compact); +#endif +} + +void Tracer::serialize(const QString& path) { + std::list currentEvents; + { + std::lock_guard guard(_eventsMutex); + currentEvents.swap(_events); + } + + // If the file exists and we can't remove it, fail early + if (QFileInfo(path).exists() && !QFile::remove(path)) { + return; + } + + // If we can't open a temp file for writing, fail early + QByteArray data; + { + QTextStream out(&data); + out << "[\n"; + bool first = true; + for (const auto& event : currentEvents) { + if (first) { + first = false; + } else { + out << ",\n"; + } + event.writeJson(out); + } + out << "\n]"; + } + + if (path.endsWith(".gz")) { + QByteArray compressed; + gzip(data, compressed); + data = compressed; + } + + { + QFile file(path); + if (!file.open(QIODevice::WriteOnly)) { + return; + } + file.write(data); + file.close(); + } + +#if 0 + QByteArray data; + { + + // "traceEvents":[ + // {"args":{"nv_payload":0},"cat":"hifi.render","name":"render::Scene::processPendingChangesQueue","ph":"B","pid":14796,"tid":21636,"ts":68795933487} + + QJsonArray traceEvents; + + QJsonDocument document { + QJsonObject { + { "traceEvents", traceEvents }, + { "otherData", QJsonObject { + { "version", QString { "High Fidelity Interface v1.0" } +BuildInfo::VERSION } + } } + } + }; + + data = document.toJson(QJsonDocument::Compact); + } +#endif +} + +void Tracer::traceEvent(const QLoggingCategory& category, + const QString& name, EventType type, + qint64 timestamp, qint64 processID, qint64 threadID, + const QString& id, + const QVariantMap& args, const QVariantMap& extra) { + std::lock_guard guard(_eventsMutex); + if (!_enabled) { + return; + } + + _events.push_back({ + id, + name, + type, + timestamp, + processID, + threadID, + category, + args, + extra + }); +} + +void Tracer::traceEvent(const QLoggingCategory& category, + const QString& name, EventType type, const QString& id, + const QVariantMap& args, const QVariantMap& extra) { + if (!_enabled) { + return; + } + + auto timestamp = std::chrono::duration_cast(p_high_resolution_clock::now().time_since_epoch()).count(); + auto processID = QCoreApplication::applicationPid(); + auto threadID = int64_t(QThread::currentThreadId()); + + traceEvent(category, name, type, timestamp, processID, threadID, id, args, extra); +} diff --git a/libraries/shared/src/Trace.h b/libraries/shared/src/Trace.h new file mode 100644 index 0000000000..e075dc24c4 --- /dev/null +++ b/libraries/shared/src/Trace.h @@ -0,0 +1,115 @@ +// +// Created by Ryan Huffman on 2016-12-14 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_Trace_h +#define hifi_Trace_h + +#include +#include + +#include +#include +#include +#include +#include + +#include "DependencyManager.h" + +#define TRACE_ENABLED + +namespace tracing { + +bool enabled(); + +using TraceTimestamp = uint64_t; + +enum EventType : char { + DurationBegin = 'B', + DurationEnd = 'E', + + Complete = 'X', + Instant = 'i', + Counter = 'C', + + AsyncNestableStart = 'b', + AsyncNestableInstant = 'n', + AsyncNestableEnd = 'e', + + FlowStart = 's', + FlowStep = 't', + FlowEnd = 'f', + + Sample = 'P', + + ObjectCreated = 'N', + ObjectSnapshot = 'O', + ObjectDestroyed = 'D', + + Metadata = 'M', + + MemoryDumpGlobal = 'V', + MemoryDumpProcess = 'v', + + Mark = 'R', + + ClockSync = 'c', + + ContextEnter = '(', + ContextLeave = ')' +}; + +struct TraceEvent { + QString id; + QString name; + EventType type; + qint64 timestamp; + qint64 processID; + qint64 threadID; + const QLoggingCategory& category; + QVariantMap args; + QVariantMap extra; + + void writeJson(QTextStream& out) const; +}; + +class Tracer : public Dependency { +public: + void traceEvent(const QLoggingCategory& category, + const QString& name, EventType type, + const QString& id = "", + const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()); + + void startTracing(); + void stopTracing(); + void serialize(const QString& file); + bool isEnabled() const { return _enabled; } + +private: + void traceEvent(const QLoggingCategory& category, + const QString& name, EventType type, + qint64 timestamp, qint64 processID, qint64 threadID, + const QString& id = "", + const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()); + + bool _enabled { false }; + std::list _events; + std::mutex _eventsMutex; +}; + +inline void traceEvent(const QLoggingCategory& category, const QString& name, EventType type, const QString& id = "", const QVariantMap& args = {}, const QVariantMap& extra = {}) { + DependencyManager::get()->traceEvent(category, name, type, id, args, extra); +} + +inline void traceEvent(const QLoggingCategory& category, const QString& name, EventType type, int id, const QVariantMap& args = {}, const QVariantMap& extra = {}) { + traceEvent(category, name, type, QString::number(id), args, extra); +} + +} + +#endif // hifi_Trace_h diff --git a/libraries/shared/src/shared/GlobalAppProperties.cpp b/libraries/shared/src/shared/GlobalAppProperties.cpp index bfb8f744f1..a8a38457f2 100644 --- a/libraries/shared/src/shared/GlobalAppProperties.cpp +++ b/libraries/shared/src/shared/GlobalAppProperties.cpp @@ -14,6 +14,7 @@ namespace hifi { namespace properties { const char* STEAM = "com.highfidelity.launchedFromSteam"; const char* LOGGER = "com.highfidelity.logger"; const char* TEST = "com.highfidelity.test"; + const char* TRACING = "com.highfidelity.tracing"; namespace gl { const char* BACKEND = "com.highfidelity.gl.backend"; diff --git a/libraries/shared/src/shared/GlobalAppProperties.h b/libraries/shared/src/shared/GlobalAppProperties.h index 4786142a08..92d8388f09 100644 --- a/libraries/shared/src/shared/GlobalAppProperties.h +++ b/libraries/shared/src/shared/GlobalAppProperties.h @@ -16,6 +16,7 @@ namespace hifi { namespace properties { extern const char* STEAM; extern const char* LOGGER; extern const char* TEST; + extern const char* TRACING; namespace gl { extern const char* BACKEND; diff --git a/libraries/shared/src/shared/NsightHelpers.cpp b/libraries/shared/src/shared/NsightHelpers.cpp index fa853029be..6f7408c7c5 100644 --- a/libraries/shared/src/shared/NsightHelpers.cpp +++ b/libraries/shared/src/shared/NsightHelpers.cpp @@ -21,49 +21,6 @@ bool nsightActive() { return nsightLaunched; } - -uint64_t ProfileRange::beginRange(const char* name, uint32_t argbColor) { - nvtxEventAttributes_t eventAttrib = { 0 }; - eventAttrib.version = NVTX_VERSION; - eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; - eventAttrib.colorType = NVTX_COLOR_ARGB; - eventAttrib.color = argbColor; - eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; - eventAttrib.message.ascii = name; - return nvtxRangeStartEx(&eventAttrib); - // return nvtxRangePushEx(&eventAttrib); -} - -void ProfileRange::endRange(uint64_t rangeId) { - nvtxRangeEnd(rangeId); - // nvtxRangePop(); -} - -ProfileRange::ProfileRange(const char *name) { - // _rangeId = nvtxRangeStart(name); - _rangeId = nvtxRangePush(name); -} - -ProfileRange::ProfileRange(const char *name, uint32_t argbColor, uint64_t payload) { - nvtxEventAttributes_t eventAttrib = {0}; - eventAttrib.version = NVTX_VERSION; - eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; - eventAttrib.colorType = NVTX_COLOR_ARGB; - eventAttrib.color = argbColor; - eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; - eventAttrib.message.ascii = name; - eventAttrib.payload.llValue = payload; - eventAttrib.payloadType = NVTX_PAYLOAD_TYPE_UNSIGNED_INT64; - - //_rangeId = nvtxRangeStartEx(&eventAttrib); - _rangeId = nvtxRangePushEx(&eventAttrib); -} - -ProfileRange::~ProfileRange() { - // nvtxRangeEnd(_rangeId); - nvtxRangePop(); -} - #else bool nsightActive() { diff --git a/libraries/shared/src/shared/NsightHelpers.h b/libraries/shared/src/shared/NsightHelpers.h index 294ffe0f7d..396d828ff9 100644 --- a/libraries/shared/src/shared/NsightHelpers.h +++ b/libraries/shared/src/shared/NsightHelpers.h @@ -11,35 +11,6 @@ bool nsightActive(); -#if defined(_WIN32) && defined(NSIGHT_FOUND) -#include - -class ProfileRange { -public: - ProfileRange(const char *name); - ProfileRange(const char *name, uint32_t argbColor, uint64_t payload); - ~ProfileRange(); - - static uint64_t beginRange(const char* name, uint32_t argbColor); - static void endRange(uint64_t rangeId); -private: - uint64_t _rangeId{ 0 }; -}; - -#define PROFILE_RANGE(name) ProfileRange profileRangeThis(name); -#define PROFILE_RANGE_EX(name, argbColor, payload) ProfileRange profileRangeThis(name, argbColor, (uint64_t)payload); - -#define PROFILE_RANGE_BEGIN(rangeId, name, argbColor) rangeId = ProfileRange::beginRange(name, argbColor) -#define PROFILE_RANGE_END(rangeId) ProfileRange::endRange(rangeId) - -#else -#define PROFILE_RANGE(name) -#define PROFILE_RANGE_EX(name, argbColor, payload) - - -#define PROFILE_RANGE_BEGIN(rangeId, name, argbColor) -#define PROFILE_RANGE_END(rangeId) - -#endif +#include "../Profile.h" #endif diff --git a/libraries/steamworks-wrapper/CMakeLists.txt b/libraries/steamworks-wrapper/CMakeLists.txt deleted file mode 100644 index 0cbe3bb5ad..0000000000 --- a/libraries/steamworks-wrapper/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(TARGET_NAME steamworks-wrapper) -setup_hifi_library() -link_hifi_libraries() - -target_steamworks() \ No newline at end of file diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h deleted file mode 100644 index a191adee97..0000000000 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// SteamClient.h -// steamworks-wrapper/src/steamworks-wrapper -// -// Created by Clement Brisset on 6/8/16. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -#ifndef hifi_SteamClient_h -#define hifi_SteamClient_h - -#include - -#include -#include - -using Ticket = QByteArray; -using TicketRequestCallback = std::function; - -class QUrl; - -class SteamClient { -public: - static bool isRunning(); - - static bool init(); - static void shutdown(); - - static void runCallbacks(); - - static void requestTicket(TicketRequestCallback callback); - static void updateLocation(QString status, QUrl locationUrl); - static void openInviteOverlay(); - static void joinLobby(QString lobbyId); - - static int getSteamVRBuildID(); -}; - -class SteamScriptingInterface : public QObject { - Q_OBJECT - - Q_PROPERTY(bool isRunning READ isRunning) - -public: - SteamScriptingInterface(QObject* parent) : QObject(parent) {} - -public slots: - bool isRunning() const { return SteamClient::isRunning(); } - void openInviteOverlay() const { SteamClient::openInviteOverlay(); } - -}; - -#endif // hifi_SteamClient_h \ No newline at end of file diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4553b80793..82ca2a7d38 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -26,9 +26,10 @@ if (NOT SERVER_ONLY AND NOT ANDROID) add_subdirectory(${DIR}) set(DIR "hifiNeuron") add_subdirectory(${DIR}) - set(DIR "hifiKinect") add_subdirectory(${DIR}) + set(DIR "steamClient") + add_subdirectory(${DIR}) endif() # server-side plugins diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index f56d594919..ce59eafd50 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -206,7 +206,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control } int numTrackedControllers = 0; - static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked & ovrStatus_PositionTracked; + static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked; auto tracking = ovr_GetTrackingState(_parent._session, 0, false); ovr_for_each_hand([&](ovrHandType hand) { ++numTrackedControllers; diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index d7d734f6a2..5ab9d2f058 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -110,7 +110,7 @@ void OculusDisplayPlugin::hmdPresent() { return; } - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) + PROFILE_RANGE_EX(displayplugins, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) int curIndex; ovr_GetTextureSwapChainCurrentIndex(_session, _textureSwapChain, &curIndex); diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp index feb0896fa4..8a160b67ff 100644 --- a/plugins/oculus/src/OculusHelpers.cpp +++ b/plugins/oculus/src/OculusHelpers.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -20,8 +19,8 @@ #include #include -Q_DECLARE_LOGGING_CATEGORY(oculus) -Q_LOGGING_CATEGORY(oculus, "hifi.plugins.oculus") +Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display") +Q_LOGGING_CATEGORY(oculus, "hifi.plugins.display.oculus") static std::atomic refCount { 0 }; static ovrSession session { nullptr }; @@ -194,15 +193,14 @@ controller::Pose ovrControllerPoseToHandPose( static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z); static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z); - static const glm::quat eighthX = glm::angleAxis(PI / 4.0f, Vectors::UNIT_X); - static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ * eighthX) * touchToHand; - static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ * eighthX) * touchToHand; + static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand; + static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand; static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, - CONTROLLER_LENGTH_OFFSET / 2.0f, - CONTROLLER_LENGTH_OFFSET * 2.0f); + -CONTROLLER_LENGTH_OFFSET / 2.0f, + CONTROLLER_LENGTH_OFFSET * 1.5f); static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET; static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET; diff --git a/plugins/oculus/src/OculusHelpers.h b/plugins/oculus/src/OculusHelpers.h index 8244add84e..50ba355b0c 100644 --- a/plugins/oculus/src/OculusHelpers.h +++ b/plugins/oculus/src/OculusHelpers.h @@ -7,6 +7,9 @@ // #pragma once + +#include + #include #include #include @@ -14,6 +17,9 @@ #include +Q_DECLARE_LOGGING_CATEGORY(displayplugins) +Q_DECLARE_LOGGING_CATEGORY(oculus) + void logWarning(const char* what); void logCritical(const char* what); bool oculusAvailable(); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index bfa61f3b36..5a963db254 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -529,7 +529,7 @@ static bool isBadPose(vr::HmdMatrix34_t* mat) { } bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { - PROFILE_RANGE_EX(__FUNCTION__, 0xff7fff00, frameIndex) + PROFILE_RANGE_EX(displayplugins, __FUNCTION__, 0xff7fff00, frameIndex) handleOpenVrEvents(); if (openVrQuitRequested()) { QMetaObject::invokeMethod(qApp, "quit"); @@ -633,7 +633,7 @@ void OpenVrDisplayPlugin::compositeLayers() { } void OpenVrDisplayPlugin::hmdPresent() { - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) + PROFILE_RANGE_EX(displayplugins, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) if (_threadedSubmit) { _submitThread->waitForPresent(); @@ -654,7 +654,7 @@ void OpenVrDisplayPlugin::hmdPresent() { } void OpenVrDisplayPlugin::postPreview() { - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) + PROFILE_RANGE_EX(displayplugins, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) PoseData nextRender, nextSim; nextRender.frameIndex = presentCount(); diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 56a5dd3f5b..09713e9f57 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -370,7 +370,7 @@ void showMinSpecWarning() { auto headPose = toGlm(vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); auto overlayPose = toOpenVr(headPose * glm::translate(glm::mat4(), vec3(0, 0, -1))); vrOverlay->SetOverlayTransformAbsolute(minSpecFailedOverlay, vr::TrackingUniverseSeated, &overlayPose); - + vr::VREvent_t event; while (vrSystem->PollNextEvent(&event, sizeof(event))) { switch (event.eventType) { @@ -405,7 +405,7 @@ bool checkMinSpecImpl() { return true; } - // If we have at least 5 cores, pass + // If we have at least MIN_CORES_SPEC cores, pass auto coreCount = QThread::idealThreadCount(); if (coreCount >= MIN_CORES_SPEC) { return true; diff --git a/plugins/steamClient/CMakeLists.txt b/plugins/steamClient/CMakeLists.txt new file mode 100644 index 0000000000..326628f8e4 --- /dev/null +++ b/plugins/steamClient/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Created by Clément Brisset on 12/14/16 +# Copyright 2016 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html +# + +set(TARGET_NAME steamClient) +setup_hifi_plugin(Gui) +link_hifi_libraries(plugins) +target_steamworks() diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/plugins/steamClient/src/SteamAPIPlugin.cpp similarity index 95% rename from libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp rename to plugins/steamClient/src/SteamAPIPlugin.cpp index 9936027302..853a53e881 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/plugins/steamClient/src/SteamAPIPlugin.cpp @@ -1,6 +1,6 @@ // -// SteamClient.cpp -// steamworks-wrapper/src/steamworks-wrapper +// SteamAPIPlugin.cpp +// plugins/steamClient/src // // Created by Clement Brisset on 6/8/16. // Copyright 2016 High Fidelity, Inc. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "SteamClient.h" +#include "SteamAPIPlugin.h" #include @@ -226,18 +226,18 @@ static std::atomic_bool initialized { false }; static SteamCallbackManager steamCallbackManager; -bool SteamClient::isRunning() { +bool SteamAPIPlugin::isRunning() { return initialized; } -bool SteamClient::init() { +bool SteamAPIPlugin::init() { if (SteamAPI_IsSteamRunning() && !initialized) { initialized = SteamAPI_Init(); } return initialized; } -void SteamClient::shutdown() { +void SteamAPIPlugin::shutdown() { if (initialized) { SteamAPI_Shutdown(); } @@ -245,7 +245,7 @@ void SteamClient::shutdown() { steamCallbackManager.getTicketRequests().stopAll(); } -int SteamClient::getSteamVRBuildID() { +int SteamAPIPlugin::getSteamVRBuildID() { if (initialized) { static const int MAX_PATH_SIZE = 512; static const int STEAMVR_APPID = 250820; @@ -271,7 +271,7 @@ int SteamClient::getSteamVRBuildID() { } -void SteamClient::runCallbacks() { +void SteamAPIPlugin::runCallbacks() { if (!initialized) { return; } @@ -285,7 +285,7 @@ void SteamClient::runCallbacks() { Steam_RunCallbacks(steamPipe, false); } -void SteamClient::requestTicket(TicketRequestCallback callback) { +void SteamAPIPlugin::requestTicket(TicketRequestCallback callback) { if (!initialized) { if (SteamAPI_IsSteamRunning()) { init(); @@ -304,7 +304,7 @@ void SteamClient::requestTicket(TicketRequestCallback callback) { steamCallbackManager.getTicketRequests().startRequest(callback); } -void SteamClient::updateLocation(QString status, QUrl locationUrl) { +void SteamAPIPlugin::updateLocation(QString status, QUrl locationUrl) { if (!initialized) { return; } @@ -315,7 +315,7 @@ void SteamClient::updateLocation(QString status, QUrl locationUrl) { SteamFriends()->SetRichPresence("connect", connectStr.toLocal8Bit().data()); } -void SteamClient::openInviteOverlay() { +void SteamAPIPlugin::openInviteOverlay() { if (!initialized) { return; } @@ -326,7 +326,7 @@ void SteamClient::openInviteOverlay() { } -void SteamClient::joinLobby(QString lobbyIdStr) { +void SteamAPIPlugin::joinLobby(QString lobbyIdStr) { if (!initialized) { if (SteamAPI_IsSteamRunning()) { init(); diff --git a/plugins/steamClient/src/SteamAPIPlugin.h b/plugins/steamClient/src/SteamAPIPlugin.h new file mode 100644 index 0000000000..90fda06de3 --- /dev/null +++ b/plugins/steamClient/src/SteamAPIPlugin.h @@ -0,0 +1,37 @@ +// +// SteamAPIPlugin.h +// plugins/steamClient/src +// +// Created by Clement Brisset on 6/8/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#ifndef hifi_SteamAPIPlugin_h +#define hifi_SteamAPIPlugin_h + +#include + +class QUrl; + +class SteamAPIPlugin : public SteamClientPlugin { +public: + bool isRunning(); + + bool init(); + void shutdown(); + + void runCallbacks(); + + void requestTicket(TicketRequestCallback callback); + void updateLocation(QString status, QUrl locationUrl); + void openInviteOverlay(); + void joinLobby(QString lobbyId); + + int getSteamVRBuildID(); +}; + +#endif // hifi_SteamAPIPlugin_h diff --git a/plugins/steamClient/src/SteamClientProvider.cpp b/plugins/steamClient/src/SteamClientProvider.cpp new file mode 100644 index 0000000000..a873d51729 --- /dev/null +++ b/plugins/steamClient/src/SteamClientProvider.cpp @@ -0,0 +1,41 @@ +// +// Created by Clément Brisset on 12/14/16 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include +#include + +#include +#include + +#include "SteamAPIPlugin.h" + +class SteamAPIProvider : public QObject, public SteamClientProvider { + Q_OBJECT + Q_PLUGIN_METADATA(IID SteamClientProvider_iid FILE "plugin.json") + Q_INTERFACES(SteamClientProvider) + +public: + SteamAPIProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~SteamAPIProvider() {} + + virtual SteamClientPluginPointer getSteamClientPlugin() override { + static std::once_flag once; + std::call_once(once, [&] { + _steamClientPlugin = std::make_shared(); + }); + return _steamClientPlugin; + } + +private: + SteamClientPluginPointer _steamClientPlugin; +}; + +#include "SteamClientProvider.moc" diff --git a/plugins/steamClient/src/plugin.json b/plugins/steamClient/src/plugin.json new file mode 100644 index 0000000000..dfe37917d2 --- /dev/null +++ b/plugins/steamClient/src/plugin.json @@ -0,0 +1 @@ +{"name":"Steam Client"} diff --git a/scripts/developer/tests/testTestMode.js b/scripts/developer/tests/testTestMode.js index add106ab72..b535f635e4 100644 --- a/scripts/developer/tests/testTestMode.js +++ b/scripts/developer/tests/testTestMode.js @@ -6,9 +6,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -print("Fooooo"); Script.setTimeout(function() { + var loggingRules = "" + +"*.debug=false\n" + +"hifi.render.debug=true\n" + +"hifi.interface.debug=true\n" + +""; + Test.startTracing(loggingRules); +}, 1 * 1000); + + +Script.setTimeout(function() { + Test.stopTracing("h:/testScriptTrace.json.gz"); Test.quit(); }, 10 * 1000); diff --git a/scripts/system/assets/images/tools/people.svg b/scripts/system/assets/images/tools/people.svg new file mode 100644 index 0000000000..5fedfefa75 --- /dev/null +++ b/scripts/system/assets/images/tools/people.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index ff1407cbf0..cdd66a905a 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -703,6 +703,8 @@ function MyController(hand) { this.autoUnequipCounter = 0; this.grabPointIntersectsEntity = false; + this.shouldScale = false; + // handPosition is where the avatar's hand appears to be, in-world. this.getHandPosition = function () { if (this.hand === RIGHT_HAND) { @@ -771,6 +773,11 @@ function MyController(hand) { this.updateSmoothedTrigger(); + // If both trigger and grip buttons squeezed and nothing is held, rescale my avatar! + if (this.hand === RIGHT_HAND && this.state === STATE_SEARCHING && this.getOtherHandController().state === STATE_SEARCHING) { + this.maybeScaleMyAvatar(); + } + if (this.ignoreInput()) { this.turnOffVisualizations(); return; @@ -1614,6 +1621,8 @@ function MyController(hand) { this.clearEquipHaptics(); this.grabPointSphereOff(); + this.shouldScale = false; + var worldControllerPosition = getControllerWorldLocation(this.handToController(), true).position; // transform the position into room space @@ -1773,6 +1782,7 @@ function MyController(hand) { } } + this.maybeScale(grabbedProperties); // visualizations var rayPickInfo = this.calcRayPickInfo(this.hand); @@ -1882,6 +1892,8 @@ function MyController(hand) { this.dropGestureReset(); this.clearEquipHaptics(); + this.shouldScale = false; + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); if (this.entityActivated) { @@ -2151,6 +2163,10 @@ function MyController(hand) { this.callEntityMethodOnGrabbed("continueNearGrab"); } + if (this.state == STATE_NEAR_GRABBING) { + this.maybeScale(props); + } + if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSECS_PER_SEC) { // if less than a 5 seconds left, refresh the actions ttl var success = Entities.updateAction(this.grabbedEntity, this.actionID, { @@ -2173,6 +2189,43 @@ function MyController(hand) { } }; + this.maybeScale = function(props) { + if (!this.shouldScale) { + // If both secondary triggers squeezed, and the non-holding hand is empty, start scaling + if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed() && this.getOtherHandController().state === STATE_OFF) { + this.scalingStartDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + this.scalingStartDimensions = props.dimensions; + this.shouldScale = true; + } + } else if (!this.secondarySqueezed() || !this.getOtherHandController().secondarySqueezed()) { + this.shouldScale = false; + } + if (this.shouldScale) { + var scalingCurrentDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + var currentRescale = scalingCurrentDistance / this.scalingStartDistance; + var newDimensions = Vec3.multiply(currentRescale, this.scalingStartDimensions); + Entities.editEntity(this.grabbedEntity, { dimensions: newDimensions }) + } + } + + this.maybeScaleMyAvatar = function() { + if (!this.shouldScale) { + // If both secondary triggers squeezed, start scaling + if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed()) { + this.scalingStartDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + this.scalingStartAvatarScale = MyAvatar.scale; + this.shouldScale = true; + } + } else if (!this.secondarySqueezed() || !this.getOtherHandController().secondarySqueezed()) { + this.shouldScale = false; + } + if (this.shouldScale) { + var scalingCurrentDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale; + MyAvatar.scale = newAvatarScale; + } + } + this.nearTriggerEnter = function() { this.clearEquipHaptics(); this.grabPointSphereOff(); diff --git a/scripts/system/pal.js b/scripts/system/pal.js new file mode 100644 index 0000000000..175418cd2e --- /dev/null +++ b/scripts/system/pal.js @@ -0,0 +1,265 @@ +"use strict"; +/*jslint vars: true, plusplus: true, forin: true*/ +/*globals Script, AvatarList, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Quat, Controller, print, getControllerWorldLocation */ +// +// pal.js +// +// Created by Howard Stearns on December 9, 2016 +// Copyright 2016 High Fidelity, Inc +// +// Distributed under the Apache License, Version 2.0 +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// FIXME when we make this a defaultScript: (function() { // BEGIN LOCAL_SCOPE + +Script.include("/~/system/libraries/controllers.js"); + +// +// Overlays. +// +var overlays = {}; // Keeps track of all our extended overlay data objects, keyed by target identifier. +function ExtendedOverlay(key, type, properties, selected) { // A wrapper around overlays to store the key it is associated with. + overlays[key] = this; + this.key = key; + this.selected = selected || false; // not undefined + this.activeOverlay = Overlays.addOverlay(type, properties); // We could use different overlays for (un)selected... +} +// Instance methods: +ExtendedOverlay.prototype.deleteOverlay = function () { // remove display and data of this overlay + Overlays.deleteOverlay(this.activeOverlay); + delete overlays[this.key]; +}; + +ExtendedOverlay.prototype.editOverlay = function (properties) { // change display of this overlay + Overlays.editOverlay(this.activeOverlay, properties); +}; +const UNSELECTED_COLOR = {red: 20, green: 250, blue: 20}; +const SELECTED_COLOR = {red: 250, green: 20, blue: 20}; +function color(selected) { return selected ? SELECTED_COLOR : UNSELECTED_COLOR; } +ExtendedOverlay.prototype.select = function (selected) { + if (this.selected === selected) { + return; + } + this.editOverlay({color: color(selected)}); + this.selected = selected; +}; +// Class methods: +var selectedIds = []; +ExtendedOverlay.isSelected = function (id) { + return -1 !== selectedIds.indexOf(id); +} +ExtendedOverlay.get = function (key) { // answer the extended overlay data object associated with the given avatar identifier + return overlays[key]; +}; +ExtendedOverlay.some = function (iterator) { // Bails early as soon as iterator returns truthy. + var key; + for (key in overlays) { + if (iterator(ExtendedOverlay.get(key))) { + return; + } + } +}; +ExtendedOverlay.applyPickRay = function (pickRay, cb) { // cb(overlay) on the one overlay intersected by pickRay, if any. + var pickedOverlay = Overlays.findRayIntersection(pickRay); // Depends on nearer coverOverlays to extend closer to us than farther ones. + if (!pickedOverlay.intersects) { + return; + } + ExtendedOverlay.some(function (overlay) { // See if pickedOverlay is one of ours. + if ((overlay.activeOverlay) === pickedOverlay.overlayID) { + cb(overlay); + return true; + } + }); +}; + +// +// The qml window and communications. +// +var pal = new OverlayWindow({ + title: 'People Action List', + source: 'hifi/Pal.qml', + width: 480, + height: 640, + visible: false +}); +pal.fromQml.connect(function (message) { // messages are {method, params}, like json-rpc. See also sendToQml. + print('From PAL QML:', JSON.stringify(message)); + switch (message.method) { + case 'selected': + selectedIds = message.params; + ExtendedOverlay.some(function (overlay) { + var id = overlay.key; + var selected = ExtendedOverlay.isSelected(id); + overlay.select(selected); + }); + break; + default: + print('Unrecognized message from Pal.qml:', JSON.stringify(message)); + } +}); + +// +// Main operations. +// +function addAvatarNode(id) { + var selected = ExtendedOverlay.isSelected(id); + return new ExtendedOverlay(id, "sphere", { // 3d so we don't go cross-eyed looking at it, but on top of everything + solid: true, + alpha: 0.8, + color: color(selected), + drawInFront: true + }, selected); +} +function populateUserList() { + var data = []; + var counter = 1; + AvatarList.getAvatarIdentifiers().sort().forEach(function (id) { // sorting the identifiers is just an aid for debugging + var avatar = AvatarList.getAvatar(id); + var avatarPalDatum = { + displayName: avatar.displayName || ('anonymous ' + counter++), + userName: "fakeAcct" + (id || "Me"), + sessionId: id || '' + }; + data.push(avatarPalDatum); + if (id) { // No overlay for ourself. + addAvatarNode(id); + } + print('PAL data:', JSON.stringify(avatarPalDatum)); + }); + pal.sendToQml({method: 'users', params: data}); +} +var pingPong = true; +function updateOverlays() { + var eye = Camera.position; + AvatarList.getAvatarIdentifiers().forEach(function (id) { + if (!id) { + return; // don't update ourself + } + var overlay = ExtendedOverlay.get(id); + if (!overlay) { // For now, we're treating this as a temporary loss, as from the personal space bubble. Add it back. + print('Adding non-PAL avatar node', id); + overlay = addAvatarNode(id); + } + var avatar = AvatarList.getAvatar(id); + var target = avatar.position; + var distance = Vec3.distance(target, eye); + overlay.ping = pingPong; + overlay.editOverlay({ + position: target, + dimensions: 0.05 * distance // constant apparent size + }); + }); + pingPong = !pingPong; + ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) + if (overlay.ping === pingPong) { + overlay.deleteOverlay(); + } + }); + // We could re-populateUserList if anything added or removed, but not for now. +} +function removeOverlays() { + selectedIds = []; + ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); }); +} + +// +// Clicks. +// +function handleClick(pickRay) { + ExtendedOverlay.applyPickRay(pickRay, function (overlay) { + // Don't select directly. Tell qml, who will give us back a list of ids. + var message = {method: 'select', params: [overlay.key, !overlay.selected]}; + pal.sendToQml(message); + return true; + }); +} +function handleMouseEvent(mousePressEvent) { // handleClick if we get one. + if (!mousePressEvent.isLeftButton) { + return; + } + handleClick(Camera.computePickRay(mousePressEvent.x, mousePressEvent.y)); +} +// We get mouseMoveEvents from the handControllers, via handControllerPointer. +// But we don't get mousePressEvents. +var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); +function controllerComputePickRay(hand) { + var controllerPose = getControllerWorldLocation(hand, true); + if (controllerPose.valid) { + return { origin: controllerPose.position, direction: Quat.getUp(controllerPose.orientation) }; + } +} +function makeClickHandler(hand) { + return function (clicked) { + if (clicked > 0.85) { + var pickRay = controllerComputePickRay(hand); + handleClick(pickRay); + } + }; +} +triggerMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); +triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); + +// +// Manage the connection between the button and the window. +// +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); +var buttonName = "pal"; +var button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/people.svg"), + visible: true, + hoverState: 2, + defaultState: 1, + buttonState: 1, + alpha: 0.9 +}); +var isWired = false; +function off() { + if (isWired) { // It is not ok to disconnect these twice, hence guard. + Script.update.disconnect(updateOverlays); + Controller.mousePressEvent.disconnect(handleMouseEvent); + isWired = false; + } + triggerMapping.disable(); // It's ok if we disable twice. + removeOverlays(); +} +function onClicked() { + if (!pal.visible) { + populateUserList(); + pal.raise(); + isWired = true; + Script.update.connect(updateOverlays); + Controller.mousePressEvent.connect(handleMouseEvent); + triggerMapping.enable(); + } else { + off(); + } + pal.setVisible(!pal.visible); +} + +// +// Button state. +// +function onVisibileChanged() { + button.writeProperty('buttonState', pal.visible ? 0 : 1); + button.writeProperty('defaultState', pal.visible ? 0 : 1); + button.writeProperty('hoverState', pal.visible ? 2 : 3); +} +button.clicked.connect(onClicked); +pal.visibleChanged.connect(onVisibileChanged); +pal.closed.connect(off); + +// +// Cleanup. +// +Script.scriptEnding.connect(function () { + button.clicked.disconnect(onClicked); + toolBar.removeButton(buttonName); + pal.visibleChanged.disconnect(onVisibileChanged); + pal.closed.disconnect(off); + off(); +}); + + +// FIXME: }()); // END LOCAL_SCOPE diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index edc2eb6a20..d79a6e46cb 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -166,6 +166,9 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) { if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); } + } else { + // Allow the user to click the snapshot HUD button again + button.clicked.connect(onClicked); } // update button states button.writeProperty("buttonState", 1); @@ -177,14 +180,16 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) { // during which time the user may have moved. So stash that info in the dialog so that // it records the correct href. (We can also stash in .jpegs, but not .gifs.) // last element in data array tells dialog whether we can share or not - confirmShare([ - { localPath: pathAnimatedSnapshot, href: href }, + var confirmShareContents = [ { localPath: pathStillSnapshot, href: href }, { canShare: !!isDomainOpen(domainId), openFeedAfterShare: shouldOpenFeedAfterShare() - } - ]); + }]; + if (pathAnimatedSnapshot !== "") { + confirmShareContents.unshift({ localPath: pathAnimatedSnapshot, href: href }); + } + confirmShare(confirmShareContents); if (clearOverlayWhenMoving) { MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog } @@ -196,9 +201,11 @@ function processingGif() { Reticle.visible = reticleVisible; // update button states - button.writeProperty("buttonState", 1); - button.writeProperty("defaultState", 1); - button.writeProperty("hoverState", 3); + button.writeProperty("buttonState", 0); + button.writeProperty("defaultState", 0); + button.writeProperty("hoverState", 2); + // Don't allow the user to click the snapshot button yet + button.clicked.disconnect(onClicked); // show overlays if they were on if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index f52ba78724..0185b1b3cd 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -70,6 +70,8 @@ #include "Camera.hpp" +Q_DECLARE_LOGGING_CATEGORY(renderperflogging) +Q_LOGGING_CATEGORY(renderperflogging, "hifi.render_perf") static const QString LAST_SCENE_KEY = "lastSceneFile"; static const QString LAST_LOCATION_KEY = "lastLocation"; @@ -856,7 +858,6 @@ private: EntityUpdateOperator updateOperator(now); //getEntities()->getTree()->recurseTreeWithOperator(&updateOperator); { - PROFILE_RANGE_EX("PreRenderLambdas", 0xffff0000, (uint64_t)0); for (auto& iter : _postUpdateLambdas) { iter.second(); } @@ -899,7 +900,7 @@ private: gpu::doInBatch(gpuContext, [&](gpu::Batch& batch) { batch.resetStages(); }); - PROFILE_RANGE(__FUNCTION__); + PROFILE_RANGE(renderperflogging, __FUNCTION__); PerformanceTimer perfTimer("draw"); // The pending changes collecting the changes here render::PendingChanges pendingChanges; diff --git a/tests/render-texture-load/src/GLIHelpers.cpp b/tests/render-texture-load/src/GLIHelpers.cpp index 8067993b49..be39e7f1c8 100644 --- a/tests/render-texture-load/src/GLIHelpers.cpp +++ b/tests/render-texture-load/src/GLIHelpers.cpp @@ -48,7 +48,7 @@ QString convertTexture(const QString& sourceFile) { fromQImageFormat(sourceImage.format()), gli::extent2d(sourceImage.width(), sourceImage.height())); auto sourceSize = sourceImage.byteCount(); - assert(sourceSize == workTexture[workTexture.base_level()].size()); + assert(sourceSize == (int)workTexture[workTexture.base_level()].size()); memcpy(workTexture[workTexture.base_level()].data(), sourceImage.constBits(), sourceSize); QString resultFile = getKtxFileName(sourceFile) ; diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index fb0b16d16c..68f007ce70 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -563,7 +563,6 @@ private: gpu::doInBatch(gpuContext, [&](gpu::Batch& batch) { batch.resetStages(); }); - PROFILE_RANGE(__FUNCTION__); auto framebuffer = DependencyManager::get()->getFramebuffer(); gpu::doInBatch(gpuContext, [&](gpu::Batch& batch) { diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index c38bd6765c..7e909bf31f 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -152,7 +152,6 @@ protected: //static const wchar_t* EXAMPLE_TEXT = L"Hello"; //static const wchar_t* EXAMPLE_TEXT = L"\xC1y Hello 1.0\ny\xC1 line 2\n\xC1y"; -static const glm::uvec2 QUAD_OFFSET(10, 10); void testShaderBuild(const char* vs_src, const char * fs_src) { auto vs = gpu::Shader::createVertex(std::string(vs_src)); diff --git a/tests/shared/src/TraceTests.cpp b/tests/shared/src/TraceTests.cpp new file mode 100644 index 0000000000..175cf2cc01 --- /dev/null +++ b/tests/shared/src/TraceTests.cpp @@ -0,0 +1,45 @@ +// +// Created by Bradley Austin Davis on 2016/12/15 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TraceTests.h" + +#include +#include + +#include +#include +#include <../QTestExtensions.h> + +QTEST_MAIN(TraceTests) +Q_LOGGING_CATEGORY(tracertestlogging, "hifi.tracer.test") + +void TraceTests::testTraceSerialization() { + auto tracer = DependencyManager::set(); + tracer->startTracing(); + tracer->traceEvent(tracertestlogging(), "TestEvent", tracing::DurationBegin); + { + auto start = usecTimestampNow(); + for (size_t i = 0; i < 10000; ++i) { + tracer->traceEvent(tracertestlogging(), "TestCounter", tracing::Counter, "", { { "i", i } }); + } + auto duration = usecTimestampNow() - start; + duration /= USECS_PER_MSEC; + qDebug() << "Recording took " << duration << "ms"; + } + tracer->traceEvent(tracertestlogging(), "TestEvent", tracing::DurationEnd); + tracer->stopTracing(); + { + auto start = usecTimestampNow(); + tracer->serialize("testTrace.json.gz"); + auto duration = usecTimestampNow() - start; + duration /= USECS_PER_MSEC; + qDebug() << "Serialization took " << duration << "ms"; + } + qDebug() << "Done"; +} + diff --git a/tests/shared/src/TraceTests.h b/tests/shared/src/TraceTests.h new file mode 100644 index 0000000000..c81173d356 --- /dev/null +++ b/tests/shared/src/TraceTests.h @@ -0,0 +1,20 @@ +// +// Created by Bradley Austin Davis on 2016/12/15 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_TraceTests_h +#define hifi_TraceTests_h + +#include + +class TraceTests : public QObject { + Q_OBJECT +private slots: + void testTraceSerialization(); +}; + +#endif // hifi_TraceTests_h diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index dad0a6d617..4c12a09388 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -81,9 +81,8 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : listenPort = parser.value(listenPortOption).toInt(); } - Setting::preInit(); - DependencyManager::registerInheritance(); Setting::init(); + DependencyManager::registerInheritance(); DependencyManager::set([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); }); DependencyManager::set(); diff --git a/tools/ac-client/src/main.cpp b/tools/ac-client/src/main.cpp index 918df6413f..12c5e6f5f8 100644 --- a/tools/ac-client/src/main.cpp +++ b/tools/ac-client/src/main.cpp @@ -13,11 +13,19 @@ #include #include +#include + #include "ACClientApp.h" using namespace std; int main(int argc, char * argv[]) { + QCoreApplication::setApplicationName(BuildInfo::AC_CLIENT_SERVER_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + ACClientApp app(argc, argv); + return app.exec(); }