Commit Graph
48098 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 3aaea4c0f9 GameInfoCache: Prioritize loads, so launching doesn't wait behind search
Type-to-search asks for the title of every game in the list, queueing a
load for each, and launching a game whose info wasn't loaded yet then
blocked until the whole queue had drained. Search's loads are now LOW,
and launching asks at HIGH, which queues its own load rather than wait
for a pending one.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 16:34:38 -06:00
Henrik Rydgård ae460c9e1a Merge pull request #22390 from hrydgard/gpu-review-leftovers
Claude code review of GPU: Fix leftover findings
2026-09-29 15:43:31 -06:00
Henrik Rydgård 68755d7f63 Merge pull request #22392 from hrydgard/headless-vulkan-screenshot-assert
Headless: Take the timeout screenshot before ending the draw frame
2026-09-29 15:41:12 -06:00
Henrik RydgårdandClaude Opus 5.5 f6e70b88ad Headless: Take the timeout screenshot before ending the draw frame
On Vulkan, reading back the display framebuffer after EndDrawFrame hit
the insideFrame_ assert in CopyFramebufferToMemory, so any run that
timed out with --screenshot-save crashed in debug builds.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 14:05:00 -06:00
Henrik Rydgård c9c26ce0fd Merge pull request #22389 from hrydgard/savedata-icon-black-background
Savedata dialog: Draw icons over black, with alpha blending
2026-09-29 13:52:34 -06:00
Henrik Rydgård 949423d8e9 Merge pull request #22388 from hrydgard/update-xxhash
Update xxhash to v0.8.4, use XXH3 for texture hashing
2026-09-29 13:52:00 -06:00
Henrik Rydgård b9c5b28b8f Merge pull request #22386 from hrydgard/adhoc-shutdown-race
Adhoc: Fix shutdown hanging when it comes right after adhoc init
2026-09-29 13:29:20 -06:00
Henrik RydgårdandClaude Opus 5.5 b9501df529 TextureReplacer: Fix stale and shared lookup results
- Reloading the ini clears the per-key lookup caches, which could keep
  saying "no replacement" for textures the new ini replaces.
- With ignoreAddress, hash ranges were skipped when sizing the
  replacement, though ComputeHash applies them. cache_ is now keyed by
  the full key, so its lookups hit too.
- Textures sharing files but differing in size, hash range or filtering
  no longer share one ReplacedTexture (the first one's settings won).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:28:21 -06:00
Henrik RydgårdandClaude Opus 5.5 1288c294fd Savedata dialog: Draw icons over black, with alpha blending
The PSP blends save icons over a black background, so their transparent
parts come out black. 0a5fa27957 turned blending off instead, which is
wrong for icons that rely on it. Revert that, and draw a black rectangle
under each icon. Fixes #22280.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:21:24 -06:00
Henrik RydgårdandClaude Opus 5.5 bd27ceb669 Headless: Reject --debugger together with --debugger-run
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:17:01 -06:00
Henrik RydgårdandClaude Opus 5.5 b8789af997 GPU: Draw frames displayed from RAM in non-buffered mode
They were uploaded but never drawn, and the block transfer hack drew
whatever source was left over. Draw them straight into the backbuffer
pass, without post shaders, which would need to bind their own targets.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:17:01 -06:00
Henrik RydgårdandClaude Opus 5.5 4bfa4e14ec Vulkan: Make WaitForPipelines wait for queued compiles too
Pipelines still in the compile queue weren't in flight yet, so the
shader cache load could stop waiting (and the spinner) early.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:17:01 -06:00
Henrik RydgårdandClaude Opus 5.5 39b6cc0c0c Vulkan: Fix the debugger screenshot in headless
There's no swapchain, so reading the backbuffer asserted. Fail the
readback, and have gpu.buffer.screenshot fall back to the displayed
framebuffer.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:17:00 -06:00
Henrik RydgårdandClaude Opus 5.5 7e553b0732 GE debugger: Lock when adding command breakpoints
Debuggers add them from their own threads, racing ClearTempBreakpoints
on the emu thread.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:17:00 -06:00
Henrik RydgårdandClaude Opus 5.5 035c98d14f D3D11: Re-read the device and context on DeviceRestore
The restored draw context can be a new device, so the cached pointers
could go stale.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:59 -06:00
Henrik RydgårdandClaude Opus 5.5 ba37f327b0 D3D11: Check Map() results
Map fails after device removal, leaving pData garbage. Skip the upload or
draw instead of writing through it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:59 -06:00
Henrik RydgårdandClaude Opus 5.5 bc581349fd GPU: Install the draw engines' invalidation callback from BeginFrame
The draw engine is created on the loader thread while the UI thread may
already be rendering and invoking the callback.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:42 -06:00
Henrik RydgårdandClaude Opus 5.5 759b494b6a GPU: Check post shaders once per host frame, after resizes
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:41 -06:00
Henrik RydgårdandClaude Opus 5.5 4749872f2e Vulkan: Clear a texture level when hardware scaling fails
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:41 -06:00
Henrik RydgårdandClaude Opus 5.5 4c2086aac5 GPU: Keep spline/bezier tessellation from reaching zero
Reduce only the larger factor when over the vertex limit, and stop at 1.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:40 -06:00
Henrik RydgårdandClaude Opus 5.5 9d3022642b SoftGPU: Fix bin queue bookkeeping and dependency tracking
- Flush() on an empty queue now trims the state and CLUT rings, since its
  callers flush because one is full and push right after.
- BinQueue::Full() uses >=, so an overshoot can't go unnoticed.
- IsExactSelfRender compares against the target the queued draws were
  binned for, not gstate, which already has the next one during a flush.
- A depth test without depth writes marks the depth buffer as read.
- The DarkStalkers untextured sprite recomputes the binner state around it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:16:40 -06:00
Henrik Rydgård 0c6a28fe11 Merge pull request #22387 from hrydgard/homebrew-slim-extra-ram
Expose extra ram to homebrew apps if Slim model is emulated
2026-09-29 13:13:10 -06:00
Henrik RydgårdandClaude Opus 5.5 7de7b2d76b TextureCache: Use XXH3 instead of the quick hash for texture data
With xxhash 0.8.4, XXH3 is faster than StableQuickTexHash on ARM64
(about 37 vs 24 GB/s on a Snapdragon X), and its scalar path, which
RISC-V builds get, is about as fast as the quick hash's. It doesn't
collide the way the quick hash does (#8249).

Texture replacement still uses its own hash setting, so texture packs
are unaffected.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:10:28 -06:00
Henrik RydgårdandClaude Opus 5.5 21ee60a8ab Build: Update xxhash to v0.8.4.
Keeps our two local changes (the ppsspp_config.h include and the ARM32
prefetch in the XXH32 loop). Hash values are unchanged.

XXH3 is much faster on ARM64 now: about 37 GB/s against 13.5 with v0.8.1
on a Snapdragon X, where our quick texture hash does 24.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 13:04:08 -06:00
Henrik Rydgård 36cbb32e77 Merge pull request #22385 from hrydgard/goedit-camera-hang
Fix Go!Edit camera hang, and some other related issues
2026-09-29 13:00:49 -06:00
Henrik RydgårdandClaude Opus 5.5 74553bfa1a D3D11: Note that the state object caches are deliberately never trimmed
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:43:12 -06:00
Henrik RydgårdandClaude Opus 5.5 3062ffd695 Map the PSP-2000 extra RAM for homebrew PBPs, outside the user partition
Homebrew written for a PSP-2000+ under custom firmware can use the top
32MB of RAM directly without setting MEMSIZE, which leaves the user
partition at its normal size. NJEMU's slim builds do this (#8925).
Previously we didn't map that memory at all for PBPs; MEMSIZE=1 isn't a
workaround either, since it grows the partition and the heap and stacks
land where the program writes.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:40:59 -06:00
Henrik RydgårdandClaude Opus 5.5 c9a631c336 sceCtrl: Add the 3.71 sceCtrl_driver NID for sceCtrlPeekBufferPositive
NJEMU's SystemButtons.prx kernel plugin imports it when the firmware
reports 3.71 or later, and polls it every frame to read HOME/volume.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:40:59 -06:00
Henrik RydgårdandClaude Opus 5.5 619d331a86 Headless: Use localhost as the adhoc server
The net tests need WLAN on, but that also made every game run log into a
real adhoc server on the internet, so results depended on the network.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:37:48 -06:00
Henrik RydgårdandClaude Opus 5.5 7ec860c24f Adhoc: Stop waiting for a login that has already failed
sceNetAdhocctlInit waits until the friend finder has logged into the adhoc
server, polling in emulated time but giving up only after 5s of wall time.
The friend finder makes one attempt per login request, and it too waited
the full 5s on a connection that had already been refused, because it
only looked for success. Now it checks the socket error and gives up at
once, and records the failure so the wait ends with it.

In headless, which runs far ahead of real time, Gods Eater Burst sat in
this wait for its whole run.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:37:48 -06:00
Henrik Rydgård 1b8553956f Merge pull request #22383 from hrydgard/preemptible-syscalls
Fixes after hardware scheduling tests by Claude
2026-09-29 12:35:27 -06:00
Henrik RydgårdandClaude Opus 5.5 9e54cebcc2 Camera: Remember the JPEG quality that fit the last frame
Start from the quality that fit the previous frame instead of the top, so
most frames encode once. Step down while a frame is too big, and step back
up when one comes out under half the limit. Windows and the recompression
fallback share the logic.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:29:04 -06:00
Henrik RydgårdandClaude Opus 5.5 07556d064e Camera: Recompress oversized frames on every platform
Android, iOS, macOS and Linux encode camera frames at a fixed quality, so a
detailed frame can exceed the game's framesize just as on Windows before.
pushCameraImage now decodes such a frame and re-encodes it at lower quality
until it fits.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 12:24:40 -06:00
Henrik RydgårdandClaude Opus 5.5 2cd84012d0 Adhoc: Fix shutdown hanging when it comes right after adhoc init
The friend finder thread set friendFinderRunning itself, after a DNS
lookup of the adhoc server. A shutdown in that window cleared the flag
first; the thread then set it again, looped forever, and the join in
NetAdhocctl_Term() never returned. Gods Eater Burst hit this in about one
headless run in six. The flag is now set before the thread is created,
and a finished thread is joined before a new one replaces it, which
would otherwise call std::terminate.

The built-in adhoc server thread had the same race, behind its check for
an existing server, and gets the same fix.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:58:42 -06:00
Henrik RydgårdandClaude Opus 5.5 9d33e828ab Camera: Compress webcam frames to fit the game's framesize
The PSP camera keeps JPEG frames within the framesize from the video setup.
Go!Edit stores frames in 15KB slots and only takes frames that fit, so our
uncompressed-quality webcam frames were dropped and one frame got repeated
for the whole clip. Lower the JPEG quality until a frame fits.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:44:10 -06:00
Henrik RydgårdandClaude Opus 5.5 948062907b sceUsbMic: Complete blocking reads when the samples are due
With a host microphone present, a blocking read waited until the host had
delivered all the data. If it never did, the thread waited forever: Go!Edit's
sound thread stalled that way and its video recording never advanced. The
PSP mic streams in real time, so wake at the scheduled time and fill what
the host didn't deliver with silence.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:44:10 -06:00
Henrik RydgårdandClaude Opus 5.5 2a5febd634 wsdbg: Add :screenshot, and document nested key=value params
:screenshot saves gpu.buffer.screenshot as a PNG without dumping the data
URI into the output. The docs claimed nested parameters need a raw JSON
line, which gets no ticket; a single-quoted JSON value in key=value form
works and keeps it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:19:18 -06:00
Henrik RydgårdandClaude Opus 5.5 4504092d3d sceUsbMic: Don't crash when there's no Windows capture device object
Only the app creates winMic, so a blocking mic read crashed headless.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:19:18 -06:00
Henrik RydgårdandClaude Opus 5.5 280ae09856 sceUsbCam: Make sceUsbCamReadVideoFrameBlocking wait for the next frame
It returned at once. Go!Edit reads frames in a loop on a high-priority
thread (bhCameraGetJpeg) that only yields to its own priority level, so
after the "Loading complete" dialog it spun and starved the rest of the
game. Return at the camera's next frame tick, at the rate from the setup
params.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:19:18 -06:00
Henrik RydgårdandClaude Opus 5.5 5865a560eb ARM JITs: Mask what ctc1 writes to fcr31
Only the rounding mode, flags, enables, cause, FCC and FS bits can be
written (0x0181FFFF, pspautotests cpu/fpu/fcr), as the interpreter, IR
and x86 already have it. Both ARM JITs stored the whole value.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:09:47 -06:00
Henrik RydgårdandClaude Opus 5.5 178186ef4e sceVaudio: Reserving the channel waits about 250us
On hardware sceVaudioChReserve takes ~260us once it gets past the busy
check, succeed or fail, and worse threads can run meanwhile. Releasing
takes ~25us and doesn't wait. We returned at once, which is what
audio/sceaudio/reserve's [r] markers showed; it now passes.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:09:47 -06:00
Henrik RydgårdandClaude Opus 5.5 69e10728c9 test.py: Add gpu/primitives/indices32 to the to-do list
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:09:47 -06:00
Henrik RydgårdandClaude Opus 5.5 af8088b790 Threads: A delay can end before it starts waiting
A delay's deadline is now + usec, and the clock is read again when the
alarm is set. If the deadline has passed by then, the call returns 0 at
once without giving up the CPU. On hardware that makes
sceKernelDelayThread(0) return at once about 60% of the time. On a thread's
first wait after it starts, a delay of 1 does so about two times in three
as well (pspautotests threads/scheduling/delayzero). We always waited at
least 210us.

The choice is pseudo-random off the tick count, not the tick phase, since
our cycle counts are regular enough for a polling loop to lock into never
yielding. Threads remember whether they've waited since starting (Thread
savestate section version 6).

Also moves threads/vpl/create into the passing tests: re-recorded on 6.61,
it agrees with what we do for partitions 8 and 9.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:09:47 -06:00
Henrik RydgårdandClaude Opus 5.5 13dee85375 sceIo: host0: behaves like usbhostfs with dispatch suspended
With dispatch suspended, IO fails in the driver when it tries to wait. The
memory stick driver returns SCE_KERNEL_ERROR_CAN_NOT_WAIT, while usbhostfs,
which serves host0: under PSPLink, returns -1. host0: is mostly what
homebrew developers run from, so it now does the same.

Also from threads/scheduling/dispatch, which now passes:
- sceIoRead reports an async operation still in progress before failing
  on suspended dispatch.
- A write to stdout or stderr doesn't give up the CPU.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:09:47 -06:00
Henrik RydgårdandClaude Opus 5.5 f2eba8f711 sceKernelLoadModule: Charge for reading the file and loading it
On hardware a load costs an open and a read of the file, plus about 1ms
and 30us per KB of loader work (pspautotests threads/scheduling/callcosts),
with the caller waiting throughout. It now charges sceIoOpen's and
sceIoRead's estimates for the file plus that, instead of a flat 500us.

Also notes why sceKernelLoadModuleByID fails from a game's own fd on ms0:
or host0: on hardware, which we don't emulate.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 11:09:47 -06:00
Henrik Rydgård 806618f9a3 Merge pull request #22382 from hrydgard/gpu-lifecycle-fixes-2
Claude code review: GPU fixes 2
2026-09-29 11:04:38 -06:00
Henrik RydgårdandClaude Opus 5.5 93f57a4f38 GPU: Delete copy operations on classes that own resources
These own GPU objects, memory or refcounts in their destructors (or assert
there that they were torn down), so a copy would double-free. Nothing copies
them today; this keeps it that way. The manager base classes cover every
backend's subclass.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 10:33:32 -06:00
Henrik RydgårdandClaude Opus 5.5 39049a67fd GLES: Free textures on device lost, and unsubmitted step data at exit
- The texture and fragment test caches dropped their GLRTexture objects on
  DeviceLost without queueing them for deletion, leaking them on every
  Android background/resume. The deleter already skips the GL calls when
  the context is gone.
- GLRenderManager::ThreadEnd cleared unsubmitted init and render steps
  without freeing the data they own. Run them through the dry run instead,
  which now also frees stereo matrices and shader code.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 10:33:32 -06:00
Henrik RydgårdandClaude Opus 5.5 b72927bbeb Texture replacement: Plug leaks on error paths
- Release the file reference when loading a level fails or finds nothing,
  since only a loaded level takes ownership of it.
- Free the PNG image when the size changed since the header was read.
- Delete the VFS when a pack without an ini has no hash-named textures.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 10:33:32 -06:00
Henrik RydgårdandClaude Opus 5.5 e108e41675 GPU: Fix assorted leaks, null derefs and small rendering bugs
- Put the anisotropy level in the sampler key, so changing it applies on
  Vulkan and D3D11.
- Release CLUT textures at shutdown on GLES and D3D11.
- Fix the depth readback viewport, which squeezed the image whenever the
  read rectangle was smaller than the fbo.
- Test the computed depth, not the unset result, in the equal-depth clear
  check.
- Don't read back a CLUT from a framebuffer without an fbo.
- Tolerate null entries when releasing post-shader objects and CLUT
  textures after a failed creation.
- ImGe: Don't crash on a framebuffer without an fbo, or on GetVFB under the
  software renderer.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-29 10:33:32 -06:00