Hi everyone, have a question regarding pixel buffer objects.
I am running a P4 1.5 with a GeForce 5200 FX (AGP of course), and the 80+ Forceware drivers.
I am trying to use PBO to increase the speed of glReadPixels. I’ve implemented a class for doing just that, and alternatively, doing a normal glReadPixels (for comparison). I am reading both the color and depth components. My normal glReadPixels looks like:
void readPixelsNormal()
{
// init mem
unsigned int * m_pBufferColor = new unsigned int[GetWidth() * GetHeight()];
unsigned int * m_pBufferDepth = new unsigned int[GetWidth() * GetHeight()];
glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
m_pBufferColor);
//... do stuff to the pixels ...
glReadPixels(0, 0, GetWidth(), GetHeight(), GL_DEPTH_COMPONENT,
GL_UNSIGNED_INT, m_pBufferDepth);
//... do stuff to the pixels ...
}
Getting about 30 FPS using the above approach. Now next is my PBO implementation:
// macro for pointing glReadPixels to ... well ... nowhere
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
// PBO generated IDs
GLuint m_pPBO[2] = {0, 0};
unsigned int * m_pBuffer;
void initPBO()
{
// init the PBOs
glGenBuffersARB(2, m_pPBO);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[0]);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
(GetWidth() * GetHeight() * sizeof(unsigned int)),
NULL,
GL_STREAM_READ);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[1]);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
(GetWidth() * GetHeight() * sizeof(unsigned int)),
NULL,
GL_STREAM_READ);
// bind it to nothing so other stuff doesn't
// think it should use the PBOs
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
}
void readPixelsPBO()
{
// bind buffer #1
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[0]);
// read pixels
glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA,
GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
// bind buffer #2
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[1]);
// read pixels
glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA,
GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
// map memory from card
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[0]);
m_pBuffer = static_cast<unsigned int *>(glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB));
//... do stuff to pixels ...
// map memory from card
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[1]);
m_pBuffer = static_cast<unsigned int *>(glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB));
//... do stuff to pixels ...
// unmap the memory
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[0]);
if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT))
{
// handle the error
}
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, m_pPBO[1]);
// unmap the memory
if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT))
{
// handle the error
}
// bind it to nothing so other stuff doesn't
// think it should use the PBOs
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
}
void killPBO()
{
// kill the PBOs
glDeleteBuffersARB(2, m_pPBO);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
}
It’s weird. This second approach yields ~27 FPS. If I’m bypassing the normal readback pipeline, and directly accessing card memory, shouldn’t I be getting some kick-butt framerate? In addition, since I’m using STREAM data, shouldn’t the glReadPixels be returning immediately and behave asynchronously? Am I doing something wrong? What do you gurus think?