WebGL - 何时调用gl.Flush?

Alv*_*par 3 opengl-es webgl

我今天才注意到这个方法,Flush()是可用的.无法找到有关它的详细文档.

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

gma*_*man 9

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

例如,由于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);
Run Code Online (Sandbox Code Playgroud)

此时,所有命令可能都位于命令队列中,尚未执行任何操作.所以,发一个同花顺

gl.flush();
Run Code Online (Sandbox Code Playgroud)

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

setTimeout(continueLater, 1000);  // continue 1 second later
Run Code Online (Sandbox Code Playgroud)

现在做其他事情,如设置页面或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...
}
Run Code Online (Sandbox Code Playgroud)

我相信谷歌地图使用这种技术,因为他们必须编译许多非常复杂的着色器,他们希望页面保持响应.如果他们调用gl.compileShadergl.linkProgram立即调用其中一个查询函数gl.getShaderParameter,gl.getProgramParameter或者gl.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告诉系统"嘿,我添加的那些命令,请确保开始执行它们".因此,您可能决定gl.flush在每1000个命令之后调用.

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

对不起,这可能是太多的信息:p

  • 感谢这里的更多信息,我不明白接受的答案 (2认同)

Tom*_*mmy 5

假设它在语义上等同于经典的 GLglFlush那么不,它几乎永远不会被需要。OpenGL 是一个异步 API — 您将要完成的工作排入队列,并在可以完成的时候完成。glFlush仍然是异步的,但强制任何累积的缓冲区尽可能快地清空,无论这可能需要多长时间;它基本上是对司机说“如果您出于任何原因打算保留任何东西,请不要”。

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

根据 WebGL 模型,任何具有双缓冲或后缓冲的平台都将自动确保缓冲及时进行。排队有助于提高性能,但不应产生负面的可观察结果。因此,您无需手动执行任何操作。

如果您拒绝刷新并且即使您在语义上可能应该刷新也没有严格需要,但无论如何您的图形都是基于实时显示的,那么您可能会遭受最糟糕的几分之一秒的延迟。

  • 不用担心积分。我只是想确保我们不会在最高投票和接受的答案中得到不正确的信息。感谢您修复它。 (2认同)