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

WASAPI code improvements #8316

Merged
merged 9 commits into from
Mar 11, 2021

Conversation

CookiePLMonster
Copy link
Contributor

This PR brings numerous improvements to WASAPI code in Dolphin, improving code readability as well as fixing numerous issues.

As a preparation, WIL has been added, since it's very useful for ensuring proper RAII-based destruction for several WinAPI types - in my case it was proper scoped calls to CoUninitialize and proper destruction of previously leaking (in some cases) PROPVARIANT.

All COM objects have been moved to use WRL, which ensures their proper release. Previously, there were numerous code paths where functions would return without cleaning up their COM objects, effectively leaking references.

device->GetId(&device_id); was present in several places, never using the return value nor freeing it - leaking memory for no reason.

Thread synchronization model for WASAPI Handler thread has been simplified by not detaching said thread. Not only it improved code readability, but also fixed a spinlock occuring if WASAPIStream::SetRunning(true) failed in any way - a following call to WASAPIStream::SetRunning(false) would then spin endlessly checking for m_stopped. Now this boolean is gone, and so is the problem.

std::string_view is now used where applicable. I opted for constructing a std::string out of std::string_view in HandleWinAPI, because it happens in code path which is taken relatively rarely - in a perfect case it's never taken.

I modified SoundLoop not to do volume adjustment unless absolutely necessary, saving on a relatively costly loop. For 100% volume, volume adjustment is not needed, and for 0% volume a AUDCLNT_BUFFERFLAGS_SILENT is now specified instead of zeroing the buffer. I also removed several nullptr checks which were not thread safe anyway, so only brought a false sense of safety.

@CookiePLMonster
Copy link
Contributor Author

Build fails because VS2017 on the build server is too old. Seems to be the same error as reported here:
microsoft/wil#25

Apparently it can be worked around by defining __WI_LIBCPP_HAS_NO_IS_AGGREGATE, but I guess upgrading VS2017 on the build server (if possible) is better?

Source/Core/AudioCommon/WASAPIStream.cpp Outdated Show resolved Hide resolved
Source/Core/AudioCommon/WASAPIStream.cpp Outdated Show resolved Hide resolved
@lioncash
Copy link
Member

The AudioCommon CMakeLists file should also be modified to handle the use of WIL.

@CookiePLMonster
Copy link
Contributor Author

The AudioCommon CMakeLists file should also be modified to handle the use of WIL.

I normally steer clear of CMake, so will

target_compile_definitions(audiocommon PRIVATE WIL_SUPPRESS_EXCEPTIONS)

be valid syntax? The other part about adding WIL\include to include paths seems easy enough.

Source/Core/AudioCommon/WASAPIStream.cpp Show resolved Hide resolved
Source/Core/AudioCommon/WASAPIStream.cpp Outdated Show resolved Hide resolved
Source/Core/AudioCommon/WASAPIStream.h Show resolved Hide resolved
Source/Core/AudioCommon/WASAPIStream.h Outdated Show resolved Hide resolved
Source/Core/AudioCommon/WASAPIStream.cpp Outdated Show resolved Hide resolved
@CookiePLMonster CookiePLMonster force-pushed the wasapi-code-improvements branch 2 times, most recently from b061e72 to 92eed7e Compare August 18, 2019 11:00
@CookiePLMonster
Copy link
Contributor Author

I have fixed CMake definitions (and tested them), also reworded all mentioned comments. Also I added one more commits, because I just noticed a std::thread constructor with invoke semantics exists - so there is no need to involve a lambda capturing the object.

@CookiePLMonster
Copy link
Contributor Author

So with build machine now migrated to Visual Studio 2019, and build succeeding, any blockers preventing from merging this in?

@CookiePLMonster
Copy link
Contributor Author

Rebased on latest master and used the most up to date WIL. Doesn't bring any improvements to the PR but I think it makes sense to start off the most up to date submodule.

@CookiePLMonster
Copy link
Contributor Author

CookiePLMonster commented Sep 24, 2019

Pushed a tiny change, since I noticed IID_PPV_ARGS can be used in one more place. Also rebased on latest master.

@CookiePLMonster CookiePLMonster force-pushed the wasapi-code-improvements branch 2 times, most recently from d525349 to edf85fa Compare October 4, 2019 18:37
@CookiePLMonster
Copy link
Contributor Author

Updated HandleWinAPI, since I just had a realization that I can pass the string size to ERROR_LOG (since it uses sprintf internally) and not have to promote string_view to string just to gain a guaranteed null terminator.

@CookiePLMonster
Copy link
Contributor Author

Rebased on latest master due to conflicts.

Copy link
Member

@BhaaLseN BhaaLseN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code seems fine, untested.

@CookiePLMonster
Copy link
Contributor Author

I've rebased against the latest master since I updated WIL to the newest version - makes sense to keep it up to date if it's to become a submodule.

However, since looks like this is not getting merged anytime soon and I really want to use WIL in other PR's, maybe I should split the commit adding WIL as submodule as a separate PR so I don't stall waiting for this to be merged?

@BhaaLseN @Warepire @lioncash thoughts?

@BhaaLseN
Copy link
Member

Not sure how others are coming along with testing and their reviews; but if that still takes a while it probably isn't a bad idea to pull it out into its own PR.

@CookiePLMonster
Copy link
Contributor Author

Postponed until #8427 gets merged.

@CookiePLMonster CookiePLMonster changed the title WASAPI code improvements [POSTPONED] WASAPI code improvements Oct 23, 2019
@leoetlino
Copy link
Member

#8427 has now been merged :)

@CookiePLMonster CookiePLMonster changed the title [POSTPONED] WASAPI code improvements WASAPI code improvements Mar 17, 2020
@CookiePLMonster
Copy link
Contributor Author

Rebased on latest master. Thankfully, all I had to do was remove the commit added WIL since it's now merged in separately!

@shuffle2
Copy link
Contributor

btw, thanks for adding WIL!
I just used it for https://github.com/dolphin-emu/dolphin/pull/9438/files , and I think it provides stuff (the COM wrappers, string wrappers, etc.) to make this PR even nicer, if you're willing to give it a shot...

@CookiePLMonster
Copy link
Contributor Author

CookiePLMonster commented Jan 12, 2021

to make this PR even nicer, if you're willing to give it a shot...

Do you see any other places where WIL could be used in this PR? For COM pointers I personally prefer WRL because it is included in Windows headers, and so it is used here.

EDIT:
One thing I see is CoCreateInstance, I haven't realized WIL has a helper for that! I can take care of it when rebasing to resolve conflicts.

@Filoppi
Copy link
Contributor

Filoppi commented Jan 12, 2021

Shame I had not seen this before starting my WASAPI works (nor anyone told me), though it's not very encouraging to see this still pending given over a year has passed and I have a lot more changes.
I think I've made a lot of the same improvements as you even if I haven't fully checked your code, but my rewrite is much more extensive (it allows any setting to be changed at runtime for example).
#8983
While the WASAPI code there is finished, I still can't mark the PR as finished as I need to clean up other parts.

@shuffle2
Copy link
Contributor

@Filoppi , let's leave this PR specifically for WASAPI resource management improvements.

This fixes numerous resource leaks, as not every return path cleaned every created resource
Now they are all managed automatically and "commited" to WASAPIStream class fields only
after it's certain they initialized properly
This skips a potentially costly loop if volume is 100% or 0%,
as for former there is no need for volume adjustment,
while latter can be solved by specifying a AUDCLNT_BUFFERFLAGS_SILENT flag
@Filoppi
Copy link
Contributor

Filoppi commented Jan 12, 2021

Never said to not keep this even if merging is gonna be annoying. I think the only improvement that mine doesn't have is converting to the new ComPtr. I should have fixed all memory leaks and resource management stuff, plus the deadlocks (which weren't exclusive to WASAPI).
Also changed the devices to be saved by ID and not name string because that would break if you had two devices with the same name, and multiplied the WASAPI volume by windows mixer volume so it's directly controllable from there as well, as it should be.
Anyway, this is great stuff, why hasn't it been merged :(.

@CookiePLMonster
Copy link
Contributor Author

CookiePLMonster commented Jan 12, 2021

Merge conflicts resolved. I decided against using wil::CoCreateInstance because:

  1. it uses wil::com_ptr and I'm using WRL::ComPtr
  2. It wouldn't improve code readability too much and we do make use of CoCreateInstance's result value, which wil::CoCreateInstanceNoThrow drops (by design)

@JosJuice JosJuice merged commit 18d95df into dolphin-emu:master Mar 11, 2021
@CookiePLMonster CookiePLMonster deleted the wasapi-code-improvements branch March 11, 2021 20:19
@Adamillo
Copy link

Does this PR fix the dreaded audio issues on Wasapi?

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

Successfully merging this pull request may close these issues.

10 participants