Commit Graph
10295 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 0edfd93a3a Depth raster: Stop a row once it has left the triangle
The triangle is convex, so once a row has been entered and left, the
rest of it is outside. This cut cycles by 5% in Wipeout Pure, where depth
raster is on for the lens flares.

The test checks the covered pixels against a per-pixel edge test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 10:14:54 +02:00
Henrik RydgårdandClaude Opus 5.5 83639a73e8 GPU: Cull-test draws four vertices at a time
TestBoundingBoxFast transformed and tested one vertex per iteration,
with a scalar divide and a min/max chain each vertex had to wait on.
It now transposes four vertices into lanes and does it all as vectors,
with the same operations in the same order, so the results don't change.
It was 16.6% of the emulator thread in Wipeout Pure (with depth raster
off) and 5% in GTA: Vice City Stories.

Per vertex, it's 1.8x faster on an M1, 2x on x86-64, 1.7x on a Galaxy S8+
and 10% faster in 32-bit mode there.

The test compares it with the old version on random draws in every
position and index format.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 10:14:51 +02:00
Henrik RydgårdandClaude Opus 5.5 f3c69fc5d1 Remove FakeJit and the pre-IR JitBlockCache
FakeJit was the native JIT for architectures without one, but the config
already forces those onto the IR interpreter, so CreateNativeJit() now
returns that instead. The vertex decoder fallback no longer needs
FakeEmitter.

JitBlockCache was the block cache of the pre-IR JITs. Its header keeps
the debug interface types the IR block caches use. Also removes the
JitInterface link hooks only it called, and the JitState fields tied to
it. This fixes a null dereference in the ImDebugger memory section,
which read GetBlockCache(), always null with the IR JITs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 02:24:25 +02:00
Henrik Rydgård 831d8f4654 Merge pull request #22569 from hrydgard/readback-shadow
Add a ReadbackShadow compat flag, for games that read many pieces of a buffer
2026-10-15 00:10:06 +02:00
Henrik RydgårdandClaude Opus 5.5 fe61574a02 D3D11: Include CommonWindows.h before the Windows SDK headers
DrawEngineD3D11.cpp started with <wrl/client.h>, which brought in windows.h
without NOMINMAX, so its min macro broke the std::min in an inline function
of FramebufferManagerCommon.h. D3D11Util and ShaderManagerD3D11 had the same
order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 23:36:45 +02:00
Henrik RydgårdandClaude Opus 5.5 5d0873d95d Depth raster: Clip to the drawing region as well as the scissor
Resistance: Retribution sets its scissor to end at 480,272, one past its
drawing region. The CPU depth rasterizer (SoftwareRasterDepth) only
clipped to the scissor, so it wrote row 272 of the depth buffer, which is
where the game keeps its logo textures. The startup logos got a garbage
strip on hardware backends and failed to fade out.

SoftGPU already clips to the minimum of the two.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 23:10:54 +02:00
Henrik RydgårdandClaude Opus 5.5 20530d35c0 Add a ReadbackShadow compat flag, for games that read many pieces of a buffer
Since the sequential copies heuristic went (50696c5b1f), every partial readback
waits for the GPU. Motorstorm reads parts of the screen about 18 times a frame,
and ran about 75% slower than 1.20.4: 5403 blocking readbacks in 10 emulated
seconds, against 156.

With the flag, the first partial color readback of a buffer reads all of it into
a copy outside PSP memory, and the pieces until the next render to the buffer
are copied from there. Unlike the old heuristic, only what the game asked for is
written to PSP memory. Motorstorm is back to 153 blocking readbacks and 1.20.4's
speed, with identical output. Grand Knights History, which the heuristic was
added for, gets the flag too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:56:32 +02:00
Henrik RydgårdandClaude Opus 5.5 d0266580d9 CMake: List the headers that were missing
Each next to its .cpp, or with its neighbours in the unconditional list for
its directory. They're only for IDEs, so this changes nothing in the build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:05:52 +02:00
Henrik Rydgård 88f4c12437 Merge pull request #22553 from hrydgard/gpu-fallback-fixes
GLES and fallback rendering fixes from running the framedumps on Android
2026-10-14 09:20:38 +02:00
Henrik RydgårdandClaude Opus 5.5 e48086484c Blend in the shader where stencil to alpha needs dual source blending we lack
A draw that blends with the source alpha while setting the stencil (the
alpha on the PSP) needs dual source blending to write both. Without it the
alpha came out wrong, and later draws that blend with the destination alpha
differed: WipEout Pure, Juiced 2 and 16131 UCES00001 on a Mali-G71 and a
PowerVR GE8320. With framebuffer fetch, blend those in the shader instead,
which matches the Mac's Vulkan render now. Without fetch it would take a
framebuffer copy per draw, too slow for something this common.

A draw that writes no color can't need the source alpha, so it writes the
stencil as alpha directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:33 +02:00
Henrik RydgårdandClaude Opus 5.5 6b989f9d12 Don't use BlueToAlpha with framebuffer fetch
With fetch, the shader applies the colour masks and logic ops to the real
bits, and OutRun 2006's water mask comes out like the software renderer's.
BlueToAlpha put the first step in alpha while the masked logic-op steps after
it worked on blue, so on the Adreno 840's OpenGL the water was off by twice as
much as on Vulkan. Now it matches or beats Vulkan there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:33 +02:00
Henrik RydgårdandClaude Opus 5.5 b9780bc132 Keep the stencil when resizing a framebuffer
ResizeFramebufFBO copied color and depth into the new FBO but left its
stencil cleared. Need for Speed Shift grows its framebuffer from 480 to 512
wide just before stencil testing, and the frame came out far too dark on
Android (112k px off the PSP on an Adreno 840, now 4k). MoltenVK happened
to keep it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:33 +02:00
Henrik RydgårdandClaude Opus 5.5 3e4458c7b7 Rebind the render target after writing stencil to another framebuffer
PerformWriteStencilFromMemory bound the framebuffer it wrote the stencil to
and, unless it blitted, left it bound. When that wasn't the current render
target, the following draws landed in it. Draws that copy the target for
shader blending rebind it themselves, which hid this; with framebuffer fetch
they don't, and OutRun 2006's masked water draws went into the old 5551
buffer at the address instead of the new 565 one.

Over the framedumps set on Vulkan, 9 dumps get closer to the PSP (OutRun
ULUS10064_0002 12295 -> 483 px, F1 2009, God of War) and one a little further
(16131 ULUS10193, a slight brightness shift).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:32 +02:00
Henrik RydgårdandClaude Opus 5.5 b25344ab7b Discard against one-sided depth ranges in the fragment fallback
Without clip distances, the fragment shader's min/max Z discard only came on
when both minz and maxz were set, while the clip planes take each side on
its own. Pursuit Force's sky has minz 0 and maxz 300 and lies past 300, so
the PSP drops it (its replays of 11399 UCES00019 and 11216 UCUS98703 show
that), but GPUs without clip distances drew it over the scene: 13.9k px off
the PSP on a Mali-G71, now 8 as with clip distances. The discard can now
come with the fragment depth clamp, for the side that's at the limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:32 +02:00
Henrik RydgårdandClaude Opus 5.5 026bbf56d6 GLES: Declare u_minZmaxZ highp in both shaders
The fragment shader's min/max Z discard declared it with the default
precision, the vertex shader with highp, and PowerVR refuses to link such a
program, so every draw that needed the discard was dropped. On a PowerVR
GE8320 that was Street Riders, Valkyria Chronicles, Flatout and Frontier
Gate, and with the discard taking one-sided depth ranges too (next commit),
most of Pursuit Force.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:32 +02:00
Henrik RydgårdandClaude Opus 5.5 5fb61b4e40 GLES: Use highp for the texcoord and the math in CLUT8 depal
Picking a byte out of a 16-bit framebuffer needs more than the defaults. The
texcoord reached the shader as a mediump varying, which Adreno keeps in fp16:
its byte coordinate (u times up to 2048) then picks the wrong byte for every
other one past 512, and SOCOM Tactical Strike's night vision came out striped
in the right half. On a PowerVR GE8320 the default lowp in the rest of the
shader made SOCOM's night vision and full screen effect far too bright (53k
and 17k px off the Mac's Vulkan render, now 0). Vulkan already uses highp.

Where the fragment shader has full precision, the vertex shader now writes the
texcoord in highp, and CLUT8 depal reads it that way and computes in highp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:32 +02:00
Henrik RydgårdandClaude Opus 5.5 9bef51177b GLES: Don't skip uniform updates while a program's locations aren't known
UpdateUniforms checked some locations against -1 before queueing the update,
but the GL thread fills them in when it links the program, which can be
later. On drivers that link slowly the check saw -1, the update was dropped
along with its dirty flag, and the uniform stayed unset. On a PowerVR GE8320
and a Mali-G71 the texture clamp values never arrived, so Harvest Moon's and
11655's composites sampled one point of the framebuffer (122k and 76k px off
the Mac's Vulkan render, now 0). The GL thread already skips -1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:32 +02:00
Henrik RydgårdandClaude Opus 5.5 7080085571 GLES: Apply the texture LOD bias in the shader
GL_TEXTURE_LOD_BIAS is desktop GL only, and the queue runner skipped it on
GLES, but GLES still reported sampler LOD bias as supported, so the bias was
dropped and textures used the wrong mip levels: Super Monkey Ball Adventure's
intro came out blurred on the Adreno 840. Report it unsupported, so the shader
applies it (GPU_USE_SHADER_LOD_BIAS), and give the GL backend the uniform that
Vulkan has in its uniform block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:33:32 +02:00
Henrik Rydgård 9b07e78604 Merge remote-tracking branch 'origin/master' into cpu-equiv-1
# Conflicts:
#	pspautotests
2026-10-14 01:22:31 +02:00
Henrik RydgårdandClaude Opus 5.5 9237bade22 x86 vertex decoder JIT: Fix the paths for constants out of RIP range
PosFloat loaded its clamp constants into XMM4/XMM5 but clamped with XMM2/XMM3,
and the S8/S16 morphs overwrote the morph weight pointer with the constant's
address. These only run when the JIT cache lands more than 2GB from the
constants, which CPUEquivalence's allocations made happen on Linux CI
(SplineTessellation). Checked by forcing every RipAccessible() false, which
SplineTessellation and VertexJit now pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:11:59 +02:00
Henrik RydgårdandClaude Opus 5.5 d0567e2dfb GE: Nest CALLs only two deep, like the hardware
- Fixes #7395

The GE has two return address registers, and a CALL beyond them does
nothing: the list carries on after it. A signal CALL is done by the
firmware, which saves and clears them, so it starts the count over,
and the signal RET restores it. Shown on a PSP by the new
gpu/callstack/depth test.

Soul Calibur: Broken Destiny turns lighting on for its weapon trails
from a third-level CALL, so on hardware the trails stay unlit and take
their colors from the vertices. We ran that CALL and drew them white.

Plain CALLs now store a 0 base address in their stack entry, which a
signal CALL never does, so the depth can be counted without changing
the savestate layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 00:54:01 +02:00
Henrik RydgårdandClaude Opus 5.5 60100c4254 - Fixes #13676
Vulkan: Batch Jackass' tiled in-place color grade

Jackass: The Game color grades the framebuffer in 32x64 tiles, one channel
per pass, texturing from the framebuffer it renders to. Each of the 225
draws became a depal pass plus a pass drawing it back, 450 render passes
per frame. A new queue hack, enabled by the TiledDepalHack compat flag,
sorts these pairs into waves of non-overlapping tiles and runs each wave
as one depal pass and one draw pass, leaving 6.

Output is byte-identical to before on both dumps from the issue, at 1x
and 3x on desktop, and at 1x on both phones below.

Time saved per post-processed frame, from replaying the dumps from the
issue with headless --bench (each replay renders that frame once):

  Redmi 9A (PowerVR GE8320):  ~145ms at 1x, ~180ms at 2x
  Unisoc UMS9632 (Mali-G57):  ~55ms at 1x and 2x

Either is more than a whole 33ms frame, so on those GPUs this pass alone
ruled out 30fps.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 17:08:58 +02:00
Henrik Rydgård 4585f70500 Merge pull request #22545 from hrydgard/gpu-fallback-fixes
Fixes to GPU feature fallbacks
2026-10-13 16:46:34 +02:00
Henrik RydgårdandClaude Opus 5.5 85d751ebe1 Keep near plane clipping in the fragment depth clamp fallback
The fallback set the rasterizer's Z to a constant so nothing would clip, which
lost the clipping at the PSP's near plane too. Hardware depth clamp loses it
the same way, which the vertex shader can only make up for with a clip plane.

Give the rasterizer (z + w) / 65536 instead: 0 at the near plane, so it clips
there, and past w only beyond 65535 * w. And without clip distances, use the
fragment fallback instead of hardware depth clamp.

With --disable-gpu-features for all three on the Mac, the framedumps set now
differs from the full render by 15570 px instead of 184229 (WALL-E, Hokuto no
Ken, Frontier Gate, FF Zero). The full render doesn't change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:06:49 +02:00
Henrik Rydgård b4b4390c49 Merge pull request #22543 from hrydgard/android-headless-gpu
Android: Add setup for headless GPU rendering test
2026-10-13 15:02:11 +02:00
Henrik RydgårdandClaude Opus 5.5 2d61d58bbe Make the fragment depth clamp fallback match hardware depth clamp
For GPUs without depth clamp (old Mali), found by comparing with
--disable-gpu-features=depth-clamp on the Mac:

- Write Z / 65536 like the vertex shader, not / 65535.
- Pass the fragment shader Z after the vertex depth rounding, which hardware
  clamp sees too (Puyo Puyo Fever 2's ground at Z = 0).
- Also clamp draws whose Z only touches 0 or 65535.
- Draws that skip the bounds check (skinned, morphed) get the fragment clamp
  and min/max discard wherever the hardware versions would be on, since those
  don't depend on the check either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:44:34 +02:00
Henrik RydgårdandClaude Opus 5.5 7c118f2ee3 Headless: Add --hardware-transform and --disable-gpu-features
--disable-gpu-features=clip-distance,cull-distance,depth-clamp acts as if the
GPU lacked those, to test the fallbacks for old Mali on any machine. It
replaces the simulateOldMali constant. --hardware-transform=false runs every
draw through software transform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:44:34 +02:00
Henrik RydgårdandClaude Opus 5.5 3193031e7b Bounds-check PRIM draws of any size, not only up to 2500 vertices
Bigger draws skipped the check and kept whatever clip flags the previous draw
left. Checked, the ones that cross the clip volume in Z get software clipping
where the GPU needs it: on the Mac (no cull distances), Valkyria Chronicles II
and Street Riders get closer to the PSP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:44:34 +02:00
Henrik RydgårdandClaude Opus 5.5 9073aad504 Cull and clip check Bezier and spline patches like PRIM
Curves skipped the per-draw bounding box check and relied on the vertex
shader's near clip plane. On old Mali (no clip distances), that left the
geometry behind the PSP's near plane to the GPU: Test Drive's hills reached
over the sky.

A patch lies within the convex hull of its control points, so run the PRIM
check on those: a patch entirely outside is skipped, and only one with points
outside the clip volume in Z goes through software transform. Missing clip
distances are now also a reason to software-clip, for PRIM too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:44:34 +02:00
Henrik Rydgård 0af0d86470 Merge pull request #22542 from hrydgard/faster-build
Faster CMake builds: libc++ transitive includes, less glslang/SPIRV-Cross, include cleanup
2026-10-13 12:57:43 +02:00
Henrik RydgårdandClaude Opus 5.5 e602aa1548 Add includes that were only arriving transitively
VertexDecoderRiscV.cpp got <cfloat> through SmallDataConvert.h, and three
headers used malloc/free without <cstdlib>, which libc++ no longer brings in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:36:06 +02:00
Henrik Rydgård 3c25f21bae Merge pull request #22541 from hrydgard/libretro-fork-fixes
Various bugfixes from libretro's experimental fork
2026-10-13 12:26:27 +02:00
Henrik RydgårdandClaude Opus 5.5 a361dfc490 Drop unused Config.h and SmallDataConvert.h includes
Config.h is edited about 100 times a year and each edit recompiled 198
files; now 172. SmallDataConvert.h pulls in arm_neon.h and was included by
headers that don't use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:13:42 +02:00
Henrik RydgårdandClaude Opus 5.5 ec76a4d56e GE dump playback: Refuse sections over 1 GB
A zstd frame doesn't always declare its size, and a small one can expand to
gigabytes, so this is the limit that keeps a crafted dump from exhausting
memory. The largest section in the 1042-dump test set is 82 MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:05:35 +02:00
Henrik RydgårdandClaude Opus 5.5 9c2cf98b84 GE dump playback: Clamp the remaining writes, bound the loader's allocations
Follows up the command range validation:
- Don't require anything of the data commands' sizes or alignment. Version 2
  dumps have empty VERTICES and CLUT commands, and old recorders didn't align
  anything. Registers() drops a trailing partial word instead.
- Split register blocks bigger than the list buffer, which they overran.
- Clamp MEMCPYDATA and MEMSET to valid memory. Only their start was checked.
- Check the compressed sizes against the file, and the decompressed sizes
  against what the frame declares, before allocating. Some version 5 dumps
  leave the size out of the zstd frame; those are checked after decompressing.
- Don't let a large FRAMEBUF size wrap around in MarkNeededTargets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:01:29 +02:00
Acts1631 80b813f507 Validate GE replay commands before execution
Crafted ppdmp command ranges can extend past the decompressed push
buffer. Frame buffer playback can then copy adjacent host heap data
into emulated VRAM, exposing process memory through rendered output.

Validate each command's type, range, and minimum payload size before
constructing the replay executor.
2026-10-13 09:21:14 +02:00
LibretroAdmin 664f6ff5ad D3D11: work on a context that refuses ID3D11DeviceContext1
D3D11DrawContext takes its base context from the deviceContext
argument, and the blend state is bound through the base context, which
accepts an ID3D11BlendState1 as is. ID3D11DeviceContext1 is optional:
RetroArch's threaded video hands v1 cores a deferred-context proxy that
answers ID3D11DeviceContext only, and the core now starts on it.
2026-10-13 02:23:48 +02:00
Henrik RydgårdandClaude Opus 5.5 531a75f045 Add AccurateSplines compat flag, enable for Coded Arms
- Fixes #21391

Makes the hardware backends tessellate Bezier patches and splines with the
GE-exact evaluation the software renderer uses. Fixes the z-fighting glow
under the floor grates in Coded Arms.

AGENTS.md: Put "- Fixes #N" first in commit messages

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 14:04:38 +02:00
Henrik RydgårdandClaude Opus 5.5 4e12f25c70 Readback: Don't write a stale buffer on failure, and clamp the height
Depth readback and the GLES stencil readback converted whatever their
buffer last held into PSP memory when the copy failed. The generic stencil
readback asked for depth, which asserts on Vulkan and D3D11. And
ReadFramebufferToMemory clamped the width to the buffer but not the height,
which a block transfer can exceed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik RydgårdandClaude Opus 5.5 ae68a7e73f Coded Arms: Contagion: Read back the stencil the crosshair checks
The crosshair turns red, and lock-on works, when stencil bit 3 is set at
the centre of the frame, which the game tests by reading the pixel from
VRAM with the CPU (#17936). Hook that and read back the stencil of that
row into the alpha bytes in RAM. The alpha the hardware backends keep
doesn't follow stencil everywhere, so reading color isn't enough.

Adds PerformReadbackStencilToMemory for this (8888 only for now).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:15:56 +02:00
Henrik RydgårdandClaude Opus 5.5 275fc53061 GE dump recording: Record one more frame when the display shows the previous one
Silent Hill: Origins shows each frame one late: the first draw of a frame
copies the previous one into its 565 display buffer. A dump of one frame
then displays a copy of the frame before it, taken from memory, and none
of what it draws. When the display buffer's last write came before most of
the frame's drawing, the recorder now records the next frame too, whose
copy puts the recorded frame on the display.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:04:25 +02:00
Henrik RydgårdandClaude Opus 5.5 c4da98e889 GE dump recording: Read back framebuffers drawn before the recording
With a hardware renderer, a framebuffer only exists on the GPU, so a dump
copied whatever stale data RAM held when a game sampled a buffer it drew
in an earlier frame. Silent Hill: Origins shows the previous frame by
copying it into its 565 display buffer at the start of the next one, so
its dumps displayed old scratch data. The recorder now reads such buffers
back once before copying them out (not ones drawn during the recording,
which replay draws again).

It asks for the copy without creating a framebuffer: with
BlockTransferAllowCreateFB (which Silent Hill has) a plain readback makes
a new framebuffer at the destination and never writes RAM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:04:25 +02:00
Henrik Rydgård 0ee8b5adf8 Merge pull request #22509 from hrydgard/buzz-video
Upload video frames written partway into a framebuffer. Fixes Buzz Master Quiz videos
2026-10-11 23:21:39 +02:00
Henrik RydgårdandClaude Opus 5.5 75865683bb Upload video frames written partway into a framebuffer
Buzz! Master Quiz converts its question videos (sceMpegBaseCscAvcRange)
straight into the middle of the frame it has drawn, at 84,69. The
framebuffer upload only matched writes starting at a framebuffer's
address, so the hardware backends never showed the video. Pass the
written width along and draw just that rectangle into the framebuffer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 22:50:57 +02:00
Henrik RydgårdandClaude Opus 5.5 5704b972e7 iOS: Remove OpenGL support from the app
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>
2026-10-11 16:13:28 +02:00
Henrik RydgårdandClaude Opus 5.5 2aaf13d8f8 Upload only the copied part of a row in a memcpy to a framebuffer
A memcpy of part of one row into a framebuffer was drawn at the buffer's full
width, pulling in whatever followed the source. Everybody's Golf copies its
loading screen spinner back to the screen 64 pixels at a time, so its sprite's
next rows were drawn alongside, as a row of discs across the bottom.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 15:10:34 +02:00
Henrik RydgårdandClaude Opus 5.5 50696c5b1f Remove the "game uses sequential copies" readback heuristic
After more than three partial readbacks of one buffer in a frame,
ReadFramebufferToMemory read the whole buffer instead for the rest of the
session, writing rows the game never asked for.

Everybody's Golf 2 reads back four portraits' color and depth per frame, which
turned it on. The whole 480x273 depth buffer then got written to VRAM, and its
last row is where the game keeps its texture heap. A texture header was
overwritten: the portrait showed the scene behind it, and the next time the
portraits were built the game crashed writing through a null pointer.

It was added for speed in Grand Knights History (c42d04829f), which copies many
slivers of a framebuffer, so that game may now do more readbacks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 14:50:19 +02:00
Henrik RydgårdandClaude Opus 5.5 648766dad4 Everybody's Golf 2: Read back color and depth for the player portraits
The game builds each 64x64 portrait by memcpying a rect of the framebuffer one
partial row at a time, then setting each texel's alpha bit from the depth
buffer, which it reads directly from VRAM. Neither got read back: the row
copies don't line up with a framebuffer, and depth is never downloaded.

Hook the copy function to read back both, whole rows at a time. That needed two
fixes to requested depth copies: they were dropped when the depth buffer lies
above all color buffers, and only an exact full-buffer size matched.

The portrait texture now matches the software renderer, though it still
doesn't show up on screen with Vulkan.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 13:25:10 +02:00
Henrik Rydgård 6779143827 Merge pull request #22486 from hrydgard/softgpu-x86-opt
SoftGPU: Do an optimization pass on x86-64 too
2026-10-10 15:48:04 +02:00
Henrik Rydgård e312af9b04 Merge pull request #22483 from hrydgard/reinterpret-subpixel
Further improve the Tantalus games
2026-10-10 15:27:21 +02:00