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
Make shader precompilation interruptable #8467
Conversation
@stenzek left comments on this ticket so I think he's the most appropriate person to review this. |
@CookiePLMonster - I completely forgot this was out there. Just because, can you rebase this on latest so I can test? |
17a2c0e
to
a6f6881
Compare
@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. |
a6f6881
to
7faf5ea
Compare
FifoCI detected that this change impacts graphical rendering. Here are the behavior differences detected by the system:
automated-fifoci-reporter |
There was a problem hiding this 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.
Any idea if fifoci result is a false negative? I have a hard time believing this change would affect rendering. |
@CookiePLMonster - I think it is, pokechu's recent PR also has that issue. |
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.
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. |
I verified this on Direct3D11 and by the time the worker threads have stopped, the pending work queue still had jobs to do.
That's weird since in my testing that wasn't true - I'd put breakpoints on |
@Dentomologist - what platform are you on / GPU? EDIT: are you starting from a fresh shader cache?
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.
That seems surprising to me, given my results. However, that does match stenzek's original comment on the issue ticket. |
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:
On PR:
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 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. |
@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. |
There was a problem hiding this 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.
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?
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. |
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. |
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. |
There was a problem hiding this 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.
There was a problem hiding this 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.
Good enough for me. |
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.