-1

最初にアプリケーションについて簡単に説明します。一度に最大48台のカメラを表示できる映像セキュリティソフトです。各ビデオ ストリームは独自の Windows HDC を取得しますが、すべて共有 OpenGL コンテキストを使用します。OpenGL でかなり良いパフォーマンスが得られ、Windows/Linux/Mac で動作します。内部では、コンテキストは wxWidgets 2.8 wxGLCanvas を使用して作成されますが、それが問題とは何の関係もないと思います。

では、本題です。同じカメラを 48 個のウィンドウすべてに表示するとします。これは基本的に、30fps のみをデコードしていることを意味します (別のスレッドで実行されます) が、画像からデコードを取り除くために最大 1440fps を表示します。私は PBO を使用して画像を転送しています。ピクセル シェーダーとマルチテクスチャリングがサポートされているかどうかに応じて、GPU で YUV->RGB 変換を行うためにそれらを使用する場合があります。次に、クワッドを使用してテクスチャを配置し、SwapBuffers を呼び出します。すべての OpenGL 呼び出しは、UI スレッドから発生します。また、CPU で YUV->RGB 変換を試み、GL_RGBA および GL_BGRA テクスチャの使用を台無しにしましたが、すべての形式でほぼ同じパフォーマンスが得られます。問題は、可能な 1440 fps のうち約 1000 fps しか得られないことです (fps で測定すべきではないことはわかっていますが、ただし、このシナリオでは簡単です)。上記のシナリオでは、320x240 (YUV420) ビデオを使用していますが、これはおよそ 110MB/秒です。1280x720 カメラを使用すると、フレームレートはほぼ同じで、ほぼ 1.3GB/秒になります。これは、テクスチャのアップロード速度ではないことを示しています。CPU で YUV->RGB 変換とスケーリングを行い、Windows DC を使用してペイントすると、完全な 1440fps を簡単に取得できます。

言及すべきもう 1 つのことは、wglSwapIntervalEXT を使用して、ビデオ カードと OpenGL の両方で vsync を無効にしたことです。また、報告されている OpenGL エラーはありません。ただし、非常に眠いアプリケーションをプロファイルするために使用すると、ほとんどの時間が SwapBuffers で費やされているようです。この問題は、複数の HDC の使用または SwapBuffers のどこかでの使用に何らかの形で関連していると想定していますが、自分が行っていることを他にどのように行うかはわかりません。

私は OpenGL の専門家ではないので、何か提案や何かあれば、ぜひ聞きたいです。私がやっていることが間違っているように聞こえる場合、または同じことをより効率的に達成できる方法がある場合は、それを聞いてみたいです.

行われているすべての OpenGL 呼び出しをよりよく理解するための glIntercept ログへのリンクを次に示します。

単純な RGB: https://docs.google.com/open?id=0BzGMib6CGH4TdUdlcTBYMHNTRnM

シェーダー YUV: https://docs.google.com/open?id=0BzGMib6CGH4TSDJTZGxDanBwS2M

プロファイリング情報: プロファイリング後、いくつかの冗長な状態変化が報告されましたが、これには驚きませんでした。私はそれらをすべて排除しましたが、私が期待していた顕著なパフォーマンスの違いは見られませんでした. レンダリング ループごとに 34 の状態変更があり、非推奨の関数をいくつか使用しています。これらを解決する頂点配列の使用を検討します。ただし、レンダリング ループごとに 1 つのクワッドを実行しているだけなので、これによるパフォーマンスへの影響はあまり期待できません。また、OpenGL 1.4 のみであると思われるかなり古い Intel チップセット ドライバーをサポートする必要があるため、すべてを取り除いてすべての VBO に移行したくはありません。

私が本当に興味を持ち、それまで思いもよらなかったことは、各コンテキストが独自のフロント バッファーとバック バッファーを持っていることです。コンテキストを 1 つしか使用していないため、前の HDC レンダー呼び出しは、スワップが発生する前にバック バッファーへの書き込みを終了する必要があります。その後、次のコンテキストがバック バッファーへの書き込みを再開できます。複数のコンテキストを使用する方が本当に効率的でしょうか? または、代わりにテクスチャ (私が思うに FBO) へのレンダリングを検討し、1 つのコンテキストを使用し続ける必要がありますか?

編集: 元の説明では、複数の OpenGL コンテキストの使用について言及されていましたが、間違っていました。1 つの OpenGL コンテキストと複数の HDC しか使用していません。EDIT2: gDEBugger でプロファイリングした後にいくつかの情報を追加しました。

4

1 に答える 1

0

アプリケーションを高速化するために私が試みていること。OpenGL レンダー スレッドを 1 つ (ビデオ カードが 2 つ以上ある場合はそれ以上) 作成しました。ビデオ カードは一度に複数のコンテキストを処理できません。複数の OpenGL コンテキストがコンテキストの 1 つを待機しています。このスレッドは、YUV->RGB 変換 (テクスチャへのレンダリングに FBO を使用) などの OpenGL のみを機能させます。Camere のスレッドはこのスレッドに画像を送信し、UI スレッドはそれを取得してウィンドウに表示できます。OpenGL コンテキストで処理するクエリがあり、複数のフレームを 1 つのテクスチャに結合して、1 つのパスで変換できます。最大 48 台のカメラを使用できるため、便利な場合があります。OpenGL スレッドが現在ビジーである場合の別のバリアントとして、CPU で一部のフレームを変換できます。

ログから、同じメソッドを頻繁に呼び出すことがわかります。

glEnable(GL_TEXTURE_2D)
glMatrixMode(GL_TEXTURE)
glLoadIdentity()
glColor4f(1.000000,1.000000,1.000000,1.000000)

コンテキストごとに 1 回呼び出すことができ、レンダリングごとに呼び出す必要はありません。

YUVの各プレーンに3つのテクスチャを使用するのが正しいと理解した場合

glTexSubImage2D(GL_TEXTURE_2D,0,0,0,352,240,GL_LUMINANCE,GL_UNSIGNED_BYTE,00000000)
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,176,120,GL_LUMINANCE,GL_UNSIGNED_BYTE,000000)
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,176,120,GL_LUMINANCE,GL_UNSIGNED_BYTE,00000000)

1 つのテクスチャを使用し、シェーダーで計算を使用して、ピクセルの正しい YUV 値を取得するようにしてください。可能です、私は自分のアプリケーションでそれを作りました。

于 2015-09-10T11:25:09.417 に答える