Skip to content

Commit

Permalink
1.2 release
Browse files Browse the repository at this point in the history
  • Loading branch information
thompsonnoahe committed Dec 8, 2024
1 parent cd21d7e commit 3a14f5e
Show file tree
Hide file tree
Showing 13 changed files with 234 additions and 61 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "Src/ThirdParty/Amd"]
path = Src/ThirdParty/Amd
url = https://github.com/GPUOpen-LibrariesAndSDKs/ADLX
[submodule "Src/com.nthompson.gpu.sdPlugin/libs"]
path = Src/com.nthompson.gpu.sdPlugin/libs
url = https://github.com/elgatosf/streamdeck-javascript-sdk.git
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ add_executable(gpu
Src/Windows/Amd/AmdGpuUsage.cpp
Src/Windows/Amd/AmdGpuUsage.h
Src/Windows/IGpuUsage.h
Src/GpuAbstraction.h
)

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})

set_property(TARGET gpu PROPERTY LINK_FLAGS "/DELAYLOAD:nvml.dll")

target_link_libraries(gpu PRIVATE StreamDeckSDK CUDA::nvml adlx d3d12.lib dxgi.lib)

set_property(TARGET gpu PROPERTY LINK_FLAGS "/DELAYLOAD:nvml.dll")
26 changes: 26 additions & 0 deletions Src/GpuAbstraction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// Created by Noah Thompson on 8/7/2024.
//

#pragma once
#include <string>
#include <nlohmann/json.hpp>


namespace nthompson {

enum class GpuVendor : int32_t {
Nvidia,
Amd,
Unknown
};

struct Gpu {
GpuVendor vendor;
std::string name;
uint32_t index;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Gpu, vendor, name, index);
}

135 changes: 84 additions & 51 deletions Src/GpuPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@

namespace nthompson {
// Convert a wide Unicode string to an UTF8 string
std::string ConvToString(const std::wstring &wStr)
{
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<void()>& func) {
void Timer::Start(const int32_t& interval, const std::function<void()>& func) {
if (running_) return;
running_ = true;
thread_ = std::thread([this, &interval, func]() {
thread_ = std::thread([this, interval, func]() {
std::scoped_lock<std::mutex> lock(mutex_);
while (running_) {
std::scoped_lock<std::mutex> lock(mutex_);
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
Expand All @@ -35,47 +34,7 @@ namespace nthompson {
}

GpuPlugin::GpuPlugin() {
IDXGIFactory* factory = nullptr;

HRESULT result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);

if (FAILED(result)) {
ESDLog("Failed to create factory object.");
return;
}

std::string amd = "amd", advancedMicroDevices = "advanced micro devices", nvidia = "nvidia";

UINT index = 0;
IDXGIAdapter* adapter = nullptr;

nlohmann::json payload;

while (factory->EnumAdapters(index, &adapter) != DXGI_ERROR_NOT_FOUND) {
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
std::wstring wDescription = desc.Description;

std::string description = ConvToString(wDescription);

std::transform(description.begin(), description.end(), description.begin(),
[](char c) { return std::tolower(c); });

if (description.find(nvidia) != std::string::npos) {
usage_ = std::make_unique<NvidiaGpuUsage>();
break;
}
else if (description.find(amd) != std::string::npos || description.find(advancedMicroDevices) != std::string::npos) {
usage_ = std::make_unique<AmdGpuUsage>();
break;
} else {
ESDLog("Found unsupported display adapter");
usage_ = nullptr;
}

++index;
}

FindAvailableGpus();

timer_ = std::make_unique<Timer>();

Expand All @@ -86,9 +45,6 @@ namespace nthompson {


void GpuPlugin::Update() {
if (mConnectionManager == nullptr) return;
std::scoped_lock<std::mutex> lock(mutex_);

if (usage_ == nullptr) {
SetActionText("?");
return;
Expand All @@ -100,7 +56,6 @@ namespace nthompson {
stream << std::to_string(utilization) << "%";

SetActionText(stream.str());

}

GpuPlugin::~GpuPlugin() {
Expand All @@ -119,10 +74,88 @@ namespace nthompson {
contexts_.erase(inContext);
}

void GpuPlugin::SetActionText(std::string text) {
void GpuPlugin::SetActionText(const std::string& text) {
for (const std::string& context : contexts_) {
mConnectionManager->SetTitle(text, context, kESDSDKTarget_HardwareAndSoftware);
}
}

void GpuPlugin::FindAvailableGpus() {
IDXGIFactory* factory = nullptr;

HRESULT result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);

if (FAILED(result)) {
ESDLog("Failed to create factory object.");
return;
}

std::string amd = "amd", advancedMicroDevices = "advanced micro devices", nvidia = "nvidia";

UINT index = 0;
IDXGIAdapter* adapter = nullptr;

nlohmann::json payload;

while (factory->EnumAdapters(index, &adapter) != DXGI_ERROR_NOT_FOUND) {
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
std::wstring wDescription = desc.Description;

std::string description = ConvToString(wDescription);
std::string gpuName = description;

std::transform(description.begin(), description.end(), description.begin(),
[](char c) { return std::tolower(c); });

if (description.find(nvidia) != std::string::npos) {
gpus_.emplace_back(Gpu{GpuVendor::Nvidia, gpuName, index});
std::string gpuLog = gpuName + " found";
ESDLog(gpuLog);
}
else if (description.find(amd) != std::string::npos || description.find(advancedMicroDevices) != std::string::npos) {
gpus_.emplace_back(Gpu{GpuVendor::Amd, gpuName, index});
std::string gpuLog = gpuName + " found";
ESDLog(gpuLog);
} else {
gpus_.emplace_back(Gpu{GpuVendor::Unknown, gpuName, index});
ESDLog("Found unsupported display adapter");
}

++index;
}
}

void
GpuPlugin::SendToPlugin(const std::string &inAction, const std::string &inContext, const nlohmann::json &inPayload,
const std::string &inDeviceID) {
nlohmann::json payload;
if (inPayload.at("propertyInspectorLoaded").get<bool>()) {
payload["type"] = "availableGpus";
payload["gpus"] = gpus_;
payload["selected"] = selectedGpu_;
mConnectionManager->SendToPropertyInspector(inAction, inContext, payload);
}

if (inPayload.at("receiveSelection").get<bool>()) {
Gpu gpu = inPayload["gpuInfo"];
HandleSelectedGpu(gpu);
mConnectionManager->SendToPropertyInspector(inAction, inContext, payload);
}
}

void GpuPlugin::HandleSelectedGpu(const Gpu &gpu) {
switch (gpu.vendor) {
case GpuVendor::Nvidia:
usage_ = std::make_unique<NvidiaGpuUsage>(gpu.index);
break;
case GpuVendor::Amd:
usage_ = std::make_unique<AmdGpuUsage>(gpu.index);
break;
case GpuVendor::Unknown:
usage_ = nullptr;
break;
}
selectedGpu_ = gpu.index;
}
}
14 changes: 12 additions & 2 deletions Src/GpuPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
#include <functional>
#include "Windows/Nvidia/NvidiaGpuUsage.h"
#include "Windows/Amd/AmdGpuUsage.h"
#include "GpuAbstraction.h"

namespace nthompson {

class Timer {
public:
void Start(int32_t interval, const std::function<void()>& func);
void Start(const int32_t& interval, const std::function<void()>& func);
void Stop();
private:
std::thread thread_;
Expand All @@ -35,7 +36,7 @@ namespace nthompson {

void Update();

void SetActionText(std::string text);
void SetActionText(const std::string& text);

void WillAppearForAction(const std::string& inAction,
const std::string& inContext,
Expand All @@ -47,11 +48,20 @@ namespace nthompson {
const std::string& inContext,
const nlohmann::json& inPayload,
const std::string& inDeviceID) override;

void SendToPlugin(const std::string &inAction,
const std::string &inContext,
const nlohmann::json &inPayload,
const std::string &inDeviceID) override;
private:
void FindAvailableGpus();
std::vector<Gpu> gpus_;
std::unique_ptr<IGpuUsage> usage_ = nullptr;
std::unique_ptr<Timer> timer_;
std::mutex mutex_;
std::set<std::string> contexts_;
int32_t selectedGpu_{0};
void HandleSelectedGpu(const Gpu &gpu);
};

} // nthompson
4 changes: 2 additions & 2 deletions Src/Windows/Amd/AmdGpuUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "AmdGpuUsage.h"

namespace nthompson {
AmdGpuUsage::AmdGpuUsage() {
AmdGpuUsage::AmdGpuUsage(int32_t index) {
ADLX_RESULT result = helper_.Initialize();
if (!ADLX_SUCCEEDED(result)) {
ESDLog("Failed to initialize ADLX");
Expand All @@ -28,7 +28,7 @@ namespace nthompson {
return;
}

result = gpus->At(gpus->Begin(), &gpu_);
result = gpus->At(index, &gpu_);

if (!ADLX_SUCCEEDED(result)) {
ESDLog("Failed to get GPU");
Expand Down
2 changes: 1 addition & 1 deletion Src/Windows/Amd/AmdGpuUsage.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace nthompson {

class AmdGpuUsage : public IGpuUsage {
public:
AmdGpuUsage();
AmdGpuUsage(int32_t index = 0);
~AmdGpuUsage() override;
uint32_t GetGpuUsage() override;
private:
Expand Down
4 changes: 2 additions & 2 deletions Src/Windows/Nvidia/NvidiaGpuUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


namespace nthompson {
NvidiaGpuUsage::NvidiaGpuUsage() {
NvidiaGpuUsage::NvidiaGpuUsage(int32_t index) {
nvmlReturn_t status = nvmlInit();

if (status != NVML_SUCCESS) {
Expand All @@ -17,7 +17,7 @@ namespace nthompson {
return;
}

if (status = nvmlDeviceGetHandleByIndex(0, &device_); status != NVML_SUCCESS) {
if (status = nvmlDeviceGetHandleByIndex(index, &device_); status != NVML_SUCCESS) {
std::stringstream error_status;
error_status << "Failed to query device. Error: " << nvmlErrorString(status);
ESDLog(error_status.str());
Expand Down
2 changes: 1 addition & 1 deletion Src/Windows/Nvidia/NvidiaGpuUsage.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace nthompson {

class NvidiaGpuUsage : public IGpuUsage {
public:
NvidiaGpuUsage();
explicit NvidiaGpuUsage(int32_t index = 0);
~NvidiaGpuUsage() override;
uint32_t GetGpuUsage() override;
private:
Expand Down
27 changes: 27 additions & 0 deletions Src/com.nthompson.gpu.sdPlugin/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GPU</title>
<meta charset="utf-8" />
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui,viewport-fit=cover">
<meta name=apple-mobile-web-app-capable content=yes>
<meta name=apple-mobile-web-app-status-bar-style content=black>
<link rel="stylesheet" href="./libs/css/sdpi.css">
</head>
<body>
<div class="sdpi-wrapper">
<div class="sdpi-item" id="select_single">
<div class="sdpi-item-label">Select GPU</div>
<select class="sdpi-item-value select" id="gpuSelect">
</select>
</div>
<div>
<script src="./libs/js/constants.js"></script>
<script src="./libs/js/events.js"></script>
<script src="./libs/js/api.js"></script>
<script src="./libs/js/property-inspector.js"></script>
<script src="./libs/js/dynamic-styles.js"></script>
<script src="js/index.js"></script>
</body>
</html>
Loading

0 comments on commit 3a14f5e

Please sign in to comment.