世界を動かす技術を、日本語で。

Vulkanを一つのサブシステムずつ簡素化する

概要

  • Vulkan® APIの進化には 拡張機能 (Extensions)が重要な役割
  • 拡張機能の増加による “Extension Explosion Problem” の課題
  • 部分的な改善ではなく サブシステムの丸ごと置き換え が新たなアプローチ
  • VK_EXT_descriptor_heap はその具体例であり、広範な業界の協力で開発
  • コミュニティからの フィードバックを歓迎 し、今後のAPI改善に活用

Vulkan API進化のための拡張機能活用

  • Vulkan®ワーキンググループ はAPIの機能追加や仕様のギャップ解消を目的に 拡張機能 を活用
  • 拡張機能により 新機能 を迅速に開発者へ提供
  • ベンダー独自の機能公開や コミュニティのフィードバック収集 が可能
  • コア仕様に盛り込む前に実践的な検証と改善が行える体制
  • OpenGL®/ES™ 時代から続く拡張機能増加による複雑化問題

Extension Explosion Problem(拡張機能爆発問題)

  • 拡張機能の増加による 利用方法の複雑化 と分かりづらさ
  • どの機能が常に利用可能か、最適な手法は何かといった判断の困難化
  • 複数の拡張機能が 連鎖的に絡み合う ことで開発者の負担増大
  • OpenGL® からVulkan®に移行した際の“クリーンスレート”も10年で再び同様の問題発生
  • APIの抜本的な再設計は非現実的なため、 新たな拡張機能によるサブシステム置き換え が提案

サブシステム置き換えの新手法

  • 部分的な拡張や改善 ではなく、APIサブシステム全体を 新拡張機能で丸ごと置き換え る手法
  • 新方式では 過去のAPIとの互換や依存を断ち切る 設計
  • VK_EXT_descriptor_heap は既存のディスクリプタセットサブシステムを完全に置き換える初の試み
  • ディスクリプタが 単なるデータ・メモリ として扱える柔軟な設計
  • コンソール機に近い操作感 を提供し、ポータブルAPIの制約を軽減

VK_EXT_descriptor_heapの特徴と開発経緯

  • 過去の VK_EXT_descriptor_buffer の経験と課題を踏まえた再設計
  • 既存のディスクリプタセットAPIやレイアウト、プッシュディスクリプタ等との 非互換性 を明示
  • 広範な業界の協力と Vulkan Working Group全体の知見結集
  • 3年以上かけて設計・改良 を重ね、品質と実用性を両立
  • 現時点では EXT拡張 として提供、将来的な コア(KHR)化 を視野

コミュニティフィードバックと今後の展望

  • EXT拡張 の段階で幅広い開発者からのフィードバックを募集
  • 仕様の大幅な変更予定はないが、 KHR化時に移行しやすい設計
  • 9ヶ月以内 のフィードバックが仕様完成への重要なインプット
  • 他の機能要望も DiscordやGitHub で積極的に受付
  • サブシステム置き換え手法を 今後のAPI刷新 にも適用予定

今後のVulkan APIと開発者への呼びかけ

  • 開発者ニーズ中心 のロードマップ策定と優先順位付け
  • エコシステム全体、ベンダーのロードマップ、将来のハード・ソフト動向も考慮
  • 使いやすく、楽しいAPI への進化を最優先
  • サブシステム置き換えによる 抜本的な改善 を今後も推進
  • フィードバックや意見 を積極的に求める姿勢

Hackerたちの意見

この変更、めっちゃ楽しんでる!レンダーパスからダイナミックレンダリングに移行したら、コードがすごくシンプルになった。新しい機能は、既存のバインドレスレンダリングと比べてどうなんだろう?リンクされた動画で言ってた「OpenCLとの機能の互換性」が一番楽しみだな。

オプションの「ルートシグネチャ」を設定すれば、既存のバインドレスシェーダーでもデスクリプタヒープが使えるよ。ただ、新しいGLSL/SPIR-V機能(またはSlang)を使うようにシェーダーを変更する方が簡単そうだね(できるなら)。ルートシグネチャを全く指定しない方がいいし、複雑で冗長だからね。デスクリプタヒープはセットアップコードをかなり減らしてくれるし、パイプラインレイアウトがなくなったから、始めるのに必要なコードの3分の1を削減できるよ。ダイナミックレンダリングと同じくらいの効果だね。

個人的には、どこでもプッシュデスクリプタを使うように切り替えたよ。デスクトップでは、実際の制限が高いから、うまくいくし、OpenGLみたいな即時モードAPIが使えるんだ。

シンプルなユースケースや新しいプロジェクトを始めるには、これが正しい方法だね。

Vulkanを使いたいんだけど、OpenCLから移行するのがめっちゃ大変で、いろんな問題があって安全に扱わなきゃいけないんだ。OpenCLのワークロードからは出てこない問題ばかり。みんなOpenCLは非推奨だって言うけど(確かにそうだけど、2026年でもバリバリ動いてるのも事実)、自分のやってることに正当性を持たせるための良い公式のOpenCLからVulkanへのラッパーがないんだよね。

少なくとも、拡張機能のスパゲッティを修正しようとしてるのは評価できる。もうOpenGLよりひどい状態だしね。さらに、これらの修正のほとんどはAndroidには入ってこないし、OpenGL ESから移行を拒否する人が多かった後に、Java/Kotlin用のWebGPUがやっと出てきたところだし、運が良くないカードは新しいドライバーも出ないしね。それでも、今やらないよりはマシだよね。[0] - https://developer.android.com/jetpack/androidx/releases/webg...

さらに、これらの修正のほとんどはAndroidには来ないよ 何言ってるの?もちろんAndroidにも来るよ。

変な意見だね。WebGPUがAndroidXライブラリだって気づいてる?つまり、WebGPU APIのサポートはそのライブラリを通じてアプリに組み込まれていて、システムのVulkanやOpenGL ES APIの上で動いてるってことだよ。君はGoogleかAndroidのOEMで働いてるの?そうじゃないなら、AndroidがVulkan APIのサポートを更新しなくなるって主張する根拠はないよ。

ゲーム開発者として言わせてもらうと、AndroidでVulkanをサポートしないでOpenGL ESにこだわるのは安全策だと思う。Vulkanでバグが出るデバイスは常にあるからね。誰もその変なベンダーのために workaround を見つけるのは嫌だよ。

Vulkanの主な問題は、プログラミングモデルや機能の不足じゃないんだ。Khronosがそれに取り組んでるからね。問題はカバレッジとアップデートの配布なんだ。めちゃくちゃばらばら!一般的なソフトウェア(Zedみたいな)を開発してると、ダイナミックレンダリングみたいな基本的なことですら均一にサポートされてるとは限らない。古いドライバーを使ってる変なシステム(Ubuntu 22 LTSを見てる)、ハードウェアベンダーが放置して使えなくすること、もちろんドライバーバグも…新しいデスクリプタヒープやバッファ機能に頼れるようになる頃には、もっと白髪が増えてるだろうし、他にもいろいろあるだろうな。

正直言って、時代に合わないGPUベンダーはさっさと見限るべきだよね。長いこと彼らに合わせてたら、適応する理由がなくなっちゃうから。

Ubuntu LTS だから、僕は新しいLinuxユーザーにはUbuntuをあまり勧めないようにしてるんだ。機能面で遅れをとってるからね。今や企業向けOSになっちゃって、耐久性が機能性よりも重要視されてるし、パワーユーザー(Zedみたいな人)にはあまり向いてないよ。

古いドライバーを使った変なシステムはいつもあるよね(Ubuntu 22 LTSを見てる) 一般的な意見には賛成だけど、RHELはもっと目立つと思う。Ubuntu 22.04とRHEL 9はどちらも2022年にリリースされたけど、Ubuntu 22.04は2027年の中頃まで一般サポートがあって、2032年の中頃までセキュリティサポートがある。一方、RHEL 9は2032年の中頃まで「本番」サポートがあって、2034年の中頃まで延長サポートがある。ウィキペディアの情報はこちら: [0] https://en.wikipedia.org/wiki/Ubuntu#Releases [1] https://upload.wikimedia.org/wikipedia/en/timeline/fcppf7prx...

Vulkanがようやく使えるようになるまで、あと5〜10年くらいだと思う。完全に不必要に複雑なことがたくさんあるし、一般的なケースのための簡単な道が必要なものもある。BDA、ダイナミックレンダリング、シェーダーオブジェクトがあれば、Vulkanもなんとか耐えられる。まだまだ足りないのは、一行でデバイスのメモリ確保ができること、キューのファミリーAPIに触れずに使えるデフォルトのキュー、完全にデスクリプタなしのコードパスだね。後者は、NVのバインドレス拡張を標準にして、テクスチャのハンドルを管理させずに渡すようにすることだと思う。同期のための簡単な道もリストに入れて、明示的なAPIをオプションにしてほしいな。それまでは、2010年からglslシェーダーでCスタイルのポインタ構文を使ったBDAがあるOpenGL 4.6を楽しむつもりだよ(NV_shader_buffer_load)。それに、手間いらずのバッファ割り当てとデスクリプタセットなしのバインドレステクスチャが使えるしね。

毎日Vulkanを使ってるよ。いくつかの例: - DXVKを使ってゲームをプレイ - llama.cppを使ってローカルのLLMを動かす VulkanはゲームからAIまで、もうどこにでもあるね。

このVulkan APIの進化は、https://www.sebastianaaltonen.com/blog/no-graphics-api で説明されているモデルに近づいているのかな?これについては https://news.ycombinator.com/item?id=46293062 で話したよね?

うん、この拡張と既存のVulkan拡張を使えば、そのAPIにかなり近づけるよ。主な違いは、まだ生ポインタの代わりに不透明なバッファやテクスチャオブジェクトが必要ってことだけど、それらのGPUポインタを取得して使うことはできる。理論的にはmalloc APIデザインもできると思うけど、Vulkanではちょっと直感的じゃないし、ラッパーレイヤーで公開しなくても内部的にはVkBuffersが必要になる。今はまだ公開準備中のVulkanのラッパーを作ってるけど、この記事にほぼ一致してるし、今のところグラフィックスプログラミングをするのにすごく楽しい方法だよ。Vulkanの上で全く不可能なのは彼のシグナルAPIで、これが見てみたいな。タイムラインセマフォがコマンドバッファ内で待機・シグナルできるようになれば実現できるかもしれないけど、既存のハードウェアでどれだけ実現可能かはわからないな。

これはその方向への一歩だね。Sebの記事からの引用だけど、 > VulkanのVK_EXT_descriptor_buffer(https://www.khronos.org/blog/vk-ext-descriptor-buffer)拡張(2022)は、直接CPUとGPUに書き込むことを可能にする僕の提案に似てる。ほとんどのベンダーがサポートしてるけど、残念ながらVulkan 1.4のコア仕様には含まれてないんだ。Khronosの投稿で説明されている新しいVK_EXT_descriptor_heap拡張は、VK_EXT_descriptor_bufferの代替で、いくつかの問題を解決しているけど、基本的には同じアイデア(例えば「デスクリプタは単なるメモリ」)なんだ。

すべてをバッファポインタとしてGPUにプッシュできるようにしてくれればいいのに、バッファデバイスアドレス拡張がそうさせてくれるみたいに、そしてシェーダーを通じて必要なフォーマットにデータを再構築できるように。GPUプログラミングは超低レベルでもありつつ、高レベルでもあるから、テクスチャやデスクリプタは超特定のデータフォーマットが必要だし、それらのフォーマットを構築してアップロードする方法はすごく複雑で、いつも変わってる。これを簡素化する方法は本当にないのかな?通常の頂点データもパイプラインで厳密に事前フォーマットされるはずだったけど、突然そうじゃなくなって、今はシェーダーにdevice_address拡張のメモリポインタを渡して、そのデータを構築できるようになったんだ。

関連情報: XDC 2025の「ディスクリプタは難しい」 - https://www.youtube.com/watch?v=TpwjJdkg2RE たとえ最新のハードウェアでも、APIレベルで調整しなきゃいけないアーキテクチャの違いがまだまだたくさんあるよね。

あなたが言ってること、私も欲しいな。純粋な計算ベースのシェーダーにとって理想的な「データイン・アウト」パイプラインのように思える。チップレベルでこれらの操作を最適化する人たちと話すときに何度も提起してきたけど、提案していることには予期しない複雑さがたくさんあるって言えるよ。これらのことをするGPUが持てないわけじゃなくて、過去と現在のアーキテクチャの決定がそれを望まないって感じだね。例えば、nVidiaのGPUはLLM計算かグラフィックスアクセラレーションのために必要なハードウェア最適化を提供することに焦点を当てている。どちらも本質的に独自の技術だからね。独自性が理由で難解なわけじゃなくて、特定のタスクのためにチップを超高速にすることも、あらゆるタスクに対してもっと一般的にすることもできる。どこかで、後方互換性と新しいハードウェアアクセラレーションタスクのサポートのトレードオフをしている人たちがいるんだ。どちらも「汎用計算とデータフロー」に焦点を当てているわけじゃないから、結局は自分がやりたいことに対してちょっとしか設定できないGPUが出来上がる。だから、あなたの「GPUプログラミングは超低レベルでもあり、高レベルでもある」というコメントが理解できる。私もそういう経験をしてきた。あなたの提案は素晴らしいアイデアだと思うし、GPUをもっとオープンな計算プラットフォームにして、さまざまなタスクを簡素化すると思うよ。

最近はRustを以前ほど詳しく見てないけど、バッファの所有権についてもっと活用すべきだと思う。昔からある並行処理のパターンで、プロデューサーとコンシューマーが2セットのバッファを使ってスループットを上げるやり方がある。プロデューサーがバッファを埋めて、所有権をコンシューマーに渡し、代わりに前のバッファを受け取るって感じ。これはダブルバッファリングのビデオに似てるけど、データ全般に使える。Rustはその健全性を証明するのに向いてると思うし、今は自分で作るんじゃなくてライブラリにすべきだね。

もし求めているものが手に入ったら、固定機能ハードウェアへのアクセスを失うことになるだろうね。あなたの例に関して言えば、データフォーマットを知っていることで、画像フォーマット間の自動的なハードウェアアクセラレーション翻訳が可能になる。手動でコンピュートシェーダーを使ってすべての操作を行えば、あなたが求めていることは自由にできるよ。手動でクリッピング、変換、ラスタライズ、さらにはテクスチャのサンプリングもできる。ただし、現在のように享受している様々な固定機能ハードウェアの暗黙の利用は失われることになる。

Vulkanは、Metalが50行でやることを600行以上必要とする。コメントは言い訳や理由で埋まるだろうけど、全部無意味だよ。単に考えが甘いAPIってこと。

同意。完全に不必要な冗長さが多すぎる。なんでメモリを割り当てるのに30行も必要なんだよ、一行のmallocで済むのに。

DirectXも同じだね。COMが実際にもっと良いツールを持ってればいいのに、冒険を選ぶC++フレームワークか、.NETの一級サポートしかないんだよね。

複数のベンダーによって実装される必要があるAPI標準についての私の理解は、プログラマーにとって使いやすいものと、ベンダーにとって実装しやすいものの間にはトレードオフがあるってことだ。OpenGLについてよく聞く不満は、ドライバー間での動作が一貫していないことなんだけど、これはその高レベルな性質をサポートするために必要なドライバーコードの量が原因だと主張できる。低レベルのAPIは実装に必要なドライバーコードが少なくて済むから、その複雑さを最終的にラップするために書かれるオープンソースライブラリに移すことができる。グラフィックスプログラマーとしては、そのライブラリの一つを選んで、より良いクロスプラットフォームサポートを無料で得ることができる。例えば、私は個人的にVulkanを使ったことはないけど、ANGLEのおかげでOpenGLプログラムで恩恵を受けているよ。

これが「おお、やばい」な出来事かどうかは分からないな。これがVulkanに入るってことは、OSと一緒に出荷される必要があるし、WGPUみたいな中間層にも入れなきゃいけない。多分、古いモードと新しいモードの両方をサポートする必要があるだろうし、レンダラーにも入れなきゃいけない。レンダラーの最上部では古いモードか新しいモードか分からないかもしれないけど、漏れ出る可能性は高い。そうなるとゲームエンジンもこれを知っておく必要がある。これがゲームコードに混乱をもたらすだろうし、AppleはMetalで何か違うことをするだろうね。Unreal EngineやUnityはこの対応ができるスタッフがいるけど、他のほとんどは無理だろうな。Vulkanの並行処理を使ってOpenGLでは出せないパフォーマンスを引き出すVulkanベースのレンダラーは少ない。多分、Unreal EngineとUnityだけがVulkanをちゃんと活用してると思う。これがVulkanの変更のトップレベルだね。簡単には見えないな。(Vulkan/WGPUの難しさと混乱のせいで、Rust界隈では開発者の疲弊によって3つのレンダラーが放棄されたから、愚痴ってるだけなんだ。レンダラーを使う側としては、ちゃんと動いてほしいな。)

これが「おお、やばい」な出来事かどうかは分からないな。 それは違うよ。デスクリプターセットは現実的には廃止されることはないから。古いコードは動いてるなら書き換える必要はないし、意味がないよ。バインドレスをやってるなら(デスクリプターセットにまだこだわってるなら、まず無理だけど)、これがその処理をより良く扱う方法を提供するよ。デスクリプターセットベースのパスをヒープを使うようにアップグレードしたいなら、この拡張はシェーダーを再コンパイルすることなく、すごくいい道筋を提供してくれる。新しいコードや将来のコードにとっては、これはしっかりした改善だよ。レンダラーに満足してるなら、特に何かをする必要はないね。