私は別のスレッドでFFMPEGを使用してビデオファイルをデコードし、別のスレッドでPBOを使用してこのテクスチャをレンダリングするアプリケーションを持っています。すべてのPBO行う-キスマークは次の関数で起こる:デコードスレッドで複数のピクセルバッファオブジェクトを使用してビデオテクスチャを更新するときのスタッター
void DynamicTexture::update()
{
if(!_isDirty)
{
return;
}
/// \todo Check to make sure that PBOs are supported
if(_usePbo)
{
// In multi PBO mode, we keep swapping between the PBOs
// We use one PBO to actually set the texture data that we will upload
// and the other we use to update/modify. Once modification is complete,
// we simply swap buffers
// Unmap the PBO that was updated last so that it can be released for rendering
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboIds[_currentPboIndex]);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
Util::GLErrorAssert();
// bind the texture
glBindTexture(GL_TEXTURE_2D, _textureId);
Util::GLErrorAssert();
// copy pixels from PBO to texture object
// Use offset instead of pointer.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _width, _height,
(_channelCount==4)?GL_RGBA:GL_RGB,
GL_UNSIGNED_BYTE, 0);
Util::GLErrorAssert();
// Now swap the pbo index
_currentPboIndex = (++_currentPboIndex) % _numPbos;
// bind PBO to update pixel values
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboIds[_currentPboIndex]);
Util::GLErrorAssert();
// map the next buffer object into client's memory
// Note that glMapBuffer() causes sync issue.
// If GPU is working with this buffer, glMapBuffer() will wait(stall)
// for GPU to finish its job
GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
Util::GLErrorAssert();
if(ptr)
{
// update data directly on the mapped buffer
_currentBuffer = ptr;
Util::GLErrorAssert();
}
else
{
printf("Unable to map PBO!");
assert(false);
}
// It is good idea to release PBOs with ID 0 after use.
// Once bound with 0, all pixel operations behave normal ways.
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
Util::GLErrorAssert();
// If a callback was registered, call it
if(_renderCallback)
{
(*_renderCallback)(this);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, _textureId);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
_width, _height, (_channelCount==4)?GL_RGBA:GL_RGB,
GL_UNSIGNED_BYTE,
&(_buffer[0])
);
Util::GLErrorAssert();
}
// Reset the dirty flag after updating
_isDirty = false;
}
、私は単に_currentBufferを更新し、trueに_isDirtyフラグを設定します。この関数は、レンダリングスレッドで呼び出されます。
単一のPBOを使用する場合、つまり上記のコードで_numPbos = 1の場合、レンダリングはスタッターなしで正常に動作します。しかし、複数のPBOを使用すると、ビデオに目障りな吃音があります。 _numPbos = 2 hereで5つのビデオをレンダリングしている私のサンプルを見つけることができます。私が使用するPBOの数が多いほど、スタッターが悪くなります。
理論的には、私が更新しているバッファと、私がレンダリングに使用しているバッファよりもバッファが異なっているので、この種のグリッチはないはずです。レンダリングのパフォーマンスを向上させるために、ダブル/トリプルバッファリングを使用したいと思います。
私は何が間違っている可能性があるかについてのいくつかのポインタ/ヒントを探しています。
はありません、それは「wasn問題はありません。 glUnmapBufferを呼び出すことは、バッファオブジェクトがもはや有効ではないことを意味するものではありません。これは単に、ドライバがGPUメモリ内のバッファを移動させるだけです。無効にされるクライアント空間内でのそのマッピングだけです。 – balajeerc