瀏覽代碼

Implement better CPU Detection

Jeff Hutchinson 4 年之前
父節點
當前提交
433d32f237
共有 3 個文件被更改,包括 88 次插入274 次删除
  1. 4 43
      Engine/source/platform/platform.h
  2. 49 228
      Engine/source/platform/platformCPU.cpp
  3. 35 3
      Engine/source/platformWin32/winCPUInfo.cpp

+ 4 - 43
Engine/source/platform/platform.h

@@ -55,50 +55,11 @@
 /// @note These enums must be globally scoped so that they work with the inline assembly
 enum ProcessorType
 {
-   // x86
    CPU_X86Compatible,
-   CPU_Intel_Unknown,
-   CPU_Intel_486,
-   CPU_Intel_Pentium,
-   CPU_Intel_PentiumMMX,
-   CPU_Intel_PentiumPro,
-   CPU_Intel_PentiumII,
-   CPU_Intel_PentiumCeleron,
-   CPU_Intel_PentiumIII,
-   CPU_Intel_Pentium4,
-   CPU_Intel_PentiumM,
-   CPU_Intel_Core,
-   CPU_Intel_Core2,
-   CPU_Intel_Corei7Xeon, // Core i7 or Xeon
-   CPU_AMD_K6,
-   CPU_AMD_K6_2,
-   CPU_AMD_K6_3,
-   CPU_AMD_Athlon,
-   CPU_AMD_Phenom,
-   CPU_AMD_PhenomII,
-   CPU_AMD_Bulldozer,
-   CPU_AMD_Unknown,
-   CPU_Cyrix_6x86,
-   CPU_Cyrix_MediaGX,
-   CPU_Cyrix_6x86MX,
-   CPU_Cyrix_GXm,          ///< Media GX w/ MMX
-   CPU_Cyrix_Unknown,
-
-   // PowerPC
-   CPU_PowerPC_Unknown,
-   CPU_PowerPC_601,
-   CPU_PowerPC_603,
-   CPU_PowerPC_603e,
-   CPU_PowerPC_603ev,
-   CPU_PowerPC_604,
-   CPU_PowerPC_604e,
-   CPU_PowerPC_604ev,
-   CPU_PowerPC_G3,
-   CPU_PowerPC_G4,
-   CPU_PowerPC_G4_7450,
-   CPU_PowerPC_G4_7455,
-   CPU_PowerPC_G4_7447, 
-   CPU_PowerPC_G5,
+   CPU_ArmCompatible,
+   CPU_Intel,
+   CPU_AMD,
+   CPU_Apple
 };
 
 /// Properties for CPU.

+ 49 - 228
Engine/source/platform/platformCPU.cpp

@@ -31,12 +31,11 @@ Signal<void(void)> Platform::SystemInfoReady;
 enum CPUFlags
 {
    // EDX Register flags
-   BIT_FPU     = BIT(0),
    BIT_RDTSC   = BIT(4),
    BIT_MMX     = BIT(23),
    BIT_SSE     = BIT(25),
    BIT_SSE2    = BIT(26),
-   BIT_3DNOW   = BIT(31),
+   BIT_3DNOW   = BIT(31), // only available for amd cpus in x86
 
    // These use a different value for comparison than the above flags (ECX Register)
    BIT_SSE3    = BIT(0),
@@ -47,241 +46,63 @@ enum CPUFlags
 
 // fill the specified structure with information obtained from asm code
 void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo,
-   char* vendor, U32 processor, U32 properties, U32 properties2)
+   char* vendor, char* brand, U32 processor, U32 properties, U32 properties2)
 {
-   Platform::SystemInfo.processor.properties |= (properties & BIT_FPU)   ? CPU_PROP_FPU : 0;
-   Platform::SystemInfo.processor.properties |= (properties & BIT_RDTSC) ? CPU_PROP_RDTSC : 0;
-   Platform::SystemInfo.processor.properties |= (properties & BIT_MMX)   ? CPU_PROP_MMX : 0;
+   // always assume FPU is available in 2021...
+   pInfo.properties |= CPU_PROP_FPU;
+
+#if defined(TORQUE_CPU_X86) || defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_ARM64)
+   pInfo.properties |= CPU_PROP_LE;
+#endif
+
+#if defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_ARM64)
+   pInfo.properties |= CPU_PROP_64bit;
+#endif
+
+#if defined(TORQUE_CPU_X86) || defined(TORQUE_CPU_X64)
+   pInfo.properties |= (properties & BIT_RDTSC)   ? CPU_PROP_RDTSC : 0;
+   pInfo.properties |= (properties & BIT_MMX)     ? CPU_PROP_MMX : 0;
+   pInfo.properties |= (properties & BIT_SSE)     ? CPU_PROP_SSE : 0;
+   pInfo.properties |= (properties & BIT_SSE2)    ? CPU_PROP_SSE2 : 0;
+   pInfo.properties |= (properties2 & BIT_SSE3)   ? CPU_PROP_SSE3 : 0;
+   pInfo.properties |= (properties2 & BIT_SSE3xt) ? CPU_PROP_SSE3xt : 0;
+   pInfo.properties |= (properties2 & BIT_SSE4_1) ? CPU_PROP_SSE4_1 : 0;
+   pInfo.properties |= (properties2 & BIT_SSE4_2) ? CPU_PROP_SSE4_2 : 0;
+#endif
 
    if (dStricmp(vendor, "GenuineIntel") == 0)
    {
-      pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
-      pInfo.properties |= (properties & BIT_SSE2) ? CPU_PROP_SSE2 : 0;
-      pInfo.properties |= (properties2 & BIT_SSE3) ? CPU_PROP_SSE3 : 0;
-      pInfo.properties |= (properties2 & BIT_SSE3xt) ? CPU_PROP_SSE3xt : 0;
-      pInfo.properties |= (properties2 & BIT_SSE4_1) ? CPU_PROP_SSE4_1 : 0;
-      pInfo.properties |= (properties2 & BIT_SSE4_2) ? CPU_PROP_SSE4_2 : 0;
-
-      pInfo.type = CPU_Intel_Unknown;
-      // switch on processor family code
-      switch ((processor >> 8) & 0x0f)
-      {
-         case 4:
-            pInfo.type = CPU_Intel_486;
-            pInfo.name = StringTable->insert("Intel 486 class");
-            break;
-
-            // Pentium Family
-         case 5:
-            // switch on processor model code
-            switch ((processor >> 4) & 0xf)
-            {
-               case 1:
-               case 2:
-               case 3:
-                  pInfo.type = CPU_Intel_Pentium;
-                  pInfo.name = StringTable->insert("Intel Pentium");
-                  break;
-               case 4:
-                  pInfo.type = CPU_Intel_PentiumMMX;
-                  pInfo.name = StringTable->insert("Intel Pentium MMX");
-                  break;
-               default:
-                  pInfo.type = CPU_Intel_Pentium;
-                  pInfo.name = StringTable->insert( "Intel (unknown)" );
-                  break;
-            }
-            break;
-
-            // Pentium Pro/II/II family
-         case 6:
-         {
-            U32 extendedModel = ( processor & 0xf0000 ) >> 16;
-            // switch on processor model code
-            switch ((processor >> 4) & 0xf)
-            {
-               case 1:
-                  pInfo.type = CPU_Intel_PentiumPro;
-                  pInfo.name = StringTable->insert("Intel Pentium Pro");
-                  break;
-               case 3:
-               case 5:
-                  pInfo.type = CPU_Intel_PentiumII;
-                  pInfo.name = StringTable->insert("Intel Pentium II");
-                  break;
-               case 6:
-                  pInfo.type = CPU_Intel_PentiumCeleron;
-                  pInfo.name = StringTable->insert("Intel Pentium Celeron");
-                  break;
-               case 7:
-               case 8:
-               case 11:
-                  pInfo.type = CPU_Intel_PentiumIII;
-                  pInfo.name = StringTable->insert("Intel Pentium III");
-                  break;
-               case 0xA:
-                  if( extendedModel == 1)
-                  {
-                     pInfo.type = CPU_Intel_Corei7Xeon;
-                     pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" );
-                  }
-                  else
-                  {
-                     pInfo.type = CPU_Intel_PentiumIII;
-                     pInfo.name = StringTable->insert( "Intel Pentium III Xeon" );
-                  }
-                  break;
-               case 0xD:
-                  if( extendedModel == 1 )
-                  {
-                     pInfo.type = CPU_Intel_Corei7Xeon;
-                     pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" );
-                  }
-                  else
-                  {
-                     pInfo.type = CPU_Intel_PentiumM;
-                     pInfo.name = StringTable->insert( "Intel Pentium/Celeron M" );
-                  }
-                  break;
-               case 0xE:
-                  pInfo.type = CPU_Intel_Core;
-                  pInfo.name = StringTable->insert( "Intel Core" );
-                  break;
-               case 0xF:
-                  pInfo.type = CPU_Intel_Core2;
-                  pInfo.name = StringTable->insert( "Intel Core 2" );
-                  break;
-               default:
-                  pInfo.type = CPU_Intel_PentiumPro;
-                  pInfo.name = StringTable->insert( "Intel (unknown)" );
-                  break;
-            }
-            break;
-         }
-
-            // Pentium4 Family
-         case 0xf:
-            pInfo.type = CPU_Intel_Pentium4;
-            pInfo.name = StringTable->insert( "Intel Pentium 4" );
-            break;
-
-         default:
-            pInfo.type = CPU_Intel_Unknown;
-            pInfo.name = StringTable->insert( "Intel (unknown)" );
-            break;
-      }
+      pInfo.type = CPU_Intel;
+      pInfo.name = StringTable->insert(brand ? brand : "Intel (Unknown)");
    }
    //--------------------------------------
-   else
-      if (dStricmp(vendor, "AuthenticAMD") == 0)
-      {
-         // AthlonXP processors support SSE
-         pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
-         pInfo.properties |= ( properties & BIT_SSE2 ) ? CPU_PROP_SSE2 : 0;
-         pInfo.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0;
-       // Phenom and PhenomII support SSE3, SSE4a
-       pInfo.properties |= ( properties2 & BIT_SSE3 ) ? CPU_PROP_SSE3 : 0;
-         pInfo.properties |= ( properties2 & BIT_SSE4_1 ) ? CPU_PROP_SSE4_1 : 0;
-         // switch on processor family code
-         switch ((processor >> 8) & 0xf)
-         {
-            // K6 Family
-            case 5:
-               // switch on processor model code
-               switch ((processor >> 4) & 0xf)
-               {
-                  case 0:
-                  case 1:
-                  case 2:
-                  case 3:
-                     pInfo.type = CPU_AMD_K6_3;
-                     pInfo.name = StringTable->insert("AMD K5");
-                     break;
-                  case 4:
-                  case 5:
-                  case 6:
-                  case 7:
-                     pInfo.type = CPU_AMD_K6;
-                     pInfo.name = StringTable->insert("AMD K6");
-                     break;
-                  case 8:
-                     pInfo.type = CPU_AMD_K6_2;
-                     pInfo.name = StringTable->insert("AMD K6-2");
-                     break;
-                  case 9:
-                  case 10:
-                  case 11:
-                  case 12:
-                  case 13:
-                  case 14:
-                  case 15:
-                     pInfo.type = CPU_AMD_K6_3;
-                     pInfo.name = StringTable->insert("AMD K6-3");
-                     break;
-               }
-               break;
-
-               // Athlon Family
-            case 6:
-               pInfo.type = CPU_AMD_Athlon;
-               pInfo.name = StringTable->insert("AMD Athlon");
-               break;
-
-               // Phenom Family
-         case 15:
-               pInfo.type = CPU_AMD_Phenom;
-               pInfo.name = StringTable->insert("AMD Phenom");
-               break;
-
-            // Phenom II Family
-         case 16:
-               pInfo.type = CPU_AMD_PhenomII;
-               pInfo.name = StringTable->insert("AMD Phenom II");
-               break;
-
-            // Bulldozer Family
-         case 17:
-               pInfo.type = CPU_AMD_Bulldozer;
-               pInfo.name = StringTable->insert("AMD Bulldozer");
-               break;
+   else if (dStricmp(vendor, "AuthenticAMD") == 0)
+   {
+      pInfo.name = StringTable->insert(brand ? brand : "AMD (unknown)");
+      pInfo.type = CPU_AMD;
 
-            default:
-               pInfo.type = CPU_AMD_Unknown;
-               pInfo.name = StringTable->insert("AMD (unknown)");
-               break;
-         }
-      }
-   //--------------------------------------
-      else
-         if (dStricmp(vendor, "CyrixInstead") == 0)
-         {
-            switch (processor)
-            {
-               case 0x520:
-                  pInfo.type = CPU_Cyrix_6x86;
-                  pInfo.name = StringTable->insert("Cyrix 6x86");
-                  break;
-               case 0x440:
-                  pInfo.type = CPU_Cyrix_MediaGX;
-                  pInfo.name = StringTable->insert("Cyrix Media GX");
-                  break;
-               case 0x600:
-                  pInfo.type = CPU_Cyrix_6x86MX;
-                  pInfo.name = StringTable->insert("Cyrix 6x86mx/MII");
-                  break;
-               case 0x540:
-                  pInfo.type = CPU_Cyrix_GXm;
-                  pInfo.name = StringTable->insert("Cyrix GXm");
-                  break;
-               default:
-                  pInfo.type = CPU_Cyrix_Unknown;
-                  pInfo.name = StringTable->insert("Cyrix (unknown)");
-                  break;
-            }
-         }
+      // 3dnow! is only available in AMD cpus on x86. Otherwise its not reliably set.
+      pInfo.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0;
+   }
+   else if (dStricmp(vendor, "Apple") == 0)
+   {
+      pInfo.name = StringTable->insert(brand ? brand : "Apple (unknown)");
+      pInfo.type = CPU_Apple;
+   }
+   else
+   {
+#if defined(TORQUE_CPU_X86) || defined(TORQUE_CPU_X64)
+      pInfo.name = StringTable->insert(brand ? brand : "x86 Compatible (unknown)");
+      pInfo.type = CPU_X86Compatible;
+#elif defined(TORQUE_CPU_ARM64)
+      pInfo.name = StringTable->insert(brand ? brand : "Arm Compatible (unknown)");
+      pInfo.type = CPU_ArmCompatible;
+#else
+#error "Unknown CPU Architecture"
+#endif
+   }
 
    // Get multithreading caps.
-
    CPUInfo::EConfig config = CPUInfo::CPUCount( pInfo.numLogicalProcessors, pInfo.numAvailableCores, pInfo.numPhysicalProcessors );
    pInfo.isHyperThreaded = CPUInfo::isHyperThreaded( config );
    pInfo.isMultiCore = CPUInfo::isMultiCore( config );

+ 35 - 3
Engine/source/platformWin32/winCPUInfo.cpp

@@ -30,7 +30,7 @@
 Platform::SystemInfo_struct Platform::SystemInfo;
 extern void PlatformBlitInit();
 extern void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo,
-   char* vendor, U32 processor, U32 properties, U32 properties2); // platform/platformCPU.cc
+   char* vendor, char* brand, U32 processor, U32 properties, U32 properties2); // platform/platformCPU.cc
 
 void Processor::init()
 {
@@ -45,7 +45,7 @@ void Processor::init()
    Platform::SystemInfo.processor.type = CPU_X86Compatible;
    Platform::SystemInfo.processor.name = StringTable->insert("Unknown x86 Compatible");
    Platform::SystemInfo.processor.mhz  = 0;
-   Platform::SystemInfo.processor.properties = CPU_PROP_C | CPU_PROP_LE;
+   Platform::SystemInfo.processor.properties = CPU_PROP_C;
 
    char  vendor[0x20];
    dMemset(vendor, 0, sizeof(vendor));
@@ -65,7 +65,31 @@ void Processor::init()
    properties = cpuInfo[3];  // edx
    properties2 = cpuInfo[2]; // ecx
 
-   SetProcessorInfo(Platform::SystemInfo.processor, vendor, processor, properties, properties2);
+   char brand[0x40];
+   dMemset(brand, 0, sizeof(brand));
+   S32 extendedInfo[4];
+   __cpuid(extendedInfo, 0x80000000);
+   S32 numberExtendedIds = extendedInfo[0];
+
+   // Sets brand
+   if (numberExtendedIds >= 0x80000004)
+   {
+      int offset = 0;
+      for (int i = 0; i < 3; ++i)
+      {
+         S32 brandInfo[4];
+         __cpuidex(brandInfo, 0x80000002 + i, 0);
+
+         *reinterpret_cast<int*>(brand + offset + 0) = brandInfo[0];
+         *reinterpret_cast<int*>(brand + offset + 4) = brandInfo[1];
+         *reinterpret_cast<int*>(brand + offset + 8) = brandInfo[2];
+         *reinterpret_cast<int*>(brand + offset + 12) = brandInfo[3];
+
+         offset += sizeof(S32) * 4;
+      }
+   }
+
+   SetProcessorInfo(Platform::SystemInfo.processor, vendor, brand, processor, properties, properties2);
 
 // now calculate speed of processor...
    U32 nearmhz = 0; // nearest rounded mhz
@@ -126,6 +150,14 @@ void Processor::init()
       Con::printf( "   SSE detected" );
    if( Platform::SystemInfo.processor.properties & CPU_PROP_SSE2 )
       Con::printf( "   SSE2 detected" );
+   if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3)
+      Con::printf( "   SSE3 detected" );
+   if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3xt)
+      Con::printf( "   SSE3ex detected ");
+   if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_1)
+      Con::printf( "   SSE4.1 detected" );
+   if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_2)
+      Con::printf( "   SSE4.2 detected" );
    if( Platform::SystemInfo.processor.isHyperThreaded )
       Con::printf( "   HT detected" );
    if( Platform::SystemInfo.processor.properties & CPU_PROP_MP )