Sprinkle locks everywhere.

This commit is contained in:
Howard Stearns 2015-08-26 16:08:07 -07:00
parent 0e18395fd0
commit 475331a97d
8 changed files with 45 additions and 4 deletions

View file

@ -318,6 +318,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
}
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
avatarLock.lockForRead();
if (_referential) {
_referential->update();
}
@ -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;
}

View file

@ -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<Avatar>(*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);
}

View file

@ -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<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;

View file

@ -105,6 +105,8 @@ public:
float getHeadClipDistance() const { return _headClipDistance; }
virtual void onInvalidate() override;
virtual void avatarLockForWriteIfApplicable() override;
virtual void avatarLockReleaseIfApplicable() override;
signals:

View file

@ -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();

View file

@ -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();
}
}

View file

@ -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() {

View file

@ -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<NetworkGeometry>& getGeometry() const { return _geometry; }