Skip to content
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

Origin Overlay does not work in Proton (specifically, with d3d11 and dxvk's dxgi) due to IDXGISwapchain methods being not in dxgi.dll #1996

Closed
gofman opened this issue Mar 29, 2021 · 16 comments · Fixed by #1997
Labels

Comments

@gofman
Copy link
Contributor

gofman commented Mar 29, 2021

The Origin's detour patcher expects the methods to be hotpatched from IDXGISwapchain1 interface to live in dxgi.dll. It checks that the methods lie within the loaded dxgi.dll image range and refuses to hotpatch them otherwise.

That's currently the same for Proton's dxgi as well due to the same reasons.
The attached PoC hack fixes the issue (attaching just for illustration of what it wants, I would not consider this a fix).

0001-d3d11-Create-dxgi-swapchain-from-dxgi.dll.txt

@K0bin K0bin added the dxgi label Mar 29, 2021
@doitsujin
Copy link
Owner

Well that's a huge pain in the arse. It doesn't look like this is possible to fix without losing compatibility to Wine's DXGI implementation, is it?

@gofman
Copy link
Contributor Author

gofman commented Mar 30, 2021

As a probably saner workaround, adding a proxy interface to dxgi itself without touching d3d11 helps too (that's what I did for Proton's dxgi, see attached). Please note it might happen (especially with a very short function which just jumps to the underlying proxy method) that it still won't be hotpatchable by Origin due to some opcode it won't understand or the function being just too short. In that case attribute((ms_hook_prologue)) function attribute (DECLSPEC_HOTPATCH in Wine) helps. This is less likely for PE .dll (the Wine's dxgi is currently dll.so), if to go this way we can check that it is actually needed before adding that.

0001-dxgi-Use-proxy-IDXGISwapChain-interface-when-importi.txt

@misyltoad
Copy link
Collaborator

misyltoad commented Mar 30, 2021

I was planning on just writing a simple swapchain wrapper/dispatcher in our DXGI. I imagine that works too?

I'm not super familiar with DECLSPEC_HOTPATCH from your patch there. What does that do to help the situation?
Is that something that's only needed in Unix and not PE dlls?

@gofman
Copy link
Contributor Author

gofman commented Mar 30, 2021

Yes, that works, the second patch I linked (for Wine's dxgi) is doing exactly that.

DECLSPEC_HOTPATCH unwraps to "attribute(ms_hook_prologue)". That means adding a standard opcode sequence at the start of procedure. That is effectively a few bytes noop for x64 and 'push %ebp; mov %esp,%ebp" on x86 which is a standard stack frame setup. Some hotpatchers did not parse the function opcodes at all and expected exactly this sequence at the beginning of the hotpatched function. That is not the case with Origin, but it still breaks on certain opcodes at the start of the function and will probably break on a function consisting, e. g., from a single jump or so. E. g., it tries to hotpatch dxvk's d3d9 TestCooperativeLevel and fails, can be fixed by adding the mentioned attribute (I didn't bring that to attention as I am not aware if anything is broken due to that). The things which can break hotpatching are more often encountered in Unix dlls but can happen in PE as well (as in the TestCooperativeLevel example).

To make things funner, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91489. That affects x86 only. The fix got to gcc trunk in November. So on x86 (x64 is not affected) the functions get miscompiled with this attribute if take a fast exit path bypassing prologue / epilgue (in the Wine case, usually happens with the stubs containing FIXME only, that is, conditional call which gets fast exit path for the case when call is not made).

So, I suppose it would be ideal to add the attribute to avoid obscure hotpatching issues (in case of Origin, the failure to properly hotpatch the function sometimes manifests itself by a crash due to the jump into the middle of opcode in the hotpatched function), but maybe for x64 only for now until gcc fixed gets populated to the distros.

@misyltoad
Copy link
Collaborator

but maybe for x64 only for now until gcc fixed gets populated to the distros.

I mean, min spec for DXVK is GCC 9.3 anyway so... 🐸

I'll do that dispatcher now I guess.

misyltoad added a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
@misyltoad
Copy link
Collaborator

Does #1997 solve the issue?

It'd be nice to be smarter than this and have an actual common DXGI windowing abstraction between dxvk and vkd3d-proton, but we can solve that later potentially.

misyltoad added a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
@gofman
Copy link
Contributor Author

gofman commented Mar 30, 2021

For some reason it doesn't so far. I will check what is missing now and get back (my modified Proton's dxgi still works, so probably some ms_hook_prologues are needed).

@misyltoad
Copy link
Collaborator

I think I have an idea why, I made a typo

misyltoad added a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
@gofman
Copy link
Contributor Author

gofman commented Mar 30, 2021

I think the first thing is QueryInterface interface returns the wrong interface, yeah.

Then, you are not redefining the AddRef / Release methods in DxgiSwapChainDispatcher, AddRef / Release... should not the refcounting go to the dispatcher?

@misyltoad
Copy link
Collaborator

It was returning the address of the dispatch in QueryInterface, I've updated the PR.

@misyltoad
Copy link
Collaborator

misyltoad commented Mar 30, 2021

Then, you are not redefining the AddRef / Release methods in DxgiSwapChainDispatcher, AddRef / Release... should not the refcounting go to the dispatcher?

It shouldn't really matter if we refcount the dispatcher or the swapchain, should it?
AFAIK we don't have anything that references the DXGI swapchain internally.

This way just deals with destroying the object easier.

@misyltoad
Copy link
Collaborator

Philip prefers the passthrough of refcounting so I'll just do that.

@gofman
Copy link
Contributor Author

gofman commented Mar 30, 2021

Seems to work now (without adding any ms_hook_prologue).

@misyltoad
Copy link
Collaborator

Cool! I'll finish the few nits Philip added then we can merge it :)

misyltoad added a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
misyltoad added a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
@misyltoad
Copy link
Collaborator

Updated the PR, can you make sure that doesn't break it somehow (it really shouldn't) and then we can merge it in.

Thanks!

@gofman
Copy link
Contributor Author

gofman commented Mar 30, 2021

Still works here.

misyltoad added a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
doitsujin pushed a commit that referenced this issue Mar 30, 2021
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants