持久性映射缓冲区(glBufferStorage with GL_MAP_PERSISTENT_BIT)性能

时间:2016-01-03 11:10:48

标签: c++ opengl

继续学习现代GL我最近遇到了持久性地图缓冲区。然而,第一批结果令人失望。与glBufferData相比,而不是一些改进或甚至可比较的结果,性能几乎不是它的1/3。 现在我想知道它是否是错误的实施或者我可能错过的任何东西。有趣的是,它也减慢了仍然大量使用glBufferData的所有其他渲染任务,并且似乎glFenceSync导致整个延迟。

以下是我的工作:

GLbitfield PersistentBufferFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
if (bDrawTileBuffers)
{
    glBufferStorage(GL_ARRAY_BUFFER, VBO_SIZE, 0, PersistentBufferFlags);
    DrawTilePMB = (float*)glMapBufferRange(GL_ARRAY_BUFFER,0,VBO_SIZE, PersistentBufferFlags);
    bDrawTileBuffers=true;
}

调用一次来创建缓冲区。

void CleanBuffer(GLsync &SyncBuffer)
{
    glDeleteSync( SyncBuffer ); 
}

void LockBuffer(GLsync &SyncBuffer)
{
    SyncBuffer = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
}

void WaitBuffer(GLsync &SyncBuffer)
{
    if( SyncBuffer )
    {
        GLbitfield WaitFlags=0;
        while( 1 )  
        {
            GLenum WaitReturn = glClientWaitSync( SyncBuffer, WaitFlags, 1 );
            if (WaitReturn == GL_ALREADY_SIGNALED || WaitReturn == GL_CONDITION_SATISFIED)
                return; 
            WaitFlags=GL_SYNC_FLUSH_COMMANDS_BIT; //Failsafe, triple buffering should avoid this ever being set (expensive).
        }
    }
}

用于缓冲处理。

GLuint IndexOffset = DrawTileBufferRange[DrawTileIndex].Begin;
if (DrawTileBufferRange[DrawTileIndex].Sync)
{
    WaitBuffer(DrawTileBufferRange[DrawTileIndex].Sync);
    CleanBuffer(DrawTileBufferRange[DrawTileIndex].Sync);
}
DrawTilePMB[IndexOffset+0] = RFX2*Z*(X - Frame->FX2);
DrawTilePMB[IndexOffset+1] = RFY2*Z*(Y - Frame->FY2);
DrawTilePMB[IndexOffset+2] = Z;
DrawTilePMB[IndexOffset+3] = (U)*TexInfo[0].UMult;
DrawTilePMB[IndexOffset+4] = (V)*TexInfo[0].VMult;

要输入数据,

glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB, 3, GL_FLOAT, GL_FALSE, Stride, (void*)(DrawTileIndex*(TotalSize*sizeof(float))));
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, Stride, (void*)(DrawTileIndex*(TotalSize*sizeof(float))+VertOffset));

glDrawArrays(GL_TRIANGLE_FAN, 0, vertsize / FloatsPerVertex);

LockBuffer(DrawTileBufferRange[DrawTileIndex].Sync);
DrawTileBufferRange[DrawTileIndex].Begin = DrawTileIndex * TotalSize;
DrawTileIndex = (DrawTileIndex + 1) % 3;

最终画出来。 由于我使用的是三重缓冲,所以不要等待。当然,现在我有了缓冲区,我可以(也可能会)通过缓冲多个数据集来减少绘制调用的数量,以进一步优化它,但我希望至少可以获得与glBufferData相同的性能,确实甚至更多,因为它应该从我读到的内容中读取驱动程序开销 - 或者我是否必须“收集数据”以减少绘制调用以真正从中受益?另一方面,这似乎使用它和整个函数的所有这些努力对我来说都是无用的。 我还读到GL_MAP_COHERENT_BIT可能有负面影响并且手动刷新glFlushMappedBufferRange应该更好,但这似乎不是问题的根源。

任何启蒙都非常感激:)

0 个答案:

没有答案