Merge branch 'master' of https://github.com/highfidelity/hifi into lemon

This commit is contained in:
samcake 2016-03-23 10:00:06 -07:00
commit de96e34f7e
7 changed files with 97 additions and 26 deletions

View file

@ -4,7 +4,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add( ExternalProject_Add(
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL http://iweb.dl.sourceforge.net/project/oglplus/oglplus-0.63.x/oglplus-0.63.0.zip URL http://hifi-public.s3.amazonaws.com/dependencies/oglplus-0.63.0.zip
URL_MD5 de984ab245b185b45c87415c0e052135 URL_MD5 de984ab245b185b45c87415c0e052135
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""

View file

@ -239,11 +239,7 @@ class DeadlockWatchdogThread : public QThread {
public: public:
static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1; static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1; static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
#ifdef DEBUG
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 600 * USECS_PER_SECOND;
#else
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 10 * USECS_PER_SECOND; static const unsigned long MAX_HEARTBEAT_AGE_USECS = 10 * USECS_PER_SECOND;
#endif
// Set the heartbeat on launch // Set the heartbeat on launch
DeadlockWatchdogThread() { DeadlockWatchdogThread() {
@ -511,8 +507,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
// Set up a watchdog thread to intentionally crash the application on deadlocks // Set up a watchdog thread to intentionally crash the application on deadlocks
auto deadlockWatchdog = new DeadlockWatchdogThread(); _deadlockWatchdogThread = new DeadlockWatchdogThread();
deadlockWatchdog->start(); _deadlockWatchdogThread->start();
qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion()); qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
@ -586,7 +582,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
ResourceManager::init(); ResourceManager::init();
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
deadlockWatchdog->updateHeartbeat(); updateHeartbeat();
// Setup MessagesClient // Setup MessagesClient
auto messagesClient = DependencyManager::get<MessagesClient>(); auto messagesClient = DependencyManager::get<MessagesClient>();
@ -734,7 +730,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
initializeGL(); initializeGL();
_offscreenContext->makeCurrent(); _offscreenContext->makeCurrent();
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
deadlockWatchdog->updateHeartbeat(); updateHeartbeat();
// Tell our entity edit sender about our known jurisdictions // Tell our entity edit sender about our known jurisdictions
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
@ -746,7 +742,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_overlays.init(); // do this before scripts load _overlays.init(); // do this before scripts load
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
deadlockWatchdog->updateHeartbeat(); updateHeartbeat();
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
@ -900,11 +896,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// do this as late as possible so that all required subsystems are initialized // do this as late as possible so that all required subsystems are initialized
scriptEngines->loadScripts(); scriptEngines->loadScripts();
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
deadlockWatchdog->updateHeartbeat(); updateHeartbeat();
loadSettings(); loadSettings();
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
deadlockWatchdog->updateHeartbeat(); updateHeartbeat();
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings); connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
@ -1019,7 +1015,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
}); });
// Make sure we don't time out during slow operations at startup // Make sure we don't time out during slow operations at startup
deadlockWatchdog->updateHeartbeat(); updateHeartbeat();
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0); qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0);
@ -1060,6 +1056,10 @@ void Application::showCursor(const QCursor& cursor) {
_cursorNeedsChanging = true; _cursorNeedsChanging = true;
} }
void Application::updateHeartbeat() {
static_cast<DeadlockWatchdogThread*>(_deadlockWatchdogThread)->updateHeartbeat();
}
void Application::aboutToQuit() { void Application::aboutToQuit() {
emit beforeAboutToQuit(); emit beforeAboutToQuit();

View file

@ -271,6 +271,8 @@ public slots:
void reloadResourceCaches(); void reloadResourceCaches();
void updateHeartbeat();
void crashApplication(); void crashApplication();
void deadlockApplication(); void deadlockApplication();
@ -505,6 +507,8 @@ private:
mutable QMutex _changeCursorLock { QMutex::Recursive }; mutable QMutex _changeCursorLock { QMutex::Recursive };
QCursor _desiredCursor{ Qt::BlankCursor }; QCursor _desiredCursor{ Qt::BlankCursor };
bool _cursorNeedsChanging { false }; bool _cursorNeedsChanging { false };
QThread* _deadlockWatchdogThread;
}; };
#endif // hifi_Application_h #endif // hifi_Application_h

View file

@ -426,7 +426,11 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
} }
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) { QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
_qmlComponent->loadUrl(qmlSource); // Synchronous loading may take a while; restart the deadlock timer
QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection);
_qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous);
if (_qmlComponent->isLoading()) { if (_qmlComponent->isLoading()) {
connect(_qmlComponent, &QQmlComponent::statusChanged, this, connect(_qmlComponent, &QQmlComponent::statusChanged, this,
[this, f](QQmlComponent::Status){ [this, f](QQmlComponent::Status){

View file

@ -10,11 +10,74 @@
// //
#include "Resource.h" #include "Resource.h"
#include <atomic>
#include <SharedUtil.h>
#include <NumericalConstants.h>
#include <QDebug> #include <QDebug>
using namespace gpu; using namespace gpu;
class AllocationDebugger {
public:
void operator+=(size_t size) {
_allocatedMemory += size;
maybeReport();
}
void operator-=(size_t size) {
_allocatedMemory -= size;
maybeReport();
}
private:
QString formatSize(size_t size) {
float num = size;
QStringList list;
list << "KB" << "MB" << "GB" << "TB";
QStringListIterator i(list);
QString unit("bytes");
while (num >= K && i.hasNext()) {
unit = i.next();
num /= K;
}
return QString().setNum(num, 'f', 2) + " " + unit;
}
void maybeReport() {
auto now = usecTimestampNow();
if (now - _lastReportTime < MAX_REPORT_FREQUENCY) {
return;
}
size_t current = _allocatedMemory;
size_t last = _lastReportedMemory;
size_t delta = (current > last) ? (current - last) : (last - current);
if (delta > MIN_REPORT_DELTA) {
_lastReportTime = now;
_lastReportedMemory = current;
qDebug() << "Total allocation " << formatSize(current);
}
}
std::atomic<size_t> _allocatedMemory;
std::atomic<size_t> _lastReportedMemory;
std::atomic<uint64_t> _lastReportTime;
static const float K;
// Report changes of 5 megabytes
static const size_t MIN_REPORT_DELTA = 1024 * 1024 * 5;
// Report changes no more frequently than every 15 seconds
static const uint64_t MAX_REPORT_FREQUENCY = USECS_PER_SECOND * 15;
};
const float AllocationDebugger::K = 1024.0f;
static AllocationDebugger allocationDebugger;
Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) { Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) {
allocationDebugger += size;
if ( !dataAllocated ) { if ( !dataAllocated ) {
qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer."; qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer.";
return NOT_ALLOCATED; return NOT_ALLOCATED;
@ -38,6 +101,7 @@ Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size)
} }
void Resource::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) { void Resource::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) {
allocationDebugger -= size;
if (dataAllocated) { if (dataAllocated) {
delete[] dataAllocated; delete[] dataAllocated;
} }

View file

@ -29,7 +29,7 @@
using namespace std; using namespace std;
static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >(); static int nakedModelPointerTypeId = qRegisterMetaType<ModelPointer>();
static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >(); static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >(); static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
@ -821,21 +821,21 @@ QStringList Model::getJointNames() const {
class Blender : public QRunnable { class Blender : public QRunnable {
public: public:
Blender(Model* model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry, Blender(ModelPointer model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients); const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients);
virtual void run(); virtual void run();
private: private:
QPointer<Model> _model; ModelPointer _model;
int _blendNumber; int _blendNumber;
QWeakPointer<NetworkGeometry> _geometry; QWeakPointer<NetworkGeometry> _geometry;
QVector<FBXMesh> _meshes; QVector<FBXMesh> _meshes;
QVector<float> _blendshapeCoefficients; QVector<float> _blendshapeCoefficients;
}; };
Blender::Blender(Model* model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry, Blender::Blender(ModelPointer model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients) : const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients) :
_model(model), _model(model),
_blendNumber(blendNumber), _blendNumber(blendNumber),
@ -847,7 +847,7 @@ Blender::Blender(Model* model, int blendNumber, const QWeakPointer<NetworkGeomet
void Blender::run() { void Blender::run() {
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
QVector<glm::vec3> vertices, normals; QVector<glm::vec3> vertices, normals;
if (!_model.isNull()) { if (_model) {
int offset = 0; int offset = 0;
foreach (const FBXMesh& mesh, _meshes) { foreach (const FBXMesh& mesh, _meshes) {
if (mesh.blendshapes.isEmpty()) { if (mesh.blendshapes.isEmpty()) {
@ -877,7 +877,7 @@ void Blender::run() {
} }
// post the result to the geometry cache, which will dispatch to the model if still alive // post the result to the geometry cache, which will dispatch to the model if still alive
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices", QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
Q_ARG(const QPointer<Model>&, _model), Q_ARG(int, _blendNumber), Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber),
Q_ARG(const QWeakPointer<NetworkGeometry>&, _geometry), Q_ARG(const QVector<glm::vec3>&, vertices), Q_ARG(const QWeakPointer<NetworkGeometry>&, _geometry), Q_ARG(const QVector<glm::vec3>&, vertices),
Q_ARG(const QVector<glm::vec3>&, normals)); Q_ARG(const QVector<glm::vec3>&, normals));
} }
@ -1088,7 +1088,7 @@ float Model::getLimbLength(int jointIndex) const {
bool Model::maybeStartBlender() { bool Model::maybeStartBlender() {
const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry(); const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
if (fbxGeometry.hasBlendedMeshes()) { if (fbxGeometry.hasBlendedMeshes()) {
QThreadPool::globalInstance()->start(new Blender(this, ++_blendNumber, _geometry, QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _geometry,
fbxGeometry.meshes, _blendshapeCoefficients)); fbxGeometry.meshes, _blendshapeCoefficients));
return true; return true;
} }
@ -1284,10 +1284,9 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) {
} }
} }
void ModelBlender::setBlendedVertices(const QPointer<Model>& model, int blendNumber, void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber,
const QWeakPointer<NetworkGeometry>& geometry, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) { const QWeakPointer<NetworkGeometry>& geometry, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
if (model) {
if (!model.isNull()) {
model->setBlendedVertices(blendNumber, geometry, vertices, normals); model->setBlendedVertices(blendNumber, geometry, vertices, normals);
} }
_pendingBlenders--; _pendingBlenders--;

View file

@ -384,7 +384,7 @@ protected:
RigPointer _rig; RigPointer _rig;
}; };
Q_DECLARE_METATYPE(QPointer<Model>) Q_DECLARE_METATYPE(ModelPointer)
Q_DECLARE_METATYPE(QWeakPointer<NetworkGeometry>) Q_DECLARE_METATYPE(QWeakPointer<NetworkGeometry>)
/// Handle management of pending models that need blending /// Handle management of pending models that need blending
@ -398,7 +398,7 @@ public:
void noteRequiresBlend(ModelPointer model); void noteRequiresBlend(ModelPointer model);
public slots: public slots:
void setBlendedVertices(const QPointer<Model>& model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry, void setBlendedVertices(ModelPointer model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals); const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
private: private: