存储OpenGL状态

时间:2014-02-28 12:15:26

标签: c++ opengl

假设我正在尝试在C ++上制作某种小型的opengl图形引擎。我已经读过通过glGet*函数访问opengl状态可能非常昂贵(虽然访问opengl状态似乎是一个经常操作),强烈建议在某处使用快速读/写访问权限存储opengl状态的副本

我目前正在考虑将opengl状态存储为某种适当类型的全局thread_local变量。这个设计有多糟糕?有没有陷阱?

2 个答案:

答案 0 :(得分:3)

如果你想坚持使用OpenGL的设计(你的上下文指针可以被认为是“thread_local”),我想这是一个有效的选项...显然,你需要完全控制所有的OpenGL调用,以保持你的状态复制与当前上下文的状态同步。

我个人更喜欢使用“OpenGLState”类来包装感兴趣的OpenGL状态,该类具有一组可设置/可获取的属性,每个属性映射到状态的某个部分。然后,您还可以避免两次设置相同的状态。你可以使它成为thread_local,但我不能(Visual C ++只支持POD类型的thread_local)。

您需要非常小心,因为一些OpenGL调用间接地改变了上下文状态中看似无关的部分。例如,glDeleteTextures会将已删除纹理的任何绑定重置为0.此外,某些工具包在更改背后的OpenGL状态时非常“有用”(例如,OSX上的QtOpenGLContext会在您更新时为您更改视口)

答案 1 :(得分:2)

由于您只能(合理地)在一个线程中使用GL上下文,为什么需要本地线程?是的,你可以在不同的时间在不同的线程中创建一个上下文,但这不是一个明智的设计。

您通常会有一个上下文和一个访问它的线程。在极少数情况下,您将有两个线程(通常是共享)的两个上下文。在这种情况下,您可以简单地将要保存的任何其他状态放入上下文类中,其中每个实例仅由一个线程拥有。

但大多数时候,无论如何你都不需要明确地“记住”状态。所有州都有充分记录的初始状态,只有当更改它们时它们才会改变(例外情况是“超级智能”工具包所做的更改,但存储错误的状态不会在这种情况下也要帮助。)

您通常会尝试将状态批处理并使用一组状态执行许多“类似”的绘制调用,原因是状态更改会使管道停滞并需要在下一次绘制调用之前完成昂贵的验证。
因此,从默认值开始,并在绘制批处理之前设置需要非默认的所有内容。然后更改下一批需要不同的内容。

如果您无法深入挖掘默认值的规格并跟踪,您可以随时冗余地设置所有内容。然后在GDebugger中运行您的应用程序,它将告诉您哪些状态更改是多余的,因此您可以消除它们。