【问题标题】:How do I tell whether an OpenGL function should be an extension function or not?如何判断 OpenGL 函数是否应该是扩展函数?
【发布时间】:2016-08-19 16:23:21
【问题描述】:

如果我加载 3.1 或更低版本的 GL 上下文,而不是 3.2 或更高版本(我正试图达到 4.4),OpenGL 渲染(Windows 操作系统)正在发生,我遇到了一个难以调试的问题,OpenGL 抛出glDrawArraysEXT 上的一个不起眼的 INVALID_OPERATION 错误。

我认为问题可能在于调用的一个或多个函数是“旧”版本,使用 GL 1.0/1.1 函数而不是可能需要的等效 3.0+ 扩展方法。例如,我将 glDrawArrays 替换为 glDrawArraysEXT 修复了早期的错误,但也许还有更多类似的功能需要更新版本?

所以我的问题是,我怎么知道我是否打算对我的任何其他功能使用“替换”扩展方法?例如我的假设是 glViewport 没有扩展方法(因为我试图加载它并且找不到它),所以使用核心版本就可以了。但是如何在不使用扩展方法的情况下检查我正在调用的所有函数呢?

如果有帮助,这里是我当前调用的 OpenGL 1.0/1.1 函数列表:

  • gl清除
  • glClearColor
  • gl 视口
  • glGetError
  • glEnable/glDisable
  • glBlendFunc
  • glBindTexture
  • glGenTextures
  • glGetTexImage
  • glTexParameteri
  • glTexImage2D
  • glGetString

这些是否有我应该使用的扩展方法,我应该如何自己找到它?

【问题讨论】:

  • 除了glGenTextures,都是GL 1.0。直到 GL 1.1 才添加纹理对象。但是与它们相关的状态是存在的,这就是为什么glTexParameteri 是 GL 1.0。另外,您的意思是API; ABI 与较低级别的事情有关,例如如何将变量传递给 CPU 上的函数。
  • 是的,1.1 是一个错字,但已更正。我从这里拿了 ABI:stackoverflow.com/questions/27873784/…
  • 我认为 GL 函数甚至不是这里的根本原因。您很可能在绘图调用时收到 GL_INVALID_OPERATION 错误,因为您的 opengl 代码与 OpenGL 核心配置文件不兼容,即在绘图调用时您没有 VAO 或没有绑定着色器。
  • @derhass 实际上,我缺少上下文标志上的核心配置文件位,以及配置文件掩码上的前向兼容位。

标签: opengl


【解决方案1】:

例如,我将 glDrawArrays 替换为 glDrawArraysEXT 修复了早期的错误,但也许还有更多类似的功能需要更新版本?

扩展程序不是这样工作的。 glDrawArraysEXT 不是核心 OpenGL 函数;这是一个扩展功能。除非实现指定它实现了这个扩展,否则你不能调用它。

GL 1.0 没有数组渲染; glBegin/End 是你所拥有的。进行了扩展,EXT_vertex_arrays,添加了glDrawArraysEXTglDrawElementsEXT(除其他外)。这些最终被 GL 1.1 吸收,因此失去了 EXT 后缀。

换句话说,glDrawArraysEXT替换为 glDrawArrays,而不是相反。因此,如果使用 EXT 版本“修复了较早的错误”,则没有;它只是似乎这样做了。所以你不应该寻找扩展函数来替换你的核心函数。


对于您的具体问题,有许多OpenGL loaders 只会生成特定版本的 API 中使用的 OpenGL 函数。 “glLoadGen”(我的)可以,但“glad”也可以。

【讨论】:

  • 除此之外,以ARB 为后缀的扩展也不是隐含的“核心”(旨在将更高版本的规范中的功能带入旧驱动程序)。例如,最初的 ARB GLSL 扩展在形式上与最终的 2.0 规范完全不同。在 OpenGL 2.0 之前,我愚蠢地假设..._ARB 扩展和以ARB 为后缀的函数与下一个规范版本中定义的无后缀对应物是一样的。男孩是我错了;)这在 3.0 中得到了纠正,“核心”扩展定义了没有后缀的函数和常量名称。
  • @AndonM.Coleman:“这在 3.0 中得到了纠正,“核心”扩展定义了函数和没有后缀的常量名称。”并非所有 ARB 扩展都这样做3.0。他们只有在扩展出现的同时公开核心功能时才会这样做。 ARB_draw_buffers_blend 就是一个例子:它是在 GL 4.0 之前发布的(当功能成为核心时);因此,它使用后缀。 ARB_bindless_texture 也有它们,因为它不是核心。 ARB 扩展只是那些 ARB “祝福”或控制其开发的跨供应商。
  • 这就是我想说的。很久以前,我有一个错误的观念,即ARB 扩展将未来的功能倒退,可以假设为完美的后备。如前所述,在发布之前定义的扩展附加函数/常量后缀。同时定义的扩展以向后移植版本所需的内容在其标记上没有后缀——它们与新定义的接口逐字匹配。我的意思是,末尾带有ARB 的常量或函数名称可能等同于也可能不等同于核心功能,您无法从名称中推断出任何东西。
  • 这个答案帮助我更好地理解了 opengl 扩展。纯粹为了您的兴趣,我通过将上下文标志 = 核心配置文件位和配置文件掩码 = 前向兼容位添加到 wglCreateContextAttribsARB 属性来修复实际错误。所以最终证明 opengl 称自己不是问题,但无论如何感谢 - 你帮助我缩小了问题所在!
【解决方案2】:

我在 GitHub 上有一个概念验证项目,可以帮助你。

Khronos 在 OpenGL 注册表中提供了一个 XML 文件,用于描述 API 的每个版本和每个标准常量。他们使用它来构建 API 文档等。如果您解析 XML 文件,则它是可搜索的,但我知道很少有工具可以做到这一点。

这个用 C++ 编写的simple program 在大约一个小时内将告诉您关于扩展、常量或函数的所有信息。这包括它是哪个版本的核心,它是否是可选的,是否有任何别名(提供相同功能的扩展)以及它在哪个版本中被弃用和/或删除。

【讨论】:

  • 感谢您的贡献,但我故意省略提及的一件事是我正在使用 C# 进行 opengl 编程,但不知道如何编译 C++ 程序。如果您提供预编译的版本,我很乐意查看! :)
【解决方案3】:

针对您的后续评论(回复:ABI),我相信我明白您的意思,这不是我最初回答的内容。

     虽然不相关,但我认为最初讨论的代码存储库与讨论有一定的相关性,并选择将其分开。相反,此答案讨论了 ABI,因为它与您可能遇到的三个主要平台(Windows、GNU/Linux 和 Mac OS X)相关,特别强调 Windows,因为它是唯一可以实际运行的平台建议。


从 Windows 95 OSR2 开始,OpenGL32.dll 提供了与 OpenGL 1.1 兼容的 ABI,它在功能上完整到 1.1。这种状态从未改变——任何未在 OpenGL 1.1 中定义的东西都需要可安装客户端驱动程序 (ICD)——而 20 年来唯一的变化是引入了 64 位版本的OpenGL32.dll

GNU/Linux 作为一个平台,不保证任何 OpenGL 支持(因此没有标准 ABI),Apple 是/曾经是真正的怪人,在每个操作系统版本中都有不断变化的 ABI。

Apple 的 ABI 很棘手,因为您可以链接和调用很多函数,但是当从不受支持的上下文中调用时,除了 raise GL_INVALID_OPERATION 之外,这将无济于事(听起来很熟悉?!)。 Apple 提出此错误的决定至少是一致的,尽管从未与您将遇到的任何其他平台充分讨论或共享。扩展在 OS X 上毫无意义,但 Apple 确实在 AGL 中定义了一种机制来查询它们各自的函数指针(也许是为了与其他所有平台进行奇偶校验?)。


在 Windows 上,ABI 从未增长或缩小。 20 年前它支持glDrawArraysEXT,直到今天,参考 GDI 实现仍然支持。您通常不会在 GDI 实现上运行任何软件;它像泥土一样慢,与平台的现代硬件加速层几乎没有交互。

尽管该平台最初设计时考虑了混合 GDI/硬件驱动程序(迷你客户端驱动程序),但这从未实现。与 MCD 相比,可安装客户端驱动程序 (ICD) 至少实现了 OpenGL32.dll 所做的所有事情,MCD 只实现了 OpenGL32.dll 的一个子集,并且可能会回退到平台的 GDI 讨厌的任何其他事情。

由于迷你客户端驱动程序从来都不是实用的,只是作为一种快速的权宜之计(想想 DOS 时代的 Quake 迷你驱动程序),因此您在 Windows 上遇到的任何和所有 OpenGL 驱动程序都将是成熟的 ICD 或完全基于软件的驱动程序。 glDrawArraysEXT 随时可供您使用,并且它始终由与 OpenGL 的所有其他部分相同的驱动程序提供。


这一切都很好,但是意义不大,因为最初讨论的glDrawArraysEXT 函数与glDrawArrays 不同。一个接一个接一个,但是将其“更新版本”忽略是错误的,因为您可能不希望被贴上父母的更新版本的标签...

除少数情况外,当调用末尾附加XYZ 的内容时,您可以假设讨论的内容与后缀免费版本相关但不相同。

如果从glDrawArrays 切换到glDrawArraysEXT 时行为发生变化,并且您正在处理 Windows(并合理地假设 MCD 不存在),那是因为该函数应该具有不同的行为(或者您有一个错误driver) -- 不是因为它是由其他东西提供的。


Windows 是唯一一个设计有驱动程序模型的平台,该模型可能会任意将其 GL 实现拆分为多个驱动程序,并且由于该事实仅适用于历史书籍,因此应该涵盖所有基础。

【讨论】:

  • TL;DR:如果你能链接到它,你可以调用它(除非是苹果,那么你必须想不同);)
猜你喜欢
  • 2013-03-30
  • 1970-01-01
  • 2010-09-10
  • 1970-01-01
  • 2013-09-09
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
相关资源
最近更新 更多