From 0b5a8f537ef256f77c7d576f4c8ffaaeb2f7f785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 21 Sep 2026 09:31:20 -0600 Subject: [PATCH] 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) --- Core/CoreParameter.h | 4 ++++ GPU/Common/DrawEngineCommon.cpp | 2 +- GPU/Common/VertexDecoderCommon.cpp | 6 +----- UI/EmuScreen.cpp | 1 + headless/Headless.cpp | 16 ++++------------ libretro/libretro.cpp | 1 + 6 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 22b75f18e8..9558ba2cac 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -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. diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 8c0a6d3bcc..09bf16b891 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -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); diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 7fd37575b0..a9e6cad933 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -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,10 +1622,7 @@ 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); - } + ClearCodeSpace(0); } struct StepFunctionNameEntry { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 014db251d9..677ef5d4d0 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -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: diff --git a/headless/Headless.cpp b/headless/Headless.cpp index cfc73f1095..414bd04cc3 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -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; diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 8f2830bdbb..a217af86f6 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -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;