diff options
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 213 |
1 files changed, 190 insertions, 23 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 8da7abb..5aeee31 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -19279,6 +19279,16 @@ bool gsp_phys_rmcall_gr_sph_bind_value(void) * 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. + * + * Mode 5 is the driver's own viewport macro path: CALL_MME_MACRO(33) + * (0x3908) with (x,y,w,h) = (0,0,1280,720) followed by the macro's + * appended state. Mode 6 is the raw equivalent without the CALL + * (scale/offset included, scaleY = +360). Header check against the + * decoder above: 0xa0040e42 = op 5 ONE_INC, cnt 4, method 0x3908 + * (four data words follow); 0x8001064b = op 4 IMM, data 1 in the + * count field, method 0x192c (single word, consumes no data); + * 0x2001064f + 0x00021800 = op 1 INC, cnt 1, method 0x193c (one + * data word). */ #define GSP_PHYS_GR_VP_PRE_WORDS 15u static const u32 gsp_phys_gr_vp_pre[GSP_PHYS_GR_VP_PRE_WORDS] = { @@ -19292,6 +19302,25 @@ static const u32 gsp_phys_gr_vp_pre[GSP_PHYS_GR_VP_PRE_WORDS] = { 0x3f800000u, }; +#define GSP_PHYS_GR_VP_PRE_M5_WORDS 17u +static const u32 gsp_phys_gr_vp_pre_m5[GSP_PHYS_GR_VP_PRE_M5_WORDS] = { + 0xa0040e42u, 0x00000000u, 0x00000000u, 0x00000500u, 0x000002d0u, + 0x20010282u, 0x3f000000u, 0x20010285u, 0x3f000000u, + 0x20020302u, 0x00000000u, 0x3f800000u, + 0x20010649u, 0x00000000u, 0x8001064bu, + 0x2001064fu, 0x00021800u, +}; + +#define GSP_PHYS_GR_VP_PRE_M6_WORDS 19u +static const u32 gsp_phys_gr_vp_pre_m6[GSP_PHYS_GR_VP_PRE_M6_WORDS] = { + 0x20020280u, 0x44200000u, 0x43b40000u, + 0x20040282u, 0x3f000000u, 0x44200000u, 0x43b40000u, 0x3f000000u, + 0x20020300u, 0x05000000u, 0x02d00000u, + 0x20020302u, 0x00000000u, 0x3f800000u, + 0x20010649u, 0x00000000u, 0x8001064bu, + 0x2001064fu, 0x00021800u, +}; + static u32 gsp_phys_gr_vp_pre_len(int mode) { switch (mode) { @@ -19302,11 +19331,27 @@ static u32 gsp_phys_gr_vp_pre_len(int mode) case 3: case 4: return GSP_PHYS_GR_VP_PRE_WORDS; + case 5: + return GSP_PHYS_GR_VP_PRE_M5_WORDS; + case 6: + return GSP_PHYS_GR_VP_PRE_M6_WORDS; default: return 0u; } } +static const u32 *gsp_phys_gr_vp_pre_src(int mode) +{ + switch (mode) { + case 5: + return gsp_phys_gr_vp_pre_m5; + case 6: + return gsp_phys_gr_vp_pre_m6; + default: + return gsp_phys_gr_vp_pre; + } +} + /* * 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 @@ -19316,8 +19361,8 @@ static u32 gsp_phys_gr_vp_pre_len(int mode) * 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. + * without the requested run returns n so the caller can skip it + * (non-draw window). */ static u32 gsp_phys_gr_vp_insert_off(const u32 *win, u32 n, int pos) { @@ -19351,17 +19396,73 @@ static u32 gsp_phys_gr_vp_insert_off(const u32 *win, u32 n, int pos) return n; } +/* + * First-run offset of a method in a window, using the same run grammar + * as the scanners above (op 1/3/5 carry 1+cnt data words; op 5 writes + * only its header method, op 4 IMM carries data in the count field and + * is a single word). Returns n when no run touches the method. + */ +static u32 gsp_phys_gr_method_run_off(const u32 *win, u32 n, u32 method) +{ + u32 r = 0; + + 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 (m == method) + return r; + } + r += span; + } + return n; +} + +/* + * The client's pixel shader has MRT_ENABLE=0 and writes RT0 (0x800), + * while its init push selects CT target0=0 (0x121c = 0x0fac6881) and + * the replayed draw window binds only RT1 (0x840) - so the colour + * write has no enabled target. When sema_gl_rt0_bind=1 and the window + * does not write 0x800 itself, insert the missing RT0 bind (same + * 1280x720 X8R8G8B8 target at B=0x0a000000) plus a count-2 CT select + * (target0=0, target1=1) ahead of the window's first 0x840 run, and + * only when the window carries a CALL run (0x3800..0x39fc); a non-draw + * window is left unchanged. + * Constant words, no relocation. Default 0 is a strict no-op. + */ +#define GSP_PHYS_GR_RT0_BIND_WORDS 9u +static const u32 gsp_phys_gr_rt0_bind[GSP_PHYS_GR_RT0_BIND_WORDS] = { + 0x20060200u, 0x00000000u, 0x0a000000u, 0x00000500u, 0x000002d0u, + 0x000000e6u, 0x00000040u, 0x20010487u, 0x0fac6882u, +}; + +static int gsp_phys_rmcall_gr_rt0_bind; +module_param_named(sema_gl_rt0_bind, gsp_phys_rmcall_gr_rt0_bind, int, + 0644); +MODULE_PARM_DESC(sema_gl_rt0_bind, + "Insert the missing RT0 colour-target bind and count-2 SET_CT_SELECT ahead of a replayed window's first 0x840 (RT1) run when the window does not bind 0x800 and carries a CALL run (non-draw windows are left unchanged; default 0 = off)"); + 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; 4 = same clip rect with the verified pixel-unit encoding)"); + "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; 5 = driver viewport macro CALL(33) 0x3908 + appended state; 6 = raw mode-5 state without the CALL)"); 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)"); + "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); pos 1/2 leave a window without the requested run unchanged (non-draw window), only 0 inserts without a CALL run)"); /* * CONT-119 (r1450): the BINDING words of the synthesized stage-2/5 @@ -28647,38 +28748,39 @@ gr_page_unmapped: * 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. + * requested run is left unchanged (non-draw window); only + * pos 0 inserts at the head without a CALL run. 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); + const u32 *vp_src = gsp_phys_gr_vp_pre_src(vp_mode); - if (vpn) { + if (vpn && vp_src) { u32 vp_at = 0; + bool vp_skip = false; 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); + static bool vp_nd_log; + + vp_skip = true; + if (!vp_nd_log) { + vp_nd_log = true; + pr_info("vgsp-gr: VP-PRELUDE skipped (no CALL run; non-draw window) window=%u pos=%d mode=%d\n", + win3d_n, vp_pos, + vp_mode); } } } - if (win3d_n + vpn + 2u + 8u <= + if (!vp_skip && + win3d_n + vpn + 2u + 8u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) { static u32 vp_emit_log; u32 vp_old = win3d_n; @@ -28688,7 +28790,7 @@ gr_page_unmapped: (size_t)(win3d_n - vp_at) * 4u); memcpy(&stream_patch[vp_at], - gsp_phys_gr_vp_pre, + vp_src, (size_t)vpn * 4u); win3d_n += vpn; if (vp_emit_log < 16u) { @@ -28698,7 +28800,7 @@ gr_page_unmapped: vp_old, win3d_n, vp_at); } - } else { + } else if (!vp_skip) { static u32 vp_skip_log; if (vp_skip_log < 8u) { @@ -28712,6 +28814,71 @@ gr_page_unmapped: } } /* + * Missing RT0 bind (see the sema_gl_rt0_bind comment). + * Insert the RT0 colour-target run and the count-2 CT + * select ahead of the window's first 0x840 (RT1) run. + * Skip when the window binds 0x800 itself; skip when it + * has no 0x840 anchor. Same run grammar and block-size + * guard as the viewport prelude; constant words, no + * relocation pass. + */ + if (READ_ONCE(gsp_phys_rmcall_gr_rt0_bind)) { + static u32 rt0_emit_log; + static u32 rt0_skip_log; + static bool rt0_nd_log; + u32 rt0_at = gsp_phys_gr_method_run_off( + stream_patch, win3d_n, 0x840u); + u32 rt0_have = gsp_phys_gr_method_run_off( + stream_patch, win3d_n, 0x800u); + u32 rt0_call = gsp_phys_gr_vp_insert_off( + stream_patch, win3d_n, 1); + + if (rt0_call >= win3d_n) { + if (!rt0_nd_log) { + rt0_nd_log = true; + pr_info("vgsp-gr: RT0-BIND skipped (non-draw window) window=%u\n", + win3d_n); + } + } else if (rt0_have < win3d_n) { + if (rt0_skip_log < 8u) { + rt0_skip_log++; + pr_info("vgsp-gr: RT0-BIND skipped (window already binds 0x800) window=%u at=%u\n", + win3d_n, rt0_at); + } + } else if (rt0_at >= win3d_n) { + if (rt0_skip_log < 8u) { + rt0_skip_log++; + pr_info("vgsp-gr: RT0-BIND skipped (no 0x840 run) window=%u\n", + win3d_n); + } + } else if (win3d_n + GSP_PHYS_GR_RT0_BIND_WORDS + + 2u + 8u <= + GSP_PHYS_RMCALL_GR_METHOD_WORDS) { + u32 rt0_old = win3d_n; + + memmove(&stream_patch[rt0_at + + GSP_PHYS_GR_RT0_BIND_WORDS], + &stream_patch[rt0_at], + (size_t)(win3d_n - rt0_at) * 4u); + memcpy(&stream_patch[rt0_at], + gsp_phys_gr_rt0_bind, + sizeof(gsp_phys_gr_rt0_bind)); + win3d_n += GSP_PHYS_GR_RT0_BIND_WORDS; + if (rt0_emit_log < 16u) { + rt0_emit_log++; + pr_info("vgsp-gr: RT0-BIND emitted window=%u->%u at=%u\n", + rt0_old, win3d_n, rt0_at); + } + } else { + if (rt0_skip_log < 8u) { + rt0_skip_log++; + pr_info("vgsp-gr: RT0-BIND skipped (no room) window=%u cap=%u\n", + win3d_n, + GSP_PHYS_RMCALL_GR_METHOD_WORDS); + } + } + } + /* * SESSION 153-CONTINUED-57: patch the attr/pipeline prelude for * this launch (relocation exactly like the window: the * SET_PIPELINE_PROGRAM_ADDRESS pairs and any other recognised |
