Trigger high performance GPU

This fixes #167
This commit is contained in:
momo5502 2023-02-18 08:46:11 +01:00
parent c27e4d04de
commit 25a6b128eb
5 changed files with 135 additions and 2 deletions

View File

@ -212,6 +212,26 @@ namespace
}
}
void trigger_high_performance_gpu_switch()
{
// Make sure to link D3D11, as this might trigger high performance GPU
static volatile auto _ = &D3D11CreateDevice;
const auto key = utils::nt::open_or_create_registry_key(
HKEY_CURRENT_USER, R"(Software\Microsoft\DirectX\UserGpuPreferences)");
if (!key)
{
return;
}
const auto self = utils::nt::library::get_by_address(&trigger_high_performance_gpu_switch);
const std::wstring data = L"GpuPreference=2;";
RegSetValueExW(key, self.get_path().make_preferred().wstring().data(), 0, REG_SZ,
reinterpret_cast<const BYTE*>(data.data()),
static_cast<DWORD>((data.size() + 1u) * 2));
}
int main()
{
if (handle_process_runner())
@ -246,10 +266,15 @@ namespace
const auto is_server = utils::flags::has_flag("dedicated") || (!has_client && has_server);
if (!is_server && !launcher::run())
if (!is_server)
{
trigger_high_performance_gpu_switch();
if (!launcher::run())
{
return 0;
}
}
if (!component_loader::activate(is_server))
{

View File

@ -24,3 +24,9 @@ extern "C"
return -1;
}
}
extern "C"
{
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
__declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1;
}

View File

@ -51,6 +51,7 @@
#include <iphlpapi.h>
#include <wincrypt.h>
#include <shellscalingapi.h>
#include <d3d11.h>
// min and max is required by gdi, therefore NOMINMAX won't work
#ifdef max
@ -101,5 +102,6 @@
#pragma comment(lib, "urlmon.lib" )
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "d3d11.lib")
using namespace std::literals;

View File

@ -1,4 +1,5 @@
#include "nt.hpp"
#include "string.hpp"
namespace utils::nt
{
@ -223,6 +224,34 @@ namespace utils::nt
return nullptr;
}
registry_key open_or_create_registry_key(const HKEY base, const std::string& input)
{
const auto parts = string::split(input, '\\');
registry_key current_key = base;
for (const auto& part : parts)
{
registry_key new_key{};
if (RegOpenKeyExA(current_key, part.data(), 0,
KEY_ALL_ACCESS, &new_key) == ERROR_SUCCESS)
{
current_key = std::move(new_key);
continue;
}
if (RegCreateKeyExA(current_key, part.data(), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
nullptr, &new_key, nullptr) != ERROR_SUCCESS)
{
return {};
}
current_key = std::move(new_key);
}
return current_key;
}
bool is_wine()
{
static const auto has_wine_export = []() -> bool

View File

@ -173,6 +173,77 @@ namespace utils::nt
HANDLE handle_{InvalidHandle};
};
class registry_key
{
public:
registry_key() = default;
registry_key(HKEY key)
: key_(key)
{
}
registry_key(const registry_key&) = delete;
registry_key& operator=(const registry_key&) = delete;
registry_key(registry_key&& obj) noexcept
: registry_key()
{
this->operator=(std::move(obj));
}
registry_key& operator=(registry_key&& obj) noexcept
{
if (this != obj.GetRef())
{
this->~registry_key();
this->key_ = obj.key_;
obj.key_ = nullptr;
}
return *this;
}
~registry_key()
{
if (this->key_)
{
RegCloseKey(this->key_);
}
}
operator HKEY() const
{
return this->key_;
}
operator bool() const
{
return this->key_ != nullptr;
}
HKEY* operator&()
{
return &this->key_;
}
registry_key* GetRef()
{
return this;
}
const registry_key* GetRef() const
{
return this;
}
private:
HKEY key_{};
};
registry_key open_or_create_registry_key(const HKEY base, const std::string& input);
bool is_wine();
bool is_shutdown_in_progress();