Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

copying texture from GPU to CPU using pixel buffer objects

I am new to OpenGL and have currently copying the contents of a 2D texture back to CPU memory as follows:

std::vector<unsigned char> frame-data(width * height * 4);
glBindTexture(GL_TEXTURE_2D, tid);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &frame_data[0]);                 

I noticed this is quite sluggish and I started reading about PBOs and thought of trying to see if that makes things a bit smoother. So I create the PBO as follows:

GLuint  pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, width*height* 4, NULL, GL_STREAM_READ); 

I think the above lines need to be just executed once to initialize the PBO.

My question is now how do I actually map the data from texture to this PBO object? I know at one point after that I will need to call glMapBuffer but I am not sure how to attach this texture to my PBO.

like image 279
Luca Avatar asked Nov 25 '16 22:11

Luca


1 Answers

When a buffer is bound to GL_PIXEL_PACK_BUFFER, texture download functions will interpret their last data argument not as a pointer in client memory, but as an offset in bytes from the beginning of the currently bound pixel pack buffer.

In other words, assuming an already created texture and a suitably sized buffer already created:

// bind PBO
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer); 

// bind texture
glBindTexture(GL_TEXTURE_2D, texture);

// transfer texture into PBO
glGetTexImage(GL_TEXTURE_2D,                 
              level,
              pixelformat,
              pixeltype,
              (GLvoid*)0 // offset in bytes into "buffer",
                         // not pointer to client memory!
             ); 

After the transfer is done, you can read your texture data contained in your buffer, for instance by mapping it.

Note that if you map the buffer right away you're not going to get any benefit from the PBO. The whole point of this approach is to let the transfer happen asynchronously while you keep the GPU busy by submitting other commands.

You can know when the transfer is finished by using synchronization calls, such as sync objects inserted after the transfer call.

like image 103
peppe Avatar answered Oct 21 '22 16:10

peppe