我今天注意到有一个叫做Flush()的方法,但没有找到详细的文档。
它具体是做什么的?需要吗?
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);
此时,所有命令可能都在命令队列中等待执行,因此,请执行一次刷新操作
gl.flush();
现在,由于我们知道编译和链接程序的速度取决于其大小和复杂程度,因此我们可以等待一段时间再尝试使用它们并做其他事情。
setTimeout(continueLater, 1000); // continue 1 second later
现在可以做一些其他的事情,比如设置页面或用户界面等。
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.compileShader
或 gl.linkProgram
并立即调用其中一个查询函数,如 gl.getShaderParameter
、gl.getProgramParameter
或 gl.getUniformLocation
,那么程序将会在首次验证着色器并将其发送到驱动程序进行编译时冻结。通过不立即进行查询而等待一段时间,他们可以避免 UX 中的暂停。gl.flush
,但这非常依赖于驱动程序/操作系统/浏览器。例如,假设您将要绘制 1000 个对象,并且需要进行 5000 次 WebGL 调用才能完成。它可能需要更多,但只是为了有一个数字,我们选择了 5000。每个对象需要 4 次对 gl.uniformXXX
的调用和 1 次对 gl.drawXXX
的调用。gl.flush
命令(这样它就可以在屏幕上组合您的结果)。这意味着 GPU 可能会空闲,而您则发出 1000、2000、3000 等命令,因为它们只是停留在缓冲区中。gl.flush
告诉系统“嘿,我添加了那些命令,请确保开始执行它们”。因此,您可能会决定在每个 1000 个命令之后调用一次 gl.flush
。gl.flush
并不是免费的,否则您会在每个命令之后立即调用它,以确保尽快执行。此外,每个驱动程序/浏览器的工作方式都不同。在某些驱动程序上,每隔几百或几千个 WebGL 调用调用一次 gl.flush
可能是一个好选择。在其他驱动程序上,这可能是浪费时间。glFlush
,那么几乎不需要。OpenGL是异步API-您排队等待要完成的工作,并在可以完成时完成。 glFlush
仍然是异步的,但会尽快清空任何累积的缓冲区,无论需要多长时间;它基本上告诉驱动程序“如果您计划因任何原因而保留任何内容,请不要这样做”。glFlush()
不会阻塞,直到工作完成。它只保证工作将在有限的时间内执行。你所描述的是 glFinish()
的行为。 - Reto Koradi