Commit Graph
91 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 16a5046124 SoftGPU: Read bilinear CLUT and 8888 texels in vector lanes
The four-pixel bilinear sampler read its sixteen texels one at a time,
each with its CLUT lookup and index transform, and loaded them as
vectors afterwards. For CLUT4 and CLUT8 with a 32-bit palette and no
index shift (by far the most common), and for 8888, the texels are now
gathered in lanes: the index bytes, the nibble, the mask and start, then
the palette entries. CrossSIMD gets Vec4S32::Gather and GatherU8 for it,
one load per lane. LocoRoco executes 5.5% fewer instructions, Burnout 3%.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 15:01:49 +02:00
Henrik RydgårdandClaude Opus 5.5 ce1f8d0a9e SoftGPU: Inline TransformClutIndex
The bilinear quad sampler called it for every CLUT texel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 15:01:49 +02:00
Henrik RydgårdandClaude Opus 5.5 f02936575d SoftGPU: Multiply small lane values with 16-bit multiplies
SSE2 has no 32-bit lane multiply, so Vec4S32::Mul is emulated with two
pmuludq and shuffles, and the bilinear sampler spent a tenth of its time
there. The texel row offsets, the texture functions, fog and blending
only multiply values that fit 16 bits, which Mul16 does in one pmaddwd.
The bilinear lerp of two channels packed as 16-bit halves uses the new
MulHalves (pmullw), which multiplies both at once.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:44:48 +02:00
Henrik RydgårdandClaude Opus 5.5 a89fdb2c9a SoftGPU: Remove the pixel and sampler JITs
The C++ paths draw and sample four pixels at a time in vector lanes,
while a JIT function only does one, and with a JIT function in use the
span and quad paths were skipped. On x86 the JITs had become slower:
Wipeout took 13% more wall time and 25% more CPU with them, God of War
3% more. They were also a second implementation of every GE rule, and
ARM never had them.

The SoftwareRendererJit setting goes with them. RasterizerRegCache.h
keeps only the types the pixel and sampler functions take, as
RasterizerTypes.h.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:44:48 +02:00
Henrik RydgårdandClaude Opus 5.5 9ce774d9f9 SoftGPU: Let the quad sampler skip the level check when all is level 0
Staged spans without mip levels pass no level arrays, and the sampler goes
straight to its one level path. 4% fewer instructions in God of War.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 11:39:29 +02:00
Henrik RydgårdandClaude Opus 5.5 cf3848d073 SoftGPU: Lerp two channels per lane in the four-pixel bilinear sampler
The texels come out corner by corner, so no transpose, and R with B, G with
A, share 32-bit lanes as 16-bit halves: no lerp of 8-bit values needs more
than 16 bits, and masking after each shift truncates both halves as before.
2.5% fewer instructions in God of War.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 11:39:29 +02:00
Henrik RydgårdandClaude Opus 5.5 2cca146b7e SoftGPU: Filter the four-pixel bilinear samples a channel per vector
SampleLinearQuadT filtered each pixel's four texels as 16-bit channels in a 64-bit integer, then
transposed the results into a vector per channel for the texture function. Now the lerps run on a
channel of all four pixels at a time, producing that layout directly. God of War about 6% faster.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 11:39:28 +02:00
Henrik RydgårdandClaude Opus 5.5 a0c57e190f SoftGPU: Pass a span's colors a channel at a time
The span pixel function and the four-pixel bilinear sampler work in vector lanes, a channel per
vector, but took and returned the colors a pixel at a time, so every span was transposed twice on the
way. Now they take a channel at a time with a stride. The staged rows keep each chunk's colors that
way from the start (their stage walks a channel at a time anyway), and DrawRectangle builds them so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 10:34:39 +02:00
Henrik RydgårdandClaude Opus 5.5 68c9593fb6 SoftGPU: Apply the texture function to a span's four pixels in lanes
The four-pixel sampler now runs the texture function (modulate, decal,
blend, replace and add, with color doubling) on all four pixels at once,
one vector per channel, instead of GetTextureFunctionOutput per pixel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 10:34:39 +02:00
Henrik RydgårdandClaude Opus 5.5 d24d420057 SoftGPU: Sample a span's four pixels in vector lanes
When the four pixels share their mip level (always, for a triangle's
span), their texel coordinates, clamping or wrapping and texel offsets
are computed in vector lanes, and only the texel and palette reads go
one by one. Adds Vec4S32::Min.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 10:34:39 +02:00
Henrik RydgårdandClaude Opus 5.5 b8690d543e SoftGPU: Draw triangles and sprites in spans of four pixels in a row
The GE walks rows in spans of four pixels and picks the mip level's q
once per span, so the rasterizer now does the same instead of 2x2
quads: triangle spans are aligned like the GE's, so the four pixels
share their level, which is computed once. Auto LOD without planes takes
its vertical derivative from the row below. Sprites, which always have
planes, lose their unused incremental UVs.

Without a sampler JIT, the four bilinear samples of a span are now taken
in one call. Same results on 263 frame dumps and 8 games.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 10:34:39 +02:00
Henrik RydgårdandClaude Opus 5.5 8c7d600b74 SoftGPU: Fewer address and plane computations per textured pixel
A texel's byte offset is a sum of one for its row and one for its column,
swizzled or not, so the four texels of a bilinear sample now take two of
each, and the CLUT offset of a mip level is found once per sample. The
UV planes at a quad's four pixels are one sum plus steps, as for depth.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 10:34:39 +02:00
Henrik RydgårdandClaude Opus 5.5 1e591405b6 SoftGPU: Specialize the bilinear sampler per texture format without a JIT
Where there's no sampler JIT (everything but x86-64), bilinear sampling
switched on the texture format per pixel, on the CLUT format per texel,
and went through swizzle checks and vector-to-stack round trips. Now a
template instance per texture format, swizzling and CLUT format is
picked with the state, and the filter does all four channels at once in
16-bit lanes of a uint64_t. Same results (checked on 263 frame dumps).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 10:34:39 +02:00
Henrik RydgårdandClaude Opus 5.5 8f699056f9 SoftGPU: Don't flush for JIT compiles where there's no JIT
The pixel and sampler JITs only exist on x86-64, but elsewhere a cache
miss still flushed the binner before the compile that did nothing, and
the cache never filled. So on ARM every switch to a new pixel or sampler
state was a full flush: hundreds per frame.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 14:55:17 -06:00
Henrik RydgårdandClaude Opus 5.5 251d42ab2e SoftGPU: Leave textures with an invalid level address to the generic samplers
The x86 sampler JIT returned zero for a whole sample when a texture level
pointer was null, and for a mipmapped texture it checked the next level
too, even when it isn't blended in. Tactics Ogre draws its font from a
mipmapped texture whose next level has an invalid address, at level 0,
so all its text was missing on x86-64. The generic samplers read a null
level's texels as zero only where they use that level, and still apply
the texture function. Now samplers for such textures aren't compiled,
and the JIT's null checks are gone. Test: gpu/textures/mipinvalid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 13:05:46 -06:00
Henrik RydgårdandClaude Opus 5.5 c8819d5087 SoftGPU: Make arm64 and x86 render the GE probes identically
Found by the probe regression run (ppsspp-re geprobe/regress.py), which
gave different counts on the two:

- Vec4<int> >> was a logical shift on SSE, arithmetic elsewhere. A negative
  spot factor lit pixels white on x86 (gpu/probe exp100).
- Vec4<float>::ToRGBA rounded on SSE and truncated on NEON and the generic
  path. Spline colors were one lower on ARM (exp48-51, the PSP rounds).
- Texel coordinates past the int range: the C++ sampler now gives INT_MIN
  like the x86 JIT's conversion, as the PSP does with a repeating texture (exp5).
- The viewer direction is normalized with the GE's normalization instead of
  the SIMD float one (exp2, exp3).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:09:43 -06:00
Henrik RydgårdandClaude Opus 5.5 347f3668ac SoftGPU: Separate mipmap CLUTs for CLUT8 too
With the separate-CLUT bit, mip level n puts n above the index bits, wrapped
to the CLUT: CLUT4 adds n * 16 as before, CLUT8 with a 16-bit palette adds
(n & 1) * 256, and a 32-bit palette's 256 entries wrap it back to 0
(gpu/probe exp90). Also in the x86 sampler JIT.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:09:42 -06:00
Henrik RydgårdandClaude Opus 5.5 15467e24c4 SoftGPU: Sprite UVs and texel addressing like the GE
Sprites interpolate UVs with the same fixed point planes as triangles, and
texture coordinates become texels at 1/16 texel, truncated toward zero, also
in the sampler JIT. Bit exact on gpu/probe exp57 (through mode and transform
mode sprites, nearest and bilinear).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:09:42 -06:00
Henrik RydgårdandClaude Opus 5.5 7d3131abc2 SoftGPU: Bilinear filter horizontally first, truncating, like the GE
The GE lerps the top and bottom texel pairs, truncates each to 8 bits, then lerps
those vertically. Bit exact on gpu/probe exp52 (also in ppsspp-re tools/geprobe).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:09:42 -06:00
Henrik RydgårdandClaude Opus 5.5 a9eacff1e1 SoftGPU: Keep the compile flushes on builds without the JIT
Skipping them is only a speed-up, but it changes how states get batched and
optimized, which changes the rendered output (NBA 2K13 and Virtua Tennis
frame dumps). Keep the old behaviour until that's understood.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 09:35:17 -06:00
Henrik RydgårdandClaude Opus 5.5 a9c782bfcf SoftGPU: Recompute the raster state after a JIT cache clear
A code space clear frees the functions the current state points to, but
the state was kept as long as the GE registers didn't change. Track the
clear generations and recompute, also when a compile during the state
computation clears the caches.

Also skip the binner flush for compiles on builds without the software
JIT, where Compile() does nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 09:35:17 -06:00
Herman Semenoff 400d136f51 GPU: modernize use C++17 constexpr for precalculate compilation 2026-05-19 21:57:45 +03:00
Henrik Rydgård 5326d87f9c Rename CrossSIMD to SIMDHeader, but also keep CrossSIMD.h (will have a future use) 2024-12-19 15:15:43 +01:00
Henrik Rydgård 3e198c53b2 More include cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård e01ca5b057 Logging API change (refactor) (#19324)
* Rename LogType to Log

* Explicitly use the Log:: enum when logging. Allows for autocomplete when editing.

* Mac/ARM64 buildfix

* Do the same with the hle result log macros

* Rename the log names to mixed case while at it.

* iOS buildfix

* Qt buildfix attempt, ARM32 buildfix
2024-07-14 14:42:59 +02:00
Henrik Rydgård 10f93875c6 Fix the semantics of DenseHashMap to be consistent even when inserting nulls 2023-09-11 12:07:18 +02:00
fp64 cd9f01c4df Remove SSE4 path from Vec4<int>::operator* 2023-06-30 22:07:26 -04:00
fp64 f133739cd0 Replace some signed divison in SoftGPU
This also adds a few bitwise operations to Vec4<int> and further
SIMDifies it.
Also, fixes unrelated warning.
2023-06-29 16:43:21 -04:00
fp64 159faaa2ec softgpu: Optimize (bi-)linear texture filtering
Seeing as SampleLinearLevel is near the top in the profiler,
optimize actual bilinear filtering using SSE2. Solid win in the
synthetic benchmark (https://godbolt.org/z/fqh3xvbGx, also doubles
as correctness check), no visible difference in actual PPSSPP.
Note: profiler suggests that hot part of SampleLinearLevel is
elsewhere.
2023-06-21 20:02:34 +03:00
Герман Семенов 122b63b9a8 GPU: using if constexpr C++17 optimization 2023-04-02 16:36:37 +02:00
Unknown W. Brackets cd3fc26190 samplerjit: Prevent thread local stale cache read.
If the generation count happens to match, would still get a stale pointer
and crash.  Let's just make the generation count static so it always
increases.
2023-02-22 21:15:03 -08:00
Unknown W. Brackets 62fe03dcb4 softgpu: Use NEON for texture blending. 2023-01-07 19:06:35 -08:00
Unknown W. Brackets 49f6c461ad Reporting: Fix some header includes.
Particularly in Common, avoid including Core/Reporting.h.
2022-12-27 14:58:20 -08:00
Unknown W. Brackets d9522a7ac5 softgpu: Avoid clear hazard for last cached funcs. 2022-12-06 21:23:56 -08:00
Unknown W. Brackets eda3ce556e softgpu: Avoid atomic structs.
Apparently we don't link libatomic and rather than fighting that, I'll
just use thread local values.
2022-12-06 20:35:07 -08:00
Unknown W. Brackets 400f6abf9a softgpu: Optimize lookup of last jit func.
This is common (for example, maybe a pixel state is updated but sampler is
not), and reduces time spent in ComputeRasterizerState() quite a bit in
Darkstalkers, where jits are available (i.e. Intel currently.)
2022-12-06 19:16:19 -08:00
Unknown W. Brackets 87fb9eef37 softgpu: Remove std::function usage.
Wanted to avoid coupling these, but don't like the std::function
construct/destructs showing in profiles...
2022-12-06 19:15:57 -08:00
Unknown W. Brackets 38eb0a7a82 softgpu: Check for queued compile.
Rarely, we could have queued compiling the same one, which would crash on
a double insert.
2022-12-03 12:15:58 -08:00
Unknown W. Brackets 778a0487cb softjit: Switch to DenseHashMap. 2022-12-02 20:59:13 -08:00
Unknown W. Brackets 4d06400548 softgpu: Fix compile hazard while running.
This prevents any clearing of cache while other threads may be using
previously cached funcs, and avoids wx exclusive hazards.
2022-11-20 12:04:02 -08:00
Unknown W. Brackets ce51942508 softgpu: Correct WX-exclusive platform hazards.
Should mainly affect BSD at this point.
2022-11-20 10:55:35 -08:00
Unknown W. Brackets 79b1d1d35f softgpu: Better approximate slope mip level mode (#16276)
* samplerjit: Remove unused x/y parameters.

Still need to tune the accuracy of filtering, but those were not the
right way.

* softgpu: Better approximate slope mip level mode.

This isn't exactly right, but it's closer.

* softgpu: Calculate auto from largest difference.

Direction shouldn't matter.
2022-10-23 10:15:43 +02:00
Unknown W. Brackets 167213c746 softgpu: Cache texture bufws at 16 bit.
Reducing the size of state a bit.
2022-09-12 21:57:00 -07:00
Unknown W. Brackets 90e009edb9 softgpu: Clamp/wrap textures at 512 pixels.
A texture larger than 512 is "valid", but simply wraps/clamps at 512.
Importantly, the texture coords are still calculated at the specified
size, which can be up to 32768.
2022-09-10 20:23:09 -07:00
Unknown W. Brackets a88c9a0680 softgpu: Remove incorrect offsetting for X/Y. 2022-02-20 09:13:20 -08:00
Unknown W. Brackets 2479d52202 Global: Reduce includes of common headers.
In many places, string, map, or Common.h were included but not needed.
2022-01-30 16:35:33 -08:00
Unknown W. Brackets d200ef40de samplerjit: Compile sampler funcs together.
We can't have the cache clear between nearest/linear, because then we'll
call a bunch of int3's.
2022-01-29 20:28:20 -08:00
Unknown W. Brackets 99d6d569f0 samplerjit: Reduce transfers in nearest texel calc.
This benefits a few games, mostly where there's lots of UI or similar.
2022-01-24 21:28:04 -08:00
Unknown W. Brackets c1e657ed47 samplerjit: Better vectorize UV linear calc.
Gives about 1-2% when mips are used.
2022-01-24 20:42:07 -08:00
Unknown W. Brackets c2985bca31 softjit: Centralize some common funcs from sampler.
No need to duplicate this code.
2022-01-19 00:03:59 -08:00