only run the main thread on P-cores

This commit is contained in:
myT 2023-08-02 18:11:36 +02:00
parent 9e19d22d46
commit a202404d16
3 changed files with 115 additions and 2 deletions

View file

@ -63,6 +63,8 @@ add: /waitms <milliseconds> to delay command executions by the specified number
add: r_alphaToCoverageMipBoost <0.0 to 0.5> (default: 0.125) boosts the alpha value of higher mip levels
with A2C enabled, it prevents alpha-tested surfaces from fading (too much) in the distance
chg: with hybrid core CPUs (e.g. Intel gen 12+) on Windows, the main thread will only run on the P-cores
chg: the client can now read .wav files from the local file system when connected to a pure server
this allows e.g. cg_fragSound to load sounds from the local file system instead of .pk3 files

View file

@ -871,6 +871,116 @@ static void WIN_RegisterDemoShellCommands()
}
static void WIN_SetCorePreference()
{
struct local_resources_t {
~local_resources_t()
{
if ( cpuSetBuffer != NULL ) {
free( cpuSetBuffer );
}
if ( pcoreIdBuffer != NULL ) {
free( pcoreIdBuffer );
}
if ( library != NULL ) {
FreeLibrary( library );
}
}
byte* cpuSetBuffer = NULL;
ULONG* pcoreIdBuffer = NULL;
HMODULE library = NULL;
};
local_resources_t res;
res.library = LoadLibraryA( "kernel32.dll" );
if ( res.library == NULL ) {
Com_Printf( "^3WIN_SetCorePreference: Failed to open kernel32.dll\n" );
return;
}
typedef BOOL (WINAPI* GetSystemCpuSetInformationFPtr)( PSYSTEM_CPU_SET_INFORMATION Information, ULONG BufferLength, PULONG ReturnedLength, HANDLE Process, ULONG Flags );
typedef BOOL (WINAPI* SetThreadSelectedCpuSetsFPtr)( HANDLE Thread, const ULONG* CpuSetIds, ULONG CpuSetIdCount );
const GetSystemCpuSetInformationFPtr pGetSystemCpuSetInformation = (GetSystemCpuSetInformationFPtr)GetProcAddress( res.library, "GetSystemCpuSetInformation" );
const SetThreadSelectedCpuSetsFPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsFPtr)GetProcAddress( res.library, "SetThreadSelectedCpuSets" );
if ( pGetSystemCpuSetInformation == NULL || pSetThreadSelectedCpuSets == NULL ) {
Com_Printf( "^3WIN_SetCorePreference: Failed to grab function pointers\n" );
Com_Printf( "^3WIN_SetCorePreference: Ignore this if you're not on Windows 10/11\n" );
return;
}
ULONG requiredByteCount = 0;
if ( pGetSystemCpuSetInformation( NULL, 0, &requiredByteCount, GetCurrentProcess(), 0 ) != TRUE &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER ) {
Com_Printf( "^3WIN_SetCorePreference: GetSystemCpuSetInformation failed\n" );
return;
}
res.cpuSetBuffer = (byte*)malloc( requiredByteCount );
if ( res.cpuSetBuffer == NULL ) {
Com_Printf( "^3WIN_SetCorePreference: malloc failed with %s\n", Com_FormatBytes( (int)requiredByteCount ) );
return;
}
if ( pGetSystemCpuSetInformation( (SYSTEM_CPU_SET_INFORMATION*)res.cpuSetBuffer, requiredByteCount, &requiredByteCount, GetCurrentProcess(), 0 ) != TRUE ) {
Com_Printf( "^3WIN_SetCorePreference: GetSystemCpuSetInformation failed\n" );
return;
}
ULONG pcoreCount = 0;
ULONG ecoreCount = 0;
byte* cpuSetByte = res.cpuSetBuffer;
for ( ULONG cpuSetByteOffset = 0; cpuSetByteOffset < requiredByteCount; ) {
SYSTEM_CPU_SET_INFORMATION* cpuSet = (SYSTEM_CPU_SET_INFORMATION*)cpuSetByte;
if ( cpuSet->Type == CpuSetInformation ) {
if ( cpuSet->CpuSet.EfficiencyClass > 0 ) {
pcoreCount++;
} else {
ecoreCount++;
}
}
cpuSetByte += cpuSet->Size;
cpuSetByteOffset += cpuSet->Size;
}
if ( pcoreCount + ecoreCount <= 1 ) {
Com_Printf( "^3WIN_SetCorePreference: no valid CPU core information found\n" );
return;
}
const size_t pcoreIdBufferSize = (size_t)pcoreCount * sizeof(ULONG);
res.pcoreIdBuffer = (ULONG*)malloc( pcoreIdBufferSize );
if ( res.pcoreIdBuffer == NULL ) {
Com_Printf( "^3WIN_SetCorePreference: malloc failed with %s\n", Com_FormatBytes( (int)pcoreIdBufferSize ) );
return;
}
ULONG* currPCoreId = res.pcoreIdBuffer;
cpuSetByte = res.cpuSetBuffer;
for ( ULONG cpuSetByteOffset = 0; cpuSetByteOffset < requiredByteCount; ) {
SYSTEM_CPU_SET_INFORMATION* cpuSet = (SYSTEM_CPU_SET_INFORMATION*)cpuSetByte;
if ( cpuSet->Type == CpuSetInformation ) {
if ( cpuSet->CpuSet.EfficiencyClass > 0 ) {
*currPCoreId++ = (ULONG)cpuSet->CpuSet.Id;
}
}
cpuSetByte += cpuSet->Size;
cpuSetByteOffset += cpuSet->Size;
}
if ( pcoreCount > 0 && ecoreCount > 0 ) {
Com_Printf( "CPU configuration: %dP/%dE hybrid cores\n", (int)pcoreCount, (int)ecoreCount );
if ( pSetThreadSelectedCpuSets( GetCurrentThread(), res.pcoreIdBuffer, pcoreCount) ) {
Com_Printf( "Main thread successfully set to run on P-Cores only\n" );
} else {
Com_Printf( "^3WIN_SetCorePreference: SetThreadSelectedCpuSets failed\n" );
}
} else {
Com_Printf( "CPU configuration: %d homogeneous cores\n", (int)(pcoreCount + ecoreCount) );
}
}
///////////////////////////////////////////////////////////////
@ -911,6 +1021,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
WIN_RegisterExceptionCommands();
WIN_RegisterMonitorCommands();
WIN_RegisterDemoShellCommands();
WIN_SetCorePreference();
NET_Init();

View file

@ -7,8 +7,8 @@
#if defined(_WIN32_WINNT)
#undef _WIN32_WINNT
#endif
#define WINVER _WIN32_WINNT_VISTA
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#define WINVER _WIN32_WINNT_WIN10
#define _WIN32_WINNT _WIN32_WINNT_WIN10
#if defined(UNICODE)
#undef UNICODE