gpt4 book ai didi

webgl - WebGL:异步操作?

转载 作者:行者123 更新时间:2023-12-04 23:23:59 28 4
gpt4 key购买 nike

我想知道是否可以利用WebGL进行任何异步调用?

我研究了Spec v1和Spec v2,他们什么都没提及。在V2中,有一种WebGL查询机制,我认为这不是我想要的。

在网络上进行搜索并没有确定的定义。有此示例,尚不清楚同步版本和异步版本如何不同。 http://toji.github.io/shader-perf/

最终,我希望能够异步实现所有这些功能:


readPixels
texSubImage2D和texImage2D
着色器编译
程序链接
画???


有一个glFinish操作,其文档显示:“直到所有以前调用的GL命令的效果完成,才返回。”对我来说,这意味着可以通过调用Finish()等待异步操作?

网络上的一些帖子建议,调用getError()也会强制一些同步性,这并不是每次调用后都希望做的事情。

最佳答案

这取决于您对异步的定义。

在Chrome中(Firefox可能现在也这样做吗?不确定)。 Chrome浏览器通过JavaScript单独运行所有GPU代码。这意味着您的命令正在异步运行。甚至OpenGL本身也被设计为异步的。函数(WebGL / OpenGL)将命令插入命令缓冲区。这些由其他线程/进程执行。您告诉OpenGL“嘿,我有新命令要执行!”通过调用gl.flush。它异步执行这些命令。如果不调用gl.flush,则在发出太多命令时会定期为您调用。假设您已调用画布的任何渲染命令(gl.drawXXX,gl.clear),当前JavaScript事件退出时也会调用该方法。

从这个意义上说,关于WebGL的一切都是异步的。如果您不查询某些内容(gl.getXXX,gl.readXXX),则表示正在处理(绘制)与JavaScript不同步的内容。 WebGL使您可以在与CPU分开运行之后访问GPU。

了解这种在Chrome中利用它的方法是通过提交着色器来异步编译着色器

for each shader
s = gl.createShader()
gl.shaderSource(...);
gl.compileShader(...);
gl.attachShader(...);
gl.linkProgram(...)
gl.flush()


GPU进程现在将编译您的着色器。因此,例如,在250ms之后,您才开始询问它是否成功并查询位置,然后,如果花费不到250ms的时间来编译和链接着色器,则它们都是异步发生的。

在WebGL2中,至少有一个更清晰的异步操作,即遮挡查询,其中WebGL2可以告诉您为一组绘制调用绘制了多少像素。如果未抽签,则您的抽签被遮挡。要获得答案,您需要定期查看答案是否准备就绪。通常,您检查下一帧,而实际上WebGL规范要求答案直到下一帧才可用。

否则,目前(2018年8月),没有明确的异步API。

更新资料

HankMoody提出了 texImage2D是同步的注释。同样,这取决于您对异步的定义。添加命令及其数据需要花费时间。像 gl.enable(gl.DEPTH_TEST)这样的命令只需添加2-8个字节。像 gl.texImage2D(..., width = 1024, height = 1024, RGBA, UNSIGNED_BYTE)这样的命令必须添加4meg!。一旦上传了4meg,其余的都是异步的,但是上传需要时间。这两个命令是相同的,只是添加2-8个字节比添加4meg所需的时间少得多。

更清楚的是,上传4兆之后,许多其他事情会异步发生。该驱动程序被称为4兆。驱动程序复制该4Meg。驱动程序计划稍后使用该4meg,因为如果纹理已在使用中,它无法立即上传数据。要么立即将其上传到新区域,然后在实际使用该新数据的绘制调用之前交换纹理指向的内容。其他驱动程序只是复制数据并存储它,然后等到在绘制调用中使用纹理来实际更新纹理。这是因为texImage2D具有疯狂的语义,您可以按任何顺序上传不同大小的mips,因此驱动程序直到绘制时间之前才知道GPU内存中实际需要什么,因为它不知道您要调用texIamge2D的顺序。本段中提到的所有这些东西都是异步发生的。

但这确实带来了更多信息。

gl.texImage2D和相关命令必须完成大量工作。一种是他们必须遵守 UNPACK_FLIP_Y_WEBGLUNPACK_PREMULTIPLY_ALPHA_WEBGL,因此他们需要复制多个数据来翻转或预乘它。其次,如果向他们传递视频,画布或图像,则它们可能必须进行大量转换,甚至从源中重新解析图像,尤其是根据 UNPACK_COLORSPACE_CONVERSION_WEBGL。这是否以某种异步方式发生取决于浏览器。由于您无权直接访问图像/视频/画布,因此浏览器可能会执行所有异步操作,但必须以一种或另一种方式完成所有工作。

为了完成ASYNC的大部分工作,添加了 ImageBitmap API。像大多数Web API一样,它的规格不足,但是您的想法是先执行 fetch(异步)。然后,您请求创建一个 ImageBitmap并为其提供颜色转换,翻转,预乘alpha的选项。这也会异步发生。然后,将结果传递给 gl.texImage2D,希望浏览器能够在进入最后一步之前完成所有繁重的工作。

例:



// note: mode: 'cors' is because we are loading
// from a different domain

async function main() {
const response = await fetch('https://i.imgur.com/TSiyiJv.jpg', {mode: 'cors'})
if (!response.ok) {
return console.error('response not ok?');
}
const blob = await response.blob();
const bitmap = await createImageBitmap(blob, {
premultiplyAlpha: 'none',
colorSpaceConversion: 'none',
});

const gl = document.querySelector("canvas").getContext("webgl");

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
{
const level = 0;
const internalFormat = gl.RGBA;
const format = gl.RGBA;
const type = gl.UNSIGNED_BYTE;
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
format, type, bitmap);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
}

const vs = `
uniform mat4 u_worldViewProjection;
attribute vec4 position;
attribute vec2 texcoord;
varying vec2 v_texCoord;

void main() {
v_texCoord = texcoord;
gl_Position = u_worldViewProjection * position;
}
`;
const fs = `
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D u_tex;
void main() {
gl_FragColor = texture2D(u_tex, v_texCoord);
}
`;

const m4 = twgl.m4;
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 2);
const uniforms = {
u_tex: tex,
};

function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);

const fov = 30 * Math.PI / 180;
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.5;
const zFar = 10;
const projection = m4.perspective(fov, aspect, zNear, zFar);
const eye = [1, 4, -6];
const target = [0, 0, 0];
const up = [0, 1, 0];

const camera = m4.lookAt(eye, target, up);
const view = m4.inverse(camera);
const viewProjection = m4.multiply(projection, view);
const world = m4.rotationY(time);

uniforms.u_worldViewProjection = m4.multiply(viewProjection, world);

gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);

requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();

body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }

<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>





不幸的是,这仅适用于2018年8月起的Chrome。 Firefox bug is here。我不知道的其他浏览器。

关于webgl - WebGL:异步操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51710067/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com