レンダリングエンジンのコアロジック部分からDirectXの依存性を排除した
世の中、マルチプラットフォームが当たり前になってきた。
ぶっちゃけ、マルチプラットフォームにする必要性はまったく感じなかったのだが(再三言っているが、プロダクト開発ではなく、あくまでゲームエンジニアとしての研鑽のためエンジンを開発している)
それはそれとして、ロジック部分にハードウェアに対する依存性が生じているのが生理的に許せなくなったので
フォトンマッピングの実装途中なのに唐突にブランチを終了してハードウェアの抽象化を始めた。
真の抽象化は、大手ベンダーの開発しているグラフィクスAPI全てのレンダリングパイプラインを抽象化して統一したスマートでエクセレントなグラフィックレンダリングライブラリを開発することだが、そもそも私はOpenGLやDirectXのv11以外はたいして分かっていない。MetalやVulkanに至っては1ミリたりとも知らない。特に、DirectX 12やMetal、Vulkanといった「ローレベルAPI」と言われる、よりハードウェアアーキテクチャに近いAPIは、現在使っているDirectX11とは仕様が多く異なっている。例えばパイプラインステートオブジェクトやディスクリプタといった部分だろうか。これらのAPIはコンシューママシンのグラフィクスAPIに通ずるものがあるのでそのうちマスターしたい。
今回はあくまで概念的な抽象化ではなく、具体的に言えば静的リンクアーキテクチャレベルでの抽象化を行った。つまり、ロジック部分のコンパイルに、DirectX系統のシンボルを一切関与させないことを目標にした。
やったこと言えば、ひたすらリソースの仮想クラス化、およびそのパラメータの汎用化だ。そして、GPUリソースを作成するデバイスおよびレンダリングコマンドを発行するデバイスコンテキストを隠蔽した、抽象ImmediateCommandクラスを実装した。なんでImmediateなんだと聞かれたら、今のところDeferredContextの必要性を感じてないとしか言いようがない。そのうち実装する。
私はもともとテンプレートメタプログラミングを愛好するプログラマだが、やはりどうしてもハードウェアの抽象化というかなり無理のあるロジックをプログラムで仕込もうと思うと、どうしてもダウンキャストを前提とする多くの仮想基底クラスを振り回すような設計になってしまう。静的にImmediateCommandsクラスの挙動を決定する設計も考えなくはなかったが実現の困難さに気づき断念した。
なにはともあれ、膨大な作業によってなんとか抽象化が完了し、依然と同じ挙動をすることを確認するところまで行った。
最初からやっておけばよかったと無限に後悔している。Windows限定でいいやとか鼻をほじりながらプログラムを書いていた昔の自分を殴り飛ばしたい。
PRはこんな感じになった。なかなかの量の差分である。
https://github.com/Riyaaaaa/EnhancedRTRenderingEngine/pull/10
リファクターの余地は大いにあるが、ひとまずは満足した。フォトンマッピングの実装に戻ろうと思う。