Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我应该缓存OpenGL状态,比如当前绑定的缓冲区,还是OpenGL会这样做?_C++_Opengl - Fatal编程技术网

C++ 我应该缓存OpenGL状态,比如当前绑定的缓冲区,还是OpenGL会这样做?

C++ 我应该缓存OpenGL状态,比如当前绑定的缓冲区,还是OpenGL会这样做?,c++,opengl,C++,Opengl,典型的OpenGL调用可能如下所示: GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_SOME_BUFFER, buffer); ... 我已经读过缓冲区和其他类似函数的绑定可能非常昂贵。是否值得保存当前绑定的缓冲区,并在绑定前检查它?例如: void StateManager::bindBuffer(GLenum bufType, GLuint bufID) { if (this->m_currentBu

典型的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\u ELEMENT\u ARRAY\u BUFFER
实际上不是上下文状态?它实际上是VAO状态,每次绑定新的VAO时,缓冲区绑定都会发生变化。因此,VAO缓存现在也必须更改阴影元素缓冲区绑定

另外,您是否知道删除对象会自动将其从当前绑定到的任何上下文绑定点解除绑定?即使是附加到另一个绑定到上下文的对象上的对象也是如此;删除的对象将自动分离

但这仅适用于某些对象类型。即使如此,它也只适用于删除对象时的当前上下文。其他上下文将不受影响


我的观点是:正确缓存状态确实很难。如果你弄错了,你会在你的应用程序中产生很多非常微妙的错误。然而,如果你让OpenGL来做它的事情,并且构造你的代码,这样多个绑定就不会发生,那么你就不会有问题。

如果你要实现它,你应该正确地实现它。没有单一的“当前缓冲区”;每个
bufType
都有自己的当前缓冲区。当然,这个想法仍然有效。不过,我会编辑这篇文章。有一次我问了一个类似的问题。不过,对答案不太满意,所以不做重复标记。不完全是你问的,但我可能会感兴趣read@BDL谢谢,那很有趣。我明白了。但是当前绑定的
GL\u元素\u数组\u缓冲区
会在绑定不同的
vao
时自动绑定,对吗?因此,在这种情况下,你不会得到任何速度提升,但你不会得到任何bug。在第二个示例中,当某个对象被删除时,不可能仅将当前缓存设置设置为无效数字(例如,缓冲区的
0
),以便下一个对象被绑定。不管怎样,如果指定的缓冲区类型没有出现这种情况,那么在最坏的情况下,绑定缓冲区的次数要比应该的多出几次,这不是什么大问题,不是吗?@user3183526:“因此,在这种情况下,您不会得到任何速度提升,但不会得到任何bug。”假设您在绑定VAO Q时绑定缓冲区。然后切换到使用缓冲区B的VAO R,然后尝试绑定缓冲区A。好的,缓存认为A已经绑定,因此不再绑定它。这意味着VAO R仍然在使用缓冲区B,当您想将其更改为使用缓冲区A时。“难道不可能只设置…当某些内容被删除时”您可以这样做。但我的总体观点是:在我提到这个问题之前,你是否意识到了这个问题?你怎么能确定你已经发现了所有这些问题?如果你不确定,那就不可靠了