Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WebGL Support #108

Open
anvaka opened this issue Feb 5, 2018 · 42 comments
Open

Add WebGL Support #108

anvaka opened this issue Feb 5, 2018 · 42 comments

Comments

@anvaka
Copy link

anvaka commented Feb 5, 2018

Hello,

I spent all day experimenting and got WebGL working with headless shell. See the thumbnails here: https://www.reddit.com/r/pplay/ - they are rendered by lambda function from webgl scene.

To enable WebGL:

  1. I built osmesa using this script: https://github.com/devernay/osmesa-install . I changed disable_shared to enable_shared (line 534) to create libOSMesa32.so file). On EC2 instance, then final file was called libMangledOSMesa32 - just copy it next to the headless chrome binary as libosmesa.so.
  2. Remove disable-gpu flag, and tweak serverless-plugin-chrome, so that libosmesa.so is included into distribution.

PS: I don't remember whether I used headless_shell from this repository.It might be from https://github.com/universalbasket/aws-lambda-chrome But still - the WebGL in AWS lambda is possible, and I'm very happy to share it :).

@adieuadieu
Copy link
Owner

adieuadieu commented Feb 6, 2018

Hi @anvaka — That's interesting. When building chromium from source, it also produces a libosmesa.so shared library. I just don't include it as it was my understanding that WebGL wasn't yet supported by the headless_shell. But, perhaps this is no longer the case!

@vsantosu
Copy link

@anvaka do you have a repo containing a working setup for running webgl on AWS lambda? I'm trying to do the same thing without luck :(

@pjsier
Copy link

pjsier commented Mar 2, 2018

I just got this running using the steps @anvaka provided. Not sure if it's enough to just include a libosmesa.so binary in the repo or if you'd want to build that at the same time as the Chrome binary, but I'm happy to try and put together a pull request with a little guidance.

@vsantosu
Copy link

vsantosu commented Mar 2, 2018

Yep, I can confirm, I got it working as well. The best option is to get the headless_shell binary and the libOSMesa.so in the AWS redHat distro and ship them together to the lambda. Note that all data paths needs to point to /tmp, otherwise it will crash because of write permissions. The webgl version Mesa provides is wegbl1 but it does the work, pretty slow but works.

@cammanderson
Copy link

cammanderson commented Mar 7, 2018

Hi Guys,

I'm still having trouble, so I'm hoping someone could point me in the right direction.

  • I installed the mesa-libOSMesa package on an Amazon Linux platform
  • Obtained the .so file, and copied this into the /node_modules/serverless-chrome/lambda/dist folder as libosmesa.so
  • I modified the bundle dist file and hobbled out the --disable-gpu
  • I added to the flags; --use-gl=osmesa

Deploying it I still can't see rendered webgl content. Is there a step I am missing?

Cheers
Cam

@vsantosu
Copy link

vsantosu commented Mar 7, 2018

To anyone looking for a working combination of Mesa and Headless shell for AWS, these are the binaries, it provides pretty slow webgl V1, but it works. Hope it helps!

Headless Shell Mesa AWS Lambda

Remember to put in your flags:

[ '--use-gl=osmesa', '--enable-webgl', '--ignore-gpu-blacklist', '--homedir=/tmp', '--single-process', '--data-path=/tmp/data-path', '--disk-cache-dir=/tmp/cache-dir' ]

Otherwise it will crash due to write permissions.

@mvoropaiev
Copy link

mvoropaiev commented Jun 11, 2018

Hello,
@vsantosu can you please share binaries again (the link is 404 at the moment)?
Also after playing around I think I got chromium to render webgl content with screenshot function, but when printing to PDF WebGL areas appears to be blank (found a similar issue puppeteer/puppeteer#1731 but nothing helps), does anyone faced this issue?
Thanks.

@mvoropaiev
Copy link

mvoropaiev commented Jun 12, 2018

If anyone had the same PDF issue, rolling back to 64.0.3282.167 (instead of latest stable 67.0.3396.79 or dev 69.0.3452.0 ) solved it for me.

@whyvez
Copy link

whyvez commented Jun 14, 2018

Has anyone had experience using swiftshader instead of mesa when no GPU available?

@rthomps7
Copy link

@vsantosu

I was hoping you still had that build somewhere. @mvoropaiev pointed out the link doesn't work.

I tried what @anvaka suggested without any luck. I have a zip with both headless_shell and libosmesa.so in there. The headless_shell works, but things fail with webgl.

Here are my CLI args:

args: [
              '--use-gl=osmesa',
              '--enable-webgl',
              '--hide-scrollbars',
              '--mute-audio',
              '--no-sandbox',
              '--single-process',
              '--disable-breakpad',
              '--ignore-gpu-blacklist',
              '--homedir=/tmp',
              '--data-path=/tmp/data-path',
              '--disk-cache-dir=/tmp/cache-dir'
]

I'm actually firing this up with Puppeteer. The same command works locally, but I get errors on the lambda. My lambda works fine for non-webgl stuff.

@vsantosu
Copy link

Sorry for the broken link guys. I re-uploaded the zip here:

It has the libosmesa.so already in the directory, just point Puppeteer to it and everything should work fine.

Dropbox Link

Disclaimer: I ended up using Software Based Rendering using array buffers(Threejs) because Mesa rendering is slow as a asphalt serum. Lambda CPU is pretty fast, so my rendering time went down from minutes to seconds(30 or less).

@rthomps7
Copy link

@vsantosu

Thanks!. This is helpful

On a sidenote, do you have any idea how to get swiftshader-webgl on a lambda? Or if it's possible?

I'm trying to render a mapbox map on a lambda, and I'm really not having luck.

@vsantosu
Copy link

vsantosu commented Jul 26, 2018

@rthomps7 I haven't deal with swiftshader yet, but if you get it working let me know! What I do is launch a Lambda EC2 image instance, compile everything there with static linking, and then try to get a screenshot of some Webgl render. To double check I try to use the static compiled library in a fresh CentOS VM locally.

@vsantosu
Copy link

@rthomps7 did you had any luck trying swift shader? I'm searching online but without luck. I think it is possible to build headless chrome with swiftshader enabled.

@vsantosu
Copy link

vsantosu commented Aug 20, 2018

What about adding the following line after: build flags?

echo 'enable_swiftshader = true' >> out/Headless/args.gn && \

Afterwards a quick test can be done by adding:

--use-gl=swiftshader

In chromium command line arguments.

@rthomps7
Copy link

rthomps7 commented Aug 20, 2018 via email

@adieuadieu
Copy link
Owner

I can try doing a build with enable_swiftshader if someone else can help test the resulting binary on aws lambda.

@apalchys
Copy link

if someone else can help test the resulting binary on aws lambda

@adieuadieu I could easily to do it tomorrow morning my time

@vsantosu
Copy link

@adieuadieu I volunteer to that. I already have some experiments setup there, I just need the binary to replace.

@adieuadieu
Copy link
Owner

adieuadieu commented Aug 20, 2018

Thank you! I've started a build. If it builds successfully, I'll provide a link to the binary in the morning (UTC+2).

@adieuadieu
Copy link
Owner

OK; binary is available here. It's also available in a Docker image: adieuadieu/headless-chromium-for-aws-lambda:experimental-swiftshader

@apalchys
Copy link

@adieuadieu it seems WebGL doesn't work with the provided binary in my case.

@vsantosu
Copy link

@adieuadieu it does not seems like it is working for me either... I have not build headless chrome for Unix yet, but in Windows, chromium comes with a directory called swiftshader with two binaries:

  • libEGL.dll
  • libGLESv2.dll

I guess that for a lambda build will be something like:

  • libEGL.o
  • libGLESv2.o

If you can find some files like those in the build directory, we need to provide those in the same directory as headless_chrome binary at the time of launching with:

--use-gl=swiftshader

Which is the case with MESA lib.

@adieuadieu
Copy link
Owner

@vsantosu ah shoot. you're right. I'll get you those library binaries, as well. Need to do another build, though. The EC2 instance I built on was terminated.

@apalchys
Copy link

apalchys commented Aug 21, 2018

i've built Chromium using this instruction

Here are the output files:
headless_shell
swiftshader/libEGL.so
swiftshader/libGLESv2.so

They works for me and WebGL renders on the page. Unfortunately I didn't notice any benefits in comparison with osmesa - almost the same rendering time.

@cammanderson
Copy link

cammanderson commented Aug 21, 2018 via email

@vsantosu
Copy link

Great! Thanks,

I will try some benchmarks tonight as well. Last time I tried MESA it took about 3 minutes to render some Threejs scene with lights. We also need to check if swiftshader takes advantage of parallelism, if so in AWS lambda 1 core environment there will be not much difference.

@rthomps7
Copy link

@vsantosu - any luck?

@vsantosu
Copy link

@rthomps7 unfortunately not :(... I tried to setup the provided build by @apalchys but it does not seems to work for me in AWS Lambda...

@apalchys , did you got to tried in an actual AWS lambda function or just docker? If so, what is your directory organization(do you leave the .o files for swiftshader in the /swiftshader directory or next to the headless chrome binary?). Also, can you provide your command line flags?

Whenever I try to launch it, it does not even load the page. The build provided by @adieuadieu works for me and is pretty lightweight but I don't have the swiftshader binaries, I don't dare to mix them with the ones provided by @apalchys. I'm curious what version of WebGL is reported when using swiftshader....

@apalchys
Copy link

@vsantosu actual AWS lambda. I will try to create a simple working repo for AWS Lambda by tomorrow

@vsantosu
Copy link

Thanks so much, @apalchys !

@apalchys
Copy link

@vsantosu

I've created a repo:
https://github.com/apalchys/lambda-puppeteer-webgl-swiftshader

Also here is you can find zipped lambda code (please note it is over 50mb and you need to use s3 to upload):
https://s3-eu-west-1.amazonaws.com/apalchys-public/lambda-puppeteer-webgl-swiftshader.zip

and here is a working demo which returns a screenshot of https://get.webgl.org/ page
https://jkkpu18gue.execute-api.eu-west-1.amazonaws.com/demo/lambda-puppeteer-webgl-swiftshader-demo

@vsantosu
Copy link

Thanks so much @apalchys, I will be testing and uploading some benchmarks tonight!

@apalchys
Copy link

Btw, this issue was marked as “Fixed” yesterday: https://bugs.chromium.org/p/chromium/issues/detail?id=873321

@vsantosu
Copy link

Ok guys, first of all thanks so much @apalchys for providing the binaries, I got the results we where looking for.

First, the benchmark in rendering one scene using the BabylonJS library(uses WebGL v1 and WebGL 2 when available).

The scene I'm rendering is one like this, which consists of:

1- Launching Puppeteer with the following flags:

"--headless",
"--no-sandbox",
"--mute-audio",
"--hide-scrollbars",
"--disable-web-security"
"--use-gl=swiftshader",
"--enable-webgl",
"--single-process",
"--ignore-gpu-blacklist",
"--data-path=/tmp/data-path",
"--disk-cache-dir=/tmp/cache-dir"

2- Load the HTML page with the BabylonJS library, which will make a network call to load a 3D model.
3- Render the 3D model into a scene and do 6 resizings which I take screenshots from:

4096x4096.png
2048x2048.png
1024x1024.png
512x512.png
256x256.png
128x128.png
64x64.png

The following are the results:

Lib Mesa: WebGL V1 supported

Scene rendered...
Taking scene screenshots.
Image 4096x4096.png extracting took 160523.815 ms.
Image 2048x2048.png extracting took 166938.935 ms.
Image 1024x1024.png extracting took 168854.40000000002 ms.
Image 512x512.png extracting took 169493.98500000002 ms.
Image 256x256.png extracting took 169769.535 ms.
Image 128x128.png extracting took 169993.46000000002 ms.
Image 64x64.png extracting took 170196.14500000002 ms.
Extracting all images from Webgl buffer took 170196.72000000003 ms.

Total 170.2 seconds

SwiftShader: WebGL V2 supported

Scene rendered...
Taking scene screenshots.
Image 4096x4096.png extracting took 1141.299999999319 ms.
Image 2048x2048.png extracting took 1243.9999999987776 ms.
Image 1024x1024.png extracting took 1273.1999999996333 ms.
Image 512x512.png extracting took 1281.8000000006577 ms.
Image 256x256.png extracting took 1284.800000001269 ms.
Image 128x128.png extracting took 1286.10000000117 ms.
Image 64x64.png extracting took 1286.8999999991502 ms.
Extracting all images from Webgl buffer took 1287.1999999988475 ms.

Total 1.29 seconds

SwiftShader is 131 times faster!

Also, the resulting render with swiftshader is higher quality, pay attention to details:

LibMesa Render
SwiftShader Render

So yea guys, swiftshader is pretty performant. So why there is so slow renders some times? Well, doing the benchmark, I think i found the real issue here...

The 3D model for the Babylon Scene is about 30MB, but thats not problem, after all I do downloads of more than 100MB in seconds before launching chromium... But lets look at this logs of the download progress inside the Chromium....

52:45  Loading scene file...
52:45  downloading: 0%
52:47  downloading: 0%
53:03  downloading: 10%
53:29  downloading: 20%
53:30  downloading: 20%
53:44  downloading: 30%
53:45  downloading: 30%
53:55  downloading: 40%
54:06  downloading: 50%
54:23  downloading: 60%
54:23  downloading: 60%
54:37  downloading: 70%
54:54  downloading: 80%
55:08  downloading: 90%
55:09  downloading: 90%
55:31  downloading: 100%
55:42  Loading scene file took 176974.40000000005 ms.

2min 56s total download time!

3 minutes to download 30MB?? Something is off... In my local machine with a slower connection it does not take even 5 seconds... So after researching a bit, it seems that the flag that is killing performance is:

"--single-process"

Which it seems there are issues around.

My theory is that when a download starts as a single process, it hugs all operations in the browser, therefore is extremely slow.

If I take this flag out, the browser fails to launch...

@dukuo
Copy link

dukuo commented Aug 30, 2018

@vsantosu that's awesome indeed! Could you share the code to get it working? somehow I get this error when trying to run the sample provided by @apalchys:

(node:14668) UnhandledPromiseRejectionWarning: Error: Failed to launch chrome! spawn ./headless_chromium/headless_shell ENOENT


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

    at onClose (C:\work\dev\lambda-puppeteer-webgl-swiftshader\node_modules\puppeteer\lib\Launcher.js:299:14)
    at ChildProcess.helper.addEventListener.error (C:\work\dev\lambda-puppeteer-webgl-swiftshader\node_modules\puppeteer\lib\Launcher.js:290:64)
    at emitOne (events.js:116:13)
    at ChildProcess.emit (events.js:211:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:196:12)
    at onErrorNT (internal/child_process.js:372:16)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
(node:14668) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:14668) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Also, do you think it could be suitable to run with THREE.js + animations?

@vsantosu
Copy link

vsantosu commented Sep 1, 2018

Hello @dukuo ,

Are you running the binaries in AWS lambda? Otherwise it won't launch in other environment which is not AWS lambda, their EC2 redhat instance, and probably a CentOS 7 OS. It was compiled to run in that distro.

"do you think it could be suitable to run with THREE.js + animations?"

Absolutely! You could definitively render a scene, and create a 360 degree rotation gif or video from the canvas.

@vsantosu
Copy link

vsantosu commented Sep 1, 2018

@dukuo I'm using the same code settings provided by @apalchys in his repo.

@apalchys
Copy link

apalchys commented Sep 1, 2018

@dukuo Usually ENOENT code means that file or directory is not found. Please check your files/directory structure and make sure you unzipped the archive with the binaries (see README https://github.com/apalchys/lambda-puppeteer-webgl-swiftshader)

@python1981
Copy link

The solution by @vsantosu is great for screenshots with Page.captureScreenshot() but when I tried to create a pdf with Page.printToPdf() the WebGL disappears.

I worked around this by reverting to the earlier version with osmesa instead of swiftshader but unfortunately it's much older and other things break as a result.

Refs: https://bugs.chromium.org/p/chromium/issues/detail?id=809065 & puppeteer/puppeteer#1731

@ghost
Copy link

ghost commented Nov 5, 2021

WebGL should work with the precompiled Chromium binaries available here.

@escully27
Copy link

@vsantosu

I've created a repo: https://github.com/apalchys/lambda-puppeteer-webgl-swiftshader

Also here is you can find zipped lambda code (please note it is over 50mb and you need to use s3 to upload): https://s3-eu-west-1.amazonaws.com/apalchys-public/lambda-puppeteer-webgl-swiftshader.zip

and here is a working demo which returns a screenshot of https://get.webgl.org/ page https://jkkpu18gue.execute-api.eu-west-1.amazonaws.com/demo/lambda-puppeteer-webgl-swiftshader-demo

Would you please be able to share the config for your AWS lambda deployment for your example? Have been trying everything with no success. Simply trying to duplicate your demo on my own lambda function.

Here's my latest error:

"{
  "errorType": "Error",
  "errorMessage": "Failed to launch chrome!\n./headless_chromium/headless_shell: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory\n\n\nTROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md\n",
  "trace": [
    "Error: Failed to launch chrome!",
    "./headless_chromium/headless_shell: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory",
    "",
    "",
    "TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md",
    "",
    "    at onClose (/var/task/node_modules/puppeteer/lib/Launcher.js:299:14)",
    "    at Interface.<anonymous> (/var/task/node_modules/puppeteer/lib/Launcher.js:288:50)",
    "    at Interface.emit (node:events:539:35)",
    "    at Interface.close (node:readline:586:8)",
    "    at Socket.onend (node:readline:277:10)",
    "    at Socket.emit (node:events:539:35)",
    "    at endReadableNT (node:internal/streams/readable:1345:12)",
    "    at processTicksAndRejections (node:internal/process/task_queues:83:21)"
  ]
}
"

I understand there's an issue location libnss3.so but it's no where to be found in your repo either. Many thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests