parent
c27e4d04de
commit
25a6b128eb
@ -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,9 +266,14 @@ namespace
|
||||
|
||||
const auto is_server = utils::flags::has_flag("dedicated") || (!has_client && has_server);
|
||||
|
||||
if (!is_server && !launcher::run())
|
||||
if (!is_server)
|
||||
{
|
||||
return 0;
|
||||
trigger_high_performance_gpu_switch();
|
||||
|
||||
if (!launcher::run())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!component_loader::activate(is_server))
|
||||
|
@ -24,3 +24,9 @@ extern "C"
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
||||
__declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user