Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[XAudio2] GC causing audio glitches #7000

Open
Jure-BB opened this issue Jan 24, 2020 · 12 comments
Open

[XAudio2] GC causing audio glitches #7000

Jure-BB opened this issue Jan 24, 2020 · 12 comments

Comments

@Jure-BB
Copy link
Contributor

Jure-BB commented Jan 24, 2020

I have noticed that audio playback is sometimes glitching in a WindowsDX mode. It seems that GC is blocking XAudio2 thread. Which is a problem, if there is any audio playing during level loading or screen transitions when a new content is being loaded and a new objects are being created.

I have narrowed the problem down to SharpDX wrapper. I have also tried the new Vortice wrapper, but it also glitches. Both are using SharpGenTools so this may be the source of the issue. I couldn't test this more as I can't get SharpGenTools to run under VS2019. I did create a simple custom wrapper that shows XAudio2 can run with managed wrapper without being affected by GC.
The source for all tests is here: https://github.com/Jure-BB/XAudio2_GlitchTest

What would be the preferred way to fix this issue in MonoGame? Fixing the discontinued SharpDX or fixing and the new Vortice wrapper and replacing SharpDX in MG or creating a custom wrapper just for the specific XAudio2 features that MonoGame needs?

UPDATE: This is caused because MG/SharpDX registers for callbacks in XAudio engine. Check this post for details.

@amerkoleci
Copy link

Where are the issues? I can fix it in my vortice project

@Jure-BB
Copy link
Contributor Author

Jure-BB commented Jan 24, 2020

@amerkoleci I don't know what specifically is causing this, but you can try the test project: https://github.com/Jure-BB/XAudio2_GlitchTest

Just change the startup project to VorticeTest and run it. After some garbage objects are initialized it will output the number of glitches that happened in XAudio2.

@amerkoleci
Copy link

So it has nothing to do with vortice or sharpdx, probably net GC holding main thread busy

@Jure-BB
Copy link
Contributor Author

Jure-BB commented Jan 24, 2020

@amerkoleci It has to do with the way Vortice and SharpDX initialize and interact with XAudio2 engine.

Try pressing H to run full blocking garbage collection in VorticeTest project and in NativeWrapperTest. In VorticeTest audio playback will be blocked during blocking GC, while in NativeWrapperTest audio playback won't be blocked. (NativeWrapperTest is a C# project)

@Jure-BB
Copy link
Contributor Author

Jure-BB commented Jan 24, 2020

XAudio2 engine creates it's own native thread for audio which should not be blocked by GC. However, in the case of SharpDX and Vortice it is blocked.

@amerkoleci
Copy link

Open issue in my project i will try to fix it

@amerkoleci
Copy link

Issue seams that by default i register callback to xaudio engine using RegisterForCallback, same with SharpDX

@Jure-BB
Copy link
Contributor Author

Jure-BB commented Jan 25, 2020

I finally managed to build SharpDX from source (a single space in the project path was causing build errors). I can confirm that the issue is caused by callbacks, like @amerkoleci suggested.

SharpDX registers for two callbacks with XAudio2 engine:

MG is making a real use of XAudio callbacks only in one place. For OnBufferEnd in DynamicSoundEffectInstance. However, MG still registers for all callbacks even, if it's not using them.

@amerkoleci
Copy link

Its necessary to understand if SharpGen leaks when using callback base or if XAudio2 has this issue when registering for callback

@amerkoleci
Copy link

amerkoleci commented Jan 25, 2020

The audio processing thread is stalling because the client's implementation of some XAudio2 callback is doing things that can block the thread. For example, it might be accessing the disk, synchronizing with other threads, or calling other functions that may block. Use a lower-priority background thread that the callback can signal to perform such tasks.

From here: https://docs.microsoft.com/en-us/windows/win32/xaudio2/debugging-audio-glitches-in-xaudio2

@Jure-BB
Copy link
Contributor Author

Jure-BB commented Jan 25, 2020

GC probably locks access to the shared callback object or suspends the audio thread as it calls back to the managed code.

@Jure-BB
Copy link
Contributor Author

Jure-BB commented Jan 26, 2020

I added a XAudio2 callback test to my custom wrapper. GC is not blocking the audio thread in that test. This shows callbacks can implemented without affecting audio performance.
https://github.com/Jure-BB/XAudio2_GlitchTest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants