T-505: the cause proven, the card measured; the card's frame wrapped without alpha

The owner's sequence: a Codex adversarial review (context/impl/impl-review-findings-t505-codex.md), then
"prove the cause first": JIHAD_GPU_NO_PUBLISH=1 (a diagnostic: frames made and read, never handed to the
card) shows the same daemon work making desktop Wikipedia 32 fps and the long page 53 while LunaSysMgr draws
nothing, 8.6 / 13.6 while the card moves: the card's redraw on the shared GPU and memory makes every daemon
stage ~3x slower. Then the card's paint measured (the adapter's [paint-stat] lines under its paint log): a
~10 ms software blit (Piranha's PSoftContext2D) of the whole view ~20 times a second, mostly repaints; a
PGSurface kept per frame changed nothing (not kept). The frame is now wrapped without alpha (every path
writes alpha 255): the blit 9 -> 5 ms, LunaSysMgr's card instance -15 % CPU while panning, the picture the
same; <state>/alphawrap reverts. The pan rate is unchanged; the owner's plan is the CPU/GPU split next.
tools/host/express-jobs.py also reads scripted pans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtfxSpM1w2uiVKeLKoV3g3
This commit is contained in:
NotAlexNoyleandClaude Opus 5.5 committed 2026-10-26 11:52:33 -04:00
1 parent a507ee867c
commit 554ed514dc
39 files changed
+49885 -10

No files matched your search

@@ -0,0 +1,97 @@
# Review findings — T-505 adversarial review by Codex (2026-10-26)
Asked by the owner after the read-only measurement ("Do an adversarial review with codex to find a way to get the fps up"). Codex CLI 0.164, gpt-5.6-sol, read-only, run directly (`codex exec`), prompt: the system, R3, the measurement (`docs/rounds/t505-2026-10-26/`), the dead ends, the constraints. Its report follows verbatim; the checks made against the source after it are at the end.
## Ranked proposals
### 1. Make frame windows work with fixed/sticky content
**Evidence:** Frame windows were designed to avoid the 3.7 MB cross-slot copy ([JihadFrameWindow.h:12](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/browserserver/Src/JihadFrameWindow.h:12)), but same-slot reuse is explicitly rejected when fixed/sticky content exists ([BrowserPageGoanna.cpp:4657](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/goanna/BrowserPageGoanna.cpp:4657), [BrowserPageGoanna.cpp:5205](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/goanna/BrowserPageGoanna.cpp:5205)). Consequently, `JihadShiftRows` still copies nearly the entire base ([CompositorOGL.cpp:2183](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/third_party/uxp/gfx/layers/opengl/CompositorOGL.cpp:2183)).
**Change:** Store fixed/sticky generation, rectangles, and keep metadata per slot. When reusing an older same slot, move its frame window and force the union of its old and current fixed/sticky rectangles into the correction reads. Permit opaque keeps only when that slot’s recorded generation matches. This is materially different from the incorrect “own-slot lane” dead end: the compositor knows exactly how old the reused base is.
**Expected gain:** Removing median copy time gives optimistic bounds:
- Wikipedia: `9.5 × 64/(64−16) = 12.7 fps`
- Long page: `16.6 × 30/(30−13) = 29.3 fps`
**Measure:** Require zero verify-mode errors on Wikipedia plus `fixed-both` and `sticky-mix`; confirm cross-slot `shift` falls near zero and compare displayed adapter sequence numbers, not merely daemon publications.
**Risk:** Moderate correctness risk around accumulated stale sticky regions; moderate implementation effort.
### 2. Send delta frames to the adapter instead of reconstructed full frames
**Evidence:** The daemon reconstructs every complete frame, then the adapter wraps and blits the complete shared-memory surface ([BrowserAdapter.cpp:1267](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/adapter/BrowserAdapter.cpp:1267), [BrowserAdapter.cpp:1325](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/adapter/BrowserAdapter.cpp:1325)). Partial invalidation is rejected whenever scroll geometry changes ([BrowserAdapter.cpp:4346](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/adapter/BrowserAdapter.cpp:4346)), and every touch-scroll calls full `invalidate()` ([BrowserAdapter.cpp:6307](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/adapter/BrowserAdapter.cpp:6307)). The documented card upload is about 2.9 MB/frame ([RENDERING-OPTIONS.md:135](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/RENDERING-OPTIONS.md:135)).
**Change:** Extend the existing trailer with patch rectangles and scroll displacement. Send only newly exposed bands/sidebar corrections; have the adapter scroll its retained surface and blit patches. Preserve a full-frame fallback without changing YAP message framing.
**Expected gain:** Copy removal alone gives 12.7/29.3 fps as above. If full card uploads cause even 24 ms of Wikipedia’s current 36 ms read stall, the upper bound becomes `9.5 × 64/(64−16−24) = 25.3 fps`. Thus the defensible range is approximately **12.7–25.3 Wikipedia, 29.3 long-page**.
**Measure:** Log bytes blitted, adapter paint/present sequence IDs, and card paint duration. Run identical drags with full-frame versus delta mode and verify every presented frame.
**Risk:** High: adapter bugs can crash LunaSysMgr; PGSurface may internally re-upload more than the requested rectangle; translucent sticky patches require exact ordering.
### 3. Pipeline band readback with the next compose
**Evidence:** The active band path deliberately disables the read thread ([CompositorBridgeParent.cpp:2031](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/third_party/uxp/gfx/layers/ipc/CompositorBridgeParent.cpp:2031)) and performs shift plus `glReadPixels` serially on the compositor thread ([CompositorBridgeParent.cpp:2129](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/third_party/uxp/gfx/layers/ipc/CompositorBridgeParent.cpp:2129)). Express refuses another job while one is composed ([BrowserPageGoanna.cpp:5006](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/render/goanna/BrowserPageGoanna.cpp:5006)).
**Change:** Double-buffer the short/tall band renderbuffers. Fence band N, let the read context wait/read it, and immediately compose band N+1 into the other target. Keep three output slots initially; “no slot” is rare, so a fourth segment is not the first lever.
**Expected gain:** Ideal throughput becomes the slower of read and remaining work:
- Wikipedia: `max(36, 14+16)=36 ms` → `9.5×64/36 = 16.9 fps`
- Long: `max(11, 3+13)=16 ms` → `16.6×30/16 = 31.1 fps`
Previous asynchronous-read experiments found no gain ([RENDERING-OPTIONS.md:166](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/RENDERING-OPTIONS.md:166)); therefore this deserves a small A/B prototype before architectural work.
**Measure:** Prove overlap from timestamps: compose N+1 must begin before read N completes. Compare GPU wait, job cadence, and displayed cadence.
**Risk:** Driver-wide GL serialization may make the gain zero; additional surfaces consume roughly 1–3 MB.
### 4. Cache sidebar foreground, not final sidebar pixels
**Evidence:** Wikipedia repeatedly reads extra column chunks: one sampled frame reads 68 band rows plus three column reads ([fp-wiki1-daemon-gpu.log:1238](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/rounds/t505-2026-10-26/fp-wiki1-daemon-gpu.log:1238)); another has 442 column rows ([fp-wiki1-daemon-gpu.log:1571](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/rounds/t505-2026-10-26/fp-wiki1-daemon-gpu.log:1571)). Keeping final translucent pixels failed because underlying content changes.
**Change:** Cache the sidebar layer subtree as premultiplied foreground plus alpha, shift/read the underlying page normally, then CPU-blend the cached foreground over it. Refresh only when the sidebar’s own layer generation changes. Restrict eligibility to axis-aligned layers without masks or filters.
**Expected gain:** Using long-page compose cost as the sidebar-free approximation: `3 compose + 16 copy + ~18 read/blend = 37 ms`; Wikipedia upper bound `9.5×64/37 = 16.4 fps`. Long page: unchanged.
**Measure:** Count cache refreshes and column bytes; compare against a diagnostic “no sidebar correction” run while verify mode checks final pixels.
**Risk:** High correctness and engineering risk; selection/highlight changes may invalidate the cache frequently.
### 5. Remove band-surface switching from the critical path
**Evidence:** Surface acquisition reaches 24 ms in [fp-wiki1-daemon-gpu.log:1223](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/rounds/t505-2026-10-26/fp-wiki1-daemon-gpu.log:1223) and 22.5 ms in [fp-wiki1-daemon-gpu.log:2163](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/rounds/t505-2026-10-26/fp-wiki1-daemon-gpu.log:2163). Switching calls forced `eglMakeCurrent` when the target differs ([GLContextProviderEGL.cpp:378](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/third_party/uxp/gfx/gl/GLContextProviderEGL.cpp:378)).
**Change:** Give band composition a permanently-current shared context/surface rather than alternating frame and band pbuffers.
**Expected gain:** Median gain is probably negligible, but removing the complete p90 surface cost bounds Wikipedia’s 123 ms tail near 100.5 ms and long-page 49 ms near 38.2 ms. Expect under 5% average FPS unless these stalls cluster.
**Risk:** Shared-context synchronization and Adreno driver stability.
### 6. CE-only zero-copy presentation
Option 6 removes readback, base reconstruction, and card upload together ([RENDERING-OPTIONS.md:326](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/docs/RENDERING-OPTIONS.md:326)). At the document’s 17 ms projected path, observed-rate scaling gives **35.8 Wikipedia and 29.3 long-page fps**. This is the most credible route comfortably past R3, but ranks last per effort: approximately five weeks, CE-specific, unknown buffer-sharing API, and no stock solution.
RGB565 is not acceptable under R2 because it changes pixels. PBOs are not a solution merely by name: source initialization is conditional on a pixel-buffer extension ([GLContext.cpp:896](/home/notalexnoyle/eclipse-workspace/Jihad/Jihad-Browser/third_party/uxp/gfx/gl/GLContext.cpp:896)), and mapping would simply move the stall unless used as a fenced ring. Probe extensions and native read format before investing.
## Claims that are wrong or unproven
- **“LunaSysMgr redraw causes the GPU wait” is not proven.** `glReadPixels` synchronizes the daemon’s own compose, surface switch, and queued uploads too. Tiny reads sometimes take tens of milliseconds, but there are no Luna paint timestamps or GPU queue counters establishing ownership. Run the same invalidation stream with card GPU painting suppressed or replaced by a CPU-only diagnostic surface.
- **“Read time” is not pure transfer time.** It includes waiting for all prior GPU work. Calling it readback bandwidth overstates what smaller reads can fix.
- **Aggregate CPU idle does not prove a GPU bottleneck.** A serialized 13–16 ms compositor-thread memcpy can coexist with 25% total idle. The failed worker-copy experiment shows that relocation did not help; it does not show that eliminating the copy cannot help.
- **Tile transactions are understated.** Wikipedia spends 1.24 seconds of compositor time processing them, about `1240/150 = 8.3 ms` per published frame. Median queue delay is small, but the 54 ms p90 means transactions plausibly explain important tails.
- **“While frames flow” FPS is not the requirement’s displayed FPS.** The parser counts daemon output over selected windows; it does not prove the card presented every sequence. Instrument `msgPainted` through adapter paint completion and report continuous time-under-finger, dropped publications, and inter-present percentiles.
- **The sampled medians are fragile.** Band phase logging samples only a subset of frames, while Wikipedia is highly variable. Report full-distribution per-frame phases or increase sampling before treating 64/30 ms as stable causal decompositions.
## Checked against the source (Claude, 2026-10-26)
- Proposal 1 confirmed: the express lane builds on the slot's own frame (frame window moved, no copy) only with no fixed or stuck layers then or in the slot's frame (`render/goanna/BrowserPageGoanna.cpp`, the `own` rule in `xStart`; the main lane's `ownWin` likewise). Both test pages have them (desktop Wikipedia's sidebars, the long page's fixed header: its band frames say "1 kept"), so every pan frame copies from the base: the 13-16 ms "shift". In the logs the own-slot lane ran 9 times on Wikipedia, 0 on the long page.
- Proposal 3 confirmed: the band pass reads on the compositor thread unless `JIHAD_GPU_READ_THREAD` is set (`CompositorBridgeParent.cpp`, the band-pass condition), so a band frame's read is serial with the next compose.
- Dispositions: the owner's to choose (asked as multiple choice).
+1 -1
View File
@@ -569,7 +569,7 @@ the mid-pan dumps, never by a screenshot. No device run while the owner is at th
| T-502 | The spike and the compositor-side scroll (rounds 1-137): patches 0040/0041/0042, the daemon's job pipeline, band reads on the band surface, the displayport, fixed/sticky rows, the composition fix for wide pages | cavekit-gpu-rendering.md | R2, R3 (part) | — | yes | L | DONE (commits through `bc4a8eaf`/`b30b9989`: test pan 27-34 fps, animation 26-31, HN 36-37, desktop Wikipedia 13-14 vs software 9-12.4) |
| T-503 | Fixed and sticky at minimum cost: opaque stuck layers kept (per opaque rect, the visible region's gaps), others read as columns, fixed header + footer as two bands; the draw-culling fix kept; verify and dumps on the long-static page, a header+footer page and desktop Wikipedia | cavekit-gpu-rendering.md | R4, R2 | T-502 | yes | M | DONE 2026-10-18 (rounds 138-150): opaque fixed/stuck layers kept per covered rect, the rest read as column chunks packed on the band surface, header + footer as two bands; the draw culling fixed; a sticky layer the engine laid out stuck counted (probed sticky ranges); the root composition covers what the card shows (Hacker News' blank bottom strip); verify made side-effect free with a structural test: 0 structurally wrong rows on the test page, `jihad-sticky-mix.html`, desktop Wikipedia and Hacker News. Pans: test page 27-34 fps, sticky-mix 15-17.5 (software 0.9-3.1), Wikipedia 16.4-18.5 (was 13-14; software 9-12.4), Hacker News 34-37.5, animation 24-32 |
| T-504 | Zoom keeps up: a scripted pinch and double-tap on Wikipedia and the test page with the frame timeline; first frame at the new zoom ≤ 250 ms; no grey at rest; tile uploads off the GPU's queue | cavekit-gpu-rendering.md | R6 | T-502 | yes | L | DONE 2026-10-26 (the owner's bounded overview: right after a zoom in the daemon composes a half-resolution picture of the page around the zoom-in point — the kept frame's rows and a frame's above and below, the scrolled content alone, rows no tile covered left out (engine 0069) — while the old tiles are still in the tree, and at a double tap out after a pan draws the card's view from it at twice its size with the fixed and stuck parts where they sit at the new position. The fixed and stuck parts are composed alone with their alpha and drawn over it where they sit at the new position. By finger on desktop Wikipedia (to 2.33, one or seven drags, back): the first frame 40-56 ms where the paint's came at 294-614 ms; frames looked at against the painted one, also on a page with a see-through fixed header and sticky sidebar; a pan past the picture still waits (the owner's bound, no black frame). An inspector review's six findings fixed (the readback's forced alpha, the parts' stale background, the probe, the scratch). Memory 1.8-2.8 MB and ~0.5 MB of parts beside the kept frame's 3.7; 7.5-9.4 MB of scratch for ~0.5 s. Cost: the zoom in's sharp frame later (682-779 ms against 519-545). `docs/rounds/t504-2026-10-26/notes.txt`) — earlier: IN PROGRESS 2026-10-26 (the owner: a bounded overview — a half-resolution picture of a few screens around the zoom-in point, ~4-8 MB per card) — earlier: PARTIAL 2026-10-18 (rounds 162-186: the zoom hold; the grey strip of a zoomed-in settle fixed; engine 0044 (tile textures converted at 1x1 and pooled: the Adreno's first write after a draw) and 0045 (no DEAA for axis-aligned scales: shader compiles in a zoom's first frame); the layers painted at the zoom's resolution above 1.1; double taps scripted (`t`), `JIHAD_GPU_ZOOM_DUMP`. Met: the scripted pinches and double taps with the timeline, the card covered at rest (dumps), uploads that do not wait, sharp zoomed text. Open: the first frame within 250 ms while the page's script holds the main thread (0.8-1.7 s on Wikipedia after its load) and one double tap in ten at ~400 ms: frames made off the main thread, with T-505); 2026-10-19, T-515: the zoom under script met (Wikipedia after load 10/10 within 225 ms); the double taps' slow ones are GPU draws: T-516; 2026-10-19 (rounds 334-341, `docs/rounds/t502-2026-10-17/dtap-r334-341.txt`): scripted double taps 2 of 18 over 250 ms (286, 367), the second core unplugged after an idle pause; the scripted tap skips the touch path's governor ramp, so a finger's tap is for T-514; a zoom's express frame now gives up uncomposed main-lane frames at the old zoom. Task token budget spent (the plugin's 45k): left PARTIAL for the owner) |
| T-505 | Real-page pans to the chart: desktop Wikipedia ≥ 24 fps; the 56 ms+ gaps traced (the main loop uncapped) and the avoidable ones removed; the per-page table against `NOGPU=1` | cavekit-gpu-rendering.md | R3 | T-503 | yes | L | IN PROGRESS 2026-10-26 (measured read-only, the owner's "measure first": under eight finger drags desktop Wikipedia 9.5 fps and the long page 16.6 while frames flow; a frame is bound by the readback path on the GPU shared with LunaSysMgr's redraw of the card — Wikipedia's band frames 64 ms median: the read's GPU wait 36, the copy from the base 16, the compose 14, its sticky sidebars read as columns doubling the read; the long page's 30 ms with 11 / 13 / 3; the long gaps are the job's GPU waits, none the main thread's; `docs/rounds/t505-2026-10-26/notes.txt`. The proposal is the owner's to choose) — earlier: IN PROGRESS 2026-10-26 (R3 re-opened against the corrected test, the owner's choice: the scripted pan never moved the card, so its 24 fps left out the card's own redraw; with the card moving desktop Wikipedia pans at ~7 fps under a finger and by the corrected scripted pan, the long page ~19 — the readback waits behind LunaSysMgr's redraw of the card on the same Adreno. Measured and not kept: the express thread's copy from the base (no gain), the card's scroll redraw coalesced to one in 33 or 50 ms (no gain, WebAppMgr's CPU unchanged). Earlier the same day: the owner: prototype the card shifting the frame it holds, the daemon sending only the new rows and the shift, behind a switch until measured; meanwhile desktop Wikipedia's pan is 24.0 fps with the sensors running since the second core comes up for a pan, T-516) — earlier: PARTIAL 2026-10-18 (rounds 187-201: the per-page table against `NOGPU=1` (the GPU path ahead on every page: the test page 30-35 against 2.7-3.2 fps, sticky-mix 17-19 against 2.4-3.1, desktop Wikipedia 19-26 against 2.7-2.9, Hacker News 31-37 against 6.4-10.4; the software path pans inside its painted region and publishes few frames); the 56 ms+ gaps traced to the page's restyle, the displayport moves' paints and misc events (stall sampler); overscan, 0.15 of the height above and below the view (engine 0046): grey-free pans, verify clean on four pages, at 10% of the rate (Wikipedia 16.5-24, the test page 25-32). Open: Wikipedia ≥ 24 fps, which needs the frames made off the main thread (T-515)); 2026-10-19, T-515: the main thread's stalls covered (19-21 fps, median gap 45 ms); the rest is the compositor thread's ~45 ms a Wikipedia frame: T-517; 2026-10-19 evening (rounds 349-357): the 10 s pan 23.2-24.1 fps; the page's tile uploads, partial uploads, deferred uploads, a topped-up pool and the express lane on its own slot measured and not kept; the band frame is GPU-bound (r357). BLOCKED by the circuit breaker: the owner's finger round (T-514) and the bench's sensord load (the owner's call) decide) |
| T-505 | Real-page pans to the chart: desktop Wikipedia ≥ 24 fps; the 56 ms+ gaps traced (the main loop uncapped) and the avoidable ones removed; the per-page table against `NOGPU=1` | cavekit-gpu-rendering.md | R3 | T-503 | yes | L | IN PROGRESS 2026-10-26 (the cause proven and the card measured, the owner's "prove the cause first" and "measure first": the same daemon work makes desktop Wikipedia 32 fps and the long page 53 with LunaSysMgr drawing nothing, 8.6 / 13.6 with the card moving — the card's redraw on the shared GPU and memory makes every daemon stage ~3x slower (`JIHAD_GPU_NO_PUBLISH=1`, a diagnostic). The card's paint is Piranha's SOFTWARE blit (~10 ms, ~20 a second, most of them repaints); a surface kept per frame changed nothing; the frame wrapped without alpha halves the blit and cuts LunaSysMgr's CPU 15 % (shipped, `<state>/alphawrap` reverts) but not the pan rate. Codex's adversarial review: `context/impl/impl-review-findings-t505-codex.md`. The owner's plan, after "consider sharing tasks across the CPU and GPU": (1) pan frames composed on the GPU as the scrolled content alone and the fixed/sticky parts blended on the CPU, then (2) scroll-only bands composed on the CPU from the tiles, each behind a switch, measured by finger; `docs/rounds/t505-2026-10-26/notes.txt`) — earlier the same day, measured read-only, the owner's "measure first": under eight finger drags desktop Wikipedia 9.5 fps and the long page 16.6 while frames flow; a frame is bound by the readback path on the GPU shared with LunaSysMgr's redraw of the card — Wikipedia's band frames 64 ms median: the read's GPU wait 36, the copy from the base 16, the compose 14, its sticky sidebars read as columns doubling the read; the long page's 30 ms with 11 / 13 / 3; the long gaps are the job's GPU waits, none the main thread's; `docs/rounds/t505-2026-10-26/notes.txt`. The proposal is the owner's to choose) — earlier: IN PROGRESS 2026-10-26 (R3 re-opened against the corrected test, the owner's choice: the scripted pan never moved the card, so its 24 fps left out the card's own redraw; with the card moving desktop Wikipedia pans at ~7 fps under a finger and by the corrected scripted pan, the long page ~19 — the readback waits behind LunaSysMgr's redraw of the card on the same Adreno. Measured and not kept: the express thread's copy from the base (no gain), the card's scroll redraw coalesced to one in 33 or 50 ms (no gain, WebAppMgr's CPU unchanged). Earlier the same day: the owner: prototype the card shifting the frame it holds, the daemon sending only the new rows and the shift, behind a switch until measured; meanwhile desktop Wikipedia's pan is 24.0 fps with the sensors running since the second core comes up for a pan, T-516) — earlier: PARTIAL 2026-10-18 (rounds 187-201: the per-page table against `NOGPU=1` (the GPU path ahead on every page: the test page 30-35 against 2.7-3.2 fps, sticky-mix 17-19 against 2.4-3.1, desktop Wikipedia 19-26 against 2.7-2.9, Hacker News 31-37 against 6.4-10.4; the software path pans inside its painted region and publishes few frames); the 56 ms+ gaps traced to the page's restyle, the displayport moves' paints and misc events (stall sampler); overscan, 0.15 of the height above and below the view (engine 0046): grey-free pans, verify clean on four pages, at 10% of the rate (Wikipedia 16.5-24, the test page 25-32). Open: Wikipedia ≥ 24 fps, which needs the frames made off the main thread (T-515)); 2026-10-19, T-515: the main thread's stalls covered (19-21 fps, median gap 45 ms); the rest is the compositor thread's ~45 ms a Wikipedia frame: T-517; 2026-10-19 evening (rounds 349-357): the 10 s pan 23.2-24.1 fps; the page's tile uploads, partial uploads, deferred uploads, a topped-up pool and the express lane on its own slot measured and not kept; the band frame is GPU-bound (r357). BLOCKED by the circuit breaker: the owner's finger round (T-514) and the bench's sensord load (the owner's call) decide) |
| T-506 | Animation, new content and self-scroll measured against the chart (DOM edit and typing ≤ 106 ms) | cavekit-gpu-rendering.md | R5 | T-502 | yes | S | DONE 2026-10-18 (rounds 202-203: the animation page 26-31 fps reading only its changed rows; typing 22-62 ms and DOM edits 26-70 ms from the input to the first published frame with changed rows (an input-latency probe on the inject channel); the self-scrolling page followed at 10.7-13.9 fps) |
| T-507 | Every other card event on the GPU path: rotation, resize, select popups, caret, link and find highlights, thumbnails, navigation without stale frames | cavekit-gpu-rendering.md | R9 | T-502 | yes | M | DONE 2026-10-18 (rounds 204-212 on `jihad-card-events.html`: rotation to landscape and back, the keyboard's resize, the select list and pick, the caret, find-in-page, link navigation with back, forward and reload, the thumbnail; the thumbnail's view row and the popups' origin corrected for overscan; the test hook gains `<`, `>`, `R`, `O<orientation>`; the inject channel `thumb <path>`) |
| T-508 | Video and Flash on the GPU path: `<video>` (VP8, Theora, H.264) to the end, styled video (rounded, fade, under a modal), Flash draw/animate/input | cavekit-gpu-rendering.md | R7 | T-502 | yes | L | DONE 2026-10-19 (rounds 213-228: VP8, Theora, VP9 and H.264 to the end on the GPU path, at the clips' rates; styled video (rounded, fade, modal); Flash draws, animates and takes keys; `push-engine-update.sh` now carries FFmpeg's libavcodec/libavutil, which a device updated by it lacked (H.264, AAC and MP3 were refused on both paths); new pages `jihad-video-styled.html`, `jihad-anim-opacity.html`, `jihad-canplay.html`) |
+14 -1
View File
@@ -81,7 +81,20 @@ own criterion. Round tools: `tools/device/t502/zoom-pan.sh` (`PRE=<n>` drags at
long page 16.6. A frame is bound by the readback path on the GPU shared with LunaSysMgr's redraw: Wikipedia's band
frames 64 ms median (the read's GPU wait 36, the copy from the base 16, the compose 14; its sticky sidebars read as
columns double the read), the long page's 30 (11 / 13 / 3); the long gaps are the job's GPU waits. Records:
`docs/rounds/t505-2026-10-26/notes.txt`. **The proposal waits on the owner** (asked as multiple choice).
`docs/rounds/t505-2026-10-26/notes.txt`. Then, the owner's choices in turn: a Codex adversarial review
(`context/impl/impl-review-findings-t505-codex.md`: the copy-free path is refused whenever fixed/sticky content
exists; the GPU-contention claim unproven) -> **the cause proven** with a diagnostic switch (`JIHAD_GPU_NO_PUBLISH=1`:
frames made and read but never handed to the card): the same daemon work makes desktop Wikipedia 32 fps and the long
page 53 while LunaSysMgr draws nothing, 8.6 / 13.6 while the card moves — the card's redraw on the shared GPU and
memory makes every daemon stage ~3x slower -> **the card measured** (the adapter's paint timed, `[paint-stat]` lines
under its paint log): a ~10 ms SOFTWARE blit (Piranha's PSoftContext2D) of the whole view ~20 times a second, mostly
repaints of the frame it has; keeping the wrapped surface per frame changed nothing (not kept); a retained-scroll card
is impossible (a software buffer LunaSysMgr re-uploads); **the frame wrapped without alpha** (opaque: every path
writes alpha 255) halves the blit and cuts LunaSysMgr's CPU 15 % while panning, the picture the same — shipped as the
default (`<state>/alphawrap` reverts), the pan rate unchanged. **The plan (the owner, after "consider sharing tasks
across the CPU and GPU"):** (1) pan frames composed on the GPU as the scrolled content alone (T-504's flag 32 idea) and
the fixed/sticky parts blended on the CPU from a parts image, the pixels beneath them restored per slot; then (2)
scroll-only bands composed on the CPU from the tiles' CPU-side pixels — each behind a switch, measured by finger.
**Observed, not changed:** a main-lane republish of an unchanged frame writes no stuck block (T-544's rects), so the
card's hold has nothing for that frame; harmless at rest (the next pan's frames carry them), noted because the
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 6983 6989 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 6484 6490 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
2946 1007 1383 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.river
25792 4179 4339 /usr/bin/LunaSysMgr -s
25868 7523 7892 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25841333 2251696 23661866 96307447 1943171 3998 49086 0 0 0
cpu 25841857 2252055 23662500 96309522 1943533 3998 49087 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 6921 6929 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 6422 6431 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
31405 1040 1814 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
25792 3682 3883 /usr/bin/LunaSysMgr -s
25868 6034 6895 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25836913 2250114 23658098 96297978 1942441 3998 49082 0 0 0
cpu 25837883 2251004 23658858 96299427 1942750 3998 49082 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 6777 6783 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 6278 6285 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
21957 3095 3953 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
25792 2193 2378 /usr/bin/LunaSysMgr -s
25868 3177 3585 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25815822 2246604 23648753 96271713 1941000 3998 49066 0 0 0
cpu 25816861 2246998 23649423 96273649 1941317 3998 49066 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 6724 6733 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 6223 6232 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
18149 2997 4187 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
25792 1712 1912 /usr/bin/LunaSysMgr -s
25868 1658 2551 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25808937 2244997 23645027 96264763 1940264 3997 49061 0 0 0
cpu 25810285 2245916 23645806 96265831 1940532 3997 49061 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 7836 7845 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 7323 7333 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
29864 1123 1929 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
24449 1561 1762 /usr/bin/LunaSysMgr -s
24535 3187 4052 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25883867 2272180 23707621 96396784 1969365 4002 49131 0 0 0
cpu 25884832 2273048 23708424 96398561 1969639 4002 49132 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 7956 7965 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 7446 7455 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
5861 1155 1934 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.river
307 1503 1708 /usr/bin/LunaSysMgr -s
374 3205 4068 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25901998 2277603 23716160 96410938 1970767 4003 49145 0 0 0
cpu 25902910 2278497 23716998 96412332 1971038 4003 49147 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 8290 8301 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 7819 7825 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
19608 1027 1784 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
14192 1499 1703 /usr/bin/LunaSysMgr -s
14270 3003 3744 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25942568 2290068 23732949 96451789 1972520 4006 49181 0 0 0
cpu 25943462 2290810 23733773 96453291 1972860 4006 49184 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 7775 7784 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 7261 7271 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
26044 3060 4264 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
24449 1031 1233 /usr/bin/LunaSysMgr -s
24535 1620 2541 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25878899 2270528 23703662 96388819 1968681 4001 49127 0 0 0
cpu 25880334 2271434 23704451 96389860 1968925 4001 49128 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
16564 7891 7899 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 7380 7390 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
1916 3044 4203 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.river
307 997 1196 /usr/bin/LunaSysMgr -s
374 1596 2518 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25896811 2275945 23711957 96401977 1969980 4003 49141 0 0 0
cpu 25898143 2276871 23712723 96403162 1970261 4003 49143 0 0 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,9 @@
--- CPU ticks over the drags (pid, before, after, command)
15828 3073 4253 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
16564 8223 8232 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
17954 7750 7757 ./ld-2.23.so --library-path /media/cryptofs/apps/usr/palm/applications/net.rive
14192 957 1165 /usr/bin/LunaSysMgr -s
14270 1592 2349 /usr/bin/LunaSysMgr -s
--- /proc/stat before and after
cpu 25937621 2288579 23728829 96443036 1971774 4006 49174 0 0 0
cpu 25938943 2289333 23729654 96444145 1972097 4006 49175 0 0 0
File diff suppressed because it is too large. Load diff
+51
View File
@@ -36,3 +36,54 @@ What it says: under a finger a frame is bound by the readback path on the GPU it
of the card: the read's wait (36 / 11 ms), the copy from the base (13-16 ms), and Wikipedia's sidebars doubling
what is read. No stage is the main thread's or the page's script's. A simple page runs ~30 ms jobs (~33 fps
possible) but the GPU stalls in the tail bring it to 16.6; Wikipedia is 2.5x short of R3's 24.
The cause, proven (the owner's "prove the cause first", after Codex's review called it unproven)
---------------------------------------------------------------------------------------------
A diagnostic switch, JIHAD_GPU_NO_PUBLISH=1 (render/goanna/BrowserPageGoanna.cpp, jihadNoPublish), makes and reads
every frame as usual but never hands it to the card. The same pan work in five conditions (tools/host/express-jobs.py
and a table of medians; the scripted pan: inject "pan 0 3000 10000", JIHAD_INJECT_PAN_NOCARD=1 keeps the card still):
round fps job (post to composed) band read copy compose read <100 rows
desktop Wikipedia
finger, frames to the card 9.4 70.6 55.1 13.7 19.3 12.0
finger, no frames to it 8.7 72.8 51.0 19.4 12.8 11.6
scripted, the card moving 8.6 58.1 31.2 12.0 9.1 9.0
scripted, the card still 23.4 33.1 9.2 11.0 10.9 5.5
scripted, still, no frames 32.0 23.0 6.8 5.7 7.6 4.7
the long page
finger, frames to the card 17.3 28.8 7.6 14.7 2.7 6.6
finger, no frames to it 13.4 42.0 9.9 12.3 2.9 8.0
scripted, the card moving 13.6 24.8 7.4 12.6 2.7 5.5
scripted, still, no frames 53.1 10.5 2.8 5.2 1.8 2.4
(The no-frames runs' dumps looked at: real content, advancing down the page.)
- With nothing drawn by LunaSysMgr the daemon's own work makes desktop Wikipedia at 32 fps and the long page at 53:
R3's 24 is met by the daemon alone.
- The card MOVING is what costs: the same work under a moving card runs at a third of the rate, every stage slower
(the read's GPU wait, the copy, the compose) — the GPU and the memory shared with LunaSysMgr's redraw of the card.
A still card that draws each new frame costs less (23.4 against 32).
- LunaSysMgr's CPU (the instance that draws the card) over the Wikipedia drags: 893 jiffies with frames to the card,
408 with none (~33 ms of CPU per new frame drawn); 861 / 369 on the long page.
- The adapter's paint (render/adapter/BrowserAdapter.cpp, the GPU path's paint) wraps the 3.7 MB shared buffer in a
new PGSurface on every paint and bit-blits from it: every scroll step of the card and every new frame. Whether
Piranha uploads the whole wrapped surface each time is the next thing to find out.
The card's paint, measured (the owner: "possibly 1 or 3 but measure first to figure out which combination is best")
-----------------------------------------------------------------------------------------------------------------
The adapter's GPU-path paint timed while its paint log is on (render/adapter/BrowserAdapter.cpp, jihadPaintStat: a
"[paint-stat]" line every 2 s; the log's gate <state>/adapterlog, read once per LunaSysMgr process), by finger:
paints/s new frames (blit) repaints, same frame (blit) the paint, % of a core
desktop Wikipedia 18-23 120 (9.3 ms) 342 (8.6 ms) 20-25 %
the long page 18 227 (9.8 ms) 226 (8.9 ms) 18 %
A paint is ~10 ms of LunaSysMgr's CPU, almost all PGContext::bitblt of the view (~720 kpx, 2.9 MB); the wrap is
0.02 ms. Most paints on Wikipedia repaint the frame the card already has (a scroll step).
- (1) The PGSurface kept for a frame across its repaints (<state>/pgcache): no change (blit 9.3 / 8.6 ms either way;
9.4 against 9.7 fps, 16.9 against 18.5). The card's PGContext is built on Piranha's PSoftContext2D (libWebKitLuna's
exports): a software blit that reads the whole source every time. Not kept.
- (3) The card scrolling a retained surface: there is no GPU-side card surface to scroll on this path; the card is a
software buffer that LunaSysMgr takes to the GPU at each redraw, and a scroll step moves every pixel of it.
- The frame wrapped without alpha (<state>/opaque; the daemon's frames are opaque): the blit 9 -> 5 ms, the paint
~12 % of a core, LunaSysMgr's card instance -15 % CPU (921 -> 757 jiffies on Wikipedia, 865 -> 741 on the long
page), the picture the same (looked at) — and the pan rate unchanged (10.0 / 15.7 fps against 9.7 / 18.5): the
daemon's GPU waits do not come from the card's CPU blit but from what LunaSysMgr does on the GPU with the card's
buffer at each redraw.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+69 -2
View File
@@ -519,6 +519,8 @@ BrowserAdapter::BrowserAdapter(NPP instance, GMainContext *ctxt, int16_t argc, c
, mOffscreen1(0)
, mOffscreen2(0)
, mOffscreenCurrent(0)
, mJihadLastPaintBuf(0)
, mJihadLastPaintSeq(0)
, mFrozenSurface(0)
, mFrozen(false)
, mFrozenRenderPos(0, 0)
@@ -1112,6 +1114,53 @@ static FILE* jihadPaintLog()
return s_log;
}
// T-505 (the owner's choice, 2026-10-26): the frame is wrapped without alpha. The daemon's frames are opaque (every
// path writes alpha 255: the GPU readback forces it, the software readback and the region render enforce it), and
// Piranha's software blit (the card's PGContext is a PSoftContext2D) then copies instead of blending: 9 -> 5 ms a
// paint by finger, LunaSysMgr's card instance -15 % CPU while panning, the picture the same. <state>/alphawrap (read
// once per LunaSysMgr process) wraps it with alpha as before.
static bool jihadOpaqueOn()
{
static int s_on = -1;
if (s_on < 0) s_on = access(JIHAD_STATE_DIR "/alphawrap", F_OK) == 0 ? 0 : 1;
return s_on == 1;
}
static double jihadMsSince(const struct timeval& a, const struct timeval& b)
{
return (b.tv_sec - a.tv_sec) * 1000.0 + (b.tv_usec - a.tv_usec) / 1000.0;
}
// T-505: the GPU path's paints while the paint log is on, a line every 2 s: how many, the new frames' and the
// repaints' (the same frame, a scroll step) wrap, blit, hold (T-544) and release times, the pixels blitted
struct JihadPaintStat {
int n[2]; double wrap[2], blit[2], hold[2], rel[2], all[2], maxAll[2]; double px[2];
struct timeval since; bool started;
};
static void jihadPaintStat(bool same, double wrap, double blit, double hold, double rel, double all, double px)
{
FILE* lf = jihadPaintLog();
if (!lf) return;
static JihadPaintStat s;
struct timeval now;
gettimeofday(&now, NULL);
if (!s.started) { memset(&s, 0, sizeof(s)); s.since = now; s.started = true; }
const int k = same ? 1 : 0;
s.n[k]++; s.wrap[k] += wrap; s.blit[k] += blit; s.hold[k] += hold; s.rel[k] += rel; s.all[k] += all; s.px[k] += px;
if (all > s.maxAll[k]) s.maxAll[k] = all;
const double span = jihadMsSince(s.since, now);
if (span < 2000.0) return;
fprintf(lf, "[paint-stat] %.0f ms: %d paints (%d new frames, %d repaints of the same), %s\n",
span, s.n[0] + s.n[1], s.n[0], s.n[1], jihadOpaqueOn() ? "opaque" : "with alpha");
for (int c = 0; c < 2; c++) {
if (!s.n[c]) continue;
fprintf(lf, "[paint-stat] %s: wrap %.2f, blit %.2f, hold %.2f, release %.2f, all %.2f ms avg (max %.1f), %.0f kpx a paint\n",
c ? "repaints" : "new frames", s.wrap[c] / s.n[c], s.blit[c] / s.n[c], s.hold[c] / s.n[c], s.rel[c] / s.n[c],
s.all[c] / s.n[c], s.maxAll[c], s.px[c] / s.n[c] / 1000.0);
}
memset(&s, 0, sizeof(s)); s.since = now; s.started = true;
}
// T-544: between two frames of a pan the card shows the frame it holds moved by the scroll since, and
// the frame's fixed and stuck parts (desktop Wikipedia's sidebars) moved with the page and jumped back
// at the next frame (the owner, 2026-10-26: the column glides, the sidebars jitter and lag). Where the
@@ -1264,8 +1313,18 @@ void BrowserAdapter::handlePaint(NpPalmDrawEvent* event)
if (nearUnity && mWindow.width > 0 && gi->bufferWidth != (int)mWindow.width)
return;
}
PGSurface* surf = PGSurface::wrap((uint32_t)gi->renderedWidth, (uint32_t)gi->renderedHeight,
(const unsigned char*)mOffscreenCurrent->rasterBuffer(), true);
// T-505: timed while the paint log is on; a repaint is the same frame in the same buffer (a scroll step)
struct timeval tvA, tvB, tvC, tvD, tvE;
const bool timed = jihadPaintLog() != NULL;
if (timed) gettimeofday(&tvA, NULL);
const unsigned char* raster = (const unsigned char*)mOffscreenCurrent->rasterBuffer();
const uint32_t frameSeq = mOffscreenCurrent->frameSeq();
const bool sameFrame = frameSeq != 0 && frameSeq == mJihadLastPaintSeq && raster == mJihadLastPaintBuf;
mJihadLastPaintSeq = frameSeq; mJihadLastPaintBuf = raster;
// (a PGSurface kept for the frame across its repaints changed nothing: the card's context is Piranha's
// software one, and its blit reads the whole source every time; measured 2026-10-26, not kept)
PGSurface* surf = PGSurface::wrap((uint32_t)gi->renderedWidth, (uint32_t)gi->renderedHeight, raster, !jihadOpaqueOn());
if (timed) gettimeofday(&tvB, NULL);
if (!surf) { if (FILE* lf = jihadPaintLog()) fprintf(lf, "[hp-pg] PGSurface::wrap FAILED %dx%d\n",
gi->renderedWidth, gi->renderedHeight); }
if (surf) {
@@ -1322,12 +1381,20 @@ void BrowserAdapter::handlePaint(NpPalmDrawEvent* event)
(int)blitted, sL, sT, sR, sB, dl, dt, dr, dbm, inv, baseX, baseY,
mScrollPos.x, mScrollPos.y, gi->renderedWidth, gi->renderedHeight,
gi->renderedX, gi->renderedY); } }
if (timed) tvD = tvC = tvB;
if (blitted) {
gc->bitblt(surf, sL, sT, sR, sB, dl, dt, dr, dbm);
if (timed) gettimeofday(&tvC, NULL);
jihadHoldStuck(gc, surf, mOffscreenCurrent, gi, event, mScrollPos.x, pageScrollY,
mZoomLevel, (int)mWindow.width, (int)mWindow.height); // T-544
if (timed) gettimeofday(&tvD, NULL);
}
surf->releaseRef(); // PG ref-counted (starts at 1); frees the wrapper, not our data
if (timed) {
gettimeofday(&tvE, NULL);
jihadPaintStat(sameFrame, jihadMsSince(tvA, tvB), jihadMsSince(tvB, tvC), jihadMsSince(tvC, tvD),
jihadMsSince(tvD, tvE), jihadMsSince(tvA, tvE), blitted ? (double)(sR - sL) * (sB - sT) : 0.0);
}
}
}
return;
+4
View File
@@ -468,6 +468,10 @@ private:
// allocated the adapter simply runs on two, exactly as before.
BrowserOffscreen* mOffscreen2;
BrowserOffscreen* mOffscreenCurrent;
// T-505 (the owner's "measure first", 2026-10-26): the GPU path's paint, timed while the paint log is on, split
// by whether the frame is new or the card repaints the frame it has (a scroll step)
const unsigned char* mJihadLastPaintBuf;
uint32_t mJihadLastPaintSeq;
QImage* mFrozenSurface;
bool mFrozen;
+15 -3
View File
@@ -378,6 +378,16 @@ bool jihadTimelineOn() {
return sOn;
}
// T-505 (the owner's "prove the cause first", 2026-10-26), device rounds only: JIHAD_GPU_NO_PUBLISH=1 makes and reads
// every GPU frame as usual but never hands one to the card (no msgPainted, the slot not out with it), so the
// daemon's GPU work runs with the card drawing nothing new: what the read waits for without LunaSysMgr's redraws
bool jihadNoPublish() {
static const bool sOn = getenv("JIHAD_GPU_NO_PUBLISH") != nullptr;
static bool sSaid = false;
if (sOn && !sSaid) { sSaid = true; fprintf(stderr, "[jihad-bs] JIHAD_GPU_NO_PUBLISH: GPU frames are not handed to the card\n"); }
return sOn;
}
// T-527 device rounds (JIHAD_GPU_TIMELINE=1): why the express lane made no frame, on the timeline when the
// reason changes or every 25 ms while it stays (the pan's 56 ms+ gaps traced to their source)
static void jihadXNote(const char* why) {
@@ -5409,8 +5419,10 @@ bool BrowserPageGoanna::xPoll(int64_t now) {
if ((sAvgN++ % 50) == 0)
JIHAD_GPU_LOG("[jihad-gpu] express frame times: on the slot's own frame %.1f ms, copied from the base %.1f ms\n", mXOwnMs, mXCopyMs);
}
mSink.msgPainted(mXJob.key); noteShown(mXJob.key);
mInFlight[s] = true; mPaintMs[s] = now;
if (!jihadNoPublish()) {
mSink.msgPainted(mXJob.key); noteShown(mXJob.key);
mInFlight[s] = true; mPaintMs[s] = now;
}
jihadTimelinePublish("express", mXJob.t0, frameY, mXJob.zoom);
if (jihadTimelineOn()) {
// T-515 device rounds: the clocks the frame was made at
@@ -6939,7 +6951,7 @@ void BrowserPageGoanna::paintToSharedBuffer() {
const bool stuckOk = gpuFinished && paintedW == w && popupsDrawn == 0;
publishWindow(mActiveKey, pubWin, partial ? dirty : nullptr, stuckOk ? &mGpuJobCr : nullptr, mGpuJobViewRow);
}
mSink.msgPainted(mActiveKey); noteShown(mActiveKey);
if (!(gpuFinished && jihadNoPublish())) { mSink.msgPainted(mActiveKey); noteShown(mActiveKey); }
const int64_t b = jihadNowMs();
jihadTimelinePublish("main", gpuFinished ? paintT0 : 0, gpuFinished ? mGpuJobY : paintedTop, oi->contentZoom);
static int sN = 0;
+5 -3
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
"""express-jobs.py <daemon log> [...]: T-505 (cavekit-gpu-rendering R3), the owner's "measure first" (2026-10-26).
Over the round's drags (between "[round] finger drags" and "[round] end", or the whole log), the frame stages from
Over the round's drags (between "[round] finger drags" and "[round] end", or a scripted pan's "inject pan" lines, or
the whole log), the frame stages from
the timeline (JIHAD_GPU_TIMELINE=1) and the compositor's own lines: each job's wait on the compositor loop and its
compose there (the compositor thread's CPU and its GL calls), the read thread's glReadPixels (the GPU finishing the
composite, behind whatever else the GPU has queued: LunaSysMgr's redraw of the card) and its swizzle, the publish's
@@ -15,8 +16,9 @@ def pct(v, p):
for path in sys.argv[1:]:
lines = open(path, encoding='latin1').read().splitlines()
a = next((i for i, l in enumerate(lines) if '[round] finger drags' in l), 0)
b = next((i for i, l in enumerate(lines) if '[round] end' in l and i > a), len(lines))
# the finger drags' marks, or the scripted pan's own lines (tools/device/t502/pan-run.sh)
a = next((i for i, l in enumerate(lines) if '[round] finger drags' in l or '] inject pan ' in l), 0)
b = next((i for i, l in enumerate(lines) if ('[round] end' in l or 'inject pan done' in l) and i > a), len(lines))
st = {k: [] for k in ('queued', 'composed', 'compose', 'handoff', 'readpx', 'rows', 'swizzle', 'gap', 'made', 'band')}
pubs, kinds, lockwait, trans, idle = [], {}, [], [], {}
for l in lines[a:b]: