Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ValveSoftware/Proton.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiam Middlebrook <lmiddlebrook@nvidia.com>2021-05-11 07:53:15 +0300
committerAndrew Eikum <aeikum@codeweavers.com>2021-08-17 18:11:32 +0300
commit0afcb194167b4168a44733fe09cc5eea8f8996be (patch)
tree386f63144902fedf83abe6d6bfeec2b11827c619
parent16308114747bc5f4852d081a259a5ed528a63be3 (diff)
proton: Copy DLLs provided by the NVIDIA driver into prefixproton-6.3-6-rc4proton-6.3-6proton_6.3-next
The upcoming NVIDIA 470 driver series will introduce a DLL (nvngx.dll) for the support of NVIDIA DLSS in Proton. This change adds logic for discovering the location of DLL files provided by the NVIDIA driver, and copies them to C:\Windows\System32\ Reviewed-by: Adam Moss <amoss@nvidia.com>
-rwxr-xr-xproton107
1 files changed, 106 insertions, 1 deletions
diff --git a/proton b/proton
index 52fc1869..62d304f8 100755
--- a/proton
+++ b/proton
@@ -15,6 +15,15 @@ import subprocess
import sys
import tarfile
+from ctypes import CDLL
+from ctypes import POINTER
+from ctypes import Structure
+from ctypes import addressof
+from ctypes import cast
+from ctypes import c_int
+from ctypes import c_char_p
+from ctypes import c_void_p
+
from filelock import FileLock
from random import randrange
@@ -99,7 +108,7 @@ def merge_user_dir(src, dst):
else:
extant_dirs += dst_dir
-def try_copy(src, dst, add_write_perm=True, copy_metadata=True):
+def try_copy(src, dst, add_write_perm=True, copy_metadata=True, optional=False):
try:
if os.path.isdir(dst):
dstfile = dst + "/" + os.path.basename(src)
@@ -119,6 +128,12 @@ def try_copy(src, dst, add_write_perm=True, copy_metadata=True):
new_mode = os.lstat(dstfile).st_mode | stat.S_IWUSR | stat.S_IWGRP
os.chmod(dstfile, new_mode)
+ except FileNotFoundError as e:
+ if optional:
+ log('Error while copying to \"' + dst + '\": ' + e.strerror)
+ else:
+ raise
+
except PermissionError as e:
if e.errno == errno.EPERM:
#be forgiving about permissions errors; if it's a real problem, things will explode later anyway
@@ -162,6 +177,87 @@ def try_get_game_library_dir():
return None
+# Function to find the installed location of DLL files for use by Wine/Proton
+# from the NVIDIA Linux driver
+#
+# See https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/issues/71 for
+# background on the chosen method of DLL discovery.
+#
+# On success, returns a str() of the absolute-path to the directory at which DLL
+# files are stored
+#
+# On failure, returns None
+def find_nvidia_wine_dll_dir():
+ try:
+ libdl = CDLL("libdl.so.2")
+ except (OSError):
+ return None
+
+ try:
+ libglx_nvidia = CDLL("libGLX_nvidia.so.0")
+ except OSError:
+ return None
+
+ # from dlinfo(3)
+ #
+ # struct link_map {
+ # ElfW(Addr) l_addr; /* Difference between the
+ # address in the ELF file and
+ # the address in memory */
+ # char *l_name; /* Absolute pathname where
+ # object was found */
+ # ElfW(Dyn) *l_ld; /* Dynamic section of the
+ # shared object */
+ # struct link_map *l_next, *l_prev;
+ # /* Chain of loaded objects */
+ #
+ # /* Plus additional fields private to the
+ # implementation */
+ # };
+ RTLD_DI_LINKMAP = 2
+ class link_map(Structure):
+ _fields_ = [("l_addr", c_void_p), ("l_name", c_char_p), ("l_ld", c_void_p)]
+
+ # from dlinfo(3)
+ #
+ # int dlinfo (void *restrict handle, int request, void *restrict info)
+ dlinfo_func = libdl.dlinfo
+ dlinfo_func.argtypes = c_void_p, c_int, c_void_p
+ dlinfo_func.restype = c_int
+
+ # Allocate a link_map object
+ glx_nvidia_info_ptr = POINTER(link_map)()
+
+ # Run dlinfo(3) on the handle to libGLX_nvidia.so.0, storing results at the
+ # address represented by glx_nvidia_info_ptr
+ if dlinfo_func(libglx_nvidia._handle,
+ RTLD_DI_LINKMAP,
+ addressof(glx_nvidia_info_ptr)) != 0:
+ return None
+
+ # Grab the contents our of our pointer
+ glx_nvidia_info = cast(glx_nvidia_info_ptr, POINTER(link_map)).contents
+
+ # Decode the path to our library to a str()
+ if glx_nvidia_info.l_name is None:
+ return None
+ try:
+ libglx_nvidia_path = os.fsdecode(glx_nvidia_info.l_name)
+ except UnicodeDecodeError:
+ return None
+
+ # Follow any symlinks to the actual file
+ libglx_nvidia_realpath = os.path.realpath(libglx_nvidia_path)
+
+ # Go to the relative path ./nvidia/wine from our library
+ nvidia_wine_dir = os.path.join(os.path.dirname(libglx_nvidia_realpath), "nvidia", "wine")
+
+ # Check that nvngx.dll exists here, or fail
+ if os.path.exists(os.path.join(nvidia_wine_dir, "nvngx.dll")):
+ return nvidia_wine_dir
+
+ return None
+
EXT2_IOC_GETFLAGS = 0x80086601
EXT2_IOC_SETFLAGS = 0x40086602
@@ -705,6 +801,15 @@ class CompatData:
if os.path.exists(nvapi32_dll):
os.unlink(nvapi32_dll)
+ # Try to detect known DLLs that ship with the NVIDIA Linux Driver
+ # and add them into the prefix
+ nvidia_wine_dll_dir = find_nvidia_wine_dll_dir()
+ if nvidia_wine_dll_dir:
+ for dll in ["_nvngx.dll", "nvngx.dll"]:
+ try_copy(nvidia_wine_dll_dir + "/" + dll,
+ self.prefix_dir + "drive_c/windows/system32/" + dll,
+ optional=True)
+
try_copy(g_proton.lib64_dir + "wine/vkd3d-proton/d3d12.dll",
self.prefix_dir + "drive_c/windows/system32/d3d12.dll")
try_copy(g_proton.lib_dir + "wine/vkd3d-proton/d3d12.dll",