perf(streaming): quiesce retired generations and budget teardown
Publish the retail blocking-for-cells edge before deferred recenter work, freeze old-world presentation/simulation/audio, and advance full-window retirement from exact metered entity and owner cursors. This removes synchronous portal teardown without allowing retained owners to remain observable.
This commit is contained in:
parent
b8f6317fe1
commit
bb16f74fd4
38 changed files with 1691 additions and 170 deletions
|
|
@ -122,7 +122,14 @@ public sealed class AudioHookSink : IAnimationHookSink
|
|||
if (waveId == 0) return;
|
||||
WaveData? wave = _cache.GetWave(waveId);
|
||||
if (wave is null) return;
|
||||
_engine.Play3DWave(waveId, wave, worldPos, volume, priority, pitch);
|
||||
_engine.Play3DWave(
|
||||
entityId,
|
||||
waveId,
|
||||
wave,
|
||||
worldPos,
|
||||
volume,
|
||||
priority,
|
||||
pitch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,13 @@ namespace AcDream.App.Audio;
|
|||
/// unaffected.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public sealed unsafe class OpenAlAudioEngine : IAudioEngine
|
||||
internal interface IWorldAudioQuiescence
|
||||
{
|
||||
void SuspendWorldAudio();
|
||||
void ResumeWorldAudio();
|
||||
}
|
||||
|
||||
public sealed unsafe class OpenAlAudioEngine : IAudioEngine, IWorldAudioQuiescence
|
||||
{
|
||||
// ── Backends ─────────────────────────────────────────────────────────────
|
||||
private AL? _al;
|
||||
|
|
@ -71,12 +77,14 @@ public sealed unsafe class OpenAlAudioEngine : IAudioEngine
|
|||
private sealed class Slot3D
|
||||
{
|
||||
public uint SourceId;
|
||||
public uint OwnerId;
|
||||
public float PlayingGain; // gain at play time (for eviction compare)
|
||||
public bool InUse;
|
||||
public uint PriorityBase; // raw priority from SoundEntry.Priority
|
||||
}
|
||||
private readonly Slot3D[] _pool3D = new Slot3D[PoolSize3D];
|
||||
private int _pool3DCursor; // round-robin start
|
||||
private bool _worldAudioSuspended;
|
||||
|
||||
private readonly uint[] _poolUi = new uint[PoolSizeUi];
|
||||
|
||||
|
|
@ -238,6 +246,7 @@ public sealed unsafe class OpenAlAudioEngine : IAudioEngine
|
|||
/// Returns true on success, false if the buffer was rejected.
|
||||
/// </summary>
|
||||
public bool Play3DWave(
|
||||
uint ownerId,
|
||||
uint waveId,
|
||||
WaveData wave,
|
||||
Vector3 position,
|
||||
|
|
@ -245,7 +254,7 @@ public sealed unsafe class OpenAlAudioEngine : IAudioEngine
|
|||
float priority,
|
||||
float pitch = 1.0f)
|
||||
{
|
||||
if (!_available || _al is null) return false;
|
||||
if (_worldAudioSuspended || !_available || _al is null) return false;
|
||||
|
||||
float effectiveGain = volume * SfxVolume;
|
||||
if (effectiveGain < 0.001f) return false; // silent; skip
|
||||
|
|
@ -284,11 +293,39 @@ public sealed unsafe class OpenAlAudioEngine : IAudioEngine
|
|||
|
||||
slot.PlayingGain = effectiveGain;
|
||||
slot.InUse = true;
|
||||
slot.OwnerId = ownerId;
|
||||
slot.PriorityBase = (uint)Math.Clamp((int)priority, 0, 7);
|
||||
_pool3DCursor = (slotIdx + 1) & (PoolSize3D - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops every world-space voice while preserving the independent UI
|
||||
/// source pool. Retail suppresses ambient/object audio while cell loading
|
||||
/// blocks world maintenance; stopped voices are not resumed afterward.
|
||||
/// </summary>
|
||||
public void SuspendWorldAudio()
|
||||
{
|
||||
_worldAudioSuspended = true;
|
||||
for (int i = 0; i < _pool3D.Length; i++)
|
||||
StopWorldSlot(_pool3D[i]);
|
||||
}
|
||||
|
||||
public void ResumeWorldAudio() => _worldAudioSuspended = false;
|
||||
|
||||
internal void StopAllForOwner(uint ownerId)
|
||||
{
|
||||
if (ownerId == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < _pool3D.Length; i++)
|
||||
{
|
||||
Slot3D slot = _pool3D[i];
|
||||
if (slot.InUse && slot.OwnerId == ownerId)
|
||||
StopWorldSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play a raw WaveData blob as a 2D UI sound (no falloff, ignores
|
||||
/// listener position).
|
||||
|
|
@ -469,4 +506,18 @@ public sealed unsafe class OpenAlAudioEngine : IAudioEngine
|
|||
_al.GetSourceProperty(sourceId, GetSourceInteger.SourceState, out int state);
|
||||
return state == (int)SourceState.Playing;
|
||||
}
|
||||
|
||||
private void StopWorldSlot(Slot3D slot)
|
||||
{
|
||||
if (_available && _al is not null && slot.SourceId != 0)
|
||||
{
|
||||
_al.SourceStop(slot.SourceId);
|
||||
_al.SetSourceProperty(slot.SourceId, SourceInteger.Buffer, 0);
|
||||
}
|
||||
|
||||
slot.OwnerId = 0;
|
||||
slot.PlayingGain = 0f;
|
||||
slot.PriorityBase = 0;
|
||||
slot.InUse = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue