web-dev-qa-db-ja.com

OpenGLは最低レベルでどのように機能しますか?

私はOpenGL/DirectXプログラムの書き方を理解しており、その背後にある数学と概念的なものを知っていますが、GPU-CPU通信が低レベルでどのように機能するか興味があります。

Cで記述された三角形を表示し、カメラを45度回転するOpenGLプログラムがあるとします。このプログラムをコンパイルすると、一連のioctl呼び出しに変換され、gpuドライバーは適切なコマンドをgpuに送信します。ここで、三角形を回転し、適切な色で適切なピクセルを設定するすべてのロジックが配線されますに?または、プログラムは、gpuにロードされ、回転などを計算する「gpuプログラム」にコンパイルされますか?それとも完全に異なるものですか?

Edit:数日後、この記事シリーズを見つけました。これは基本的に質問に答えます: http://fgiesen.wordpress.com/ 2011/07/01/a-trip-through-the-graphics-pipeline-2011-part-1 /

81
Benno

OpenGL自体は単なるフロントエンドAPIであり、実装が仕様に準拠し、結果がこれに準拠している限り、任意の方法で実行できるため、この質問に答えることはほとんど不可能です。

問題は、OpenGLドライバーが最低レベルでどのように機能するかです。ドライバーはハードウェアの一部と密接に結びついているため、これは一般的に答えることは再び不可能です。

したがって、質問は「OpenGLとグラフィックスシステムの舞台裏で平均してどのように見えるのでしょうか?」でした。これを下から見てみましょう。

  1. 最下層にはグラフィックデバイスがあります。現在、これらは動作を制御するレジスタのセットを提供するGPUです(レジスタはデバイスに完全に依存しています)シェーダー用のプログラムメモリ、入力データ(頂点、テクスチャなど)用のバルクメモリ、および残りへのI/Oチャネルを備えていますデータおよびコマンドストリームを受信/送信するシステムの.

  2. グラフィックスドライバーは、GPUの状態と、GPUを使用するすべてのリソースアプリケーションプログラムを追跡します。また、アプリケーションによって送信されたデータの変換またはその他の処理を行います(テクスチャをGPUがサポートするピクセル形式に変換し、GPUのマシンコードでシェーダーをコンパイルします)。さらに、アプリケーションプログラムへの抽象的なドライバ依存インターフェイスを提供します。

  3. 次に、ドライバーに依存するOpenGLクライアントライブラリ/ドライバーがあります。 Windowsでは、これはopengl32.dllを介してプロキシによってロードされます。Unixシステムでは、これは2つの場所にあります。

    • X11 GLXモジュールおよびドライバー依存GLXドライバー
    • および/usr/lib/libGL.soには、直接レンダリング用のドライバー依存のものが含まれている場合があります

    MacOS Xでは、これはたまたま「OpenGLフレームワーク」です。

    この部分は、OpenGL呼び出しをどのように実行するかを、(2)で説明されているドライバーの一部のドライバー固有の関数の呼び出しに変換するものです。

  4. 最後に、実際のOpenGL APIライブラリ、Windowsのopengl32.dll、Unixの/usr/lib/libGL.so。これは主に、コマンドを適切なOpenGL実装に渡すだけです。

実際の通信がどのように行われるかは一般化できません。

Unixでは、3 <-> 4接続は、ソケット(はい、必要に応じてネットワークを経由します)または共有メモリ経由で行われます。 Windowsでは、インターフェイスライブラリとドライバークライアントの両方がプロセスのアドレス空間に読み込まれるため、それほど多くの通信ではなく、単純な関数呼び出しと変数/ポインターの受け渡しが行われます。 MacOS Xでは、これはWindowsに似ていますが、OpenGLインターフェースとドライバークライアントが分離されていないだけです(これが、MacOS Xが新しいOpenGLバージョンに対応するのが非常に遅い理由です。フレームワーク)。

3 <-> 2の間の通信は、ioctl、読み取り/書き込み、または一部のメモリをプロセスアドレス空間にマッピングしてMMUを構成し、そのメモリへの変更が行われるたびにドライバコードをトリガするカーネル/ユーザーランドの境界を常に横断する必要があるため、これはどのオペレーティングシステムでも非常に似ています:最終的には、syscallを実行します。

システムとGPU間の通信は、ペリフェラルバスとそれが定義するアクセス方法を介して行われるため、PCI、AGP、PCI-Eなどは、ポートI/O、メモリマップI/O、DMA、IRQを介して機能します。

82
datenwolf

このプログラムをコンパイルすると、一連のioctl呼び出しに変換され、gpuドライバーは適切なコマンドをgpuに送信します。ここで、三角形を回転し、適切な色で適切なピクセルを設定するすべてのロジックが配線されますに?または、プログラムは、gpuにロードされて回転などを計算する「gpuプログラム」にコンパイルされますか?

あなたは遠くない。プログラムはインストール可能なクライアントドライバーを呼び出します(これは実際にはドライバーではなく、ユーザースペース共有ライブラリです)。これは、ioctlまたは同様のメカニズムを使用して、カーネルドライバーにデータを渡します。

次の部分では、ハードウェアに依存します。古いビデオカードには、「固定機能パイプライン」と呼ばれるものがありました。ビデオカードには、マトリックス用の専用メモリスペースと、テクスチャルックアップ、ブレンドなど専用のハードウェアがありました。ビデオドライバーは、これらの各ユニットに適切なデータとフラグをロードし、DMAをセットアップします。頂点データ(位置、色、テクスチャ座標など)を転送します。

新しいハードウェアでは、ビデオカード内にプロセッサコア(「シェーダー」)があります。CPUは、それぞれの実行速度がはるかに遅いという点で異なりますが、並行して動作するものがさらに多くあります。これらのビデオカードの場合、ドライバーはプログラムバイナリを準備してGPUシェーダーで実行します。

23
Ben Voigt

プログラムは特定のGPU用にコンパイルされていません。 OpenGLを実装するライブラリに対して動的にリンクされているだけです。実際の実装には、OpenGLコマンドのGPUへの送信、ソフトウェアフォールバックの実行、シェーダーのコンパイルとGPUへの送信、またはOpenGLコマンドへのシェーダーフォールバックの使用が含まれます。グラフィックスの風景はかなり複雑です。ありがたいことにリンクすることで、ドライバーの複雑さのほとんどを回避でき、ドライバーの実装者が適切と思われる技術を自由に使用できるようになります。

19
Tobu

C/C++コンパイラ/リンカーは、テキストファイルをCPUで実行される一連のマシン固有のオペコードに変換することを1つだけ行います。 OpenGLとDirect3Dは単なるC/C++ APIです。 C/C++コンパイラ/リンカーをGPUのコンパイラ/リンカーに魔法のように変換することはできません。

作成するC/C++コードの各行は、CPUで実行されます。 OpenGL/Direct3Dの呼び出しは、場合によっては静的または動的なC/C++ライブラリを呼び出します。

「gpuプログラム」が機能するのは、コードでシェーダーを明示的に作成する場合のみです。つまり、シェーダーのコンパイルとリンクを引き起こすAPIをOpenGL/D3Dに呼び出す場合です。これを行うには、(C/C++コンパイル時ではなく、実行時に)シェーダー言語のシェーダーを表す文字列を生成またはロードします。次に、シェーダーコンパイラーでそれらを突き出し、そのシェーダーを表すそのAPIのオブジェクトを取得します。次に、特定のレンダリングコマンドに1つ以上のシェーダーを適用します。これらの各ステップは、C/C++コードの指示で明示的に行われ、前述のようにCPUで実行されます。

多くのシェーダー言語は、C/C++のような構文を使用します。しかし、だからといってC/C++と同等になるわけではありません。

16
Nicol Bolas