所以当你调用opengl函数时,比如glDraw或gLBufferData,是否会导致程序的线程停止并等待GL完成调用?
如果没有,那么GL如何处理调用像glDraw这样的重要函数,然后立即改变一个影响绘制调用的设置?
答案 0 :(得分:6)
不,他们(大部分)没有。大多数GL函数在使用时进行缓冲,并在以后实际执行。这意味着您无法将CPU和GPU视为两个同时协同工作的处理器。通常,CPU执行一系列缓冲的GL函数,一旦它们被传递到GPU,它就会执行它们。这意味着只需比较执行前后的时间,就无法可靠地控制特定GL函数执行所需的时间。
如果你想这样做,你需要首先运行一个glFinish(),这样它实际上会等待所有以前缓冲的GL调用执行,然后你可以开始计数,执行你想要基准测试的调用,调用再次glFinish以确保执行这些调用,然后完成基准测试。
另一方面,我说“大多数”。这是因为读取函数实际上需要与GPU同步才能显示实际结果,因此,在这种情况下,它们会等待并冻结主线程。
编辑:我认为解释本身会回答你问的第二个问题,但是以防万一:所有调用都被缓冲的事实使得抽奖可以先完成,然后为了成功的调用而改变设置
答案 1 :(得分: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实现在内部生成依赖树,以跟踪依赖于什么的依赖树。当同步点必须阻塞时,它至少会阻塞,直到满足所有依赖关系。