C++ glGetError与性能 背景

C++ glGetError与性能 背景,c++,performance,opengl,opengl-es,C++,Performance,Opengl,Opengl Es,在工作中,我们开发了两个产品,它们都有OpenGL3.x+和GLE2.0/3.0+后端。团队是独立的,但有一些重叠,我们最近讨论了glGetError的性能 在这两种产品中,设计都是这样的:没有GL调用会生成由glGetError记录的错误代码。为了检测此类错误,在debug中,我们有一个宏,在每次GL调用后添加一个glGetError,并断言是否检测到任何错误,因为这意味着存在错误。在我的产品上,这是默认启用的,在另一种情况下,它必须显式启用 这些已经存在于我工作多年的产品的代码库中,我们看到

在工作中,我们开发了两个产品,它们都有OpenGL3.x+和GLE2.0/3.0+后端。团队是独立的,但有一些重叠,我们最近讨论了
glGetError
的性能

在这两种产品中,设计都是这样的:没有GL调用会生成由
glGetError
记录的错误代码。为了检测此类错误,在debug中,我们有一个宏,在每次GL调用后添加一个
glGetError
,并断言是否检测到任何错误,因为这意味着存在错误。在我的产品上,这是默认启用的,在另一种情况下,它必须显式启用

这些已经存在于我工作多年的产品的代码库中,我们看到它们会导致性能下降,通常在许多平台上都会达到25%左右。我们已经决定,这是为早期发现错误而付出的合理代价。另一个团队声称,在某些情况下,添加这些检查会将其以60FPS速度运行的产品的执行速度降低到<1FPS,从而使产品无法使用,这就是为什么默认情况下不启用这些检查的原因。这两款产品都运行在许多OpenGL/GLE平台(PC、OSX、Linux、iOS和Android)上

问题 我理解
glGetError
降低性能背后的原因;您(可能)需要CPU/GPU同步,以确保前一操作的状态正确。根据我的理解,这应该将预期的帧时间从“
MAX(CPU时间,GPU时间)
”(假设没有其他同步点,也没有排队的帧)更改为“
CPU时间+GPU时间+同步开销”
(假设每个glGetError调用都会产生一个同步点)。这是不正确的推理,还是使用
glGetError
降低性能还有其他原因

我总是觉得调试中每次调用
glGetError
都是一件合理的事情(至少在不可能出现错误的GL调用之后)。这难道不是一种“最佳实践”吗?
是否存在某些情况会导致极端性能问题,如所述的其他团队(例如,使用一组特定的GL调用和/或平台)?

可能需要某种CPU/GPU同步来查询错误状态,但我认为这是言过其实了。这与读回仍在运行或挂起的渲染操作的结果完全不同。错误状态是在执行命令之前经过验证和设置的,它通常会提醒您API使用无效或状态设置无效,但不会提醒您其他情况

现代OpenGL实现有一个更复杂的扩展/核心功能,用于跟踪调试信息,称为。您已经标记了此OpenGL以及OpenGL ES,因此它可能不适用于您软件的所有部署,但当使用具有此功能的OpenGL或ES实现时,它确实应该是您的解决方案。当然,您会得到错误信息,但会得到一些额外的警告,如不推荐和性能(这实际上取决于驱动程序的详细程度,我看到一些驱动程序给出了非常好的警告,而另一些驱动程序根本不使用该功能)


您可以同步运行调试输出,这可能会导致您在问题中讨论的性能损失;也可以异步运行调试输出,这可能会对性能更友好,但在试图实时跟踪问题的原因时会稍微不太有用。没有一成不变的解决方案,这就是为什么调试输出比GLGETError(…)>代码>更灵活和更明确。

< P>嗯,我会考虑在这种情况下触发完全CPU /GPU同步非常不可能(但不是不可能)。GPU对GL客户端错误一无所知,GPU将要使用的所有资源都由CPU管理,因此在这一点上GPU可以报告的错误不多。通常,如果由于某些用户错误导致GPU端出现“错误”,则结果只是未定义,但不会触发GL错误

话虽如此,我并不想暗示
glGetError
调用的开销很低。现代GL实现是高度多线程的。通常,GL调用自己,只将命令和数据转发给后台的其他工作线程,并尝试尽早返回,以便应用程序可以继续。查询错误意味着您必须与所有这些工作线程同步,这可能会严重滞后

是否存在可能导致极端性能的情况 其他团队描述的问题

那么,报告的性能影响肯定是可能的。但要想弄清楚到底是什么触发了这种情况将非常困难。我不知道错误检查异常糟糕的任何具体情况,我怀疑是否可以为这些事情推导出一套简单的经验法则。复杂性太高了

当你询问最佳实践时,我们进入了观点领域。这将始终取决于具体的场景。在每次GL调用后,我从未进行过错误检查。我在“战略位置”进行了一些错误检查,通常在ressource设置中启用,但从不在“快速路径”中启用。此外,我曾经在调试构建中默认启用“战略”位置的附加检查。我也经常有一些额外的马可,以使更多的检查,以缩小发生的错误容易

然而,随着时间的推移,这些检查变得越来越不有用。现在,有一些GL调试工具可以帮助您识别失败的GL调用

另一个非常有用的概念是or扩展引入的调试上下文(后者也被定义为GLES扩展,但我不知道它的可用性有多广)。这基本上允许设置GL将调用的回调,因此“轮询”fo