mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
wasapi: address buffer overflow when using -wasapishared (#758)
## Link to GitHub Issue or related Pull Request, if one exists Building on #745 ## Description of change With `-wasapishared`, some users see `AUDCLNT_E_BUFFER_TOO_LARGE` (`0x88890006`). The existing one-device-period buffer clamp wasn't enough on endpoints with a small shared buffer; the shared buffer is double-buffered, so a full-buffer write often exceeds the free space. ### Fix Added a FIFO bridge to `SharedRedirect` that decouples the game's per-event writes from the shared engine's clock: - **`GetBuffer`** hands the game a pointer into the FIFO tail to write in place. - **`ReleaseBuffer`** commits the write and drains `min(pending, device_free)` frames to the device - so a write can never exceed what the device accepts, structurally preventing the overflow on any endpoint. - **`GetCurrentPadding`** reports the FIFO fill level (capped to the reported buffer size) so poll/timer-driven games pace correctly against the virtual buffer. ## Testing
This commit is contained in:
@@ -295,6 +295,13 @@ HRESULT STDMETHODCALLTYPE WrappedIAudioClient::Initialize(
|
||||
copy_wave_format(&hooks::audio::FORMAT, device_format);
|
||||
copy_wave_format(&this->device_format, device_format);
|
||||
|
||||
// arm the shared-mode buffer bridge so the redirected game's full-buffer writes are paced to
|
||||
// the device instead of overflowing the shared buffer (AUDCLNT_E_BUFFER_TOO_LARGE).
|
||||
if (this->shared.redirected_from_exclusive) {
|
||||
this->shared.enable_bridge(
|
||||
device_format->nChannels * (device_format->wBitsPerSample / 8));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIAudioClient::GetBufferSize(UINT32 *pNumBufferFrames) {
|
||||
@@ -379,6 +386,12 @@ HRESULT STDMETHODCALLTYPE WrappedIAudioClient::GetCurrentPadding(UINT32 *pNumPad
|
||||
*pNumPaddingFrames = this->resample.padding_device_to_game(*pNumPaddingFrames);
|
||||
}
|
||||
|
||||
// shared-mode bridge: the game writes into a FIFO, not the device buffer, so report the FIFO's
|
||||
// fill level rather than the device's padding (which is in a different buffer space).
|
||||
if (SUCCEEDED(ret) && this->shared.bridge_enabled() && pNumPaddingFrames) {
|
||||
*pNumPaddingFrames = this->shared.virtual_padding();
|
||||
}
|
||||
|
||||
CHECK_RESULT(ret);
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE WrappedIAudioClient::IsFormatSupported(
|
||||
|
||||
Reference in New Issue
Block a user