正在存储OpenGL状态
Storing OpenGL state
假设我正试图在C++上制作某种小型的opengl图形引擎。我读到通过glGet*
函数访问opengl状态可能非常昂贵(而访问opengl状态似乎是一种常见的操作),强烈建议将opengl状态的副本存储在具有快速读/写访问权限的地方。
我目前正在考虑将opengl状态存储为某种适当类型的全局thread_local变量。这个设计有多糟糕?有陷阱吗?
如果你想坚持OpenGL的设计(你的上下文指针可以被认为是"thread_local"),我想这是一个有效的选项。。。显然,您需要完全控制所有OpenGL调用,以便使状态副本与当前上下文的状态保持同步。
我个人更喜欢使用一个"OpenGLState"类来包装OpenGL感兴趣的状态,其中包含一组可设置/可获取的属性,每个属性都映射到状态的某个部分。然后也可以避免两次设置相同的状态。您可以将其设置为thread_local,但我做不到(Visual C++只支持POD类型的thread_local)。
您需要非常小心,因为一些OpenGL调用会间接更改上下文状态中看似不相关的部分。例如,glDeleteTextures会将已删除纹理的任何绑定重置为0。此外,一些工具包在背后更改OpenGL状态时非常"有用"(例如,OSX上的QtOpenGLContext会在设置为当前视口时为您更改视口)。
既然只能(合理地)将GL上下文与一个线程一起使用,为什么需要线程本地?是的,您可以在不同的时间在不同的线程中使上下文成为当前上下文,但这不是一个明智的设计。
你通常会有一个上下文和一个线程访问它。在极少数情况下,你会有两个上下文(通常是共享的)和两个线程。在这种情况下,您可以简单地将希望保存的任何其他状态放入上下文类中,其中每个实例都由一个线程所有。
但大多数时候,您不需要明确地"记住"状态。所有状态都有充分记录的初始状态,只有当您更改它们时,它们才会更改("超级智能"工具包所做的更改除外,但在这种情况下,存储错误的状态也没有帮助)。
您通常会尝试将状态批处理在一起,并用一组状态进行许多"类似"的绘制调用,原因是状态更改会使管道停滞,并且需要在下一次绘制调用之前进行昂贵的验证
因此,从默认值开始,并在绘制批次之前设置所有需要为非默认值的内容。然后更改下一批需要不同的内容。
如果你不想费力地浏览默认值的规范并跟踪,你可以一直冗余地设置所有内容。然后在GDebugger中运行您的应用程序,它会告诉您哪些状态更改是多余的,这样您就可以消除它们。
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 了解 GLM- openGL 中的相机转换
- 如何在全屏模式下(在OpenGL中)使背景透明
- 为什么我不能使用 EGL 创建无头 OpenGl 上下文?
- OpenGL大的3D纹理(>2GB)非常慢
- OpenGl glm rotate
- OpenGL 4.5 直接状态访问呈现三角形 - GL_INVALID_VALUE
- OpenGL 纹理状态使用警告:
- opengl Idempotent状态变化的影响
- 在 OpenGL 计划链路状态检查期间"No definition of main in vertex shader"
- 正在存储OpenGL状态
- 在glutKeyboardFunc中所做的OpenGL状态更改不会立即可见
- 正在恢复 OpenGL 状态
- 当底层OpenGL状态被修改时,我应该声明一个方法常量吗
- OpenGL 无效的纹理或状态
- OpenGL的状态需要在新的共享上下文上重置
- 如何定位OPENGL顶部的状态栏
- 如何保存-恢复所有opengl状态变量
- 我应该缓存OpenGL状态,比如当前绑定的缓冲区,还是OpenGL会这样做
- 管理 OpenGL 状态机的策略