Commit Graph
456 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 c9ddd26cd2 SoftGPU: Walk the staged rows' planes four pixels at a time
When a plane's values at both ends of the chunk fit in 32 bits, so do all between, and 32-bit
wrapping arithmetic gets them exactly: then in vector lanes, with the clamp.

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 6223f1926b SoftGPU: Compute the staged rows' coverage in vector lanes
The coverage stage was a scalar loop per pixel with the snap edge as a branch. A chunk starts a span,
so relative to it the bounds fit in 32 bits and the snap edge's pixel is a fixed offset per lane.

Also read the depth buffer for the early depth test with one load where SSE isn't used.

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 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 2ec3212d92 SoftGPU: Specialize the staged rows' texturing for the triangle
The last stage of a staged row (texturing, the secondary color and the
pixels) is now a template on what's fixed per triangle: textured or not,
the UV planes fitting 32 bits, the mip level's q and through mode.

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 6edaf432ad SoftGPU: Check a triangle's UV planes once instead of every span
When a triangle's q, s and t plane sums fit 32 bits wherever its spans
are walked, and the planes' exponents keep the GE's UV arithmetic in the
normal float range (GEUVSpanSafe), a span's plane values are one vector
add each and GEUVSpanCore runs without its range checks. Tested bit for
bit against the scalar code under those conditions.

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 1d60f375d7 SoftGPU: Draw triangle rows in stages
Where the pixel function is the C++ one (and textures have planes), a
row is now drawn in stages over up to 64 pixels at a time: coverage,
depth and the early depth test, then the colors, secondary colors and fog
of all its pixels, then texturing and the pixels span by span. Each stage
keeps little state, where the single span loop spilled most of its.

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 0d6bb8b198 SoftGPU: Draw the pixels of a span together, in vector lanes
Where the pixel function is the C++ one, triangles and sprites now hand
it a whole span of four pixels. Unless the state has a stencil or color
test, a logic op or a signed blend factor, the span goes through one pixel
per vector lane: clamping, alpha test, fog, depth range, test and write,
blending, dither and the color write mask, as the per-pixel code does
them. Checked against the per-pixel code span by span in 8 games and 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 d729df2ecd SoftGPU: Step a triangle's planes along the row
Depth, colors, fog and the UV planes are now started once per row and
stepped a span at a time, instead of evaluated from scratch at every
span.

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 0223fbcce3 SoftGPU: Walk triangle rows between their exact ends
Each row's covered pixels now come from the three edges directly, as a
range from 64-bit integer bounds at the pixel centers, and only the spans
in it are visited, with lane masks from the range. The edge functions
per span (32-bit, with a coarse row narrowing) are gone. The mip level's
q comes from the row's covered range instead of edge tests per pixel. A
tall triangle's long edge, which the GE checks at the other end of a span
for its first or last pixel, is still checked 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 cb48381ada SoftGPU: Compute a span's exact texture coordinates in vector lanes
GEUVSpan does the GE's per-pixel UV arithmetic for four pixels at once:
the plane values to float24s by exponent arithmetic, GERecip with its
table entries gathered, and the truncated 24-bit products from the 16-bit
significands' product. Lanes it doesn't cover (values past 2^24,
denormals, results out of range) send the span to the scalar code.
Tested bit for bit against it.

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 3b26ba54ba SoftGPU: Inline GERecip, and pick the mip level's q once per quad row
The rasterizer takes a GERecip per pixel, so it's inline now, with its
table exported. The q for the mip level is the same for the two pixels
of a quad row unless they're in different 4-pixel spans, so it's only
looked up again then.

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 b707a6837f SoftGPU: Scale UV plane values by a power of two instead of ldexp
The per-pixel texture coordinates called ldexp with a shift that's fixed
per triangle or line. The shift keeps the values in double's normal
range, so multiplying by a precomputed 2^-shift is exact. Lines also
convert their end values to fixed point once instead of 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 a11fd22553 SoftGPU: Store depth in VRAM as the GE does
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>
2026-10-08 18:35:48 +02:00
Henrik RydgårdandClaude Opus 5.5 3fcce3895e SoftGPU: Texture coordinates along lines as the GE computes them
Transform-mode lines take the triangle's per-vertex s, t, q (15 bits at the
larger exponent) along the line's gradient, like their color and depth, then
u = s * R(q). A pixel just inside a line's end samples short of the end
vertex's coordinate rather than at it (gpu/texmtx/prims: texel row 255, not a
wrap to 0).

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 0357baf1b7 SoftGPU: Depth along lines as the GE computes it
The same way as Gouraud color: a gradient along the major axis from the
setup reciprocal, and each pixel's value from its center's signed distance
from v0, so an endpoint's pixel extrapolates past the endpoint's depth
(gpu/probe exp170, exact; it had 435 wrong pixels). Coded Arms' (ULUS10019)
last pixel, where a short line passed a GEQUAL test, and SOCOM's line depth.

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 0870c0135b SoftGPU: Exact side test for a triangle's edges
Which side an edge is on decides whether a pixel center exactly on it is
inside. The test divided with truncation, so a vertex 0.2 subpixels left of
the opposite edge counted as on it, and a thin triangle's right edge became
inclusive. Peace Walker (ULUS10509), ULJM05302 and mali_missing_circle PSP
replays become exact.

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 65421f1f6b SoftGPU: Lines shorter than a pixel keep their fog
With no steps along the line, both endpoint weights were zero, so fog (and
UVs) interpolated to zero: full fog. SOCOM's (UCUS98649) radar lines, a few
pixels long in an orthographic view, came out in the fog color.

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 683f593de5 SoftGPU: Line endpoints on a diamond's major-axis corner are outside
An endpoint exactly on the left or right corner of a pixel's diamond (top
or bottom for y-major lines) doesn't count as inside it: the pixel is lit
only if the line crosses the diamond (gpu/probe exp149). Makes exp72,
Virtua Tennis and echochrome exact.

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 10fcf4bde6 SoftGPU: Interpolated depth below 0 is 0
Next to an edge between two z = 0 vertices, the floored depth plane can
come out -1. The GE stores and range-tests 0 there, in through and
transform mode, with depth clamp on or off (gpu/probe exp148). Fixes a
seam across the sky in Frontier Gate Boost.

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 8b3f3b20de SoftGPU: Don't skip zero alpha pixels when dithering
The forced alpha test for src alpha / inv src alpha blending assumed a
zero alpha pixel leaves the target unchanged, but with dithering on the
GE still writes dst + dither (gpu/probe exp141). Makes the Test Drive
(ULUS10249) frame dump exact.

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 6fe7d5d35c SoftGPU: Gouraud color along lines as the GE computes it
A line's color gradient along its major axis comes from the triangle
setup's reciprocal, with 14 fraction bits per subpixel, floored, and each
pixel is the start color plus the gradient times its center's signed
distance from v0 along the line. A diagonal line (|dx| == |dy|) is
y-major. gpu/probe exp137, exact; fixes the line strips in a Final Fantasy
Zero frame dump.

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 b10ab1d4aa SoftGPU: Span snapping on very tall triangles' long edge
When a triangle's long edge (top to bottom vertex) has 3 dy > 2^17 in
screen subpixels, the GE lights the first pixel of each 4-pixel span along
it (the last, for a right edge) when any of the span is inside, likely an
overflowing 3 dy span offset. Bottom ties end the long edge at the left
vertex. Such triangles take a scalar mask path. gpu/probe exp130-135, exact;
none of 216 frame dumps has such a triangle.

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 9bca024674 SoftGPU: Sprite UVs with a different w at each vertex
The GE builds a sprite's UV plane from three corners whose s, t and q it
takes component by component from the two vertices: s from the vertex that
supplies the corner's x, t from the one that supplies its y (swapped when the
sprite is rotated), and q from the one that supplies its x. With different w
at the two vertices that bends the mapping; we used v1's w at every corner.
gpu/probe exp129: all four vertex orders at w = 1, 2.7 and differing w, exact.

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 f5bfa77841 SoftGPU: Rotated sprites' first row and UV plane
A sprite drawn from bottom left to top right is rotated: its first row
rounds like a column ((y + 6) >> 4), and its UV plane comes from v0, v1 and
the bottom right corner, anchoring it at the bottom left. The other three
vertex orders were already exact (gpu/probe exp121-122, through and
transform mode). Fixes the last differences in an MGS frame dump (HUD
sprites).

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 47261f8b86 SoftGPU: Y-major lines count the other diamond edges as inside
Which boundary points of a pixel's diamond count as inside is transposed for
y-major lines: the left corner, the edges beside it and the top corner,
where x-major lines use the top corner, its edges and the left corner. exp72
went from 12 differing pixels to 1, and antialiased lines (exp112, same
pixels) from 117 to 101.

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 32c41a3417 SoftGPU: Gather the GE arithmetic in GEMath.h
The float24 truncations, reciprocal and rsqrt tables, GE adder and row sums,
the setup reciprocal for planes, the mip log2, texture coordinate precision,
the lighting pow and color scaling, and the antialiased line alpha, from
TransformUnit, Rasterizer and Lighting, so they can be unit tested. No
behavior change.

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 e21af05123 SoftGPU: Antialias lines with the GE's coverage alpha
Antialiased lines light the same pixels as plain ones, and each pixel's
alpha (replacing the vertex alpha) is 128 - |v|, v the largest integer
below 256 times the pixel center's offset from the line along the minor
axis (gpu/probe exp112: about 98% of line pixels exact, through and
transform mode; the rest look like the GE's stepper). Echochrome's MSE
against the PSP goes from 170 to 0.12.

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 8d8fc726a5 SoftGPU: Take the mip level's q once per four-pixel span
The GE picks a triangle pixel's mip level (auto and slope modes) with the q
at the second pixel of its row's four-pixel span in the direction it walks
the row: x = 4k + 1 left to right, but 4k + 2 for triangles whose long edge
is the right side (the same condition as the plane anchor). When that pixel
is outside the triangle, the span's first covered pixel in that order. Auto
LOD under perspective is exact (gpu/probe exp93, exp103-106, the latter built
from a GTA LCS triangle), and the slope mode probes stay exact.

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 2001623984 SoftGPU: Only skip the alpha test for CLUT alphas that can't be zero
The check ANDs every CLUT entry, but took any common bit as proof that no
alpha is zero, so a white palette with alphas 0, 0x10, ... lost its alpha
test. Only the alpha bits count now. Ace Combat's subtitles become bit exact
against the PSP.

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 15a2543bcc SoftGPU: Pick auto mip levels from the UV planes like the GE
The auto level is the largest of the four UV gradients (du/dx, du/dy, dv/dx,
dv/dy) in texels per pixel, taken from the s and t planes, minus the pixel's
q, both through the GE's float-bits log2 (gpu/probe exp92: exact for affine
mappings at any rotation and anisotropy). Before, only du/dx and dv/dy from a
2x2 quad's differences counted. Under perspective (exp93) about 14% of
pixels are still a sixteenth of a level off.

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 85d788db06 SoftGPU: Double the specular color along with the texture result
With separate specular lighting and color doubling, the GE doubles the
secondary color as well (gpu/probe exp86, exact for modulate, add and
replace).

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 0427e07903 SoftGPU: Keep texture coordinates at the GE's precision
A perspective u = s * R(q) keeps 24 significant bits, truncated, instead of
a float24's 16 (gpu/probe exp82: large UVs from a texture matrix, as NFS Most
Wanted uses). Through-mode points keep 15 bits of their UVs, as the UV planes
do for triangles (exp83, exp84).

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 f12273f450 SoftGPU: Interpolate fog with the GE's plane
The 8-bit fog of each vertex goes through the same plane as depth and color.
Bit exact on gpu/probe exp21 (all 9 cases, from 94-98%).

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 d366456f2a SoftGPU: Interpolate through mode triangle UVs with the GE's planes
Like transform mode with w = 1, and like sprites. Bit exact on gpu/probe
exp73.

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 5dba44d0c3 SoftGPU: Rasterize lines with diamond exit like the GE
A pixel is lit when the line passes through its diamond and doesn't end inside
it, with points on the top corner, its two edges and the left corner counting
as inside (also where the line only touches the diamond). Exact for 313 of 320
random lines on gpu/probe exp72; a few ties at line ends still differ.
PPSSPP's DDA matched about 20%.

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 abd4c21b9b SoftGPU: Texture matrix and projected UVs like the GE
The texture matrix is summed like a position row, and projected texture
coordinates go through the same s, t, q planes as perspective ones, with q
the texture matrix's q over w. Points use the planes too. Bit exact on
gpu/probe exp64-65, except the normalized normal source, whose normalization
isn't matched.

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 a75df22ddc SoftGPU: Select mip levels in slope mode like the GE
Per pixel, from the interpolated q = 1/w: 16 + log2(slope) - log2(q), both
with the same float-bits log2, plus the bias. Bit exact on gpu/probe
exp58-60, including nearest level rounding.

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 0f2b5613fb SoftGPU: Interpolate Gouraud color and perspective UVs like the GE
Both use the GE's fixed point depth plane. Color is screen-linear, also in
transform mode, with 8-bit channels as the plane values (gpu/probe exp54). For
perspective UVs, s = u * R(w), t and q = R(w) become 15-bit integers at the
triangle's largest exponent, go through the plane, and u = s * R(q) per pixel
(exp55-56, bit exact at 1/16 texel).

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 df8f1663dd SoftGPU: Interpolate depth with the GE's fixed point plane
Bit exact against the PSP on every pixel of gpu/probe exp36-41 (over a million
pixels of large, small, steep and slanted triangles):
- Per triangle, the doubled area's 16-bit significand indexes a 256-segment
  reciprocal table, linear over each segment's low 8 bits (measured for all
  inputs; not the z/w table).
- The x and y depth gradients are fixed point, 14 fractional bits per
  subpixel, from the exact edge cross products times that reciprocal.
- The plane is anchored at the leftmost vertex, or the rightmost when the long
  edge (top to bottom) is strictly the right side of the triangle.
- Each pixel takes the plane at its center, floored.

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 3bf25586bd SoftGPU: Compute X and Y like the GE, and sample at pixel centers
X and Y now go through the same float24 math as Z: clip coordinates from the
combined matrix (also when lighting needs the world position), the GE's
reciprocal, and the viewport offset added without guard bits, which around
2048 lands on the 1/16 subpixel grid. The 12.4 conversion truncates instead of
rounding up at 10/16.

Triangles are sampled exactly at pixel centers, not 1/16 before them, with left
and top edges inclusive. Sprites start at (x + 6) >> 4 horizontally and
(y + 7) >> 4 vertically and end at (v + 7) >> 4, and their 2x2 loop no longer
treats ties differently by pixel parity. Measured with gpu/probe; against PSP
replays, Coded Arms goes from MSE 33 to 26 and the Test Drive map from 17 to 7.

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 c35f7527a3 SoftGPU: Quantize fog per vertex, like the GE
The GE converts the fog factor to 8 bits per vertex, min(floor(256 * f), 255),
and interpolates that linearly in screen space. Clamping after interpolation
instead was up to 127 levels off on triangles that cross the fog range.
Measured with gpu/probe; points and wacky values still match exactly.

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 9162592493 SoftGPU: Add the secondary color on the portable triangle path
Without SSE or NEON, triangle pixels got the secondary color in place of
the primary one plus it, so lit triangles came out black. It showed as
the "unexplained" known failures on riscv64 and loongarch64, and broke
the new gpu/lighting/shademap there. Reproduced on arm64 by building
without NEON.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:47:16 -06:00
Henrik Rydgård 46d5fae342 VSH prep: Free up kernel memory by not storing the PPGe atlas in it 2026-08-19 18:45:52 +02:00
Henrik Rydgård c5e4d0d90d Rename the get-memory-pointer functions to make it clear where CPU exceptions can happen. 2026-08-12 14:06:16 +02:00
Henrik Rydgård a317890c08 Remove the GPUDebugInterface class
Just a pointless extra layer in the class hiearchy, making it
unnecessarily hard to modify the interface.

Might as well hit GPUCommon directly.
2026-06-02 11:15:08 +02:00
Henrik Rydgård 250abe0d56 Loongarch64 build fixes 2026-05-25 15:41:24 +02:00
Henrik Rydgård a602be6ca4 Fix regression for line gouraud shading
Caused by a2abf94
2025-03-03 11:58:12 +01:00