Reputation: 1472
I'm using a 2D texture array to store some data. As I often want to bind single layers of this 2D texture array, I create individual GL_TEXTURE_2D texture views for each layer:
for(int l(0); l < m_layers; l++)
{
QOpenGLTexture * view_texture = m_texture.createTextureView(QOpenGLTexture::Target::Target2D,
m_texture_format,
0,0,
l,l);
view_texture->setMinMagFilters(QOpenGLTexture::Filter::Linear, QOpenGLTexture::Filter::Linear);
view_texture->setWrapMode(QOpenGLTexture::WrapMode::MirroredRepeat);
assert(view_texture != 0);
m_texture_views.push_back(view_texture);
}
These 2D TextureViews work fine. However, if I want to retrieve the 2D texture data from the GPU side using that texture view it doesn't work.
In other words, the following copies no data (but throws no GL errors):
glGetTexImage(GL_TEXTURE_2D, 0, m_pixel_format, m_pixel_type, (GLvoid*) m_raw_data[layer] )
However, retrieving the entire GL_TEXTURE_2D_ARRAY does work:
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, m_pixel_format, m_pixel_type, (GLvoid*) data );
There would obviously be a performance loss if I need to copy across all layers of the 2D texture array when only data for a single layer has been modified.
Is there a way to copy GPU->CPU only a single layer of a GL_TEXTURE_2D_ARRAY? I know there is for the opposite (i.e CPU->GPU) so I would be surprised if there wasn't.
Upvotes: 0
Views: 1422
Reputation: 54642
Looks like you found a solution with using glGetTexSubImage()
from OpenGL 4.5. There is also a simple solution that works with OpenGL 3.2 or higher.
You can set the texture layer as an FBO attachment, and then use glReadPixels()
:
GLuint fboId = 0;
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
textureId, 0, layer);
glReadPixels(...);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Upvotes: 5
Reputation: 43359
What version of GL are you working with?
You are probably not going to like this, but... GL 4.5 introduces glGetTextureSubImage (...)
to do precisely what you want. That is a pretty hefty version requirement for something so simple; it is also available in extension form, but that extension is relatively new as well.
There is no special hardware requirement for this functionality, but it requires a very recent driver.
I would not despair just yet, however.
You can copy the entire texture array into a PBO and then read a sub-rectangle of that PBO back using the buffer object API (e.g. glGetBufferSubData (...)
). That requires extra memory on the GPU-side, but will allow you to transfer a single slice of this 2D array.
Upvotes: 3