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

Make shader precompilation interruptable #8467

Conversation

CookiePLMonster
Copy link
Contributor

This PR refactors shader precompilation ("Compile shaders before starting") to be interruptable. Previously, user was unable to close emulation gracefully during that step and had to either wait or forcibly terminate the process.

Additionally, UI window will now clear after finishing or aborting shader precompilation - so ImGui's message box will not linger until game renders something.

@8times9
Copy link
Contributor

8times9 commented Nov 11, 2019

@CookiePLMonster
Copy link
Contributor Author

@stenzek left comments on this ticket so I think he's the most appropriate person to review this.

@iwubcode
Copy link
Contributor

iwubcode commented Jun 9, 2022

@CookiePLMonster - I completely forgot this was out there. Just because, can you rebase this on latest so I can test?

@CookiePLMonster CookiePLMonster force-pushed the interruptable-shader-precompile branch from 17a2c0e to a6f6881 Compare June 9, 2022 17:24
@CookiePLMonster
Copy link
Contributor Author

@iwubcode Done! Even though it's been years, rebase thankfully wasn't hard. I verified that after rebase compilation can still be interrupted. It's not instant because each worker is still given the chance to finish work that it's performing (as the code joins on worker threads), but any other pending work is being discarded correctly.

@CookiePLMonster CookiePLMonster force-pushed the interruptable-shader-precompile branch from a6f6881 to 7faf5ea Compare June 10, 2022 15:20
@CookiePLMonster CookiePLMonster requested review from iwubcode and Dentomologist and removed request for stenzek June 10, 2022 15:20
@dolphin-emu-bot
Copy link
Contributor

FifoCI detected that this change impacts graphical rendering. Here are the behavior differences detected by the system:

automated-fifoci-reporter

Copy link
Contributor

@iwubcode iwubcode left a comment

Choose a reason for hiding this comment

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

Code changes LGTM. Tested and confirmed working.

@CookiePLMonster
Copy link
Contributor Author

CookiePLMonster commented Jun 11, 2022

Any idea if fifoci result is a false negative? I have a hard time believing this change would affect rendering.

@iwubcode
Copy link
Contributor

@CookiePLMonster - I think it is, pokechu's recent PR also has that issue.

@Dentomologist
Copy link
Contributor

Setup: I press escape once while the shader compilation progress bar is active and Confirm on Stop is disabled.

Master: The progress bar finishes all remaining in-progress and queued shaders. The emulated game then freezes for several minutes with the "Shutting Down" toast up, before finally quitting.

This PR: The progress bar finishes all remaining in-progress and queued shaders. The game then closes after several seconds.

Fixing the hang is clearly an improvement and I was ready to approve this PR, but after digging into it I'm not sure it's behaving the way it's supposed to.

  • It doesn't prevent queued (as opposed to in-progress) shaders from being compiled.
  • The check for whether Core's state is Stopping is never true. I commented it out without changing the behavior, and I added a logging statement and breakpoint before it returns that I've never seen triggered.

The conditions and behavior surrounding Core's state changes are complicated enough that I'm not certain of this, but I think that it won't switch to Core::State::Stopping until after (among other things) the shader queue is empty.

@CookiePLMonster
Copy link
Contributor Author

  • It doesn't prevent queued (as opposed to in-progress) shaders from being compiled.

I verified this on Direct3D11 and by the time the worker threads have stopped, the pending work queue still had jobs to do.

  • The check for whether Core's state is Stopping is never true. I commented it out without changing the behavior, and I added a logging statement and breakpoint before it returns that I've never seen triggered.

That's weird since in my testing that wasn't true - I'd put breakpoints on return false from the core checks and they were hit.

@iwubcode
Copy link
Contributor

iwubcode commented Jun 12, 2022

@Dentomologist - what platform are you on / GPU? EDIT: are you starting from a fresh shader cache?

Master: The progress bar finishes all remaining in-progress and queued shaders

For me, after clicking "stop" as soon as I see the progress bar, master will hang until it completely gets through the entire progress bar. That process can take up to say 30seconds. On this PR, it is a mere couple seconds for how long it stops.

I initially tried on D3D11 but just tried on D3D12 and Vulkan as well and had the same results.

I have not yet tried stopping when the game is in progress and the shaders changed. I will do that later.

The check for whether Core's state is Stopping is never true

That seems surprising to me, given my results. However, that does match stenzek's original comment on the issue ticket.

@Dentomologist
Copy link
Contributor

I'm on Windows 10 1903 (my Windows Update is broken), and my 770 died recently so I'm using an integrated Intel HD Graphics 4600.

Specialized (default) Shaders, Compile Shaders Before Starting, Confirm on Stop disabled.

My testing has been with OpenGL, Direct3D 11, and Direct3D 12 and I haven't seen any difference between them. I deleted my cache as needed to make compilation happen. Of the games I have Twilight Princess seems to have the longest compilation times so I used that.

I'm not certain what behavior you're seeing on master and what you're expecting in this PR, so here's what happens for me in a bunch of situations. Stop = hit escape once, Force Stop = hit escape twice.

On Master:

  • Wait for Intro cutscene (after the Wiimote warning), Stop.
    • Result: Game closes normally.
  • Wait for Intro cutscene, toggle Per-Pixel Lighting to trigger recompilation, Stop after progress bar appears.
    • Result: Compilation continues, finishes the current bar (roughly 30 seconds), then starts and finishes one or two new bars. The game closes normally afterward.
  • Same as above, but Force Stop:
    • Result: Same as above.
  • Change settings before opening game, start game, Stop.
    • Result: Compilation and game progress as if I hadn't hit Stop. Stopping during the intro works normally (I turned on Confirm on Stop for this to verify it was a Stop rather than Force Stop)
  • Same as above, but Force Stop:
    • Result: Also no effect, even after hitting escape repeatedly.
      

On PR:

  • Wait for Intro cutscene (after the Wiimote warning), Stop.
    • Result: Game closes normally. (Same as Master)
  • Wait for Intro cutscene, toggle Per-Pixel Lighting to trigger recompilation, Stop after progress bar appears.
    • Result: Window title immediately says Stopping, but compilation continues, finishes the current bar (roughly 30 seconds), then starts and finishes one or two new bars. The game closes normally afterward. (Same as master except for title bar changing)
  • Same as above, but Force Stop:
    • Result: Shader compilation is almost immediately interrupted (I presume any delay is from the in-progress unit from each worker thread), then game closes normally.
  • Change settings before opening game, start game, Stop.
    • Result: Compilation and game progress as if I hadn't hit Stop. Stopping during the intro works normally (I turned on Confirm on Stop for this to verify it was a Stop rather than Force Stop)
  • Same as above, but Force Stop:
    • Result: Also no effect, even after hitting escape repeatedly.

The only part thus far where I saw the new conditional triggered is when I Force Stopped the in-game recompilation.


And at this point I reread iwubcode's post and noticed clicking "stop" instead of hitting escape like I had been.

I tried clicking stop during the initial compilation, and it worked!

...then I tried it during the in-game recompilation and it didn't.

Do all my results match what you were expecting? I think we should make in-game recompilation interruptible too, but before I review any further I'd like to make sure I understand what's supposed to be happening first.

@iwubcode
Copy link
Contributor

iwubcode commented Jun 12, 2022

@Dentomologist - yeah. I am noticing similar results as you. And yes, I was hitting "stop" instead of "escape". Surprised they work differently.

Clicking stop when the game has started running and the shader ompilation is occurring will go through the entire progress bar before stopping.

Also, I notice that stopping at startup will sometimes make the progress disappear but there will still be a black screen for sometime after that. Not sure what is going on there. I was not seeing that before.

Copy link
Contributor

@iwubcode iwubcode left a comment

Choose a reason for hiding this comment

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

Cookie - it'd be nice if we could fix both of these issues.

@CookiePLMonster
Copy link
Contributor Author

Clicking stop when the game has started running and the shader ompilation is occurring will go through the entire progress bar before stopping.

I'll check - does the emu actually show the progress bar when compiling in game? Or does it only happen when synchronous shaders with no ubershaders are active?

Also, I notice that stopping at startup will sometimes make the progress disappear but there will still be a black screen for sometime after that. Not sure what is going on there. I was not seeing that before.

I think that's just finishing work that's already started by the time compilation was interrupted - I know there is some brief black screen time after the worker threads tear down but I think it's unrelated to shaders.

@Dentomologist
Copy link
Contributor

I'll check - does the emu actually show the progress bar when compiling in game? Or does it only happen when synchronous shaders with no ubershaders are active?

For all four Shader Compilation models, the progress bar can show up when you change a setting that requires recompiling existing shaders. I don't know if it would show up naturally during gameplay as you encounter new shaders, since there's a ~1 second delay before the progress bar appears, but in principle it's possible if the game tries to compile enough shaders at once.

Re: the stop hotkey:

Hotkeys are processed in Core/DolphinQt/HotkeyScheduler.cpp. Escape triggers HK_STOP on line 220, but line 189 checks if Core::IsRunningAndStarted(). If it's not, which is the case until after initial shader compilation is complete, it skips checking other hotkeys except HK_PLAY_RECORDING and so HK_STOP does nothing. If it was processed normally it would send a signal to the connected MainWindow::RequestStop.

Meanwhile, Menubar buttons are processed normally and the Stop button also has a signal connected to MainWindow::RequestStop, which is why clicking Stop works in the beginning.

Since they both call the same function and clicking the stop button works before Core's fully started, it should be safe to move the hotkey check before the Core check so that escape will work during startup.

@CookiePLMonster
Copy link
Contributor Author

CookiePLMonster commented Jun 14, 2022

Since they both call the same function and clicking the stop button works before Core's fully started, it should be safe to move the hotkey check before the Core check so that escape will work during startup.

Probably, but is it in scope of this PR?

For compiling shaders during gameplay, I'll check but I expected that to be interruptable already. I may be wrong.

Copy link
Contributor

@Dentomologist Dentomologist left a comment

Choose a reason for hiding this comment

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

After looking into it more handling the in-game recompilation case is going to be tricky enough to be worth its own PR. The hotkey isn't essential and would fit in better with another PR too, so no need to delay this one any further.

Copy link
Contributor

@iwubcode iwubcode left a comment

Choose a reason for hiding this comment

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

While the lack of hotkey support is unfortunate and might be confusing to users, I think it's reasonable to save that for another PR (given how long this has sat). Code wise I think this seems reasonable and I tested again and it works as expected.

@AdmiralCurtiss
Copy link
Contributor

Good enough for me.

@AdmiralCurtiss AdmiralCurtiss merged commit 3bcd7ac into dolphin-emu:master Jul 2, 2022
@CookiePLMonster CookiePLMonster deleted the interruptable-shader-precompile branch July 3, 2022 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
7 participants