mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-11-01 12:14:56 +02:00
perf(tiles): program the blit constants once per frame, not once per tile
Spec 8.3's hoist, and the 60 fps work showed it was the per-tile cost that mattered, not the per-frame one. Every tile_blit() call used to save 8 B registers, load B1/B3/B4/B7/B8/B9 and write 11 I/O registers (PSIZE, CONVSP, CONVDP, PMASK, the CONTROL read-modify- write and its read-back) -- all constants. The user's guide marks only SADDR and DADDR changed by PIXBLT, and the TMS34010 agent's reading of it confirms B1/B3 survive, so those two are the only ones a per-tile call has to reload. vram_tile.asm now exports tile_init_() (the constants, once per frame, called from paint_tiles/paint_delta) and a tile_blit_() that is setf, two pushes, two register loads, pixblt, two pops, rets. Measured on the real 140-tile deltas at a 60 fps send, same window, terminal's own status frames: before the hoist 162 accepted after the hoist 231 accepted (+43%) and the one-tile stream (where tile cost is nil) already runs at 60 fps with DINT: 600 frames sent at 59.8 fps, 579 accepted (96.5%), drops=0. Pixel verdicts unchanged: modes tiles, delta and replay all RESULT PASS with tile_check; 155 unit tests pass. What the remaining gap is, for the next reader: MAME's PIXBLT moves about 3.4 us per destination word (0.22 ms per 32x32 tile, measured from the accepted rate) against the unit's measured 0.40 us/word for FILL. A 140-tile delta is 8,960 words, i.e. ~30 ms of MAME CPU against a 16.7 ms frame -- so 60 fps for this content is bounded by the emulator's pixel engine, not by the design. Whether the unit can do it turns on the one number nobody has measured there: PIXBLT B,XY's per-word rate (spec 10, risk table).
This commit is contained in:
1 parent
1bb3643144
commit
9139322892
2 files changed
+45
-26
No files matched your search
@@ -339,6 +339,7 @@ unsigned int tile_src, tile_daddr;
|
||||
|
||||
extern void vram_blit_b_(); /* vram_b.asm: PIXBLT B,XY, SPTCH = 0 */
|
||||
extern void tile_blit_(); /* vram_tile.asm: PIXBLT B,XY, 32x32 tile */
|
||||
extern void tile_init_(); /* vram_tile.asm: the per-frame constants */
|
||||
extern void vid_dint_(); /* vram_b.asm: DINT */
|
||||
extern void vid_eint_(); /* vram_b.asm: EINT */
|
||||
|
||||
@@ -687,6 +688,7 @@ fp_header *h;
|
||||
}
|
||||
|
||||
vid_dint_();
|
||||
tile_init_(); /* the tile constants: once per frame */
|
||||
decode_begin();
|
||||
k = 0;
|
||||
pos = h->payload_off; /* the frame's first index byte */
|
||||
@@ -864,6 +866,7 @@ fp_header *h;
|
||||
* the per-row samples keep the 16-bit REFCNT counter unambiguous. */
|
||||
decode_sample();
|
||||
vid_dint_();
|
||||
tile_init_(); /* the tile constants: once per frame */
|
||||
frag_get(h->payload_off + FP_DELTA_HDR, &lo);
|
||||
frag_get(h->payload_off + FP_DELTA_HDR + 1, &hi);
|
||||
pos = lo | (hi << 8);
|
||||
|
||||
@@ -45,9 +45,12 @@
|
||||
; tile_daddr the destination XY word
|
||||
;
|
||||
; and the C wrapper tile_blit(src, tx, ty) is the only entry point. B7 (DYDX)
|
||||
; is the constant 32x32 this primitive exists for. All inputs are reloaded on
|
||||
; every call: PIXBLT leaves SADDR/DADDR and the B registers it advanced in a
|
||||
; half-consumed state, so a caller that "saved" them would save that.
|
||||
; is the constant 32x32 this primitive exists for.
|
||||
;
|
||||
; Two entry points, split by what changes: tile_init_() programs the constants
|
||||
; (pitch, offset, dimensions, colours, PSIZE/CONVSP/CONVDP/PMASK/CONTROL) once
|
||||
; per frame, and tile_blit_() then only reloads SADDR and DADDR -- the two
|
||||
; registers PIXBLT destroys -- before executing it.
|
||||
;
|
||||
; Revert note: this file is new in Task 4 and nothing else calls it. To
|
||||
; revert, delete it, the VRAMTILE entries in build-stream.sh and the
|
||||
@@ -62,28 +65,31 @@
|
||||
.ref _tile_src
|
||||
.ref _tile_daddr
|
||||
.text
|
||||
.globl _tile_blit_
|
||||
_tile_blit_:
|
||||
setf 32, 0, 1
|
||||
move b0, -*sp, 1
|
||||
move b1, -*sp, 1
|
||||
move b2, -*sp, 1
|
||||
move b3, -*sp, 1
|
||||
move b4, -*sp, 1
|
||||
move b7, -*sp, 1
|
||||
move b8, -*sp, 1
|
||||
move b9, -*sp, 1
|
||||
|
||||
move @_tile_src, b0, 1 ; SADDR: dictionary entry, index << 10 bits
|
||||
; _tile_init_ -- program everything that does not vary between tiles.
|
||||
;
|
||||
; Spec 8.3's hoist, and it is worth real time in MAME: measured per-tile cost
|
||||
; was ~0.36 ms against the unit's ~40 us, and the call did 11 I/O-register
|
||||
; accesses plus 8 push/pop pairs for constants that never change. The registers
|
||||
; this sets -- PSIZE, CONVSP, CONVDP, PMASK, CONTROL and B1 (SPTCH), B3 (DPTCH),
|
||||
; B4 (OFFSET), B7 (DYDX), B8 (COLOR0), B9 (COLOR1) -- survive PIXBLT (the
|
||||
; user's guide marks only SADDR/DADDR and B10-B14 as changed), so once per
|
||||
; frame is enough.
|
||||
;
|
||||
; B8/B9 are NOT I/O registers: they are implied operands of every graphics
|
||||
; instruction, and the resident OS leaves them arbitrary -- measured in the
|
||||
; strip work: the first draw run painted every row black because nothing had
|
||||
; set B9.
|
||||
.globl _tile_init_
|
||||
_tile_init_:
|
||||
setf 32, 0, 1
|
||||
movi 020h, b1 ; SPTCH = 32 bits = four bytes a tile row
|
||||
move @_tile_daddr, b2, 1 ; DADDR (XY): (ty*32 << 16) | tx*32
|
||||
movi 800h, b3 ; DPTCH = 2048 bits = 256-byte screen row
|
||||
movi 04000000h, b4 ; OFFSET = VRAM base
|
||||
movi 0200020h, b7 ; DYDX = (32 rows << 16) | 32 pixels
|
||||
clr b8 ; COLOR0 = 0 (black)
|
||||
movi 0FFFFh, b9 ; COLOR1 = all planes set (white)
|
||||
|
||||
; --- pixel format ------------------------------------------------------
|
||||
movi 1, a1
|
||||
move a1, @0C0000150h, 0 ; PSIZE = 1
|
||||
movi 14h, a1
|
||||
@@ -93,21 +99,31 @@ _tile_blit_:
|
||||
move a1, @0C0000160h, 0 ; PMASK = 0 (all planes writable)
|
||||
move a1, @0C0000170h, 0 ; upper half, for forward compatibility
|
||||
|
||||
; --- graphics operation: replace, no transparency, no window ----------
|
||||
; raster op 0 (replace), CD/RM/RR preserved
|
||||
move @0C00000B0h, a1, 0 ; CONTROL
|
||||
andi 0801Fh, a1 ; keep CD (15) and RM/RR (2-4) only
|
||||
andi 0801Fh, a1
|
||||
move a1, @0C00000B0h, 0
|
||||
move @0C00000B0h, a1, 0 ; read back: I/O writes are pipelined
|
||||
rets
|
||||
|
||||
; _tile_blit_ -- one 32x32 tile, everything already programmed.
|
||||
;
|
||||
; Only B0 (SADDR) and B2 (DADDR) vary, and PIXBLT destroys both, so those two
|
||||
; are the only registers this saves and reloads. tile_init_() must have run.
|
||||
;
|
||||
; Revert note: this file is new in Task 4 and nothing else calls it. To
|
||||
; revert, delete it, the VRAMTILE entries in build-stream.sh and the
|
||||
; tile_blit/paint_tiles code in vidstream.c; the strip path (vram_b.asm) does
|
||||
; not reference any symbol defined here and is unaffected.
|
||||
.globl _tile_blit_
|
||||
_tile_blit_:
|
||||
setf 32, 0, 1
|
||||
move b0, -*sp, 1
|
||||
move b2, -*sp, 1
|
||||
move @_tile_src, b0, 1 ; SADDR: dictionary entry, index << 10 bits
|
||||
move @_tile_daddr, b2, 1 ; DADDR (XY): (ty*32 << 16) | tx*32
|
||||
pixblt b, xy
|
||||
|
||||
move *sp+, b9, 1
|
||||
move *sp+, b8, 1
|
||||
move *sp+, b7, 1
|
||||
move *sp+, b4, 1
|
||||
move *sp+, b3, 1
|
||||
move *sp+, b2, 1
|
||||
move *sp+, b1, 1
|
||||
move *sp+, b0, 1
|
||||
rets
|
||||
|
||||
|
||||
Reference in new issue
Block a user