Improve CPU detection code

Structure now fully aligns with that of the engine, with exception of newly added fields for the SDK (new fields are marked in the structure definition).
This commit is contained in:
Kawe Mazidjatari 2023-10-08 16:27:10 +02:00
parent ffedb41705
commit ab1d28c778
3 changed files with 76 additions and 63 deletions

View File

@ -362,21 +362,24 @@ void QuerySystemInfo()
void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 (Supplemental SSE 3 Instructions).
{
const CPUInformation& pi = GetCPUInformation();
static char szBuf[1024];
if (!pi.m_bSSE3)
CpuIdResult_t cpuResult;
__cpuid(reinterpret_cast<int*>(&cpuResult), 1);
char szBuf[1024];
if ((cpuResult.ecx & (1 << 0)) == 0)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSE 3");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
if (!pi.m_bSSSE3)
if ((cpuResult.ecx & (1 << 9)) == 0)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSSE 3 (Supplemental SSE 3 Instructions)");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
if (!pi.m_bPOPCNT)
if ((cpuResult.ecx & (1 << 23)) == 0)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "POPCNT");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);

View File

@ -13,35 +13,15 @@ static CPUInformation s_cpuInformation;
static char s_CpuVendorID[13] = "unknown";
bool s_bCpuBrandInitialized = false;
bool s_bCpuVendorIdInitialized = false;
static CpuBrand_t s_CpuBrand;
/*******************************************************************************/
struct CpuIdResult_t
{
unsigned long eax;
unsigned long ebx;
unsigned long ecx;
unsigned long edx;
void Reset(void)
{
eax = ebx = ecx = edx = 0;
}
};
struct IntelCacheDesc_t
{
uint8_t nDesc;
uint16_t nCacheSize;
};
/*******************************************************************************/
union CpuBrand_t
{
CpuIdResult_t cpuid[3];
char name[49];
};
CpuBrand_t s_CpuBrand;
/*******************************************************************************/
inline static IntelCacheDesc_t s_IntelL1DataCacheDesc[] = {
{ 0xA, 8 },
@ -347,23 +327,25 @@ static bool HTSupported(void)
((cpuid1.ebx >> 16) & 0xFF) > 1; // Hyper-Threading OR Core Multi-Processing has been enabled.
}
// | Commented out as its currently unused, this is to avoid a compiler warning |
// | regarding unused function of static linkage. |
// Returns the number of logical processors per physical processors.
static uint8_t LogicalProcessorsPerPackage(void)
{
// EBX[23:16] indicate number of logical processors per package.
const unsigned NUM_LOGICAL_BITS = 0x00FF0000;
if (!HTSupported())
{
return 1;
}
return static_cast<uint8_t>(((cpuid(1).ebx & NUM_LOGICAL_BITS) >> 16));
}
//static uint8_t LogicalProcessorsPerPackage(void)
//{
// // EBX[23:16] indicate number of logical processors per package.
// const unsigned NUM_LOGICAL_BITS = 0x00FF0000;
//
// if (!HTSupported())
// {
// return 1;
// }
//
// return static_cast<uint8_t>(((cpuid(1).ebx & NUM_LOGICAL_BITS) >> 16));
//}
// Measure the processor clock speed by sampling the cycle count, waiting
// for some fraction of a second, then measuring the elapsed number of cycles.
static int64_t CalculateClockSpeed(void)
static int64 CalculateClockSpeed(void)
{
LARGE_INTEGER waitTime, startCount, curCount;
CCycleCount start, end;
@ -444,7 +426,7 @@ const CPUInformation& GetCPUInformation(void)
pi.m_Speed = CalculateClockSpeed();
// Get the logical and physical processor counts:
pi.m_nLogicalProcessors = LogicalProcessorsPerPackage();
//pi.m_nLogicalProcessors = LogicalProcessorsPerPackage();
bool bAuthenticAMD = (0 == _stricmp(GetProcessorVendorId(), "AuthenticAMD"));
bool bGenuineIntel = !bAuthenticAMD && (0 == _stricmp(GetProcessorVendorId(), "GenuineIntel"));
@ -479,7 +461,6 @@ const CPUInformation& GetCPUInformation(void)
pi.m_bRDTSC = (cpuid1.edx >> 4) & 1;
pi.m_bCMOV = (cpuid1.edx >> 15) & 1;
pi.m_bFCMOV = (pi.m_bCMOV && bFPU) ? 1 : 0;
pi.m_bPOPCNT= (cpuid1.edx >> 17) & 1;
pi.m_bMMX = (cpuid1.edx >> 23) & 1;
pi.m_bSSE = (cpuid1.edx >> 25) & 1;
pi.m_bSSE2 = (cpuid1.edx >> 26) & 1;

View File

@ -7,6 +7,31 @@
#ifndef CPU_H
#define CPU_H
//-----------------------------------------------------------------------------
// CPUID Result:
//-----------------------------------------------------------------------------
struct CpuIdResult_t
{
unsigned long eax;
unsigned long ebx;
unsigned long ecx;
unsigned long edx;
void Reset(void)
{
eax = ebx = ecx = edx = 0;
}
};
//-----------------------------------------------------------------------------
// CPU Brand:
//-----------------------------------------------------------------------------
union CpuBrand_t
{
CpuIdResult_t cpuid[3];
char name[49];
};
//-----------------------------------------------------------------------------
// Processor Information:
//-----------------------------------------------------------------------------
@ -14,19 +39,23 @@ struct CPUInformation
{
int m_Size; // Size of this structure, for forward compatibility.
uint8_t m_nLogicalProcessors; // Number op logical processors.
uint8_t m_nPhysicalProcessors; // Number of physical processors.
bool m_bRDTSC : 1, // Is RDTSC supported?
m_bCMOV : 1, // Is CMOV supported?
m_bFCMOV : 1, // Is FCMOV supported?
m_bPOPCNT : 1, // Is POPCNT supported?
m_bSSE : 1, // Is SSE supported?
m_bSSE2 : 1, // Is SSE2 Supported?
m_b3DNow : 1, // Is 3DNow! Supported?
m_bMMX : 1, // Is MMX supported?
m_bHT : 1; // Is HyperThreading supported?
uint8 m_nLogicalProcessors; // Number op logical processors.
uint8 m_nPhysicalProcessors; // Number of physical processors.
int64 m_Speed; // In cycles per second.
char* m_szProcessorID; // Processor vendor Identification.
// !!! any member below here is SDK specific and does NOT exist in the game engine !!!
char* m_szProcessorBrand; // Processor brand string, if available.
bool m_bSSE3 : 1,
m_bSSSE3 : 1,
@ -35,31 +64,21 @@ struct CPUInformation
m_bSSE42 : 1,
m_bAVX : 1; // Is AVX supported?
int64_t m_Speed; // In cycles per second.
// Any member below doesn't exist in the game engine!
char* m_szProcessorID; // Processor vendor Identification.
char* m_szProcessorBrand; // Processor brand string, if available.
uint32_t m_nModel;
uint32_t m_nFeatures[3];
uint32_t m_nL1CacheSizeKb;
uint32_t m_nL1CacheDesc;
uint32_t m_nL2CacheSizeKb;
uint32_t m_nL2CacheDesc;
uint32_t m_nL3CacheSizeKb;
uint32_t m_nL3CacheDesc;
uint32 m_nModel;
uint32 m_nFeatures[3];
uint32 m_nL1CacheSizeKb;
uint32 m_nL1CacheDesc;
uint32 m_nL2CacheSizeKb;
uint32 m_nL2CacheDesc;
uint32 m_nL3CacheSizeKb;
uint32 m_nL3CacheDesc;
CPUInformation() : m_Size(0)
{
m_Size = 0;
m_nLogicalProcessors = 0;
m_nPhysicalProcessors = 0;
m_bRDTSC = false;
m_bCMOV = false;
m_bCMOV = false;
m_bFCMOV = false;
m_bSSE = false;
m_bSSE2 = false;
@ -67,11 +86,21 @@ struct CPUInformation
m_bMMX = false;
m_bHT = false;
m_nLogicalProcessors = 0;
m_nPhysicalProcessors = 0;
m_Speed = NULL;
m_szProcessorID = nullptr;
m_szProcessorBrand = nullptr;
m_bSSE3 = false;
m_bSSSE3 = false;
m_bSSE4a = false;
m_bSSE41 = false;
m_bSSE42 = false;
m_bAVX = false;
m_nModel = 0;
m_nFeatures[0] = 0;
m_nFeatures[1] = 0;