1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added CpuAffinity setting

This commit is contained in:
narzoul 2021-05-01 01:43:46 +02:00
parent b3b54d5fbd
commit 74460b2d24
12 changed files with 232 additions and 20 deletions

View File

@ -2,5 +2,6 @@
namespace Config
{
Settings::CpuAffinity cpuAffinity;
Settings::ThreadPriorityBoost threadPriorityBoost;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <Config/Settings/CpuAffinity.h>
#include <Config/Settings/ThreadPriorityBoost.h>
namespace Config
@ -8,5 +9,6 @@ namespace Config
const unsigned evictionTimeout = 200;
const unsigned maxPaletteUpdatesPerMs = 5;
extern Settings::CpuAffinity cpuAffinity;
extern Settings::ThreadPriorityBoost threadPriorityBoost;
}

View File

@ -0,0 +1,36 @@
#include <Config/ListSetting.h>
#include <Config/Parser.h>
namespace Config
{
ListSetting::ListSetting(const std::string& name, const std::string& default)
: Setting(name)
, m_default(default)
{
}
void ListSetting::resetValue()
{
setValue(m_default);
}
void ListSetting::setValue(const std::string& value)
{
std::vector<std::string> values;
std::size_t startPos = 0;
std::size_t endPos = 0;
do
{
endPos = value.find(',', startPos);
if (endPos == std::string::npos)
{
endPos = value.length();
}
values.push_back(Parser::trim(value.substr(startPos, endPos - startPos)));
startPos = endPos + 1;
} while (endPos < value.length());
setValues(values);
}
}

View File

@ -0,0 +1,21 @@
#pragma once
#include <vector>
#include <Config/Setting.h>
namespace Config
{
class ListSetting : public Setting
{
protected:
ListSetting(const std::string& name, const std::string& default);
private:
void resetValue() override;
void setValue(const std::string& value) override;
virtual void setValues(const std::vector<std::string>& values) = 0;
std::string m_default;
};
}

View File

@ -11,7 +11,6 @@ namespace
{
void setConfig(const std::string& name, const std::string& value, const std::string& source);
std::string tolower(const std::string& str);
std::string trim(const std::string& str);
auto& getSettings()
{
@ -52,7 +51,7 @@ namespace
throw Config::ParsingError("missing '=' separator");
}
setConfig(trim(line.substr(0, pos)), trim(line.substr(pos + 1)), source);
setConfig(Config::Parser::trim(line.substr(0, pos)), Config::Parser::trim(line.substr(pos + 1)), source);
}
catch (const Config::ParsingError& error)
{
@ -94,23 +93,6 @@ namespace
}
return result;
}
std::string trim(const std::string& str)
{
auto result(str);
auto pos = str.find_last_not_of(" \t");
if (pos != std::string::npos)
{
result.resize(pos + 1);
}
pos = result.find_first_not_of(" \t");
if (pos != std::string::npos)
{
result = result.substr(pos);
}
return result;
}
}
namespace Config
@ -160,10 +142,36 @@ namespace Config
}
}
unsigned parseUnsigned(const std::string& value)
{
if (value.empty() || std::string::npos != value.find_first_not_of("0123456789"))
{
throw ParsingError("not an unsigned integer: '" + value + "'");
}
return std::strtoul(value.c_str(), nullptr, 10);
}
void registerSetting(Setting& setting)
{
const auto& name = setting.getName();
getSettings().emplace(name, setting);
}
std::string trim(const std::string& str)
{
auto result(str);
auto pos = str.find_last_not_of(" \t");
if (pos != std::string::npos)
{
result.resize(pos + 1);
}
pos = result.find_first_not_of(" \t");
if (pos != std::string::npos)
{
result = result.substr(pos);
}
return result;
}
}
}

View File

@ -2,6 +2,7 @@
#include <filesystem>
#include <stdexcept>
#include <string>
namespace Config
{
@ -16,6 +17,8 @@ namespace Config
namespace Parser
{
void loadAllConfigFiles(const std::filesystem::path& processPath);
unsigned parseUnsigned(const std::string& value);
void registerSetting(Setting& setting);
std::string trim(const std::string& str);
}
}

View File

@ -0,0 +1,73 @@
#include <Config/Parser.h>
#include <Config/Settings/CpuAffinity.h>
namespace Config
{
namespace Settings
{
CpuAffinity::CpuAffinity()
: ListSetting("CpuAffinity", "1")
, m_value(1)
{
}
std::string CpuAffinity::getValueStr() const
{
if (0 == m_value)
{
return "app";
}
if (UINT_MAX == m_value)
{
return "all";
}
std::string result;
for (unsigned i = 0; i < 32; ++i)
{
if (m_value & (1U << i))
{
result += ',' + std::to_string(i + 1);
}
}
return result.substr(1);
}
void CpuAffinity::setValues(const std::vector<std::string>& values)
{
if (values.empty())
{
throw ParsingError("empty list is not allowed");
}
if (1 == values.size())
{
if ("app" == values.front())
{
m_value = 0;
return;
}
else if ("all" == values.front())
{
m_value = UINT_MAX;
return;
}
}
unsigned result = 0;
for (const auto& value : values)
{
auto num = Parser::parseUnsigned(value);
if (num < 1 || num > 32)
{
throw ParsingError("'" + value + "' is not an integer between 1 and 32");
}
result |= 1U << (num - 1);
}
m_value = result;
}
}
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <Config/ListSetting.h>
namespace Config
{
namespace Settings
{
class CpuAffinity : public ListSetting
{
public:
CpuAffinity();
unsigned get() const { return m_value; }
private:
std::string getValueStr() const override;
void setValues(const std::vector<std::string>& values) override;
unsigned m_value;
};
}
}

View File

@ -179,8 +179,10 @@
<ClInclude Include="Common\Time.h" />
<ClInclude Include="Config\Config.h" />
<ClInclude Include="Config\EnumSetting.h" />
<ClInclude Include="Config\ListSetting.h" />
<ClInclude Include="Config\Parser.h" />
<ClInclude Include="Config\Setting.h" />
<ClInclude Include="Config\Settings\CpuAffinity.h" />
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
<ClInclude Include="D3dDdi\Adapter.h" />
<ClInclude Include="D3dDdi\AdapterCallbacks.h" />
@ -277,8 +279,10 @@
<ClCompile Include="Common\Time.cpp" />
<ClCompile Include="Config\Config.cpp" />
<ClCompile Include="Config\EnumSetting.cpp" />
<ClCompile Include="Config\ListSetting.cpp" />
<ClCompile Include="Config\Parser.cpp" />
<ClCompile Include="Config\Setting.cpp" />
<ClCompile Include="Config\Settings\CpuAffinity.cpp" />
<ClCompile Include="D3dDdi\Adapter.cpp" />
<ClCompile Include="D3dDdi\AdapterCallbacks.cpp" />
<ClCompile Include="D3dDdi\AdapterFuncs.cpp" />

View File

@ -85,6 +85,9 @@
<Filter Include="Header Files\Config\Settings">
<UniqueIdentifier>{bdde0d15-27ab-43a7-9c0a-294df6a52bad}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Config\Settings">
<UniqueIdentifier>{0b4eec6c-ece5-4417-913c-8829b34ec08c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Gdi\Gdi.h">
@ -408,6 +411,12 @@
<ClInclude Include="Win32\Thread.h">
<Filter>Header Files\Win32</Filter>
</ClInclude>
<ClInclude Include="Config\ListSetting.h">
<Filter>Header Files\Config</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\CpuAffinity.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -638,9 +647,15 @@
<ClCompile Include="Config\EnumSetting.cpp">
<Filter>Source Files\Config</Filter>
</ClCompile>
<ClCompile Include="Config\ListSetting.cpp">
<Filter>Source Files\Config</Filter>
</ClCompile>
<ClCompile Include="Win32\Thread.cpp">
<Filter>Source Files\Win32</Filter>
</ClCompile>
<ClCompile Include="Config\Settings\CpuAffinity.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">

View File

@ -212,7 +212,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Win32::Thread::installHooks();
Compat::closeDbgEng();
SetProcessAffinityMask(GetCurrentProcess(), 1);
timeBeginPeriod(1);
setDpiAwareness();
SetThemeAppProperties(0);

View File

@ -7,6 +7,16 @@
namespace
{
BOOL WINAPI setProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask)
{
LOG_FUNC("SetProcessAffinityMask", hProcess, Compat::hex(dwProcessAffinityMask));
if (0 != Config::cpuAffinity.get())
{
return LOG_RESULT(TRUE);
}
return LOG_RESULT(CALL_ORIG_FUNC(SetProcessAffinityMask)(hProcess, dwProcessAffinityMask));
}
BOOL WINAPI setProcessPriorityBoost(HANDLE hProcess, BOOL bDisablePriorityBoost)
{
LOG_FUNC("SetProcessPriorityBoost", hProcess, bDisablePriorityBoost);
@ -34,6 +44,22 @@ namespace Win32
{
void applyConfig()
{
auto cpuAffinity = Config::cpuAffinity.get();
if (0 != cpuAffinity)
{
SYSTEM_INFO si = {};
GetSystemInfo(&si);
const unsigned cpuCount = min(si.dwNumberOfProcessors, 32);
cpuAffinity &= UINT_MAX >> (32 - cpuCount);
if (0 == cpuAffinity || !CALL_ORIG_FUNC(SetProcessAffinityMask)(GetCurrentProcess(), cpuAffinity))
{
Compat::Log() << (0 == cpuAffinity ? "Invalid" : "Failed to set") << " CPU affinity, falling back to default";
Config::cpuAffinity.reset();
CALL_ORIG_FUNC(SetProcessAffinityMask)(GetCurrentProcess(), Config::cpuAffinity.get());
}
}
switch (Config::threadPriorityBoost.get())
{
case Config::Settings::ThreadPriorityBoost::OFF:
@ -53,6 +79,7 @@ namespace Win32
void installHooks()
{
HOOK_FUNCTION(kernel32, SetProcessAffinityMask, setProcessAffinityMask);
HOOK_FUNCTION(kernel32, SetProcessPriorityBoost, setProcessPriorityBoost);
HOOK_FUNCTION(kernel32, SetThreadPriorityBoost, setThreadPriorityBoost);
}