summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike <contact@mikelittman.me>2026-10-22 12:20:17 -0400
committerGitHub <noreply@github.com>2026-10-23 00:20:17 +0800
commit5b52af0bf830de6732bc587f5932c0209f6c337a (patch)
treeb9708b676d7d790951391abc24d289955834cc2e
parent32721d1421819fcd8ca0776421e147d59dad60ab (diff)
Fix remaining Apple audio, depth, and speaking-indicator crashes (#39)
Stop the OpenAL wind path from spinning when unqueue fails. Allocate Apple depth buffers with the unsized format and skip deferred lighting when that allocation left the target empty. Remove every registration of a speaking indicator, including a null one.
-rw-r--r--indra/llaudio/llaudioengine_openal.cpp17
-rw-r--r--indra/llrender/llrendertarget.cpp32
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp25
-rw-r--r--indra/newview/pipeline.cpp7
4 files changed, 62 insertions, 19 deletions
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
index 4126c8ef80..b65e9c518f 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -500,6 +500,7 @@ bool LLAudioEngine_OpenAL::initWind()
if((error=alGetError()) != AL_NO_ERROR)
{
LL_WARNS() << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<LL_ENDL;
+ mWindSource = AL_NONE;
}
mWindGen = new LLWindGen<WIND_SAMPLE_T>;
@@ -564,6 +565,9 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
if(!mWindBuf)
return;
+ if (mWindSource == AL_NONE)
+ return;
+
if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
{
@@ -589,7 +593,7 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
// ok lets make a wind buffer now
- ALint processed, queued, unprocessed;
+ ALint processed = 0, queued = 0, unprocessed = 0;
alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued);
unprocessed = queued - processed;
@@ -601,7 +605,7 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
//LL_INFOS() << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << LL_ENDL;
- while(processed--) // unqueue old buffers
+ while (processed > 0) // unqueue old buffers
{
ALuint buffer;
ALenum error;
@@ -610,12 +614,11 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
error = alGetError();
if(error != AL_NO_ERROR)
{
- LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << LL_ENDL;
- }
- else
- {
- alDeleteBuffers(1, &buffer);
+ LL_WARNS() << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers: " << error << LL_ENDL;
+ break;
}
+ alDeleteBuffers(1, &buffer);
+ --processed;
}
unprocessed += mNumEmptyWindALBuffers;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index dcee340a71..0745397c3a 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -370,21 +370,39 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
bool LLRenderTarget::allocateDepth()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ if (mResX == 0 || mResY == 0)
+ {
+ LL_WARNS() << "Unable to allocate depth buffer for render target " << mName
+ << ": size " << mResX << "x" << mResY << LL_ENDL;
+ return false;
+ }
+
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
- LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-
- sBytesAllocated += mResX*mResY*4;
-
- if (glGetError() != GL_NO_ERROR)
+ // Apple's GL rejects the sized GL_DEPTH_COMPONENT24 internal format
+ // with GL_UNSIGNED_INT. The unsized format is the one it allocates.
+#if LL_DARWIN
+ const U32 depth_internal = GL_DEPTH_COMPONENT;
+#else
+ const U32 depth_internal = GL_DEPTH_COMPONENT24;
+#endif
+ glGetError();
+ LLImageGL::setManualImage(internal_type, 0, depth_internal, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR)
{
- LL_WARNS() << "Unable to allocate depth buffer for render target " << mName << LL_ENDL;
+ LL_WARNS() << "Unable to allocate depth buffer for render target " << mName
+ << " (" << mResX << "x" << mResY << ") gl error " << err << LL_ENDL;
return false;
}
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ glGetError();
+
+ sBytesAllocated += mResX*mResY*4;
+
return true;
}
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index aa3eaba21d..70d8d64ae0 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -147,6 +147,10 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i
LL_DEBUGS("SpeakingIndicator") << "Registering indicator: " << speaker_id << "|"<< speaking_indicator << ", session: " << session_id << LL_ENDL;
+ if (!speaking_indicator)
+ {
+ return;
+ }
ensureInstanceDoesNotExist(speaking_indicator);
@@ -167,15 +171,20 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i
void SpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator)
{
LL_DEBUGS("SpeakingIndicator") << "Unregistering indicator: " << speaker_id << "|"<< speaking_indicator << LL_ENDL;
- speaking_indicators_mmap_t::iterator it;
- it = mSpeakingIndicators.find(speaker_id);
- for (;it != mSpeakingIndicators.end(); ++it)
+ // The same control can be registered under more than one speaker id.
+ // Removing only the current id leaves a dangling pointer that crashes
+ // the next time that speaker's indicators are switched. See EXT-4782.
+ speaking_indicators_mmap_t::iterator it = mSpeakingIndicators.begin();
+ while (it != mSpeakingIndicators.end())
{
if (it->second == speaking_indicator)
{
LL_DEBUGS("SpeakingIndicator") << "Unregistered." << LL_ENDL;
- mSpeakingIndicators.erase(it);
- break;
+ it = mSpeakingIndicators.erase(it);
+ }
+ else
+ {
+ ++it;
}
}
}
@@ -253,6 +262,10 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea
{
was_found = true;
LLSpeakingIndicator* indicator = (*it_indicator).second;
+ if (!indicator)
+ {
+ continue;
+ }
was_switched_on = was_switched_on || switch_on;
if (indicator) indicator->switchIndicator(switch_on);
@@ -279,6 +292,8 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea
void SpeakingIndicatorManager::ensureInstanceDoesNotExist(LLSpeakingIndicator* const speaking_indicator)
{
LL_DEBUGS("SpeakingIndicator") << "Searching for an registered indicator instance: " << speaking_indicator << LL_ENDL;
+ // The same LLOutputMonitorCtrl can be registered under several speaker ids.
+ // Every copy has to be removed before it is registered again. See EXT-4782.
speaking_indicators_mmap_t::iterator it = mSpeakingIndicators.begin();
while (it != mSpeakingIndicators.end())
{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bccff55a2c..2b45892ff4 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8906,6 +8906,13 @@ void LLPipeline::renderDeferredLighting()
LLRenderTarget *screen_target = &mRT->screen;
LLRenderTarget* deferred_light_target = &mRT->deferredLight;
+ // A failed depth allocation leaves these targets with no textures.
+ // Binding them logs the empty-target warnings and then faults in the GL driver.
+ if (screen_target->getNumTextures() == 0)
+ {
+ return;
+ }
+
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("deferred");
LLViewerCamera *camera = LLViewerCamera::getInstance();