Every 4.11.674 player log is saturated with acquisition failures -- 3031, 4657, 5245, 6275, 6571 across five machines. In Lynx's largest session the first failure lands 9.3% in and they continue to 96.8%: once it starts it never recovers for the rest of the match. CAUSE: RequestAudioChannels called alGenSources() per sound event and ReleaseSourceSet called alDeleteSources() on release -- create and destroy per sound. OpenAL sources are a scarce driver resource (OpenAL Soft caps a context at 256) and a combat burst churned straight through the ceiling. The two counters looked contradictory and were the tell: ACQUIRE FAILED always printed live=256 while the 30s census printed live=6. Same global, sampled at different moments -- sources spike to the cap during a burst and drain back between them. Churn, not a steady leak. FIX: generate sources once, up to a cap, and recycle them through a free list. Release scrubs and parks instead of deleting. Steady-state play performs no AL allocation at all. The scrub is load-bearing, not hygiene: a recycled source carries whatever the previous owner set, and the engine sets AL_LOOPING per sound (L4AUDLVL.cpp:327). Hand a looping source to a one-shot and it plays forever -- which is the "sound stuck looping" family (#51, #5). Every reusable property is reset at the single point where a source changes owner. VERIFIED (scratchpad/night8/audiopool.sh + the two-node mp_burst.sh): solo, sustained fire : 0 failures, pooled 152, reuses 21998 two nodes, 4 min : 0 failures on both, pooled 148/149, reuses ~7000 each ⚠ HONEST LIMIT: the bench does NOT reproduce the field failure -- the PRE-fix binary also scores 0 on it (peak 49 live), because solo/2-node combat is not dense enough to reach 256. So this verifies the pool works and allocates nothing in steady state; it does NOT by itself prove the field failures are gone. The five field logs remain the "before". Peak demand is set by how many audio COMPONENTS are alive (each reserves a SourceSet of up to 25 voices and holds them), not by audible sounds: measured high-water 138 solo, 149 two-node. That scales with player count, so the cap is set near the driver ceiling (240) and the pool now logs its high-water mark once per 25-source band -- so the next playtest sizes this from field data instead of a guess. Growth also self-limits: if a driver offers fewer sources than the cap, alGenSources simply fails, growth stops, and the pool recycles what it has. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
42 lines
1.4 KiB
Bash
42 lines
1.4 KiB
Bash
#!/usr/bin/env bash
|
|
# #32 AUDIO SOURCE POOL verification.
|
|
#
|
|
# BEFORE: sources were alGenSources'd per sound event and alDeleteSources'd on
|
|
# release. Every 4.11.674 player log shows thousands of ACQUIRE FAILED lines
|
|
# (3031-6571 across five machines), first failure ~10% into the match, still
|
|
# failing at 97% -- combat bursts churned through OpenAL's 256-source context
|
|
# limit.
|
|
#
|
|
# AFTER: sources are generated once and recycled. This run reproduces the
|
|
# failure mode -- sustained combat, all weapon groups firing, missiles, deaths
|
|
# and explosions -- and reads the census.
|
|
#
|
|
# PASS:
|
|
# * ACQUIRE FAILED lines == 0
|
|
# * census `pooled` settles well under the 200 cap (steady-state demand)
|
|
# * census `reuses` climbs into the thousands (recycling is doing the work)
|
|
set -x
|
|
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
|
cd /c/git/bt411/content || exit 1
|
|
taskkill //F //IM btl4.exe > /dev/null 2>&1
|
|
sleep 2
|
|
sed "s/^map=.*/map=grass/; s/^time=.*/time=day/" MP.EGG > AUD.EGG
|
|
|
|
LOG=audiopool_${1:-post}.log
|
|
rm -f "$LOG"
|
|
|
|
BT_DMG_LOG=1 \
|
|
BT_SPAWN_ENEMY=1 BT_GOTO=enemy BT_GOTO_STOP=2 \
|
|
BT_AUTOFIRE=1 BT_AF_MISSILE=1 BT_AF_PERIOD=1 \
|
|
bt_launch "$LOG" AUD.EGG 0x03
|
|
|
|
sleep 200
|
|
taskkill //F //IM btl4.exe > /dev/null 2>&1
|
|
sleep 2
|
|
|
|
echo "=== ACQUIRE FAILED (want 0) ==="
|
|
grep -c "ACQUIRE FAILED" "$LOG"
|
|
echo "=== census progression ==="
|
|
grep -oE "\[audio\] source census:.*" "$LOG" | head -3
|
|
grep -oE "\[audio\] source census:.*" "$LOG" | tail -3
|