为什么OpenGL给对象句柄而不是指针



OpenGL传统是让用户使用unsigned int句柄操作OpenGL对象。为什么不直接给个指针呢?惟一id相对于指针有什么优势?

TL;DR: OpenGL id不客观地映射到内存位置。一个OpenGL ID可以同时引用多个内存位置。此外,OpenGL也被设计用于分布式渲染架构(如X11),并且在不同机器上运行的程序可能会使用相同的OpenGL上下文。

OpenGL被设计成一个与体系结构和显示系统无关的API。当OpenGL首次开发时,这种情况发生在客户端-服务器显示架构(如X11)的基础上。如果你看一下OpenGL规范,即使是现代的OpenGL-4,它也指的是客户端和服务器。

然而,在客户机/服务器体系结构中,指针没有意义。首先,服务器的地址空间是客户端无法访问的,除非经过一些步骤。即使您设置了共享内存映射,对象的地址对于客户机和服务器来说也是不一样的。此外,在像X11这样的架构上,单个间接的OpenGL上下文可以被多个客户端使用,甚至可以在不同的机器上运行。指针根本就不适合。

最后但并非最不重要的是,OpenGL对象模型是高度抽象的,OpenGL绘图模型是异步的,假设我做以下事情:

id = glGenTextures(1)
glBindTexture(id)
glTexStorage(…)
glTexSubImage(image_a)
draw_something()
glTexSubImage(image_b)
draw_someting_b()

当到达这个小代码片段的末尾时,实际上可能根本没有绘制,因为没有到达同步点(glFinish, glReadPixels,缓冲区交换)。注意对glTexSubImage的两次调用,它们发生在同一个id上。当像素最终被放入framebuffer时,会有两个不同的图像来自一个纹理ID,因为OpenGL向你保证,事情会看起来好像是同步绘制的。因此,在绘制批处理结束时,单个对象ID可能指的是在内存中具有不同位置的不同数据集的整个集合。

我的第一个考虑-拥有指针会让程序员怀疑他们是否可以用指针算术的方式操作它们,例如通过指向纹理的中间来更新它或类似的东西。也许还有更疯狂的事情,比如即时修补着色器代码。这一切听起来像是一个全新的酷自由度,除非你考虑到篡改高效和优化的GPU"黑盒"操作方式所造成的额外复杂性。

例如-考虑GPU内存分配的内部工作。就像操作系统一样,从操作系统获得的指针不是真正的"物理"指针,操作系统内存管理器可以在保持指针不变的情况下在幕后移动东西(例如切换到HDD)。在这种情况下,id是一样的——GPU可以更自由地优化和打包实体,同时保持它们在1-2-3可用的良好外观。

另一个例子- OpenGL实际上在制造商之间并不相同。事实上,OpenGL只是对API的描述,每个供应商都可以以最适合自己的方式实现它。例如,没有关于如何存储纹理贴图、对齐或交错等的规则。拥有指向纹理的指针会诱使开发人员篡改mipmaps,这会给支持各种实现带来很多麻烦,或者迫使所有实现变得严格统一,这对于性能来说也是一个坏主意。

OpenGL设备(GPU)可能有自己的内存和自己的地址空间,独立于主机(CPU)内存系统。(想想一个独立的视频卡,它有自己的板载内存。)主机不能(直接)访问内存,所以不可能有指向它的指针。

最好将GPU视为一个完整的独立计算机;实际上,在网络上实现OpenGL是可能的,在一台计算机上运行的程序在另一台计算机上渲染显卡上的图形。当你设置纹理和缓冲区时,你基本上是将数据上传到GL设备以供其内部使用。

最新更新