C++ opengl:glFlush() 与 glFinish()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2143240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
opengl: glFlush() vs. glFinish()
提问by jay.lee
I'm having trouble distinguishing the practical difference between calling glFlush()
and glFinish()
.
我无法区分调用glFlush()
和glFinish()
.
The docs say that glFlush()
and glFinish()
will push all buffered operations to OpenGL so that one can be assured they will all be executed, the difference being that glFlush()
returns immediately where as glFinish()
blocks until all the operations are complete.
文档说,glFlush()
并且glFinish()
会将所有缓冲操作推送到 OpenGL,以便可以确保它们都将被执行,不同之处在于glFlush()
立即返回 where as glFinish()
blocks 直到所有操作完成。
Having read the definitions, I figured that if I were to use glFlush()
that I would probably run into the problem of submitting more operations to OpenGL than it could execute. So, just to try, I swapped out my glFinish()
for a glFlush()
and lo and behold, my program ran (as far as I could tell), the exact same; frame rates, resource usage, everything was the same.
阅读定义后,我想如果我要使用glFlush()
它,我可能会遇到向 OpenGL 提交的操作多于它可以执行的问题。所以,只是为了尝试,我把我的换成了glFinish()
a glFlush()
,瞧,我的程序运行了(据我所知),完全一样;帧率,资源使用,一切都一样。
So I'm wondering if there's much difference between the two calls, or if my code makes them run no different. Or where one should be used vs. the other.
I also figured that OpenGL would have some call like glIsDone()
to check whether or not all the buffered commands for a glFlush()
are complete or not (so one doesn't send operations to OpenGL faster than they can be executed), but I could find no such function.
所以我想知道这两个调用之间是否有很大区别,或者我的代码是否使它们运行没有什么不同。或者应该在哪里使用一个而不是另一个。我还认为 OpenGL 会有一些调用,例如glIsDone()
检查 a 的所有缓冲命令glFlush()
是否完整(因此不会以比执行速度更快的速度向 OpenGL 发送操作),但我找不到这样的功能.
My code is the typical game loop:
我的代码是典型的游戏循环:
while (running) {
process_stuff();
render_stuff();
}
采纳答案by Malte Clasen
Mind that these commands exist since the early days of OpenGL. glFlush ensures that previous OpenGL commands must complete in finite time(OpenGL 2.1 specs, page 245). If you draw directly to the front buffer, this shall ensure that the OpenGL drivers starts drawing without too much delay. You could think of a complex scene that appears object after object on the screen, when you call glFlush after each object. However, when using double buffering, glFlush has practically no effect at all, since the changes won't be visible until you swap the buffers.
请注意,这些命令从 OpenGL 的早期就存在。glFlush 确保之前的 OpenGL 命令必须在有限的时间内完成(OpenGL 2.1 规范,第 245 页)。如果直接绘制到前端缓冲区,这将确保 OpenGL 驱动程序开始绘制时不会有太多延迟。当您在每个对象之后调用 glFlush 时,您可以想象一个复杂的场景,在屏幕上一个接一个地出现。但是,当使用双缓冲时,glFlush 实际上根本没有任何影响,因为在您交换缓冲区之前更改将不可见。
glFinish does not return until all effects from previously issued commands [...] are fully realized. This means that the execution of your program waits here until every last pixel is drawn and OpenGL has nothing more to do. If you render directly to the front buffer, glFinish is the call to make before using the operating system calls to take screenshots. It is far less useful for double buffering, because you don't see the changes you forced to complete.
glFinish在之前发出的命令 [...] 的所有效果都完全实现之前不会返回。这意味着您的程序的执行会在这里等待,直到绘制了每个最后一个像素并且 OpenGL 无事可做。如果直接渲染到前端缓冲区,glFinish 是在使用操作系统调用截取屏幕截图之前进行的调用。它对双缓冲的用处要小得多,因为您看不到被迫完成的更改。
So if you use double buffering, you probably won't need neither glFlush nor glFinish. SwapBuffers implicitly directs the OpenGL calls to the correct buffer, there's no need to call glFlush first. And don't mind stressing the OpenGL driver: glFlush will not choke on too many commands. It is not guaranteed that this call returns immediately(whatever that means), so it can take any time it needs to process your commands.
因此,如果您使用双缓冲,您可能既不需要 glFlush 也不需要 glFinish。SwapBuffers 隐式地将 OpenGL 调用定向到正确的缓冲区,无需先调用 glFlush。并且不要介意强调 OpenGL 驱动程序:glFlush 不会因太多命令而窒息。不保证此调用会立即返回(无论这意味着什么),因此它可能需要任何时间来处理您的命令。
回答by Andy Ross
As the other answers have hinted, there really is no good answer as per the spec. The general intent of glFlush()
is that after calling it, the host CPU will have no OpenGL-related work to do -- the commands will have been pushed to the graphics hardware. The general intent of glFinish()
is that after it returns, noremaining work is left, and the results should be available too all appropriate non-OpenGL APIs (e.g. reads from the framebuffer, screenshots, etc...). Whether that is really what happens is driver-dependent. The specification allows a ton of latitude as to what is legal.
正如其他答案所暗示的那样,根据规范确实没有好的答案。的一般意图glFlush()
是,在调用它之后,主机 CPU 将没有与 OpenGL 相关的工作要做——命令将被推送到图形硬件。的一般意图glFinish()
是在它返回后,没有剩余的工作剩下,并且结果应该也可用所有适当的非 OpenGL API(例如从帧缓冲区读取,屏幕截图等...)。这是否真的发生取决于驱动程序。该规范允许大量自由决定什么是合法的。
回答by Tara
I was always confused about those two commands too, but this image made it all clear to me:
Apparently some GPU drivers don't send the issued commands to the hardware unless a certain number of commands has been accumulated. In this example that number is 5.
The image shows various OpenGL commands (A, B, C, D, E...) that have been issued. As we can see at the top, the commands don't get issued yet, because the queue isn't full yet.
我也总是对这两个命令感到困惑,但是这张图片让我很清楚:
显然,除非积累了一定数量的命令,否则一些 GPU 驱动程序不会将发出的命令发送到硬件。在这个例子中,这个数字是5。
该图像显示了已发出的各种 OpenGL 命令(A、B、C、D、E...)。正如我们在顶部看到的,命令还没有发出,因为队列还没有满。
In the middle we see how glFlush()
affects the queued up commands. It tells the driver to send all queued up commands to the hardware (even if the queue isn't full yet). This doesn't block the calling thread. It merely signals the driver that we might not be sending any additional commands. Therefore waiting for the queue to fill up would be a waste of time.
在中间,我们看到如何glFlush()
影响排队的命令。它告诉驱动程序将所有排队的命令发送到硬件(即使队列尚未满)。这不会阻塞调用线程。它只是向驱动程序发出信号,表明我们可能不会发送任何其他命令。因此,等待队列填满将是浪费时间。
At the bottom we see an example using glFinish()
. It almost does the same thing as glFlush()
, except that it makes the calling thread wait till all commands have been processed by the hardware.
在底部,我们看到一个使用glFinish()
. 它几乎与 做同样的事情glFlush()
,除了它使调用线程等待直到所有命令都被硬件处理。
Image taken from the book "Advanced Graphics Programming Using OpenGL".
图片取自“使用 OpenGL 进行高级图形编程”一书。
回答by Bahbar
If you did not see any performance difference, it means you're doing something wrong. As some others mentioned, you don't need to call either, but if you do call glFinish, then you're automatically losing the parallelism that the GPU and CPU can achieve. Let me dive deeper:
如果您没有看到任何性能差异,则意味着您做错了什么。正如其他一些人提到的,您不需要调用它们,但是如果您调用 glFinish,那么您将自动失去 GPU 和 CPU 可以实现的并行性。让我深入探讨:
In practice, all the work you submit to the driver is batched, and sent to the hardware potentially way later (e.g. at SwapBuffer time).
在实践中,您提交给驱动程序的所有工作都是批处理的,并可能稍后(例如在 SwapBuffer 时间)发送到硬件。
So, if you're calling glFinish, you're essentially forcing the driver to push the commands to the GPU (that it batched till then, and never asked the GPU to work on), and stall the CPU until the commands pushed are completely executed. So during the whole time the GPU works, the CPU does not (at least on this thread). And all the time the CPU does its work (mostly batching commands), the GPU does not do anything. So yeah, glFinish should hurt your performance. (This is an approximation, as drivers may start having the GPU work on some commands if a lot of them were already batched. It's not typical though, as the command buffers tend to be big enough to hold quite a lot of commands).
因此,如果您正在调用 glFinish,您实际上是在强制驱动程序将命令推送到 GPU(直到那时它已批量处理,并且从未要求 GPU 处理),并停止 CPU,直到推送的命令完全执行。所以在 GPU 工作的整个过程中,CPU 没有(至少在这个线程上)。CPU 一直在工作(主要是批处理命令),GPU 不做任何事情。所以是的, glFinish 应该会损害你的表现。(这是一个近似值,因为如果许多命令已经批处理,驱动程序可能会开始让 GPU 处理某些命令。但这并不典型,因为命令缓冲区往往足够大以容纳相当多的命令)。
Now, why would you call glFinish at all then ? The only times I've used it were when I had driver bugs. Indeed, if one of the commands you send down to the hardware crashes the GPU, then your simplest option to identify which command is the culprit is to call glFinish after each Draw. That way, you can narrow down what exactly triggers the crash
现在,你为什么要调用 glFinish 呢?我唯一使用它的时候是当我有驱动程序错误时。事实上,如果您发送到硬件的命令之一使 GPU 崩溃,那么确定哪个命令是罪魁祸首的最简单选择是在每次 Draw 后调用 glFinish。这样,您可以缩小确切触发崩溃的范围
As a side note, APIs like Direct3D don't support a Finish concept at all.
附带说明一下,像 Direct3D 这样的 API 根本不支持 Finish 概念。
回答by starmole
glFlush really dates back to a client server model. You send all gl commands through a pipe to a gl server. That pipe might buffer. Just like any file or network i/o might buffer. glFlush only says "send the buffer now, even if it is not full yet!". On a local system this is almost never needed because a local OpenGL API is unlikely to buffer itself and just issues commands directly. Also all commands that cause actual rendering will do an implicit flush.
glFlush 实际上可以追溯到客户端服务器模型。您通过管道将所有 gl 命令发送到 gl 服务器。那个管道可能会缓冲。就像任何文件或网络 i/o 可能会缓冲一样。glFlush 只说“现在发送缓冲区,即使它还没有满!”。在本地系统上,这几乎是不需要的,因为本地 OpenGL API 不太可能自行缓冲,而只是直接发出命令。此外,所有导致实际渲染的命令都将进行隐式刷新。
glFinish on the other hand was made for performance measurement. Kind of a PING to the GL server. It roundtrips a command and waits until the server responds "I am idle".
另一方面, glFinish 用于性能测量。一种对 GL 服务器的 PING。它往返一个命令并等待服务器响应“我空闲”。
Nowadays modern, local drivers have quite creative ideas what it means to be idle though. Is it "all pixels are drawn" or "my command queue has space"? Also because many old programs sprinkled glFlush and glFinish throughout their code without reason as voodoo coding many modern drivers just ignore them as an "optimization". Can't blame them for that, really.
如今现代的本地司机对闲置意味着什么很有创意。是“绘制了所有像素”还是“我的命令队列有空间”?也因为许多旧程序在他们的代码中无缘无故地撒上了 glFlush 和 glFinish,因为巫毒编码许多现代驱动程序只是将它们作为“优化”忽略了。这真的不能怪他们。
So in summary: Treat both glFinish and glFlush as no ops in practice unless you are coding for an ancient remote SGI OpenGL server.
所以总而言之:除非您正在为古老的远程 SGI OpenGL 服务器编码,否则在实践中将 glFinish 和 glFlush 视为没有操作。
回答by AndiDog
Have a look here. In short, it says:
看看这里。简而言之,它说:
glFinish() has the same effect as glFlush(), with the addition that glFinish() will block until all commands submitted have been executed.
glFinish() 与 glFlush() 具有相同的效果,此外 glFinish() 将阻塞,直到所有提交的命令都执行完毕。
Another article describes other differences:
另一篇文章描述了其他差异:
- Swap functions (used in double-buffered applications) automatically flush the commands, so no need to call
glFlush
glFinish
forces OpenGL to perform outstanding commands, which is a bad idea (e.g. with VSync)
- 交换函数(用于双缓冲应用程序)自动刷新命令,因此无需调用
glFlush
glFinish
强制 OpenGL 执行未完成的命令,这是一个坏主意(例如使用 VSync)
To sum up, this means that you don't even need these functions when using double buffering, except if your swap-buffers implementation doesn't automatically flush the commands.
总而言之,这意味着您在使用双缓冲时甚至不需要这些函数,除非您的交换缓冲区实现不会自动刷新命令。
回答by GManNickG
There doesn't seem to be a way of querying the status of the buffer. There is this Apple extensionwhich could serve the same purpose, but it doesn't seem cross-platform (haven't tried it.) At it quick glance, it seems prior to flush
you'd push the fence command in; you can then query the status of that fence as it moves through the buffer.
似乎没有查询缓冲区状态的方法。有这个Apple 扩展可以达到同样的目的,但它似乎不是跨平台的(还没有尝试过)。乍一看,它似乎在flush
您将栅栏命令推入之前;然后,您可以在该围栏通过缓冲区时查询该围栏的状态。
I wonder if you could use flush
prior to buffering up commands, but prior to beginning to render the next frame you call finish
. This would allow you to begin processing the next frame as the GPU works, but if it's not done by the time you get back, finish
will block to make sure everything's in a fresh state.
我想知道您是否可以flush
在缓冲命令之前使用,但在开始渲染您调用的下一帧之前finish
。这将允许您在 GPU 工作时开始处理下一帧,但如果在您回来时还没有完成,finish
它将阻塞以确保一切都处于全新状态。
I haven't tried this, but I will shortly.
我还没有尝试过这个,但我很快就会尝试。
I have tried it on an old application that has pretty even CPU & GPU use. (It originally used finish
.)
我已经在 CPU 和 GPU 使用率相当均匀的旧应用程序上进行了尝试。(它最初使用finish
.)
When I changed it to flush
at end and finish
at begin, there were no immediate problems. (Everything looked fine!) The responsiveness of the program increased, probably because the CPU wasn't stalled waiting on the GPU. Definitely a better method.
当我将其更改flush
为结束和finish
开始时,没有立即出现问题。(一切看起来都很好!)程序的响应能力提高了,可能是因为 CPU 没有停止等待 GPU。绝对是更好的方法。
For comparison, I removed finished
from the start of the frame, leaving flush
, and it performed the same.
为了进行比较,我finished
从帧的开头删除了,离开了flush
,它的表现是一样的。
So I would say use flush
and finish
, because when the buffer is empty at the call to finish
, there is no performance hit. And I'm guessing if the buffer were full you should want to finish
anyway.
所以我会说使用flush
and finish
,因为当调用 时缓冲区为空时finish
,不会影响性能。而且我猜如果缓冲区已满,您finish
无论如何都应该想要。
回答by anon
The question is: do you want your code to continue running while the OpenGL commands are being executed, or only to run afteryour OpenGL commands has been executed.
问题是:您希望代码在 OpenGL 命令执行时继续运行,还是仅在OpenGL 命令执行后运行。
This can matter in cases, like over network delays, to have certain console output only afterthe images have been drawn or the such.
这在某些情况下可能很重要,例如网络延迟,仅在绘制图像后才具有某些控制台输出等。