2016-08-18 15 views
0

私は、OpenGLでビデオストリームを表示するプロジェクトに取り組んでいて、QOpenGLWidgetの内容を外部の画面に表示しています。だから、私がやったのは、OpenGLウィジェットにストリームを表示してから、glReadPixelsに2つのPixel Pack Buffer Objectを使ってバッファを取得し、それを別の画面に送ります。問題は、私がそうでないときと比較してPBOを使用するときのパフォーマンスが低下していることです。ここでQt/OpenGL:PBOを正しく使用していますか?

は、コードの興味深い部分である:外部画面に送信することになるだろうフレームを作成するための

コード:

screenBufferQOpenGLWidgetからフレームを格納するためのメモリバッファでありますコードのこの時点で

、PBOは既にpaintGL機能

からのデータで満たされていPBOの

初期化:ここ

void GLWidget::InitializeGL(){ 

    pbo1 = new QOpenGLBuffer(QOpenGLBuffer::PixelPackBuffer); 
    pbo1->create(); 
    pbo1->bind(); 
    pbo1->allocate(vWidth*vHeight*3); 
    pbo1->release(); 

    pbo2 = new QOpenGLBuffer(QOpenGLBuffer::PixelPackBuffer); 
    pbo2->create(); 
    pbo2->bind(); 
    pbo2->allocate(vWidth*vHeight*3); 
    pbo2->release(); 

} 

IはglReadPixels

void GLWidget::paintGL(){ 


    glClear(GL_COLOR_BUFFER_BIT); 

    program->bind(); 
    { 
     vao.bind(); 

      glBindTexture(GL_TEXTURE_2D, tex); 

       glDrawArrays(GL_QUADS, 0, 4); 

      glBindTexture(GL_TEXTURE_2D, 0); 

     vao.release(); 
    } 
    program->release(); 

    if(!isZoomed){ 

     programMouse->bind(); 
     { 
      vaoMouse.bind(); 

        glLineWidth(2.0); 
        glDrawArrays(GL_LINES, 0, 8); 

      vaoMouse.release(); 
     } 
     programMouse->release(); 

    } 

    if(pboIndex){ 

     pbo2->bind(); 

    }else{ 

     pbo1->bind(); 
    } 

      glReadPixels(0, 0, vWidth, vHeight, GL_RGB, GL_UNSIGNED_BYTE, 0); 

    if(pboIndex){ 

     pbo2->release(); 

    }else{ 

     pbo1->release(); 
    } 



} 

pboIndexとPBOを使用することは、第一及び第二のPBOとの間に交互に値を切り替えるだけブール値です。

私はパフォーマンスが低下しているので、間違っていますか?私は間違った方法でPBOを使用しているか、または私がそれらを使うべき状況を正しく理解していない。

おかげ

答えて

2

あなたはピンポン二つの異なるバッファ間の各フレームをによって実証され、ピクセルバッファオブジェクトの背後にある目的の一般的な理解を(と思う)、持っています。実際の問題は、2つのピクセルバッファがパイプラインを停止させるのに十分ではない可能性が高いことです。

多くのドライバは、3つのフレームのコマンドをキューに入れるように設定されています。フレームn+2の間にフレームnの結果を読み取ろうとすると、パイプラインの最大深さが効果的に短くなります。フレームn+2のコマンド設定は、nの結果が終了してリードバックされるまで続行できません。

ドライバのコマンドキューイングの動作は、OpenGLの範囲をはるかに超えています。ドライバがセットアップするフレームの数を決して知ることはできません。リードバック間の時間を3倍に増やすことは役に立ちますが、理想的には使用するのはfence syncです。

OpenGLのコマンドストリームに同期オブジェクトを挿入することができます。その目的は、特定のポイントまでのすべてのコマンドが完了すると通知することだけです。このオブジェクトのシグナル状態をチェックすることは、パイプラインを何らかの方法で停止させることはなく、前のフレームからのコマンドがGPUで終了したときにすばやく知ることができ、ピクセルバッファのリードバックによってCPU/GPU同期の問題

+1

もちろん、バッファの長さを単純に増やすと、余分な遅延が発生します。Direct3DのようないくつかのAPIは、レンダリングされたフレーム表示にFIFOキューを使用します。これは、キュー内のすべてのバッファに対して1フレームのレイテンシを追加します(各フレームは、次のフレームに移動する前に表示されなければなりません)。絶対にビデオアプリケーション、ドロップフレームのこのデザインを使用しないでください。 –

関連する問題