Better deal with dxvk-nvapi (#230)

This commit is contained in:
Michał Lewandowski
2025-02-24 11:58:11 +01:00
committed by GitHub
parent db86103b44
commit d7845abcbb
5 changed files with 90 additions and 36 deletions
+43 -14
View File
@@ -2292,40 +2292,69 @@ static void CheckQuirks() {
bool isNvidia()
{
bool nvidiaDetected = false;
bool loadedHere = false;
auto nvapiModule = GetModuleHandleW(L"nvapi64.dll");
bool loadedHere = false;
if (!nvapiModule) {
nvapiModule = LoadLibraryExW(L"nvapi64.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
loadedHere = true;
}
// No nvapi, should not be nvidia
if (!nvapiModule)
return false;
NvAPI_Status result = NVAPI_NVIDIA_DEVICE_NOT_FOUND;
if (!nvapiModule) {
LOG_DEBUG("Detected: {}", nvidiaDetected);
return nvidiaDetected;
}
if (auto o_NvAPI_QueryInterface = (PFN_NvApi_QueryInterface)GetProcAddress(nvapiModule, "nvapi_QueryInterface"))
{
auto init = static_cast<decltype(&NvAPI_Initialize)>(o_NvAPI_QueryInterface(GET_ID(NvAPI_Initialize)));
result = init();
if (result == NVAPI_OK)
// dxvk-nvapi calls CreateDxgiFactory which we can't do because we are inside DLL_PROCESS_ATTACH
NvAPI_ShortString desc;
auto* getVersion = GET_INTERFACE(NvAPI_GetInterfaceVersionString, o_NvAPI_QueryInterface);
if (getVersion
&& getVersion(desc) == NVAPI_OK
&& (std::string_view(desc) == std::string_view("NVAPI Open Source Interface (DXVK-NVAPI)") || std::string_view(desc) == std::string_view("DXVK_NVAPI")))
{
if (auto unload = static_cast<decltype(&NvAPI_Unload)>(o_NvAPI_QueryInterface(GET_ID(NvAPI_Unload))))
unload();
LOG_DEBUG("Using dxvk-nvapi");
DISPLAY_DEVICEA dd;
dd.cb = sizeof(dd);
int deviceIndex = 0;
while (EnumDisplayDevicesA(nullptr, deviceIndex, &dd, 0)) {
if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE && std::string_view(dd.DeviceID).contains("VEN_10DE")) {
// Having any Nvidia GPU active will take precedence
nvidiaDetected = true;
}
deviceIndex++;
}
}
else if (o_NvAPI_QueryInterface(GET_ID(Fake_InformFGState)))
{
// Check for fakenvapi in system32, assume it's not nvidia if found
if (o_NvAPI_QueryInterface(GET_ID(Fake_InformFGState)) != nullptr)
return false;
LOG_DEBUG("Using fakenvapi");
nvidiaDetected = false;
}
else
{
LOG_DEBUG("Using Nvidia's nvapi");
auto init = GET_INTERFACE(NvAPI_Initialize, o_NvAPI_QueryInterface);
if (init && init() == NVAPI_OK)
{
nvidiaDetected = true;
if (auto unload = GET_INTERFACE(NvAPI_Unload, o_NvAPI_QueryInterface))
unload();
}
}
}
if (loadedHere)
FreeLibrary(nvapiModule);
return result != NVAPI_NVIDIA_DEVICE_NOT_FOUND;
LOG_DEBUG("Detected: {}", nvidiaDetected);
return nvidiaDetected;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+39 -15
View File
@@ -2248,37 +2248,61 @@ HRESULT WINAPI detEnumAdapters(IDXGIFactory* This, UINT Adapter, IDXGIAdapter**
HRESULT _CreateDXGIFactory(REFIID riid, IDXGIFactory** ppFactory)
{
State::Instance().skipDxgiLoadChecks = true;
HRESULT result = dxgi.CreateDxgiFactory(riid, ppFactory);
State::Instance().skipDxgiLoadChecks = false;
if (dxgi.CreateDxgiFactory) {
HRESULT result = dxgi.CreateDxgiFactory(riid, ppFactory);
State::Instance().skipDxgiLoadChecks = false;
if (result == S_OK)
AttachToFactory(*ppFactory);
if (result == S_OK)
AttachToFactory(*ppFactory);
return result;
return result;
}
else
{
LOG_ERROR("CreateDxgiFactory is NULL");
State::Instance().skipDxgiLoadChecks = false;
return DXGI_ERROR_INVALID_CALL;
}
}
HRESULT _CreateDXGIFactory1(REFIID riid, IDXGIFactory1** ppFactory)
{
State::Instance().skipDxgiLoadChecks = true;
HRESULT result = dxgi.CreateDxgiFactory1(riid, ppFactory);
State::Instance().skipDxgiLoadChecks = false;
if (dxgi.CreateDxgiFactory1) {
HRESULT result = dxgi.CreateDxgiFactory1(riid, ppFactory);
State::Instance().skipDxgiLoadChecks = false;
if (result == S_OK)
AttachToFactory(*ppFactory);
if (result == S_OK)
AttachToFactory(*ppFactory);
return result;
return result;
}
else
{
LOG_ERROR("CreateDxgiFactory1 is NULL");
State::Instance().skipDxgiLoadChecks = false;
return DXGI_ERROR_INVALID_CALL;
}
}
HRESULT _CreateDXGIFactory2(UINT Flags, REFIID riid, IDXGIFactory2** ppFactory)
{
State::Instance().skipDxgiLoadChecks = true;
HRESULT result = dxgi.CreateDxgiFactory2(Flags, riid, ppFactory);
State::Instance().skipDxgiLoadChecks = false;
if (dxgi.CreateDxgiFactory2) {
HRESULT result = dxgi.CreateDxgiFactory2(Flags, riid, ppFactory);
State::Instance().skipDxgiLoadChecks = false;
if (result == S_OK)
AttachToFactory(*ppFactory);
if (result == S_OK)
AttachToFactory(*ppFactory);
return result;
return result;
}
else
{
LOG_ERROR("CreateDxgiFactory2 is NULL");
State::Instance().skipDxgiLoadChecks = false;
return DXGI_ERROR_INVALID_CALL;
}
}
HRESULT _DXGIDeclareAdapterRemovalSupport()
+2 -2
View File
@@ -84,12 +84,12 @@ void* __stdcall NvApiHooks::hkNvAPI_QueryInterface(unsigned int InterfaceId)
{
if (InterfaceId == GET_ID(NvAPI_GPU_GetArchInfo) && !State::Instance().enablerAvailable)
{
o_NvAPI_GPU_GetArchInfo = static_cast<decltype(&NvAPI_GPU_GetArchInfo)>(functionPointer);
o_NvAPI_GPU_GetArchInfo = reinterpret_cast<decltype(&NvAPI_GPU_GetArchInfo)>(functionPointer);
return &hkNvAPI_GPU_GetArchInfo;
}
if (InterfaceId == GET_ID(NvAPI_DRS_GetSetting))
{
o_NvAPI_DRS_GetSetting = static_cast<decltype(&NvAPI_DRS_GetSetting)>(functionPointer);
o_NvAPI_DRS_GetSetting = reinterpret_cast<decltype(&NvAPI_DRS_GetSetting)>(functionPointer);
return &hkNvAPI_DRS_GetSetting;
}
}
+1
View File
@@ -6,6 +6,7 @@
#include <nvapi.h>
#define GET_ID(name) NvApiTypes::Instance().getId(#name)
#define GET_INTERFACE(name, queryInterface) reinterpret_cast<decltype(&name)>(queryInterface(GET_ID(name)))
typedef void* (__stdcall* PFN_NvApi_QueryInterface)(unsigned int InterfaceId);
typedef NvAPI_Status(__stdcall* PFN_Fake_InformFGState)(bool fg_state);
+5 -5
View File
@@ -91,11 +91,11 @@ void ReflexHooks::hookReflex(PFN_NvApi_QueryInterface& queryInterface) {
#endif
if (!_inited) {
o_NvAPI_D3D_SetSleepMode = static_cast<decltype(&NvAPI_D3D_SetSleepMode)>(queryInterface(GET_ID(NvAPI_D3D_SetSleepMode)));
o_NvAPI_D3D_Sleep = static_cast<decltype(&NvAPI_D3D_Sleep)>(queryInterface(GET_ID(NvAPI_D3D_Sleep)));
o_NvAPI_D3D_GetLatency = static_cast<decltype(&NvAPI_D3D_GetLatency)>(queryInterface(GET_ID(NvAPI_D3D_GetLatency)));
o_NvAPI_D3D_SetLatencyMarker = static_cast<decltype(&NvAPI_D3D_SetLatencyMarker)>(queryInterface(GET_ID(NvAPI_D3D_SetLatencyMarker)));
o_NvAPI_D3D12_SetAsyncFrameMarker = static_cast<decltype(&NvAPI_D3D12_SetAsyncFrameMarker)>(queryInterface(GET_ID(NvAPI_D3D12_SetAsyncFrameMarker)));
o_NvAPI_D3D_SetSleepMode = GET_INTERFACE(NvAPI_D3D_SetSleepMode, queryInterface);
o_NvAPI_D3D_Sleep = GET_INTERFACE(NvAPI_D3D_Sleep, queryInterface);
o_NvAPI_D3D_GetLatency = GET_INTERFACE(NvAPI_D3D_GetLatency, queryInterface);
o_NvAPI_D3D_SetLatencyMarker = GET_INTERFACE(NvAPI_D3D_SetLatencyMarker, queryInterface);
o_NvAPI_D3D12_SetAsyncFrameMarker = GET_INTERFACE(NvAPI_D3D12_SetAsyncFrameMarker, queryInterface);
_inited = o_NvAPI_D3D_SetSleepMode && o_NvAPI_D3D_Sleep && o_NvAPI_D3D_GetLatency && o_NvAPI_D3D_SetLatencyMarker && o_NvAPI_D3D12_SetAsyncFrameMarker;