ValveSoftware / Proton

Compatibility tool for Steam Play based on Wine and additional components
Other
23.94k stars 1.05k forks source link

Crysis 3 Remastered (2096610) #7082

Open bluestang2006 opened 1 year ago

bluestang2006 commented 1 year ago

Compatibility Report

System Information

I confirm:

Proton Log captured w/ following options: `PROTON_LOG=+wintrust,+crypt,+advapi,+cryptnet,+cryptasn` [steam-2096610.zip](https://github.com/ValveSoftware/Proton/files/12561531/steam-2096610.zip) ## Symptoms **Note - This is a corner case issue** Crysis 3 Remastered with the use of CyberFSR2 will crash back to the desktop when launched using Proton Experimental[Bleeding Edge]. The wine commit that is causing the issue is - https://github.com/ValveSoftware/wine/commit/1a152d73f0552ec257ea15170fa98aefe7342d00 I'm 100% positive that commit is at fault, how...I have no idea because it doesn't seem related...but it is...I tested it 3X. The only way to repro it is with CyberFSR2 enabled. CyberFS2 Background: CyberFS2 is a DLSS to FSR2 mod and it recently added DX11 support for games that use DLSS. CyberFSR2 hooks into the DLSS calls and then translates them to FSR2 instead. This mod opens up the possibility of any GPU to use FSR2 in place of where DLSS is the only available option. https://github.com/PotatoOfDoom/CyberFSR2 ## Reproduction 1. This the latest built release files required to enable CyberFSR2 - [CyberFSR_2.2.1_DX11.zip](https://github.com/ValveSoftware/Proton/files/12561622/CyberFSR_2.2.1_DX11.zip) Extract all files (`nvngx.dll`, `nvgnx.ini`, `EnableSignatureOverride.reg`, `DisableSignatureOverride.reg`) 2. Copy`nvngx.dll` and `nvgnx.ini` to game exe folder - `/path/to/steamapps/common/Crysis3Remastered/Bin64` 3. On first launch, the prefix needs to be created first, so ensure Proton Experimental[Bleeding Edge] is selected. 4. Once the prefix is created we now need to patch with the included `EnableSignatureOverride.reg` file. 5. Patching the prefix can be done as follows: `WINEPREFIX=/path/to/steamapps/compatdata/2096610/pfx '/path/to/steamapps/common/Proton - Experimental/files/bin/wine64' regedit /path/to/EnableSignatureOverride.reg` 6. Once completed you will see a msg that reads Wine prefix updated, etc 7. This game also seems to have a vendor id check so a `dxvk.conf` file is needed with the following line: `dxgi.customVendorId = 10de` 8. Place the `dxvk.conf` file in the game exe folder - `/path/to/steamapps/common/Crysis3Remastered/Bin64` 9. Re-launch Crysis 3 Remastered, the game should crash back to the desktop If you use Proton 8 Stable the game will launch successfully and you should be able to navigate to the `Options` / `Advanced Graphics` menu and see that DLSS Image Quality options are available/selectable: ![Screenshot_20230907_214146](https://github.com/ValveSoftware/Proton/assets/67126489/417ca1f7-4004-4fa9-9371-79de0e96af66)
gofman commented 1 year ago

So I looked into this and this is neither a regression nor a Proton bug in general.

The attribution to commit is random. I could reproduce the described problem immediately, but also with the commit reverted and with Proton 8.0-3 (which never had the blamed commit). My crash stack (from C++ exception) matches the attached log. Once over attempts I actually got the game started.

The immediate reason is that ID3D11Device_CreateTexture2D called from modded nvngx fails (and nvngx fires uncaught exception on that). It fails because on first invocation from mod it usually gets bogus width and height (typical values I observe are around 0 x 63482640 but not necessarily that). Fixing up bogus sizes to 1x1 in dxvk's ID3D11Device_CreateTexture2D makes it work, but this is wrong of course.

That looks like some use after free or using uninitialized stack variable somewhere (in game or mod). Since CyberFSR2 is available with source, I built in on Windows with some logging. Then, I immediately reproduced the same problem on Windows (both with my built mod's DLL and the original one attached in the report). That was on AMD (didn't dig why it didn't need any GPU vendor faking, I didn't do anything besides placing the mod, nor dropping in any dxvk). I logged width and height from the mod and they have the same bogus values on Windows (or sometimes 0x0 like in Proton sometimes too, this variant results in crash from division by zero in the mod's code before attempting to create a texture). The bogus values come from the game code calling NVSDK_NGX_Parameter_SetUI for "Width" and "Height". Maybe I didn't try too much, but over ~6-7 starts on Windows with locally built and original versions of the mod I didn't get it working even once.

I didn't dig further and don't know if that is related to some data returned by the mod or a game bug, but since it is easily reproduced on Windows all the same way (along with other details I checked and described) this is not our bug.

gofman commented 1 year ago

Unrelated, but the values are actually from uninitialized heap allocated memory (with warn+heap those width and height are 0xbaadf00d which is used memory canary). The game actually calls NGX function multiple times, and at some moment starts giving correct dimension. One possibility is that this is the game behaviour but "real" nvngx does some parameter validation instead of crashing the whole thing with own exception and works once later initialized properly.

bluestang2006 commented 1 year ago

Replying to https://github.com/ValveSoftware/Proton/issues/7082#issuecomment-1712422777

Thanks for taking the time to dig into this issue...and yes after your explanation I agree that this is not proton bug at all.

So I did some tinkering around with CyberFSR2's code and manually used my desktop res - 2560x1440 respectively in: https://github.com/PotatoOfDoom/CyberFSR2/blob/ed00f4a0022e273e8e4e938b70781d481d3b868d/CyberFSR/CyberFsrDx11.cpp#L114-L115

initParams.maxRenderSize.width = inParams->Width;
initParams.maxRenderSize.height = inParams->Height;

And of course the game works with DLSS enabled on both Windows and Linux...so I guess this might be some weird game bug? This is the only game known that does behaves this way...Crysis 1 & 2 RM work w/o any issues with the orig code.

Again thanks for looking into this and also the RT rendering issue as well. I can confirm that all 3 Crysis RM games work great on the bleeding-edge branch.

gofman commented 1 year ago

@bluestang2006 I think most likely one (mod) bug here is that it throws an exception from NVSDK_NGX_D3D11_CreateFeature on texture creation error instead of just returning an error code (as well as maybe many other error conditions). The game calls it again anyway, and at some moment with some sensible sizes. The attached diff is one (possibly not the best, just proof of concept) way to fix that in mod, it avoids crashing on Windows and Proton. Note that the diff, besides try / catch in cpp file also adds /EHa exception handling in vcproj file, so the case of 0 width / height when it fires divide by zero is also caught. A better way would probably be to just stop firing exceptions in the underlying fsr library and return error codes. And avoid divising by zero with 0 height of course. testpatch.txt

gofman commented 1 year ago

Note that the mod also does some probably not quite correct handling of NV parameters: I am not sure params->Set(NVSDK_NGX_Parameter_Width, 1024.0f); (mind float width) will do the right thing with the mod. Although this is not what happens here, game sets width and height as integere.