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

Library Forwarding: Add support for 32-bit OpenGL #3630

Merged
merged 7 commits into from
Jun 11, 2024

Conversation

neobrain
Copy link
Member

@neobrain neobrain commented May 15, 2024

Overview

This PR adds support for forwarding the overwhelming majority of the OpenGL API to the host driver for 32-bit applications. Previously, this was exclusively possible for 64-bit titles.

This work is enabled by #3584, thanks to which forwarding OpenGL calls to the host does not require forwarding libX11 calls anymore. We can now tick off the last critical box in the Library Forwarding Roadmap:

X11 (64-bit) Wayland (64-bit) Wayland (32-bit) X11 (32-bit)
no forwarding ☑️ 2022 ☑️ 2022 ☑️ 2022 ☑️ 2022
only Wayland forwarding N/A ☑️ Phase 1 ☑️ Phase 3 N/A
Vulkan ☑️ 2022 ☑️ Phase 1 ☑️ Phase 4 Phase 7
zink on Vulkan ☑️ Phase 2 ☑️ Phase 2 Phase 4 Phase 7
OpenGL ☑️ 2022 Phase 5 Phase 6 ✅ Phase 7

That leaves only 32-bit Vulkan applications and OpenGL-on-Wayland unsupported. The former is barely used in the wild, and the latter is also still uncommon in practice. (Note that due to putting #3487 on hold, the phase numbering is off)

Implementation

thunkgen has caught all APIs that are problematic with regards to 32-bit support:

  • Pointers to size_t/intptr_t (only in-parameters)
  • char** (only in-parameters)
  • void** (only out-parameters)

The first two cases are handled by relocating the data element-by-element (onto the stack). The last case only occurs in APIs that write a single pointer to a user-provided destination and is easily handled without overhead.

Other errors raised by thunkgen refer to unannotated void* pointers. Since these are very common in the OpenGL API but always refer to data of consistent layout, an escape hatch is added to ignore errors from void* specifically.

Limitations

A small number of vendor-specific functions is currently not implemented on 32-bit, simply because exhaustively doing so is tedious busy-work that I couldn't verify the results of for lack of corresponding hardware. If individual functions are considered critical, adding support for them should be easy though.

Testing

I only have few 32-bit OpenGL applications in my library, so further testing will be needed in addition to these

  • ✅ 7 Billion Humans
  • ✅ Dandara: Trials of Fear Edition
  • ✅ Enter the Gungeon
  • ✅ FTL
  • ✅ Super Meat Boy
  • ✅ World of Goo
  • ✅ Xonotic (both GLX/SDL builds)

Testing round 2:

  • ✅ Portal (native)
  • ✅ Half Life 2 (native)

Testing round 3:

  • ✅ FEZ (wined3d)
  • ✅ Floating Point (wined3d)
  • ✅ Magicka 2 (wined3d)
  • ✅ Mirror's Edge (wined3d)
  • ✅ Portal (native, wined3d)
  • ✅ Portal 2 (native, wined3d)
  • ✅ Psychonauts (native)

TODO

  • Drop void* pointer automation (or make it specific to libGL)
  • Relocate double-pointers only for 32-bit applications
  • Reconsider whether alloca is suitable in all instances (should be fine, since the count parameters should never be huge)
  • Testing
  • Tidy up commit history

@@ -405,6 +405,12 @@ struct host_to_guest_convertible {
{
return {static_cast<uint32_t>(from.data)};
}

// libGL also needs to allow long->int conversions for return values...
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to double-check if this is still required. The other changes in Host.h may have obsoleted it.

@Sonicadvance1
Copy link
Member

Did some light testing.
32-bit DXVK/Vulkan games now crash:

  • Sonic Mania
  • I assume all in this situation will now crash since Wine loads GL and Vulkan. Won't test this any further.

32-bit OpenGL Linux games now crash:

  • Grim Fandango Remastered
Backtrace
                #0  0x00000003642447dc n/a (n/a + 0x0)
                #1  0x00000000f69b9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f69895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f699d974 _ZL34fexfn_unpack_libGL_glXQueryVersionP39fexfn_packed_args_libGL_glXQueryVersion (libGL-host.so + 0xcd974)
                #4  0x00000003644452c0 n/a (n/a + 0x0)
                #5  0x00000003644452c0 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Portal
Backtrace
                #0  0x000000036406232c n/a (n/a + 0x0)
                #1  0x00000000f6bb9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6b895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6bb6e40 _ZN27GuestWrapperForHostFunctionIFPKcP9_XDisplayjEJS3_jEE4CallIXtl20ParameterAnnotationsEEJXtlS7_Lb0ELb1EEEXtlS7_EEEEEvPv (libGL-host.so + 0xe6e40)
                #4  0x00000003641158b0 n/a (n/a + 0x0)
                #5  0x00000003641158b0 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Portal 2
Backtrace
                #0  0x000000036403cb54 n/a (n/a + 0x0)
                #1  0x00000000f6bb9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6b895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6bb6e40 _ZN27GuestWrapperForHostFunctionIFPKcP9_XDisplayjEJS3_jEE4CallIXtl20ParameterAnnotationsEEJXtlS7_Lb0ELb1EEEXtlS7_EEEEEvPv (libGL-host.so + 0xe6e40)
                #4  0x00000003640edaf8 n/a (n/a + 0x0)
                #5  0x00000003640edaf8 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Psychonauts - Shows some intro logos before crashing
Backtrace
                #0  0x00000003647767b4 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Left 4 Dead 2
Backtrace
                #0  0x0000000363fba7f4 n/a (n/a + 0x0)
                #1  0x00000000f6bb9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6b895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6bb6e40 _ZN27GuestWrapperForHostFunctionIFPKcP9_XDisplayjEJS3_jEE4CallIXtl20ParameterAnnotationsEEJXtlS7_Lb0ELb1EEEXtlS7_EEEEEvPv (libGL-host.so + 0xe6e40)
                #4  0x00000003640d5b04 n/a (n/a + 0x0)
                #5  0x00000003640d5b04 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Lethal League
Backtrace
                #0  0x0000000363f63f8c n/a (n/a + 0x0)
                #1  0x00000000f5f39084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f5f095e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f5f1d974 _ZL34fexfn_unpack_libGL_glXQueryVersionP39fexfn_packed_args_libGL_glXQueryVersion (libGL-host.so + 0xcd974)
                #4  0x0000000363fdca6c n/a (n/a + 0x0)
                #5  0x0000000363fdca6c n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Hotline Miami
Backtrace
                #0  0x00000003644fb71c n/a (n/a + 0x0)
                #1  0x00000000f5c89084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f5c595e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f5c6d974 _ZL34fexfn_unpack_libGL_glXQueryVersionP39fexfn_packed_args_libGL_glXQueryVersion (libGL-host.so + 0xcd974)
                #4  0x000000036459fbb0 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Half-Life: Source
Backtrace
                #0  0x0000000364062484 n/a (n/a + 0x0)
                #1  0x00000000f6bb9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6b895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6bb6e40 _ZN27GuestWrapperForHostFunctionIFPKcP9_XDisplayjEJS3_jEE4CallIXtl20ParameterAnnotationsEEJXtlS7_Lb0ELb1EEEXtlS7_EEEEEvPv (libGL-host.so + 0xe6e40)
                #4  0x0000000364115870 n/a (n/a + 0x0)
                #5  0x0000000364115870 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Half-Life 2
Backtrace
                #0  0x0000000364067620 n/a (n/a + 0x0)
                #1  0x00000000f6bb9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6b895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6bb6e40 _ZN27GuestWrapperForHostFunctionIFPKcP9_XDisplayjEJS3_jEE4CallIXtl20ParameterAnnotationsEEJXtlS7_Lb0ELb1EEEXtlS7_EEEEEvPv (libGL-host.so + 0xe6e40)
                #4  0x000000036411a8c0 n/a (n/a + 0x0)
                #5  0x000000036411a8c0 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Counter-Strike: Source
Backtrace
                #0  0x0000000363fd8de0 n/a (n/a + 0x0)
                #1  0x00000000f6bb9084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6b895e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6bb6e40 _ZN27GuestWrapperForHostFunctionIFPKcP9_XDisplayjEJS3_jEE4CallIXtl20ParameterAnnotationsEEJXtlS7_Lb0ELb1EEEXtlS7_EEEEEvPv (libGL-host.so + 0xe6e40)
                #4  0x00000003640f99f8 n/a (n/a + 0x0)
                #5  0x00000003640f99f8 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Cave Story Plus
Backtrace
                #0  0x0000000364252eb0 n/a (n/a + 0x0)
                #1  0x00000000f6a69084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f6a395e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f6a4d974 _ZL34fexfn_unpack_libGL_glXQueryVersionP39fexfn_packed_args_libGL_glXQueryVersion (libGL-host.so + 0xcd974)
                #4  0x00000003643b41bc n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Braid
Backtrace
                #0  0x0000000363f6f1fc n/a (n/a + 0x0)
                #1  0x00000000f5e69084 _ZN14CallbackUnpackIFiPviEE12CallGuestPtrES0_i (libGL-host.so + 0xe9084)
                #2  0x00000000f5e395e8 _ZN11host_layoutIP9_XDisplayEC2ER12guest_layoutIS1_E (libGL-host.so + 0xb95e8)
                #3  0x00000000f5e4d974 _ZL34fexfn_unpack_libGL_glXQueryVersionP39fexfn_packed_args_libGL_glXQueryVersion (libGL-host.so + 0xcd974)
                #4  0x00000003645e7ef0 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64
  • Brütal Legend
Backtrace
                #0  0x0000aaaab5fc88e0 _ZN3FEX3HLE19SyscallPassthrough3ILi131EQneT_ngLi1EEEmPN7FEXCore4Core13CpuStateFrameEmmm (FEXInterpreter + 0x2a88e0)
                #1  0x000000039a20a4f0 n/a (n/a + 0x0)
                #2  0x000000039a20a4f0 n/a (n/a + 0x0)
                #3  0x00000000f68633fc _ZN10X11Manager18GuestToHostDisplayEP9_XDisplay (libGL-host.so + 0xe33fc)
                #4  0x00000000f684d974 _ZL34fexfn_unpack_libGL_glXQueryVersionP39fexfn_packed_args_libGL_glXQueryVersion (libGL-host.so + 0xcd974)
                #5  0x0000000364cfcfd4 n/a (n/a + 0x0)
                ELF object binary architecture: AARCH64

32-bit Linux games that work:

  • Osmos
  • Half-Life (GoldSrc)
  • Fahrenheit: Indigo Prophecy Remastered
  • Counter-Strike (GoldSrc)

@neobrain neobrain force-pushed the feature_libfwd_gl32 branch from 3364954 to ab82141 Compare May 30, 2024 21:27
@neobrain
Copy link
Member Author

32-bit OpenGL Linux games now crash:

I added a patch to fix this: The _XDisplay returned from glXGetCurrentDisplay didn't get remapped to a guest display (even on 64-bit). I could only confirm Portal and Half Life 2 to work, but it'll probably fix most (if not all) the other ones on your list.

@Sonicadvance1
Copy link
Member

32-Bit OpenGL Linux games:

Works:

  • Grim Fandango - 150 FPS up to 270FPS, kind of neat.
  • Portal
  • Left 4 Dead 2
  • Lethal League
  • Hotline Miami
  • Half-Life: Source
  • Half-Life 2
  • Counter-Strike: Source
  • Cave Story Plus
  • Braid
  • Brütal Legend

Crashes:

  • Psychonauts - Same as before

Misc:

  • Portal 2 - Futex hang. Might be unrelated to PR

Games that previously worked and still work:

  • Osmos
  • Half-Life (GoldSrc)
  • Fahrenheit: Indigo Prophecy Remastered
  • Counter-Strike (GoldSrc)

Looking pretty interesting.

@neobrain neobrain force-pushed the feature_libfwd_gl32 branch from bf8dff3 to 70a38e8 Compare June 10, 2024 14:40
@neobrain
Copy link
Member Author

More 32-bit games tested:

  • ✅ FEZ (wined3d)
  • ✅ Floating Point (wined3d)
  • ✅ Half-Life 2 (native)
  • ✅ Magicka 2 (wined3d)
  • ✅ Mirror's Edge (wined3d)
  • ✅ Portal (native, wined3d)
  • ✅ Portal 2 (native, wined3d)
  • ✅ Psychonauts (native)

I couldn't reproduce the Psychonauts crash on either X11 or XWayland, so I'm inclined to merge the PR as-is and debug that crash another time. (For future reference, the intro sequences can be skipped by renaming some of the files in the game's movies folder)

All main TODOs have been addressed then. I'll tidy up the commit history after approval since it's clean enough for review.

@neobrain neobrain marked this pull request as ready for review June 10, 2024 15:47
@neobrain neobrain force-pushed the feature_libfwd_gl32 branch from 70a38e8 to 7a703e1 Compare June 11, 2024 15:17
@neobrain neobrain merged commit 4dc8648 into FEX-Emu:main Jun 11, 2024
11 checks passed
@neobrain neobrain deleted the feature_libfwd_gl32 branch June 11, 2024 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants