代码之家  ›  专栏  ›  技术社区  ›  jay.lee

opengl:glFlush()与glFinish()的比较

  •  96
  • jay.lee  · 技术社区  · 16 年前

    我很难区分打电话和打电话的实际区别 glFlush() glFinish() .

    glFlush() glFinish() 将所有缓冲操作推送到OpenGL,这样就可以确保它们都将被执行,区别在于 glFlush() glFinish() 阻塞,直到所有操作完成。

    在阅读了定义之后,我想如果我使用 glFlush() 我可能会遇到这样的问题:向OpenGL提交的操作比OpenGL能够执行的要多。所以,为了尝试,我换了我的 glFinish() 暂时 你瞧,我的程序运行(据我所知)完全一样;帧速率,资源使用,一切都是一样的。

    所以我想知道这两个调用之间是否有很大的区别,或者我的代码是否让它们运行起来没有什么不同。或者应该使用其中一个与另一个的位置。 glIsDone() 检查是否所有缓冲的命令 glFlush() 是否完整(因此,向OpenGL发送操作的速度不会超过它们可以执行的速度),但我找不到这样的函数。

    我的代码是典型的游戏循环:

    while (running) {
        process_stuff();
        render_stuff();
    }
    
    8 回复  |  直到 7 年前
        1
  •  97
  •   Wagner Patriota    9 年前

    请注意,这些命令早在OpenGL早期就存在了。glFlush确保以前的OpenGL命令 ( OpenGL 2.1 specs ,第245页)。如果直接绘制到前缓冲区,这将确保OpenGL驱动程序开始绘制时不会有太多延迟。当您在每个对象之后调用glFlush时,您可以想象一个复杂的场景在屏幕上一个对象接一个对象出现。但是,当使用双缓冲时,glFlush实际上没有任何效果,因为只有在交换缓冲之前,更改才会可见。

    在完全实现以前发出的命令[…]的所有效果之前不会返回 . 这意味着程序的执行在这里等待,直到最后一个像素被绘制出来,OpenGL没有更多的事情要做。如果直接渲染到前端缓冲区,则glFinish是在使用操作系统调用进行屏幕截图之前要进行的调用。对于双缓冲来说,它的用处要小得多,因为您看不到强制完成的更改。

    因此,如果使用双缓冲,则可能既不需要glFlush也不需要glFinish。SwapBuffers隐式地将OpenGL调用定向到正确的缓冲区, there's no need to call glFlush first 立即 (无论这意味着什么),因此它可以花任何时间来处理您的命令。

        2
  •  23
  •   Andy Ross    16 年前

    正如其他答案所暗示的那样,根据规范,确实没有好的答案 glFlush() 在调用它之后,主机CPU将没有OpenGL相关的工作要做——命令将被推送到图形硬件。总的意图 glFinish() 是它回来以后,, 剩下的工作已经完成,结果也应该可以在所有适当的非OpenGL API中使用(例如,从帧缓冲区读取、屏幕截图等)。这是否真的发生取决于驾驶员。该规范允许对什么是合法的有很大的自由度。

        3
  •  20
  •   Tara    10 年前

    我也一直对这两个命令感到困惑,但这张图片让我明白了: Flush vs Finish 显然,一些GPU驱动程序不会将发出的命令发送到硬件,除非累积了一定数量的命令。在这个例子中,这个数字是 5. .
    该图显示了已发出的各种OpenGL命令(A、B、C、D、E…)。正如我们在顶部看到的,命令尚未发出,因为队列尚未满。

    在中间我们看到了如何 glFlush()

    在底部,我们看到一个使用 glFinish() . 它的功能几乎与 glFlush() ,但它使调用线程等待硬件处理完所有命令。

    图片取自《使用OpenGL进行高级图形编程》一书。

        4
  •  7
  •   Bahbar    16 年前

    如果您没有看到任何性能差异,则表示您做错了什么。正如其他一些人提到的,您不需要调用任何一个,但是如果您调用glFinish,那么您将自动失去GPU和CPU可以实现的并行性。让我深入一点:

    因此,如果调用glFinish,实际上就是迫使驱动程序将命令推送到GPU(直到那时它才批处理,并且从未要求GPU处理),并暂停CPU,直到推送的命令完全执行为止。因此,在GPU工作的整个过程中,CPU不工作(至少在这个线程上)。CPU一直在工作(主要是批处理命令),GPU什么也不做。所以是的,glFinish会影响你的表现(这是一个近似值,因为如果已经批处理了很多命令,那么驱动程序可能会开始让GPU处理这些命令。但这并不典型,因为命令缓冲区往往大到足以容纳相当多的命令)。

    那么,你为什么要叫glFinish呢?我唯一一次使用它是在我有驱动程序错误的时候。事实上,如果您发送到硬件的命令之一使GPU崩溃,那么确定哪个命令是罪魁祸首的最简单方法就是在每次绘制后调用glFinish。这样,你就可以缩小引发崩溃的确切原因

    另外,像Direct3D这样的API根本不支持完成概念。

        5
  •  7
  •   starmole    14 年前

    glFlush实际上可以追溯到客户机-服务器模型。通过管道将所有gl命令发送到gl服务器。那根管子可能会起缓冲作用。就像任何文件或网络i/o可能需要缓冲一样。glFlush只说“现在发送缓冲区,即使它还没有满!”。在本地系统上,这几乎是不需要的,因为本地OpenGL API不太可能缓冲自身,而只是直接发出命令。此外,所有导致实际渲染的命令都将执行隐式刷新。

    另一方面,glFinish用于性能测量。类似于对GL服务器的PING。它来回发送一个命令,并等待服务器响应“我空闲”。

    如今,当地的司机们有着相当有创意的想法——尽管无所事事意味着什么。是“绘制所有像素”还是“我的命令队列有空间”?此外,由于许多旧程序在其代码中毫无理由地使用glFlush和glFinish作为伏都教编码,许多现代驱动程序只是将其视为“优化”而忽略。这不能怪他们,真的。

        6
  •  6
  •   AndiDog    16 年前

    看一看 here . 简言之,它说:

    另一个 article 描述其他差异:

    • 交换函数(在双缓冲应用程序中使用)自动刷新命令,因此无需调用 glFlush
    • glFinish 强制OpenGL执行未完成的命令,这是一个坏主意(例如使用VSync)

    总之,这意味着您在使用双缓冲时甚至不需要这些函数,除非您的交换缓冲实现没有自动刷新命令。

        7
  •  4
  •   GManNickG    16 年前

    似乎没有办法查询缓冲区的状态。有这个 Apple extension 这可以达到同样的目的,但它似乎没有跨平台(没有尝试过)。快速浏览一下,它似乎比 flush 你会把篱笆命令推进去;然后,您可以在围栏通过缓冲区时查询其状态。

    我想知道你是否可以用 在缓冲命令之前,但在开始渲染调用的下一帧之前 finish 完成 将阻止以确保一切都处于新状态。

    完成 .)

    当我把它改成 脸红 最后 完成 一开始,没有直接的问题(一切看起来都很好!)程序的响应性提高了,可能是因为CPU没有在GPU上暂停等待。肯定是更好的方法。

    finished 从画面开始,离开 脸红 ,它的表现也一样。

    脸红 完成 完成 ,则没有性能影响。我猜如果缓冲区满了你应该 完成 无论如何

        8
  •  0
  •   anon    16 年前

    之后 您的OpenGL命令已执行。

    这在某些情况下很重要,比如网络延迟,只有特定的控制台输出 之后

    推荐文章