- この10年間、DirectX 12、Vulkan、Metal などの低レベルグラフィックスAPIはGPU性能を引き出してきた一方で、複雑さと保守コストが急激に増大した
- 現代のGPUは 完全なキャッシュ階層、64ビットポインタ、バインドレス(bindless)リソース をサポートしており、従来の複雑なステートオブジェクトやバインディングモデルは不要になっている
- 提案された設計は、C/C++ポインタベースのメモリアクセス と 単一の64ビットルートポインタ を用いて、レンダリングパイプラインを大幅に単純化する
- PSOの爆発的増加、リソースバリア、複雑なバインディングAPI を取り除き、GPUメモリとシェーダー言語を直接結びつける構造を提示する
- このアプローチは、現代GPUアーキテクチャに最適化された次世代API として、DirectX 13やVulkan 2.0が目指すべき方向性を示している
低レベルグラフィックスAPIの変化
- 2013年、Xbox OneとPS4の AMD GCNアーキテクチャ がAAAゲーム開発の標準となり、Mantle・DirectX 12・Vulkan・Metalのような低レベルAPIが登場した
- つまり、これらは 2013年前後のGPUアーキテクチャ を基準に設計されている
- 従来の DirectX 11/OpenGL は、単一スレッドレンダリングと高いドライバオーバーヘッドによって限界があった
- これらのAPIは 事前コンパイル済みのパイプラインオブジェクト(PSO) によってドローコールのコストを減らしたが、エンジン構造と合わず複雑性を高めた
- その結果、エンジン内部にもう1つの「ローレベルドライバ層」が生まれ、グラフィックスプログラマの役割は細分化された
歴史的背景: なぜここまで複雑になったのか
- 初期のGPUは、分離されたメモリと固定機能パイプライン中心の構造だった
- OpenGL・DirectXは、ハードウェアの多様性を抽象化 するために、ステートベース・オブジェクトベースの設計を採用した
- DirectX 11までは、テクスチャやバッファが 不透明なディスクリプタ として管理されていた
- こうした設計は、その後のAPIにも 惰性的に維持 された
現代GPUとAPIの不一致
- 現在のGPUは 一貫したキャッシュ階層、PCIe ReBAR、64ビットポインタ、バインドレステクスチャ をサポートしている
- CPUがGPUメモリに直接書き込み、GPUが即座に読み取る構造 が可能になっている
- この環境では、PSO・ディスクリプタセット・バインディングテーブル のような構造は不要である
- PSOキャッシュの爆発的増加により、数百GBのキャッシュが必要になり、これは 読み込み遅延やスタッタリング の原因となる
- 新しいAPIは、こうした時代遅れの構造を取り除き、シンプルなポインタベースアクセス へ移行できる
GPUメモリ管理の単純化
- 既存のVulkan/DirectX 12では、リソース作成後にヒープ互換性を問い合わせる 必要があり非効率だった
- 提案方式では、gpuMalloc/gpuFree 形式のシンプルなAPIでGPUメモリを直接割り当てる
- CPUがGPUメモリを直接マップして初期化できる
- 大容量データはコピーコマンドで転送し、DCC圧縮やswizzle処理 を行う
- CPUのマップアドレスとGPUアドレスは区別し、gpuHostToDevicePointer で変換する
データとシェーダー言語の近代化
- CUDA・Metal・OpenCLのように、C/C++ポインタベースのシェーダー言語 を使う
- 構造体単位の ワイドロード(128ビット以上) により、効率的なメモリアクセスが可能になる
- DirectXの ByteAddressBuffer や テクセルバッファ は、もはや最適ではない
- GLSL/HLSLはポインタ非対応のため、再利用可能なシェーダーライブラリエコシステムの不在 につながっている一方、CUDAは豊富なライブラリとともに発展してきた
ルート引数とデータ構造
- GPUカーネルは 単一の64ビットポインタ を入力として受け取り、構造体にキャストする
- CPUとGPUが同じC/C++ヘッダを共有し、データ構造の一貫性を確保する
- const/restrict キーワードでコンパイラ最適化を促し、不要なUBO/SSBOの区別をなくす
- 現代GPUの スカラレジスタのプリロード と 動的ユニフォーム最適化 を活用する
テクスチャバインディングの単純化
- すべてのテクスチャを 256ビットディスクリプタ配列(ヒープ) として管理し、CPU・GPUが直接書き込める
- 32ビットインデックスベースのアクセス により、非一様(non-uniform)テクスチャサンプリングをサポートする
- DirectX 12 SM 6.6のディスクリプタヒープより単純で、Vulkan VK_EXT_descriptor_buffer に似ている
- テクスチャオブジェクトの作成・アップロード・サンプリングはすべて GPUメモリポインタベース に統合される
シェーダーパイプラインと定数
- パイプライン作成は、単に シェーダーIRをロードして gpuCreatePipeline を呼ぶ だけでよい
- ルートシグネチャ、ディスクリプタセット、バインディング定義は不要
- 静的定数(structベース) でシェーダーの特殊化定数を置き換え、PSOの組み合わせ爆発 問題を緩和する
- 定数構造体にはGPUポインタを含めることができ、実行時アドレスを直接ハードコードできる
バリアと同期の単純化
- 既存APIの リソースごとのバリアリスト は、現代GPUの構造と一致していない
- 提案モデルでは、キュー/ステージ単位のビットフィールドフラグ のみを使う
- gpuBarrier(before, after, hazard) 形式に単純化し、リソース追跡は不要
- gpuSignalAfter / gpuWaitBefore 命令により、タイムラインセマフォに似たGPU→GPU同期を実装する
コマンドバッファとレンダリング
- 使い捨て(transient)コマンドバッファ のみを使用し、Vulkanの複雑な再利用モデルをなくす
- gpuBeginRenderPass / gpuEndRenderPass でレンダーターゲットの設定とクリアを行う
- レンダーパス間の自動バリアはなく、並列レンダリングや深度プリパス最適化が可能
ラスターパイプラインの単純化
- 頂点/ピクセルシェーダー はポインタベースのデータアクセスにより、バインディングAPIを不要にする
- GpuDepthStencilState、GpuBlendState をPSOから分離し、組み合わせ数を減らす
- モバイルGPUは フレームバッファfetch intrinsic により、プログラマブルブレンドをサポートする
- PSOには最小限の状態(トポロジ、フォーマット、サンプル数など)のみを含める
間接ドローとGPU駆動レンダリング
- すべての引数(data、arguments)を GPUポインタ として渡す
- gpuDrawIndexedInstancedIndirectMulti によりマルチドローをサポートする
- GPUがルートデータとドロー引数を直接生成でき、完全な GPU駆動レンダリング を実現できる
ツーリングと互換性
- ポインタベース構造は、CUDA/Metalデバッガ のようにシンボル情報を通じて追跡できる
- 仮想メモリで保護されるためセキュリティ上の問題はなく、誤ったアクセス時にはページフォルトが発生する
- MoltenVK、Proton の事例のように、既存のDirectX/Vulkan/Metal APIは変換レイヤーとして互換運用できる
最小要件と結論
- Nvidia Turing(2018)、AMD RDNA1(2019)、Intel Xe1(2022)、Apple M1(2020) などは、いずれも提案された機能をサポートしている
- 今日のGPUはすでに バインドレス・64ビットポインタ・一貫キャッシュ 構造へ移行している
- 過去の抽象化に縛られているのはAPIだけである
- 新しいAPIは DirectX 11より単純で、Vulkanより高速、Metalより柔軟 である
- 次世代の Vulkan 2.0 / DirectX 13 は、この 完全バインドレス設計 へ移行し、HLSL/GLSLの代わりに C/C++ポインタベースのシェーダー言語 によるエコシステム拡張を進めるべきである
1件のコメント
Hacker Newsの意見
この記事は、Vulkan と DX12 の不要な部分をうまく示した素晴らしい記事だと思う
最近の DX12 はバッファポインタすらサポートしておらず、事実上放置されているように感じるし、Vulkan も 2.0 として整理されていないため、拡張機能 がきちんと実装されていないドライバが多い
もしこうした新しい API が存在するなら、その上で OpenGL をはるかに高速にエミュレートできるだろうし、SDL3 GPU のようなものも 3〜4 倍の性能向上を得られそうだ
Frank Luna の本も最新機能を扱っておらず、Learn サイトや GitHub のサンプル、リファレンス文書を漁るしかない
Vulkan も同様に複雑で、たとえ 2.0 が出たとしても、特に Android のような主要プラットフォームで実際にどう使えるのかは疑問だ
Intel Arc を除けば、大半の GPU は reBAR なしでも動作するが、Microsoft や Intel がこれを UEFI で強制しないと、bindless texture のような機能を安定して使えないのかもしれない
ただ、その場合はサポート可能なハードウェアの下限ができてしまい、2020 年以前のマザーボードでは対応状況にばらつきがある
記事の中核となる動機が抜けている
ブログのインデックスによれば、「過去 10 年でグラフィックス API とシェーダ言語の複雑性が急激に増し、今こそ 抽象化レイヤーを単純化 して開発効率と性能を高め、将来の GPU ワークロードに備えるべきだ」という趣旨だ
SSD は当初 IDE/SATA インターフェースを流用していたが、回転ディスク前提を捨てて新しい転送方式を作ってこそ本来の性能を発揮できた
グラフィックス API もそうした レガシー制約 を捨てるべき時期に来ている、という比喩に見える
私は Sebastian Aaltonen の仕事を長く追ってきたので偏っているかもしれないが、今回の記事は本当に素晴らしい
今後の方向性は ソフトウェアレンダリングへの回帰 だと考えている
ただし今回は、そのアルゴリズムとデータ構造がハードウェアアクセラレーションを受けるという点が違う
すでに VFX 業界ではこうした流れが進んでおり、約 5 年前に OTOY が OctaneRender を CUDA ベースに移植したのもその一例だ
シェーダタイプはこうしたパイプラインの間を埋める役割を果たしているので、完全なソフトウェア化は現実的ではない
たとえば Unreal Engine の Nanite は、小さな三角形を処理する際に GPU の compute shader 上で動くソフトウェアラスタライザを使っている
この記事のディテールは印象的だった
一部しか理解できなかったが、今後の グラフィックス API 設計の参考書 になりそうだ
大半のゲーマーにとって Vulkan/DX12 は大きな利点ではなく、PSO の問題で多くのゲームが苦しんだ
Vulkan は改善中だが、WebGPU は初期の Vulkan 設計上の制約をそのまま受け継いでいる
ハードウェアが急速に進化している状況で、API をあまりに低レベルにしすぎたのは失策だったのかもしれない
むしろ CUDA のように汎用コンピューティング中心で考える方が良い方向なのかもしれない
Mantle が懐かしくなる
欠点もあったが、ハードウェアを直接触っている感覚があり、Xbox 360 の開発をしていた頃がいちばん楽しかった
Nvidia と Nintendo が設計したもので、コンソールの中では最も直感的な API だと思う
この記事を読んで、歴史的な瞬間 を目撃しているような気分になった
関連プロジェクトとして Google Toucan を思い出した
この記事は昔の記憶をいろいろ呼び起こした
API 設計者が考慮する追加要素としては、
なぜ Microsoft が新しい DirectX バージョン を出さないのか気になる
DirectX Ultimate や 12.2 も実質的には DX12 と同じだ
Unreal Engine のようなミドルウェアの影響で独自 API の重要性が下がったのか、それとも EPIC が新しい API を提案すべきなのかと思う
実際のゲーム開発者は RHI(Rendering Hardware Interface)を作ってゲーム開発そのものに集中する
レイトレーシング と メッシュシェーダ が最大の革新だったが、いまだ活用は少なく、それ以上先に進んでいないように見える
Unreal や Unity といったエンジンの 中央集権化 によって API 革新への関心が薄れ、進化は GPU 側だけで続いている
CPU API はいまでも単純なバッファマッピング程度にとどまっている
かつて テッセレーションシェーダ が登場したときのように、新しいハードウェアの変化がないと前進は難しそうだ
Valve が SteamOS 向けに独自のグラフィックス API を作る可能性はあるのだろうか
Vulkan の初期開発段階で、Valve は主要な推進役の一つだったと聞いている