Commit Graph
108 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 061038e0bb SoftGPU: Don't skin in the vertex decoder for the transform unit
ApplyGESkinning computes skinned positions and normals the way the GE
does and overwrites what the decoder skinned in float, so that was
wasted, 4% of the emulation thread in God of War. A new decoder option,
callerSkins, leaves out the weights, position and normal steps for
weighted vertices outside through mode and only reserves the float
position and normal. The software renderer's transform unit gets its
own decoders with it; bounding boxes, splines and the debugger still
use the ones that skin. Checked to give the same output with the vertex
decoder JIT as without the option.

God of War takes 4.0 s for five emulated seconds (from 4.1 s).

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 bdac4fff45 SoftGPU: Transform a run of draws' vertices together, on helper threads
God of War draws thousands of short strips per frame, each continuing
the previous one's vertices with nothing changed in between. At the
first draw of such a run, SoftGPU now looks ahead in the display list
for the draws that follow it, past only commands that can't change
anything (NOPs, unchanged state, VADDR to where the vertices continue),
and the transform unit decodes the whole run at once and then skins and
transforms it in chunks that two helper threads take alongside the
emulation thread. The draws then read their vertices from that, and the
UV and normal they carry to the next draw are updated as reading their
last vertex would.

The helpers wait a moment for the next run before their tasks end, as
the drawing threads do: waking them costs the emulation thread a system
call. The thresholds were picked under WSL2, where that costs more than
on bare metal, so they're worth measuring again there.

God of War takes 4.2 s for five emulated seconds (from 4.5 s).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:55:57 +02:00
Henrik RydgårdandClaude Opus 5.5 5151e5d10f SoftGPU: Transform vertex positions four at a time
A draw's vertices now go through the position stage of ReadVertex (the
clip coordinates, the viewport, the screen rounding and the GE's fog)
four at a time, a vertex per lane, before the rest. GERowSumLanes is
GERowSum4 with a lane per vertex instead of per matrix row, sharing the
positions' parts between the five rows, and GERecip4 is GERecip for four
w's. A group with a lane those don't handle (non-finite coordinates, a
w that's zero, denormal or too large) goes through ReadVertex as before.

Wipeout takes 3.8 s for five emulated seconds (from 4.2 s), God of War
4.7 s (from 5.0 s).

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 63213a69f9 SoftGPU: Take a draw's matrices apart once for GERowSum4
GERowSum4 split every matrix entry into exponent, fraction and sign for
each vertex. GERowSumRows does that once when the transform state is
computed, for the clip matrix, the world matrix's normal rows, the fog
row and the texture matrix.

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 1752a2e53b SoftGPU: Transform a vertex's screen position in vector lanes, without stalls
ReadVertex took the GE's viewport arithmetic one coordinate at a time,
with a reciprocal of w for each, and stored the position, the UVs and
the whole vertex in pieces that were then reloaded with wider loads,
each a store forwarding stall. x, y and z now go through one GERecip and
the four-lane multiply and add (the scalar path stays for non-finite
input and zero or denormal w), the position is loaded as a vector, and
the vertex is written straight into its destination.

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 d272703721 SoftGPU: Keep the vertex position, normal and light vectors as Vec4F32
The position is read once as (x, y, z, 1) for the clip, fog, texgen and
light vector rows, and lighting works on Vec4F32 throughout, without
going through arrays. Each light's constant term, its position minus
the world translation, is computed once per state instead of per
vertex. The texture matrix rows are now prepared with the transform
state, so loading that matrix dirties it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 09:07:12 +02:00
Henrik RydgårdandClaude Opus 5.5 834e617cc1 SoftGPU: Carry UVs and normals into formats without them as the GE does
gpu/vertices/carry, recorded on a PSP: a draw whose format has no UVs uses the last ones read, by any
earlier draw in draw order, textured or not. They're kept as read and get the scale and offset of the
draw that uses them. Normals carry over the same way.

We kept the UVs after scaling, only read them with texturing on, and after a cached indexed draw
carried the highest vertex instead of the last one drawn. The carried values move from statics in
ReadVertex to TransformUnit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 02:03:31 +02:00
Henrik RydgårdandClaude Opus 5.5 fb79979e01 SoftGPU: Small self-textures stay cached until TEXFLUSH
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>
2026-10-02 15:09:43 -06:00
Henrik RydgårdandClaude Opus 5.5 7df47b336b SoftGPU: Light vectors as one matrix row from the model position
The GE never forms a world position for lighting: the vector to a point
or spot light is the light position minus the world translation, minus
the model position times the world matrix, summed like a matrix row.
gpu/probe exp153-158 (point lights 0.02-20 units away, spot exponents up
to 40, game-like world matrices; exp153 is a Syphon Filter vertex) are
exact, and Syphon Filter (#13568) becomes 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 61c7478679 SoftGPU: Clip vertex colors and fog with t rounded to 1/256
The near-plane clipper's new vertices get their colors and fog (both 8-bit
per vertex) by lerping with t rounded to the nearest 1/256, not truncated
(gpu/probe exp136: every clipped color and fog pixel exact; the colors were
recovered exactly from the PSP's plane values per clipped 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 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 cfaa7a0d55 SoftGPU: Normalize, dot and transform normals like the GE
The GE normalizes with its own reciprocal square root, a 2 x 128 segment
table like its reciprocal's (measured on gpu/probe exp69), and sums dot
products and the world matrix rows like clip space rows. Used for normals,
light vectors, the half vector, the normalized normal texgen source, and the
world position. Bit exact on exp61, exp64 and exp69; point light attenuation
is 99.9%.

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 524fac1c32 SoftGPU: Clip at the near plane like the GE
Measured with gpu/probe exp43-47, bit exact:
- New vertices are interpolated from the inside vertex, t = d_in / (d_in -
  d_out) with d = z + w through the GE adder, using the GE's reciprocal;
  out - in is truncated to float24 before the multiply by t, and t and each
  coordinate use float24 products and adds.
- With one vertex outside, the quad is split from the vertex before it in the
  GE's order: (p, a, b) and (p, b, n). The GE takes odd strip triangles in
  reverse and fan triangles in order, so SendTriangle now says when the
  vertices it gets are reversed from that.

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 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) <noreply@anthropic.com>
2026-09-29 10:33:32 -06:00
Henrik Rydgård 623545bd24 Delete the "Hardware tessellation" feature.
Very hard to maintain and debug, not worth it.
2026-06-16 16:17:14 +02:00
Henrik Rydgård 0dc6e36d19 Delete redundant implementation of vertex preview in SoftGpu 2026-06-02 15:43:11 +02:00
Henrik Rydgård bb573e6e0c Well, it builds, but doesn't work yet. 2026-06-02 12:33:53 +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 44ece6dfa2 Determine the clip flags directly when culling, simplifying the code. 2026-05-30 19:07:59 +02:00
Henrik Rydgård 8b84fd555d Apply triangle near-clipping in software transform.
Fixes, but only in SW transform, #10914

Re-enable range culling, oops.
2026-05-30 19:07:59 +02:00
Henrik Rydgård b1723086be Plumb through depth information (although not yet always generated) 2026-05-30 19:07:58 +02:00
Henrik Rydgård f60e27a9b7 Just some refactoring of the GPUStatistics struct, and more use of StringWriter 2026-05-29 14:40:31 +02:00
Henrik Rydgård e71ffc59a6 Remove unnecessary IsStarted method 2026-02-17 10:18:08 +01:00
Henrik Rydgård 32df2f7a03 Remove unused functions 2025-01-28 10:54:43 +01:00
Henrik Rydgård ee297e974d Move more code into SoftwareTransformCommon, cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård 54d18bb343 Lift some more debugging functionality into GPUCommon 2024-12-15 14:03:05 +01:00
Henrik Rydgård 11dbae3457 Remove the "DispatchFlush" mechanism, not convinced it's a win 2024-12-15 13:42:05 +01:00
Herman Semenov b57dab2812 [GPU] Make static and const methods if possible 2024-04-05 17:04:31 +03:00
Henrik Rydgård 078018a943 Move the clockwise calculation out of DrawEngineCommon 2023-10-10 13:16:34 +02:00
Henrik Rydgård 880379c15d Extract some minor changes from #17497 2023-06-12 20:20:06 +02:00
Henrik Rydgård 72bed6f2b5 Some DeviceLost/DeviceRestore cleanup 2023-02-26 11:05:52 +01:00
Unknown W. Brackets be84bc9934 softgpu: Detect binner alloc fail and bail. 2023-01-01 06:59:14 -08:00
Unknown W. Brackets a7b7bf7826 Global: Set many read-only params as const.
This makes what they do and which args to use clearer, if nothing else.
2022-12-10 21:13:36 -08:00
Unknown W. Brackets dc962094f8 softgpu: Correctly fix inversions, matching tests.
Inversions are allowed just fine, but if clipping results in coordinates
outside range, the triangle should be culled.  Fixes more wanted
inversions.
2022-11-30 23:20:39 -08:00
Unknown W. Brackets 7880eb15c1 softgpu: Always use software skinning.
There's only software skinning, after all.
2022-11-06 08:44:22 -08:00
Unknown W. Brackets 80cccd7abb Build: Fix debug build on Windows 32-bit. 2022-10-01 17:07:27 -07:00
Unknown W. Brackets 6282f8b05f softgpu: Expand texture coords to include q.
We'll need this to correctly project.
2022-09-26 17:13:14 -07:00
Unknown W. Brackets 8376176b2f softgpu: Split clippos out of rasterization vert.
We don't use it, except w, at all in rasterization, so no need to keep it
in the bin queue.
2022-09-26 16:50:40 -07:00
Unknown W. Brackets 88b3b26ed3 softgpu: Cache reused indexed verts.
This happens a lot for spline/bezier, so can significantly speed up curve
heavy scenes.  Isn't necessarily that common otherwise, though.
2022-09-22 18:27:59 -07:00
Unknown W. Brackets 6877ff1af2 softgpu: Fix state/continuation for imm prims. 2022-09-18 06:16:26 -07:00
Unknown W. Brackets 596b07bd2e softgpu: Support fog and color1 on imm verts. 2022-09-18 06:16:26 -07:00
Unknown W. Brackets 35ba01e01f softgpu: Refactor imm draws to bypass vert read. 2022-09-18 06:16:25 -07:00
Unknown W. Brackets de080e2594 softgpu: Simplify vertex range culling.
The previous logic was harder to understand and easier to get wrong.
Just drop them when clipping the primitive.
2022-09-18 06:16:25 -07:00
Unknown W. Brackets 028a341cc8 softgpu: Explicitly flush on sync and output.
We could in theory skip flush on FinishDeferred, and allow some CPU/GPU
overlap.  If we did, we'd still want to flush at these times.
2022-09-18 06:16:25 -07:00
Unknown W. Brackets 8371091734 softgpu: Force correct alignment on 32-bit. 2022-09-12 22:15:02 -07:00
Henrik Rydgård 2791ab3226 Merge pull request #16011 from unknownbrackets/softgpu-rect
Detect more triangles as rectangles in softgpu
2022-09-12 08:35:13 +02:00
Unknown W. Brackets ce4fee7373 softgpu: Refactor triangle cull processing. 2022-09-11 22:39:32 -07:00
Unknown W. Brackets 8a6e8066bf softgpu: Store vertex colors as packed RGBA8.
No need to keep it expanded at 4x the space for both colors.
2022-09-11 18:41:06 -07:00
Unknown W. Brackets 8c55e18ea8 softgpu: Switch vert continue buffer to members.
Better this than static.  May be easier to handle imm prims correctly.
2022-09-11 08:54:34 -07:00