Open kamiyaowl opened 4 years ago
FPSカウンターだけの表示だと秒10000いける
for (uint32_t counter = 0 ; ; ++counter ) {
// EmbeddedEmulator_update_screen(&fb);
// print_framebuffer(150, 0, 2);
sprintf(msg, "%d", counter);
BSP_LCD_DisplayStringAt(5, 5, (uint8_t *)msg, LEFT_MODE);
/* Touchscreen test */
// TS_StateTypeDef TS_State = {0};
// BSP_TS_GetState(&TS_State);
// if(TS_State.touchDetected) {
// const uint16_t x1 = TS_State.touchX[0];
// const uint16_t y1 = TS_State.touchY[0];
// BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
// BSP_LCD_FillCircle(x1, y1, 10);
// }
}
エミュレーションだけ入れると10fps
for (uint32_t counter = 0 ; ; ++counter ) {
EmbeddedEmulator_update_screen(&fb);
// print_framebuffer(150, 0, 2);
sprintf(msg, "%d", counter);
BSP_LCD_DisplayStringAt(5, 5, (uint8_t *)msg, LEFT_MODE);
/* Touchscreen test */
// TS_StateTypeDef TS_State = {0};
// BSP_TS_GetState(&TS_State);
// if(TS_State.touchDetected) {
// const uint16_t x1 = TS_State.touchX[0];
// const uint16_t y1 = TS_State.touchY[0];
// BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
// BSP_LCD_FillCircle(x1, y1, 10);
// }
}
print_framebuffer入れても8fps、これは最適化が効いている気がする
for (uint32_t counter = 0 ; ; ++counter ) {
EmbeddedEmulator_update_screen(&fb);
print_framebuffer(150, 0, 2);
sprintf(msg, "%d", counter);
BSP_LCD_DisplayStringAt(5, 5, (uint8_t *)msg, LEFT_MODE);
/* Touchscreen test */
// TS_StateTypeDef TS_State = {0};
// BSP_TS_GetState(&TS_State);
// if(TS_State.touchDetected) {
// const uint16_t x1 = TS_State.touchX[0];
// const uint16_t y1 = TS_State.touchY[0];
// BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
// BSP_LCD_FillCircle(x1, y1, 10);
// }
}
ざっとこんな感じ。本当ならPPUは完全並列で動かしていいのだけれど、ポリシーに反するのでアレ
opt-level=3, debug_assertions=noで2msぐらい削れた
ICache/DCache有効にしてなさそう。core_cm7のSCB_xxxにキャッシュ操作周りのインライン関数がある
体感でわからんぐらいだな、なんかミスってるかも
SCB_EnableDCache();
SCB_EnableICache();
ART, Prefetch Buffer有効化して9fpsぐらい。framebuffer解決しても15fps届くかどうかぐらいか
思い当たる節
一旦デスクトップ向け環境でもいいから、ベンチ図る環境を構築すべき、100frame書くまでにどのぐらいかかるか。などで
u16のアンアラインドな読み書きは間違いなくパフォーマンス低下になっていそう
まぁあえてu32使わせるのももとのコード崩しすぎるから微妙。 あとppuのdraw_lineは剰余が使われていたりするので、ここもdisasm眺めてみたほうがいいかも
SRAM先頭はDTCMに乗ってるけど、FlashはITCM使ってなさそう 実際のところ、ROMの固定地はcassette構造体の配列にコピーして利用しているのでFlashのアクセス経路には依存しない DCacheを有効にしてもすでにDTCM上にあるので、ゼロウェイト非キャッシュで恩恵がなかったと見るべき
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
RAM (rwx) : ORIGIN = 0x200001F8, LENGTH = 512K - 0x1F8
}
https://youtu.be/73ciNT9tl-U f4で30fps前後は出ていそう
小手先の修正で劇的に速くならなかったので、以下案
既存のコードと整合取れなくなる点どうしよう...型まるごと置き換えたりすると原型は保てなさそう
現在、ベンチテストは60frame書くのにかかる時間
running 6 tests
test tests::test_run_hello_cpu ... ignored
test tests::test_run_hello_ppu ... ignored
test tests::test_run_mario_demo ... ignored
test tests::test_run_mario_title ... ignored
test tests::test_run_nestest ... ignored
test bench::bench_hello ... bench: 94,229,800 ns/iter (+/- 4,619,103)
ちょっと変わった...?
test bench::bench_hello ... bench: 92,228,830 ns/iter (+/- 7,182,915)
test bench::bench_hello ... bench: 93,150,040 ns/iter (+/- 5,742,562)
剰余をbit andにするのはあまり変わらなそう
関数呼び出しをフェッチしてあげるのは結構明確に聞くっぽい、何でもかんでもinlineにするのはきらいだが
test bench::bench_hello ... bench: 89,489,360 ns/iter (+/- 7,959,146)
これみてたらやっぱunstable使ってでもconst fn使ったほうがいい気がしてきた
test bench::bench_hello ... bench: 76,373,280 ns/iter (+/- 3,452,911)
更に引数の数を減らしたりして2ms縮めた。多分これはarm相手だともっと効くはず。
test bench::bench_hello ... bench: 74,050,190 ns/iter (+/- 2,112,266)
動かしてみた感じ、体感でわかるぐらい気持ち早くなっていたがまだまだ
進捗
94.2ms -> 74.1msまで縮んだよ。やったね!
既存のコードと整合取れなくなる点どうしよう...型まるごと置き換えたりすると原型は保てなさそう
コードぶっ壊したくないとの兼ね合いが難しいしつらい。特にrustだと
境界チェック外しは、featureでマクロ切り替える方式が良さそう
あとusizeはターゲットのアドレス空間でサイズが決まる模様。arm向けなら4byte
カセットの読み書きをuncheckedにしたら1ms縮まった...
test bench::bench_hello ... bench: 73,403,310 ns/iter (+/- 2,966,874)
system/video_systemに適用したがあまり変わらず、全体的なアクセスはカセットを占めているので自明ではある。
test bench::bench_hello ... bench: 73,348,660 ns/iter (+/- 1,937,178)
きちんと確認していないけど条件的に範囲外例外を超えない可能性が高い領域だからかもしれない。 system_read/writeの中身はリージョンサイズで小さい順にifで引っ掛けているので、コンパイラが最後の条件までは範囲外にならないことを知っている。 なのでカセットに対してしか有効な高速化にならなかった。
system_ppu_regにinlineいれても早くならんな
x86だからかと思ったけど普通に遅くなった
(ARMでも
思い当たる節