从 Web Worker 内部使用 WebGL:可能吗?如何?
我打开这个矩阵乘法基准测试,我的浏览器 (Firefox 7.0.1) 冻结了,直到基准测试完成(我在旧的 Asus EeePC 1000H 中打开该页面)。
我听说网络工作者的发明是为了将处理与显示网页分开。是否可以利用 Web Workers API 使 WebGL 不会停止整个 Web 浏览器?
I opened this matrix multiplication benchmarks and my browser (Firefox 7.0.1) froze until the benchmarks finished (I opened the page in an old Asus EeePC 1000H).
I heard that web workers were invented to separate processing from displaying the web pages. Is it possible to make use of the Web Workers API to make WebGL not stall the whole web browser ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为了清楚起见:您链接到的基准测试根本不使用 WebGL。 (我应该知道,是我写的。)对于特定的基准测试,您现在绝对可以在 Web Worker 中运行它,而且效果非常好。
(有趣的事实 - 当构建基准测试时,Web Workers 不支持 TypedArrays,并且由于大多数矩阵库都依赖于当时在 Worker 中运行它是不切实际的。此后这个问题已得到修复。)
无论如何,回答你原来的问题:不,WebGL 不能在工作线程中运行。核心阻碍是,为了获取 WebGL 上下文,您需要在画布元素上调用
getContext
。 Web Workers 明确禁止 DOM 访问(顺便说一句,这是一件好事!),因此您将永远无法从 Worker 访问 WebGL。但这并不像您想象的那么糟糕。其一,考虑到大多数 3D 渲染实际上都发生在不同的线程中。具体来说,是在 GPU 上运行的一大堆线程。浏览器的唯一部分是告诉您的图形驱动程序“嘿!开始使用这些数据渲染一些三角形!”然后它继续前进,而不等待三角形被实际渲染。因此,虽然绘制命令必须从主进程执行,但阻塞该进程所花费的时间(通常)非常少。
当然,如果您正在编写实时游戏,那么这不会占用您大量的时间。你有动画、物理、人工智能、碰撞检测、寻路……其中涉及很多非图形任务,如果你允许的话,它们会耗尽你的 CPU。在某些情况下(动画),它通常只是大量的矩阵数学,就像您链接到的基准一样!然而,对我们来说幸运的是,这种类型的处理可以在 Worker 中完成,并且我们需要与主线程通信的只是渲染场景所需的数据。
是的,这在同步和数据传输方面带来了一些挑战,但总的来说,这比在我们尝试模拟这 500 个盒子碰撞时锁定您的浏览器要好得多。
For the sake of clarity: the benchmark that you linked to does not use WebGL at all. (I should know, I wrote it.) And in the case of that particular benchmark you absolutely could run it in a Web Worker now and it would be perfectly fine.
(Fun fact - Web Workers didn't support TypedArrays when the benchmark was built, and since most of the matrix libraries rely on that it was impractical to run it in a Worker at that time. That has since been fixed.)
Anyway, to answer your original question: No, WebGL cannot run in a worker. The core blocker to this is that in order to get a WebGL context you need to call
getContext
on a canvas element. Web Workers explicitly disallow DOM access (which is a good thing, BTW!) and as such you'll never be able to access WebGL from a worker.But that's not as bad as you might think. For one, consider that most all 3D rendering is actually happening in a different thread anyway. Specifically, a whole bunch of threads running on your GPU. The only part the browser has in it is to tell your graphics driver "Hey! Start rendering some triangles using this data!" and then it moves on without waiting for the triangles to actually be rendered. As such, while the draw commands must be executed from the main process, the time it spends blocking that process is (usually) very little.
Of course, that's not what's going to eat up a bunch of your time if you were coding a realtime game. You've got animations, physics, AI, collision detection, pathfinding... there's a lot of non-graphical tasks involved that will eat your CPU alive if you let them. In some case (animation), it's usually just gobs and gobs of matrix math, just like the benchmark you linked to! Fortunately for us, however, that type of processing CAN be done in a Worker, and all we need to communicate back to the main thread is the data required to render the scene.
Yes, this introduces some challenges in terms of synchronization and data transfer, but on the whole it will be vastly preferable to locking up your browser while we try and simulate those 500 boxes colliding.
是的,在火狐浏览器上!
https://hacks.mozilla.org/2016/01/ webgl-off-the-main-thread/
Yes, on Firefox!
https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/
默认情况下,您不能在 Web Worker 中使用 WebGL,正如 Toji 所解释的那样。
您可以查看 WebGLWorker 这是一个库,可让您在 Web Worker 中执行 WebGL 操作,方法是透明地将命令代理到主线程。
这是一个很好的
By default you can't use WebGL in a Web Worker as Toji explained.
You can check out WebGLWorker which is a library that lets you do WebGL stuff in a Web Worker, by transparently proxying commands to the main thread.
Here is a nice blog post that explains how it works.