Audio: Pin UI sounds in memory and preload UISndNewIncomingIMSession to prevent frame hitching - #6264
Open
Shadowolf7 wants to merge 2 commits into
Open
Shadowolf7 wants to merge 2 commits into
Shadowolf7 wants to merge 2 commits into
Conversation
…to prevent frame hitching - In LLAudioEngine, audio buffers were subject to aggressive purging in idle() after 30 seconds of inactivity, and to LRU reclamation in getFreeBuffer(). - Preloaded UI sounds that hadn't fired recently had their decoded audio buffers deleted from memory. When a notification arrived (e.g. object IM or chat alert), LLAudioSource::play() was forced to synchronously read and parse the WAV file from disk on the main thread via loadWAV(), causing noticeable frame hitches. - Furthermore, UISndNewIncomingIMSession was never preloaded in init_audio(), meaning incoming object IM sessions always incurred full on-demand asset decode and disk I/O. - Increase LL_MAX_AUDIO_BUFFERS from 40 to 80 to guarantee headroom for pinned UI sounds alongside the 30 audio channels. - Add pinned buffer tracking (mPinned) to LLAudioData and LLAudioBuffer to exempt UI sounds from 30s stale purging and LRU reuse. - Ensure preloadSound() immediately loads decoded WAV data into a buffer if available on disk and marks it pinned. - In tryFinishAudio(), if an audio asset is pinned, immediately load it into a pinned buffer upon decode completion. - In LLAudioSource::play(), dynamically pin buffers for AUDIO_TYPE_UI. - In init_audio(), preload UISndNewIncomingIMSession and UISndChatPing, pinning all UI sounds into memory.
…to preloaded UI sounds - Change preloadSound() default parameter pin_buffer from true to false to prevent inventory sound previews and decode retries from unintentionally pinning buffers into RAM. - Remove dynamic UI pinning from LLAudioSource::play(); active playback is already protected from idle eviction and LRU reclamation by mInUse, and fixed UI sounds are preloaded with pin_buffer = true in init_audio(). - Preserve mPinned state on decode reload retry in LLAudioData::load().
Contributor
There was a problem hiding this comment.
Pull request overview
This PR targets notification-related frame hitches by ensuring key UI sounds are preloaded and kept resident in audio buffers, preventing on-demand synchronous disk I/O and buffer eviction from impacting frame time.
Changes:
- Add “pinned” state to
LLAudioData/LLAudioBufferand exempt pinned buffers from idle purge and LRU reclamation. - Extend
preloadSound()to optionally pin and eagerly load an existing decoded sound into an in-memory buffer. - Preload and pin additional UI sounds at startup, and increase the max audio buffer pool size to provide headroom.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| indra/newview/llvieweraudio.cpp | Pins startup-preloaded UI sounds and adds missing UI notification sounds to the preload list. |
| indra/llaudio/llaudioengine.h | Introduces pin APIs/state and extends preloadSound() signature to support pinning. |
| indra/llaudio/llaudioengine.cpp | Prevents eviction of pinned buffers and adds eager-load + pin behavior to preloadSound() / LLAudioData::load(). |
| indra/llaudio/llaudiodecodemgr.cpp | Loads pinned decoded assets into memory immediately on decode completion. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+761
to
+765
| adp->load(); | ||
| if (adp->getBuffer()) | ||
| { | ||
| adp->getBuffer()->setPinned(true); | ||
| } |
Comment on lines
+661
to
+665
| adp->load(); | ||
| if (adp->getBuffer() && pin_buffer) | ||
| { | ||
| adp->getBuffer()->setPinned(true); | ||
| } |
| void triggerSound(SoundData& soundData); | ||
|
|
||
| bool preloadSound(const LLUUID &id); | ||
| bool preloadSound(const LLUUID &id, bool pin_buffer = false); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR fixes noticeable frame hitches/freezes that occur when receiving notifications (especially incoming direct messages from objects or users with sound).
Root Causes
UISndNewIncomingIMSession(the notification sound played when a new IM session begins, such as from scripted objects or users) was never included ininit_audio()'s preloaded sound list. When a notification arrived, the viewer initiated an on-demand decode and disk write.LLAudioEngine::idle(), any audio buffer not actively playing withmLastUseTimer > 30.0fwas unconditionally flushed and deleted from memory (mAudioDatap->mBufferp = NULL). Even sounds that were preloaded at startup were wiped within 30 seconds of quiet time.LLAudioSource::play()was invoked for a notification sound whose buffer had been evicted (or never loaded),LLAudioData::load()calledmBufferp->loadWAV()synchronously on the main thread, blocking the frame while opening, reading, and parsing the WAV file from disk.LLAudioEngine::getFreeBuffer(), buffers could be reclaimed if all were allocated, evicting preloaded UI sounds.Solution
mPinnedflag toLLAudioDataandLLAudioBuffer(withsetPinned()/isPinned()).LLAudioEngine::idle()and from LRU reclamation inLLAudioEngine::getFreeBuffer().LLAudioSource::play(), ifmType == LLAudioEngine::AUDIO_TYPE_UI, dynamically pin the audio data and buffer.LLAudioEngine::preloadSound(uuid, pin_buffer = true):mBufferpand pin it.tryFinishAudio()(llaudiodecodemgr.cpp): If the decoded audio asset is pinned, immediately load it into memory on decode completion so future plays are zero-latency.init_audio()(llvieweraudio.cpp), addedUISndNewIncomingIMSessionandUISndChatPingto the preloaded sound list withpin_buffer = true.LL_MAX_AUDIO_BUFFERSfrom 40 to 80 (providing headroom for pinned UI sounds alongside the 30 audio channels).Related Issues
Checklist
Additional Notes
Tested locally with incoming object IMs, notification alerts, and repeated sound playback. Frame times remain smooth when notifications arrive without any disk-read hitching.