web-dev-qa-db-ja.com

OpenGLでのマルチスレッドレンダリング

マルチスレッドアプリケーションを使用していますが、さまざまなスレッドでレンダリングしようとしています。最初に、すべてのスレッド間で同じレンダリングコンテキストを使用しようとしましたが、他のスレッドに対してNULLの現在のコンテキストを取得していました。私はインターネットで、1つのコンテキストが一度に1つのスレッドでのみ最新である可能性があることを読みました。

だから私は何か違うものを作ることにしました。ウィンドウを作成し、そこからHDCを取得して、最初のRCを作成します。その後、このHDCをスレッド間で共有し、作成するすべての新しいスレッドで、同じHDCから新しいRCを取得し、そのスレッドに対して最新の状態にします。実行するたびに、返されるRCは常に異なります(通常は前の値+ 1)。 wglGetCurrentContext()がRCを返すかどうかを確認するアサーションを作成しました。作成されたばかりのRCを返すようです。しかし、レンダリングを行った後、レンダリングが表示されず、GetLastError()を呼び出すと、エラー6(無効なハンドル??)が発生します。

つまり、これは、wglCreateContext()を呼び出すたびに新しい値が得られるにもかかわらず、どういうわけか、これらのすべての異なる値がOpenGL呼び出しへの同じ「接続チャネル」であることを意味しますか?

これは、スレッドの前のレンダリングコンテキストを常に無効にし、新しいコンテキストでアクティブにする必要があることを意味しますか?私は本当にこの同期を常に行う必要がありますか、この問題を回避する他の方法はありますか?

17
filipehd

マルチスレッドアプリケーションを使用していますが、さまざまなスレッドでレンダリングしようとしています。

しないでください!!!

レンダラーをマルチスレッド化しようとするとnothingが得られます。基本的に、1つの大きな競合状態に陥っており、ドライバーはスレッドを同期してビジー状態になり、何らかの形でそれを理解できるようになります。

最高のレンダリングパフォーマンスを得るには、すべてのOpenGL操作を1つのスレッドのみに維持します。すべての並列化はGPUで無料で行われます。

52
datenwolf

OpenGLコンソーシアムの 次のwiki記事 を読むことをお勧めします。

簡単に言うと、OpenGlに関するマルチスレッドの意味に大きく依存します。1つのスレッドがレンダリング部分を実行し、1つ(または複数)が他のジョブ(AI、物理、ゲームロジックなど)を実行している場合、完全に正しい。

複数のスレッドがOpenGLをめちゃくちゃにしたい場合はできませんが、それ以上のことはできますが、実際には利点よりも多くの問題が発生します。

この概念をよりよく理解するには、OpenGLの並列使用に関する次のFAQを読んでみてください。

http://www.equalizergraphics.com/documentation/parallelOpenGLFAQ.html

14

場合によっては、異なるスレッドで複数のレンダリングコンテキストを使用することが理にかなっています。私はそのようなデザインを使用してファイルシステムから画像データをロードし、このデータをテクスチャにプッシュしました。

5
JoR

Mac OS X上のOpenGLはシングルスレッドセーフです。それを有効にする:

#include <OpenGL/OpenGL.h>

CGLError err = 0;
CGLContextObj ctx = CGLGetCurrentContext();

// Enable the multi-threading
err =  CGLEnable( ctx, kCGLCEMPEngine);

if (err != kCGLNoError ) {
     // Multi-threaded execution is possibly not available
     // Insert your code to take appropriate action
}

参照: 同時実行とOpenGL-Apple Developer

そして: テクニカルQ&A QA1612:OpenGL ESマルチスレッドと...

1
geowar