Decide on the vertex decoder JIT with CoreParameter, not the CPU core

The vertex decoder JIT was enabled only when g_Config.iCpuCore was one of the
JIT cores, which tied an unrelated GPU path to the CPU setting. Headless leaned
on that by forcing iCpuCore to the interpreter after ApplyToConfig(), to keep
the decoder JIT off in the tests.

Add CoreParameter::bUseVertexDecoderJit instead. Standalone and libretro set it
wherever the host can JIT, so IR interpreter users on such hosts now get the
decoder JIT too. Headless sets it false, which keeps the test results as they
were and lets --cpu go through ApplyToConfig() like every other option.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-21 10:31:58 -06:00
1 parent 8afbcc3747
commit 0b5a8f537e
6 files changed
+11 -17

No files matched your search

+4
View File
@@ -55,6 +55,10 @@ struct CoreParameter {
CPUCore cpuCore;
GPUCore gpuCore;
// Independent of cpuCore. Standalone turns it on wherever the host can JIT; headless keeps it
// off, since the test references were recorded with the C++ vertex decoder.
bool bUseVertexDecoderJit = false;
GraphicsContext *graphicsContext = nullptr; // TODO: Find a better place.
bool enableSound = true; // there aren't multiple sound cores.
+1 -1
View File
@@ -44,7 +44,7 @@ enum {
};
DrawEngineCommon::DrawEngineCommon() : decoderMap_(32) {
if (g_Config.bVertexDecoderJit && (g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR)) {
if (g_Config.bVertexDecoderJit && PSP_CoreParameter().bUseVertexDecoderJit) {
decJitCache_ = new VertexDecoderJitCache();
}
transformed_ = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
-4
View File
@@ -27,7 +27,6 @@
#include "Common/Math/CrossSIMD.h"
#include "Common/Log.h"
#include "Common/LogReporting.h"
#include "Core/Config.h"
#include "Core/ConfigValues.h"
#include "Core/HDRemaster.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
@@ -1623,11 +1622,8 @@ VertexDecoderJitCache::VertexDecoderJitCache()
}
void VertexDecoderJitCache::Clear() {
// TODO: These should check CoreParameter instead.
if (g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR) {
ClearCodeSpace(0);
}
}
struct StepFunctionNameEntry {
StepFunction func;
+1
View File
@@ -282,6 +282,7 @@ void EmuScreen::ProcessGameBoot(const Path &filename) {
CoreParameter coreParam{};
coreParam.cpuCore = (CPUCore)g_Config.iCpuCore;
coreParam.bUseVertexDecoderJit = System_GetPropertyBool(SYSPROP_CAN_JIT);
coreParam.gpuCore = GPUCORE_GLES;
switch (GetGPUBackend()) {
case GPUBackend::DIRECT3D11:
+4 -12
View File
@@ -835,8 +835,7 @@ int main(int argc, const char* argv[]) {
// Force known values for deterministic test execution. This happens before
// ApplyToConfig() below, so a matching command line flag can still override any of it -
// ApplyToConfig() always has the final say on the settings in g_Config - except for iCpuCore,
// which is forced after it instead, see below.
// ApplyToConfig() always has the final say on the settings in g_Config.
// NOTE: In headless mode, we never save the config. This is just for this run.
g_Config.iDumpFileTypes = 0;
@@ -889,14 +888,6 @@ int main(int argc, const char* argv[]) {
// overrides above, so a matching command line flag always wins.
cmdLineOptions.ApplyToConfig();
// The exception to that, forced after ApplyToConfig() so --cpu can't reach it. g_Config.iCpuCore
// doesn't pick the MIPS core here (CoreParameter below does, straight from the command line) -
// it also gates the vertex decoder JIT, in the DrawEngineCommon constructor. Letting --cpu=jit
// switch that on decodes vertices through a different path and changes the output of a dozen or
// so GPU tests, gpu/vertices/morph among them. The core to test is a CPU question, so keep the
// GPU side on one path for every backend.
g_Config.iCpuCore = (int)CPUCore::INTERPRETER;
// pspautotests is plain homebrew PRXes so do not ship user libraries that a retail disc may carry.
// So we must use HLE, unless we install firmware.
// A disc brings its own copies and the app runs them for real, so
@@ -907,8 +898,6 @@ int main(int argc, const char* argv[]) {
g_Config.iForceEnableHLE = 0xFFFFFFFF & ~g_Config.iDisableHLE;
}
// This looks contradictory to above checks. But, this preserves the old test behavior which apparently ran the JIT for the CPU
// but ended up running software vertex decoding due to the setting in g_Config. Yeah, it's a mess.
CPUCore cpuCore = CPUCore::JIT;
if (cmdLineOptions.cpuCore.has_value()) {
cpuCore = cmdLineOptions.cpuCore.value();
@@ -963,6 +952,9 @@ int main(int argc, const char* argv[]) {
// but not now.
CoreParameter coreParameter;
coreParameter.cpuCore = (CPUCore)cpuCore;
// The pspautotests expectations and frametest references were recorded with the C++ vertex
// decoder, and the JIT decoders don't match it everywhere yet.
coreParameter.bUseVertexDecoderJit = false;
coreParameter.gpuCore = (GPUCore)gpuCore;
coreParameter.graphicsContext = graphicsContext;
coreParameter.enableSound = false;
+1
View File
@@ -1512,6 +1512,7 @@ bool retro_load_game(const struct retro_game_info *game) {
// set cpuCore from libretro setting variable
coreParam.cpuCore = (CPUCore)g_Config.iCpuCore;
coreParam.bUseVertexDecoderJit = System_GetPropertyBool(SYSPROP_CAN_JIT);
g_pendingBoot = true;