diff options
author | Jens Peters <jp7677@gmail.com> | 2021-12-05 10:19:17 +0300 |
---|---|---|
committer | Jens Peters <jp7677@gmail.com> | 2021-12-05 15:51:17 +0300 |
commit | ca6c35bfc48d452a42d099e9f43d2cdace290738 (patch) | |
tree | fa29cc418b3bd1adb8c492695d1b677f14a22d39 | |
parent | fe232dcf2c0bc5d8e1de93c1c490320630d21ee7 (diff) |
nvapi: Report GPUs with NVIDIAs proprietary driver only
This matches Windows behavior and may avoid reports about version number mismatch when using other vendors.
Introduce 'DXVK_NVAPI_ALLOW_OTHER_DRIVERS' environment variable to enable the old behavior.
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | src/sysinfo/nvapi_adapter.cpp | 10 | ||||
-rw-r--r-- | tests/nvapi_d3d12.cpp | 4 | ||||
-rw-r--r-- | tests/nvapi_sysinfo.cpp | 51 |
4 files changed, 54 insertions, 18 deletions
@@ -15,7 +15,7 @@ While originally being developed for usage with Unreal Engine 4, most notably fo ## Requirements -This implementation is supposed to be used on Linux using Wine or derivatives like Proton. Usage on Windows is discouraged. Please do not replace `nvapi.dll`/`nvapi64.dll` on Windows from NVIDIA's driver package with this version. DXVK-NVAPI uses several DXVK and VKD3D-Proton extension points, thus using DXVK (D3D11 and DXGI) is a requirement. Using Wine's D3D11 or DXGI will fail. Usage of DXVK-NVAPI is not restricted to NVIDIA GPUs, but some entry points offer no functionality when a different GPU vendor is detected. +This implementation is supposed to be used on Linux using Wine or derivatives like Proton. Usage on Windows is discouraged. Please do not replace `nvapi.dll`/`nvapi64.dll` on Windows from NVIDIA's driver package with this version. DXVK-NVAPI uses several DXVK and VKD3D-Proton extension points, thus using DXVK (D3D11 and DXGI) is a requirement. Using Wine's D3D11 or DXGI will fail. Usage of DXVK-NVAPI is not restricted to NVIDIA GPUs, though the default behavior is to report only NVIDIA GPUs. Some entry points offer no functionality when a different GPU vendor is detected. When available, DXVK-NVAPI uses NVIDIA's NVML management library to query temperature, utilization and others for NVIDIA GPUs. See [wine-nvml](https://github.com/Saancreed/wine-nvml) how to add NVML support to Wine/Proton. @@ -62,17 +62,18 @@ Wine does not includes DXVK-NVAPI. - Ensure that Wine uses DXVK's `dxgi.dll`, e.g. with `WINEDLLOVERRIDES=dxgi=n`. - Disable the `nvapiHack` in DXVK with `dxgi.nvapiHack = False` set in a DXVK configuration file, see [dxvk.conf](https://github.com/doitsujin/dxvk/blob/master/dxvk.conf#L51). -## Debugging and troubleshooting +## Tweaks, debugging and troubleshooting See [Quirks-for-usage-with-DXVK-NVAPI](https://github.com/jp7677/dxvk-nvapi/wiki/Quirks-for-usage-with-DXVK-NVAPI) for any known quirks or work arounds. The following environment variables tweak DXVK-NVAPI's runtime behavior: - `DXVK_NVAPI_DRIVER_VERSION` lets you override the reported driver version. Valid values are numbers between 100 and 99999. Use e.g. `DXVK_NVAPI_DRIVER_VERSION=47141` to report driver version `471.41`. +- `DXVK_NVAPI_ALLOW_OTHER_DRIVERS` - lets you use DXVK-NVAPI without running an NVIDIA card on NVIDIAs proprietary driver when set, e.g. `DXVK_NVAPI_ALLOW_OTHER_DRIVERS=1`. Useful for using e.g. D3D11 extension on a non-NVIDIA GPU. - `DXVK_NVAPI_LOG_LEVEL` set to `info` prints log statements. The default behavior omits any logging. Please fill an issue if using log servery `info` creates log spam. There are no other log levels. - `DXVK_NVAPI_LOG_PATH` enables file logging additionally to console output and sets the path where the log file `dxvk-nvapi.log` should be written to. Log statements are appended to an existing file. Please remove this file once in a while to prevent excessive grow. This requires `DXVK_NVAPI_LOG_LEVEL` set to `info`. -This project provides a test suite. Run the package script with `--enable-tests` (see above) to build `nvapi64-tests.exe`. Running the tests executable without arguments queries the local system and provides system information about visible GPU's: +This project provides a test suite. Run the package script with `--enable-tests` (see above) to build `nvapi64-tests.exe`. Running the tests executable without arguments queries the local system and provides system information about visible GPUs: ```bash DXVK_LOG_LEVEL=none WINEDEBUG=-all WINEDLLOVERRIDES=dxgi,nvapi64=n wine nvapi64-tests.exe diff --git a/src/sysinfo/nvapi_adapter.cpp b/src/sysinfo/nvapi_adapter.cpp index d41c796..9c9f4cf 100644 --- a/src/sysinfo/nvapi_adapter.cpp +++ b/src/sysinfo/nvapi_adapter.cpp @@ -12,6 +12,7 @@ namespace dxvk { bool NvapiAdapter::Initialize(Com<IDXGIAdapter1>& dxgiAdapter, std::vector<NvapiOutput*>& outputs) { constexpr auto driverVersionEnvName = "DXVK_NVAPI_DRIVER_VERSION"; + constexpr auto allowOtherDriversEnvName = "DXVK_NVAPI_ALLOW_OTHER_DRIVERS"; // Get the Vulkan handle from the DXGI adapter to get access to Vulkan device properties which has some information we want. Com<IDXGIVkInteropAdapter> dxgiVkInteropAdapter; @@ -68,6 +69,13 @@ namespace dxvk { m_vulkan.GetPhysicalDeviceMemoryProperties2(vkInstance, vkDevice, &memoryProperties2); m_memoryProperties = memoryProperties2.memoryProperties; + auto allowOtherDrivers = env::getEnvVariable(allowOtherDriversEnvName); + if (!allowOtherDrivers.empty()) + log::write(str::format(allowOtherDrivers, " is set, reporting also GPUs with non-NVIDIA proprietary driver.")); + + if (GetDriverId() != VK_DRIVER_ID_NVIDIA_PROPRIETARY && allowOtherDrivers.empty()) + return false; + if (GetDriverId() == VK_DRIVER_ID_NVIDIA_PROPRIETARY) // Handle NVIDIA version notation m_vkDriverVersion = VK_MAKE_VERSION( @@ -114,7 +122,7 @@ namespace dxvk { if (std::string(end).empty() && driverVersionOverride >= 100 && driverVersionOverride <= 99999) { std::stringstream stream; stream << (driverVersionOverride / 100) << "." << std::setfill('0') << std::setw(2) << (driverVersionOverride % 100); - log::write(str::format(driverVersionEnvName, " is set to '", driverVersion, "', reporting driver version ", stream.str())); + log::write(str::format(driverVersionEnvName, " is set to '", driverVersion, "', reporting driver version ", stream.str(), ".")); m_driverVersionOverride = driverVersionOverride; } else diff --git a/tests/nvapi_d3d12.cpp b/tests/nvapi_d3d12.cpp index 872b9aa..b344f04 100644 --- a/tests/nvapi_d3d12.cpp +++ b/tests/nvapi_d3d12.cpp @@ -159,6 +159,8 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") { Data{VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, 0, 0}, Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, "ext", 0, 0}); + ::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", "1"); + luid->HighPart = 0x00000002; luid->LowPart = 0x00000001; @@ -185,6 +187,8 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") { REQUIRE(graphicsCaps.majorSMVersion == args.expectedMajorSMVersion); REQUIRE(graphicsCaps.minorSMVersion == args.expectedMinorSMVersion); REQUIRE(deviceRefCount == 0); + + ::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", ""); } } diff --git a/tests/nvapi_sysinfo.cpp b/tests/nvapi_sysinfo.cpp index 1e21085..d1f062c 100644 --- a/tests/nvapi_sysinfo.cpp +++ b/tests/nvapi_sysinfo.cpp @@ -12,27 +12,42 @@ TEST_CASE("GetErrorMessage returns OK", "[.sysinfo]") { REQUIRE(strcmp(desc, "NVAPI_NVIDIA_DEVICE_NOT_FOUND") == 0); } -TEST_CASE("Initialize returns device-not-found when DXVK reports no adapters", "[.sysinfo]") { +TEST_CASE("Initialize succeed", "[.sysinfo]") { auto dxgiFactory = std::make_unique<DXGIFactory1Mock>(); auto vulkan = std::make_unique<VulkanMock>(); auto nvml = std::make_unique<NvmlMock>(); + DXGIDxvkAdapterMock adapter; + DXGIOutputMock output; + + auto e = ConfigureDefaultTestEnvironment(*dxgiFactory, *vulkan, *nvml, adapter, output); - ALLOW_CALL(*dxgiFactory, AddRef()) - .RETURN(1); - ALLOW_CALL(*dxgiFactory, Release()) - .RETURN(0); - ALLOW_CALL(*dxgiFactory, EnumAdapters1(_, _)) - .RETURN(DXGI_ERROR_NOT_FOUND); + SECTION("Initialize returns OK") { + SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml)); + REQUIRE(NvAPI_Initialize() == NVAPI_OK); + REQUIRE(NvAPI_Unload() == NVAPI_OK); + } - ALLOW_CALL(*vulkan, IsAvailable()) - .RETURN(true); + SECTION("Initialize returns device-not-found when DXVK reports no adapters") { + ALLOW_CALL(*dxgiFactory, EnumAdapters1(_, _)) // NOLINT(bugprone-use-after-move) + .RETURN(DXGI_ERROR_NOT_FOUND); - ALLOW_CALL(*nvml, IsAvailable()) - .RETURN(false); + SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml)); + REQUIRE(NvAPI_Initialize() == NVAPI_NVIDIA_DEVICE_NOT_FOUND); + REQUIRE(NvAPI_Unload() == NVAPI_API_NOT_INITIALIZED); + } - SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml)); - REQUIRE(NvAPI_Initialize() == NVAPI_NVIDIA_DEVICE_NOT_FOUND); - REQUIRE(NvAPI_Unload() == NVAPI_API_NOT_INITIALIZED); + SECTION("Initialize returns device-not-found when adapter with non NVIDIA driver ID has been found") { + ALLOW_CALL(*vulkan, GetPhysicalDeviceProperties2(_, _, _)) // NOLINT(bugprone-use-after-move) + .SIDE_EFFECT( + ConfigureGetPhysicalDeviceProperties2(_3, + [](auto props, auto idProps, auto pciBusInfoProps, auto driverProps, auto fragmentShadingRateProps) { + driverProps->driverID = VK_DRIVER_ID_MESA_RADV; + })); + + SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml)); + REQUIRE(NvAPI_Initialize() == NVAPI_NVIDIA_DEVICE_NOT_FOUND); + REQUIRE(NvAPI_Unload() == NVAPI_API_NOT_INITIALIZED); + } } TEST_CASE("Topology methods succeed", "[.sysinfo]") { @@ -251,6 +266,8 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 470, 101, 1, 47099}, Data{VK_DRIVER_ID_AMD_OPEN_SOURCE, 21, 2, 3, 2102}); + ::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", "1"); + ALLOW_CALL(*vulkan, GetPhysicalDeviceProperties2(_, _, _)) // NOLINT(bugprone-use-after-move) .SIDE_EFFECT( ConfigureGetPhysicalDeviceProperties2(_3, @@ -275,6 +292,8 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { REQUIRE(version.drvVersion == args.expectedVersion); REQUIRE(strcmp(version.szAdapterString, "GPU0") == 0); REQUIRE(std::string(version.szBuildBranchString).length() > 0); + + ::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", "0"); } SECTION("GetDisplayDriverVersion with version override returns OK") { @@ -480,6 +499,8 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { } SECTION("GetArchInfo returns device-not-found when no NVIDIA device is present") { + ::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", "1"); + ALLOW_CALL(*vulkan, GetPhysicalDeviceProperties2(_, _, _)) // NOLINT(bugprone-use-after-move) .SIDE_EFFECT( ConfigureGetPhysicalDeviceProperties2(_3, @@ -496,6 +517,8 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { NV_GPU_ARCH_INFO archInfo; archInfo.version = NV_GPU_ARCH_INFO_VER_2; REQUIRE(NvAPI_GPU_GetArchInfo(handle, &archInfo) == NVAPI_NVIDIA_DEVICE_NOT_FOUND); + + ::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", "0"); } SECTION("NVML depending methods succeed when NVML is available") { |