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 namespace Config
{ {
Settings::CpuAffinity cpuAffinity;
Settings::ThreadPriorityBoost threadPriorityBoost; Settings::ThreadPriorityBoost threadPriorityBoost;
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <Config/Settings/CpuAffinity.h>
#include <Config/Settings/ThreadPriorityBoost.h> #include <Config/Settings/ThreadPriorityBoost.h>
namespace Config namespace Config
@ -8,5 +9,6 @@ namespace Config
const unsigned evictionTimeout = 200; const unsigned evictionTimeout = 200;
const unsigned maxPaletteUpdatesPerMs = 5; const unsigned maxPaletteUpdatesPerMs = 5;
extern Settings::CpuAffinity cpuAffinity;
extern Settings::ThreadPriorityBoost threadPriorityBoost; 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); void setConfig(const std::string& name, const std::string& value, const std::string& source);
std::string tolower(const std::string& str); std::string tolower(const std::string& str);
std::string trim(const std::string& str);
auto& getSettings() auto& getSettings()
{ {
@ -52,7 +51,7 @@ namespace
throw Config::ParsingError("missing '=' separator"); 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) catch (const Config::ParsingError& error)
{ {
@ -94,23 +93,6 @@ namespace
} }
return result; 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 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) void registerSetting(Setting& setting)
{ {
const auto& name = setting.getName(); const auto& name = setting.getName();
getSettings().emplace(name, setting); 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 <filesystem>
#include <stdexcept> #include <stdexcept>
#include <string>
namespace Config namespace Config
{ {
@ -16,6 +17,8 @@ namespace Config
namespace Parser namespace Parser
{ {
void loadAllConfigFiles(const std::filesystem::path& processPath); void loadAllConfigFiles(const std::filesystem::path& processPath);
unsigned parseUnsigned(const std::string& value);
void registerSetting(Setting& setting); 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="Common\Time.h" />
<ClInclude Include="Config\Config.h" /> <ClInclude Include="Config\Config.h" />
<ClInclude Include="Config\EnumSetting.h" /> <ClInclude Include="Config\EnumSetting.h" />
<ClInclude Include="Config\ListSetting.h" />
<ClInclude Include="Config\Parser.h" /> <ClInclude Include="Config\Parser.h" />
<ClInclude Include="Config\Setting.h" /> <ClInclude Include="Config\Setting.h" />
<ClInclude Include="Config\Settings\CpuAffinity.h" />
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" /> <ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
<ClInclude Include="D3dDdi\Adapter.h" /> <ClInclude Include="D3dDdi\Adapter.h" />
<ClInclude Include="D3dDdi\AdapterCallbacks.h" /> <ClInclude Include="D3dDdi\AdapterCallbacks.h" />
@ -277,8 +279,10 @@
<ClCompile Include="Common\Time.cpp" /> <ClCompile Include="Common\Time.cpp" />
<ClCompile Include="Config\Config.cpp" /> <ClCompile Include="Config\Config.cpp" />
<ClCompile Include="Config\EnumSetting.cpp" /> <ClCompile Include="Config\EnumSetting.cpp" />
<ClCompile Include="Config\ListSetting.cpp" />
<ClCompile Include="Config\Parser.cpp" /> <ClCompile Include="Config\Parser.cpp" />
<ClCompile Include="Config\Setting.cpp" /> <ClCompile Include="Config\Setting.cpp" />
<ClCompile Include="Config\Settings\CpuAffinity.cpp" />
<ClCompile Include="D3dDdi\Adapter.cpp" /> <ClCompile Include="D3dDdi\Adapter.cpp" />
<ClCompile Include="D3dDdi\AdapterCallbacks.cpp" /> <ClCompile Include="D3dDdi\AdapterCallbacks.cpp" />
<ClCompile Include="D3dDdi\AdapterFuncs.cpp" /> <ClCompile Include="D3dDdi\AdapterFuncs.cpp" />

View File

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

View File

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

View File

@ -7,6 +7,16 @@
namespace 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) BOOL WINAPI setProcessPriorityBoost(HANDLE hProcess, BOOL bDisablePriorityBoost)
{ {
LOG_FUNC("SetProcessPriorityBoost", hProcess, bDisablePriorityBoost); LOG_FUNC("SetProcessPriorityBoost", hProcess, bDisablePriorityBoost);
@ -34,6 +44,22 @@ namespace Win32
{ {
void applyConfig() 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()) switch (Config::threadPriorityBoost.get())
{ {
case Config::Settings::ThreadPriorityBoost::OFF: case Config::Settings::ThreadPriorityBoost::OFF:
@ -53,6 +79,7 @@ namespace Win32
void installHooks() void installHooks()
{ {
HOOK_FUNCTION(kernel32, SetProcessAffinityMask, setProcessAffinityMask);
HOOK_FUNCTION(kernel32, SetProcessPriorityBoost, setProcessPriorityBoost); HOOK_FUNCTION(kernel32, SetProcessPriorityBoost, setProcessPriorityBoost);
HOOK_FUNCTION(kernel32, SetThreadPriorityBoost, setThreadPriorityBoost); HOOK_FUNCTION(kernel32, SetThreadPriorityBoost, setThreadPriorityBoost);
} }