[d3d11] With DXVK d3d objects may become doubly wrapped leading to a crash
werman opened this issue · comments
I saw this issue when tried to capture "Resident Evil 3" and "Injustice 2" running on DXVK.
How it happens:
- Game calls
IDXGIDevice4::GetParent(IID_IDXGIAdapter)
WrapIDXGIDevice4::GetParent
is called- It calls
dxvk::D3D11DXGIDevice::GetParent
- Which calls
WrapIDXGIAdapter4::QueryInterface
#0 WrapIDXGIAdapter4::QueryInterface (this=0x8982d0, riid=..., ppvObj=0x6bbc3ed8) at wrappers/dxgitrace.cpp:62353
#1 0x000000003b45ee6b in dxvk::D3D11DXGIDevice::GetParent (this=0x970050, riid=..., ppParent=0x6bbc3ed8) at src/d3d11/d3d11_device.cpp:3250
#2 0x000000020f7c58b5 in WrapIDXGIDevice4::GetParent (this=0x4d6a6350, riid=..., ppParent=0x6bbc3ed8) at wrappers/dxgitrace.cpp:57442
#3 0x0000000141b97ce0 in DCF2Game
QueryInterface
wraps object once, and then WrapIDXGIDevice4::GetParent
wraps it for the second time.
I made a change to prevent the double wrapping of the objects, though not sure it's a good one: 7fbc86b
Something's amiss here, as DXVK should never have accessed apitrace's wrapper objects, therefore calls from DXVK back into apitrace should never have happened.
7fbc86b might workaround the issue, but it's papering over the root problem, whatever it may be.
I see two possible explanations:
- Apitrace is inadvertently intercepting internal DXVK calls. Maybe DXVK is using public interfaces, and dxvk's DLLs should be added to
apitrace/inject/injectee_iat.cpp
Lines 760 to 778 in 9de54e5
- Apitrace is inadvertently passing wrapped pointers to DXVK (instead of unwrapping them as it should.)
I think explanation 1 is the most likely.
That said, I think it would be good to have the warning from 7fbc86b , to easily diagnose the issue.
The more I look at dxvk's source code, the more I belive explanation 1 is the right one.
I suspect what's happening is that call DXVK is internally calling D3D11CoreCreateDevice
and this call is being intercepted by apitrace, when it shouldn't. Try breakpoing (or add asm("__int3")
on DXVK's D3D11CoreCreateDevice
code), and I'm sure we'll see apitrace double-intercepting in the call stack.
The issue is a bit earlier:
#0 dxvk::createDxgiFactory (Flags=5174976, riid=..., ppFactory=0x1e77170) at ../../../src/dxgi/dxgi_main.cpp:8
#1 0x000000002779848a in CreateDXGIFactory1 (riid=..., ppFactory=0x4ef7d8) at ../../../src/dxgi/dxgi_main.cpp:31
#2 0x000000020f74288c in _get_CreateDXGIFactory1 (riid=..., ppFactory=0x4ef7d8) at wrappers/dxgitrace.cpp:108
#3 0x000000020f9b3e36 in CreateDXGIFactory1 (riid=..., ppFactory=0x4ef7d8) at wrappers/dxgitrace.cpp:186050
#4 0x000000003b465113 in D3D11InternalCreateDeviceAndSwapChain (pAdapter=0x1, DriverType=5175600, Software=0x3b8d5898 <vtable for std::basic_ofstream<char, std::char_traits<char> >+24>, Flags=999117984,
pFeatureLevels=0x3b8d54a0 <vtable for std::basic_filebuf<char, std::char_traits<char> >+16>, FeatureLevels=0, SDKVersion=9764944, pSwapChainDesc=0x950050, ppSwapChain=0x0, ppDevice=0x7f62084cbe60,
pFeatureLevel=0x4ef870, ppImmediateContext=0x7b61c1f9 <GetBinaryTypeW+73>) at ../../../src/d3d11/d3d11_main.cpp:141
So internal to DXVK IDXGIFactory
gets wrapped after that the result of dxgiFactory->EnumAdapters
gets wrapped, so later on the GetParent
is called on wrapped adapter.
- Apitrace is inadvertently intercepting internal DXVK calls. Maybe DXVK is using public interfaces, and dxvk's DLLs should be added to
Adding dxgi.dll
, d3d11.dll
, d3d9.dll
to the ignore list doesn't change anything. D3D11InternalCreateDeviceAndSwapChain
still calls CreateDXGIFactory1
from the apitrace.
I'll probably need to reproduce this myself.
I don't understand though, why just these games are affected. If all D3D11InternalCreateDeviceAndSwapChain -> CreateDXGIFactory1 were affected then I'd expect this to happen all the time.
Can you confirm how you're capturing this? You're capturing as described in https://github.com/apitrace/apitrace/wiki/WINE#pure-wine ? Or something different?
@jrfonseca I'm just copying dxgi and d3d11 apitrace dlls near game's executable.
I'm just copying dxgi and d3d11 apitrace dlls near game's executable.
Hmm, I wouldn't expect this approach to ever work. But indeed this is what's recommended on https://github.com/doitsujin/dxvk/wiki/Using-Apitrace#on-linux
Please remove any apitrace DLL from the game directory, and try following the instructions on https://github.com/apitrace/apitrace/wiki/WINE#windows-native if you haven't already.
Instead of d3d9.dll, you'll need to set WINEDLLOVERRIDES
environment variable to Z:\path\to\apitrace\build\mingw32\wrappers\dxgi.dll=n;Z:\path\to\apitrace\build\mingw32\wrappers\d3d11.dll=n
, replacing Z:\path\to\apitrace
to the full WINE path of apitrace binaries.
Also note that https://github.com/doitsujin/dxvk/wiki/Using-Apitrace#on-linux also states:
- Before the next step, make sure you disable or get rid of DXVK files first, as it's preferred that you use WineD3D to make an apitrace.
That's probably what's going on. The DXVK DLLs interfere with apitrace wrappers, so it's better not to use both at the same time.
Please remove any apitrace DLL from the game directory, and try following the instructions on https://github.com/apitrace/apitrace/wiki/WINE#windows-native if you haven't already.
Ok, I'll try. The method of dropping the dlls near executable worked for 2+ years, so I didn't expected it to fail this time =)
Before the next step, make sure you disable or get rid of DXVK files first, as it's preferred that you use WineD3D to make an apitrace.
That's too cryptic of a warning (it's likely there to safeguard against embedding corrupted render results into the trace). In my case I don't try to capture any issue, but capture a trace to replay it on my arm board with Turnip driver in order to find issues in it.
Anyway, I'll try to follow your instructions, if it helps I'll suggest an update to dxvk docs.
The good part is that when following your guide there is no crash. The bad part is that there is only a black screen during the replay.
The calls in both traces looks similar, with the difference that one lacks internal DXVK calls, but I probably missing something...