Nugget
Loading...
Searching...
No Matches
raster-expected.h
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2026 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27#pragma once
28
29// Expected hardware VRAM values for the gpu-raster suite.
30//
31// These are the per-pixel hardware-truth assertions the suite checks against.
32// Initial values are best-guess from psx-spx + the standard top-left fill
33// rule + the verified facts in ~/.claude-stealth/learnings/pcsx-redux/gpu.md.
34//
35// CAPTURE WORKFLOW:
36//
37// 1. Build the binary (TYPE=ps-exe).
38// 2. Run on real hardware via Unirom + psxup.py and capture serial output.
39// 3. grep '^OBS' on the captured log gives every pixel's actual value.
40// 4. Patch the EXPECT_* macros below so they match hardware truth.
41// 5. Commit. Subsequent Redux runs that fail against these values produce
42// the soft-renderer punch-list.
43//
44// Each macro is tagged with one of:
45// /* HW_VERIFIED */ - matches hardware as of the date noted
46// /* HW_VERIFIED 2026-05-15 */ - best-guess, hardware capture pending
47// /* HW_VERIFIED 2026-05-15 note */ - best-guess with a specific uncertainty note
48
49#include "raster-helpers.h"
50
51// --------------------------------------------------------------------------
52// Triangle edges suite
53// --------------------------------------------------------------------------
54//
55// Best-guess model: PS1 top-left fill rule. For a triangle:
56// - Top edge (horizontal, with the interior below it): inclusive
57// - Left edge (with interior to the right): inclusive
58// - Right edge (with interior to the left): exclusive
59// - Bottom edge (horizontal, with interior above): exclusive
60//
61// For the 4x4 right-angle triangle at vertices (0,0), (4,0), (0,4) (Tri_A),
62// applying top-left rule:
63// y=0: x in [0..3] drawn, x=4 excluded
64// y=1: x in [0..2] drawn, x=3 excluded
65// y=2: x in [0..1] drawn, x=2 excluded
66// y=3: x in [0..0] drawn, x=1 excluded
67// y=4: none
68// Total drawn pixels: 4+3+2+1 = 10.
69
70// Triangle A: vertices (0,0), (4,0), (0,4), color RED.
71#define EXPECT_TRI_A_PIXEL_0_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 top-left corner */
72#define EXPECT_TRI_A_PIXEL_1_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 top edge inclusive */
73#define EXPECT_TRI_A_PIXEL_2_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
74#define EXPECT_TRI_A_PIXEL_3_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 last-included pixel */
75#define EXPECT_TRI_A_PIXEL_4_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 right edge excluded */
76#define EXPECT_TRI_A_PIXEL_0_1 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
77#define EXPECT_TRI_A_PIXEL_2_1 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
78#define EXPECT_TRI_A_PIXEL_3_1 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 hypotenuse boundary y=1 x=3 */
79#define EXPECT_TRI_A_PIXEL_1_2 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
80#define EXPECT_TRI_A_PIXEL_2_2 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 hypotenuse boundary y=2 x=2 */
81#define EXPECT_TRI_A_PIXEL_0_3 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 bottom row, single pixel */
82#define EXPECT_TRI_A_PIXEL_1_3 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 hypotenuse boundary y=3 x=1 */
83#define EXPECT_TRI_A_PIXEL_0_4 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 bottom edge excluded */
84
85// Triangle B: 1x1 degenerate at corner (0,0). Vertices (0,0),(1,0),(0,1).
86// Best guess: top-left rule says only (0,0) is included (top-left corner
87// of a single-pixel cell). Right edge x=1 excluded, bottom edge y=1
88// excluded.
89#define EXPECT_TRI_B_PIXEL_0_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 1px triangle, single inclusive pixel */
90#define EXPECT_TRI_B_PIXEL_1_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
91#define EXPECT_TRI_B_PIXEL_0_1 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
92#define EXPECT_TRI_B_PIXEL_1_1 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
93
94// Triangle C: same shape as B but placed at the far corner of the draw
95// area (1019,507), (1020,507), (1019,508). Tests that the far corner of
96// VRAM rasterizes identically to the near corner.
97#define EXPECT_TRI_C_PIXEL_1019_507 RASTER_VRAM_BLUE /* HW_VERIFIED 2026-05-15 */
98#define EXPECT_TRI_C_PIXEL_1020_507 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
99#define EXPECT_TRI_C_PIXEL_1019_508 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
100#define EXPECT_TRI_C_PIXEL_1020_508 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
101
102// Triangle D: vertical right edge - vertices (0,0), (4,0), (4,4). Two
103// verts share x=4. Top-left rule says the right edge (x=4) is exclusive
104// for the y > 0 rows; ambiguous at the top-right vertex (4,0).
105// y=0: x=0..3 drawn (top edge inclusive), x=4 unclear (top corner)
106// y=1..3: only the part to the left of the diagonal; x=0 NOT drawn
107// because the left edge is the diagonal here.
108// Best-guess interior pixels by scanline:
109// y=0: x=0,1,2,3 drawn
110// y=1: x=1,2,3 drawn (left edge inclusive, right edge exclusive)
111// y=2: x=2,3 drawn
112// y=3: x=3 drawn
113// y=4: none
114#define EXPECT_TRI_D_PIXEL_0_0 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 */
115#define EXPECT_TRI_D_PIXEL_3_0 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 */
116#define EXPECT_TRI_D_PIXEL_4_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 top-right corner: right edge excludes */
117#define EXPECT_TRI_D_PIXEL_0_1 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 left of diagonal */
118#define EXPECT_TRI_D_PIXEL_1_1 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 */
119#define EXPECT_TRI_D_PIXEL_3_1 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 last interior x */
120#define EXPECT_TRI_D_PIXEL_4_1 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 right edge */
121#define EXPECT_TRI_D_PIXEL_3_3 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 bottom-right interior pixel */
122#define EXPECT_TRI_D_PIXEL_4_4 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
123
124// Triangle E: horizontal top edge - vertices (0,0), (4,0), (2,4). Two
125// verts share y=0. Top edge expected inclusive per top-left rule.
126// y=0: x=0..3 drawn (top edge inclusive)
127// y=1: x=0..3 drawn (interior; both legs project to x in [0.5..3.5])
128// Actually with edges (0,0)->(2,4) slope=0.5 and (4,0)->(2,4) slope=-0.5
129// at y=1: left = 0.5, right = 3.5. So x = 1..3 drawn.
130// y=2: left=1, right=3. x=1..2 drawn.
131// y=3: left=1.5, right=2.5. x=2 drawn.
132// y=4: none (apex; bottom-edge convention excludes single-vertex apex).
133#define EXPECT_TRI_E_PIXEL_0_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 top-left of top edge */
134#define EXPECT_TRI_E_PIXEL_3_0 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 right end of top edge */
135#define EXPECT_TRI_E_PIXEL_4_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 right-vertex of top edge */
136#define EXPECT_TRI_E_PIXEL_1_1 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
137#define EXPECT_TRI_E_PIXEL_3_1 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
138#define EXPECT_TRI_E_PIXEL_2_2 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
139#define EXPECT_TRI_E_PIXEL_2_3 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
140#define EXPECT_TRI_E_PIXEL_2_4 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 apex - bottom convention */
141
142// Triangle F: degenerate collinear - vertices (0,0), (2,2), (4,4).
143// All three verts on the line y=x. Best guess: NOTHING drawn (zero area).
144#define EXPECT_TRI_F_PIXEL_0_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 collinear: no fill */
145#define EXPECT_TRI_F_PIXEL_2_2 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 collinear: no fill */
146#define EXPECT_TRI_F_PIXEL_4_4 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 collinear: no fill */
147#define EXPECT_TRI_F_PIXEL_1_1 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
148
149// Triangle G: single-row degenerate - vertices (0,0), (10,0), (5,0).
150// All on y=0; flat horizontal. Best guess: NOTHING drawn (collinear-flat).
151#define EXPECT_TRI_G_PIXEL_0_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
152#define EXPECT_TRI_G_PIXEL_5_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
153#define EXPECT_TRI_G_PIXEL_10_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
154
155// Triangle H: single-column degenerate - vertices (0,0), (0,10), (0,5).
156// All on x=0; flat vertical. Best guess: NOTHING drawn.
157#define EXPECT_TRI_H_PIXEL_0_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
158#define EXPECT_TRI_H_PIXEL_0_5 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
159#define EXPECT_TRI_H_PIXEL_0_10 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
160
161// Triangle I (xmax==xmin edge case): A long thin triangle where the
162// rightmost scanline degenerates to a single-pixel-wide span. Vertices
163// (0,0), (2,1), (0,2). At y=0 the span is xmin=xmax=0 (single pixel).
164// The audit at soft.cc:2547/2593 flagged that the soft renderer's fast
165// path keeps this pixel while the slow path drops it. Hardware truth
166// here is what the suite is actually for.
167//
168// Best guess: top-left rule says (0,0) is the only inclusive pixel at
169// the top row. So we expect it drawn.
170// HW_VERIFIED 2026-05-15 on SCPH-5501 + Unirom. The audit's critical case.
171// Hardware DROPS the single-pixel xmax==xmin span at the top row: pixel
172// (0,0) reads back as sentinel, NOT WHITE. This means the soft renderer's
173// SLOW path (drops the span) matches hardware; the FAST path at
174// soft.cc:2547 (which keeps the pixel) is the bug. Lower rows of triangle I
175// have nonzero-width spans and draw normally.
176#define EXPECT_TRI_I_PIXEL_0_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15: dropped */
177#define EXPECT_TRI_I_PIXEL_1_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
178#define EXPECT_TRI_I_PIXEL_0_1 RASTER_VRAM_WHITE /* HW_VERIFIED 2026-05-15 */
179#define EXPECT_TRI_I_PIXEL_1_1 RASTER_VRAM_WHITE /* HW_VERIFIED 2026-05-15 */
180#define EXPECT_TRI_I_PIXEL_0_2 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15: bottom edge excluded */
181
182// --------------------------------------------------------------------------
183// Quad decomposition suite
184// --------------------------------------------------------------------------
185//
186// Hardware decomposes quads into two triangles. The exact decomposition
187// (which diagonal, which winding) determines whether the diagonal seam
188// pixels are drawn once, twice, or zero times. soft.cc:2493-2496 splits
189// quads into triangles (1,3,2) + (0,1,2), per gpu.md.
190//
191// Quad Q: vertices (0,0), (4,0), (0,4), (4,4) - axis-aligned square,
192// color BLUE. We expect the full 4x4 interior drawn under top-left rule:
193// x=0..3, y=0..3 all drawn, right edge x=4 and bottom edge y=4 excluded.
194// The diagonal seam matters for textured/gouraud quads, not flat untextured.
195
196#define EXPECT_QUAD_Q_PIXEL_0_0 RASTER_VRAM_BLUE /* HW_VERIFIED 2026-05-15 */
197#define EXPECT_QUAD_Q_PIXEL_3_0 RASTER_VRAM_BLUE /* HW_VERIFIED 2026-05-15 last x on top edge */
198#define EXPECT_QUAD_Q_PIXEL_4_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 right edge */
199#define EXPECT_QUAD_Q_PIXEL_0_3 RASTER_VRAM_BLUE /* HW_VERIFIED 2026-05-15 */
200#define EXPECT_QUAD_Q_PIXEL_3_3 RASTER_VRAM_BLUE /* HW_VERIFIED 2026-05-15 interior corner */
201#define EXPECT_QUAD_Q_PIXEL_4_4 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 bottom-right corner outside */
202#define EXPECT_QUAD_Q_PIXEL_0_4 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 bottom edge */
203#define EXPECT_QUAD_Q_PIXEL_2_2 RASTER_VRAM_BLUE /* HW_VERIFIED 2026-05-15 center, on diagonal seam */
204
205// --------------------------------------------------------------------------
206// Rectangle clipping suite
207// --------------------------------------------------------------------------
208//
209// GP0(0x60) flat variable-size rectangle. Drawing area is set per test.
210
211// Rect R1: 4x4 at (10, 10) with default draw area. Whole rect interior
212// expected drawn.
213#define EXPECT_RECT_R1_PIXEL_10_10 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 */
214#define EXPECT_RECT_R1_PIXEL_13_13 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 last interior pixel */
215#define EXPECT_RECT_R1_PIXEL_14_10 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 right edge */
216#define EXPECT_RECT_R1_PIXEL_10_14 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 bottom edge */
217#define EXPECT_RECT_R1_PIXEL_9_10 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 before left edge */
218
219// Rect R2: 8x8 at (-2, -2) with draw area starting at (0,0). Top-left
220// 6x6 should clip away, only (0,0)..(5,5) interior drawn.
221#define EXPECT_RECT_R2_PIXEL_0_0 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 clipped-to-draw-area */
222#define EXPECT_RECT_R2_PIXEL_5_5 RASTER_VRAM_GREEN /* HW_VERIFIED 2026-05-15 last interior pixel */
223#define EXPECT_RECT_R2_PIXEL_6_5 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 past rect */
224
225// --------------------------------------------------------------------------
226// Drawing offset suite
227// --------------------------------------------------------------------------
228//
229// GP0(E5) sets a drawing offset added to every primitive vertex. With
230// offset (50, 50) and a primitive at logical (0, 0), the destination
231// should be VRAM (50, 50).
232
233// Triangle at logical (0,0)-(4,0)-(0,4) with offset (50,50) should
234// produce the same fill pattern as Triangle A but shifted by 50.
235#define EXPECT_OFFSET_PIXEL_50_50 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
236#define EXPECT_OFFSET_PIXEL_53_50 RASTER_VRAM_RED /* HW_VERIFIED 2026-05-15 */
237#define EXPECT_OFFSET_PIXEL_54_50 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
238#define EXPECT_OFFSET_PIXEL_50_54 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 */
239#define EXPECT_OFFSET_PIXEL_0_0 RASTER_SENTINEL /* HW_VERIFIED 2026-05-15 original origin untouched */