OpenGL 纹理存储

OpenGL Texture Storage

我想了解在 OpenGL 中创建新纹理时会发生什么。我一直以为当

glTexImage2D 

是运行,纹理存储在CPU,直到它被激活

glActiveTexture; 
glBindTexture;

图像已复制到 GPU。但是看了一点之后,我觉得我的理解是错误的。我意识到许多 OpenGL 版本不可能读回纹理像素值,这让我认为数据存储在 GPU 上,这就是为什么无法读回像素的原因。并且 GLreadpixels 很慢,因为它是从 GPU 内存中复制信息。 glTexImage2D 是否在 GPU 上创建内存,而激活纹理和绑定纹理只是为程序设置句柄以使用图像?这是有道理的,因为每次使用图像时来回复制图像数据的成本太高。这是特定于 gl 实现的东西吗?该文档没有提供有关数据存储位置的任何信息,而且我无法在线找到任何答案。

一般来说,当驱动程序将数据存储在 GPU 上时,我认为这取决于驱动程序,大多数 OpenGL 函数倾向于将数据推送到 GPU VBO-s 例如,明确声明生成的对象在 GPU 内存中。在 OpenGL 中,您提供一个指向纹理数据的指针,然后实现对其进行处理,但从不拥有您提供的内存,因此您可以在调用后立即释放它。

glTexImageglTexSubImage 不要直接使用您提供的缓冲区:

void glTexImage2D(  GLenum target,
                    GLint level,
                    GLint internalFormat,
                    GLsizei width,
                    GLsizei height,
                    GLint border,
                    GLenum format,
                    GLenum type,
                    const GLvoid * data);

internalFormat - 是一个有趣的参数,因为它表示内部存储但是永远不能保证它会像这样存储,我过去读过的论文说一些 ATI/AMD GPUS 甚至不支持 non-RGBA 格式,所以如果你为 internalFormat 说 GL_RGB 它无论如何都会将它转换为 RGBA 因为这是它支持的,这已在 Vulkan 中修复,因为您可以查询实际支持的格式并以将存储在 GPU 上的格式上传纹理。 formattypedata 是必需的,因为实施需要知道它将从您那里得到什么。从执行纹理上传所需的时间以及使用它时没有出现后续问题来判断,我认为可以安全地假设纹理更新很可能直接上传到 GPU 内存。

使用 PBO(像素缓冲对象),因为你做了同样的事情,所以没有任何改变,但是你为 data 参数指定 NULL 并绑定一个 PBO,它保证在GPU内存作为上传源。

glGenTextures 调用只是在 CPU 侧创建对象,将其视为一个数组,其中包含您获得的纹理 "objects" 的信息 id-s到。稍后您使用这些 id 通过 glTexImage 初始化纹理,您在其中指定存储和基本参数,使用 glTexSubImage 然后可用于更新整个或图像的一部分。使用 glTexSubImage 更新纹理也比调用 tex glTexImage 更快,这表明实现做了一些不同的事情。

glReadPixels 很慢,因为它将驻留在 GPU 中的帧缓冲区读取到 CPU 内存中 space,因为 GPU 制造商倾向于尽可能多地推动负载尽可能在 GPU 端,例如变换反馈解决了需要从 CPU space 馈送 GPU 的问题,你可以直接洗牌缓冲区而不需要从 CPU [ 触摸它们=68=] 并轻松模拟 1M 粒子,否则会因 CPU 瓶颈而死亡。

如果您的假设确实是在第一次使用纹理时上传信息,那么在您第一次渲染大型场景时,您会遇到惊人的巨大延迟,因为所有纹理都是一个接一个地上传的。您可以通过上传大量纹理来测试这一点,并测量 glTexImage 需要多少时间以及首次显示它们需要多少时间。据了解 glTexImage 调用可能会花费很多时间,具体取决于纹理大小,当然这也取决于设备,但是假设上传纹理需要 15 毫秒很多.