-
Notifications
You must be signed in to change notification settings - Fork 83
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
Reference count fix for Shaders and StateBlocks to prevent a crash when exiting games #181
Conversation
This will revert PR crosire#159 so shaders and state blocks are not released but also fixes the device reference count
Issue is caused by modifying the unordered map in the middle of looping through the same unordered map
This PR is ready to check-in. It fixes a crash in Windows 7 caused by modifying the unordered map in the middle of looping through the same unordered map. It also fixes the reference count in both |
I don't think this is incorrect. There are two ways of creating a state block in D3D8:
You'll notice both If you want, I can write a test to check it explicitly, but based on the above described behavior it should be pretty clear how it works. P.S.: Some D3D8 games are known to leak state blocks and will crash in certain situations even with native D3D8. |
Ok, good catch. I have fixed this issue.
The games I tested did not use StateBlocks at all. One used only Vertex Shaders. Plus, I literally just started the game and exited immediately on the opening menu and it crashed. You don't even need to play the game to see the crash. The issue with Windows 7 64bit was that when an item in map is modified while looping through the map then the next iteration though the loop would retrieve, and thus send, an invalid handle to Note: If the game crashes even with native d3d8 then it would not be an issue with d3d8to9. |
You are welcome to test this. More testing is always good. But I did already run this through several games and checked the reference count before and after every call to any create function and every call to the Release and AddRef functions. I tested both native d3d8 and I tested with d3d8to9 to verify the references match. |
Thank you.
Edit: Nevermind on the initial suggestion, missed that sets were used here, not vectors. Cossacks II is the game to test for anything state block related, or perhaps Supreme Ruler 2010/2020, as the latter spuriously creates state blocks every frame. This is just FYI, if you ever need to test anything state block related.
Indeed. My point was mostly that crashes due to various leaks, especially on alt+tab-ing, are not unheard of.
I was only referring to the state blocks, but I'm pretty sure I have checked this myself as well in the past. Otherwise I see no problem with the shader related changes, if they improve compatibility. |
Yeah, unfortunately std::unordered_set doesn't support indexing. I don't think using std::move is too bad. Keep in mind the code only runs when the whole device is being deleted anyways.
Thanks for checking. I appreciate it. More eyes are always better. |
@WinterSnowfall, I found a better way to loop through the maps without moving them to a temporary map. |
Nicely done. I was actually considering to suggest getting the set keys in a temp vector and iterating over that rather than copying the whole thing, but this is even better (you've done the same, but in place, which makes more sense). |
@crosire, this is ready to check in. This fixes a rather prevalent crash that happens on Windows 7. We are hoping to get this fix into the Silent Hill 2 Enhancements project. |
This will fix PR #159 so shaders and state blocks are correctly released once the device reference count reaches 1. The previous code would cause a crash on exit in a couple of games, including Indiana Jones and the Emperor's Tomb and State of Emergency.
This fix does the following things:
AddRef()
andRelease()
to return the correct value based on how the native Direct3D8 works.CreateVertexShader()
I tested this with a couple of games alongside the native d3d8 to ensure it does not crash and it works the same as the native d3d8.
Note: it appears that you need to get the current device reference count by call
AddRef()
and thenRelease()
before releasing the shaders and state blocks. If you callRelease()
first then it can lead to a crash in some games.