C#で画面キャプチャしようとしたら遅かった原因が分かった件
とあるゲーム…と、いうかオンラインのパチスロを打つプログラムを試しているところ。
パチスロなんだから高設定じゃないと勝てないのは普通だが、4号機時代の技術介入ができる台であれば、完ぺきに打つことができれば設定1でも100%を超える。
最近でもディスクアップなんかはどのホールでも設定1だけど、数千万回転の実践を集計すると100%をぎりぎり超えているらしい。
さて、パチスロはドラム1回転でたいてい21コマの図柄がループしているが、1分間で79.5~79.9回転程度の速度らしい。オンラインのパチスロゲームでも基本的には変わらない。
60(秒)÷79.5(回転)÷21(コマ) = 0.0359(秒/コマ)。1つの図柄をビタ押しするには35ミリ秒の勝負となる。
人間が目押しする場合は回転の間隔も体感で覚えれば、ほぼ完全目押しもできる。
自分がやろうとしているのは瞬間目押しである。余計なドラムの回転を待たずに1周目で目的のコマをビタ押ししてやろうということだ。
さてクランキー系でちょっくらやってみるかとプログラムつくってみたものの、これがどうにもうまく行かない。いや、うまく行くのだが、うまく行かない。
メインのPCは4年前に購入したPCで当時そこそこハイエンドのPCなので、性能的にはよい。このPCでコーディングして、試しに目押しさせてみるととほぼ想定のとおりに目押しできる。小役はおいといて、BIG時のリプ外しなんて完璧だ。やっとできたと思ったのに。
メインのPCは普段使いするので、パチスロでメダル稼ぎたいときは、サブのミニPCで勝手にメダル獲得しておいてほしいのだ。で、サブのミニPCにはディスプレイがつながっておらず、VNCを使ってリモートログインしている。そして、25,000円ぐらいでOSまでついているミニだが、当然性能は低いCeleron J4125。グラフィクスはIntel UHD Graphics 600だ。
性能的にイマイチでも、なんとかなるのではないかと思っていたが、やっぱりどうにもならない。やってみると、目押しが全くあっていない。遅れまくる。
なんでかとログを出力しながら確認したところ…
57:48.190 比較終了 57:48.190 画面取得開始 57:48.217 画面取得終了 57:48.217 比較終了 57:48.217 画面取得開始 57:48.253 画面取得終了 57:48.253 比較終了 |
こんな状態なのだ。
BitBlt()を使ってわずか20×20ドット程度の範囲を画面取得して、コマの状態を比較する処理を書いてるのだが、画面の状態を取得するのに30~50ミリ秒かかっている。画面取得終了後の画像の比較処理なんか、1ミリ秒もかからないのに。
つまり、画面の取得するだけで、ドラム1コマ分以上ずれているのだ。しかもその間隔が安定していない。
ちなみにメインPCでやったら16ミリ秒前後でほぼ一定=ディスプレイのリフレッシュレートが16.6666ミリ秒なので、これにほぼ一致していた。
BitBlt()より速そうかとおもいDesktopDuplicatorAPIとかつかってみたりもしたが、いったん画面全体をテクスチャで処理するせいか、これもダメ。200~400ミリ秒とかえって遅くなってしまったり。
やっぱりダメなのかとあきらめていた。
ところが、ある時、実験につかれ、たまたまミニPCをテレビにつなげて動画をみおわったあと、そのままアプリを動かした。
あれ?ログの表示の画面取得開始~画面取得終了の間隔が16ミリ秒前後になってる。
・・・???
推論。ディスプレイつなげていないとIntel HUD Graphics 600が描画さぼってるんじゃないの?そしてBitBlt()は描画されるまで待っているんじゃないの?
HDMIを抜いてみる。ログの出力をみるとやはり画面取得開始~画面取得終了の間隔が広がる。
まさかの事実。
でもHDMIケーブルも常時余っているわけでもないので、ちょっくらネットで調べてみた。
うってつけの物があった。
amazonで850円で2つ入りのものを購入。
ディスプレイが接続されているふりをする、仮想ディスプレイアダプタだ。
もともとはリモートワークをするひとが、会社のPCなどにリモートデスクトップ利用しようとすると、ディスプレイのつながっていないマシンの場合解像度が800x600として認識されてしまい非常に使いにくいといった問題に対し、リモートで操作するマシンにこれをつけておくと最大4Kの解像度が設定できるようになるというものだ。
購入して早速ミニPCにつけて試す。しっかり16ミリ秒前後になった。
さらに、これをとりつけることで、ディスプレイのリフレッシュレートを60Hz→120Hzに設定することもできる。
すると…
24:00.205 比較終了 24:00.205 画面取得開始 24:00.213 画面取得終了 24:00.213 比較終了 24:00.213 画面取得開始 24:00.222 画面取得終了 24:00.222 比較終了 |
ちゃんと、8~9ミリ秒で画面取得できるじゃないか。ミニPC自体の性能のせいではなかった。
大したことしてないのにとは思っていたが、まさかのGPUがさぼっていただけ。ちゃんと働かせると、働かせたなりに仕事してくれたのでした。
コメント
コメントを投稿