From 1f08cc93b514f7267a1c536a2e61b7ff3afe84a5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 4 Nov 2026 19:22:26 -0500 Subject: vgsp-gr: sema_gl_vp_prelude_pos - insert the synthesized viewport before the first CALL run (default 1) so the 0x2080 SET_PIPELINE bind lands first, or before the first 0x3910 (pos 2); mode 4 = clip rect with the verified (size<<16)|origin pixel encoding; r1462: 3 DRAWs executed with pos=1 VP and still zero RT stores --- kernel/gsp_phys_booter.c | 125 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 20 deletions(-) diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 4903d5d..8da7abb 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -19270,9 +19270,15 @@ bool gsp_phys_rmcall_gr_sph_bind_value(void) * 0x20040300 INC cnt=4 method 0x0c00 -> SET_VIEWPORT_CLIP_ * HORIZONTAL/VERTICAL/MIN_Z/MAX_Z(0) * Mode 1 = scale/offset block; mode 2 adds the immediate controls; - * mode 3 adds the 1280x720 clip rect. None of the words is an - * address operand, so the sequence is emitted verbatim (no - * relocation pass). Default 0 keeps the legacy window bytes. + * mode 3 adds the 1280x720 clip rect. Mode 4 is the same words with + * the clip-rect encoding verified against the class definitions + * (X0/Y0 in bits 15:0, WIDTH/HEIGHT in bits 31:16, integer pixel + * units) and the producer's (size << 16) | origin packing, so a + * 1280x720 target at a top-left origin emits 0x05000000, + * 0x02d00000, 0.0f (0x00000000) and 1.0f (0x3f800000); min_z/max_z + * are IEEE-754 floats. None of the words is an address operand, so + * the sequence is emitted verbatim (no relocation pass). Default 0 + * keeps the legacy window bytes. */ #define GSP_PHYS_GR_VP_PRE_WORDS 15u static const u32 gsp_phys_gr_vp_pre[GSP_PHYS_GR_VP_PRE_WORDS] = { @@ -19294,17 +19300,68 @@ static u32 gsp_phys_gr_vp_pre_len(int mode) case 2: return 10u; case 3: + case 4: return GSP_PHYS_GR_VP_PRE_WORDS; default: return 0u; } } +/* + * Insertion word offset for the viewport prelude inside an emitted 3D + * window. The walk is the same run grammar as the MME-WINRUN census and + * the CALL drop pass (op = hdr[31:29], count = hdr[28:16] for op 1/3/5, + * run method = hdr[11:0] << 2; multi-word INC/NON_INCR runs cover + * m + 4k, IMM/ONE_INCR entries cover only their own method). Runs are + * never split. pos 1 stops at the first run touching the CALL_MME + * family 0x3800..0x39fc (after the window's state binds, ahead of its + * macro calls); pos 2 stops at the first run touching 0x3910. A window + * without the requested run returns n so the caller falls back to the + * head. + */ +static u32 gsp_phys_gr_vp_insert_off(const u32 *win, u32 n, int pos) +{ + u32 r = 0; + + if (pos != 1 && pos != 2) + return n; + while (r < n) { + u32 h = win[r]; + u32 op = (h >> 29) & 7u; + u32 cnt = (h >> 16) & 0x1fffu; + u32 span = 1u, k; + + if ((op == 1u || op == 3u || op == 5u) && cnt && + r + 1u + cnt <= n) + span = 1u + cnt; + for (k = 0; k < span; k++) { + u32 m = ((h & 0xfffu) << 2) + 4u * k; + + if (k && op != 1u && op != 3u) + break; + if (pos == 1) { + if (m >= 0x3800u && m <= 0x39fcu) + return r; + } else if (m == 0x3910u) { + return r; + } + } + r += span; + } + return n; +} + static int gsp_phys_rmcall_gr_vp_prelude; module_param_named(sema_gl_vp_prelude, gsp_phys_rmcall_gr_vp_prelude, int, 0644); MODULE_PARM_DESC(sema_gl_vp_prelude, - "Synthesize the missing viewport state ahead of replayed 3D windows (0 = off (default); 1 = scale/offset; 2 = + pixel centre and clip control; 3 = + clip rect)"); + "Synthesize the missing viewport state ahead of replayed 3D windows (0 = off (default); 1 = scale/offset; 2 = + pixel centre and clip control; 3 = + clip rect; 4 = same clip rect with the verified pixel-unit encoding)"); + +static int gsp_phys_rmcall_gr_vp_prelude_pos = 1; +module_param_named(sema_gl_vp_prelude_pos, gsp_phys_rmcall_gr_vp_prelude_pos, + int, 0644); +MODULE_PARM_DESC(sema_gl_vp_prelude_pos, + "Insertion point of the synthesized viewport prelude in a replayed 3D window (0 = window head (legacy); 1 = before the first CALL run 0x3800..0x39fc, after the state binds (default); 2 = before the first 0x3910 run); falls back to the head when no such run exists)"); /* * CONT-119 (r1450): the BINDING words of the synthesized stage-2/5 @@ -28583,44 +28640,72 @@ gr_page_unmapped: } /* * SESSION 154c: synthesized viewport preamble (see the - * sema_gl_vp_prelude comment). Prepend the chosen literal - * sequence at the head of the final window so it precedes - * the window's first 0x840 (SET_COLOR_TARGET) run and the - * FE decodes it in the same window-carrier context. The - * words carry no address operand, so no relocation pass is - * applied - they are emitted verbatim. Same head-insertion - * path and block-size guard as SPH-BIND / SURF-PRELUDE. + * sema_gl_vp_prelude comment). Insert the chosen literal + * sequence at sema_gl_vp_prelude_pos: the window head + * (legacy), immediately ahead of the first CALL run + * (0x3800..0x39fc) so every state bind - including the + * 0x2080 SET_PIPELINE(2)=0x21 run - has landed before the + * macro calls, or ahead of the first 0x3910 run. The scan + * uses the MME-WINRUN run grammar; a window without the + * requested run falls back to the head. The words carry no + * address operand, so no relocation pass is applied - they + * are emitted verbatim. Same block-size guard as SPH-BIND / + * SURF-PRELUDE. */ { int vp_mode = READ_ONCE(gsp_phys_rmcall_gr_vp_prelude); + int vp_pos = READ_ONCE(gsp_phys_rmcall_gr_vp_prelude_pos); u32 vpn = gsp_phys_gr_vp_pre_len(vp_mode); if (vpn) { + u32 vp_at = 0; + + if (vp_pos == 1 || vp_pos == 2) { + vp_at = gsp_phys_gr_vp_insert_off( + stream_patch, win3d_n, vp_pos); + if (vp_at >= win3d_n) { + static bool vp_fb_log; + + vp_at = 0; + if (!vp_fb_log) { + vp_fb_log = true; + pr_info("vgsp-gr: VP-PRELUDE pos=%d found no %s run; fallback to head (window=%u mode=%d)\n", + vp_pos, + vp_pos == 2 ? + "0x3910" : + "CALL", + win3d_n, vp_mode); + } + } + } if (win3d_n + vpn + 2u + 8u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) { static u32 vp_emit_log; u32 vp_old = win3d_n; - memmove(&stream_patch[vpn], - stream_patch, - (size_t)win3d_n * 4u); - memcpy(stream_patch, + memmove(&stream_patch[vp_at + vpn], + &stream_patch[vp_at], + (size_t)(win3d_n - vp_at) * + 4u); + memcpy(&stream_patch[vp_at], gsp_phys_gr_vp_pre, (size_t)vpn * 4u); win3d_n += vpn; if (vp_emit_log < 16u) { vp_emit_log++; - pr_info("vgsp-gr: VP-PRELUDE mode=%d words=%u window=%u->%u\n", - vp_mode, vpn, vp_old, - win3d_n); + pr_info("vgsp-gr: VP-PRELUDE mode=%d pos=%d words=%u window=%u->%u at=%u\n", + vp_mode, vp_pos, vpn, + vp_old, win3d_n, + vp_at); } } else { static u32 vp_skip_log; if (vp_skip_log < 8u) { vp_skip_log++; - pr_info("vgsp-gr: VP-PRELUDE skipped (no room) mode=%d words=%u window=%u cap=%u\n", - vp_mode, vpn, win3d_n, + pr_info("vgsp-gr: VP-PRELUDE skipped (no room) mode=%d pos=%d words=%u window=%u cap=%u\n", + vp_mode, vp_pos, vpn, + win3d_n, GSP_PHYS_RMCALL_GR_METHOD_WORDS); } } -- cgit v1.2.3