WebGL - 何时调用gl.Flush?

时间:2014-06-17 22:04:28

标签: opengl-es webgl

我今天刚才注意到这个方法,Flush()可用。 无法找到详细的文档。

这到底是做什么的? 这需要吗?

2 个答案:

答案 0 :(得分:8)

WebGL中的

gl.flush确实有它的用途,但它是驱动程序和浏览器特有的。

例如,因为Chrome的GPU架构是多进程的,所以可以执行此操作

function var loadShader = function(gl, shaderSource, shaderType) {
  var shader = gl.createShader(shaderType);
  gl.shaderSource(shader, shaderSource);
  gl.compileShader(shader);
  return shader;
}

var vs = loadShader(gl, someVertexShaderSource, gl.VERTEX_SHADER);
var fs = loadShader(gl, someFragmentShaderSource, FRAGMENT_SHADER);
var p = gl.createProgram();
gl.attachShader(p, vs);
gl.attachShader(p, fs);
gl.linkProgram(p);

此时所有命令都可能位于命令中 没有执行它们的队列。所以,发出一个刷新

gl.flush();

现在,因为我们知道编译和链接程序的速度很慢,具体取决于它们的大小和复杂程度所以我们可以等待一段时间再尝试使用它们并执行其他操作

setTimeout(continueLater, 1000);  // continue 1 second later

现在做其他事情,比如设置页面或UI或其他东西

1秒后continueLater将被调用。我们的着色器很可能完成了编译和链接。

function continueLater() {

  // check results, get locations, etc.
  if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS) ||
      !gl.getShaderParameter(fs, gl.COMPILE_STATUS) ||
      !gl.getProgramParameter(p, gl.LINK_STATUS)) {
     alert("shaders didn't compile or program didn't link");
     ...etc... 
   }

   var someLoc = gl.getUniformLocation(program, "u_someUniform");
   ...etc...
}

我相信谷歌地图使用这种技术,因为他们必须编译许多非常复杂的着色器,他们希望页面保持响应。如果他们致电gl.compileShadergl.linkProgram并立即调用其中一个查询函数,例如gl.getShaderParametergl.getProgramParametergl.getUniformLocation,那么在首次验证着色器时程序会冻结然后发送给驱动程序进行编译。通过不立即进行查询但等待片刻,他们可以避免在UX中暂停。

不幸的是,这仅适用于Chrome AFAIK,因为其他浏览器不是多进程的,我相信所有驱动程序都会同步编译/链接。

可能还有其他原因要调用gl.flush,但同样是特定于驱动程序/操作系统/浏览器。举个例子,假设您要绘制1000个对象,并且这样做需要5000个webgl调用。它可能需要更多,但只需要一个数字就可以选择5000. 4个调用gl.uniformXXX和1个调用gl.drawXXX每个对象。

这些呼叫中的所有5000个都可能适合浏览器(Chrome)或驱动程序的命令缓冲区。如果没有刷新,他们将不会开始执行,直到浏览器为您发出gl.flush(这样做它可以在屏幕上合成您的结果)。这意味着GPU可能会在您发出1000,然后是2000,然后是3000等命令时处于空闲状态,因为它们只是位于缓冲区中。 gl.flush告诉系统“嘿,我添加的那些命令,请确保开始执行它们”。因此,您可能决定在每1000个命令之后调用gl.flush

问题是gl.flush不是免费的,否则你会在每个命令后调用它以确保它尽快执行。最重要的是,每个驱动程序/浏览器以不同的方式工作。在一些司机呼叫gl.flush每隔几百或1000个WebGL呼叫可能是一个胜利。在其他方面,这可能是浪费时间。

抱歉,这可能是太多的信息:p

答案 1 :(得分:4)

假设它在语义上等同于经典GL glFlush,那么它几乎不会被要求。 OpenGL是一个异步API - 您可以将工作排队,并在可能的情况下完成。 glFlush仍然是异步的,但强制任何累积的缓冲区尽可能快地清空,无论多长时间都可以;它基本上对司机说“如果你打算因任何原因收回任何东西,请不要”。

它通常仅用于与OpenGL和该系统上的其他显示机制的耦合相关的特定于平台的原因。例如,一个平台可能需要订购所有GL工作,以便在将要绘制到的容器移动到屏幕之前不排队。另一个可能允许从后台线程到主OpenGL上下文的资源管道,但不保证它们必须可用于后续调用,直到你刷新(例如,如果多线程最终创建两个单独的队列,否则可能会有一个然后刷新可能会在两者之间插入同步障碍。

根据WebGL模型,任何具有双缓冲区或后缓冲的平台都将自动确保缓冲区及时进行。排队是为了帮助提高绩效,但不应产生负面的可观察后果。所以你不必手动做任何事情。

如果你拒绝刷新并且即使你在语义上也不应该严格要求,但你的图形无论如何都是以实时显示为基础的,那么你可能会在最坏的情况下遭受一秒钟的痛苦延迟。