Improved CPU detection code.

This commit is contained in:
LoRd_MuldeR 2012-02-07 03:37:47 +01:00
parent 42a2bf73ec
commit 9db58c543f
6 changed files with 61 additions and 23 deletions

BIN
asm/cpu-detect.obj Normal file

Binary file not shown.

View File

@ -412,6 +412,14 @@ bool x264_is_prerelease(void)
return (VER_X264_PRE_RELEASE);
}
/*
* CPUID prototype (actual function is in ASM code)
*/
extern "C"
{
void x264_cpu_cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx);
}
/*
* Detect CPU features
*/
@ -425,7 +433,7 @@ x264_cpu_t x264_detect_cpu_features(int argc, char **argv)
x264_cpu_t features;
SYSTEM_INFO systemInfo;
int CPUInfo[4] = {-1};
unsigned int CPUInfo[4];
char CPUIdentificationString[0x40];
char CPUBrandString[0x40];
@ -434,42 +442,49 @@ x264_cpu_t x264_detect_cpu_features(int argc, char **argv)
memset(CPUIdentificationString, 0, sizeof(CPUIdentificationString));
memset(CPUBrandString, 0, sizeof(CPUBrandString));
__cpuid(CPUInfo, 0);
memcpy(CPUIdentificationString, &CPUInfo[1], sizeof(int));
memcpy(CPUIdentificationString + 4, &CPUInfo[3], sizeof(int));
memcpy(CPUIdentificationString + 8, &CPUInfo[2], sizeof(int));
x264_cpu_cpuid(0, &CPUInfo[0], &CPUInfo[1], &CPUInfo[2], &CPUInfo[3]);
memcpy(CPUIdentificationString, &CPUInfo[1], 4);
memcpy(CPUIdentificationString + 4, &CPUInfo[3], 4);
memcpy(CPUIdentificationString + 8, &CPUInfo[2], 4);
features.intel = (_stricmp(CPUIdentificationString, "GenuineIntel") == 0);
strncpy_s(features.vendor, 0x40, CPUIdentificationString, _TRUNCATE);
if(CPUInfo[0] >= 1)
{
__cpuid(CPUInfo, 1);
features.mmx = (CPUInfo[3] & 0x800000) || false;
features.sse = (CPUInfo[3] & 0x2000000) || false;
features.sse2 = (CPUInfo[3] & 0x4000000) || false;
features.ssse3 = (CPUInfo[2] & 0x200) || false;
features.sse3 = (CPUInfo[2] & 0x1) || false;
features.ssse3 = (CPUInfo[2] & 0x200) || false;
x264_cpu_cpuid(1, &CPUInfo[0], &CPUInfo[1], &CPUInfo[2], &CPUInfo[3]);
features.mmx = (CPUInfo[3] & 0x800000U) || false;
features.sse = (CPUInfo[3] & 0x2000000U) || false;
features.sse2 = (CPUInfo[3] & 0x4000000U) || false;
features.ssse3 = (CPUInfo[2] & 0x200U) || false;
features.sse3 = (CPUInfo[2] & 0x1U) || false;
features.ssse3 = (CPUInfo[2] & 0x200U) || false;
features.stepping = CPUInfo[0] & 0xf;
features.model = ((CPUInfo[0] >> 4) & 0xf) + (((CPUInfo[0] >> 16) & 0xf) << 4);
features.family = ((CPUInfo[0] >> 8) & 0xf) + ((CPUInfo[0] >> 20) & 0xff);
if(features.sse) features.mmx2 = true; //MMXEXT is a subset of SSE!
}
__cpuid(CPUInfo, 0x80000000);
int nExIds = qMax<int>(qMin<int>(CPUInfo[0], 0x80000004), 0x80000000);
x264_cpu_cpuid(0x80000000U, &CPUInfo[0], &CPUInfo[1], &CPUInfo[2], &CPUInfo[3]);
unsigned int nExIds = qBound(0x80000000U, CPUInfo[0], 0x80000004U);
for(int i = 0x80000002; i <= nExIds; ++i)
if((_stricmp(CPUIdentificationString, "AuthenticAMD") == 0) && (nExIds >= 0x80000001U))
{
__cpuid(CPUInfo, i);
x264_cpu_cpuid(0x80000001U, &CPUInfo[0], &CPUInfo[1], &CPUInfo[2], &CPUInfo[3]);
features.mmx2 = features.mmx2 || (CPUInfo[3] & 0x00400000U);
}
for(unsigned int i = 0x80000002U; i <= nExIds; ++i)
{
x264_cpu_cpuid(i, &CPUInfo[0], &CPUInfo[1], &CPUInfo[2], &CPUInfo[3]);
switch(i)
{
case 0x80000002:
case 0x80000002U:
memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
break;
case 0x80000003:
case 0x80000003U:
memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
break;
case 0x80000004:
case 0x80000004U:
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
break;
}
@ -517,11 +532,13 @@ x264_cpu_t x264_detect_cpu_features(int argc, char **argv)
{
if(!_stricmp("--force-cpu-no-64bit", argv[i])) { flag = true; features.x64 = false; }
if(!_stricmp("--force-cpu-no-mmx", argv[i])) { flag = true; features.mmx = false; }
if(!_stricmp("--force-cpu-no-mmx2", argv[i])) { flag = true; features.mmx2 = false; }
if(!_stricmp("--force-cpu-no-sse", argv[i])) { flag = true; features.sse = features.sse2 = features.sse3 = features.ssse3 = false; }
if(!_stricmp("--force-cpu-no-intel", argv[i])) { flag = true; features.intel = false; }
if(!_stricmp("--force-cpu-have-64bit", argv[i])) { flag = true; features.x64 = true; }
if(!_stricmp("--force-cpu-have-mmx", argv[i])) { flag = true; features.mmx = true; }
if(!_stricmp("--force-cpu-have-mmx2", argv[i])) { flag = true; features.mmx2 = true; }
if(!_stricmp("--force-cpu-have-sse", argv[i])) { flag = true; features.sse = features.sse2 = features.sse3 = features.ssse3 = true; }
if(!_stricmp("--force-cpu-have-intel", argv[i])) { flag = true; features.intel = true; }
}

View File

@ -78,6 +78,7 @@ typedef struct
int count;
bool x64;
bool mmx;
bool mmx2;
bool sse;
bool sse2;
bool sse3;

View File

@ -59,13 +59,22 @@ static int x264_main(int argc, char* argv[])
qDebug(" CPU vendor id : %s (Intel: %s)", cpuFeatures.vendor, X264_BOOL(cpuFeatures.intel));
qDebug("CPU brand string : %s", cpuFeatures.brand);
qDebug(" CPU signature : Family: %d, Model: %d, Stepping: %d", cpuFeatures.family, cpuFeatures.model, cpuFeatures.stepping);
qDebug("CPU capabilities : MMX: %s, SSE: %s, SSE2: %s, SSE3: %s, SSSE3: %s, x64: %s", X264_BOOL(cpuFeatures.mmx), X264_BOOL(cpuFeatures.sse), X264_BOOL(cpuFeatures.sse2), X264_BOOL(cpuFeatures.sse3), X264_BOOL(cpuFeatures.ssse3), X264_BOOL(cpuFeatures.x64));
qDebug("CPU capabilities : MMX=%s, MMXEXT=%s, SSE=%s, SSE2=%s, SSE3=%s, SSSE3=%s, X64=%s", X264_BOOL(cpuFeatures.mmx), X264_BOOL(cpuFeatures.mmx2), X264_BOOL(cpuFeatures.sse), X264_BOOL(cpuFeatures.sse2), X264_BOOL(cpuFeatures.sse3), X264_BOOL(cpuFeatures.ssse3), X264_BOOL(cpuFeatures.x64));
qDebug(" Number of CPU's : %d\n", cpuFeatures.count);
//Make sure this CPU can run x264
if(!(cpuFeatures.mmx && cpuFeatures.sse))
//Make sure this CPU can run x264 (requires MMX + MMXEXT/iSSE to run x264 with ASM enabled, additionally requires SSE1 for most x264 builds)
if(!(cpuFeatures.mmx && cpuFeatures.mmx2))
{
qFatal("Sorry, but this machine is not physically capable of running x264. Please get a CPU that supports at least the MMX and ISSE instruction sets!");
qFatal("Sorry, but this machine is not physically capable of running x264. Please get a CPU that supports at least the MMX and MMXEXT instruction sets!");
}
else if(!(cpuFeatures.mmx && cpuFeatures.sse))
{
qWarning("WARNING: System does not support SSE1, most x264 builds will not work !!!\n");
for(;;)
{
int ret = MessageBoxW(NULL, L"BIG FAT WARNING: This machine apparently does NOT support the SSE1 instruction set and thus probably will NOT be able to run x264!", L"Simple x264 Launcher", MB_ABORTRETRYIGNORE|MB_TOPMOST|MB_ICONEXCLAMATION);
if(ret == IDIGNORE) break; else if(ret == IDRETRY) continue; else return -1;
}
}
//Initialize Qt

View File

@ -260,6 +260,9 @@ copy "$(SolutionDir)res\toolset\*.exe" "$(SolutionDir)bin\$(Configuration)\tools
<ItemGroup>
<ResourceCompile Include="x264_launcher.rc" />
</ItemGroup>
<ItemGroup>
<Object Include="asm\cpu-detect.obj" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -19,6 +19,9 @@
<Filter Include="Generated Files">
<UniqueIdentifier>{961e9f99-8107-45a2-984d-188819a67e8e}</UniqueIdentifier>
</Filter>
<Filter Include="Assembly">
<UniqueIdentifier>{2c9c8836-2259-4412-894e-7cc32bef99de}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
@ -142,4 +145,9 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Object Include="asm\cpu-detect.obj">
<Filter>Assembly</Filter>
</Object>
</ItemGroup>
</Project>