1. 程式人生 > >從GPU讀取資料到系統記憶體的三種方式

從GPU讀取資料到系統記憶體的三種方式

方法一:glReadPixels

首先建立一個fbo,繫結fbo後,attach上需要操作的texture,再進行讀取。

if(fbo == 0)

{

glGenFramebuffers(1, &fbo);

}

glBindFramebuffer(GL_FRAMEBUFFER, fbo);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);

glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dataPointer);

方法二: glGetTexImg

也是比較簡單,bind需要讀取的texture後,就可以直接呼叫glGetTexImg進行讀取

glBindTexture(GL_TEXTURE_2D, textureID);

glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, dataPointer);

glBindTexture(GL_TEXTURE_2D, 0);

方法三:使用pbo

使用pbo是最複雜的,但是比前兩種要快。只使用一個pbo的話,也就是同步,比glReadpixel快那麼一點點,但是如果使用多個pbo進行非同步讀取,呵呵,那就快了幾百倍了。

首先初始化的時候,可生成兩個pbo

GLuint pbo[2];

//creates PBOs to hold the data, this allocates memory for them too

glGenBuffers(2, pbo);

glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[0]);

glBufferData(GL_PIXEL_PACK_BUFFER, height* width, 0, GL_STREAM_READ);

glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[1]);

glBufferData(GL_PIXEL_PACK_BUFFER, height* width, 0, GL_STREAM_READ);

//unbind buffers for now

glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

然後建立fbo

if(fbo == 0)

{

glGenFramebuffers(1, &fbo);

}

glBindFramebuffer(GL_FRAMEBUFFER, fbo);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);

接下來就是fbo的非同步處理了

writeIndex = (writeIndex + 1) % 2;

readIndex = (readIndex + 1) % 2;

//bind FBO to read pixels. This buffer is being compied from GPU to CPU memory

glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[writeIndex]);

//copy from framebuffer to FBO asynchronously. it will be ready in the Next Frame

glReadPixels(0,0 ,width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

//now read other FBO which should be already in CPU memory

glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[readIndex]);

//map buffer so we can access it

cpixel = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);

if (cpixel)

{

// ok we have the data now avaliable and could process it or copy it somewhere

// ...

// unmap the buffer again

memcpy(dataPointer,cpixel,height * width);

//cpixel = nullptr;

glUnmapBuffer(GL_PIXEL_PACK_BUFFER);

}

//back to conventional pixel operation

glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

三種方法介紹完了,其實還有很多其他的寫法。第一次分享,嘻嘻~

轉載請註明出處,謝謝!