STORM-163 FIXED Intermittent FPS drop related to "audio" (main thread hangs often on openal lock)

Submitting a patch made by Aleric Inglewood (See VWR-14914).

This bug happens for a lot of people, although it might be needed to have a fast multi core machine.
I have seen it on 1.22.10 once, never used 1.23 sorry, and saw it often on snowglobe. I am sure
it also affects 1.23 but I'd have to test that.

The symptons are that on a viewer with normally a good, high FPS, sometimes it happens
that the FPS dramatically drops (as low as 0.3, but it can also be anything higher, as high
as 10, say).

This particular jira is about a problem where the main thread is slowed down by a mutex lock
in libopenal (most calls starting with 'al' in indra/llaudio/audioengine_openal.cpp and
one in indra/llaudio/listener_openal.cpp). You can see that this is the case by opening the
Frame Console (control-shift-2) and checking that the "audio" (and possibly misc) timings
are very large compared to the Render time.
master
Vadim Savchuk 2010-09-21 19:11:40 +03:00
parent 5304ad2746
commit 5b2d4a1698
8 changed files with 103 additions and 61 deletions

View File

@ -66,6 +66,7 @@ Aleric Inglewood
VWR-13996
VWR-14426
SNOW-766
STORM-163
Ales Beaumont
VWR-9352
SNOW-240

View File

@ -97,6 +97,7 @@ void LLAudioEngine::setDefaults()
}
mMasterGain = 1.f;
mInternalGain = 0.f;
mNextWindUpdate = 0.f;
mStreamingAudioImpl = NULL;
@ -247,15 +248,6 @@ void LLAudioEngine::idle(F32 max_decode_time)
// Primarily does position updating, cleanup of unused audio sources.
// Also does regeneration of the current priority of each audio source.
if (getMuted())
{
setInternalGain(0.f);
}
else
{
setInternalGain(getMasterGain());
}
S32 i;
for (i = 0; i < MAX_BUFFERS; i++)
{
@ -284,6 +276,12 @@ void LLAudioEngine::idle(F32 max_decode_time)
continue;
}
if (sourcep->isMuted())
{
++iter;
continue;
}
if (!sourcep->getChannel() && sourcep->getCurrentBuffer())
{
// We could potentially play this sound if its priority is high enough.
@ -336,9 +334,9 @@ void LLAudioEngine::idle(F32 max_decode_time)
// attached to each channel, since only those with active channels
// can have anything interesting happen with their queue? (Maybe not true)
LLAudioSource *sourcep = iter->second;
if (!sourcep->mQueuedDatap)
if (!sourcep->mQueuedDatap || sourcep->isMuted())
{
// Nothing queued, so we don't care.
// Muted, or nothing queued, so we don't care.
continue;
}
@ -418,6 +416,10 @@ void LLAudioEngine::idle(F32 max_decode_time)
for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
{
LLAudioSource *sourcep = iter->second;
if (sourcep->isMuted())
{
continue;
}
if (sourcep->isSyncMaster())
{
if (sourcep->getPriority() > max_sm_priority)
@ -691,15 +693,23 @@ bool LLAudioEngine::isWindEnabled()
void LLAudioEngine::setMuted(bool muted)
{
mMuted = muted;
if (muted != mMuted)
{
mMuted = muted;
setMasterGain(mMasterGain);
}
enableWind(!mMuted);
}
void LLAudioEngine::setMasterGain(const F32 gain)
{
mMasterGain = gain;
setInternalGain(gain);
F32 internal_gain = getMuted() ? 0.f : gain;
if (internal_gain != mInternalGain)
{
mInternalGain = internal_gain;
setInternalGain(mInternalGain);
}
}
F32 LLAudioEngine::getMasterGain()
@ -1243,13 +1253,14 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32
mOwnerID(owner_id),
mPriority(0.f),
mGain(gain),
mType(type),
mSourceMuted(false),
mAmbient(false),
mLoop(false),
mSyncMaster(false),
mSyncSlave(false),
mQueueSounds(false),
mPlayedOnce(false),
mType(type),
mChannelp(NULL),
mCurrentDatap(NULL),
mQueuedDatap(NULL)
@ -1301,6 +1312,10 @@ void LLAudioSource::updatePriority()
{
mPriority = 1.f;
}
else if (isMuted())
{
mPriority = 0.f;
}
else
{
// Priority is based on distance
@ -1349,25 +1364,33 @@ bool LLAudioSource::setupChannel()
bool LLAudioSource::play(const LLUUID &audio_uuid)
{
// Special abuse of play(); don't play a sound, but kill it.
if (audio_uuid.isNull())
{
if (getChannel())
{
getChannel()->setSource(NULL);
setChannel(NULL);
addAudioData(NULL, true);
if (!isMuted())
{
mCurrentDatap = NULL;
}
}
return false;
}
// Reset our age timeout if someone attempts to play the source.
mAgeTimer.reset();
LLAudioData *adp = gAudiop->getAudioData(audio_uuid);
bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid);
addAudioData(adp);
if (isMuted())
{
return false;
}
bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid);
if (!has_buffer)
{
// Don't bother trying to set up a channel or anything, we don't have an audio buffer.
@ -1392,10 +1415,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
}
bool LLAudioSource::isDone()
bool LLAudioSource::isDone() const
{
const F32 MAX_AGE = 60.f;
const F32 MAX_UNPLAYED_AGE = 15.f;
const F32 MAX_MUTED_AGE = 11.f;
if (isLoop())
{
@ -1403,7 +1427,6 @@ bool LLAudioSource::isDone()
return false;
}
if (hasPendingPreloads())
{
return false;
@ -1420,10 +1443,10 @@ bool LLAudioSource::isDone()
// This is a single-play source
if (!mChannelp)
{
if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
if ((elapsed > (mSourceMuted ? MAX_MUTED_AGE : MAX_UNPLAYED_AGE)) || mPlayedOnce)
{
// We don't have a channel assigned, and it's been
// over 5 seconds since we tried to play it. Don't bother.
// over 15 seconds since we tried to play it. Don't bother.
//llinfos << "No channel assigned, source is done" << llendl;
return true;
}
@ -1449,7 +1472,7 @@ bool LLAudioSource::isDone()
if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
{
// The sound isn't playing back after 5 seconds or we're already done playing it, kill it.
// The sound isn't playing back after 15 seconds or we're already done playing it, kill it.
return true;
}

View File

@ -118,8 +118,8 @@ public:
// Use these for temporarily muting the audio system.
// Does not change buffers, initialization, etc. but
// stops playing new sounds.
virtual void setMuted(bool muted);
virtual bool getMuted() const { return mMuted; }
void setMuted(bool muted);
bool getMuted() const { return mMuted; }
#ifdef USE_PLUGIN_MEDIA
LLPluginClassMedia* initializeMedia(const std::string& media_type);
#endif
@ -239,6 +239,7 @@ protected:
LLAudioBuffer *mBuffers[MAX_BUFFERS];
F32 mMasterGain;
F32 mInternalGain; // Actual gain set; either mMasterGain or 0 when mMuted is true.
F32 mSecondaryGain[AUDIO_TYPE_COUNT];
F32 mNextWindUpdate;
@ -303,7 +304,8 @@ public:
virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); }
const LLUUID &getID() const { return mID; }
bool isDone();
bool isDone() const;
bool isMuted() const { return mSourceMuted; }
LLAudioData *getCurrentData();
LLAudioData *getQueuedData();
@ -325,6 +327,7 @@ protected:
LLUUID mOwnerID; // owner of the object playing the sound
F32 mPriority;
F32 mGain;
bool mSourceMuted;
bool mAmbient;
bool mLoop;
bool mSyncMaster;

View File

@ -35,11 +35,8 @@
LLAudioSourceVO::LLAudioSourceVO(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, LLViewerObject *objectp)
: LLAudioSource(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX),
mObjectp(objectp),
mActualGain(gain)
mObjectp(objectp)
{
setAmbient(FALSE);
updateGain();
update();
}
@ -54,18 +51,18 @@ LLAudioSourceVO::~LLAudioSourceVO()
void LLAudioSourceVO::setGain(const F32 gain)
{
mActualGain = llclamp(gain, 0.f, 1.f);
updateGain();
mGain = llclamp(gain, 0.f, 1.f);
}
void LLAudioSourceVO::updateGain()
void LLAudioSourceVO::updateMute()
{
if (!mObjectp)
if (!mObjectp || mObjectp->isDead())
{
mSourceMuted = true;
return;
}
BOOL mute = FALSE;
bool mute = false;
LLVector3d pos_global;
if (mObjectp->isAttachment())
@ -84,21 +81,21 @@ void LLAudioSourceVO::updateGain()
{
pos_global = mObjectp->getPositionGlobal();
}
if (!LLViewerParcelMgr::getInstance()->canHearSound(pos_global))
{
mute = TRUE;
mute = true;
}
if (!mute)
{
if (LLMuteList::getInstance()->isMuted(mObjectp->getID()))
{
mute = TRUE;
mute = true;
}
else if (LLMuteList::getInstance()->isMuted(mOwnerID, LLMute::flagObjectSounds))
{
mute = TRUE;
mute = true;
}
else if (mObjectp->isAttachment())
{
@ -110,24 +107,38 @@ void LLAudioSourceVO::updateGain()
if (parent
&& LLMuteList::getInstance()->isMuted(parent->getID()))
{
mute = TRUE;
mute = true;
}
}
}
if (!mute)
if (mute != mSourceMuted)
{
mGain = mActualGain;
}
else
{
mGain = 0.f;
mSourceMuted = mute;
if (mSourceMuted)
{
// Stop the sound.
this->play(LLUUID::null);
}
else
{
// Muted sounds keep there data at all times, because
// it's the place where the audio UUID is stored.
// However, it's possible that mCurrentDatap is
// NULL when this source did only preload sounds.
if (mCurrentDatap)
{
// Restart the sound.
this->play(mCurrentDatap->getID());
}
}
}
}
void LLAudioSourceVO::update()
{
updateMute();
if (!mObjectp)
{
return;
@ -139,7 +150,11 @@ void LLAudioSourceVO::update()
return;
}
updateGain();
if (mSourceMuted)
{
return;
}
if (mObjectp->isHUDAttachment())
{
mPositionGlobal = gAgentCamera.getCameraPositionGlobal();

View File

@ -42,11 +42,10 @@ public:
/*virtual*/ void setGain(const F32 gain);
private:
void updateGain();
void updateMute();
private:
LLPointer<LLViewerObject> mObjectp;
F32 mActualGain; // The "real" gain, when not off due to parcel effects
};
#endif // LL_LLAUDIOSOURCEVO_H

View File

@ -114,10 +114,6 @@ void audio_update_volume(bool force_update)
gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
#ifdef kAUDIO_ENABLE_WIND
gAudiop->enableWind(!mute_audio);
#endif
gAudiop->setMuted(mute_audio);
if (force_update)

View File

@ -4213,13 +4213,11 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data)
// Don't play sounds from a region with maturity above current agent maturity
LLVector3d pos_global = objectp->getPositionGlobal();
if( !gAgent.canAccessMaturityAtGlobal( pos_global ) )
if (gAgent.canAccessMaturityAtGlobal(pos_global))
{
return;
// Add audioData starts a transfer internally.
sourcep->addAudioData(datap, FALSE);
}
// Add audioData starts a transfer internally.
sourcep->addAudioData(datap, FALSE);
}
void process_attached_sound(LLMessageSystem *msg, void **user_data)

View File

@ -4445,6 +4445,13 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
mAudioSourcep = NULL;
}
if (mAudioSourcep && mAudioSourcep->isMuted() &&
mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid)
{
//llinfos << "Already having this sound as muted sound, ignoring" << llendl;
return;
}
getAudioSource(owner_id);
if (mAudioSourcep)