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

Posted

技术标签:

【中文标题】将 2D 纹理阵列的单层从 GPU 复制到 CPU【英文标题】:Copying a single layer of a 2D Texture Array from GPU to CPU 【发布时间】:2015-08-18 11:18:33 【问题描述】:

我正在使用 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->CPU 的单层 GL_TEXTURE_2D_ARRAY?我知道有相反的情况(即 CPU->GPU),所以如果没有,我会感到惊讶。

【问题讨论】:

【参考方案1】:

看起来您找到了使用 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);

【讨论】:

【参考方案2】:

您使用的是哪个版本的 GL?

您可能不会喜欢这个,但是... GL 4.5 引入了glGetTextureSubImage (...) 来精确地做您想做的事。对于如此简单的事情,这是一个相当高的版本要求;它也可以在 extension form 中使用,但该扩展也是相对较新的。

此功能对硬件没有特殊要求,但需要最新的驱动程序。


不过,我还不会绝望。

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

【讨论】:

幸运的是,我正在使用 GL 4.5 和最新的 Nvidia 驱动程序,所以这个消息一点也不坏。它完美地工作!不知道我在浏览 openGL 文档时是如何错过该功能的。非常感谢安东。 啊,太好了。具有高版本要求的 OpenGL 功能让我夜不能寐;)我总是为寻找适用于旧系统的解决方案而烦恼。对于旧版本的 API 中缺少这么简单的东西,这真是令人沮丧。

以上是关于将 2D 纹理阵列的单层从 GPU 复制到 CPU的主要内容,如果未能解决你的问题,请参考以下文章

无法从 GPU 复制到 CPU (OpenGL)

vbscript 将ADO Recordset复制到2D阵列

从 GPU 复制到 CPU 比从 CPU 复制到 GPU 慢

有没有更好更快的方法来使用推力从 CPU 内存复制到 GPU?

glFramebufferTexture2D 性能

GPU上的纹理图像处理?