では、glDraw や gLBufferData などの opengl 関数を呼び出すと、プログラムのスレッドが停止し、GL が呼び出しを終了するのを待つことになりますか?
そうでない場合、GL は glDraw のような重要な関数の呼び出しをどのように処理し、その直後に描画呼び出しに影響する設定を変更しますか?
いいえ、(ほとんど)そうではありません。GL関数の大部分は、使用時にバッファリングされ、後で実際に実行されます。これは、CPUとGPUを2つのプロセッサが同時に動作していると考えることはできないことを意味します。通常、CPUはバッファリングされる一連のGL関数を実行し、GPUに配信されるとすぐに、この関数がそれらを実行します。つまり、実行の前後の時間を比較するだけでは、特定のGL関数の実行にかかる時間を確実に制御することはできません。
これを行う場合は、最初にglFinish()を実行して、以前にバッファリングされたすべてのGL呼び出しが実行されるのを実際に待機する必要があります。次に、カウントを開始し、ベンチマークする呼び出しを実行して、glFinishを再度呼び出します。これらの呼び出しも実行されていることを確認してから、ベンチマークを終了します。
一方、私は「ほとんど」と言いました。これは、読み取り関数が実際にGPUと同期して実際の結果を表示する必要があるためです。したがって、この場合、読み取り関数はメインスレッドを待機してフリーズします。
編集:説明自体が2番目に尋ねた質問に答えると思いますが、念のため:すべての呼び出しがバッファリングされているため、最初に描画を完了し、その後、後続の呼び出しの設定を変更することができます
問題の OpenGL 呼び出しと OpenGL の状態に厳密に依存します。OpenGL 呼び出しを行うと、実装は最初にそれらを内部的にキューに入れ、次に呼び出しプログラムの実行に対して非同期で実行します。OpenGL の重要な概念の 1 つに同期ポイントがあります。これらは、特定の条件が満たされるまで OpenGL 呼び出しをブロックする必要があるワーク キュー内の操作です。
OpenGL オブジェクト (テクスチャ、バッファ オブジェクトなど) は純粋に抽象的であり、仕様により、クライアント プログラム内のオブジェクトのハンドルは常にデータに対して、オブジェクトはこのオブジェクトを参照する OpenGL 関数の呼び出し時に持っています。たとえば、次のシーケンスを考えてみましょう。
glBindTexture(GL_TEXTURE_2D, texID);
glTexImage2D(..., image_1);
draw_textured_quad();
glTexImage2D(..., image_2);
draw_textured_quad();
最初のdraw_textured_quad
ものは、何かが描画されるずっと前に戻ってくる場合があります。ただし、呼び出しを行うことで、OpenGL はテクスチャが現在保持しているデータへの内部参照を作成します。そのため、最初のクワッドが描画される前に glTexImage2D が 2 回呼び出されると、OpenGL は、テクスチャになりtexID
、 の 2 回目の呼び出しで使用されるセカンダリ テクスチャ オブジェクトを内部的に作成する必要がありdraw_textured_quad
ます。が呼び出された場合glTexSubImage2D
、変更されたコピーを作成する必要さえあります。
OpenGL 呼び出しは、呼び出しの結果がクライアント側のメモリを変更し、以前の OpenGL 呼び出しによって生成されたデータに依存する場合にのみブロックされます。つまり、OpenGL 呼び出しを行う場合、OpenGL 実装は依存関係ツリーを内部的に生成して、何が何に依存しているかを追跡します。また、同期ポイントがブロックする必要がある場合、少なくともすべての依存関係が満たされるまでブロックされます。