Selectable with --graphics=metal, the backend choice in settings and the
Mac menu bar. SDL creates a Metal view for it, and headless renders
offscreen. Games run on the null GPU until there's a GPU/Metal.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The loader thread now only loads the game. PSP_InitUpdate creates the GPU on
the thread that owns the graphics device, so device loss can't race the
creation, and the device-lost flag and the GPU init on libretro's separate
path are gone. Vulkan loads its shader cache without waiting for the
pipelines, and PSP_InitUpdate keeps the boot in Booting until they're
created. Exiting during boot joins the loader thread in PSP_Shutdown.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
EmuScreen::deviceLost waited for the boot thread to finish, so that it
wouldn't create the GPU on a lost device. With the main thread joining the
render thread on surfaceDestroyed, backgrounding the app during a slow boot
(like the firmware auto-install from the disc) caused ANRs.
Instead, the boot thread now skips creating the GPU if the device is lost,
and PSP_InitUpdate creates it once rendering resumes, as on libretro.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The GPU only picks up the setting when emulation runs, so after turning
Skip Buffer Effects off in the pause menu, PreRender ran the buffered-mode
display path with a GPU still in non-buffered mode. For a frame displayed
from RAM, that draws straight to output (since b8789af997) with no render
pass bound, crashing in VulkanRenderManager::SetScissor.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Fixes#13722
Opening the chat with focus left the stick directions and keys held in-game
in the UI's held-key list, so the focus started moving right away. And while
the chat is open, stick movements don't reach the control mapper, so a stick
let go inside the chat stayed pushed for the game after it closed. Clear the
held keys when focus movement turns on, and release the mapper's input on
the next update (OpenChat can run under the mapper's lock).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Part of #21585
Android 17 blocks LAN traffic in both directions (TCP and UDP, including
broadcast and multicast) without ACCESS_LOCAL_NETWORK. Ask for it when
networking, the built-in ad hoc server, UPnP, share-on-startup or the
remote debugger gets turned on, when a game initializes ad hoc with
networking enabled, and at startup if a server is set to start then.
A denied ad hoc send fails with EPERM, which the games never see, so show
a message for it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The app now always uses the Metal view controller with Vulkan (MoltenVK),
for both the App Store and sideload builds. The GL view controller is gone,
and Common/GPU/OpenGL (except GLFeatures, used by the shader generators) and
GPU/GLES are no longer compiled for it. PPSSPP_API_ANY_GL is now off for
all of iOS except the libretro core, which still uses GLES.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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) <noreply@anthropic.com>
Freeze-frame restores a savestate every frame, straight through
SaveState::LoadFromRam(), so it never touched the operation queue and neither
hardcore check saw it. Blocked at the toggle in the dev menu, and again in the
render loop, since hardcore mode can come up after the fact once the game has
been identified.
Enqueue also just dropped operations silently, so a load that arrived through a
path with no check of its own (--state, auto-load) did nothing with no
explanation. Both it and Process now go through WarnUserIfHardcoreModeActive,
which is the same predicate plus the standard message. Callers that already ask
it themselves return before reaching Enqueue, so nothing shows the message twice.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgACRqkQNpfJQ4fjwyoEup