Оптимизация каскада плит: -27% работы за кадр (пять правок с замерами)
Сцена — ур.13 комната 23, шесть плит с потолка (docs/perf_l13_room23.md).
Все замеры сняты одним и тем же прогоном «ESC -> зонды -> roomtest».
было стало
работа за кадр 1 437 150 1 051 332 -27%
зелёная (фон) 805 000 575 730 -28%
циан (спрайты) 631 800 438 546 -31%
синяя 142 830 142 830 в бюджете
Цена одной перерисовки:
RDA_CEIL_GONE (запечь колодец) 251 335 -> 137 975 -45%
RD_FLOOR (щебень на посадке) 198 805 -> 182 124 -8%
RDA_CEIL (дрожащая плита) 48 785 -> 43 543 -11%
C1. Пометки «фон трогали» в mob_render ПОДАВЛЕНЫ (pop_cd_mute): коридор
куска уже помечен одним вызовом в pop_loose_mob_tick, а три блита метили
подмножества того же прямоугольника по 4 502 такта. Плюс пометка в
mob_spawn_copy — кусок, рождённый внутри тика, свою мог не получить
(слот выдаётся с начала таблицы, то есть уже пройденный). -55 тыс.
G2. Контекст тайла — file-scope, а не локали draw_tile (порт
load_curr_and_left_tile, seg008:0339). В функции 57 вызовов, и каждое
живое через вызов значение спиливалось: 26 байт кадра и 513 обращений
`-N(ix)`. Стало 33 обращения, кадра нет, банк 7 -703 Б. -55 тыс.
G1. Окно клипа для точечной перерисовки (pop_t_win_set/clear). В
pop_ceil_bake_empty куски ряда 0 высотой 63 px рисовались целиком, хотя
восстановить надо девять строк: блит стоил 21 447, стал 7 619. -90 тыс.
В pop_floor_bake окно попробовано и ОТКАЧЕНО (там нет клипа, блиты шли
быстрым путём, а окно уводило их в blit_b_clip и не отсеивало ничего:
187 266 -> 198 279) — вернуться после G3, запись в коде.
G3. blit_b_clip: байтовый габарит + file-scope вместо локалей. Одного
байтового габарита НЕ ХВАТИЛО (кадр остался, 211 -> 173 обращений) —
значений, живых через шесть вызовов ядер libbgi, больше, чем регистров.
С file-scope: 51 обращение, кадр 22 -> 12 Б. Клипованный блит подешевел.
C4. Падающий кусок КЛИПУЕТСЯ сам, вместо чистки бортов после. Раньше он
рисовался в борт целиком и взводил border_dirty, а pop_room_clip_borders
стирал две полосы 320x28 — 150 978 тактов в каждом кадре, пока хоть один
кусок торчит выше поля (гряда 13-го рождается ровно у потолка, y=2), то
есть почти весь каскад. Стало 1 722. -138 тыс.
Заодно blit_b_oversize больше не ходит через blit_b_clip (у того габарит
теперь байтовый) — рисует напрямую gfx_blit_part. Это путь под
полноэкранные подложки интро/финала (320x200, docs/perf_l13_room23.md §5).
Проверено: 8 наборов tests-host зелёные; в MAME каскад рисуется корректно
(кадр с летящими плитами, чистые борта, итоговая картинка как до правок).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,20 @@ extern uint8_t pop_cd_batch;
|
||||
void pop_cd_batch_begin(void);
|
||||
void pop_cd_batch_end(void);
|
||||
|
||||
/* ПОДАВИТЬ пометки на время серии блитов — для того, кто пометил область САМ
|
||||
* и заведомо шире, чем нарисует (падающий кусок: pop_loose_mob_tick помечает
|
||||
* весь коридор heal'а одним вызовом, а спрайт куска — три блита внутри него).
|
||||
* Дешевле пакета: pop_cd_touch выходит второй проверкой, не считая ни колонок,
|
||||
* ни рядов. Замер 2026-08-17: настоящий вызов pop_cd_touch = 4 502 такта,
|
||||
* 28% всей цены блита.
|
||||
*
|
||||
* ОПАСНО применять без разбора: пропущенная пометка = персонаж, которого
|
||||
* стёрли, но не попросили перерисоваться, то есть исчезнувший со экрана
|
||||
* персонаж (ровно этот баг ловили 2026-08-13 в комнате 23). Ставить только
|
||||
* там, где покрытие доказано. */
|
||||
void pop_cd_mute(void);
|
||||
void pop_cd_unmute(void);
|
||||
|
||||
/* Кого в этом кадре можно НЕ перерисовывать: бит 0 — Кид, бит 1 — соперник.
|
||||
* Звать ДВАЖДЫ: перед heal (стирать нечего) и перед отрисовкой (тик мог
|
||||
* персонажа всё-таки сдвинуть — тогда бит снимется сам, а pop_char_draw
|
||||
|
||||
Reference in New Issue
Block a user