protonscr

Disable nvapi/nvapi64 by default

protonclosed
ValveSoftware/Proton#165 · opened 2018-08-22 by AccountOneOff · updated 2020-04-09 · 9 comments · github
3 matching comments, n / p to jump
AAccountOneOff 2018-08-22 github

Doitsujin recommends disabling nvapi/nvapi64 when using DXVK but Proton does not set this override. The Flame in the Flood runs at 18fps in the menu because of this and at 60fps with nvapi disabled. I haven't tested in-game yet.

Log: steam-318600.zip

screenshot from 2018-08-22 13-56-53

Rromulasry 2018-08-22 github

Great idea!

Kkode54 2018-08-27 github

Maybe this is related to #336 ? Can someone tell me how to disable nvapi/nvapi64 to test this with that? It only runs full speed in wine-staging, which doesn't have dxvk.

E: Tested, unrelated. Does not fix #336.

Incidentally, nvapi/nvapi64 is what makes it possible for PhysX to work on NVidia Linux drivers, but that's the extent that the implementation provides. I guess it doesn't work too well while running Vulkan?

Kkisak-valve maintainer 2018-09-06 github

UE4 games constantly searches for nvapi64.dll/nvapi64.dll.so

Issue transferred from https://github.com/ValveSoftware/Proton/issues/1290.
@lieff posted on 2018-09-06T22:15:08:

Form https://github.com/ValveSoftware/Proton/issues/1178 and https://github.com/doitsujin/dxvk/issues/622#issuecomment-419256413 .
It seems one of UE4 threads do constant directory scan in search of nvapi64.dll/nvapi64.dll.so

stat(".../SteamLibrary/steamapps/compatdata/414340/pfx/dosdevices/c:/windows/system32/nvapi64.dll", 0x171be330) = -1 ENOENT (No such file or directory)
stat(".../SteamLibrary/steamapps/compatdata/414340/pfx/dosdevices/c:/windows", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
stat(".../SteamLibrary/steamapps/compatdata/414340/pfx/dosdevices/c:/windows/system32", {st_mode=S_IFDIR|0775, st_size=49152, ...}) = 0
stat(".../SteamLibrary/steamapps/compatdata/414340/pfx/dosdevices/c:/windows/system32/nvapi64.dll", 0x171be3c0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, ".../SteamLibrary/steamapps/compatdata/414340/pfx/dosdevices/c:/windows/system32", O_RDONLY|O_DIRECTORY) = 4529
ioctl(4529, VFAT_IOCTL_READDIR_BOTH, 0x121000) = -1 ENOTTY (Inappropriate ioctl for device)
close(4529)                             = 0
openat(AT_FDCWD, ".../SteamLibrary/steamapps/compatdata/414340/pfx/dosdevices/c:/windows/system32", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 4529
fstat(4529, {st_mode=S_IFDIR|0775, st_size=49152, ...}) = 0
getdents(4529, /* 799 entries */, 32768) = 32752 << directory scan in inner loop!
getdents(4529, /* 86 entries */, 32768) = 3632
getdents(4529, /* 0 entries */, 32768)  = 0
close(4529)                             = 0

What affects performance.

Llieff 2018-09-06 github

Can confirm, no UE4 directory scans with nvapi/nvapi64 disabled.

Llieff 2018-09-07 github

I've checked Unreal source. Problem seems in D3D11RHI module.
There lot of code under IsRHIDeviceNVIDIA() check to handle SLI etc which uses NvAPI_* from nvapi.lib/nvapi64.lib. Even with disabled nvapi it still tries LoadLibrary("nvapi.dll").
If game do not calls FD3D11Texture3D too often disable nvapi approach helps, but if it uses even very simple function often in inner loop - even with disabled nvapi this path can decrease performance.
So nvapi stub or fake AMD card is better solution.

This can be fixed in UE as well. We just can transform checks from

if (IsRHIDeviceNVIDIA())
{
    NvAPI_call()->
    {
        if (!g_lib)
            g_lib = LoadLibrary("nvapi.dll");
        ...call from dll
    }
}

to

static bool GNVAPIChecked = false;
static bool GNVAPIAvailable = false;

bool IsNVAPIAvailable()
{
    if (GNVAPIChecked)
        return GNVAPIAvailable;
    if (IsRHIDeviceNVIDIA() && NVAPI_Loads())
        GNVAPIAvailable = true;
    GNVAPIChecked = true;
}

if (IsNVAPIAvailable())
{
    NvAPI_call()->
    {
        if (!g_lib)
            g_lib = LoadLibrary("nvapi.dll");
        ...call from dll
    }
}
Jjarrard 2018-09-07 github

what happens if we just grab nvapi dll's and toss it in the desired path? will it just continue without issue?

Ppchome 2018-09-08 github

Could it help if we'll have nvapi fake-dlls in system32 and syswow64 directories, and nvapi disabled?

Fake dlls can be generated quite simple, e.g. :

$ winebuild -m64 --dll --fake-module -o nvapi64.dll
$ winebuild -m32 --dll --fake-module -o nvapi.dll

Wine looking for requested dll wherever possible before "Load Order" logic will act (see load_dll and find_dll_file).

Disabling nvapi should prevent further searching for builtin nvapi.dll.so, or any actions with nvapi.dll as real dll file, and will return STATUS_DLL_NOT_FOUND immediately.

For UE4 result will be the same, but the way should be shorter.

Ppchome 2018-09-12 github

An hack for proton+nvapi.

Enable/disable nvapi w/ PROTON_USE_NVAPI variable.

Ppchome 2018-09-13 github

And you can build nvapi only, w/o needing to build/install wine-staging.

@aeikum
If you plan to include nvapi in Proton, this example can help you to integrate it in current Proton build process.
As well as hack mentioned above. Both of them together can behave same as DXVK in Proton.

Also there is an option (meson configure -Denable_d3d11=false) to build nvapi using only wined3d, which can be used for PROTON_NO_D3D11=1 needs (or even for DXVK, not sure).

I'm going to use those hacks locally for my own needs, but hope they will be useful to solve nvapi issues in Proton.