Windows 上的 OpenGL 1.0 和 1.1 函数指针

Posted

技术标签:

【中文标题】Windows 上的 OpenGL 1.0 和 1.1 函数指针【英文标题】:OpenGL 1.0 and 1.1 Function Pointers on Windows 【发布时间】:2014-08-09 01:51:04 【问题描述】:

我对 的性质有点困惑。我想我已经记下来了,但我不是 100% 确定,所以我希望有人能够确认或评论我目前的理解:

我目前的理解是,您应该使用wglGetProcAddress() 加载 1.2+ 函数,但必须使用 GetProcAddress()opengl32.dll 加载 1.0 和 1.1 函数。然而,引起我注意的是wglGetProcAddress() 应该根据当前的HGLRC 上下文返回不同的函数指针。然而,GetProcAddress() 中的 1.0 和 1.1 指针可能总是相同的。这种行为上的差异感觉很不寻常。

假设我有多个HGLRC 对象,我们将它们称为AB。我调用wglGetProcAddress() 并将结果保存在单独的指针池中,一个用于A,另一个用于B。然而,我还必须将 1.0 和 1.1 函数加载到这些指针池中,在这种情况下,AB 的指针似乎总是相同的。

令我惊讶的是,1.0 和 1.1 函数因此必须是瘦包装器,它将 OpenGL 调用重定向到与当前 HGLRC 关联的任何驱动程序。然而,如果 Windows 上已经存在这样的重定向机制,那么我想知道为什么 wglGetProcAddress() 也不能使用它,因为这样做会减轻它返回依赖于上下文的指针的危险。我什至不需要知道这个问题的答案,但这个问题的存在让我怀疑我是否一开始就理解正确。

【问题讨论】:

【参考方案1】:

原因很简单:OpenGL-1.1 的符号是一个固定的集合,因此接口 DLL opengl32.dll 可以包含回退实现和蹦床到图形驱动程序提供的完整 OpenGL 实现中(ICD)。这些符号由符号表中的接口 DLL 公开,因此可以通过 GetProcAddress 访问。

任何超出 OpenGL-1.2 版本的内容对于接口库都是未知的。因此,opengl32.dll 既不包含用于这些功能的 ICD 的后备方案,也不包含蹦床。相反,它充当代理,将对wglGetProcAddress 的调用传递给图形驱动程序 (ICD) 中的实际 OpenGL 实现。然而,由于不同的 OpenGL 上下文可能由不同的图形驱动程序 (ICD) 提供服务,因此结果可能是位于不同地址的符号。 wglGetProcAddress 不查看某些 DLL 的符号表,但可以在 ICD 认为合适的任何地方实现。

【讨论】:

有趣。所以我认为我最初的评估是正确的:在我的其他依赖于上下文的函数指针池中,指向 1.0 和 1.1 调用的函数指针将始终相同(并且没有什么奇怪或损坏的;好吧,也许很奇怪,但不是坏了)。 @patrick-rutkowski:是的,确实如此。恕我直言,接口 DLL opengl32.dll 绝不应该导出任何 OpenGL 符号,而只能导出 wgl… 符号。这将迫使所有程序通过wglGetProcAddress 动态加载所有OpenGL 符号;乏味是的,但更一致。此外,让所有返回的指针指向 TLS 区域中动态管理的 JMP 表中的条目也很简单,只要切换 OpenGL 上下文,该表就会更新。 有趣的是你提到了 TLS 跳转表。我目前正在尝试为 GL 1.2+ 函数编写蹦床包装器。蹦床函数必须跟踪给定线程中哪个函数指针池是“活动的”。在从实际的 ICD 驱动程序调用 GL 函数之前,我的每一个蹦床函数都必须调用 TlsGetValue() 以获取活动的函数指针池。我目前正在研究它,但我怀疑这可能会带来太多的性能开销,而且我不太确定如何进行。 @patrick-rutkowski:嗯,是的,有一定的惩罚。话虽如此,TlsGetValue 已针对速度进行了优化(根据 MSDN)。也不要忘记,现代 OpenGL 就是为了减少绘制大量图元所需的函数调用次数。请注意,只有 Windows 搞砸了。在 GLX 中,函数指针在所有上下文和线程中都被指定为相同(它仍然存在不同的上下文可以绑定到需要调度的不同线程的问题,但这对于实现来说是一个更加良性的问题。) @patrick-rutkowski:您可能想看看 Mesa 如何解决调度表问题:mesa3d.org/dispatch.html#overview

以上是关于Windows 上的 OpenGL 1.0 和 1.1 函数指针的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 3.0 不适用于 Windows 上的 Qt

OpenGL——三维多面体实现

OpenGL step to step

OpenGL蓝宝书第五章代码勘误以及惯性坐标系去解释模型变换:Pyramid.cpp

Windows 上的 OpenCL/OpenGL 纹理互操作:调整 OpenGL 纹理的大小

opengl程序问题,为啥只有白屏?