GLFW FAQの項目2.9には、次のように記載されています。
[...]すべてのOpenGLおよびGLFW呼び出し (スレッド管理および同期呼び出しを除く)をメインスレッドから行うことを強くお勧めします。これは、単一のウィンドウのみがサポートされているため、大きな問題にはなりません。この方法は、GLFWの将来の方向性とも互換性があります。
強調は私のものです。
では、メインスレッドと他のスレッドの違いは何ですか?
GLFW FAQの項目2.9には、次のように記載されています。
[...]すべてのOpenGLおよびGLFW呼び出し (スレッド管理および同期呼び出しを除く)をメインスレッドから行うことを強くお勧めします。これは、単一のウィンドウのみがサポートされているため、大きな問題にはなりません。この方法は、GLFWの将来の方向性とも互換性があります。
強調は私のものです。
では、メインスレッドと他のスレッドの違いは何ですか?
質問は古いGLFWAPIとFAQに言及しています。更新されたGLFWFAQとGLFWスレッドセーフドキュメントを参照してください。
いくつかの制約が残っており、多くのGLFW呼び出しはメインスレッドから行う必要があります。メインスレッドと他のスレッドの違いは、GLFWが処理するウィンドウ作成、イベントなどのプラットフォーム固有の動作によって異なります。詳細については、公式GLFWフォーラムのこの投稿を参照してください。
OpenGLウィンドウが作成されると、コンテキストを別のスレッドで最新のものにし、そのスレッドからOpenGL呼び出しを行うことができます。
ステートメント
「…スレッドセーフですか?いいえ。ただし、OpenGLもそうではありません。」
間違っている。もちろん、OpenGLはスレッドセーフです。
取引は次のとおりです。スレッドごとに、OpenGLコンテキストを1つまたはまったくバインドできません(現在の状態にします)。OpenGL呼び出しは、呼び出し元のスレッドでアクティブなコンテキストで動作します。スレッド間でOpenGLコンテキストを転送することは完全に可能です。このため、最初に転送されるコンテキストはバインドされていない必要があり、次に別のスレッドで再バインドできます。
各OpenGLコンテキストは、独自の状態変数とオブジェクトのセット(テクスチャ、バッファ)を管理します。ただし、コンテキストは「絡み合う」、つまりオブジェクト空間を共有することができます。ただし、状態はまだ個別です。
単一のドローアブル(ウィンドウ、PBuffer)は、バインドされている異なるスレッドからの複数のコンテキストを持つことができます。異なるスレッドからのコンテキストが同じドローアブルにドローする場合、競合状態が発生し、結果は未定義です。ただし、深さテストされた描画の場合、結果は合理的である必要があります。ただし、単一の描画可能オブジェクトへの同時描画はパフォーマンスを大幅に低下させるため、回避する方が適切です。
複数のスレッドでの複数のOpenGLコンテキストの主な用途は、オブジェクトを共有して、1つのスレッドが他のコンテキストのデータをロードおよび更新できるようにすることです。ヘルパーコンテキストを画面外または非表示のドローアブルにバインドして、競合状態が発生しないようにすることは理にかなっています。
スレッド間に技術的な違いはありません。プログラミングの観点からは、各スレッドのセマンティクスはわずかに異なります。これは、システムアーキテクチャではなく、実行中のプログラムによって課せられます。ほとんどのOpenGLアプリケーションの場合、従来のセマンティクスでは、メインスレッドがウィンドウを作成し、ユーザーに表示されるすべての要素(OpenGL操作を含む)を描画し、ユーザー入力を収集します。メインスレッドから起動されるスレッドは、ユーザーが直接操作することのないワーカースレッドです。ただし、このタスクの分散は純粋に選択によるものであり、うまく機能することが判明したためです。ただし、別のスキームを使用することは完全に可能であり、場合によっては推奨されます。そして、すでに述べたように、プログラム内のスレッドについて技術的な違いはありません。すべてのスレッドは、プロセス内の平等な権利の市民です。
ドキュメントは、少し誤解を招くような表現になっている可能性があります。より良い言い回しは次のようになります。
すべてのOpenGLおよびGLFW呼び出し(スレッド管理および同期呼び出しを除く)を単一のスレッドから作成することを強くお勧めします。できれば、およびを呼び出したスレッドと同じスレッドを
glfwInit
作成glfwOpenWindow
します。これは、単一のウィンドウのみがサポートされているため、大きな問題にはなりません。この方法は、GLFWの将来の方向性とも互換性があります。
その理由は、OpenGLには、そのコンテキストの「現在のスレッド」の概念があるためです。これは、特定の時間にそのコンテキストを正当に変更または使用できる1つのスレッドです。コンテキストは、最初はそれを作成したスレッドに属します。wglMakeCurrent
またはを呼び出すことで、他のスレッドで「現在」にすることができますglxMakeCurrent
。これは、GLFWとは異なり、移植性がありません(ただし、GLFWにはそのラッパーがある可能性がありますが、よくわかりません)。
もちろん、複数の独立したコンテキストを持つことは非常に可能であり、使用する前に各スレッドで同じコンテキストを最新にすることにより、複数のスレッドから同じコンテキストにアクセスすることができます。そして最後に、状態を共有するいくつかのスレッドにいくつかのコンテキストを持つことができます。
ただし、これらのオプションはいずれも、無視できない同期オーバーヘッドを伴うか、OpenGLの一般的な使用法に適していないため、通常のケースではありません。「1つのスレッド、1つのコンテキスト」以外のものは、通常、ごくわずかな例外を除いて、利点を提供しませんが、不必要な複雑さを伴います。
したがって、通常のケースでは、1つのスレッドで使用されるコンテキストが1つだけであり、オプションで、データをマップされたバッファーにシャッフルするのに役立つワーカースリーアドがいくつかあります。
「メインスレッド」と「任意のスレッド」については、違いはありません。メインスレッドは、ほとんどの場合、 GLFW(したがってOpenGL)を初期化するスレッドです。