ドリクラエミュ描画安定化

 はてさて、箱エミュ(ドリクラエミュ)弄りのお話。
 ここの所またかなり根を詰めてしまっておりまして、
 「もう駄目だ、もうこれで終わりにする」
とか言って先週末に動画YouTubeニコ動を上げた翌日にはまた延長戦に入っておりました(苦笑)。

 ただそこでまた一つ問題がクリアできたので、「もう一週間様子を見ておけば良かったのにね」とは思いつつも。ただそうやって「もう少し」を延々繰り返してドツボにはまっていたのがこの一ヶ月余りの出来事(苦笑)。
 それも元を辿れば昨年からで、
  • マシンスペックが足りていないのでPC新調
  • モデルデータの効率上、エミュ負荷が上がっていたので改善
  • 内部的には処理落ち無く動いてるのに未だにカクつくので動作改善 <次ココ
 はい、ネタで上げてる改造部分とは全く別に、プログラム動作部分と未だにひたすら格闘を続けておりました。

 実際今月上げたネタ改造に費やしたのも実は正味2,3日くらいで、それ以外は殆どずっとこの問題と格闘し続けてましたよ。いやもうホント、今回は「勝った!第三部完!」の敗北フラグを何度積み重ねてしまったことか(苦笑)。
 あまりやり続けると「何やってんだこいつは」の自問自答が始まりかねないですが、「納得が全てに優先」しすぎるこの性格。
 ただだから何か引っ掛かる物がある内は(メモ等にまとめている内にまたという感じで)ついいつまでも手を動かし続けてしまうし、それで疲弊してしまったら世話が無いというもので。何処かに止め時を置かなければいけないものだとは思いつつ、その線の見極めがやっぱり難しい(以下ループ)、みたいな感じで。

 まぁ大分落とし所は見えてきたかなぁというところでこの辺で。
 あ、はい、またもゲーム内容の改造とは無縁のお話になります。そのクセむっちゃ長いです。ただ苦労話をぶちまけたい時だってあるんや。<自ら勝手に飛び込んだ地雷原ですけどねぇ。

 さて、PCも新調して、この前のデータのエミュ負荷問題も回避策が見えて、ようやくフルフレーム60fpsで動作させられる所までこぎ着けた訳ですが、それでも未だに妙なカクつきが絶えないという状況。
 気の所為ではなくて録画して見ても相当にフレームドロップしてしまっている。

 これが処理落ちなら仕方ないと思ってそちらを見てきたのが今までな訳ですが、どうやらそもそも論で動作スペックが足りていようが描画・録画側で上手く行っていないというのが今回の課題。
 この点色々かなり試行錯誤してしまったのでとても書き切れないけど、
  • VSync描画更新間隔の問題
  • ストリームカメラの処理問題
  • 録画の処理パフォーマンス問題
 大きな所ではこんな感じ。

●VSync描画更新間隔の問題
 当然最初に疑ったのはこの問題。
 録画ソフトとしては60fpsないし59.94fpsのフレーム間隔で録画するけれど、描画側の更新間隔がそれに噛み合っていなければ当然がたつく。
 ここは実機ではハードウェアVSyncの割り込みタイミングでの描画スワップで周期を安定させているので、実機の録画では概ね安定した録画が望める。
 しかし如何せんエミュのVSync相当の処理はハードウェア制御は全くしていなくて(まぁモニタ毎に周波数とか違うし)、あくまで擬似的にイベントを起こしているだけだった。そしてそれがなんと1msウェイト*16カウントでという、滅茶苦茶ザルなイベント発火(要するに16ms周期、16.6666msとでは誤差の蓄積が物凄い)。
 実際ソフトウェアのsleepタイマーには正確性を求められるものではないとはいえ、ここまで雑だと全くもって頼りにはならず。

 しょうがないのでこの疑似VSyncは切ってしまって即時描画モードで動かして、代わりにゲームソフト側のメインループで描画実行間隔を1/60sec間隔にしてやろうと始めたのが最初。

 元々の実装にもVSync描画待ちの他に最低1/60sec置く作りになっていたのだけれど、ここが別段正確ではなかった(そこまで重視されたものではなかった)。そこで開始クロックから計算してきっちり1/60(正確には1/59.94)sec間隔でタイマー時刻を置くように細工を施してみた。分かり易く言えば、1.05sec経過していたら次は0.95sec待つみたいな補正を掛けたという話(その1/60)。
(※細かい所ではこのタイマーの張り方にも幾つか試行錯誤して、エミュのVSync処理側とも連携してみたりとか色々アイデアは出してみたりもしてますがそこは割愛。というか実のところまだどれがベターという答えも出し切れてないし)

 これで「勝った!以下略」となったのはもう大分遠い過去の話のような(遠い目)。
 いやこれ自体は随分良い線は行っていて、録画はともかくモニタの周波数(うちの場合は59.95hz)に合わせてきっちり綺麗にヌルヌルで動いて自己満足の極みにはなっていた訳ですが、ここからちょっと細々とした課題が噴出してきましてね、、。

●ストリームカメラの処理問題(フレーム値の小数点丸め誤差)
 因みにそもそも論で、きっちり1/60sec間隔で回すなんて考えず素直にウェイト無しで即時描画させて100fpsとかの数字が出ている所を録画してしまえばいいという話もある。というか普通のゲーム録画レベルならそう。

 ただこれの問題としては、まず周期がずれているぶん当然録画されないフレームが発生してそこが飛んで見える。これは見た目としては僅かなモーションの誤差(60fpsも枚数が出ていれば後は脳が補完する)でしかないのだけれど。
 問題はもう一つ別にあって、内部データ処理上1/60(59.94)secで一枚ずつの絵を描く想定になっているので、fpsが異なる場合は経過時間をフレーム数に換算する所で小数点以下の端数が発生してしまい、その誤差がカク付きとなって現れてしまう。

 もっともキャラのダンスモーションは小数点以下も補完計算して描画されている。問題はカメラ。
 ストリーム・ランダムカメラで経過フレーム値を算出している部分、ここが見事に整数値で処理されてしまっていて、小数点以下に下手な端数を出すと丸め誤差でがたつきが起こってしまう。例えば、1, 1.99, 3.01 という風に経過した場合に小数点以下切り捨てで 1, 1, 3 というフレーム値で処理されてしまう。これが実際かなり深刻。
 モーションは滑らかに描画されているのにカメラ=背景だけ動かないという絵が作られる(構図が一瞬ズレる)ので、これがまた新たな違和感を生んでただのフレームドロップとは別の意味でのがたつきを発生させてしまう。

 だったらこのカメラモーション(とでも呼ぶことにする)をダンスモーションと同じく端数の補完に対応させられればいいんですけどね。キャラモーションと違ってカメラはシーン毎に位置が切り替わるので単純に前後の値から線形補間すればいいものでもない。その辺のデータ構造の解析にも繋がっていきそうなので割と大ごとになりそう。
 それよりも目的は1/60(59.94)sec間隔の録画なんだから、1フレームずつ刻むように処理できれば問題ないじゃないかと。それで十分じゃないかと。そういう方向性で、先のカメラフレームの整数値化部分を細工。無論、単純に1ずつプラスしていけばいいってものでもなくて、後は処理落ち(フレームドロップ発生時)の事も踏まえつつそれっぽい実装に。

 因みに言うとこの話、特に丸めの境界線付近に数値が来た場合、その境界の前に来たり後に来たりという風にしばらくは値が前後するので、ただの1フレームだけではなくて何度もがたつきが発生するのが嫌なところ。これは周期ズレにも言えること。
 だから極力正確に1/60(59.94)sec間隔で描画させるのが一番じゃないかなという考えになってくるというところで。
 まぁ処理落ち時を考慮すると補完(小数点以下)処理するに越した事はないんですけどね。

 あ、あと因みに勿論、「ストリーム/ランダムカメラを使わなければいい」のも一つの妥協ラインなんですが。流石に勿体ないじゃないですか。

●録画の処理パフォーマンス問題
 ここまでやれば描画側としては安定している(筈)で、実際の描画回数をカウントしてフレーム落ちしていない事も確認して、これで描画側としては概ね万全。
 だけれども録画を行うとポコポコとフレーム落ちしてしまう。
 まぁね、そりゃエミュを動かしているのと同じPCで録画もさせてますからね。録画側の処理が間に合わない事もそりゃありますよと。
 特に平時の動作は大した負荷が掛かっていなくても、カラオケの演出でスモークやエフェクトが出たタイミングでは負荷が掛かって、描画はぎりぎりフルフレームを保てていても録画まで手が回らずに僅かなフレーム落ちに繋がってしまうということもある。ここまで行くと仕方ないよね感は勿論あるわけですが。

 なお今はx2倍解像度で録っているのでそれでGPU負荷が70%くらいまでは行っているのもある(重いモデルならもっと)。
 だから録画負荷を改善できないかとGPU2枚差しでエンコ担当もさせてみたけれど、これは思わしい結果も出なかった。元より僅かなタイミング負荷以外はGPUをフルで使っている訳でもないので。(それとどうせ帯域とかは別だよね)
 それじゃあと次はGPUのオーバークロックにも挑戦。元々オーバークロックモデルなのに、、。でも弄ってみたら確かに1フレーム毎に1,2msくらい速度が稼げたケースもあったので、こちらは有効かなという感じで恐る恐る。夏にはやりたくねえな!って感じで(苦笑)。

 こんな感じでGPUパフォーマンスもちょい足しして少しは処理速度も稼げただろうかと。
 元々負荷がギリギリになってしまう制服モデル系はともかく、軽い水着モデルくらいは安定させたい。
 なのだけれどどうもまだ決め手に欠ける。

 如何せんそういう微妙なフレーム落ちは「重くて一杯一杯になった時に取りこぼすことがある」。それで何フレームもがたついてしまうこともあるし、録り直せばもうちょっと良くなることもある。はい、ここに来て運ゲーです(苦笑)。
 まぁそりゃそうなんだけどさぁ。割と目立つタイミングで出ちゃったりもして「クソ、録り直しかよ」というゲンナリ感。
 それに割とどうでもいいような軽い所でフレーム落ちしたりもして、やっぱりまだ微妙な録画のご機嫌問題が否めない。正に運ゲー。
 やれやれ。自分ははっきり言って運ゲーが大嫌いなんですよ。
(注:ゲーム進行上の揺らぎとしてのランダム要素はむしろ肯定派。だけどただの繰り返し作業のための運は嫌な人)

 あ、いやだから運ゲーにならなくて済むようにしたいと思う所でしてね。
 勿論、運ゲーと結論付ける前にまだ何処かに不備があるんじゃないか?という試行錯誤フェーズも当然長く据えてますし。
 ただもうここまで来たら運ゲーなんだろうな、みたいな所まで何とか漕ぎ着けたところ。
 せめてこのやり方ならフレーム落ちしにくい方かな、みたいな線を見定めつつ。

 これで「もう沢山だ!、ダイノボットを破壊する」のコンボイ司令みたいな心境で見切りを付けて動画をアップしたのが先週。
 ちょっと週末ぎりぎりお疲れモードだったのでまた翌日にでもまとめ文を書こうと思ってたら、また変な不具合を見付けてしまいましてね。見事な延長戦突入。

 という訳なので以下は最後の修正が入る前のものですが、
ドリームクラブZERO デュエット(ノノノ・アイリ)☆Paradise☆


 いやこのデュエットの方はそこまで大きな問題はないんですよ。
 精々「シーン切り替えの処理がおかしい気がする、けどこれは元からなのかなぁ」くらいで。
 ただトリオ動画の方がですね、、。(後日今度こそ触れたいとは思いますが)

●ストリームカメラの処理問題(フレーム値の小数点丸め誤差)・再
 先程「勝った!以下略」と思い込んでいたストリームカメラがたつきの修正改造、
 ソロ(VIP)モードでは問題ないのだけれど、バックダンサー(以後BD)やデュエットモードでは少々処理が異なっているのを見落としていて、いや全くもって想定通りに動いてませんでしたわ。
 せっかくの変更がまるで機能せず。ア~ンド、稀に微妙にデグレ起こしてましたよ(テヘペロ)。(稀に一瞬フレームが巻き戻ってしまっている瞬間があるので決してコマ送りしないでお願い<誰もやらんわ)

 元々これは60fps安定を狙ってやっていたことだったので、処理落ちが起こるケースではしょうがないよね、そりゃフレーム落ちしている以上はがたつくよなぁ、くらいの気持ちで出来た動画を受け止めていたんですが。
 しかし結局ここも丸め誤差の所為で必要以上のがたつきが生まれてしまっていたと。

 これを取り除いたら何だもっと綺麗にスクロールして見えるじゃないですかって。
 多少フレーム落ちしてたってそんながたつきは感じられないじゃないですかって。
 そりゃそうだよなぁ。実機録画で上げられてる物だって大抵エフェクト発生時にフレーム落ちしてるけどそこまで気にならないし。

●BD,Duetモードでのストリームカメラのシーン遷移演出
 因みに上記を調べる過程で気付いたのが、どうもまだカメラシーンの切り替え演出のタイミングで変なカメラモーションのドロップ、同じカメラフレーム値を使った描画が起きてしまっている。キャラだけ動いてカメラ(背景)が動かないという状況。
 これが起きるのはシーン遷移演出タイミングの前後っぽいので、まぁその重ね合わせ処理に関連した不備なのだろうかと。

 元々この演出はDuetとBDモードでのみ使っている模様。
 当然負荷は掛かるのでソロのVIPでは60fps再生を優先して切っているのだろう。どうせレートが出せないDuet,BDでは入れてみようという感じだろうか。BDモードはまたモデル数分の負荷が増すので控えめになっている。
 だから実機では30fps(以下)の再生でしか見られないので表面化することもなかったのかもしれない。

 それが今回のエミュでフルフレーム描画したら見えてしまった訳ですが。
 ただ内部のフレーム値はきちんと1ずつ進んでいるのに何だこりゃと思って、ついこれも気になって見てしまいましてね。
 細かな実装を追った訳ではないんですが、傍目にこの値が何か想定と違うんじゃ?と少し弄ってみたら何だか綺麗に収まったっぽい? これはもう素直に「勝った」って思うことにしておきました(笑)。(まぁその内また何か影響に気付くかもしれないけど今のところ良好)

 そんなこんなで結局、
 大元の作りがエミュで不都合を起こしている部分を解決したらちゃんと動くじゃないですかって。
 この最後の詰めが甘かったばかりに、すっかり残念な録画を上げてしまって実に悔やまれるところ。(まぁそれを言ったら過去殆どですけどね)

 といった風に、やっとこさで腰を落ち着けようかというところ。
 残ったのはこんな感じですかね。
  • 録画で僅かにフレーム取りこぼしはあるかもしれない(専用ハードでもないので限界点)
  • 処理落ち時を考慮すると、根本的にはストリームカメラに小数以下の補完処理が入ればより自然になる(筈)

 後者はまぁ当時の作りの限界と言いますか。
 念のために言っておきますが、別に作りの粗とかを糾弾する等が目的なのではなくて。それを言ったら自分だって過去にどれだけ穴のある、悔いの残るコードを残してきたことか。それを修正、ブラッシュアップしてより良くして行くのがプログラムという物だと思いますよ。
 だけれどもう過去の製品にアップデートは望めない(新作も)から、じゃあ自分で(こっそり)やりますねフェーズだということです、はい。

 ただその点、ちょっとだけ思ったのは、「PS3版だったらここまで悩まずに済んだのかもね」と。
 それこそPS3版だったら実装も改められて綺麗になっていたんじゃあないか?とも。実際普通に上げてる人もいるし。そりゃ後発の方が普通は出来は良いですもん。(稀に劣化するケースも無くはないですが)

 まぁここは当初の出発点が、軽い気持ちで手持ちの箱○版データ(DLCを含む)を活用してみたという所から始まって、そこからの流れなので。
 それにPS3版の方は例えばテクスチャも小さいだとか、本体スペック的に少し見劣りしてるのは確かなので、敢えて(数多のDLCを買い直してまで)移ろうとも思わなかったのもあり。あと何より個人的にはアイリのヘルメット髪の問題ですね。この辺でちょろっと。屋上直行案件の教義()の対立問題なのでこればっかりは)

 いやまぁPS3にしかないGogo.は気になってはいますけどね。ソフトは持ってるんですけどね、ソフトだけは(笑)。
(PS5の互換でどうにかならないかなと思ってましたが普通に駄目でした。あーもうエミュでやるしかないかな、、、)
 なのでまぁPS版に関しては今はまだ保留ということで、、。
 データは覗いたんだけどやっぱり機種もエンジンも違うから同じとはいかないですね。

 そんなこんなで長々と無駄な苦労話でした。
 次こそは振り返りネタになる、はず、、、はず。