diff --git a/CMakeLists.txt b/CMakeLists.txt index 8961ca2..dfe5bf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,6 @@ project(com.nthompson.gpu VERSION 1.0.0) set(CMAKE_CXX_STANDARD 20) find_package(CUDAToolkit) -find_package(GLEW CONFIG REQUIRED) -find_package(glfw3 CONFIG REQUIRED) -find_package(OpenGL) include("Src/ThirdParty/StreamDeckSDK.cmake") @@ -31,7 +28,6 @@ target_include_directories(gpu PUBLIC Src/ThirdParty/Amd) add_library(adlx STATIC ${THIRD_PARTY_AMD_INCLUDE} ${THIRD_PARTY_AMD_SRC} ${THIRD_PARTY_AMD_SRC_WIN}) -target_link_libraries(gpu PRIVATE StreamDeckSDK CUDA::nvml adlx OpenGL::GL glfw GLEW::GLEW) - -install(FILES Src/com.nthompson.gpu.sdPlugin/manifest.json DESTINATION Release) +target_link_libraries(gpu PRIVATE StreamDeckSDK CUDA::nvml adlx d3d12.lib dxgi.lib) +set_property(TARGET gpu PROPERTY LINK_FLAGS "/DELAYLOAD:nvml.dll") \ No newline at end of file diff --git a/README.md b/README.md index d587460..d452925 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![GPU Utilization Icon](Src/com.nthompson.gpu.sdPlugin/defaultImage.png) -# Stream Deck GPU Utilization Plugin 📈 +# Stream Deck GPU Utilization Plugin 📈 A plugin for monitoring the utilization of your GPU on the Elgato Stream Deck. Windows only. @@ -39,4 +39,6 @@ Finally, repeat the steps you performed for GLEW to install [GLFW](https://www.g And presto! You should be good to go. -![GPU Utilization Icon](Src/com.nthompson.gpu.sdPlugin/previews/Preview2.png) \ No newline at end of file +![GPU Utilization Icon](Src/com.nthompson.gpu.sdPlugin/previews/Preview2.png) + +Buy Me A Coffee diff --git a/Src/GpuPlugin.cpp b/Src/GpuPlugin.cpp index 0134f21..5ee0c3d 100644 --- a/Src/GpuPlugin.cpp +++ b/Src/GpuPlugin.cpp @@ -5,6 +5,16 @@ #include "GpuPlugin.h" namespace nthompson { + // Convert a wide Unicode string to an UTF8 string + std::string ConvToString(const std::wstring &wStr) + { + if(wStr.empty()) return {}; + int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, &wStr[0], (int)wStr.size(), nullptr, 0, nullptr, nullptr); + std::string strTo(sizeNeeded, 0); + WideCharToMultiByte(CP_UTF8, 0, &wStr[0], (int)wStr.size(), &strTo[0], sizeNeeded, nullptr, nullptr); + return strTo; + } + void Timer::Start(int32_t interval, const std::function& func) { if (running_) return; running_ = true; @@ -25,41 +35,48 @@ namespace nthompson { } GpuPlugin::GpuPlugin() { - if (!glfwInit()) { - ESDLog("Failed to init GLFW3"); + IDXGIFactory* factory = nullptr; + + HRESULT result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); + + if (FAILED(result)) { + ESDLog("Failed to create factory object."); + return; } - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + std::string amd = "amd", advancedMicroDevices = "advanced micro devices", nvidia = "nvidia"; - GLFWwindow* context = glfwCreateWindow(1, 1, "", nullptr, nullptr); + UINT index = 0; + IDXGIAdapter* adapter = nullptr; - glfwMakeContextCurrent(context); + nlohmann::json payload; - GLenum status = glewInit(); + while (factory->EnumAdapters(index, &adapter) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC desc; + adapter->GetDesc(&desc); + std::wstring wDescription = desc.Description; - if (status != GLEW_OK) { - ESDLog("Failed to init GLEW"); - } + std::string description = ConvToString(wDescription); - std::string amd = "amd", advancedMicroDevices = "advanced micro devices", nvidia = "nvidia"; - std::string gpuVendor = reinterpret_cast(glGetString(GL_VENDOR)); + std::transform(description.begin(), description.end(), description.begin(), + [](char c) { return std::tolower(c); }); - // Transform to lowercase - std::transform(gpuVendor.begin(), gpuVendor.end(), gpuVendor.begin(), [](unsigned char c) { - return std::tolower(c); - }); + if (description.find(nvidia) != std::string::npos) { + usage_ = std::make_unique(); + break; + } + else if (description.find(amd) != std::string::npos || description.find(advancedMicroDevices) != std::string::npos) { + usage_ = std::make_unique(); + break; + } else { + ESDLog("Found unsupported display adapter"); + usage_ = nullptr; + } - if (gpuVendor.find(amd) != std::string::npos || gpuVendor.find(advancedMicroDevices) != std::string::npos) { - usage_ = std::make_unique(); - } - else if (gpuVendor.find(nvidia) != std::string::npos) { - usage_ = std::make_unique(); - } - else { - ESDLog("Unsupported GPU."); - return; + ++index; } + timer_ = std::make_unique(); timer_->Start(1000, [this]() { @@ -71,10 +88,19 @@ namespace nthompson { void GpuPlugin::Update() { if (mConnectionManager == nullptr) return; std::scoped_lock lock(mutex_); - uint32_t utilization = usage_->GetGpuUsage(); - for (const std::string& context : contexts_) { - mConnectionManager->SetTitle(std::to_string(utilization) + "%", context, kESDSDKTarget_HardwareAndSoftware); + + if (usage_ == nullptr) { + SetActionText("?"); + return; } + + uint32_t utilization = usage_->GetGpuUsage(); + + std::stringstream stream; + stream << std::to_string(utilization) << "%"; + + SetActionText(stream.str()); + } GpuPlugin::~GpuPlugin() { @@ -93,4 +119,10 @@ namespace nthompson { contexts_.erase(inContext); } + void GpuPlugin::SetActionText(std::string text) { + for (const std::string& context : contexts_) { + mConnectionManager->SetTitle(text, context, kESDSDKTarget_HardwareAndSoftware); + } + } + } \ No newline at end of file diff --git a/Src/GpuPlugin.h b/Src/GpuPlugin.h index b968f84..5d0d98f 100644 --- a/Src/GpuPlugin.h +++ b/Src/GpuPlugin.h @@ -10,9 +10,7 @@ #include #include #include -#include -#include -#include +#include #include #include #include "Windows/Nvidia/NvidiaGpuUsage.h" @@ -37,6 +35,8 @@ namespace nthompson { void Update(); + void SetActionText(std::string text); + void WillAppearForAction(const std::string& inAction, const std::string& inContext, const nlohmann::json& inPayload, @@ -48,7 +48,7 @@ namespace nthompson { const nlohmann::json& inPayload, const std::string& inDeviceID) override; private: - std::unique_ptr usage_; + std::unique_ptr usage_ = nullptr; std::unique_ptr timer_; std::mutex mutex_; std::set contexts_; diff --git a/Src/com.nthompson.gpu.sdPlugin/manifest.json b/Src/com.nthompson.gpu.sdPlugin/manifest.json index a906c0b..0d92098 100644 --- a/Src/com.nthompson.gpu.sdPlugin/manifest.json +++ b/Src/com.nthompson.gpu.sdPlugin/manifest.json @@ -1,20 +1,20 @@ { "Actions": [ { - "Icon": "icon", + "Icon": "icon", "Name": "GPU", "States": [ { "Image": "defaultImage", - "TitleAlignment": "middle", + "TitleAlignment": "middle", "FontSize": "12" } - ], + ], "SupportedInMultiActions": false, "Tooltip": "This action displays the GPU usage", "UUID": "com.nthompson.gpu.gpu" } - ], + ], "SDKVersion": 2, "Author": "Noah Thompson", "CodePathWin": "gpu.exe", @@ -23,16 +23,16 @@ "Description": "Displays the current GPU usage.", "Name": "GPU", "Icon": "pluginIcon", - "Version": "1.1.0", + "Version": "1.1.1", "URL": "https://github.com/thompsonnoahe/StreamDeckGpu", "OS": [ { - "Platform": "windows", - "MinimumVersion" : "10" + "Platform": "windows", + "MinimumVersion" : "10" } ], - "Software": - { - "MinimumVersion" : "4.1" - } -} + "Software": + { + "MinimumVersion" : "4.1" + } +} \ No newline at end of file