DrawSpanVector now covers everything but logic ops and the signed blend factors. Stencil tests pick
the SFail, ZFail or ZPass op per lane, and lanes that only get a new stencil keep their old color.
Pixels are read and written in the framebuffer's own format, converting the whole span at once, and
a span with all four pixels drawn is stored in one go.
Only drawn pixels are written: spans are aligned in screen coordinates, so with a draw offset one can
reach into a tile another thread is drawing.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With the software renderer, which now stores depth as the GE does, a
16-bit read or write at VRAM's 0x04200000 or 0x04600000 mirror goes to
where the GE's 16-bit or 32-bit color layout puts that depth pixel
(ppsspp-re geprobe exp88: the mirrors are the layout's exact inverse).
Games access depth there with nothing else, so other widths stay plain.
The accessors check the address, then whether the GPU core is the
software renderer (CoreParameter); the hardware renderers keep depth plain
and handle the layout their own way. The renderer keeps the layouts up to
date with the EDRAM address translation. With it, the JITs send 16-bit
loads and stores to the interpreter, and the IR passes don't change a
load's width to or from 16 bits.
The pspautotests that read depth through the mirrors now do so 16 bits
at a time, re-recorded on hardware unchanged.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The software renderer kept depth linear in VRAM, where the GE stores it
in the layout GPU/Common/DepthSwizzle.h describes, from the EDRAM address
translation and the color format. So a texture or anything else sharing
VRAM with a depth buffer saw depth land in the wrong places (the player's
shadow in Silent Hill: Origins, #22415). Now every depth access goes
through the layout: the generic pixel functions, the 2x2 depth test, the
depth clear in 16-pixel runs, and the x86 pixel JIT, whose IDs carry the
translation so the layout's constants are compiled in. It changes with
the color format and sceGeEdramSetAddrTranslation, after a flush.
Reading VRAM through its 0x04200000 and 0x04600000 mirrors undoes the
layout, as the GE does: texturing from them (drawn from a linear copy
made after a flush), and block transfers from or to them (Hayate no
Gotoku restores its depth buffer through 0x04600000, #17878). Saved and
debugger depth buffers read through the layout, so they're linear.
Socom's lens flare dump now matches a PSP replay where it changes. About
2-3% more cycles in God of War, Tekken 6, Wipeout and Burnout.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Returning to the CPU flushed all queued drawing, also when a list only reached its stall address.
Wipeout Pure builds its lists as it goes and stalls about a hundred times a frame, so the main thread
spent a third of its time finishing the drawing at those flushes. A stalled list isn't done, so now
only a finished one flushes there, which makes Wipeout Pure 15% faster.
What relied on that flush now flushes itself: memory copies, sets, readbacks and uploads that overlap
the queued drawing, and save states, before memory is saved or loaded (FlushPendingDrawing). Syncs and
the display already did. Queued drawing still reads textures from PSP memory when it runs, so a game
that rewrites a texture between stalls without syncing would see the new one; on hardware the GE has
usually drawn with the old one by then.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A texture that fits in the GE's 8 KB texture cache keeps what was first
read until TEXFLUSH, across primitives and draws, so a later self-textured
draw doesn't see an earlier one's writes (gpu/probe exp174: three passes
over a 16x16 4444 buffer differ in 177 pixels with and without a flush
between them, both now exact). FF Type-0's (NPJH50443) blur; two of its
PSP replays become exact.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The hack skips the game's stretch blit, so the display framebuffer stays
black and savestate thumbnails and screenshots came out empty. Do the
stretch from the source image when reading back the display framebuffer.
AGENTS.md: Commit finished work without asking, push only when asked
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The values read back when saving a context or getting matrix data are set
differently than the actual values used for rendering.
This implements the wrapping and bleeding between matrices within softgpu,
but leaves hardware rendering to only use the rendering registers for
speed.
When we flush we mark all pending writes zero, but we rely on this being
set to detect self-render.
TRANSFORM_ALL was wrong as well, sometimes clearing BINNER_RANGE.
When games draw and display with a frame lag, it becomes important that we
indicate really dirty for the correct buffer. Since some triple buffer,
this attempts to track at the buffer level using 1024 byte granularity.