2

使用 OpenGL 编程时,应避免使用 glGet 函数,因为它们会强制 GPU 和 CPU 同步,这是否也适用于获取当前 OpenGL 上下文句柄的 wgl 函数“wglGetCurrentContext”?如果没有,wglGetCurrentContext 是否还有其他性能问题?

4

2 回答 2

4

您的问题暗示了一些误解:

应避免使用 glGet 函数,因为它们会强制 GPU 和 CPU 同步

第一部分是真的。第二部分不是。大多数glGet*()调用不会强制 GPU/CPU 同步。它们只获取存储在驱动程序代码中的状态,根本不涉及 GPU。

有一些例外,其中包括glGet*()实际获取 GPU 生成的数据的调用。典型例子包括:

  • glGetBufferSubData():如果数据是由 GPU 生成的(例如使用变换反馈),则必须阻止。
  • glGetTexImage(): 如果纹理数据是由 GPU 生成的(例如,如果用作渲染目标),则阻塞。
  • glGetQueryObjectiv(..., GL_QUERY_RESULT, ...): 如果查询未完成则阻塞。

现在,您仍然应该glGet*()尽可能避免打电话。主要有两个原因:

  • 它们中的大多数是不必要的,因为它们会查询您自己设置的状态,因此您应该已经知道它是什么。任何不必要的电话都是浪费。
  • 它们可能会导致多线程驱动程序实现中线程之间的同步。因此它们可能会导致同步,但不会与 GPU 同步。

调用当然有一些很好的用途glGet*(),例如:

  • 要获得实现限制,例如最大纹理大小等。在启动期间调用一次。
  • 调用glGetUniformLocation()glGetAttribLocation(). 确保在着色器链接后只调用一次。尽管至少在最近的 GLSL 版本中,这些也可以通过在着色器代码中使用限定符来避免。
  • glGetError(), 仅在调试期间。

至于wglGetCurrentContext(),我怀疑它会非常昂贵。当前上下文通常存储在某种线程本地存储中,可以非常有效地访问。

不过,我不明白为什么有必要调用它。如果您稍后再次需要上下文,您可以在创建它时将其存储起来。如果由于某种原因无法做到这一点,您可以调用wglGetCurrentContext()一次,然后存储结果。绝对不需要重复调​​用它。

于 2015-09-29T04:31:31.710 回答
2

根据供应商和驱动程序的不同,所有 WGL 功能对性能特征的影响差异很大。

我不认为 wglGetCurrentContext 会是一个特别占用性能的调用(除非你做了很多次)。由于 WGL 函数通常与 GL 上下文的状态向量分离。

话虽这么说,设置当前上下文将导致上下文之间的各种同步方式,通常是以非常未记录的方式。我已经处理了几个 AMD 和 Intel 驱动程序错误,其中一些应该通过其他方式同步的东西只能与每帧的冗余 MakeCurrent 调用同步。

于 2015-09-28T22:49:01.663 回答