Joël van der Werf
記事一覧

56件の問題:エンジン全体のレビューで見つかったこと

機能を追加する前に、エンジンとエディタの約6,000行すべてをレビューしました。6件の重大なバグ、スワップチェーンの分割、そしてすべてのVulkanリソースのRAII化。

2026年10月にHydroを再開したとき、物理、パーティクル、3Dレンダラーなど、多くの機能を素早く追加したいと考えていました。何年も見ていなかった土台の上にそれを積むのは危険に感じたので、新機能の前にエンジンとエディタ全体、約6,000行をレビューしました。見つかった問題は56件です。

6件の重大なバグ

  1. リサイズでレンダラーの半分がリークしていた。スワップチェーンの再作成が、レンダーパス、コマンドプール、コマンドバッファ、セマフォ、フェンス、サンプラーを古いものを破棄せずに作り直し、イメージビューとフレームバッファを2回作っていました。今はサイズに依存するオブジェクトだけを作り直します。
  2. バリデーションが黙って無効になっていた。GLFWの拡張機能リストがdebug-utils拡張を上書きしていたため、デバッグメッセンジャーが一度も作られていませんでした。さらにReleaseでもレイヤーが有効でした。何年もの「バリデーションエラーなし」には意味がなかったのです。
  3. イメージのフラグが間違っていた。レイアウトの定数がusageとaspectのフラグとして渡され、ファイルからの画像読み込みではピクセルが実際にはコピーされていませんでした。
  4. 処理中の複数フレームがデータを共有していた。2Dレンダラーは、同時に処理中のフレーム間で1つの頂点バッファと1つのオフスクリーンイメージを同期なしで使い、インデックスバッファを半分のサイズでアップロードしていました。
  5. スクリプトがダングリングポインタを保持していた。ネイティブスクリプトが、ストレージを移動させるEnTTのプール内のthisや、スタック変数のアドレスを保存していました。
  6. コピペのバグ。PushOverlayがPopOverlayを呼んでいました。

一番考えさせられるのは2つ目です。他のバグを見つけるための道具そのものが壊れていて、すべてが正常に見えていました。

構造の修正

  • スワップチェーンは表示だけを担当。フレームごとのオブジェクトはフレームコンテキストへ、サーフェスはレンダラーコンテキストへ、フレームループはレンダラーへ移しました。
  • すべてをRAIIに。すべてのVulkanラッパーはデストラクタで自分を解放します。所有者はScope(単独所有)を持ち、利用側は参照を受け取ります。所有するGPUオブジェクトを共有ポインタで持つことはなくなりました。
  • 削除キュー。デストラクタはGPUメモリをすぐには解放せず、処理中のフレームが使い終わってから解放するキューに送ります。これでホットリロードとリサイズからWaitIdleがすべてなくなり、エディタが止まらなくなりました。

そこから生まれたルール

レビューからは独自のスタイルも生まれました。すべてnamespace Hydroの中、!の代わりに== false、すべての本体に波括弧、リソースは仕様の構造体から作成。これらはドキュメントとAIエージェント用の設計スキルに書かれ、のちに規約チェッカーにもなり、同じバグが黙って戻ってくることはありません。

学び:拡大する前にレビューする。その後の数週間で作ったすべての機能は、このレビューでの修正の上に立っています。

前の記事:Hydroの4年間:Vulkanの三角形からエディタまで次の記事:実行時の状態はどこに置くか:ECSのコンポーネントのための4つのルール

お仕事のご相談はお気軽にどうぞ

東京在住です。Unity・C++・ゲームエンジン関連のポジション、C#・.NETのソフトウェア開発のポジション、そしてAIエージェントを活用した開発体制づくりに関心があります。英語・オランダ語・日本語(勉強中)で対応できます。