继续学习现代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应该更好,但这似乎不是问题的根源。
任何启蒙都非常感激:)