解释来自 KDAB 博客的引述
Posted
技术标签:
【中文标题】解释来自 KDAB 博客的引述【英文标题】:Explaining a quote from KDAB blog 【发布时间】:2013-12-17 16:04:30 【问题描述】:我正在阅读来自KDAB 的OpenGL in Qt 5.1。他们说关于 OpenGL:
...需要在运行时动态解析入口点地址 而不是构建时链接器能够这样做。
这究竟是什么意思,为什么会这样?
【问题讨论】:
【参考方案1】:我认为解释这里发生的事情的最佳方式是在大多数平台上(OS X 是规则的例外),它们附带了一个非常原始的 OpenGL 实现(在 Windows 上为 1.1),这是责任用于扩展 OpenGL 的硬件(有时是软件)驱动程序。
因为必须将您的程序显式链接到每个可能的驱动程序组合(并在发布新驱动程序版本时重新编译和链接您的程序)对任何人都没有好处,所以实际发生的情况是:OpenGL 的版本平台附带的运行时具有在运行时从另一个已安装组件(驱动程序)加载扩展函数地址的机制。你不需要知道驱动是谁写的,什么版本,你只需要让平台的OpenGL库与驱动通信,并返回一个库本身没有实现的函数的地址。
通过这种方式,基本库(现在实际上是一个存根,因为大量 OpenGL 1.1 已被弃用)只需编写一次。在运行时之前,您仍然无法确定您的主机将支持什么,因为提供的功能集取决于安装的驱动程序。
我之前提到过 OS X,我会花一些时间来解释它的不同之处。在 OS X 上,该库实际上包含 Apple 在平台上实现的每个扩展的函数(Apple 自己在 OS X 上实现了显示驱动程序)。也就是说,只需链接到适当的框架,您就可以访问每个功能。但是,如果该功能无法在硬件/软件配置上实现,则尝试调用这些功能中的任何一个都会在运行时产生GL_INVALID_OPERATION
错误。
这就是链接时解析和运行时解析之间的区别——在 OS X 上,所有函数都在链接时解析,但这并不意味着它们是可用的。在其他平台上,扩展功能在运行时通过安装的第 3 方驱动程序解析。由于驱动程序由第三方实现比平台开发方更常见,因此第二种情况更为常见。
【讨论】:
【参考方案2】:KDAB 文章给出了非常详细的解释:
... 自 OpenGL 1.1 以来引入的任何函数的地址都必须在运行时解析
OpenGL 不是一个库,它是一个 API,即提供的一组函数。 API 的某些部分已被定义为始终由操作系统接口 库提供。由于这是固定的,因此可以在链接时解决。
在 Microsoft Windows 中,OpenGL-1.1 的所有功能都是其中的一部分。然而,后来引入 OpenGL 的所有内容,即更新版本的 OpenGL 和 扩展,都没有出现在该接口库中(这在某种程度上是支持的功能集上的最小公分母)。
由于所支持的版本和功能取决于安装的 GPU 和驱动程序,它们会因系统而异,因此必须在运行时动态使用指向所有附加功能的指针。由于加载扩展或新版本功能集没有区别,两者都通过相同的机制发生。
【讨论】:
您的报价与我在问题中引用的内容相同......但适用于 Windows。所以这里没有什么新东西^^ 另外,如果您在库和 API 之间有所不同,那么我们正在讨论一组函数规范。但是,如果驱动程序遵守这个规范,应该没有任何问题......但是,情况并非如你所说,所以我们需要某种机制来在“正常”OpenGL(我正在写的那个)之间“转换”和“驱动程序”opengl。这就是我们所说的吗? @Korchkidu:这真的很难理解吗:操作系统为您提供了程序和驱动程序之间的接口。新硬件和驱动程序可能会引入在创建操作系统级接口时不存在的功能。为了避免必须通过完整的操作系统更新,接口允许从驱动程序加载功能,即使在创建接口库时它不存在。由于您希望能够使用具有多种硬件的操作系统,因此将接口库写入您想要断言可用的最低版本 @Korchkidu:Windows 与否无关紧要。 Linux、Solaris 和 FreeBSD 都是一样的。只有 MacOS X 没有公开扩展机制,需要完整的操作系统升级才能支持更新版本的 OpenGL。这实质上意味着 MacOS X 落后于 OpenGL 开发大约 2 年。 Windows、Linux、Solaris 和 BSD 都是最新的,因为它们的驱动程序架构允许扩展。 @Korchkidu:“遵循”规范的驱动程序也没有抓住重点。您的应用程序需要能够与驱动程序对话。而且它只能通过操作系统提供的接口来完成。但是,如果操作系统将提供具有完整 OpenGL-4.4 功能集的接口库,那么在该操作系统上可用的 GPU 的最低要求是支持 OpenGL-4.4 的 GPU。因此,您希望驱动程序接口的版本尽可能低,并且仅在运行时加载更新和扩展的功能,否则您将严重限制支持的 GPU 集。【参考方案3】:您应该进一步阅读它。它给出了一个示例,为什么链接器在构建期间无法完成:
... 例如,在 Microsoft Windows 上,自 OpenGL 1.1 以来引入的任何函数的地址都必须在运行时解析。这几乎是现代 OpenGL 应用程序中使用的所有函数! ...
文章还解释了 proc 地址和函数等需要在运行时通过适当的查询和辅助功能来解决。
... 为了帮助解决这个问题,Qt 提供了几个有用的实用程序:QOpenGLContext::getProcAddress() 和 QOpenGLFunctions。 ...
继续阅读这篇文章!
【讨论】:
你没有解释,你只是改写。 OpenGL 和任何其他库有什么区别?为什么我们不能像其他任何库一样链接到函数? @Korchkidu:呃,我想你对文章的主题有点误解了。这不是关于是否链接到 opengl,而是关于解决运行时依赖的实现。 “解析入口点地址”+“构建时链接器”。看起来他们真的在谈论链接。您能否详细举例说明问题是什么以及为什么会这样? @Korchkidu:我不确定我是否理解您的问题,但是如果没有运行时解析,您将如何解决上述 Microsoft 案例? 只是为了确定,我们在谈论扩展吗?我对此表示怀疑,因为他们在下一节中介绍了扩展。另外,这是 OpenGL 2.0 特有的吗(我不知道)?以上是关于解释来自 KDAB 博客的引述的主要内容,如果未能解决你的问题,请参考以下文章
如何将来自 github 的“当前连续”贡献添加到我的博客?