我应该缓存OpenGL状态,比如当前绑定的缓冲区,还是OpenGL会这样做
Should I cache OpenGL state such as currently bound buffers, or does OpenGL do that anyway?
一个典型的OpenGL调用可能是这样的:
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_SOME_BUFFER, buffer);
...
我读到过绑定缓冲区和其他类似的函数可能非常昂贵。是否值得保存当前绑定的缓冲区,并在绑定之前检查它?例如:
void StateManager::bindBuffer(GLenum bufType, GLuint bufID) {
if (this->m_currentBuffer[bufType] != bufID) {
glBindBuffer(bufType, bufID);
this->m_currentBuffer[bufType] = bufID;
}
}
这背后的想法是,如果bufID
已经绑定,那么对glBindBuffer
的昂贵调用将被忽略。这是一个有价值的方法吗?我认为OpenGL很可能已经实现了这样的优化,但我现在已经在几个项目中看到了这种模式,所以我有我的怀疑。我只是感兴趣,因为这将是一个非常简单的事情实现,但如果它没有太多/任何区别,那么我将跳过它(避免过早优化)。
这是高度依赖于平台和供应商的。
你问的是"OpenGL会实现…"。正如你已经理解的那样,OpenGL是一个API规范。有许多不同的实现,它们是否检查冗余状态更改完全是一个实现决策,这可以(并且将)因实现而异。
你甚至不应该期望给定的实现对所有状态块都处理相同。
根据过去的经验,这个话题有点接近我的心,我想写一篇小文章,包括一些咆哮。但我决定它不属于这里,所以这里只是一个考虑事项列表,如果给定的OpenGL实现在特定情况下测试冗余状态更改,可能会影响:
- 实际改变状态的成本有多高?如果它非常便宜,检查多余的更改可能根本不值得。
- 检查冗余更改的成本有多高?通常不多,但我们正在研究的软件,每一点都很重要。 重要的应用程序/基准是否会频繁地冗余更改此状态?
- 关于应用程序的责任和OpenGL实现的责任的哲学是什么?
是的,这对每个人都是不幸的。对于想要跨供应商/平台获得理想性能的应用程序编写人员来说,确实没有简单的解决方案。如果你在代码中添加检查,它们将是无用的,并且在OpenGL实现中具有相同检查的平台上增加额外的开销。如果你没有在你的代码中进行检查,并且不能轻易地避免这些冗余的状态更改,那么你可能会在OpenGL实现不进行检查的平台上留下性能表。
状态缓存是一个坏主意的原因很简单:你做错了。你总是有做错的危险。
哦,当然,你纠正了我指出的错误,不同的缓冲区绑定有不同的状态。也许你正在使用一个哈希表,它使查找非常快,即使一个新的扩展出现了,添加了一个新的缓冲区绑定点,当你写缓存时不存在。
但这只是对象绑定特性的冰山一角。
例如,您是否意识到GL_ELEMENT_ARRAY_BUFFER
实际上不是上下文状态?它实际上是VAO状态,每次绑定新的VAO时,缓冲区绑定都会发生变化。因此,您的VAO缓存现在也必须更改阴影元素缓冲区绑定。
但这只对某些对象类型成立。即使这样,它也只适用于对象被删除时当前的上下文。其他上下文不受影响。
我的观点是:适当的状态缓存是非常困难的。如果您弄错了,您将在应用程序中创建大量非常细微的错误。而如果你只是让OpenGL做它自己的事情并构造你的代码使多重绑定不会发生,那么你就不会有问题。- OpenGL 16 位模板缓冲区?
- 在 openGL 中多次绑定缓冲区
- 是否可以从 OpenGL 缓冲区获取原始大小的像素?
- 是否可以在 OpenGL 中的同一调用中呈现两个具有不同索引起点的不同缓冲区?
- OpenGL 调试上下文警告 -"将使用视频内存作为缓冲区异议的来源
- Opengl 3/4 : 我可以将相同的缓冲区对象绑定到不同的目标吗?
- OpenGL 更新缓冲区如何影响速度
- 从OpenGL应用程序中提取颜色/深度缓冲区
- 使用 OpenGL 插值数据缓冲区?
- 写入渲染缓冲区并使用单个渲染调用使用 OpenGL 显示
- OpenGL 顶点缓冲区类重定义和模板方法错误
- 使用推力使用sort_by_key对两个OpenGL缓冲区进行排序
- OpenGL:缓冲区对象/着色器超出范围
- OpenGL-缓冲区更新下一个渲染对象
- 自定义 OpenGL 缓冲区类不显示任何内容
- OpenGL缓冲区到属性
- 在MS Visual Studio 2010上使用带有Cuda互操作的OpenGL缓冲区时出现异常错误
- 使用OpenCL获取OpenGL缓冲区
- 自定义分配器,用于将stl矢量存储在OpenGL缓冲区对象中
- 如何通过 OpenGL 缓冲区将 glm 数据类型直接传递给 GPU