From 475331a97df3a41ddeaf5358f561c0928136243a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 26 Aug 2015 16:08:07 -0700 Subject: [PATCH] Sprinkle locks everywhere. --- interface/src/avatar/Avatar.cpp | 5 +++++ interface/src/avatar/AvatarManager.cpp | 6 +++++ interface/src/avatar/SkeletonModel.cpp | 7 ++++++ interface/src/avatar/SkeletonModel.h | 2 ++ libraries/avatars/src/AvatarData.h | 2 ++ .../src/DynamicCharacterController.cpp | 2 ++ libraries/render-utils/src/Model.cpp | 22 +++++++++++++++---- libraries/render-utils/src/Model.h | 3 +++ 8 files changed, 45 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e7423336b1..7b40b5cc5b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -318,6 +318,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptrupdate(); } @@ -392,6 +393,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) { + avatarLock.unlock(); return; } @@ -542,6 +544,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) { renderDisplayName(batch, *renderArgs->_viewFrustum, renderArgs->_viewport); } + avatarLock.unlock(); } glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { @@ -1019,6 +1022,7 @@ void Avatar::setBillboard(const QByteArray& billboard) { } int Avatar::parseDataFromBuffer(const QByteArray& buffer) { + avatarLock.lockForWrite(); if (!_initialized) { // now that we have data for this Avatar we are go for init init(); @@ -1034,6 +1038,7 @@ int Avatar::parseDataFromBuffer(const QByteArray& buffer) { if (_moving && _motionState) { _motionState->addDirtyFlags(EntityItem::DIRTY_POSITION); } + avatarLock.unlock(); return bytesRead; } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 1644f22b09..fefb774d66 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -93,7 +93,9 @@ void AvatarManager::updateMyAvatar(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()"); + _myAvatar->avatarLock.lockForWrite(); _myAvatar->update(deltaTime); + _myAvatar->avatarLock.unlock(); quint64 now = usecTimestampNow(); quint64 dt = now - _lastSendAvatarDataTime; @@ -129,7 +131,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { _avatarFades.push_back(avatarIterator.value()); avatarIterator = _avatarHash.erase(avatarIterator); } else { + avatar->avatarLock.lockForWrite(); avatar->simulate(deltaTime); + avatar->avatarLock.unlock(); ++avatarIterator; } } @@ -148,6 +152,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { render::PendingChanges pendingChanges; while (fadingIterator != _avatarFades.end()) { auto avatar = std::static_pointer_cast(*fadingIterator); + avatar->avatarLock.lockForWrite(); avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true); if (avatar->getTargetScale() < MIN_FADE_SCALE) { avatar->removeFromScene(*fadingIterator, scene, pendingChanges); @@ -156,6 +161,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { avatar->simulate(deltaTime); ++fadingIterator; } + avatar->avatarLock.unlock(); } scene->enqueuePendingChanges(pendingChanges); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index bd50215de6..973a9ea8c7 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -39,6 +39,13 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer r SkeletonModel::~SkeletonModel() { } +void SkeletonModel::avatarLockForWriteIfApplicable() { + _owningAvatar->avatarLock.lockForWrite(); +} +void SkeletonModel::avatarLockReleaseIfApplicable() { + _owningAvatar->avatarLock.unlock(); +} + void SkeletonModel::initJointStates(QVector states) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 4ae615eadd..f18895d674 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -105,6 +105,8 @@ public: float getHeadClipDistance() const { return _headClipDistance; } virtual void onInvalidate() override; + virtual void avatarLockForWriteIfApplicable() override; + virtual void avatarLockReleaseIfApplicable() override; signals: diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 8bb874bc71..7356bc863b 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -305,6 +305,8 @@ public: bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; } + QReadWriteLock avatarLock; // Name is redundant, but it aids searches. + public slots: void sendAvatarDataPacket(); void sendIdentityPacket(); diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index 22f84eccec..7c1455c69e 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -405,6 +405,7 @@ void DynamicCharacterController::preSimulation(btScalar timeStep) { void DynamicCharacterController::postSimulation() { if (_enabled && _rigidBody) { + _avatarData->avatarLock.lockForWrite(); const btTransform& avatarTransform = _rigidBody->getWorldTransform(); glm::quat rotation = bulletToGLM(avatarTransform.getRotation()); glm::vec3 position = bulletToGLM(avatarTransform.getOrigin()); @@ -412,5 +413,6 @@ void DynamicCharacterController::postSimulation() { _avatarData->setOrientation(rotation); _avatarData->setPosition(position - rotation * _shapeLocalOffset); _avatarData->setVelocity(bulletToGLM(_rigidBody->getLinearVelocity())); + _avatarData->avatarLock.unlock(); } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c2d723a323..039cd803c7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1285,7 +1285,9 @@ void Model::simulateInternal(float deltaTime) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; updateRig(deltaTime, parentTransform); - +} +void Model::updateClusterMatrices() { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 zeroScale(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), @@ -1419,15 +1421,17 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { return AABox(); } + avatarLockForWriteIfApplicable(); if (meshIndex < _meshStates.size()) { const MeshState& state = _meshStates.at(meshIndex); bool isSkinned = state.clusterMatrices.size() > 1; if (isSkinned) { // if we're skinned return the entire mesh extents because we can't know for sure our clusters don't move us - return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents); + AABox box = calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents); + avatarLockReleaseIfApplicable(); + return box; } } - if (_geometry->getFBXGeometry().meshes.size() > meshIndex) { // FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding @@ -1443,8 +1447,11 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { // // If we not skinned use the bounds of the subMesh for all it's parts const FBXMesh& mesh = _geometry->getFBXGeometry().meshes.at(meshIndex); - return calculateScaledOffsetExtents(mesh.meshExtents); + AABox box = calculateScaledOffsetExtents(mesh.meshExtents); + avatarLockReleaseIfApplicable(); + return box; } + avatarLockReleaseIfApplicable(); return AABox(); } @@ -1482,6 +1489,9 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran return; } + avatarLockForWriteIfApplicable(); + updateClusterMatrices(); + const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get()); const FBXMesh& mesh = geometry.meshes.at(meshIndex); const MeshState& state = _meshStates.at(meshIndex); @@ -1536,6 +1546,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran _meshGroupsKnown = false; // regenerate these lists next time around. _readyWhenAdded = false; // in case any of our users are using scenes invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid + avatarLockReleaseIfApplicable(); return; // FIXME! } @@ -1543,6 +1554,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { // sanity check + avatarLockReleaseIfApplicable(); return; // FIXME! } @@ -1587,6 +1599,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // guard against partially loaded meshes if (partIndex >= (int)networkMesh._parts.size() || partIndex >= mesh.parts.size()) { + avatarLockReleaseIfApplicable(); return; } @@ -1703,6 +1716,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } + avatarLockReleaseIfApplicable(); } void Model::segregateMeshGroups() { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e55bff6aca..ca291450f7 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -113,6 +113,9 @@ public: bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } virtual void simulate(float deltaTime, bool fullUpdate = true); + void updateClusterMatrices(); + virtual void avatarLockForWriteIfApplicable() {}; + virtual void avatarLockReleaseIfApplicable() {}; /// Returns a reference to the shared geometry. const QSharedPointer& getGeometry() const { return _geometry; }