Apple Metal API:大したことは何ですか?

画像 WWDC 2014では、驚きが待っていました。Metalと呼ばれる新しい3DグラフィックスAPIの発表です。 ただし、今回はOpenGL ES上の新しい高レベルAPI(Scene Kitの場合のように)ではなく、ゲームのOpenGLの代替として機能するレンダリングおよびコンピューティング用の新しい低レベルAPIを扱います。 Appleによると、MetalはOpenGL ESよりも最大10倍速く(正確には、 描画呼び出しを生成でき、GPUへのデータ転送] 10倍速く)、iOSデバイスと最新のA7プロセッサでのみ利用可能です。



この発表は、OpenGLを置き換える必要がある(または知ってはいけない-知ってはいけない)新しいグラフィックスAPIの必要性についての議論と議論の新しい波を引き起こしました。 この投稿はこの議論に参加するつもりはありません-その目的は、MetalがOpenGL ESとどのように異なるかを明確にすることです。 このような特別な(または逆に特別なものはない)がMetal APIにあることを理解するには、グラフィックAPIとGPUの「フード」の下を少し見る必要があります。



GPUとグラフィックスAPIの仕組み


素朴な読者は、APIを直接呼び出すとGPUで何かを実行するか、GPU内で何かを実行できるようにすることを提案する場合があります。 さらに素朴な読者は、APIが結果を返すときにGPUがこの呼び出しの処理を終了すると想定しています。 これらの声明は両方とも現実にはほど遠い。 ドライバーが作成された直後にレンダリングコマンドを実行し、レンダリングプロセスが完了するのを待ってから結果をAPI呼び出しに返す場合、プロセッサーの1つは常にロックされるため、CPUもGPUも効率的に動作できませんでした別に。



GPUのパフォーマンスを簡単に改善するには、このプロセスを非同期で開始する必要があります。 その後、GPUはCPUをブロックせず、API呼び出しはほぼ即座に結果を返します。 この場合、GPUはCPUが新しいレンダリング呼び出し(=フレーム開始)を行うのを待つ必要があるため、GPUが完全に使用されない可能性がありますが、他のコマンドの呼び出しは前のコマンドの完了を待ちます。 これが、ほとんどのグラフィックスドライバーがすべての描画呼び出し (およびGPUで実行する必要がある他のタスク-状態の変更など)を収集して、GPUに送信する前にフレーム全体を描画する理由です。 これらのバッファされたコマンドは、次のフレームを描画するコマンドが受信された後に送り返されるため、GPUは可能な限り効率的に使用されます。 もちろん、これにより1つの遅延フレームが追加されます。CPUは現在のフレームのタスクを作成しますが、最後のフレームはGPUでレンダリングされます。 実際、複数のフレームをバッファリングして、より大きな遅延のために、より高いフレームレートを達成できます。



単純な仮定のもう1つの間違いは、状態変更の課題が何をするかの仮定です。



そのため、最新のGPUで動作するOpenGLの背後で起こっていることについて少なくとも2つの重要なことを学びました:状態の新しい組み合わせが必要な場合、状態の変更は困難であり、GPUでのすべての操作が一定時間遅延します。



アプリケーションでは、GPUで実行される1つのフレームに関連するコマンドの1つのストリームが一度に形成され、GPUに一度に送信されます(実際、すべてが少し複雑になりますが、まだ深く入りません)。



Fabian Giesensによる一連の記事「グラフィックスパイプラインの旅 」で、最新のコンピューターグラフィックスパイプラインの仕組みについて詳しく読むことができます。



別のソフトウェアモデルに利点がある理由


すでに見たように、プログラマーには膨大な量の複雑さとトリックが隠されており(おそらく、私が言及したよりもさらに多くのものがあります)、直接起こっていることを隠しています。 単純な開発者の生活を楽にするものもあれば、ドライバーを裏切る方法や、API呼び出しの副作用の方向に「掘る」方法を探すものもあります。



今日のいくつかのグラフィカルAPIは、これらのトリックのほとんどを削除しようとして、隠れている「混乱」を明らかにします。場合によっては、プログラムに関連するすべての問題を解決できるようにします。 PS3グラフィックスAPIはこの方向に進み、AMDとそのマントルはその方向に進み、今後のDirectX 12とApple Metalもそこに行きます。



何が変わった?


これで、コマンドバッファーが開かれ、アプリケーションはこれらのバッファーをいっぱいにしてコマンドキューに送信し、GPIで指定された順序でこれらのバッファーを実行します。これにより、アプリケーションはGPUに送信されるタスクを完全に制御し、追加する必要がある遅延フレームの数を決定します(遅延を追加しますが、同時にGPUの使いやすさを向上させます)。 GPUでのコマンドのバッファリングと次のフレームへの非同期送信は、アプリケーション自体で実装する必要があります。



これらのバッファーはすぐには実行されない(つまり、作成時に)こと、および複数のバッファーを特定の順序で作成して実行キューに追加できることが明らかになるため、アプリケーションはそれらを複数のスレッドで並行してビルドする余裕があります。 また、プログラマーにとって、どの計算結果がすでに利用可能であり、どの計算結果が利用可能でないかがより明らかになります。



状態の変更は、単純に切り替えることができる状態オブジェクトに整理されるようになりましたが、これらのオブジェクトの作成はより高価になります。 たとえば、MTLRenderPipelineStateには、シェーダーと、パッチによって実装されるすべての状態が含まれます。



新しいAPIのもう1つの利点は、以前のバージョンとの互換性の負担を負う必要がないため、それほど保守的ではないことです。



A7のシャープ化にはニュアンスがあります-それのおかげで、Metalは共有メモリを持つシステムで作業するためにシャープ化されています。 CPUとGPUは、PCIバスを介して転送する必要なく、同じデータに直接アクセスできます。 Metalは、プログラムがCPUからバッファーに直接アクセスできるようにし、このデータがGPUによって同時に使用されないという事実の責任はプログラマーにあります。 この便利な機能を使用すると、GPUとCPUでコンピューティングの作業を混在させることができます。



そして、それはどのように10倍高速ですか?


各描画呼び出しには、CPUとGPUで時間がかかります。 Metal APIは、状態の監視を簡素化することでCPU時間を短縮し、正しい状態の組み合わせに対するドライバーからのエラーチェックの回数を減らします。 状態の予備計算も役立ちます。ビルド中にエラーチェックを実行できるだけでなく、状態の変更自体に必要なAPI呼び出しが少なくなります。 命令バッファを並行して構築する機能により、アプリケーションがCPUに関連付けられている場合でも、描画呼び出しの数が増加します。



しかし、一方でGPUでのレンダリングは速くなりません。大きなメッシュ( メッシュはオブジェクトの頂点で構成されるモデルの一部です)の描画呼び出しをほとんど行わないアプリケーションは、Metalに切り替えてもメリットがありません。



OpenGLでも同じことができますか?


GDC 14には、キャスエヴィット、ジョンマクドナルド、グラハムセラーズ、ティムフォーリーによる「 アプローチゼロドライバーオーバーヘッド 」の優れたプレゼンテーションがありました。 その主なアイデアは、描画呼び出しによって生成される作業量を増やし、新しいGLオブジェクトと少ないGL呼び出しを使用して効率を高めることにより、OpenGLでのドライバーの作業を減らすことでした。



このアイデアや他のアイデアには、OpenGLのさらなる拡張とこのAPIの新しいバージョンの外観が必要になりますが、この多くはOpenGL ESに移植できます。 失うのは、長所と短所をすべて備えたコマンドバッファーを直接制御する機能です。



将来これを見る可能性はどのくらいですか? 下位互換性のサポートにより、「モダンカーネル」と呼ばれる特定の関数セットの出現のみを期待できますが、ほとんどの場合、元のglBegin()関数までのすべてと互換性を持たせる必要があります。 この制限は、OpenGLの将来の可能性を通じて継続され、進化の限界になり、Metal APIのような代替手段がますます好まれるようになります...



元の記事:

http://renderingpipeline.com/2014/06/whats-the-big-deal-with-apples-metal-api/



All Articles