Opengl es OpenGL纹理存储

Opengl es OpenGL纹理存储,opengl-es,opengl-es-2.0,Opengl Es,Opengl Es 2.0,我试图了解在OpenGL中创建新纹理时会发生什么。我一直认为当 glTexImage2D 在运行时,纹理存储在CPU中,直到被激活 glActiveTexture; glBindTexture; 将图像复制到GPU。然而,读了一点之后,我觉得我的理解是错误的。我意识到许多OpenGL版本不可能读回纹理像素值,这让我认为数据存储在GPU上,这就是为什么没有读回像素的能力。GLreadpixels速度较慢,因为它正在从GPU内存复制信息。glTexImage2D是否在GPU上创建内存,而ac

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

glTexImage2D 
在运行时,纹理存储在CPU中,直到被激活

glActiveTexture; 
glBindTexture;

将图像复制到GPU。然而,读了一点之后,我觉得我的理解是错误的。我意识到许多OpenGL版本不可能读回纹理像素值,这让我认为数据存储在GPU上,这就是为什么没有读回像素的能力。GLreadpixels速度较慢,因为它正在从GPU内存复制信息。
glTexImage2D
是否在GPU上创建内存,而activate texture和bind texture只是设置程序使用图像的句柄?这是有意义的,因为每次使用图像时来回复制图像数据的成本太高。这是德国劳埃德船级社实施特有的吗?文档没有提供任何关于数据存储位置的信息,我也无法在网上找到任何答案

一般来说,我假设在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 GPU甚至不支持非RGBA格式,所以如果你说GL_RGB forinternalFormat,它无论如何都会将其转换为RGBA,因为它支持非RGBA格式,这在Vulkan中得到了修复,因为您可以查询实际支持的格式,并以存储在GPU上的格式上载纹理格式类型数据是必需的,因为实现需要知道它将从您那里得到什么。从执行纹理上传所需的时间以及使用它时不会出现打嗝的情况来看,我认为可以安全地假设纹理更新最有可能直接上传到GPU内存

使用PBO(像素缓冲区对象),由于您执行了相同的操作,所以不会更改任何内容,但是您为数据参数指定NULL,并绑定一个PBO,该PBO保证位于GPU内存中,用作上载源

glGenTextures调用仅在CPU端创建对象,可以将其视为一个数组,该数组保存获取id-s的纹理“对象”的信息。稍后,使用这些ID通过glTexImage初始化纹理,其中使用glTexSubImage指定存储和基本参数,然后可用于更新整个或部分图像。使用glTexSubImage更新纹理也比调用texglTexImage更快,这表明该实现做了一些不同的事情

glReadPixels速度较慢,因为它将驻留在GPU中的帧缓冲区读取到CPU内存空间,因为GPU制造商倾向于在GPU端尽可能多地推送负载,例如,变换反馈解决了需要从CPU空间向GPU馈电的问题,您只需洗牌缓冲区,无需从CPU空间触摸缓冲区,即可轻松模拟1M粒子,否则这些粒子将因CPU瓶颈而消亡


如果您的假设是真的,即在首次使用纹理时上载信息,那么在第一次渲染大规模场景时,您将获得惊人的巨大延迟,因为所有纹理都是一个接一个地上载的。这可以通过上传大量纹理进行测试,并测量glTexImage需要多少时间以及首次显示它们需要多少时间。就我们所知,glTexImage调用可能需要很多时间,这取决于纹理大小,当然这也取决于设备,但假设15毫秒上传纹理就太多了。

非常感谢您的澄清!我想如果你用这种方式创建了太多的图像,gpu内存会被填满并抛出一个错误?是否有任何方式会与其他gpu内存(如制服)冲突?。。。为了完整起见,
glTexStorage2D
定义了纹理的大小并分配了空间,但没有将任何数据传输到内存中。这个答案很好,解释了这么多。非常感谢。
glReadPixels
速度较慢,因为如果同步使用,它会耗尽管道;请记住,大多数GPU渲染的是CPU正在处理的内容后面的一帧(ish),任何同步回读都必须等待GPU赶上CPU的世界视图。