GS: Add MultiISA files

This commit is contained in:
TellowKrinkle 2021-12-17 23:05:50 -06:00 committed by TellowKrinkle
parent 0692a9ff51
commit d56e6427a9
9 changed files with 204 additions and 21 deletions

View File

@ -673,6 +673,7 @@ set(pcsx2GSSources
GS/GSTables.cpp
GS/GSUtil.cpp
GS/GSVector.cpp
GS/MultiISA.cpp
GS/Renderers/Common/GSDevice.cpp
GS/Renderers/Common/GSDirtyRect.cpp
GS/Renderers/Common/GSFunctionMap.cpp
@ -732,6 +733,7 @@ set(pcsx2GSHeaders
GS/GSVector4i.h
GS/GSVector8.h
GS/GSVector8i.h
GS/MultiISA.h
GS/Renderers/Common/GSDevice.h
GS/Renderers/Common/GSDirtyRect.h
GS/Renderers/Common/GSFastList.h

View File

@ -17,6 +17,7 @@
#include "GS.h"
#include "GSExtra.h"
#include "GSUtil.h"
#include "MultiISA.h"
#include "common/StringUtil.h"
#ifdef _WIN32
@ -29,8 +30,6 @@
#define SVN_MODS 0
#endif
Xbyak::util::Cpu g_cpu;
static class GSUtilMaps
{
public:
@ -149,37 +148,30 @@ bool GSUtil::HasCompatibleBits(u32 spsm, u32 dpsm)
bool GSUtil::CheckSSE()
{
bool status = true;
struct ISA
{
Xbyak::util::Cpu::Type type;
ProcessorFeatures::VectorISA isa;
const char* name;
};
ISA checks[] = {
{Xbyak::util::Cpu::tSSE41, "SSE41"},
{ProcessorFeatures::VectorISA::SSE4, "SSE 4.1"},
#if _M_SSE >= 0x500
{Xbyak::util::Cpu::tAVX, "AVX1"},
{ProcessorFeatures::VectorISA::AVX, "AVX"},
#endif
#if _M_SSE >= 0x501
{Xbyak::util::Cpu::tAVX2, "AVX2"},
{Xbyak::util::Cpu::tBMI1, "BMI1"},
{Xbyak::util::Cpu::tBMI2, "BMI2"},
{ProcessorFeatures::VectorISA::AVX2, "AVX2"},
#endif
};
for (const ISA& check : checks)
{
if (!g_cpu.has(check.type))
if (g_cpu.vectorISA < check.isa)
{
fprintf(stderr, "This CPU does not support %s\n", check.name);
status = false;
Console.Error("This CPU does not support %s", check.name);
return false;
}
}
return status;
return true;
}
CRCHackLevel GSUtil::GetRecommendedCRCHackLevel(GSRendererType type)

View File

@ -22,8 +22,6 @@
#include <dxgi.h>
#endif
#include <xbyak/xbyak_util.h>
class GSUtil
{
public:
@ -52,5 +50,3 @@ void GSmkdir(const char* dir);
std::string GStempdir();
const char* psm_str(int psm);
extern Xbyak::util::Cpu g_cpu;

92
pcsx2/GS/MultiISA.cpp Normal file
View File

@ -0,0 +1,92 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "MultiISA.h"
#include <xbyak/xbyak_util.h>
#ifdef _WIN32
#define strcasecmp _stricmp
#endif
static Xbyak::util::Cpu s_cpu;
static ProcessorFeatures::VectorISA getCurrentISA()
{
// For debugging
if (const char* over = getenv("OVERRIDE_VECTOR_ISA"))
{
if (strcasecmp(over, "avx2") == 0)
{
fprintf(stderr, "Vector ISA Override: AVX2\n");
return ProcessorFeatures::VectorISA::AVX2;
}
if (strcasecmp(over, "avx") == 0)
{
fprintf(stderr, "Vector ISA Override: AVX\n");
return ProcessorFeatures::VectorISA::AVX;
}
if (strcasecmp(over, "sse4") == 0)
{
fprintf(stderr, "Vector ISA Override: SSE4\n");
return ProcessorFeatures::VectorISA::SSE4;
}
}
if (s_cpu.has(Xbyak::util::Cpu::tAVX2) && s_cpu.has(Xbyak::util::Cpu::tBMI1) && s_cpu.has(Xbyak::util::Cpu::tBMI2))
return ProcessorFeatures::VectorISA::AVX2;
else if (s_cpu.has(Xbyak::util::Cpu::tAVX))
return ProcessorFeatures::VectorISA::AVX;
else if (s_cpu.has(Xbyak::util::Cpu::tSSE41))
return ProcessorFeatures::VectorISA::SSE4;
else
return ProcessorFeatures::VectorISA::None;
}
static ProcessorFeatures getProcessorFeatures()
{
ProcessorFeatures features = {};
features.vectorISA = getCurrentISA();
features.hasFMA = s_cpu.has(Xbyak::util::Cpu::tFMA);
if (const char* over = getenv("OVERRIDE_FMA"))
{
features.hasFMA = over[0] == 'Y' || over[0] == 'y' || over[0] == '1';
fprintf(stderr, "Processor FMA override: %s\n", features.hasFMA ? "Supported" : "Unsupported");
}
features.hasSlowGather = false;
if (const char* over = getenv("OVERRIDE_SLOW_GATHER")) // Easy override for comparing on vs off
{
features.hasSlowGather = over[0] == 'Y' || over[0] == 'y' || over[0] == '1';
fprintf(stderr, "Processor gather override: %s\n", features.hasSlowGather ? "Slow" : "Fast");
}
else if (features.vectorISA == ProcessorFeatures::VectorISA::AVX2)
{
if (s_cpu.has(Xbyak::util::Cpu::tINTEL))
{
// Slow on Haswell
// CPUID data from https://en.wikichip.org/wiki/intel/cpuid
features.hasSlowGather = s_cpu.displayModel == 0x46 || s_cpu.displayModel == 0x45 || s_cpu.displayModel == 0x3c;
}
else
{
// Currently no Zen CPUs with fast VPGATHERDD
// Check https://uops.info/table.html as new CPUs come out for one that doesn't split it into like 40 µops
// Doing it manually is about 28 µops (8x xmm -> gpr, 6x extr, 8x load, 6x insr)
features.hasSlowGather = true;
}
}
return features;
}
const ProcessorFeatures g_cpu = getProcessorFeatures();

85
pcsx2/GS/MultiISA.h Normal file
View File

@ -0,0 +1,85 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "PCSX2Base.h"
// For multiple-isa compilation
#ifdef MULTI_ISA_UNSHARED_COMPILATION
// Preprocessor should have MULTI_ISA_UNSHARED_COMPILATION defined to `isa_sse4`, `isa_avx`, or `isa_avx2`
#define CURRENT_ISA MULTI_ISA_UNSHARED_COMPILATION
#else
// Define to isa_native in shared section in addition to multi-isa-off so if someone tries to use it they'll hopefully get a linker error and notice
#define CURRENT_ISA isa_native
#endif
#if defined(MULTI_ISA_UNSHARED_COMPILATION)
// Preprocessor should have MULTI_ISA_IS_FIRST defined to 0 or 1
/// Use with `#if MULTI_ISA_COMPILE_ONCE` to make a single definition of something in an otherwise multi-isa-compiled file.
#define MULTI_ISA_COMPILE_ONCE MULTI_ISA_IS_FIRST
#elif !defined(MULTI_ISA_SHARED_COMPILATION)
#define MULTI_ISA_COMPILE_ONCE 1
#else
#define MULTI_ISA_COMPILE_ONCE static_assert(0, "You don't need MULTI_ISA_COMPILE_ONCE in a non-multi-isa file!");
#endif
#ifndef MULTI_ISA_SHARED_COMPILATION
/// Mark the start of a header defining code that will be compiled multiple times in multi-isa mode
/// Anything between this and a `MULTI_ISA_UNSHARED_END` will be placed in a different namespace for each of the multilple compilations
#define MULTI_ISA_UNSHARED_START namespace CURRENT_ISA {
/// Mark the end of a header defining code that will be compiled multiple times in multi-isa mode
#define MULTI_ISA_UNSHARED_END }
/// Mark the beginning of a file implementing things that will be compiled multiple times in multi-isa mode
/// Takes advantage of the fact that a `using namespace` declaration will also affect any implementations of things as long as they're not valid without it
/// Fully global variables are valid as-is, however, and will need to have `CURRENT_ISA::` manually prepended to them.
/// If you forget to do this, it will show up as a linker error (either multiple definitions of the function/variable, or a "failed to find isa_native::function")
#define MULTI_ISA_UNSHARED_IMPL using namespace CURRENT_ISA
#else
#define MULTI_ISA_UNSHARED_START static_assert(0, "This file should not be included by multi-isa shared compilation!");
#define MULTI_ISA_UNSHARED_IMPL static_assert(0, "This file should be compiled unshared in multi-isa mode!");
#define MULTI_ISA_UNSHARED_END
#endif
struct ProcessorFeatures
{
enum class VectorISA { None, SSE4, AVX, AVX2 };
VectorISA vectorISA;
bool hasFMA;
bool hasSlowGather;
};
extern const ProcessorFeatures g_cpu;
#if defined(MULTI_ISA_UNSHARED_COMPILATION) || defined(MULTI_ISA_SHARED_COMPILATION)
#define MULTI_ISA_DEF(...) \
namespace isa_sse4 { __VA_ARGS__ } \
namespace isa_avx { __VA_ARGS__ } \
namespace isa_avx2 { __VA_ARGS__ }
#define MULTI_ISA_FRIEND(klass) \
friend class isa_sse4::klass; \
friend class isa_avx ::klass; \
friend class isa_avx2::klass;
#define MULTI_ISA_SELECT(fn) (\
::g_cpu.vectorISA == ProcessorFeatures::VectorISA::AVX2 ? isa_avx2::fn : \
::g_cpu.vectorISA == ProcessorFeatures::VectorISA::AVX ? isa_avx ::fn : \
isa_sse4::fn)
#else
#define MULTI_ISA_DEF(...) namespace isa_native { __VA_ARGS__ }
#define MULTI_ISA_FRIEND(klass) friend class isa_native::klass;
#define MULTI_ISA_SELECT(fn) (isa_native::fn)
#endif

View File

@ -475,6 +475,7 @@
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp" />
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
<ClCompile Include="GS\Renderers\Common\GSVertexTrace.cpp" />
<ClCompile Include="GS\MultiISA.cpp" />
<ClCompile Include="Dump.cpp" />
<ClCompile Include="Pcsx2Config.cpp" />
<ClCompile Include="windows\FlatFileReaderWindows.cpp" />
@ -875,6 +876,7 @@
<ClInclude Include="GS\Renderers\SW\GSVertexSW.h" />
<ClInclude Include="GS\Renderers\Common\GSVertexTrace.h" />
<ClInclude Include="GS\resource.h" />
<ClInclude Include="GS\MultiISA.h" />
<ClInclude Include="IPU\IPUdma.h" />
<ClInclude Include="Mdec.h" />
<ClInclude Include="Patch.h" />

View File

@ -1520,6 +1520,9 @@
<ClCompile Include="GS\GSLzma.cpp">
<Filter>System\Ps2\GS</Filter>
</ClCompile>
<ClCompile Include="GS\MultiISA.cpp">
<Filter>System\Ps2\GS</Filter>
</ClCompile>
<ClCompile Include="gui\Dialogs\PINEDialog.cpp">
<Filter>AppHost\Dialogs</Filter>
</ClCompile>
@ -2722,6 +2725,9 @@
<ClInclude Include="GS\GSLzma.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>
<ClInclude Include="GS\MultiISA.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>
<ClInclude Include="GS\Renderers\Common\GSFastList.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>

View File

@ -328,6 +328,7 @@
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp" />
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
<ClCompile Include="GS\Renderers\Common\GSVertexTrace.cpp" />
<ClCompile Include="GS\MultiISA.cpp" />
<ClCompile Include="SPU2\Windows\SndOut_XAudio2.cpp" />
<ClCompile Include="USB\USBNull.cpp" />
<ClCompile Include="Dump.cpp" />
@ -651,6 +652,7 @@
<ClInclude Include="GS\Renderers\Common\GSVertexList.h" />
<ClInclude Include="GS\Renderers\SW\GSVertexSW.h" />
<ClInclude Include="GS\Renderers\Common\GSVertexTrace.h" />
<ClInclude Include="GS\MultiISA.h" />
<ClInclude Include="GS\resource.h" />
<ClInclude Include="IPU\IPUdma.h" />
<ClInclude Include="Mdec.h" />

View File

@ -1013,6 +1013,9 @@
<ClCompile Include="GS\GSVector.cpp">
<Filter>System\Ps2\GS</Filter>
</ClCompile>
<ClCompile Include="GS\MultiISA.cpp">
<Filter>System\Ps2\GS</Filter>
</ClCompile>
<ClCompile Include="GS\GSPng.cpp">
<Filter>System\Ps2\GS</Filter>
</ClCompile>
@ -1871,6 +1874,9 @@
<ClInclude Include="GS\GSVector8.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>
<ClInclude Include="GS\MultiISA.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>
<ClInclude Include="GS\config.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>