将单个2D纹理阵列层从GPU复制到CPU

时间:2015-08-18 11:18:33

标签: qt opengl textures texture2d

我使用2D纹理数组来存储一些数据。由于我经常想要绑定此2D纹理数组的单个图层,因此我为每个图层创建了单独的 GL_TEXTURE_2D 纹理视图:

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);
}

这些2D TextureViews工作正常。但是,如果我想使用该纹理视图从GPU端检索2D纹理数据,它就无法工作。

换句话说,以下复制没有数据(但不会引发GL错误):

glGetTexImage(GL_TEXTURE_2D, 0, m_pixel_format, m_pixel_type, (GLvoid*) m_raw_data[layer] )

但是,检索整个 GL_TEXTURE_2D_ARRAY 确实有效:

glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, m_pixel_format, m_pixel_type, (GLvoid*) data );

如果我只需修改单个图层的数据,那么当我需要复制2D纹理数组的所有图层时,显然会出现性能损失。

有没有办法复制GPU-&gt; CPU只有一层 GL_TEXTURE_2D_ARRAY ?我知道存在相反的情况(即CPU-> GPU),所以如果没有,我会感到惊讶。

2 个答案:

答案 0 :(得分:4)

您似乎找到了使用OpenGL 4.5中的glGetTexSubImage()的解决方案。还有一个适用于OpenGL 3.2或更高版本的简单解决方案。

您可以将纹理图层设置为FBO附件,然后使用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);

答案 1 :(得分:3)

您使用的是什么版本的GL?

你可能不会喜欢这个,但...... GL 4.5引入glGetTextureSubImage (...)来做你想要的。对于这么简单的事情,这是一个非常大的版本要求;它也可以在extension form中使用,但该扩展也是相对较新的。

此功能没有特殊的硬件要求,但它需要一个非常新的驱动程序。

然而,我不会绝望。

您可以将整个纹理数组复制到PBO中,然后使用缓冲区对象API(例如 glGetBufferSubData (...))读回该PBO的子矩形。这需要GPU端额外的内存,但允许您传输这个2D阵列的单个片段。