From aecf295b12a0c1768a7309f157058d1e7e1d7dfc Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Tue, 8 Oct 2019 20:02:33 +1100 Subject: [PATCH] make `GPUModel.h` for GPU model/architecture detection, use GPU architecture detection for launcher GPU support detection (and also ShaderPatch) --- source-code/dependencies/GPUModel/GPUModel.h | 58 +++++++++++++++++++ .../PluginConfigApi/PluginConfigApi.h | 4 ++ .../source/plugins/Launcher/Launcher.vcxproj | 4 +- source-code/source/plugins/Launcher/ui.h | 51 ++++++++++------ .../plugins/ShaderPatch/ShaderPatch.vcxproj | 4 +- .../plugins/ShaderPatch/src/dllmain.cpp | 47 +-------------- .../plugins/ShaderPatch/src/framework.h | 8 --- 7 files changed, 102 insertions(+), 74 deletions(-) create mode 100644 source-code/dependencies/GPUModel/GPUModel.h diff --git a/source-code/dependencies/GPUModel/GPUModel.h b/source-code/dependencies/GPUModel/GPUModel.h new file mode 100644 index 0000000..7fb6157 --- /dev/null +++ b/source-code/dependencies/GPUModel/GPUModel.h @@ -0,0 +1,58 @@ +/* +Simple header for detecting Nvidia GPU models +*/ + +namespace GPUModel +{ + #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + #include + #include + + void*(*NvAPI_QueryInterface)(unsigned int offset) = NULL; + int(*NvAPI_Initialize)() = NULL; + int(*NvAPI_Unload)() = NULL; + int(*NvAPI_EnumPhysicalGPUs)(int64_t** handle, int* count) = NULL; + int(*NvAPI_GPU_GetShortName)(int64_t* handle, char* name) = NULL; + + std::string getGpuName() + { + NvAPI_QueryInterface = (void*(*)(unsigned int offset))GetProcAddress(LoadLibraryW(L"nvapi64.dll"), "nvapi_QueryInterface"); + + if (NvAPI_QueryInterface == nullptr) + { + return "Other"; + } + + NvAPI_Initialize = (int(*)())NvAPI_QueryInterface(0x0150E828); + NvAPI_Unload = (int(*)()) NvAPI_QueryInterface(0xD22BDD7E); + NvAPI_EnumPhysicalGPUs = (int(*)(int64_t** handle, int* count))NvAPI_QueryInterface(0xE5AC921F); + NvAPI_GPU_GetShortName = (int(*)(int64_t* handle, char* name))NvAPI_QueryInterface(0xD988F0F3); + + if (NvAPI_Initialize == nullptr || + NvAPI_Unload == nullptr || + NvAPI_EnumPhysicalGPUs == nullptr || + NvAPI_GPU_GetShortName == nullptr) + { + return "Unknown"; + } + + int64_t* hdlGpu[64] = { 0 }; + int nGpu = 0; + + NvAPI_Initialize(); + NvAPI_EnumPhysicalGPUs(hdlGpu, &nGpu); + + //printf("[ShaderPatch] nGpu: %d\n", nGpu); + if (nGpu < 1) + { + NvAPI_Unload(); + return "Unknown"; + } + + char nameBuf[64]; + NvAPI_GPU_GetShortName(hdlGpu[0], nameBuf); + NvAPI_Unload(); + + return std::string(nameBuf); + } +} \ No newline at end of file diff --git a/source-code/dependencies/PluginConfigApi/PluginConfigApi.h b/source-code/dependencies/PluginConfigApi/PluginConfigApi.h index bb39dca..7c1f0e2 100644 --- a/source-code/dependencies/PluginConfigApi/PluginConfigApi.h +++ b/source-code/dependencies/PluginConfigApi/PluginConfigApi.h @@ -1,3 +1,7 @@ +/* +PD Loader Launcher Plugin Information Structs +*/ + #pragma once #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include diff --git a/source-code/source/plugins/Launcher/Launcher.vcxproj b/source-code/source/plugins/Launcher/Launcher.vcxproj index fef5717..a430bf6 100644 --- a/source-code/source/plugins/Launcher/Launcher.vcxproj +++ b/source-code/source/plugins/Launcher/Launcher.vcxproj @@ -111,7 +111,7 @@ Level3 Disabled _DEBUG;%(PreprocessorDefinitions) - ..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) stdcpp17 @@ -142,7 +142,7 @@ Level3 NDEBUG;%(PreprocessorDefinitions) - ..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) stdcpp17 diff --git a/source-code/source/plugins/Launcher/ui.h b/source-code/source/plugins/Launcher/ui.h index fd610d1..b355042 100644 --- a/source-code/source/plugins/Launcher/ui.h +++ b/source-code/source/plugins/Launcher/ui.h @@ -7,6 +7,7 @@ #include #include "SkinnedMessageBox.h" #include "PluginConfig.h" +#include "GPUModel.h"" namespace Launcher { @@ -155,6 +156,8 @@ namespace Launcher { String^ renderer = gcnew String((char*)glGetString(GL_RENDERER)); String^ version = gcnew String((char*)glGetString(GL_VERSION)); + String^ gpuModel = gcnew String(GPUModel::getGpuName().c_str()); + glutDestroyWindow(window); // destroy the window so it doesn't remain on screen if (glutMainLoopEventDynamic != NULL) glutMainLoopEventDynamic(); // freeglut needs this @@ -163,37 +166,51 @@ namespace Launcher { this->labelGPU->Text += "OpenGL: " + version + "\n"; int linkStart = this->labelGPU->Text->Length; - if (!vendor->Contains("NVIDIA")) + if (!vendor->Contains("NVIDIA")) // check OpenGL renderer to get actual GPU being used for vendor check (ensure not running on iGPU) { this->labelGPU->Text += "Issues: NVIDIA GPU REQUIRED!"; - GPUIssueText = "Your graphics card is not supported! Only NVIDIA GPUs can run the game.\nPlease use a GTX 600 series or later GPU."; + GPUIssueText = "Your graphics card is not supported! Only NVIDIA GPUs can run the game.\nPlease use a GTX 600 series or later GPU.\n\nIf you have a laptop with an NVIDIA GPU, you may need to set diva.exe to use it in NVIDIA Control Panel."; this->labelGPU->LinkColor = System::Drawing::Color::Red; SkinnedMessageBox::Show(this, GPUIssueText, "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Warning); } - else if (version[0] < '4') - { - this->labelGPU->Text += "Issues: GPU too old! 3D rendering might be broken.\n(Click for more information)"; - GPUIssueText = "Your GPU is very old and does not support a recent enough version of OpenGL.\nPlease upgrade to a GTX 600 series or later GPU."; - this->labelGPU->LinkColor = System::Drawing::Color::Orange; - } - else if (renderer->Contains("RTX") || renderer->Contains("GTX 16")) + else if (gpuModel->StartsWith("TU")) { this->labelGPU->Text += "Issues: Turing GPU detected! Possible noise.\n(Click for more information)"; - GPUIssueText = "On Turing GPUs (RTX/GTX 1600), some of the important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled."; + GPUIssueText = "On Turing GPUs (RTX/GTX 1600), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled."; this->labelGPU->LinkColor = System::Drawing::Color::Yellow; } - // these GPU names aren't exact, but they cover most generations reasonably well - else if (renderer->Contains("GTX 8") || renderer->Contains("GTX 9") || renderer->Contains("TITAN X") || renderer->Contains("GTX 10") || renderer->Contains("TITAN V")) + else if (gpuModel->StartsWith("GM") || gpuModel->StartsWith("GP") || gpuModel->StartsWith("GV")) { this->labelGPU->Text += "Issues: May have minor noise on some stages.\n(Click for more information)"; - GPUIssueText = "On Maxwell GPUs (~GTX 900) or newer, some minor stage shaders create noise.\nWhile not certain, it is likely that your GPU is affected.\nPlease make sure the ShaderPatch plugin is enabled."; + GPUIssueText = "On Maxwell GPUs (~GTX 900) or newer, some minor stage shaders create noise.\nPlease make sure the ShaderPatch plugin is enabled."; this->labelGPU->LinkColor = System::Drawing::Color::Yellow; } - else + else if (gpuModel->StartsWith("GF") || gpuModel->StartsWith("GK")) { - this->labelGPU->Text += "Issues: None."; - GPUIssueText = "Your GPU should have no issues running the game."; - this->labelGPU->LinkColor = System::Drawing::Color::Lime; + if (version[0] < '4') + { + this->labelGPU->Text += "Issues: Driver too old."; + GPUIssueText = "Your GPU should have no issues running the game, but it looks like your OpenGL version is too old.\nA driver update should fix this."; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; + } + else + { + this->labelGPU->Text += "Issues: None."; + GPUIssueText = "Your GPU should have no issues running the game."; + this->labelGPU->LinkColor = System::Drawing::Color::Lime; + } + } + else if (gpuModel->StartsWith("G") || gpuModel->StartsWith("NV")) + { + this->labelGPU->Text += "Issues: GPU too old! 3D rendering might be broken.\n(Click for more information)"; + GPUIssueText = "Your GPU is very old and does not support rendering techniques used by the game.\nYou may be able to play, but graphics will likely have major issues.\nPlease upgrade to a GTX 600 series or later GPU."; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; + } + else //if (gpuModel->Length == 0 || gpuModel->StartsWith("Unk") || gpuModel->StartsWith("Oth")) + { + this->labelGPU->Text += "Issues: Unable to detect GPU architecture.\n(Click for more information)"; + GPUIssueText = "It looks like you have an NVIDIA GPU, but something went wrong while trying to determine your GPU's architecture (type).\nThis may be a caused by a bug, but it probably indicates potential issues.\nPlease make sure you have a GTX 600 series or later GPU. (GTX 400 series or later should also work)"; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; } int linkEnd = this->labelGPU->Text->Length - linkStart; diff --git a/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj b/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj index b015031..442f3fe 100644 --- a/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj +++ b/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj @@ -86,7 +86,7 @@ Level3 Disabled true - ..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi ..\..\..\dependencies\detours\lib @@ -112,7 +112,7 @@ true true true - ..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi true diff --git a/source-code/source/plugins/ShaderPatch/src/dllmain.cpp b/source-code/source/plugins/ShaderPatch/src/dllmain.cpp index a86d1c8..ff325e6 100644 --- a/source-code/source/plugins/ShaderPatch/src/dllmain.cpp +++ b/source-code/source/plugins/ShaderPatch/src/dllmain.cpp @@ -3,6 +3,7 @@ #include "framework.h" #include "PluginConfigApi.h" +#include "GPUModel.h" #include "detours.h" #pragma comment(lib, "detours.lib") @@ -29,51 +30,7 @@ void NopBytes(void* address, unsigned int num) } -void loadGpuName() -{ - NvAPI_QueryInterface = (void*(*)(unsigned int offset))GetProcAddress(LoadLibrary("nvapi64.dll"), "nvapi_QueryInterface"); - if (NvAPI_QueryInterface == nullptr) - { - gpuName = "Other"; - return; - } - - NvAPI_Initialize = (int(*)())NvAPI_QueryInterface(0x0150E828); - NvAPI_Unload = (int(*)()) NvAPI_QueryInterface(0xD22BDD7E); - NvAPI_EnumPhysicalGPUs = (int(*)(int64_t** handle, int* count))NvAPI_QueryInterface(0xE5AC921F); - NvAPI_GPU_GetShortName = (int(*)(int64_t* handle, char* name))NvAPI_QueryInterface(0xD988F0F3); - - if (NvAPI_Initialize == nullptr || - NvAPI_Unload == nullptr || - NvAPI_EnumPhysicalGPUs == nullptr || - NvAPI_GPU_GetShortName == nullptr) - { - gpuName = "Unknown"; - return; - } - - int64_t* hdlGpu[64] = { 0 }; - int nGpu = 0; - - NvAPI_Initialize(); - NvAPI_EnumPhysicalGPUs(hdlGpu, &nGpu); - - //printf("[ShaderPatch] nGpu: %d\n", nGpu); - if (nGpu < 1) - { - gpuName = "Unknown"; - NvAPI_Unload(); - return; - } - - char nameBuf[64]; - NvAPI_GPU_GetShortName(hdlGpu[0], nameBuf); - NvAPI_Unload(); - - gpuName = nameBuf; - return; -} void LoadConfig() @@ -283,7 +240,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DetourAttach(&(PVOID&)loadFromFarcThunk, (PVOID)hookedLoadFromFarcThunk); DetourTransactionCommit(); - loadGpuName(); + gpuName = GPUModel::getGpuName(); printf("[ShaderPatch] Detected GPU: %s\n", gpuName.c_str()); //Sleep(2000); diff --git a/source-code/source/plugins/ShaderPatch/src/framework.h b/source-code/source/plugins/ShaderPatch/src/framework.h index 3f38996..379072f 100644 --- a/source-code/source/plugins/ShaderPatch/src/framework.h +++ b/source-code/source/plugins/ShaderPatch/src/framework.h @@ -54,15 +54,7 @@ struct FArchivedFile { void (__stdcall* loadFromFarcThunk)(FArchivedFile** file) = (void(__stdcall*)(FArchivedFile** file))0x1405e5991; - std::string gpuName; -void*(*NvAPI_QueryInterface)(unsigned int offset) = NULL; -int(*NvAPI_Initialize)() = NULL; -int(*NvAPI_Unload)() = NULL; -int(*NvAPI_EnumPhysicalGPUs)(int64_t** handle, int* count) = NULL; -int(*NvAPI_GPU_GetShortName)(int64_t* handle, char* name) = NULL; - - std::vector SplitString(const std::string& str, const std::string& delim) {