6

那么当你调用opengl函数时,比如glDraw或者gLBufferData,是否会导致程序的线程停止并等待GL完成调用呢?

如果不是,那么 GL 如何处理调用诸如 glDraw 之类的重要函数,然后立即更改影响绘图调用的设置?

4

2 回答 2

6

不,他们(大部分)没有。大多数 GL 函数在使用时被缓冲,稍后实际执行。这意味着您不能将 CPU 和 GPU 视为同时工作的两个处理器。通常,CPU 会执行一堆缓冲的 GL 函数,一旦它们被传递到 GPU,这个函数就会执行它们。这意味着您无法仅通过比较执行特定 GL 函数之前和之后的时间来可靠地控制执行特定 GL 函数所需的时间。

如果你想这样做,你需要首先运行一个 glFinish() 以便它实际上会等待所有以前缓冲的 GL 调用执行,然后你可以开始计数,执行你想要基准的调用,再次调用 glFinish 到确保这些调用也被执行,然后完成基准测试。

另一方面,我说“大部分”。这是因为读取函数实际上需要与 GPU 同步以显示真实结果,因此,在这种情况下,它们会等待并冻结主线程。

编辑:我认为解释本身回答了你第二个问的问题,但以防万一:所有调用都被缓冲的事实使得可以先完成平局,然后为连续调用更改设置

于 2013-03-02T19:24:02.883 回答
1

它严格取决于相关的 OpenGL 调用和 OpenGL 状态。当您进行 OpenGL 调用时,实现首先在内部将它们排队,然后与调用程序的执行异步执行它们。OpenGL 的一个重要概念是同步点。这些是工作队列中的操作,需要 OpenGL 调用阻塞,直到满足某些条件。

OpenGL 对象(纹理、缓冲区对象等)是纯粹抽象的,并且通过规范客户端程序中对象的句柄始终指向数据,该对象在调用 OpenGL 函数时引用该对象。所以以这个序列为例:

glBindTexture(GL_TEXTURE_2D, texID);

glTexImage2D(..., image_1);
draw_textured_quad();

glTexImage2D(..., image_2);
draw_textured_quad();

第一个draw_textured_quad可能会在绘制任何东西之前很久就返回。然而,通过调用,OpenGL 创建了一个对纹理当前保存的数据的内部引用。因此,当第二次调用 glTexImage2D 时,这可能发生在第一个四边形绘制之前,OpenGL 必须在内部创建一个辅助纹理对象,该对象将成为纹理texID并供draw_textured_quad. 如果glTexSubImage2D被调用,它甚至必须制作它的修改副本。

OpenGL 调用只会阻塞,如果调用的结果修改了客户端内存并且依赖于之前的 OpenGL 调用生成的数据。换句话说,当进行 OpenGL 调用时,OpenGL 实现会在内部生成一个依赖树来跟踪什么依赖什么。当一个同步点必须阻塞时,它至少会阻塞,直到满足所有依赖项。

于 2013-03-02T19:33:21.287 回答