3

アプリケーションの openGL フレームバッファのコンテンツをすばやくキャプチャする方法が必要です。通常、glReadPixels() は、フレームバッファの内容をバッファに読み込むために使用されます。しかし、これは遅いです。

glReadPixels()を使用して4つの異なる領域からフレームバッファを読み取るために4つのスレッドを作成することにより、フレームバッファのコンテンツを読み取るプロセスを並列化しようとしていました。しかし、アプリケーションはセグメンテーション違反のために終了しています。スレッドから glReadPixels() 呼び出しを削除すると、アプリケーションは正しく実行されます。

4

1 に答える 1

8

スレッドは機能しません。そのアプローチは控えてください。

お気づきのように、複数のスレッドの作成は失敗します。これは、現在の OpenGL コンテキストを持つスレッドが 1 つだけであるためです。原則として、 を呼び出す前に各ワーカー スレッドでコンテキストを最新にすることができますが、これにはサイドで追加の同期が必要になります (そうしないと、コンテキストを最新にしてから読み戻すまでの間にスレッドがglReadPixelsプリエンプトされる可能性があります!)。(wgl|glx)MakeCurrentOpenGL を深刻に失速させる関数。最終的には、より遅いものを得るために、より多くの作業を行うことになります。

glReadPixelsこれ以上高速化する方法はありません1が、かかる時間を切り離すことができます (つまり、リードバックは非同期で実行されます)。そのため、アプリケーションはブロックされず、効果的に「高速」に実行されているように見えます。そのためにPixel バッファ オブジェクト
を使用します。バッファフラグを正しく取得してください。

完全なコンテンツの転送が完了していない場合でも、バッファーをマップしてそのコンテンツにアクセスするとブロックされるため、まだ高速ではないことに注意しくださいこれを考慮するには、前のフレームを読み取るか、クエリが完了したことを確認できるフェンス オブジェクトを使用する必要があります。
または、より単純ですが信頼性は低くなりますが、間に「他の作業」を挿入glReadPixelsしてデータにアクセスすることができます。これは、データにアクセスするまでに転送が完了したことを保証するものではないため、ブロックされる可能性があります。ただし、それ機能する可能性があり、おそらく短い時間ブロックされます (したがって、「より速く」実行されます)。


1速度を遅くする方法はたくさんあります。たとえば、OpenGL に変な変換をさせたり、間違ったバッファ フラグを使用したりする場合などです。ただし、一般に、速度は、転送が開始される前に以前のすべての描画コマンドが終了していることと、PCIe バスを介して転送されるデータに依存するため、高速化する方法はありません (固定時間のオーバーヘッドと有限の帯域幅があります)。 .
リードバックを「高速」にする唯一の実行可能な方法は、このレイテンシを隠すことです。もちろん、まだ速くはありませんが、それを感じることはできません。

于 2013-11-14T10:34:56.733 に答える