OpenGL には、論理的であろうとなかろうと、「フレーム」という概念がありません。
OpenGL は非常に単純です。すべてのコマンドは、前のすべてのコマンドが事前に完了しているかのように実行されます。
「あたかも」というキーワードに注意してください。バッファ オブジェクトからレンダリングし、その後すぐにそのデータを変更するとします。このような:
glBindVertexArray(someVaoThatUsesBufferX);
glDrawArrays(...);
glBindBuffer(GL_ARRAY_BUFFER, BufferX);
glBufferSubData(GL_ARRAY_BUFFER, ...);
これは、OpenGL では 100% 合法です。これがどのように機能するかについて、警告、質問、懸念などはありません。そのglBufferSubData
呼び出しは、glDrawArrays
コマンドが終了したかのように実行されます。
考慮しなければならない唯一のことは、仕様で指定されていない唯一のことです:パフォーマンス.
実装は、使用中の可能性のあるバッファーを変更していることを検出する権利を十分に持っているため、glBufferSubData
そのバッファーからのレンダリングが完了するまで CPU をストールさせます。OpenGL の実装では、これを行うか、実際のソース バッファが使用中に変更されないようにするその他のことを行う必要があります。
そのため、OpenGL の実装は、仕様に従って、可能な場合は非同期でコマンドを実行します。外の世界がglDrawArrays
何も描画を終えていないことを認識できない限り、実装はそれが望むことを何でも行うことができます。glReadPixels
描画コマンドの直後に発行すると、パイプラインは停止する必要があります。実行できますが、パフォーマンスを保証するものではありません。
これが、OpenGL が閉じたボックスとして定義されている理由です。これにより、実装は可能な限り非同期にする自由度が高くなります。OpenGL データへのすべてのアクセスには、OpenGL 関数呼び出しが必要です。これにより、実装は、そのデータがまだ実際に利用可能かどうかを確認できます。そうでない場合は、失速します。
バッファ オブジェクトの無効化が可能な理由の 1 つは、ストールを取り除くことです。バッファのデータストレージを孤立させたいことをOpenGLに効果的に伝えます。これが、バッファ オブジェクトをピクセル転送に使用できる理由です。これにより、転送を非同期で行うことができます。これがフェンス同期オブジェクトが存在する理由であり、リソースがまだ使用されているかどうかを知ることができます (おそらくGL_UNSYNCHRONIZED_BIT
バッファー マッピング用)。などなど。
ただし、これはブロックを呼び出して v-sync をサポートするため、返されるまで新しいコマンドを発行できません。
誰が言ったのですか?バッファ スワッピング コマンドが停止する場合があります。そうではないかもしれません。これは実装定義であり、特定のコマンドで変更できます。のドキュメントにeglSwapBuffers
は、フラッシュを実行するとのみ記載されています。これにより、CPU が停止する可能性がありますが、そうする必要はありません。