Nugget
Loading...
Searching...
No Matches
triangle-edges.c
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// Triangle-edges suite for the gpu-raster test binary.
28//
29// This file is #included from gpu-raster.c (cester is single-TU). It uses
30// helpers defined in raster-helpers.h and expected-value macros defined in
31// raster-expected.h, both of which gpu-raster.c includes before pulling in
32// this file.
33//
34// Each CESTER_TEST is one pixel-of-interest. Tests are self-contained: they
35// reset the GPU, fill the test region with the sentinel, draw the triangle
36// under test, and read back exactly one pixel. cester reports failures as
37// "expected X, received Y at file:line" and the ASSERT_PIXEL_EQ macro also
38// emits an OBS line so a hardware capture run produces a complete log
39// independent of cester's pass/fail accounting.
40
41// --------------------------------------------------------------------------
42// Per-triangle draw helpers
43// --------------------------------------------------------------------------
44//
45// All static helpers must be wrapped in CESTER_BODY(...) because cester
46// re-#includes __BASE_FILE__ multiple times during its forward-declaration
47// + array-build + function-body passes. CESTER_BODY's expansion is empty
48// on the early passes and contains its argument only on the final pass,
49// so a static helper inside CESTER_BODY is defined exactly once. See
50// cop0/cester-cop0.c for the canonical pattern.
51
53
54// Triangle A: 4x4 right-angle, vertices (0,0),(4,0),(0,4), color RED.
55static void rasterDrawTriA(void) {
56 rasterReset();
57 rasterClearTestRegion(0, 0, 16, 16);
58 rasterFlatTri(RASTER_CMD_RED, 0, 0, 4, 0, 0, 4);
59 rasterFlushPrimitive();
60}
61
62// Triangle B: 1-pixel degenerate at near corner, (0,0),(1,0),(0,1), RED.
63static void rasterDrawTriB(void) {
64 rasterReset();
65 rasterClearTestRegion(0, 0, 4, 4);
66 rasterFlatTri(RASTER_CMD_RED, 0, 0, 1, 0, 0, 1);
67 rasterFlushPrimitive();
68}
69
70// Triangle C: 1-pixel degenerate at far corner.
71static void rasterDrawTriC(void) {
72 rasterReset();
73 rasterClearTestRegion(1016, 504, 8, 8);
74 rasterFlatTri(RASTER_CMD_BLUE, 1019, 507, 1020, 507, 1019, 508);
75 rasterFlushPrimitive();
76}
77
78// Triangle D: vertical-right-edge, (0,0),(4,0),(4,4), GREEN.
79static void rasterDrawTriD(void) {
80 rasterReset();
81 rasterClearTestRegion(0, 0, 16, 16);
82 rasterFlatTri(RASTER_CMD_GREEN, 0, 0, 4, 0, 4, 4);
83 rasterFlushPrimitive();
84}
85
86// Triangle E: horizontal-top-edge isoceles, (0,0),(4,0),(2,4), RED.
87static void rasterDrawTriE(void) {
88 rasterReset();
89 rasterClearTestRegion(0, 0, 16, 16);
90 rasterFlatTri(RASTER_CMD_RED, 0, 0, 4, 0, 2, 4);
91 rasterFlushPrimitive();
92}
93
94// Triangle F: collinear-diagonal, (0,0),(2,2),(4,4), WHITE.
95static void rasterDrawTriF(void) {
96 rasterReset();
97 rasterClearTestRegion(0, 0, 16, 16);
98 rasterFlatTri(RASTER_CMD_WHITE, 0, 0, 2, 2, 4, 4);
99 rasterFlushPrimitive();
100}
101
102// Triangle G: collinear-horizontal, (0,0),(10,0),(5,0), WHITE.
103static void rasterDrawTriG(void) {
104 rasterReset();
105 rasterClearTestRegion(0, 0, 16, 8);
106 rasterFlatTri(RASTER_CMD_WHITE, 0, 0, 10, 0, 5, 0);
107 rasterFlushPrimitive();
108}
109
110// Triangle H: collinear-vertical, (0,0),(0,10),(0,5), WHITE.
111static void rasterDrawTriH(void) {
112 rasterReset();
113 rasterClearTestRegion(0, 0, 8, 16);
114 rasterFlatTri(RASTER_CMD_WHITE, 0, 0, 0, 10, 0, 5);
115 rasterFlushPrimitive();
116}
117
118// Triangle I: xmax==xmin single-pixel span at top. (0,0),(2,1),(0,2), WHITE.
119// This is the audit's soft.cc:2547/2593 critical case: the top row of this
120// triangle has the right-edge xmax equal to xmin (single-pixel span). Soft
121// renderer fast path keeps the pixel; slow path drops it.
122static void rasterDrawTriI(void) {
123 rasterReset();
124 rasterClearTestRegion(0, 0, 8, 8);
125 rasterFlatTri(RASTER_CMD_WHITE, 0, 0, 2, 1, 0, 2);
126 rasterFlushPrimitive();
127}
128
129) // CESTER_BODY
130
131// --------------------------------------------------------------------------
132// Triangle A: 4x4 right-angle - full interior + complement
133// --------------------------------------------------------------------------
134
135CESTER_TEST(triA_pixel_0_0, gpu_raster_phase1,
136 rasterDrawTriA();
138)
139
140CESTER_TEST(triA_pixel_1_0, gpu_raster_phase1,
141 rasterDrawTriA();
143)
144
145CESTER_TEST(triA_pixel_2_0, gpu_raster_phase1,
146 rasterDrawTriA();
148)
149
150CESTER_TEST(triA_pixel_3_0, gpu_raster_phase1,
151 rasterDrawTriA();
153)
154
155CESTER_TEST(triA_pixel_4_0_right_edge, gpu_raster_phase1,
156 rasterDrawTriA();
158)
159
160CESTER_TEST(triA_pixel_0_1, gpu_raster_phase1,
161 rasterDrawTriA();
163)
164
165CESTER_TEST(triA_pixel_2_1, gpu_raster_phase1,
166 rasterDrawTriA();
168)
169
170CESTER_TEST(triA_pixel_3_1_hypotenuse, gpu_raster_phase1,
171 rasterDrawTriA();
173)
174
175CESTER_TEST(triA_pixel_1_2, gpu_raster_phase1,
176 rasterDrawTriA();
178)
179
180CESTER_TEST(triA_pixel_2_2_hypotenuse, gpu_raster_phase1,
181 rasterDrawTriA();
183)
184
185CESTER_TEST(triA_pixel_0_3, gpu_raster_phase1,
186 rasterDrawTriA();
188)
189
190CESTER_TEST(triA_pixel_1_3_hypotenuse, gpu_raster_phase1,
191 rasterDrawTriA();
193)
194
195CESTER_TEST(triA_pixel_0_4_bottom_edge, gpu_raster_phase1,
196 rasterDrawTriA();
198)
199
200// --------------------------------------------------------------------------
201// Triangle B: 1-pixel degenerate at near corner
202// --------------------------------------------------------------------------
203
204CESTER_TEST(triB_pixel_0_0, gpu_raster_phase1,
205 rasterDrawTriB();
207)
208
209CESTER_TEST(triB_pixel_1_0, gpu_raster_phase1,
210 rasterDrawTriB();
212)
213
214CESTER_TEST(triB_pixel_0_1, gpu_raster_phase1,
215 rasterDrawTriB();
217)
218
219CESTER_TEST(triB_pixel_1_1, gpu_raster_phase1,
220 rasterDrawTriB();
222)
223
224// --------------------------------------------------------------------------
225// Triangle C: 1-pixel degenerate at far corner of draw area
226// --------------------------------------------------------------------------
227
228CESTER_TEST(triC_pixel_1019_507, gpu_raster_phase1,
229 rasterDrawTriC();
231)
232
233CESTER_TEST(triC_pixel_1020_507, gpu_raster_phase1,
234 rasterDrawTriC();
236)
237
238CESTER_TEST(triC_pixel_1019_508, gpu_raster_phase1,
239 rasterDrawTriC();
241)
242
243CESTER_TEST(triC_pixel_1020_508, gpu_raster_phase1,
244 rasterDrawTriC();
246)
247
248// --------------------------------------------------------------------------
249// Triangle D: vertical right edge - tests right-edge inclusion
250// --------------------------------------------------------------------------
251
252CESTER_TEST(triD_pixel_0_0_top_left, gpu_raster_phase1,
253 rasterDrawTriD();
255)
256
257CESTER_TEST(triD_pixel_3_0_top_inner, gpu_raster_phase1,
258 rasterDrawTriD();
260)
261
262CESTER_TEST(triD_pixel_4_0_top_right_corner, gpu_raster_phase1,
263 rasterDrawTriD();
265)
266
267CESTER_TEST(triD_pixel_0_1_left_of_diag, gpu_raster_phase1,
268 rasterDrawTriD();
270)
271
272CESTER_TEST(triD_pixel_1_1, gpu_raster_phase1,
273 rasterDrawTriD();
275)
276
277CESTER_TEST(triD_pixel_3_1, gpu_raster_phase1,
278 rasterDrawTriD();
280)
281
282CESTER_TEST(triD_pixel_4_1_right_edge, gpu_raster_phase1,
283 rasterDrawTriD();
285)
286
287CESTER_TEST(triD_pixel_3_3_bottom_right_interior, gpu_raster_phase1,
288 rasterDrawTriD();
290)
291
292CESTER_TEST(triD_pixel_4_4_bottom_right_vertex, gpu_raster_phase1,
293 rasterDrawTriD();
295)
296
297// --------------------------------------------------------------------------
298// Triangle E: horizontal top edge - tests top-edge inclusion
299// --------------------------------------------------------------------------
300
301CESTER_TEST(triE_pixel_0_0_top_left_of_top, gpu_raster_phase1,
302 rasterDrawTriE();
304)
305
306CESTER_TEST(triE_pixel_3_0_top_inner, gpu_raster_phase1,
307 rasterDrawTriE();
309)
310
311CESTER_TEST(triE_pixel_4_0_top_right_vertex, gpu_raster_phase1,
312 rasterDrawTriE();
314)
315
316CESTER_TEST(triE_pixel_1_1, gpu_raster_phase1,
317 rasterDrawTriE();
319)
320
321CESTER_TEST(triE_pixel_3_1, gpu_raster_phase1,
322 rasterDrawTriE();
324)
325
326CESTER_TEST(triE_pixel_2_2_center, gpu_raster_phase1,
327 rasterDrawTriE();
329)
330
331CESTER_TEST(triE_pixel_2_3_near_apex, gpu_raster_phase1,
332 rasterDrawTriE();
334)
335
336CESTER_TEST(triE_pixel_2_4_apex, gpu_raster_phase1,
337 rasterDrawTriE();
339)
340
341// --------------------------------------------------------------------------
342// Triangle F: collinear-diagonal - expects zero fill
343// --------------------------------------------------------------------------
344
345CESTER_TEST(triF_collinear_diag_pixel_0_0, gpu_raster_phase1,
346 rasterDrawTriF();
348)
349
350CESTER_TEST(triF_collinear_diag_pixel_1_1, gpu_raster_phase1,
351 rasterDrawTriF();
353)
354
355CESTER_TEST(triF_collinear_diag_pixel_2_2, gpu_raster_phase1,
356 rasterDrawTriF();
358)
359
360CESTER_TEST(triF_collinear_diag_pixel_4_4, gpu_raster_phase1,
361 rasterDrawTriF();
363)
364
365// --------------------------------------------------------------------------
366// Triangle G: collinear-horizontal - expects zero fill
367// --------------------------------------------------------------------------
368
369CESTER_TEST(triG_collinear_horiz_pixel_0_0, gpu_raster_phase1,
370 rasterDrawTriG();
372)
373
374CESTER_TEST(triG_collinear_horiz_pixel_5_0, gpu_raster_phase1,
375 rasterDrawTriG();
377)
378
379CESTER_TEST(triG_collinear_horiz_pixel_10_0, gpu_raster_phase1,
380 rasterDrawTriG();
382)
383
384// --------------------------------------------------------------------------
385// Triangle H: collinear-vertical - expects zero fill
386// --------------------------------------------------------------------------
387
388CESTER_TEST(triH_collinear_vert_pixel_0_0, gpu_raster_phase1,
389 rasterDrawTriH();
391)
392
393CESTER_TEST(triH_collinear_vert_pixel_0_5, gpu_raster_phase1,
394 rasterDrawTriH();
396)
397
398CESTER_TEST(triH_collinear_vert_pixel_0_10, gpu_raster_phase1,
399 rasterDrawTriH();
401)
402
403// --------------------------------------------------------------------------
404// Triangle I: xmax==xmin top row - CRITICAL audit case (soft.cc:2547/2593)
405// --------------------------------------------------------------------------
406
407CESTER_TEST(triI_xmax_eq_xmin_pixel_0_0, gpu_raster_phase1,
408 rasterDrawTriI();
410)
411
412CESTER_TEST(triI_xmax_eq_xmin_pixel_1_0, gpu_raster_phase1,
413 rasterDrawTriI();
415)
416
417CESTER_TEST(triI_xmax_eq_xmin_pixel_0_1, gpu_raster_phase1,
418 rasterDrawTriI();
420)
421
422CESTER_TEST(triI_xmax_eq_xmin_pixel_1_1, gpu_raster_phase1,
423 rasterDrawTriI();
425)
426
427CESTER_TEST(triI_xmax_eq_xmin_pixel_0_2_bottom_excluded, gpu_raster_phase1,
428 rasterDrawTriI();
430)
CESTER_BODY(static int s_got40;static int s_got80;static uint32_t s_cause;static uint32_t s_epc;static uint32_t s_from;static uint32_t *s_resume;static uint32_t *s_regs;static uint32_t(*s_customhandler)()=NULL;static uint32_t s_oldIMASK;static uint32_t s_oldDPCR;static uint32_t s_oldDICR;uint32_t handler(uint32_t *regs, uint32_t from) { if(from==0x40) s_got40=1;if(from==0x80) s_got80=1;uint32_t cause;uint32_t epc;s_from=from;asm("mfc0 %0, $13\nnop\nmfc0 %1, $14\nnop" :"=r"(cause), "=r"(epc));s_cause=cause;s_epc=epc;if(s_customhandler) { return s_customhandler();} else { return s_resume ?((uint32_t) s_resume) :(epc+4);} } void installExceptionHandlers(uint32_t(*handler)(uint32_t *regs, uint32_t from));void uninstallExceptionHandlers();uint32_t branchbranch1();uint32_t branchbranch2();uint32_t jumpjump1();uint32_t jumpjump2();uint32_t cpu_LWR_LWL_half(uint32_t buff[], uint32_t initial);uint32_t cpu_LWR_LWL_nodelay(uint32_t buff[], uint32_t initial);uint32_t cpu_LWR_LWL_delayed(uint32_t buff[], uint32_t initial);uint32_t cpu_LWR_LWL_load_different(uint32_t buff[], uint32_t initial);uint32_t cpu_LW_LWR(uint32_t buff[], uint32_t initial);uint32_t cpu_delayed_load(uint32_t buff[], uint32_t override);uint32_t cpu_delayed_load_cancelled(uint32_t buff[], uint32_t override);uint64_t cpu_delayed_load_load(uint32_t buff[], uint32_t override);uint32_t linkandload();uint32_t lwandlink();uint32_t nolink();static int s_interruptsWereEnabled;) CESTER_BEFORE_EACH(cpu_tests
CESTER_TEST(cpu_cop0_basic_write_bp, cpu_tests, uint32_t expectedEPC;uint32_t t;volatile uint32_t *ptr=(volatile uint32_t *) 0x58; *ptr=1;__asm__ volatile("" " lui %0, 0b1100101010000000\n" " mtc0 %0, $7\n" " li %0, 0x58\n" " mtc0 %0, $5\n" " li %0, 0xfffffff0\n" " mtc0 %0, $9\n" :"=r"(t));cester_assert_uint_eq(1, *ptr);__asm__ volatile("la %0, 1f\n1:\nsw $0, 0x58($0)" :"=r"(expectedEPC));__asm__ volatile("mtc0 $0, $7\n");cester_assert_uint_eq(0, *ptr);cester_assert_uint_eq(1, s_got40);cester_assert_uint_eq(0, s_got80);cester_assert_uint_eq(0x40, s_from);cester_assert_uint_eq(expectedEPC, s_epc);) CESTER_TEST(cpu_cop0_kseg_write_bp
#define EXPECT_TRI_D_PIXEL_4_1
Definition raster-expected.h:120
#define EXPECT_TRI_B_PIXEL_0_0
Definition raster-expected.h:89
#define EXPECT_TRI_D_PIXEL_0_1
Definition raster-expected.h:117
#define EXPECT_TRI_I_PIXEL_0_2
Definition raster-expected.h:180
#define EXPECT_TRI_I_PIXEL_0_1
Definition raster-expected.h:178
#define EXPECT_TRI_I_PIXEL_1_0
Definition raster-expected.h:177
#define EXPECT_TRI_A_PIXEL_1_0
Definition raster-expected.h:72
#define EXPECT_TRI_G_PIXEL_10_0
Definition raster-expected.h:153
#define EXPECT_TRI_B_PIXEL_1_1
Definition raster-expected.h:92
#define EXPECT_TRI_A_PIXEL_1_3
Definition raster-expected.h:82
#define EXPECT_TRI_B_PIXEL_1_0
Definition raster-expected.h:90
#define EXPECT_TRI_F_PIXEL_1_1
Definition raster-expected.h:147
#define EXPECT_TRI_H_PIXEL_0_5
Definition raster-expected.h:158
#define EXPECT_TRI_F_PIXEL_4_4
Definition raster-expected.h:146
#define EXPECT_TRI_A_PIXEL_3_0
Definition raster-expected.h:74
#define EXPECT_TRI_D_PIXEL_0_0
Definition raster-expected.h:114
#define EXPECT_TRI_D_PIXEL_3_0
Definition raster-expected.h:115
#define EXPECT_TRI_D_PIXEL_3_3
Definition raster-expected.h:121
#define EXPECT_TRI_D_PIXEL_4_4
Definition raster-expected.h:122
#define EXPECT_TRI_E_PIXEL_3_1
Definition raster-expected.h:137
#define EXPECT_TRI_I_PIXEL_0_0
Definition raster-expected.h:176
#define EXPECT_TRI_F_PIXEL_2_2
Definition raster-expected.h:145
#define EXPECT_TRI_E_PIXEL_2_2
Definition raster-expected.h:138
#define EXPECT_TRI_D_PIXEL_4_0
Definition raster-expected.h:116
#define EXPECT_TRI_A_PIXEL_2_0
Definition raster-expected.h:73
#define EXPECT_TRI_A_PIXEL_0_1
Definition raster-expected.h:76
#define EXPECT_TRI_A_PIXEL_0_3
Definition raster-expected.h:81
#define EXPECT_TRI_H_PIXEL_0_10
Definition raster-expected.h:159
#define EXPECT_TRI_E_PIXEL_0_0
Definition raster-expected.h:133
#define EXPECT_TRI_A_PIXEL_3_1
Definition raster-expected.h:78
#define EXPECT_TRI_E_PIXEL_4_0
Definition raster-expected.h:135
#define EXPECT_TRI_E_PIXEL_1_1
Definition raster-expected.h:136
#define EXPECT_TRI_E_PIXEL_2_3
Definition raster-expected.h:139
#define EXPECT_TRI_A_PIXEL_1_2
Definition raster-expected.h:79
#define EXPECT_TRI_F_PIXEL_0_0
Definition raster-expected.h:144
#define EXPECT_TRI_B_PIXEL_0_1
Definition raster-expected.h:91
#define EXPECT_TRI_A_PIXEL_0_0
Definition raster-expected.h:71
#define EXPECT_TRI_E_PIXEL_3_0
Definition raster-expected.h:134
#define EXPECT_TRI_D_PIXEL_1_1
Definition raster-expected.h:118
#define EXPECT_TRI_C_PIXEL_1020_507
Definition raster-expected.h:98
#define EXPECT_TRI_H_PIXEL_0_0
Definition raster-expected.h:157
#define EXPECT_TRI_C_PIXEL_1019_507
Definition raster-expected.h:97
#define EXPECT_TRI_A_PIXEL_4_0
Definition raster-expected.h:75
#define EXPECT_TRI_A_PIXEL_2_2
Definition raster-expected.h:80
#define EXPECT_TRI_C_PIXEL_1019_508
Definition raster-expected.h:99
#define EXPECT_TRI_D_PIXEL_3_1
Definition raster-expected.h:119
#define EXPECT_TRI_G_PIXEL_0_0
Definition raster-expected.h:151
#define EXPECT_TRI_C_PIXEL_1020_508
Definition raster-expected.h:100
#define EXPECT_TRI_I_PIXEL_1_1
Definition raster-expected.h:179
#define EXPECT_TRI_E_PIXEL_2_4
Definition raster-expected.h:140
#define EXPECT_TRI_A_PIXEL_2_1
Definition raster-expected.h:77
#define EXPECT_TRI_G_PIXEL_5_0
Definition raster-expected.h:152
#define EXPECT_TRI_A_PIXEL_0_4
Definition raster-expected.h:83
#define RASTER_CMD_BLUE
Definition raster-helpers.h:127
#define RASTER_CMD_RED
Definition raster-helpers.h:123
#define RASTER_CMD_WHITE
Definition raster-helpers.h:129
#define RASTER_CMD_GREEN
Definition raster-helpers.h:125
#define ASSERT_PIXEL_EQ(expected, x_, y_)
Definition raster-helpers.h:472