mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 04:02:42 +01:00
Improve CPU feature check
Damn exit on SSSE3 failure Check AVX for Intel processors
This commit is contained in:
parent
3f6b24d33a
commit
0fa148e65e
@ -12,6 +12,7 @@
|
||||
#include "File.h"
|
||||
#include "Log.h"
|
||||
#include "mutex.h"
|
||||
#include "sysinfo.h"
|
||||
#include "VirtualMemory.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -377,6 +378,20 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>
|
||||
if (m_cpu.empty())
|
||||
{
|
||||
m_cpu = llvm::sys::getHostCPUName();
|
||||
|
||||
if (m_cpu == "sandybridge" ||
|
||||
m_cpu == "ivybridge" ||
|
||||
m_cpu == "haswell" ||
|
||||
m_cpu == "broadwell" ||
|
||||
m_cpu == "skylake" ||
|
||||
m_cpu == "skylake-avx512" ||
|
||||
m_cpu == "cannonlake")
|
||||
{
|
||||
if (!utils::has_avx())
|
||||
{
|
||||
m_cpu = "nehalem";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string result;
|
||||
|
50
Utilities/sysinfo.cpp
Normal file
50
Utilities/sysinfo.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "sysinfo.h"
|
||||
#include "StrFmt.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
std::string utils::get_system_info()
|
||||
{
|
||||
std::string result;
|
||||
std::string brand;
|
||||
|
||||
if (get_cpuid(0x80000000, 0)[0] >= 0x80000004)
|
||||
{
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
brand.append(reinterpret_cast<const char*>(get_cpuid(0x80000002 + i, 0).data()), 16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
brand = "Unknown CPU";
|
||||
}
|
||||
|
||||
brand.erase(0, brand.find_first_not_of(' '));
|
||||
brand.erase(brand.find_last_not_of(' ') + 1);
|
||||
|
||||
while (auto found = brand.find(" ") + 1)
|
||||
{
|
||||
brand.erase(brand.begin() + found);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
::SYSTEM_INFO sysInfo;
|
||||
::GetNativeSystemInfo(&sysInfo);
|
||||
::MEMORYSTATUSEX memInfo;
|
||||
memInfo.dwLength = sizeof(memInfo);
|
||||
::GlobalMemoryStatusEx(&memInfo);
|
||||
const u32 num_proc = sysInfo.dwNumberOfProcessors;
|
||||
const u64 mem_total = memInfo.ullTotalPhys;
|
||||
#else
|
||||
const u32 num_proc = ::sysconf(_SC_NPROCESSORS_ONLN);
|
||||
const u64 mem_total = ::sysconf(_SC_PHYS_PAGES) * ::sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
|
||||
fmt::append(result, "%s | %d Threads | %.2f GiB RAM", brand, num_proc, mem_total / (1024.0f * 1024 * 1024));
|
||||
return result;
|
||||
}
|
35
Utilities/sysinfo.h
Normal file
35
Utilities/sysinfo.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include <string>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
inline std::array<u32, 4> get_cpuid(u32 func, u32 subfunc)
|
||||
{
|
||||
int regs[4];
|
||||
#ifdef _MSC_VER
|
||||
__cpuidex(regs, func, subfunc);
|
||||
#else
|
||||
__asm__ volatile("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (func), "c" (subfunc));
|
||||
#endif
|
||||
return {0u+regs[0], 0u+regs[1], 0u+regs[2], 0u+regs[3]};
|
||||
}
|
||||
|
||||
inline bool has_ssse3()
|
||||
{
|
||||
return get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x200;
|
||||
}
|
||||
|
||||
inline bool has_avx()
|
||||
{
|
||||
return get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x10000000;
|
||||
}
|
||||
|
||||
inline bool has_rtm()
|
||||
{
|
||||
return get_cpuid(0, 0)[0] >= 0x7 && get_cpuid(7, 0)[1] & 0x800;
|
||||
}
|
||||
|
||||
std::string get_system_info();
|
||||
}
|
@ -102,6 +102,13 @@
|
||||
<ClCompile Include="..\Utilities\StrFmt.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\sysinfo.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="..\Utilities\version.cpp" />
|
||||
<ClCompile Include="..\Utilities\VirtualMemory.cpp" />
|
||||
@ -426,6 +433,7 @@
|
||||
<ClInclude Include="..\Utilities\rXml.h" />
|
||||
<ClInclude Include="..\Utilities\StrFmt.h" />
|
||||
<ClInclude Include="..\Utilities\StrUtil.h" />
|
||||
<ClInclude Include="..\Utilities\sysinfo.h" />
|
||||
<ClInclude Include="..\Utilities\Thread.h" />
|
||||
<ClInclude Include="..\Utilities\Timer.h" />
|
||||
<ClInclude Include="..\Utilities\types.h" />
|
||||
|
@ -923,6 +923,9 @@
|
||||
<ClCompile Include="Emu\Cell\lv2\sys_ss.cpp">
|
||||
<Filter>Emu\Cell\lv2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\sysinfo.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -1777,5 +1780,8 @@
|
||||
<ClInclude Include="..\Utilities\CRC.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\sysinfo.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1201,7 +1201,6 @@
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\system_info.h" />
|
||||
<ClInclude Include="rpcs3qt\game_list.h" />
|
||||
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
|
@ -514,9 +514,6 @@
|
||||
<ClInclude Include="QTGeneratedFiles\ui_welcome_dialog.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\system_info.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\game_list.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "rpcs3_version.h"
|
||||
#include "system_info.h"
|
||||
#include "Utilities/sysinfo.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QActionGroup>
|
||||
@ -40,7 +40,7 @@ struct gui_listener : logs::listener
|
||||
read = new packet;
|
||||
last = new packet;
|
||||
read->next = last.load();
|
||||
last->msg = fmt::format("RPCS3 v%s\n%s\n", rpcs3::version.to_string(), System_Info::getCPU().first);
|
||||
last->msg = fmt::format("RPCS3 v%s\n%s\n", rpcs3::version.to_string(), utils::get_system_info());
|
||||
|
||||
// Self-registration
|
||||
logs::listener::add(this);
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include "rpcs3_version.h"
|
||||
#include "system_info.h"
|
||||
#include "Utilities/sysinfo.h"
|
||||
|
||||
#include "ui_main_window.h"
|
||||
|
||||
@ -112,13 +112,13 @@ void main_window::Init()
|
||||
RequestGlobalStylesheetChange(guiSettings->GetCurrentStylesheetPath());
|
||||
ConfigureGuiFromSettings(true);
|
||||
|
||||
if (!System_Info::getCPU().second)
|
||||
if (!utils::has_ssse3())
|
||||
{
|
||||
QMessageBox::critical(this, "SSSE3 Error (with three S, not two)",
|
||||
"Your system does not meet the minimum requirements needed to run RPCS3.\n"
|
||||
"Your CPU does not support SSSE3 (with three S, not two).\n"
|
||||
"\n"
|
||||
"No games will run and RPCS3 will crash if you try.");
|
||||
"Your CPU does not support SSSE3 (with three S, not two).\n");
|
||||
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <regex>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#include <bitset>
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
class System_Info
|
||||
{
|
||||
class CPUID {
|
||||
uint32_t regs[4];
|
||||
|
||||
public:
|
||||
explicit CPUID(uint32_t func, uint32_t subfunc) {
|
||||
#ifdef _WIN32
|
||||
__cpuidex((int *)regs, func, subfunc);
|
||||
#else
|
||||
asm volatile
|
||||
("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
|
||||
: "a" (func), "c" (subfunc));
|
||||
// ECX is set to zero for CPUID function 4
|
||||
#endif
|
||||
}
|
||||
|
||||
const uint32_t &EAX() const { return regs[0]; }
|
||||
const uint32_t &EBX() const { return regs[1]; }
|
||||
const uint32_t &ECX() const { return regs[2]; }
|
||||
const uint32_t &EDX() const { return regs[3]; }
|
||||
const uint32_t *data() const { return ®s[0]; }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Retrieves various information about the system's hardware
|
||||
@return a pair consisting of the compiled information as string value and a bool for SSSE3 compatibility
|
||||
*/
|
||||
static const std::pair<std::string, bool> getCPU()
|
||||
{
|
||||
int nIds_ = 0;
|
||||
int nExIds_ = 0;
|
||||
char brand[0x40];
|
||||
std::bitset<32> cpu_capabilities = 0;
|
||||
|
||||
nIds_ = CPUID(0, 0).EAX();
|
||||
// load bitset with flags for function 0x00000001
|
||||
if (nIds_ >= 1)
|
||||
{
|
||||
cpu_capabilities = CPUID(1, 0).ECX();
|
||||
}
|
||||
|
||||
nExIds_ = CPUID(0x80000000, 0).EAX();
|
||||
memset(brand, 0, sizeof(brand));
|
||||
if (nExIds_ >= 0x80000004)
|
||||
{
|
||||
memcpy(brand, CPUID(0x80000002, 0).data(), 16);
|
||||
memcpy(brand + 16, CPUID(0x80000003, 0).data(), 16);
|
||||
memcpy(brand + 32, CPUID(0x80000004, 0).data(), 16);
|
||||
}
|
||||
|
||||
bool supports_ssse3 = cpu_capabilities[9];
|
||||
|
||||
std::string s_sysInfo = fmt::format("%s | SSSE3 %s", std::regex_replace(brand, std::regex("^ +"), ""), supports_ssse3 ? "Supported" : "Not Supported");
|
||||
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetNativeSystemInfo(&sysInfo);
|
||||
MEMORYSTATUSEX memInfo;
|
||||
memInfo.dwLength = sizeof(memInfo);
|
||||
GlobalMemoryStatusEx(&memInfo);
|
||||
s_sysInfo += fmt::format(" | %d Threads | %.2f GB RAM", sysInfo.dwNumberOfProcessors, (float)memInfo.ullTotalPhys / std::pow(1024.0f, 3));
|
||||
#else
|
||||
long mem_total = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
|
||||
s_sysInfo += fmt::format(" | %d Threads | %.2f GB RAM", sysconf(_SC_NPROCESSORS_ONLN), (float)mem_total / std::pow(1024.0f, 3));
|
||||
#endif
|
||||
|
||||
return std::pair<std::string, bool>(s_sysInfo, supports_ssse3);
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user