bo3b / 3Dmigoto

Chiri's DX11 wrapper to enable fixing broken stereoscopic effects.
Other
772 stars 123 forks source link

Hang launching Far Cry 4 on Windows 10 #32

Closed DarkStarSword closed 8 years ago

DarkStarSword commented 8 years ago

Split out from #31 as this appears to be a separate issue. Reported by pirateguybrush with 3DMigoto 1.2.9 using FC4 update WIP from github.

Win 10 log:

d3d11_log(1).txt

Of note there appear to be several failures creating the stereo texture and ini params resources just before a final release of the device:

HackerDevice::Release counter=1, this=000000D5DFAB45E0
  created NVAPI stereo handle. Handle = 000000D5E5504330 
  creating stereo parameter texture. 
    call failed with result = 80070057. 
  creating .ini constant parameter texture.
    CreateTexture1D call failed with result = 80070057.
->returns result = 0, device handle = 000000D5E5434440, device wrapper = 000000D5DFAB45E0, context handle = 0000000000000000, context wrapper = 0000000000000000 

HackerDevice::Release counter=0, this=000000D5DFAB45E0
  deleting self
DarkStarSword commented 8 years ago

Another log from 1.2.6 on Windows 10... Was looking for a comparison from before the recent change to HackerDXGIAdapter::QueryInterface, but that is more relevant to #31 than this issue. Still posting this as an extra data point so I don't lose track of it. d3d11_log_win10_1.2.6.txt

Edit: Plus this one may still have other bugs I recently fixed, so not worth paying much attention to

DarkStarSword commented 8 years ago

pirateguybrush confirmed this is working on Win 10 with 1.0.1

DarkStarSword commented 8 years ago

A notable difference in the log of #31 and #32 - on Windows 10, the game asks for an Adapter1, while on Windows 8 it asks for an Adapter2. The Windows 10 run therefore continues past that point and dies later on for a yet undetermined reason.

DarkStarSword commented 8 years ago

It looks like this might affect Win 8 as well, but is being masked by the IDXGIAdapter2 issue #31.

DarkStarSword commented 8 years ago

pirateguybrush has confirmed that multiple other games (including other UPlay games) are working on Win10 with the latest 3DMigoto, so this problem seems to be specific to Far Cry 4.

bo3b commented 8 years ago

Win10_1.2.9.txt

Another log file from Win10, before the giant Win10 update of Nov 11. This is 3Dmigoto 1.2.9.

Also a hang at launch. Attaching with VS2013 leads to killing the 64 bit process as part of their copy protection.

DarkStarSword commented 8 years ago

I was never able to attach a debugger with VS2013 on Win7, but after updating to VS 2015 community I now can. Might be worth a try on Win 10 as well

bo3b commented 8 years ago

Weird, I'll definitely try 2015.

FarCry4 is definitely looking for DX12 now:

 *** D3D11CreateDevice called with  
    pAdapter = 0000009A7ED91ED0 
    Flags = 0 
    pFeatureLevels = 0xc000 
    ppDevice = 0000009A7E1B8800 
    pFeatureLevel = 0 
    ppImmediateContext = 0000000000000000 
HackerDXGIAdapter::QueryInterface(class HackerDXGIAdapter1@0000009A7ED91ED0) called with IID: IDXGIAdapter1 
  created HackerDXGIAdapter1(class HackerDXGIAdapter1@0000009A7ED91F30) wrapper of 0000009A7EDD42E0 
  returns result = 0 for 0000009A7ED91F30 
HackerDXGIAdapter1::GetDesc1(class HackerDXGIAdapter1@0000009A7ED91F30) called 
  returns adapter: NVIDIA GeForce GTX 480, sysmem=0, vidmem=1556541440, flags=0
HackerUnknown::Release(class HackerDXGIAdapter1@0000009A7ED91F30), counter=2, this=0000009A7ED91F30 
HackerDXGIObject::GetPrivateData(class HackerDXGIAdapter1@0000009A7ED91ED0) called with GUID: {1D6AD054-FB2F-4000-B3AB-E873A9131A7C} 
  returns result = 887a0002
HackerUnknown::AddRef(class HackerDXGIAdapter1@0000009A7ED91ED0), counter=3, this=0000009A7ED91ED0 
HackerDXGIAdapter::QueryInterface(class HackerDXGIAdapter1@0000009A7ED91ED0) called with IID: {7ABB6563-02BC-47C4-8EF9-ACC4795EDBCF} 
  returns result = 0 for 0000009A7EDD4318 
   Hooked_LoadLibraryExW load: nvwgf2umx.dll.
HackerUnknown::Release(class HackerDXGIAdapter1@0000009A7ED91ED0), counter=3, this=0000009A7ED91ED0 
  failed with HRESULT=887a0004

That's not super significant, other than it seems clear that there was a game update. If benchmarks of DX12 game paths show performance improvements for a game like this, that would be compelling to support. (current DX12 benchmarks I've seen are only helping AMD cards.)

Edit: Less sure- no file mod dates are newer. I don't have an old log file to look for those CreateDevice calls, and it's conceivable that the 7/15/15 update was looking for DX12.

DarkStarSword commented 8 years ago

Wouldn't surprise me if it's the UPlay overlay that's checking for DX12 - those overlays seem to like trying every possible API regardless of what the game actually uses.

BTW what is it in the above excerpt that makes you think it's DX12? Other than the undecoded IID I can't see anything there out of the ordinary. I would have thought if the game were using DX12 it would be using D3D12CreateDevice or similar, and we wouldn't see that in our logs at all since we don't wrap it, but I haven't looked too closely at the DX12 interfaces yet or the DX11 compatibility interfaces.

bo3b commented 8 years ago

It's the feature level request in the CreateDevice call, of pFeatureLevels = 0xc000, that's for DX12. I don't quite grok the feature level request here, but I think that if it returns feature level of DX12, that means you could QueryInterface your way into the higher level objects.

In this case it returns an error of 887a004 of DXGI error for no interface.

bo3b commented 8 years ago

Fully updated Win10 install, latest Nvidia driver 358.91, stereo enabled, 1.2.9. Still hangs at launch.

Full debug log: Win10_1.2.9_358.91.txt

I see these sorts of errors in most of the logs:

HackerUnknown::Release(class HackerDXGIAdapter1@0000026E6F478910), counter=3, this=0000026E6F478910 
  failed with HRESULT=887a0004

Pretty weird for Release() to get a DXGI error.

DXGI_ERROR_UNSUPPORTED
0x887A0004

Edit: No, sorry, that's not for the Release() call, that call has no logging like that. There are only two spot in the code that logs "failed with HRESULT" and that is in HookedDXGI, or in CreateDXGIFactory.

It looks like maybe a DXGIFactory2 has snuck through, possibly as part of that upcasting QueryInterface stuff. That's bad because we don't have the other 15 up-level objects to back that up.

Not sure, I'll have to dig more later.

Edit2: No, my bad, it's the return from CreateDevice. Time to get some sleep I'd say.

bo3b commented 8 years ago

If I run a Debug build on Win10 setup, it's not a hang, but I do get a crash while creating iniParams.

>   KernelBase.dll!00007ffd6b561f08()   Unknown
    DXGIDebug.dll!CInfoQueue::AddMessage(struct _GUID,void *,enum DXGI_INFO_QUEUE_MESSAGE_CATEGORY,enum DXGI_INFO_QUEUE_MESSAGE_SEVERITY,int,char const *)  Unknown
    d3d11_3SDKLayers.dll!CInfoQueue::AddMessage(enum D3D11_MESSAGE_CATEGORY,enum D3D11_MESSAGE_SEVERITY,enum D3D11_MESSAGE_ID,char const *) Unknown
    d3d11_3SDKLayers.dll!NDebug::CInterfaceSentinel::CFunctionSentinel::ReportMessage(enum D3D11_MESSAGE_ID,char const *,...)   Unknown
    d3d11_3SDKLayers.dll!Validate10on9CreateResourceSemantics(void *,class CAPICaps const *,enum D3D10DDIRESOURCE_TYPE,unsigned int,unsigned int,unsigned int,unsigned int,enum DXGI_FORMAT,enum DXGI_FORMAT,struct DXGI_SAMPLE_DESC,unsigned int,unsigned int,struct DXGI_DDI_PRIMARY_DESC *,unsigned int,unsigned int,unsigned int,bool,bool,bool)    Unknown
    d3d11_3SDKLayers.dll!CCreateTexture1DValidator::Validate(struct D3D11_TEXTURE1D_DESC const *,struct D3D11_SUBRESOURCE_DATA const *,struct ID3D11Device *,unsigned int &,unsigned int,class CAPICaps const *,enum D3D_FEATURE_LEVEL,enum CD3D11FormatHelper::eExtendedFormatFeatures,bool,enum D3D11_TILED_RESOURCES_TIER,bool,bool) Unknown
    d3d11_3SDKLayers.dll!NDebug::CDevice::CreateTexture1DPreValidation(class NDebug::CInterfaceSentinel::CFunctionSentinel &,struct D3D11_TEXTURE1D_DESC const *,struct D3D11_SUBRESOURCE_DATA const *,struct IUnknown * *) Unknown
    d3d11_3SDKLayers.dll!NDebug::CDevice::CreateTexture1D(struct D3D11_TEXTURE1D_DESC const *,struct D3D11_SUBRESOURCE_DATA const *,struct ID3D11Texture1D * *) Unknown
    d3d11.dll!HackerDevice::CreateIniParamResources() Line 233  C++
    d3d11.dll!HackerDevice::Create3DMigotoResources() Line 321  C++
    d3d11.dll!D3D11CreateDevice(IDXGIAdapter * pAdapter, D3D_DRIVER_TYPE DriverType, HINSTANCE__ * Software, unsigned int Flags, const D3D_FEATURE_LEVEL * pFeatureLevels, unsigned int FeatureLevels, unsigned int SDKVersion, ID3D11Device * * ppDevice, D3D_FEATURE_LEVEL * pFeatureLevel, ID3D11DeviceContext * * ppImmediateContext) Line 685  C++
    [External Code] 
    systemdetection64.dll!000000018003fe50()    Unknown

Log file tail:

HackerContext::End(class HackerContext@000002AF2B635220) 
HackerContext::Release counter=0, this=000002AF2B635220
  deleting self
HackerDevice::GetHackerContext returns 000002AF2B635220 
  clearing mHackerDevice->mHackerContext
HackerDevice::Release counter=3, this=000002AF28557BB0
  created NVAPI stereo handle. Handle = 000002AF2B5268A0 
  creating stereo parameter texture. 
    stereo texture created, handle = 000002AF2B1F63C0 
  creating stereo parameter resource view. 
    stereo texture resource view created, handle = 000002AF2B4BCA20.
  creating .ini constant parameter texture.

D3D11 Debug Layer reports:

D3D11 ERROR: ID3D11Device::CreateTexture1D: CreateResource: This format does not support binding as a shader resource. [ STATE_CREATION ERROR #1048589: CREATERESOURCE_NOT_BINDABLE_AS_SHADER_RESOURCE]
D3D11 ERROR: ID3D11Device::CreateTexture1D: A Texture1D does not support the following Format (0x2, R32G32B32A32_FLOAT). [ STATE_CREATION ERROR #75: CREATETEXTURE1D_UNSUPPORTEDFORMAT]
D3D11 ERROR: ID3D11Device::CreateTexture1D: Returning E_INVALIDARG, meaning invalid parameters were passed. [ STATE_CREATION ERROR #87: CREATETEXTURE1D_INVALIDARG_RETURN]
bo3b commented 8 years ago

Not sure this is the right fix, but it does solve the hang and crash in Win10.

    // With all the interacting objects set up, we can now safely finish the HackerDevice init.
    if ((deviceWrap != nullptr) && (*pFeatureLevels == D3D_FEATURE_LEVEL_11_0))
        deviceWrap->Create3DMigotoResources();

In CreateDevice in D3D11Wrapper.cpp.

The problem seems to be that we create iniParams, pink shader, and stereo params regardless of the CreateDevice. FC4 calls CreateDevice like 10 times before getting rolling, with all sorts of parameters, including looking for v9.0 and v9.1 of DX, which don't support that pink shader (SM 4.0), and also not the parameters for iniParams. Too old, limited API.

So, if I skip all those, and only build on D3D_FEATURE_LEVEL_11_0 as the target, it avoids all those other bad variants.

Not sure this is the right fix, just hacking around to understand it. This runs without crashing, hanging, or D3D11 debug layer errors on Win10.

Edit: PirateGuyBrush tried an Eng build on Win8, and did not change the result there.

bo3b commented 8 years ago

Have a WIP for forcing feature level back to 11_0 only. Not ready to roll just yet.

Tried an experiment of forcing it fail for anything except for 11_0. Curiously that allows FC4 to launch even with overlay on. Crashes later at Draw(), after having done a bunch successfully. So... not really expecting that to work, but was expecting a different failure mode.

bo3b commented 8 years ago

OK, here's a weird idea that seems to work really well. What do you think of returning E_INVALIDARG for anything other than D3D_FEATURE_LEVEL_11_0?

When I try this experiment it's pretty wildly successful. This fixes this hang with Far Cry 4 on Win10. It also removes the need to check for DX10 for the overlay crash. FC4 still runs with Uplay overlay enabled, after removing that code check.

Shader hunting and overlay is all working.

In my test suite from CopyToGames.bat, I can run all 7 games without error.

xcopy "%1*.*" "T:\Games\Watch_Dogs\bin"  /F /Y
xcopy "%1*.*" "T:\SteamLibrary\SteamApps\common\Call of Duty Ghosts\"  /F /Y
xcopy "%1*.*" "T:\Bootleg\Project CARS\" /F /Y
xcopy "%1*.*" "T:\Bootleg\Dying Light\" /F /Y
xcopy "%1*.*" "T:\Games\The Witcher 3 Wild Hunt\bin\x64\" /F /Y
xcopy "%1*.*" "T:\SteamLibrary\SteamApps\common\Batman Arkham Knight\Binaries\Win64\" /F /Y
xcopy "%1*.*" "T:\Games\Far Cry 4\bin\" /F /Y

It's pretty notable that it works with Watch_Dogs, because that was one of the remaining problem children for 1.2 branch that I hadn't gotten working before. I tried Watch_Dogs on Win10, and it worked there as well.
Generally speaking I'd think this is too extreme a technique, but I'm struck by the fact that it fixes the hang on Win10, as well as Watch_Dogs, without breaking anybody else in my suite.
What do you think?

DarkStarSword commented 8 years ago

I think unless we find a counter example, go for it :)

It seems like the better approach anyway - blacklist all feature levels except for those we know we actually support.

bo3b commented 8 years ago

OK, not a full win, drat. When I build for x32 variants and run my test suite there:

xcopy "%1*.*" "T:\Bootleg\Assassin's Creed IV - Black Flag\"  /F /Y  - works
xcopy "%1*.*" "T:\SteamLibrary\SteamApps\common\BioShock Infinite\Binaries\Win32\" /F /Y - works
xcopy "%1*.*" "T:\Bootleg\Saints Row IV\" /F /Y - works
xcopy "%1*.*" "T:\SteamLibrary\SteamApps\common\Saints Row the Third\" /F /Y - works
xcopy "%1*.*" "T:\SteamLibrary\SteamApps\common\F.E.A.R. 3\" /F /Y - works
xcopy "%1*.*" "C:\Program Files (x86)\Steam\SteamApps\common\Alien Isolation\" /F /Y - works
xcopy "%1*.*" "T:\Bootleg\Ori and the Blind Forest\" /F /Y - works
xcopy "%1*.*" "C:\Program Files (x86)\Steam\SteamApps\common\DefenseGrid2\" /F /Y - works
xcopy "%1*.*" "T:\Bootleg\DiRT Rally\" /F /Y - silent exit at launch, getting HD errors
xcopy "%1*.*" "T:\Games\Crysis 3\Bin32\" /F /Y - works

So.... 9 out of 10 work on x32 games.

This is actually closer to what we'd expect. Makes some games freak out. I also tried the variant of always forcing it to be DX11 no matter the request, and that has similar side effects, but only for x32 games.

I'll try some more experiments to see if there is something more clear. In any case, when you need to update FC4, we have a solution for the hangs.

Edit: Updated the list. Had some bad install setups with experimental dinput8.dll loaders that conflicted, and my 3T game dumping drive is giving me read errors. This actually looks pretty good now.

After doing better experiments, it actually seems to work fine.

bo3b commented 8 years ago

OK, went ahead and pushed this fix up. We might very well run into problems with on some games, but let's see. If we get a problem game, we can always make it an optional parameter in the d3dx.ini. For now it seems pretty compelling for all games.

The problem for Win10 was that we were getting a device request for DX9.2, which does not support the ps_4_0 that we use for the pink shader, and also does not support the CreateTexture1D call we use for iniParams. So, avoiding that device creation altogether is a good way to fix it.

Closing for now as fixed.

DarkStarSword commented 8 years ago

Thanks for looking into this one :)