将 2D 纹理阵列的单层从 GPU 复制到 CPU
Copying a single layer of a 2D Texture Array from GPU to CPU
我正在使用 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 TextureView 工作正常。但是,如果我想使用该纹理视图从 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 );
如果只修改了单个图层的数据,而我需要跨所有图层复制二维纹理数组,显然会有性能损失。
有没有办法只复制GL_TEXTURE_2D_ARRAY的单层GPU->CPU?我知道有相反的东西(即 CPU->GPU)所以如果没有我会感到惊讶。
您使用的是哪个版本的 GL?
您可能不会喜欢这个,但是... GL 4.5 引入了 glGetTextureSubImage (...)
来精确地执行您想要的操作。对于如此简单的事情,这是一个相当高的版本要求;它也可以在 extension form 中使用,但该扩展也是相对较新的。
此功能对硬件没有特殊要求,但需要最新的驱动程序。
不过,我还不会绝望。
您可以将整个纹理数组复制到 PBO 中,然后使用缓冲区对象 API(例如 glGetBufferSubData (...)
).这需要 GPU 端的额外内存,但可以让您传输此二维数组的单个切片。
看起来您找到了使用 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);
我正在使用 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 TextureView 工作正常。但是,如果我想使用该纹理视图从 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 );
如果只修改了单个图层的数据,而我需要跨所有图层复制二维纹理数组,显然会有性能损失。
有没有办法只复制GL_TEXTURE_2D_ARRAY的单层GPU->CPU?我知道有相反的东西(即 CPU->GPU)所以如果没有我会感到惊讶。
您使用的是哪个版本的 GL?
您可能不会喜欢这个,但是... GL 4.5 引入了 glGetTextureSubImage (...)
来精确地执行您想要的操作。对于如此简单的事情,这是一个相当高的版本要求;它也可以在 extension form 中使用,但该扩展也是相对较新的。
此功能对硬件没有特殊要求,但需要最新的驱动程序。
不过,我还不会绝望。
您可以将整个纹理数组复制到 PBO 中,然后使用缓冲区对象 API(例如 glGetBufferSubData (...)
).这需要 GPU 端的额外内存,但可以让您传输此二维数组的单个切片。
看起来您找到了使用 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);