From 24b88c3ba2b90a52e6ea06c898208bc40443c35d Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 6 Jul 2026 19:25:55 -0500 Subject: [PATCH] Performance improvement plan. --- NATIVE-PERF-PLAN.md | 189 +++++++++++++++++++++++++++++++++ PERF.md | 102 +++++++++++------- examples/uber/uber.c | 137 ++++++++++++++++++++++++ src/atarist/hal.c | 10 +- src/core/surface.c | 39 ++++--- tests/goldens/uber/amiga.txt | 124 +++++++++++++++++---- tests/goldens/uber/atarist.txt | 150 ++++++++++++++++++++------ tests/goldens/uber/dos.txt | 150 ++++++++++++++++++++------ tests/goldens/uber/iigs.txt | 96 ++++++++++++----- 9 files changed, 818 insertions(+), 179 deletions(-) create mode 100644 NATIVE-PERF-PLAN.md diff --git a/NATIVE-PERF-PLAN.md b/NATIVE-PERF-PLAN.md new file mode 100644 index 0000000..1a617e3 --- /dev/null +++ b/NATIVE-PERF-PLAN.md @@ -0,0 +1,189 @@ +# NATIVE-PERF-PLAN: match hand-coded native, per port + +Directive (Scott, 2026-07-06): floor parity against the IIgs is not the +bar anymore -- "still way too slow across the board." The new target is +**each port within ~1.5x of what hand-coded native technique achieves on +that hardware**, proven by cycle-math ceilings and workload benchmark +rows, not vibes. The IIgs-floor rule remains a secondary invariant +(never ship a 68k port slower than the 65816). + +Why the current table lies about games: UBER measures best-case single +ops (aligned sprite x, one tile, one call). Real games pay (a) the +alignment cliff -- only aligned-x sprite draws are compiled; other x +falls to interpreters/per-pixel walkers 3-20x slower -- and (b) a +measured ~35-50% per-call wrapper tax (dispatch + validation + +dirty-mark) around cores that are already at silicon parity, and (c) +have no batch paths, so a tilemap repaint pays that tax per tile. + +Frame-budget reality check (2026-07-06 table): at 25% CPU and 50/60 Hz, +~3 sprites/frame on ST/Amiga/IIgs; a 40x25 tilemap repaint costs +~0.44-0.64s on the 68k ports. Hand-coded games on these machines did +far better. Close that gap. + +Ground rules (inherited from PERF-AUDIT-PLAN, all still binding): +- Source toolchains/env.sh before any make; delete stale binaries after + .s edits; Scott owns git; style rules apply. +- Every phase is hash-gated: existing goldens stay bit-identical + (diff-uber-hashes 45/45 x4) unless a phase EXPLICITLY adds rows, in + which case new goldens are frozen only after 4-port cross-identity. +- Every phase ends with a 4-port bench + PERF.md regeneration. +- Cycle models are hypotheses; the emulator measurement decides (lesson: + the fillCircle asm probe and the 17% ST clock bug). + +## Phase 0 -- Ceilings + honest workload rows [items 1+2 DONE 2026-07-06] + +### Item 1 RESULT -- native-technique ceilings (cycle-math, emulator-class) + +Ops/sec, hand-coded best technique per port. "Meas" = current UBER +(2026-07-06, millis clock). Gap = ceiling / measured. Full derivations +with instruction-level arithmetic are in the Phase-0 workflow reports +(session scratchpad); re-derive on demand -- the arithmetic styles were +validated where models met measurements (ST present model 53/sec vs 56 +measured; IIgs 29/sec present ceiling already in PERF.md). + +| Op (16x16 sprite, 8x8 tile) | ST ceiling | meas | Amiga ceiling | meas | IIgs ceiling | meas | DOS ceiling | meas | +|---|---|---|---|---|---|---|---|---| +| Sprite draw, arbitrary x | ~2,235-2,750 (pre-shifted movem RMW) | 585 aligned / far less unaligned | ~3,600-4,300 (blitter cookie-cut; CPU-compiled ~1,350) | 903 aligned only | 4,300 aligned / 2,490 odd (compiled stores) | 907 | ~11,000 | 6,094 | +| Sprite save or restore | ~5,300 (move.l window) | 703/553 | ~6,300-7,400 (A->D blit) | 567/553 | ~2,520 (MVN) | 543/568 | ~14,500-18,000 | 8,964/5,744 | +| Tile paste 8x8 | ~12,700-15,500 | 1,574 | ~10,700 | 2,253 | ~5,830 | 1,803 | ~57,000 | 9,454 | +| 40-tile row repaint | 352-880 | -- | ~316 | -- | ~190 | -- | ~1,900 | -- | +| Present (native answer) | page flip ~free + dirty bands (full copy ~53/s) | 56 | page flip ~free (8 copper pokes; full blit ~110/s) | 362* | dirty bands (full PEI 20-29/s; real HW ~14-32) | 68* | dirty bands (real ISA full blast 10-31 fps!) | 354* | + +*Present measurement artifacts found: Amiga/DOS measured presents +EXCEED their physical full-copy ceilings because UBER's timed present +loop never re-dirties the stage -- after the first copy it measures the +dirty-union idle early-out, not a copy. IIgs 68 is the known SEI +inflation. The gameFrame workload row (below) fixes this by dirtying +every call. + +Headline: the wrapper tax is universal and dominates -- tile paste runs +3-6x (up to ~10x ST, ~90% overhead DOS) below hand-coded ceilings on +EVERY port with cores already at parity; IIgs C glue measured at +~800-4,000 cycles per call (jlDrawPixel = 820 cycles for a 1-byte op). +Sprite ceilings are 2.5-4x above current aligned numbers (ST via +movem long-RMW + all 16 phases; Amiga via the BLITTER, which also +frees the CPU -- its compiled-CPU path caps at ~1,350). + +### Item 2 RESULT -- alignment-cliff code truth (supersedes all memory) + +SPRITE_SHIFT_INDEX (spriteInternal.h:24-30): Amiga x&7, ST +(x&7)?2:((x>>3)&1), chunky (IIgs/DOS) x&1. Emitters: + +| Port | DRAW compiled | SAVE/RESTORE compiled | Fallback at NOT_COMPILED | +|---|---|---|---| +| IIgs | shifts 0+1 = EVERY x | shifts 0+1 = every x | (n/a -- no cliff) | +| DOS | shifts 0+1 = EVERY x | shifts 0+1 = every x | (n/a -- no cliff) | +| ST | 0,1 only (x%8==0) | NEVER (stubs) | draw: byte-wide shifted c2p walker (hal.c:1815+); save/restore: asm byte copy when x%8==0 else per-pixel pair walker | +| Amiga | shift 0 ONLY (x%8==0) | NEVER (stubs) | draw: shifted c2p walker (hal.c:1491); save/restore: plane-major copy when x%8==0 else pair walker | + +So the cliff is 68k-ONLY: 7/8 x positions run walkers on ST/Amiga, and +jlSpriteSaveAndDraw's combined fast path NEVER fires on 68k (SAVE never +compiled). IIgs/DOS need nothing in Phase 1. + +Phase-1 design constraints discovered: (a) ST's shift-2 bucket cannot +hold compiled code -- ST needs SPRITE_SHIFT_INDEX changed to x&7 (a +dispatcher-contract change) plus emitter support; (b) routineOffsets +are uint16_t so one sprite's compiled bytes must stay < 64KB -- 8 DRAW +variants of a mixed 32x32 (~8-16KB each) blow it; needs selective +emission or offset-scheme change (16x16 sprites fit fine); (c) the +jlSpriteRestoreUnder gate accepts only copyBytes == bytesPerRow or +1 +(spriteCompile.c:547-552) -- planar shifted saves record +4, so the +gate must widen or 7/8 alignments stay interpreted even after emitters +land; (d) stale doc: sprite.h:32-40 contradicts spriteInternal.h:16-23 +(fix during Phase 1); (e) uber.c:972 comment claims Amiga has 8 +variants -- aspirational, false today. + +### Item 3 -- workload rows [IN PROGRESS] + +Four rows appended AFTER the surfaceMarkDirtyRect timeOp (cumulative- +hash safety: correctness checks clear the stage first, so the frozen 45 +stay bit-identical; Phase-7 precedent): +- "jlSpriteDraw unaligned" -- x=71,y=120 (odd AND x%8==7: worst case on + all four ports simultaneously). +- "jlSpriteDraw sweep16" -- all 16 x phases (208..223) inside ONE call + so the op is idempotent regardless of per-port iteration counts. +- "jlTilePaste map 10x5" -- 50 pastes of two SNAPPED patterned tiles + (tile pixels are platform-private; only snap round-trips portably). +- "gameFrame composite" -- 256x96 repaint + 16 HUD tiles + 3 sprite + saveAndDraw + 3 restores + present, net-idempotent per call; all + sprite x mod-16-aligned so this row isolates wrapper tax + present + (rows above own the alignment signal). Also fixes the present-row + artifact (dirties every call). +Golden contract goes 45 -> 49. Refreeze procedure: regression gate +first (each port: exactly 45 match + 4 extra vs OLD golden), then +cross-identity (49/49 IIgs vs each), only then freeze + regenerate +PERF.md. +Gate: ceilings documented (DONE above); new rows golden'd x4; existing +45 untouched. + +## Phase 1 -- Kill the alignment cliff + +All-shift compiled sprites everywhere. ST: emit shifts covering all +x%16 phases in spriteEmitInterleaved68k (pre-shifted plane bytes + +masks spanning byte halves/groups; the Amiga 8-variant planar emitter +is the proven template). IIgs/DOS: odd-x nibble-shifted DRAW variants +(chunky). Save/restore already widen via shift where applicable -- +verify per port. Arena sizing: 8x DRAW variants (Amiga precedent: +8-32KB arena; re-check DEFAULT_CODEGEN_BYTES per port). +Gate: unaligned-sprite UBER rows reach ~parity with aligned rows on +every port; goldens hold. + +## Phase 2 -- Strip the per-op tax + +Plane-pointer caching (kill per-draw jlpSurfacePlanePtr x4), flattened +hot-op dispatch, inline dirty marks for the remaining hot ops (extend +the 2026-07-06 surfaceMarkDirtyRows inline that bought 2-5%), remove +redundant validation layers (core wrapper already proves s/bounds). +Gate: small-op rows (tileFill/Paste/Copy, sprite ops, fillRect small) +move measurably toward Phase-0 ceilings on all ports; goldens hold. + +## Phase 3 -- Batch APIs + +jlTileMapPaste (N tiles, one validation, one dirty union -- the +jlDrawText pattern generalized) + sprite batch draw/save/restore. +API shape needs Scott's sign-off before landing in public headers. +Gate: tilemap workload row approaches ceiling (per-tile overhead ~0); +goldens hold (new API rows get their own goldens). + +## Phase 4 -- Port-native heavy weapons + +Amiga: blitter cookie-cut sprite draw for larger-than-16x16 objects; +blitter tile/tilemap paste evaluation. ST: evaluate movem-based +row engines + restore-from-clean-buffer strategy for backgrounds. +IIgs: PEI-slam variants for batch paths where applicable. +Gate: per-op measurements vs ceilings; keep only what beats the +compiled-CPU path on the emulator (fillCircle lesson: no dead asm). + +## Phase 5 -- Acceptance + +Every workload row within ~1.5x of its Phase-0 ceiling per port, or a +documented cycle-proof that the remaining gap is structural (e.g. ST +interleaved-planar RMW). PERF.md gets a ceilings column. Update the +perf-directive memory with the outcome. + +## Progress tracker + +- [x] Phase 0 COMPLETE 2026-07-06. Ceilings + code-truth in this file + (above); four workload rows landed in uber.c and golden'd: regression + gate exactly 45 match + 4 extras on every port, cross-identity 49/49 + x4 (bonus: sweep16 validated the ST/Amiga shifted c2p walkers pixel- + perfect at all 14 untested phases). Golden contract is now 49 lines. + BASELINE the later phases must move (ops/sec, millis clock): + jlSpriteDraw unaligned: ST 40 (5% of floor!) | Amiga 75 (9%) | + IIgs 842 | DOS 5115 -- vs aligned 607/903/902/6218 = the + 15x/12x 68k cliff, Phase 1's gate. + jlSpriteDraw sweep16 (x16 = draws/sec): ST 32 | Amiga 80 | + IIgs 896 | DOS 5648 -- real arbitrary-x sprite rate. + jlTilePaste map 10x5 (x50 = tiles/sec): ST 1600 | Amiga 2300 | + IIgs 1750 | DOS 10000 -- Phase 2/3's gate (ceilings say + 10-15k on 68k, 57k DOS). + gameFrame composite: ST 9 | Amiga 18 | IIgs 10 | DOS 18 fps -- + the bottom-line number; the program ends when this is at/near + the port's refresh-limited ceiling or a documented structural + bound. +- [ ] Phase 1 (68k all-shift emitters + save/restore emitters; + constraints (a)-(e) in the Phase-0 item-2 section above) +- [ ] Phase 2 +- [ ] Phase 3 +- [ ] Phase 4 +- [ ] Phase 5 diff --git a/PERF.md b/PERF.md index 4ba76c8..c552cd7 100644 --- a/PERF.md +++ b/PERF.md @@ -24,10 +24,26 @@ is `jlFillCircle r=40` (74%); a whole-circle asm routine was tried and did NOT help (per-span dispatch is not the cost -- the 8-way-symmetry overlap fill dominates), so it stays on the C span walker for now. +**2026-07-06, NATIVE-PERF Phase 0:** four WORKLOAD rows were added (see +NATIVE-PERF-PLAN.md) and the goldens refrozen at **49 lines** after a +clean regression gate (45 match + exactly 4 extras per port) and full +4-port cross-identity. The new rows measure what games actually do, and +they expose the real problem the per-op rows hid: `jlSpriteDraw +unaligned` runs at **5% (ST) / 9% (Amiga)** of the IIgs floor -- a +15x/12x cliff vs the aligned row, because only x%8==0 draws are +compiled on the 68k ports (see the plan's code-truth table). The +`gameFrame composite` row is the bottom line: **ST 9 / Amiga 18 / +IIgs 10 / DOS 18 frames/sec** for a modest game frame. Bonus finding: +cross-identity of the sweep16 row validated the ST/Amiga shifted c2p +walkers as pixel-perfect at all 14 previously-untested x phases. +(Re-capture note: IIgs input/audio rows wobbled vs the prior MAME run +-- e.g. jlAudioFrameTick 50223 -> 27612 -- run-to-run MAME variance on +cheap ops; hashes are unaffected and those rows gate nothing.) + Correctness statement backing this table: all four ports produce BYTE-IDENTICAL pixels on every measured op and every correctness -check -- 45/45 surface hashes match the frozen goldens in -tests/goldens/uber/ (34 timed ops + 11 hashed checks; the PASS/FAIL +check -- **49/49** surface hashes match the frozen goldens in +tests/goldens/uber/ (37 timed ops + 12 hashed checks; the PASS/FAIL checks -- palette round-trip, PRNG golden sequence, sprite clip round-trip, arena churn, sprite-from-surface -- pass everywhere). The Phase 0-era divergences (#75 tilePasteMono three-way, #78 ST @@ -82,39 +98,43 @@ default cuts off the final checks). | Op | IIgs (ops/sec) | Amiga (ops/sec, % of IIGS) | Atari ST (ops/sec, % of IIGS) | DOS (ops/sec, % of IIGS) | | --- | --- | --- | --- | --- | -| jlSurfaceClear | 35 | 75 (214%) | 44 (126%) | 70 (200%) | -| jlPaletteSet | 1623 | 11503 (709%) | 5256 (324%) | 29474 (1816%) | -| jlScbSetRange | 163 | 3953 (2425%) | 2418 (1483%) | 8474 (5199%) | -| jlDrawPixel | 3423 | 5853 (171%) | **3322 (97%)** | 23524 (687%) | -| jlDrawLine H | 1143 | 1703 (149%) | 1341 (117%) | 5674 (496%) | -| jlDrawLine V | 99 | 269 (272%) | 120 (121%) | 494 (499%) | -| jlDrawLine diag | 42 | **40 (95%)** | 42 (100%) | 110 (262%) | -| jlDrawRect 100x100 | 90 | 203 (226%) | 100 (111%) | 399 (443%) | -| jlDrawCircle r=16 | 306 | **285 (93%)** | **178 (58%)** | 424 (139%) | -| jlDrawCircle r=80 | 70 | **63 (90%)** | **40 (57%)** | 96 (137%) | -| jlFillRect 16x16 | 603 | 1153 (191%) | **585 (97%)** | 2874 (477%) | -| jlFillRect 80x80 | 110 | 269 (245%) | 115 (105%) | 380 (345%) | -| jlFillRect 320x200 | 21 | 66 (314%) | 38 (181%) | 56 (267%) | -| jlFillCircle r=40 | 42 | **31 (74%)** | 75 (179%) | 153 (364%) | -| jlSamplePixel | 5223 | 7253 (139%) | **4862 (93%)** | 44244 (847%) | -| jlTileFill | 2043 | 2303 (113%) | **1516 (74%)** | 8894 (435%) | -| jlTileCopy | 1443 | 1853 (128%) | **1307 (91%)** | 8404 (582%) | -| jlTileCopyMasked | 624 | 953 (153%) | 677 (108%) | 3084 (494%) | -| jlTilePaste | 1803 | 2303 (128%) | **1544 (86%)** | 9454 (524%) | -| jlTileSnap | 2643 | 3503 (133%) | 2907 (110%) | 18624 (705%) | -| jlSpriteSaveUnder | 543 | 567 (104%) | 833 (153%) | 8964 (1651%) | -| jlSpriteDraw | 907 | 953 (105%) | **585 (64%)** | 6094 (672%) | -| jlSpriteRestoreUnder | 568 | **553 (97%)** | 655 (115%) | 5744 (1011%) | -| jlSpriteSaveAndDraw | 376 | **332 (88%)** | **318 (85%)** | 4204 (1118%) | -| jlStagePresent full | 68 | 359 (528%) | **56 (82%)** | 354 (521%) | -| jlInputPoll | 243 | 4003 (1647%) | 1425 (586%) | 3084 (1269%) | -| jlKeyDown | 12303 | 39753 (323%) | 22826 (186%) | 76514 (622%) | -| jlKeyPressed | 14043 | 38003 (271%) | 22826 (163%) | 74064 (527%) | -| jlMouseX | 30123 | 96703 (321%) | 59354 (197%) | 153864 (511%) | -| joeyJoyConnected | 12303 | 39303 (319%) | 22283 (181%) | 77144 (627%) | -| jlAudioFrameTick | 50223 | 56503 (113%) | **11724 (23%)** | 58664 (117%) | -| jlAudioIsPlayingMod | 13503 | 56403 (418%) | 29870 (221%) | 127334 (943%) | -| surfaceMarkDirtyRect (via jlFillRect 32x32) | 323 | 853 (264%) | 376 (116%) | 1474 (456%) | +| jlSurfaceClear | 33 | 75 (227%) | 44 (133%) | 66 (200%) | +| jlPaletteSet | 1561 | 11503 (737%) | 5256 (337%) | 29809 (1910%) | +| jlScbSetRange | 163 | 3953 (2425%) | 2418 (1483%) | 8495 (5212%) | +| jlDrawPixel | 3179 | 5853 (184%) | 3384 (106%) | 23757 (747%) | +| jlDrawLine H | 1142 | 1703 (149%) | 1341 (117%) | 5708 (500%) | +| jlDrawLine V | 99 | 269 (272%) | 132 (133%) | 470 (475%) | +| jlDrawLine diag | 42 | **40 (95%)** | 43 (102%) | 109 (260%) | +| jlDrawRect 100x100 | 89 | 203 (228%) | 108 (121%) | 377 (424%) | +| jlDrawCircle r=16 | 303 | **285 (94%)** | **184 (61%)** | 449 (148%) | +| jlDrawCircle r=80 | 70 | **63 (90%)** | **42 (60%)** | 98 (140%) | +| jlFillRect 16x16 | 605 | 1153 (191%) | 610 (101%) | 3013 (498%) | +| jlFillRect 80x80 | 110 | 269 (245%) | 120 (109%) | 414 (376%) | +| jlFillRect 320x200 | 21 | 66 (314%) | 40 (190%) | 58 (276%) | +| jlFillCircle r=40 | 42 | **31 (74%)** | 77 (183%) | 156 (371%) | +| jlSamplePixel | 4815 | 7253 (151%) | 4862 (101%) | 46397 (964%) | +| jlTileFill | 1981 | 2303 (116%) | **1603 (81%)** | 9313 (470%) | +| jlTileCopy | 1441 | 1853 (129%) | **1341 (93%)** | 8764 (608%) | +| jlTileCopyMasked | 623 | 953 (153%) | 689 (111%) | 3147 (505%) | +| jlTilePaste | 1741 | 2303 (132%) | **1574 (90%)** | 9806 (563%) | +| jlTileSnap | 2520 | 3503 (139%) | 2907 (115%) | 19247 (764%) | +| jlSpriteSaveUnder | 545 | 567 (104%) | 849 (156%) | 9229 (1693%) | +| jlSpriteDraw | 902 | 953 (106%) | **607 (67%)** | 6218 (689%) | +| jlSpriteRestoreUnder | 566 | **553 (98%)** | 689 (122%) | 5933 (1048%) | +| jlSpriteSaveAndDraw | 376 | **332 (88%)** | **328 (87%)** | 4271 (1136%) | +| jlStagePresent full | 67 | 359 (536%) | **55 (82%)** | 360 (537%) | +| jlInputPoll | 229 | 4003 (1748%) | 1400 (611%) | 3134 (1369%) | +| jlKeyDown | 10191 | 39753 (390%) | 22403 (220%) | 77800 (763%) | +| jlKeyPressed | 11432 | 38003 (332%) | 22344 (195%) | 74977 (656%) | +| jlMouseX | 20138 | 97703 (485%) | 58314 (290%) | 155140 (770%) | +| joeyJoyConnected | 10191 | 38903 (382%) | 21870 (215%) | 77819 (764%) | +| jlAudioFrameTick | 27612 | 56453 (204%) | **11732 (42%)** | 59162 (214%) | +| jlAudioIsPlayingMod | 11029 | 56503 (512%) | 29870 (271%) | 127794 (1159%) | +| surfaceMarkDirtyRect (via jlFillRect 32x32) | 323 | 853 (264%) | 389 (120%) | 1478 (458%) | +| jlSpriteDraw unaligned | 842 | **75 (9%)** | **40 (5%)** | 5115 (607%) | +| jlSpriteDraw sweep16 | 56 | **5 (9%)** | **2 (4%)** | 353 (630%) | +| jlTilePaste map 10x5 | 35 | 46 (131%) | **32 (91%)** | 200 (571%) | +| gameFrame composite | 10 | 18 (180%) | **9 (90%)** | 18 (180%) | > **IIgs full-screen ceiling (~29 ops/sec).** A full-screen op moves > 32000 bytes = 16000 word-stores x 6 cyc (STA long,X / PEI, both @@ -143,11 +163,15 @@ default cuts off the final checks). constraint, no blitter allowed (STF baseline). The IIgs circle-outline case is a known structural loss (3-register 65816 vs 16-register 68000 Bresenham; see feedback memory). With IIgs sprites now compiled, a - 68k sprite gap re-opened: ST jlSpriteDraw 64%, ST jlSpriteSaveAndDraw - 85%, ST jlTileFill 74%, and Amiga jlSpriteRestoreUnder 97% + + 68k sprite gap re-opened: ST jlSpriteDraw 67%, ST jlSpriteSaveAndDraw + 87%, ST jlTileFill 77%, and Amiga jlSpriteRestoreUnder 97% + jlSpriteSaveAndDraw 88% remain below the IIgs floor (they were masked - while the IIgs interpreted; ST jlSpriteRestoreUnder is now 115%, above - floor, after the clock fix). The ST jlSpriteDraw case was investigated + while the IIgs interpreted; ST jlSpriteRestoreUnder is now 119%, above + floor, after the clock fix). A 2026-07-06 shared fix -- inlining the + per-row widen in surfaceMarkDirtyRows (removing an 8x function call in + every multi-row stage op's dirty mark) -- lifted all ST multi-row ops + ~2-5% (tileFill 1516->1574, spriteDraw 585->607, tileCopy 1307->1366, + fillRect16 to 100%), the ST/Amiga counterpart to the IIgs asm marker. The ST jlSpriteDraw case was investigated 2026-07-06 and is ARCHITECTURAL, the same root as the ST circle gap: DRAW is already compiled (JIT, shifts 0/1), but the word-interleaved planar layout forces `move.b #imm,(d16,An)` (~18 cyc) per plane byte, diff --git a/examples/uber/uber.c b/examples/uber/uber.c index 43eb004..56880c6 100644 --- a/examples/uber/uber.c +++ b/examples/uber/uber.c @@ -117,6 +117,18 @@ static unsigned char gBackupBytes[256]; static jlTileT gTileScratch; +// Phase 0 workload rows (NATIVE-PERF-PLAN.md item 3): patterned tiles +// seeded via draw+snap (tile pixels are platform-private; only a snap +// round-trips portably) and dedicated gameFrame sprite backups so the +// correctness-check gBackup state stays untouched. +static jlTileT gTileMapA; +static jlTileT gTileMapB; + +#define UBER_FRAME_SPRITES 3 + +static jlSpriteBackupT gFrameBackups[UBER_FRAME_SPRITES]; +static unsigned char gFrameBackupBytes[UBER_FRAME_SPRITES][256]; + // Current timed-op number (1-based); mirrored into the mailbox. Lives // up here because runForFrames re-writes it every loop pass: the SHR @@ -302,6 +314,106 @@ static void op_surfaceMarkDirty(void) { /* jlDrawPixel already marks; use fill i jlFillRect(gStage, 0, 0, 32, 32, 0); } +// ----- Phase 0 workload ops (NATIVE-PERF-PLAN.md item 3) ----- + +// Worst-case unaligned x on every port at once: odd -> IIgs/DOS +// compiled shift-1 (widened RMW row); x % 8 == 7 -> ST shift index 2 +// (never compiled, interpreted jlpSpriteDrawPlanes) and Amiga shift 7 +// (only shift 0 compiled) with the maximal 7-bit spill across three +// plane bytes per row. Phase 1's all-shift emitters must pull this row +// to ~parity with the aligned jlSpriteDraw row. +#define UBER_UNALIGNED_X 71 +#define UBER_UNALIGNED_Y 120 + +static void op_spriteDrawUnaligned(void) { jlSpriteDraw(gStage, gSprite, UBER_UNALIGNED_X, UBER_UNALIGNED_Y); } + + +// All 16 x phases in ONE call so the op is idempotent: per-port +// iteration counts and the 16-call unrolled batch would otherwise +// leave a port-dependent final x and a port-dependent hash. 208..223 +// covers each Amiga shift twice, both ST compiled shifts (208, 216) +// plus all 14 interpreter phases, and 8 even + 8 odd IIgs/DOS draws. +// Reported ops/sec is SWEEPS per second: multiply by 16 for draws/sec. +#define UBER_SWEEP_X0 208 +#define UBER_SWEEP_Y 120 + +static void op_spriteDrawSweep(void) { + int16_t x; + + for (x = UBER_SWEEP_X0; x < (int16_t)(UBER_SWEEP_X0 + 16); x++) { + jlSpriteDraw(gStage, gSprite, x, UBER_SWEEP_Y); + } +} + + +// 50 single-tile pastes = the per-call wrapper tax paid 50 times; the +// Phase 3 jlTileMapPaste batch API must beat this row by roughly the +// per-call overhead fraction. Fixed checker of two snapped tiles. +#define UBER_TILEMAP_X0 12 +#define UBER_TILEMAP_Y0 12 +#define UBER_TILEMAP_W 10 +#define UBER_TILEMAP_H 5 + +static void op_tileMapPaste(void) { + uint8_t tx; + uint8_t ty; + + for (ty = 0; ty < UBER_TILEMAP_H; ty++) { + for (tx = 0; tx < UBER_TILEMAP_W; tx++) { + if (((tx + ty) & 1u) == 0u) { + jlTilePaste(gStage, (uint8_t)(UBER_TILEMAP_X0 + tx), (uint8_t)(UBER_TILEMAP_Y0 + ty), &gTileMapA); + } else { + jlTilePaste(gStage, (uint8_t)(UBER_TILEMAP_X0 + tx), (uint8_t)(UBER_TILEMAP_Y0 + ty), &gTileMapB); + } + } + } +} + + +// One realistic game frame: repaint a play region, paste a HUD tile +// row, save+draw three sprites, restore them in reverse, present. +// The fill runs FIRST in the same call, so the saves always capture +// UBER_FRAME_BG and the surface is net-identical after every call -- +// the post-window hash is iteration-count independent. All sprite x +// are mod-16-aligned (compiled shift 0 on every port): this row +// isolates the per-call wrapper tax + present; the rows above own the +// alignment signal. Presenting a re-dirtied stage every call also +// fixes the present-row artifact (the timed jlStagePresent row goes +// idle after its first copy). +#define UBER_FRAME_RX 32 +#define UBER_FRAME_RY 64 +#define UBER_FRAME_RW 256 +#define UBER_FRAME_RH 96 +#define UBER_FRAME_BG 6 +#define UBER_FRAME_TILES 16 +#define UBER_FRAME_TILE_TX 4 +#define UBER_FRAME_TILE_TY 8 + +static const int16_t gFrameSpriteX[UBER_FRAME_SPRITES] = { 48, 144, 240 }; +static const int16_t gFrameSpriteY[UBER_FRAME_SPRITES] = { 80, 96, 112 }; + +static void op_gameFrame(void) { + int16_t i; + uint8_t t; + + jlFillRect(gStage, UBER_FRAME_RX, UBER_FRAME_RY, UBER_FRAME_RW, UBER_FRAME_RH, UBER_FRAME_BG); + for (t = 0; t < UBER_FRAME_TILES; t++) { + if ((t & 1u) == 0u) { + jlTilePaste(gStage, (uint8_t)(UBER_FRAME_TILE_TX + t), UBER_FRAME_TILE_TY, &gTileMapA); + } else { + jlTilePaste(gStage, (uint8_t)(UBER_FRAME_TILE_TX + t), UBER_FRAME_TILE_TY, &gTileMapB); + } + } + for (i = 0; i < UBER_FRAME_SPRITES; i++) { + jlSpriteSaveAndDraw(gStage, gSprite, gFrameSpriteX[i], gFrameSpriteY[i], &gFrameBackups[i]); + } + for (i = UBER_FRAME_SPRITES - 1; i >= 0; i--) { + jlSpriteRestoreUnder(gStage, &gFrameBackups[i]); + } + jlStagePresent(); +} + + // ----- Build the ball sprite procedurally ----- #define BALL_TILES_X 2 @@ -896,6 +1008,31 @@ static void __attribute__((noinline)) runAllTests(void) { // Surface mark dirty (via jlFillRect's mark step). timeOp("surfaceMarkDirtyRect (via jlFillRect 32x32)", op_surfaceMarkDirty); + // ----- Phase 0 workload rows (NATIVE-PERF-PLAN.md item 3). Appended + // last on purpose: timed hashes are cumulative and the correctness + // checks clear the stage first, so the frozen lines above stay + // bit-identical (Phase-7 golden-extension precedent). + timeOp("jlSpriteDraw unaligned", op_spriteDrawUnaligned); + timeOp("jlSpriteDraw sweep16", op_spriteDrawSweep); + + // Seed two patterned tiles via portable draws + snap. jlTileT.pixels + // is platform-private (plane bytes on ST/Amiga), so hand-written + // bytes would render differently per port; only a snap round-trips. + jlFillRect(gStage, 0, 72, 4, 4, 3); + jlFillRect(gStage, 4, 72, 4, 4, 5); + jlFillRect(gStage, 0, 76, 4, 4, 5); + jlFillRect(gStage, 4, 76, 4, 4, 3); + jlTileSnap(gStage, 0, 9, &gTileMapA); + jlFillRect(gStage, 8, 72, 8, 8, 9); + jlDrawLine(gStage, 8, 72, 15, 79, 1); + jlTileSnap(gStage, 1, 9, &gTileMapB); + gFrameBackups[0].bytes = gFrameBackupBytes[0]; + gFrameBackups[1].bytes = gFrameBackupBytes[1]; + gFrameBackups[2].bytes = gFrameBackupBytes[2]; + + timeOp("jlTilePaste map 10x5", op_tileMapPaste); + timeOp("gameFrame composite", op_gameFrame); + jlLogF("UBER: ----- end -----\n"); } diff --git a/src/atarist/hal.c b/src/atarist/hal.c index 607a966..442c165 100644 --- a/src/atarist/hal.c +++ b/src/atarist/hal.c @@ -1368,15 +1368,11 @@ void jlpTileFill(jlSurfaceT *s, uint8_t bx, uint8_t by, uint8_t colorIndex) { uint16_t halfMask; uint8_t *gp; - if (s->portData == NULL) { - jlpGenericTileFill(s, bx, by, colorIndex); - return; - } - if (s == NULL) { - return; - } + // Core jlTileFill already proved s != NULL and clipped bx/by; only + // the non-planar (offscreen, no portData) fallback needs handling. pd = (StPlanarT *)s->portData; if (pd == NULL) { + jlpGenericTileFill(s, bx, by, colorIndex); return; } group = (uint16_t)((uint16_t)bx >> 1); diff --git a/src/core/surface.c b/src/core/surface.c index f70f7f1..acfc98d 100644 --- a/src/core/surface.c +++ b/src/core/surface.c @@ -43,19 +43,9 @@ bool gStagePaletteDirty = true; // ----- Internal helpers (alphabetical) ----- -// widenRow serves only the non-IIgs surfaceMarkDirtyRows loop; the -// IIgs multi-row path is the asm marker and the single-row path is -// inlined by the surfaceMarkDirtyRect macro (surfaceInternal.h). -#ifndef JOEYLIB_PLATFORM_IIGS -static void widenRow(int16_t y, uint8_t minWord, uint8_t maxWord) { - if (minWord < gStageMinWord[y]) { - gStageMinWord[y] = minWord; - } - if (maxWord > gStageMaxWord[y]) { - gStageMaxWord[y] = maxWord; - } -} -#endif +// (surfaceMarkDirtyRows inlines the per-row widen with walking pointers +// -- see below. The single-row widen is inlined by the surfaceMarkDirtyRect +// macro, and the IIgs multi-row path is the asm marker.) // ----- Public API (alphabetical) ----- @@ -243,10 +233,27 @@ void surfaceMarkDirtyAll(const jlSurfaceT *s) { // iigsMarkDirtyRowsInner instead. #ifndef JOEYLIB_PLATFORM_IIGS void surfaceMarkDirtyRows(uint16_t y, uint16_t yEnd, uint8_t minWord, uint8_t maxWord) { - uint16_t row; + uint8_t *minPtr; + uint8_t *maxPtr; + uint8_t *minEnd; - for (row = y; row < yEnd; row++) { - widenRow((int16_t)row, minWord, maxWord); + // Straight-line inlined widen (no per-row helper call) with walking + // pointers, so a multi-row stage op -- tile fill/paste/copy, sprite + // draw, fillRect -- pays one tight loop instead of yEnd-y function + // calls. This is the ST/Amiga counterpart to the IIgs asm marker; + // the 8-row tile mark was ~a third of jlTileFill's cost. + minPtr = &gStageMinWord[y]; + maxPtr = &gStageMaxWord[y]; + minEnd = &gStageMinWord[yEnd]; + while (minPtr < minEnd) { + if (minWord < *minPtr) { + *minPtr = minWord; + } + if (maxWord > *maxPtr) { + *maxPtr = maxWord; + } + minPtr++; + maxPtr++; } } #endif diff --git a/tests/goldens/uber/amiga.txt b/tests/goldens/uber/amiga.txt index ffc77dc..e55e91d 100644 --- a/tests/goldens/uber/amiga.txt +++ b/tests/goldens/uber/amiga.txt @@ -12,69 +12,151 @@ UBER: ----- begin ----- UBER: jlSurfaceClear: 33 iters / 22 frames = 75 ops/sec | hash=428CEE42 -UBER: jlPaletteSet: 2145 iters / 16 frames = 6703 ops/sec | hash=5267FFB1 +UBER-CLK: jlSurfaceClear: frame=75 millis=75 ops/sec (440 ms) -UBER: jlScbSetRange: 1233 iters / 16 frames = 3853 ops/sec | hash=5267FFB1 +UBER: jlPaletteSet: 3681 iters / 16 frames = 11503 ops/sec | hash=5267FFB1 -UBER: jlDrawPixel: 1361 iters / 16 frames = 4253 ops/sec | hash=75D75161 +UBER-CLK: jlPaletteSet: frame=11503 millis=11503 ops/sec (320 ms) -UBER: jlDrawLine H: 513 iters / 16 frames = 1603 ops/sec | hash=1E97E361 +UBER: jlScbSetRange: 1265 iters / 16 frames = 3953 ops/sec | hash=5267FFB1 -UBER: jlDrawLine V: 49 iters / 16 frames = 153 ops/sec | hash=A0474D91 +UBER-CLK: jlScbSetRange: frame=3953 millis=3953 ops/sec (320 ms) + +UBER: jlDrawPixel: 1873 iters / 16 frames = 5853 ops/sec | hash=75D75161 + +UBER-CLK: jlDrawPixel: frame=5853 millis=5853 ops/sec (320 ms) + +UBER: jlDrawLine H: 545 iters / 16 frames = 1703 ops/sec | hash=1E97E361 + +UBER-CLK: jlDrawLine H: frame=1703 millis=1703 ops/sec (320 ms) + +UBER: jlDrawLine V: 97 iters / 18 frames = 269 ops/sec | hash=A0474D91 + +UBER-CLK: jlDrawLine V: frame=269 millis=269 ops/sec (360 ms) UBER: jlDrawLine diag: 13 iters / 16 frames = 40 ops/sec | hash=69471D91 -UBER: jlDrawRect 100x100: 49 iters / 19 frames = 128 ops/sec | hash=5CAFF471 +UBER-CLK: jlDrawLine diag: frame=40 millis=40 ops/sec (320 ms) + +UBER: jlDrawRect 100x100: 65 iters / 16 frames = 203 ops/sec | hash=5CAFF471 + +UBER-CLK: jlDrawRect 100x100: frame=203 millis=203 ops/sec (320 ms) UBER: jlDrawCircle r=16: 97 iters / 17 frames = 285 ops/sec | hash=7F1F5531 +UBER-CLK: jlDrawCircle r=16: frame=285 millis=285 ops/sec (340 ms) + UBER: jlDrawCircle r=80: 33 iters / 26 frames = 63 ops/sec | hash=B249C9AB -UBER: jlFillRect 16x16: 193 iters / 17 frames = 567 ops/sec | hash=F4BD4B0B +UBER-CLK: jlDrawCircle r=80: frame=63 millis=63 ops/sec (520 ms) -UBER: jlFillRect 80x80: 33 iters / 23 frames = 71 ops/sec | hash=7C952E5F +UBER: jlFillRect 16x16: 369 iters / 16 frames = 1153 ops/sec | hash=F4BD4B0B -UBER: jlFillRect 320x200: 33 iters / 24 frames = 68 ops/sec | hash=6467AFB1 +UBER-CLK: jlFillRect 16x16: frame=1153 millis=1153 ops/sec (320 ms) + +UBER: jlFillRect 80x80: 97 iters / 18 frames = 269 ops/sec | hash=7C952E5F + +UBER-CLK: jlFillRect 80x80: frame=269 millis=269 ops/sec (360 ms) + +UBER: jlFillRect 320x200: 33 iters / 25 frames = 66 ops/sec | hash=6467AFB1 + +UBER-CLK: jlFillRect 320x200: frame=66 millis=66 ops/sec (500 ms) UBER: jlFillCircle r=40: 10 iters / 16 frames = 31 ops/sec | hash=6467AFB1 +UBER-CLK: jlFillCircle r=40: frame=31 millis=31 ops/sec (320 ms) + UBER: jlSamplePixel: 2321 iters / 16 frames = 7253 ops/sec | hash=6467AFB1 -UBER: jlTileFill: 721 iters / 16 frames = 2253 ops/sec | hash=6467AFB1 +UBER-CLK: jlSamplePixel: frame=7253 millis=7253 ops/sec (320 ms) + +UBER: jlTileFill: 737 iters / 16 frames = 2303 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileFill: frame=2303 millis=2303 ops/sec (320 ms) UBER: jlTileCopy: 593 iters / 16 frames = 1853 ops/sec | hash=6467AFB1 +UBER-CLK: jlTileCopy: frame=1853 millis=1853 ops/sec (320 ms) + UBER: jlTileCopyMasked: 305 iters / 16 frames = 953 ops/sec | hash=6467AFB1 +UBER-CLK: jlTileCopyMasked: frame=953 millis=953 ops/sec (320 ms) + UBER: jlTilePaste: 737 iters / 16 frames = 2303 ops/sec | hash=6467AFB1 -UBER: jlTileSnap: 1137 iters / 16 frames = 3553 ops/sec | hash=6467AFB1 +UBER-CLK: jlTilePaste: frame=2303 millis=2303 ops/sec (320 ms) -UBER: jlSpriteSaveUnder: 177 iters / 16 frames = 553 ops/sec | hash=CA673FB1 +UBER: jlTileSnap: 1121 iters / 16 frames = 3503 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileSnap: frame=3503 millis=3503 ops/sec (320 ms) + +UBER: jlSpriteSaveUnder: 193 iters / 17 frames = 567 ops/sec | hash=CA673FB1 + +UBER-CLK: jlSpriteSaveUnder: frame=567 millis=567 ops/sec (340 ms) UBER: jlSpriteDraw: 305 iters / 16 frames = 953 ops/sec | hash=82B9646B +UBER-CLK: jlSpriteDraw: frame=953 millis=953 ops/sec (320 ms) + UBER: jlSpriteRestoreUnder: 177 iters / 16 frames = 553 ops/sec | hash=CA673FB1 -UBER: jlSpriteSaveAndDraw: 113 iters / 16 frames = 353 ops/sec | hash=82B9646B +UBER-CLK: jlSpriteRestoreUnder: frame=553 millis=553 ops/sec (320 ms) -UBER: jlStagePresent full: 105 iters / 16 frames = 328 ops/sec | hash=82B9646B +UBER: jlSpriteSaveAndDraw: 113 iters / 17 frames = 332 ops/sec | hash=82B9646B + +UBER-CLK: jlSpriteSaveAndDraw: frame=332 millis=332 ops/sec (340 ms) + +UBER: jlStagePresent full: 115 iters / 16 frames = 359 ops/sec | hash=82B9646B + +UBER-CLK: jlStagePresent full: frame=359 millis=359 ops/sec (320 ms) UBER: jlInputPoll: 1281 iters / 16 frames = 4003 ops/sec | hash=82B9646B -UBER: jlKeyDown: 12737 iters / 16 frames = 39803 ops/sec | hash=82B9646B +UBER-CLK: jlInputPoll: frame=4003 millis=4003 ops/sec (320 ms) + +UBER: jlKeyDown: 12721 iters / 16 frames = 39753 ops/sec | hash=82B9646B + +UBER-CLK: jlKeyDown: frame=39753 millis=39753 ops/sec (320 ms) UBER: jlKeyPressed: 12161 iters / 16 frames = 38003 ops/sec | hash=82B9646B +UBER-CLK: jlKeyPressed: frame=38003 millis=38003 ops/sec (320 ms) + UBER: jlMouseX: 31265 iters / 16 frames = 97703 ops/sec | hash=82B9646B -UBER: joeyJoyConnected: 12465 iters / 16 frames = 38953 ops/sec | hash=82B9646B +UBER-CLK: jlMouseX: frame=97703 millis=97703 ops/sec (320 ms) -UBER: jlAudioFrameTick: 18241 iters / 16 frames = 57003 ops/sec | hash=82B9646B +UBER: joeyJoyConnected: 12449 iters / 16 frames = 38903 ops/sec | hash=82B9646B -UBER: jlAudioIsPlayingMod: 17857 iters / 16 frames = 55803 ops/sec | hash=82B9646B +UBER-CLK: joeyJoyConnected: frame=38903 millis=38903 ops/sec (320 ms) -UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 113 iters / 16 frames = 353 ops/sec | hash=D2B9E46B +UBER: jlAudioFrameTick: 18065 iters / 16 frames = 56453 ops/sec | hash=82B9646B + +UBER-CLK: jlAudioFrameTick: frame=56453 millis=56453 ops/sec (320 ms) + +UBER: jlAudioIsPlayingMod: 18081 iters / 16 frames = 56503 ops/sec | hash=82B9646B + +UBER-CLK: jlAudioIsPlayingMod: frame=56503 millis=56503 ops/sec (320 ms) + +UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 273 iters / 16 frames = 853 ops/sec | hash=D2B9E46B + +UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=853 millis=853 ops/sec (320 ms) + +UBER: jlSpriteDraw unaligned: 33 iters / 22 frames = 75 ops/sec | hash=69CEBB34 + +UBER-CLK: jlSpriteDraw unaligned: frame=75 millis=75 ops/sec (440 ms) + +UBER: jlSpriteDraw sweep16: 2 iters / 19 frames = 5 ops/sec | hash=24E7E0C9 + +UBER-CLK: jlSpriteDraw sweep16: frame=5 millis=5 ops/sec (380 ms) + +UBER: jlTilePaste map 10x5: 15 iters / 16 frames = 46 ops/sec | hash=92E7B0C9 + +UBER-CLK: jlTilePaste map 10x5: frame=46 millis=46 ops/sec (320 ms) + +UBER: gameFrame composite: 6 iters / 16 frames = 18 ops/sec | hash=55B9EC6B + +UBER-CLK: gameFrame composite: frame=18 millis=18 ops/sec (320 ms) UBER: ----- end ----- @@ -116,5 +198,7 @@ UBER-CHK: floodFillBounded: hash=EF6B6F51 UBER-CHK: ----- end ----- -UBER: total wall time: 145820 ms (7291 frames @ 50 Hz) +UBER: total wall time: 165280 ms (8264 frames @ 50 Hz) + +UBER: press any key to exit diff --git a/tests/goldens/uber/atarist.txt b/tests/goldens/uber/atarist.txt index cd6d43f..27bd8ef 100644 --- a/tests/goldens/uber/atarist.txt +++ b/tests/goldens/uber/atarist.txt @@ -6,71 +6,153 @@ UBER: showcase cells: 0=pixels 1=lineH 2=lineV 3=diag 4=rect 5=fillRect 6=circle UBER: ----- begin ----- -UBER: jlSurfaceClear: 12 iters / 16 frames = 37 ops/sec | hash=428CEE42 +UBER: jlSurfaceClear: 12 iters / 16 frames = 44 ops/sec | hash=428CEE42 -UBER: jlPaletteSet: 1009 iters / 16 frames = 3153 ops/sec | hash=5267FFB1 +UBER-CLK: jlSurfaceClear: frame=45 millis=44 ops/sec (270 ms) -UBER: jlScbSetRange: 641 iters / 16 frames = 2003 ops/sec | hash=5267FFB1 +UBER: jlPaletteSet: 1393 iters / 16 frames = 5256 ops/sec | hash=5267FFB1 -UBER: jlDrawPixel: 721 iters / 16 frames = 2253 ops/sec | hash=75D75161 +UBER-CLK: jlPaletteSet: frame=5223 millis=5256 ops/sec (265 ms) -UBER: jlDrawLine H: 369 iters / 16 frames = 1153 ops/sec | hash=1E97E361 +UBER: jlScbSetRange: 641 iters / 16 frames = 2418 ops/sec | hash=5267FFB1 -UBER: jlDrawLine V: 33 iters / 16 frames = 103 ops/sec | hash=A0474D91 +UBER-CLK: jlScbSetRange: frame=2403 millis=2418 ops/sec (265 ms) -UBER: jlDrawLine diag: 12 iters / 16 frames = 37 ops/sec | hash=69471D91 +UBER: jlDrawPixel: 897 iters / 16 frames = 3384 ops/sec | hash=75D75161 -UBER: jlDrawRect 100x100: 33 iters / 19 frames = 86 ops/sec | hash=5CAFF471 +UBER-CLK: jlDrawPixel: frame=3363 millis=3384 ops/sec (265 ms) -UBER: jlDrawCircle r=16: 49 iters / 16 frames = 153 ops/sec | hash=7F1F5531 +UBER: jlDrawLine H: 369 iters / 16 frames = 1341 ops/sec | hash=1E97E361 -UBER: jlDrawCircle r=80: 11 iters / 16 frames = 34 ops/sec | hash=B249C9AB +UBER-CLK: jlDrawLine H: frame=1383 millis=1341 ops/sec (275 ms) -UBER: jlFillRect 16x16: 177 iters / 17 frames = 520 ops/sec | hash=F4BD4B0B +UBER: jlDrawLine V: 49 iters / 22 frames = 132 ops/sec | hash=A0474D91 -UBER: jlFillRect 80x80: 33 iters / 16 frames = 103 ops/sec | hash=7C952E5F +UBER-CLK: jlDrawLine V: frame=133 millis=132 ops/sec (370 ms) -UBER: jlFillRect 320x200: 11 iters / 17 frames = 32 ops/sec | hash=6467AFB1 +UBER: jlDrawLine diag: 12 iters / 16 frames = 43 ops/sec | hash=69471D91 -UBER: jlFillCircle r=40: 33 iters / 26 frames = 63 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawLine diag: frame=45 millis=43 ops/sec (275 ms) -UBER: jlSamplePixel: 1313 iters / 16 frames = 4103 ops/sec | hash=6467AFB1 +UBER: jlDrawRect 100x100: 33 iters / 18 frames = 108 ops/sec | hash=5CAFF471 -UBER: jlTileFill: 417 iters / 16 frames = 1303 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawRect 100x100: frame=110 millis=108 ops/sec (305 ms) -UBER: jlTileCopy: 353 iters / 16 frames = 1103 ops/sec | hash=6467AFB1 +UBER: jlDrawCircle r=16: 49 iters / 16 frames = 184 ops/sec | hash=7F1F5531 -UBER: jlTileCopyMasked: 193 iters / 17 frames = 567 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawCircle r=16: frame=183 millis=184 ops/sec (265 ms) -UBER: jlTilePaste: 417 iters / 16 frames = 1303 ops/sec | hash=6467AFB1 +UBER: jlDrawCircle r=80: 12 iters / 17 frames = 42 ops/sec | hash=B249C9AB -UBER: jlTileSnap: 785 iters / 16 frames = 2453 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawCircle r=80: frame=42 millis=42 ops/sec (285 ms) -UBER: jlSpriteSaveUnder: 225 iters / 16 frames = 703 ops/sec | hash=CA673FB1 +UBER: jlFillRect 16x16: 177 iters / 17 frames = 610 ops/sec | hash=F4BD4B0B -UBER: jlSpriteDraw: 161 iters / 16 frames = 503 ops/sec | hash=82B9646B +UBER-CLK: jlFillRect 16x16: frame=624 millis=610 ops/sec (290 ms) -UBER: jlSpriteRestoreUnder: 177 iters / 16 frames = 553 ops/sec | hash=CA673FB1 +UBER: jlFillRect 80x80: 33 iters / 16 frames = 120 ops/sec | hash=7C952E5F -UBER: jlSpriteSaveAndDraw: 97 iters / 18 frames = 269 ops/sec | hash=82B9646B +UBER-CLK: jlFillRect 80x80: frame=123 millis=120 ops/sec (275 ms) -UBER: jlStagePresent full: 15 iters / 16 frames = 46 ops/sec | hash=82B9646B +UBER: jlFillRect 320x200: 11 iters / 16 frames = 40 ops/sec | hash=6467AFB1 -UBER: jlInputPoll: 385 iters / 16 frames = 1203 ops/sec | hash=82B9646B +UBER-CLK: jlFillRect 320x200: frame=41 millis=40 ops/sec (275 ms) -UBER: jlKeyDown: 6049 iters / 16 frames = 18903 ops/sec | hash=82B9646B +UBER: jlFillCircle r=40: 33 iters / 25 frames = 77 ops/sec | hash=6467AFB1 -UBER: jlKeyPressed: 6049 iters / 16 frames = 18903 ops/sec | hash=82B9646B +UBER-CLK: jlFillCircle r=40: frame=79 millis=77 ops/sec (425 ms) -UBER: jlMouseX: 15745 iters / 16 frames = 49203 ops/sec | hash=82B9646B +UBER: jlSamplePixel: 1313 iters / 16 frames = 4862 ops/sec | hash=6467AFB1 -UBER: joeyJoyConnected: 5921 iters / 16 frames = 18503 ops/sec | hash=82B9646B +UBER-CLK: jlSamplePixel: frame=4923 millis=4862 ops/sec (270 ms) -UBER: jlAudioFrameTick: 3152 iters / 16 frames = 9850 ops/sec | hash=82B9646B +UBER: jlTileFill: 433 iters / 16 frames = 1603 ops/sec | hash=6467AFB1 -UBER: jlAudioIsPlayingMod: 8065 iters / 16 frames = 25203 ops/sec | hash=82B9646B +UBER-CLK: jlTileFill: frame=1623 millis=1603 ops/sec (270 ms) -UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 113 iters / 17 frames = 332 ops/sec | hash=D2B9E46B +UBER: jlTileCopy: 369 iters / 16 frames = 1341 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileCopy: frame=1383 millis=1341 ops/sec (275 ms) + +UBER: jlTileCopyMasked: 193 iters / 16 frames = 689 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileCopyMasked: frame=723 millis=689 ops/sec (280 ms) + +UBER: jlTilePaste: 433 iters / 16 frames = 1574 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTilePaste: frame=1623 millis=1574 ops/sec (275 ms) + +UBER: jlTileSnap: 785 iters / 16 frames = 2907 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileSnap: frame=2943 millis=2907 ops/sec (270 ms) + +UBER: jlSpriteSaveUnder: 225 iters / 16 frames = 849 ops/sec | hash=CA673FB1 + +UBER-CLK: jlSpriteSaveUnder: frame=843 millis=849 ops/sec (265 ms) + +UBER: jlSpriteDraw: 161 iters / 16 frames = 607 ops/sec | hash=82B9646B + +UBER-CLK: jlSpriteDraw: frame=603 millis=607 ops/sec (265 ms) + +UBER: jlSpriteRestoreUnder: 193 iters / 17 frames = 689 ops/sec | hash=CA673FB1 + +UBER-CLK: jlSpriteRestoreUnder: frame=681 millis=689 ops/sec (280 ms) + +UBER: jlSpriteSaveAndDraw: 97 iters / 17 frames = 328 ops/sec | hash=82B9646B + +UBER-CLK: jlSpriteSaveAndDraw: frame=342 millis=328 ops/sec (295 ms) + +UBER: jlStagePresent full: 15 iters / 16 frames = 55 ops/sec | hash=82B9646B + +UBER-CLK: jlStagePresent full: frame=56 millis=55 ops/sec (270 ms) + +UBER: jlInputPoll: 385 iters / 16 frames = 1400 ops/sec | hash=82B9646B + +UBER-CLK: jlInputPoll: frame=1443 millis=1400 ops/sec (275 ms) + +UBER: jlKeyDown: 6049 iters / 16 frames = 22403 ops/sec | hash=82B9646B + +UBER-CLK: jlKeyDown: frame=22683 millis=22403 ops/sec (270 ms) + +UBER: jlKeyPressed: 6033 iters / 16 frames = 22344 ops/sec | hash=82B9646B + +UBER-CLK: jlKeyPressed: frame=22623 millis=22344 ops/sec (270 ms) + +UBER: jlMouseX: 15745 iters / 16 frames = 58314 ops/sec | hash=82B9646B + +UBER-CLK: jlMouseX: frame=59043 millis=58314 ops/sec (270 ms) + +UBER: joeyJoyConnected: 5905 iters / 16 frames = 21870 ops/sec | hash=82B9646B + +UBER-CLK: joeyJoyConnected: frame=22143 millis=21870 ops/sec (270 ms) + +UBER: jlAudioFrameTick: 3109 iters / 16 frames = 11732 ops/sec | hash=82B9646B + +UBER-CLK: jlAudioFrameTick: frame=11658 millis=11732 ops/sec (265 ms) + +UBER: jlAudioIsPlayingMod: 8065 iters / 16 frames = 29870 ops/sec | hash=82B9646B + +UBER-CLK: jlAudioIsPlayingMod: frame=30243 millis=29870 ops/sec (270 ms) + +UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 113 iters / 17 frames = 389 ops/sec | hash=D2B9E46B + +UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=398 millis=389 ops/sec (290 ms) + +UBER: jlSpriteDraw unaligned: 11 iters / 16 frames = 40 ops/sec | hash=69CEBB34 + +UBER-CLK: jlSpriteDraw unaligned: frame=41 millis=40 ops/sec (270 ms) + +UBER: jlSpriteDraw sweep16: 1 iters / 21 frames = 2 ops/sec | hash=24E7E0C9 + +UBER-CLK: jlSpriteDraw sweep16: frame=2 millis=2 ops/sec (350 ms) + +UBER: jlTilePaste map 10x5: 9 iters / 17 frames = 32 ops/sec | hash=92E7B0C9 + +UBER-CLK: jlTilePaste map 10x5: frame=31 millis=32 ops/sec (280 ms) + +UBER: gameFrame composite: 3 iters / 19 frames = 9 ops/sec | hash=55B9EC6B + +UBER-CLK: gameFrame composite: frame=9 millis=9 ops/sec (325 ms) UBER: ----- end ----- @@ -112,7 +194,7 @@ UBER-CHK: floodFillBounded: hash=EF6B6F51 UBER-CHK: ----- end ----- -UBER: total wall time: 302060 ms (15103 frames @ 50 Hz) +UBER: total wall time: 289833 ms (17390 frames @ 60 Hz) UBER: press any key to exit diff --git a/tests/goldens/uber/dos.txt b/tests/goldens/uber/dos.txt index c0d0349..90bd482 100644 --- a/tests/goldens/uber/dos.txt +++ b/tests/goldens/uber/dos.txt @@ -6,71 +6,153 @@ UBER: showcase cells: 0=pixels 1=lineH 2=lineV 3=diag 4=rect 5=fillRect 6=circle UBER: ----- begin ----- -UBER: jlSurfaceClear: 16 iters / 17 frames = 65 ops/sec | hash=428CEE42 +UBER: jlSurfaceClear: 16 iters / 16 frames = 66 ops/sec | hash=428CEE42 -UBER: jlPaletteSet: 3505 iters / 16 frames = 15334 ops/sec | hash=5267FFB1 +UBER-CLK: jlSurfaceClear: frame=70 millis=66 ops/sec (239 ms) -UBER: jlScbSetRange: 1889 iters / 16 frames = 8264 ops/sec | hash=5267FFB1 +UBER: jlPaletteSet: 6737 iters / 16 frames = 29809 ops/sec | hash=5267FFB1 -UBER: jlDrawPixel: 3985 iters / 16 frames = 17434 ops/sec | hash=75D75161 +UBER-CLK: jlPaletteSet: frame=29474 millis=29809 ops/sec (226 ms) -UBER: jlDrawLine H: 1329 iters / 16 frames = 5814 ops/sec | hash=1E97E361 +UBER: jlScbSetRange: 1937 iters / 16 frames = 8495 ops/sec | hash=5267FFB1 -UBER: jlDrawLine V: 81 iters / 16 frames = 354 ops/sec | hash=A0474D91 +UBER-CLK: jlScbSetRange: frame=8474 millis=8495 ops/sec (228 ms) -UBER: jlDrawLine diag: 33 iters / 24 frames = 96 ops/sec | hash=69471D91 +UBER: jlDrawPixel: 5393 iters / 16 frames = 23757 ops/sec | hash=75D75161 -UBER: jlDrawRect 100x100: 81 iters / 16 frames = 354 ops/sec | hash=5CAFF471 +UBER-CLK: jlDrawPixel: frame=23594 millis=23757 ops/sec (227 ms) -UBER: jlDrawCircle r=16: 85 iters / 16 frames = 371 ops/sec | hash=7F1F5531 +UBER: jlDrawLine H: 1313 iters / 16 frames = 5708 ops/sec | hash=1E97E361 -UBER: jlDrawCircle r=80: 19 iters / 16 frames = 83 ops/sec | hash=B249C9AB +UBER-CLK: jlDrawLine H: frame=5744 millis=5708 ops/sec (230 ms) -UBER: jlFillRect 16x16: 609 iters / 16 frames = 2664 ops/sec | hash=F4BD4B0B +UBER: jlDrawLine V: 113 iters / 16 frames = 470 ops/sec | hash=A0474D91 -UBER: jlFillRect 80x80: 81 iters / 16 frames = 354 ops/sec | hash=7C952E5F +UBER-CLK: jlDrawLine V: frame=494 millis=470 ops/sec (240 ms) -UBER: jlFillRect 320x200: 13 iters / 16 frames = 56 ops/sec | hash=6467AFB1 +UBER: jlDrawLine diag: 33 iters / 21 frames = 109 ops/sec | hash=69471D91 -UBER: jlFillCircle r=40: 29 iters / 16 frames = 126 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawLine diag: frame=110 millis=109 ops/sec (301 ms) -UBER: jlSamplePixel: 8321 iters / 16 frames = 36404 ops/sec | hash=6467AFB1 +UBER: jlDrawRect 100x100: 82 iters / 16 frames = 377 ops/sec | hash=5CAFF471 -UBER: jlTileFill: 2081 iters / 16 frames = 9104 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawRect 100x100: frame=358 millis=377 ops/sec (217 ms) -UBER: jlTileCopy: 1569 iters / 16 frames = 6864 ops/sec | hash=6467AFB1 +UBER: jlDrawCircle r=16: 97 iters / 16 frames = 449 ops/sec | hash=7F1F5531 -UBER: jlTileCopyMasked: 545 iters / 16 frames = 2384 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawCircle r=16: frame=424 millis=449 ops/sec (216 ms) -UBER: jlTilePaste: 1825 iters / 16 frames = 7984 ops/sec | hash=6467AFB1 +UBER: jlDrawCircle r=80: 22 iters / 16 frames = 98 ops/sec | hash=B249C9AB -UBER: jlTileSnap: 2993 iters / 16 frames = 13094 ops/sec | hash=6467AFB1 +UBER-CLK: jlDrawCircle r=80: frame=96 millis=98 ops/sec (223 ms) -UBER: jlSpriteSaveUnder: 1937 iters / 16 frames = 8474 ops/sec | hash=CA673FB1 +UBER: jlFillRect 16x16: 657 iters / 16 frames = 3013 ops/sec | hash=F4BD4B0B -UBER: jlSpriteDraw: 1393 iters / 16 frames = 6094 ops/sec | hash=82B9646B +UBER-CLK: jlFillRect 16x16: frame=2874 millis=3013 ops/sec (218 ms) -UBER: jlSpriteRestoreUnder: 1297 iters / 16 frames = 5674 ops/sec | hash=CA673FB1 +UBER: jlFillRect 80x80: 97 iters / 17 frames = 414 ops/sec | hash=7C952E5F -UBER: jlSpriteSaveAndDraw: 961 iters / 16 frames = 4204 ops/sec | hash=82B9646B +UBER-CLK: jlFillRect 80x80: frame=399 millis=414 ops/sec (234 ms) -UBER: jlStagePresent full: 81 iters / 16 frames = 354 ops/sec | hash=82B9646B +UBER: jlFillRect 320x200: 13 iters / 16 frames = 58 ops/sec | hash=6467AFB1 -UBER: jlInputPoll: 705 iters / 16 frames = 3084 ops/sec | hash=82B9646B +UBER-CLK: jlFillRect 320x200: frame=56 millis=58 ops/sec (221 ms) -UBER: jlKeyDown: 17441 iters / 16 frames = 76304 ops/sec | hash=82B9646B +UBER: jlFillCircle r=40: 35 iters / 16 frames = 156 ops/sec | hash=6467AFB1 -UBER: jlKeyPressed: 16897 iters / 16 frames = 73924 ops/sec | hash=82B9646B +UBER-CLK: jlFillCircle r=40: frame=153 millis=156 ops/sec (223 ms) -UBER: jlMouseX: 35105 iters / 16 frames = 153584 ops/sec | hash=82B9646B +UBER: jlSamplePixel: 10161 iters / 16 frames = 46397 ops/sec | hash=6467AFB1 -UBER: joeyJoyConnected: 17601 iters / 16 frames = 77004 ops/sec | hash=82B9646B +UBER-CLK: jlSamplePixel: frame=44454 millis=46397 ops/sec (219 ms) -UBER: jlAudioFrameTick: 13377 iters / 16 frames = 58524 ops/sec | hash=82B9646B +UBER: jlTileFill: 2049 iters / 16 frames = 9313 ops/sec | hash=6467AFB1 -UBER: jlAudioIsPlayingMod: 29041 iters / 16 frames = 127054 ops/sec | hash=82B9646B +UBER-CLK: jlTileFill: frame=8964 millis=9313 ops/sec (220 ms) -UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 305 iters / 16 frames = 1334 ops/sec | hash=D2B9E46B +UBER: jlTileCopy: 1937 iters / 16 frames = 8764 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileCopy: frame=8474 millis=8764 ops/sec (221 ms) + +UBER: jlTileCopyMasked: 705 iters / 16 frames = 3147 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileCopyMasked: frame=3084 millis=3147 ops/sec (224 ms) + +UBER: jlTilePaste: 2177 iters / 16 frames = 9806 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTilePaste: frame=9524 millis=9806 ops/sec (222 ms) + +UBER: jlTileSnap: 4273 iters / 16 frames = 19247 ops/sec | hash=6467AFB1 + +UBER-CLK: jlTileSnap: frame=18694 millis=19247 ops/sec (222 ms) + +UBER: jlSpriteSaveUnder: 2049 iters / 16 frames = 9229 ops/sec | hash=CA673FB1 + +UBER-CLK: jlSpriteSaveUnder: frame=8964 millis=9229 ops/sec (222 ms) + +UBER: jlSpriteDraw: 1393 iters / 16 frames = 6218 ops/sec | hash=82B9646B + +UBER-CLK: jlSpriteDraw: frame=6094 millis=6218 ops/sec (224 ms) + +UBER: jlSpriteRestoreUnder: 1329 iters / 16 frames = 5933 ops/sec | hash=CA673FB1 + +UBER-CLK: jlSpriteRestoreUnder: frame=5814 millis=5933 ops/sec (224 ms) + +UBER: jlSpriteSaveAndDraw: 961 iters / 16 frames = 4271 ops/sec | hash=82B9646B + +UBER-CLK: jlSpriteSaveAndDraw: frame=4204 millis=4271 ops/sec (225 ms) + +UBER: jlStagePresent full: 81 iters / 16 frames = 360 ops/sec | hash=82B9646B + +UBER-CLK: jlStagePresent full: frame=354 millis=360 ops/sec (225 ms) + +UBER: jlInputPoll: 721 iters / 16 frames = 3134 ops/sec | hash=82B9646B + +UBER-CLK: jlInputPoll: frame=3154 millis=3134 ops/sec (230 ms) + +UBER: jlKeyDown: 17505 iters / 16 frames = 77800 ops/sec | hash=82B9646B + +UBER-CLK: jlKeyDown: frame=76584 millis=77800 ops/sec (225 ms) + +UBER: jlKeyPressed: 16945 iters / 16 frames = 74977 ops/sec | hash=82B9646B + +UBER-CLK: jlKeyPressed: frame=74134 millis=74977 ops/sec (226 ms) + +UBER: jlMouseX: 35217 iters / 16 frames = 155140 ops/sec | hash=82B9646B + +UBER-CLK: jlMouseX: frame=154074 millis=155140 ops/sec (227 ms) + +UBER: joeyJoyConnected: 17665 iters / 16 frames = 77819 ops/sec | hash=82B9646B + +UBER-CLK: joeyJoyConnected: frame=77284 millis=77819 ops/sec (227 ms) + +UBER: jlAudioFrameTick: 13489 iters / 16 frames = 59162 ops/sec | hash=82B9646B + +UBER-CLK: jlAudioFrameTick: frame=59014 millis=59162 ops/sec (228 ms) + +UBER: jlAudioIsPlayingMod: 29265 iters / 16 frames = 127794 ops/sec | hash=82B9646B + +UBER-CLK: jlAudioIsPlayingMod: frame=128034 millis=127794 ops/sec (229 ms) + +UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 337 iters / 16 frames = 1478 ops/sec | hash=D2B9E46B + +UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=1474 millis=1478 ops/sec (228 ms) + +UBER: jlSpriteDraw unaligned: 1105 iters / 16 frames = 5115 ops/sec | hash=69CEBB34 + +UBER-CLK: jlSpriteDraw unaligned: frame=4834 millis=5115 ops/sec (216 ms) + +UBER: jlSpriteDraw sweep16: 77 iters / 16 frames = 353 ops/sec | hash=24E7E0C9 + +UBER-CLK: jlSpriteDraw sweep16: frame=336 millis=353 ops/sec (218 ms) + +UBER: jlTilePaste map 10x5: 44 iters / 16 frames = 200 ops/sec | hash=92E7B0C9 + +UBER-CLK: jlTilePaste map 10x5: frame=192 millis=200 ops/sec (220 ms) + +UBER: gameFrame composite: 5 iters / 19 frames = 18 ops/sec | hash=55B9EC6B + +UBER-CLK: gameFrame composite: frame=18 millis=18 ops/sec (270 ms) UBER: ----- end ----- @@ -112,7 +194,7 @@ UBER-CHK: floodFillBounded: hash=EF6B6F51 UBER-CHK: ----- end ----- -UBER: total wall time: 20928 ms (1465 frames @ 70 Hz) +UBER: total wall time: 23142 ms (1620 frames @ 70 Hz) UBER: press any key to exit diff --git a/tests/goldens/uber/iigs.txt b/tests/goldens/uber/iigs.txt index e2b9744..8cc3f42 100644 --- a/tests/goldens/uber/iigs.txt +++ b/tests/goldens/uber/iigs.txt @@ -1,41 +1,81 @@ -UBER: jlSpriteCompile failed UBER: jlSpriteCompile: 1 call in <= 1 frame UBER: audioInit OK UBER: showcase cells: 0=pixels 1=lineH 2=lineV 3=diag 4=rect 5=fillRect 6=circle 7=fillCircle 8=tiles 9=sprite 10=flood 11=scene UBER: ----- begin ----- -UBER: jlSurfaceClear: 10 iters / 17 frames = 35 ops/sec | hash=428CEE42 -UBER: jlPaletteSet: 385 iters / 16 frames = 1443 ops/sec | hash=5267FFB1 +UBER: jlSurfaceClear: 9 iters / 16 frames = 33 ops/sec | hash=428CEE42 +UBER-CLK: jlSurfaceClear: frame=33 millis=33 ops/sec (266 ms) +UBER: jlPaletteSet: 417 iters / 16 frames = 1561 ops/sec | hash=5267FFB1 +UBER-CLK: jlPaletteSet: frame=1563 millis=1561 ops/sec (267 ms) UBER: jlScbSetRange: 49 iters / 18 frames = 163 ops/sec | hash=5267FFB1 -UBER: jlDrawPixel: 865 iters / 16 frames = 3243 ops/sec | hash=75D75161 -UBER: jlDrawLine H: 273 iters / 16 frames = 1023 ops/sec | hash=1E97E361 +UBER-CLK: jlScbSetRange: frame=163 millis=163 ops/sec (300 ms) +UBER: jlDrawPixel: 849 iters / 16 frames = 3179 ops/sec | hash=75D75161 +UBER-CLK: jlDrawPixel: frame=3183 millis=3179 ops/sec (267 ms) +UBER: jlDrawLine H: 305 iters / 16 frames = 1142 ops/sec | hash=1E97E361 +UBER-CLK: jlDrawLine H: frame=1143 millis=1142 ops/sec (267 ms) UBER: jlDrawLine V: 33 iters / 20 frames = 99 ops/sec | hash=A0474D91 +UBER-CLK: jlDrawLine V: frame=99 millis=99 ops/sec (333 ms) UBER: jlDrawLine diag: 12 iters / 17 frames = 42 ops/sec | hash=69471D91 -UBER: jlDrawRect 100x100: 33 iters / 23 frames = 86 ops/sec | hash=5CAFF471 +UBER-CLK: jlDrawLine diag: frame=42 millis=42 ops/sec (284 ms) +UBER: jlDrawRect 100x100: 33 iters / 22 frames = 89 ops/sec | hash=5CAFF471 +UBER-CLK: jlDrawRect 100x100: frame=90 millis=89 ops/sec (367 ms) UBER: jlDrawCircle r=16: 81 iters / 16 frames = 303 ops/sec | hash=7F1F5531 +UBER-CLK: jlDrawCircle r=16: frame=303 millis=303 ops/sec (267 ms) UBER: jlDrawCircle r=80: 33 iters / 28 frames = 70 ops/sec | hash=B249C9AB -UBER: jlFillRect 16x16: 145 iters / 17 frames = 511 ops/sec | hash=F4BD4B0B +UBER-CLK: jlDrawCircle r=80: frame=70 millis=70 ops/sec (466 ms) +UBER: jlFillRect 16x16: 161 iters / 16 frames = 605 ops/sec | hash=F4BD4B0B +UBER-CLK: jlFillRect 16x16: frame=603 millis=605 ops/sec (266 ms) UBER: jlFillRect 80x80: 33 iters / 18 frames = 110 ops/sec | hash=7C952E5F +UBER-CLK: jlFillRect 80x80: frame=110 millis=110 ops/sec (300 ms) UBER: jlFillRect 320x200: 6 iters / 17 frames = 21 ops/sec | hash=6467AFB1 +UBER-CLK: jlFillRect 320x200: frame=21 millis=21 ops/sec (284 ms) UBER: jlFillCircle r=40: 12 iters / 17 frames = 42 ops/sec | hash=6467AFB1 -UBER: jlSamplePixel: 1313 iters / 16 frames = 4923 ops/sec | hash=6467AFB1 -UBER: jlTileFill: 433 iters / 16 frames = 1623 ops/sec | hash=6467AFB1 -UBER: jlTileCopy: 337 iters / 16 frames = 1263 ops/sec | hash=6467AFB1 -UBER: jlTileCopyMasked: 161 iters / 16 frames = 603 ops/sec | hash=6467AFB1 -UBER: jlTilePaste: 417 iters / 16 frames = 1563 ops/sec | hash=6467AFB1 -UBER: jlTileSnap: 705 iters / 16 frames = 2643 ops/sec | hash=6467AFB1 -UBER: jlSpriteSaveUnder: 33 iters / 19 frames = 104 ops/sec | hash=CA673FB1 -UBER: jlSpriteDraw: 5 iters / 16 frames = 18 ops/sec | hash=82B9646B -UBER: jlSpriteRestoreUnder: 33 iters / 18 frames = 110 ops/sec | hash=CA673FB1 -UBER: jlSpriteSaveAndDraw: 5 iters / 19 frames = 15 ops/sec | hash=82B9646B -UBER: jlStagePresent full: 33 iters / 28 frames = 70 ops/sec | hash=82B9646B -UBER: jlInputPoll: 65 iters / 16 frames = 243 ops/sec | hash=82B9646B -UBER: jlKeyDown: 3281 iters / 16 frames = 12303 ops/sec | hash=82B9646B -UBER: jlKeyPressed: 3745 iters / 16 frames = 14043 ops/sec | hash=82B9646B -UBER: jlMouseX: 8033 iters / 16 frames = 30123 ops/sec | hash=82B9646B -UBER: joeyJoyConnected: 3281 iters / 16 frames = 12303 ops/sec | hash=82B9646B -UBER: jlAudioFrameTick: 13393 iters / 16 frames = 50223 ops/sec | hash=82B9646B -UBER: jlAudioIsPlayingMod: 3601 iters / 16 frames = 13503 ops/sec | hash=82B9646B -UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 81 iters / 16 frames = 303 ops/sec | hash=D2B9E46B +UBER-CLK: jlFillCircle r=40: frame=42 millis=42 ops/sec (283 ms) +UBER: jlSamplePixel: 1281 iters / 16 frames = 4815 ops/sec | hash=6467AFB1 +UBER-CLK: jlSamplePixel: frame=4803 millis=4815 ops/sec (266 ms) +UBER: jlTileFill: 529 iters / 16 frames = 1981 ops/sec | hash=6467AFB1 +UBER-CLK: jlTileFill: frame=1983 millis=1981 ops/sec (267 ms) +UBER: jlTileCopy: 385 iters / 16 frames = 1441 ops/sec | hash=6467AFB1 +UBER-CLK: jlTileCopy: frame=1443 millis=1441 ops/sec (267 ms) +UBER: jlTileCopyMasked: 177 iters / 17 frames = 623 ops/sec | hash=6467AFB1 +UBER-CLK: jlTileCopyMasked: frame=624 millis=623 ops/sec (284 ms) +UBER: jlTilePaste: 465 iters / 16 frames = 1741 ops/sec | hash=6467AFB1 +UBER-CLK: jlTilePaste: frame=1743 millis=1741 ops/sec (267 ms) +UBER: jlTileSnap: 673 iters / 16 frames = 2520 ops/sec | hash=6467AFB1 +UBER-CLK: jlTileSnap: frame=2523 millis=2520 ops/sec (267 ms) +UBER: jlSpriteSaveUnder: 145 iters / 16 frames = 545 ops/sec | hash=CA673FB1 +UBER-CLK: jlSpriteSaveUnder: frame=543 millis=545 ops/sec (266 ms) +UBER: jlSpriteDraw: 241 iters / 16 frames = 902 ops/sec | hash=82B9646B +UBER-CLK: jlSpriteDraw: frame=903 millis=902 ops/sec (267 ms) +UBER: jlSpriteRestoreUnder: 161 iters / 17 frames = 566 ops/sec | hash=CA673FB1 +UBER-CLK: jlSpriteRestoreUnder: frame=568 millis=566 ops/sec (284 ms) +UBER: jlSpriteSaveAndDraw: 113 iters / 18 frames = 376 ops/sec | hash=82B9646B +UBER-CLK: jlSpriteSaveAndDraw: frame=376 millis=376 ops/sec (300 ms) +UBER: jlStagePresent full: 18 iters / 16 frames = 67 ops/sec | hash=82B9646B +UBER-CLK: jlStagePresent full: frame=67 millis=67 ops/sec (266 ms) +UBER: jlInputPoll: 65 iters / 17 frames = 229 ops/sec | hash=82B9646B +UBER-CLK: jlInputPoll: frame=229 millis=229 ops/sec (283 ms) +UBER: jlKeyDown: 2721 iters / 16 frames = 10191 ops/sec | hash=82B9646B +UBER-CLK: jlKeyDown: frame=10203 millis=10191 ops/sec (267 ms) +UBER: jlKeyPressed: 3041 iters / 16 frames = 11432 ops/sec | hash=82B9646B +UBER-CLK: jlKeyPressed: frame=11403 millis=11432 ops/sec (266 ms) +UBER: jlMouseX: 5377 iters / 16 frames = 20138 ops/sec | hash=82B9646B +UBER-CLK: jlMouseX: frame=20163 millis=20138 ops/sec (267 ms) +UBER: joeyJoyConnected: 2721 iters / 16 frames = 10191 ops/sec | hash=82B9646B +UBER-CLK: joeyJoyConnected: frame=10203 millis=10191 ops/sec (267 ms) +UBER: jlAudioFrameTick: 7345 iters / 16 frames = 27612 ops/sec | hash=82B9646B +UBER-CLK: jlAudioFrameTick: frame=27543 millis=27612 ops/sec (266 ms) +UBER: jlAudioIsPlayingMod: 2945 iters / 16 frames = 11029 ops/sec | hash=82B9646B +UBER-CLK: jlAudioIsPlayingMod: frame=11043 millis=11029 ops/sec (267 ms) +UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 97 iters / 18 frames = 323 ops/sec | hash=D2B9E46B +UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=323 millis=323 ops/sec (300 ms) +UBER: jlSpriteDraw unaligned: 225 iters / 16 frames = 842 ops/sec | hash=69CEBB34 +UBER-CLK: jlSpriteDraw unaligned: frame=843 millis=842 ops/sec (267 ms) +UBER: jlSpriteDraw sweep16: 15 iters / 16 frames = 56 ops/sec | hash=24E7E0C9 +UBER-CLK: jlSpriteDraw sweep16: frame=56 millis=56 ops/sec (267 ms) +UBER: jlTilePaste map 10x5: 10 iters / 17 frames = 35 ops/sec | hash=92E7B0C9 +UBER-CLK: jlTilePaste map 10x5: frame=35 millis=35 ops/sec (283 ms) +UBER: gameFrame composite: 3 iters / 18 frames = 10 ops/sec | hash=55B9EC6B +UBER-CLK: gameFrame composite: frame=10 millis=10 ops/sec (300 ms) UBER: ----- end ----- UBER-CHK: ----- begin ----- UBER-CHK: edge-pixels: hash=5267FFB1 @@ -54,9 +94,7 @@ UBER-CHK: arena-churn: PASS UBER-CHK: sprite-from-surface: PASS UBER-CHK: sprite-from-surface-draw: hash=5F4394C9 UBER-CHK: tilePasteMonoAll: hash=30C3A2C9 - UBER-CHK: floodFillBounded: hash=EF6B6F51 - UBER-CHK: ----- end ----- -UBER: total wall time: 367016 ms (22021 frames @ 60 Hz) +UBER: total wall time: 419016 ms (25141 frames @ 60 Hz) UBER: press any key to exit