【问题标题】:OpenGL - How is GLenum a unsigned 32 bit Integer?OpenGL - GLenum 如何是无符号的 32 位整数?
【发布时间】:2014-01-16 18:03:24
【问题描述】:

首先,OpenGL 中有 8 种类型的缓冲区对象:

  • GL_ARRAY_BUFFER​
  • GL_ELEMENT_ARRAY_BUFFER​
  • GL_COPY_READ_BUFFER
  • ...

它们是枚举,或者更具体地说是 GLenum 的。其中 GLenum 是一个无符号的 32 位整数,其值最高可达 ~ 4,743,222,432。

缓冲区对象的大多数用途涉及将它们绑定到某个目标,如下所示:例如

glBindBuffer (GL_ARRAY_BUFFER, 缓冲区 [大小]);

[void glBindBuffer(GLenum 目标,GLuint 缓冲区)] 文档

我的问题是 - 如果它是一个枚举,那么它的唯一值必须分别为 0,1,2,3,4..7 那么如果它只有向上的值,为什么要一直让它成为一个 32 位整数到 7 点?请原谅我对 CS 和 OpenGL 的了解,这似乎是不道德的。

【问题讨论】:

    标签: opengl enums opengl-4


    【解决方案1】:

    枚举不仅仅用于缓冲区——在任何地方都需要一个符号常量。目前,分配了数千个枚举值(查看您的 GL.h 和最新的glext.h。请注意,供应商被分配了他们的官方枚举范围,因此他们可以在不干扰其他人的情况下实现特定于供应商的扩展 - 所以 32 位枚举空间是不错的主意。此外,在现代 CPU 架构上,使用小于 32 位的效率不会更高,因此这在性能方面不是问题。

    更新: 正如 Andon M. Coleman 指出的那样,目前只分配了 16 位枚举范围。在OpenGL Enumerant Allocation Policies 处链接可能会有用,其中也有以下备注:

    从历史上看,一些单一供应商扩展的枚举值以 1000 个块为单位进行分配,从块 [102000,102999] 开始并逐渐向上。此范围内的值不能表示为 16 位无符号整数。这对某些实现造成了重大且不必要的性能损失。已经分配给供应商的这些块将保持分配状态,除非并且直到供应商自愿释放整个块,但不会再分配此范围内的块。

    其中大部分似乎已被删除以支持 16 位值,但 32 位值已被使用。在当前的 glext.h 中,仍然可以找到一些高于 0xffff 的(过时的)枚举数,例如

    #ifndef GL_PGI_misc_hints
    #define GL_PGI_misc_hints 1
    #define GL_PREFER_DOUBLEBUFFER_HINT_PGI   0x1A1F8
    #define GL_CONSERVE_MEMORY_HINT_PGI       0x1A1FD
    #define GL_RECLAIM_MEMORY_HINT_PGI        0x1A1FE
    ...
    

    【讨论】:

    • 那么你是说缓冲区对象与数百个其他枚举共享“空间”吗?
    • 尽管如此,OpenGL 仍然官方只使用GLenum 空间的低 16 位来分配常量值。 GLenum 是 32 位类型,但在核心和现代扩展 GL 中只有 16 位可用。这就是为什么当扩展从 EXT 提升到 ARB 然后提升到核心时,您经常会看到枚举数的重用。如果我们真的有一个 32 位的枚举空间可以使用,那么这真的没有必要。你可以很容易地为扩展的每个(通常在功能上不兼容的)迭代赋予它自己的一组离散常量值。
    • @BDillan:好吧。 GL 枚举数只有一个全局“名称”空间。所以这可能是这个问题的“是”。
    • 所以我猜当时红皮书(第 8 版)已经过时了。因为它说它是 32 位的。 OpenGL 移动得很快,我想我不会在意这些小细节
    • @BDillian:类型的大小和范围之间存在差异。仅仅因为GLenum 是 32 位的,并不意味着您可以使用 32 位整数的全部范围。同样,仅仅因为像glBindSampler (...) 这样的函数使用GLuint 来标识您将与之关联的纹理单元(而不是GLenum),并不意味着您实际上可以拥有42.7 亿个纹理图像单元。我不会费心阅读这些细节的书,它们在官方 OpenGL 规范中进行了概述,您可以在以下位置免费阅读(适用于任何版本):opengl.org/registry
    【解决方案2】:

    你为什么还要使用short呢?你会在什么情况下通过使用 short 或 uint8_t 而不是 GLuint 来进行枚举和 const 声明,甚至可以节省超过 8k 的内存(如果接近一千个 GLenums 的报告是正确的)?考虑到潜在的硬件不兼容和潜在的跨平台错误带来的麻烦,即使在原始 2mb Voodoo3d 图形硬件的上下文中尝试保存类似 8k ram 的东西有点奇怪,更不用说 SGL 超级计算机农场 OpenGL 了为。

    此外,现代 x86 和 GPU 硬件一次对齐 32 位或 64 位,您实际上会停止 CPU/GPU 的操作,因为必须将寄存器的 24 位或 56 位清零,然后读取/写入到,而它一旦被复制就可以在标准 int 上运行。从 OpenGL 开始,计算资源往往比内存更有价值,而你可能会在程序的生命周期中进行数十亿次状态更改,你会节省如果您将每个 32 位 GLuint 枚举替换为 uint8_t 枚举,则内存最大值约为 10kb(千字节)。我现在很努力不要变得愤世嫉俗,呵呵。

    例如,像 uint18_t 之类的东西的一个有效原因是数据适合该位深度的大型数据缓冲区/算法。堆栈上的 1024 个整数与 1024 个 uint8_t 变量为 8k,我们是否要将头发分割超过 8k?现在考虑一个 4000*2500*32 位的 4k 原始位图图像,我们说的是几百兆,如果我们使用 64 位 RGBA 缓冲区代替标准的 8 位 RGBA8 缓冲区,它的大小将是 8 倍,或者四倍如果我们使用 32 位 RGBA 编码,则在大小上。将其乘以打开的纹理数量或保存的图片数量,并为所有额外的内存交换一些 cpu 操作是有意义的,尤其是在这种类型的工作环境中。

    这就是使用非标准整数类型的意义所在。除非您使用的是 64k 机器或其他设备(例如老式蜂鸣器,祝您在其上运行 OpenGL 好运)系统,如果您试图在 const 声明或引用计数器之类的东西上节省一些内存,那么您就是只是浪费大家的时间。

    【讨论】:

      猜你喜欢
      • 2011-01-31
      • 2012-07-27
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多