Safari 14, Shadertoy and WebGL 2

(Edit 2021: In the lat­est Safari 14.2 the Shader­toy does not work and my crash or hang the dis­play. This is unfor­tu­nate­ly a regression.)

This is a quick post thrown togeth­er to report on my expe­ri­ence with the new Safari 14 regard­ing sup­port for WebGL 2. The news of improved WebGL sup­port was float­ed last month in the Shader­toy Com­mu­ni­ty Group:Fast for­ward to today and the Safari 14 update has now come to my lap­top (which still runs macOS Mojave). So the first thing I did check out all my shaders on Shader­toy and then some to see if the promis­es were true. My ver­dict (TL/DR):

  • Yes, all WebGL 2 shaders that I tried out com­pile out of the box (although the WebGL 2 sup­port is still dis­abled by default and has to be enabled in the exper­i­men­tal fea­tures menu).
  • No, Safari is not the per­fect brows­er for Shader­toy, at least not for author­ing. More on that later.

Performance and compile times

The devel­op­er tools in Safari come with a pro­fil­er that feels sim­i­lar to DTrace or’In­stru­ments’ in XCode, where you can inspect the stack trace of a time­line. Thus is should be pos­si­ble to track the exact com­pile times for a shad­er. Unfor­tu­nate­ly, the WebGL APIs of compileShader and linkProgram seem to return ear­ly and the bulk of the work hap­pens lat­er in the dri­ver, result­ing in Shader­toy hap­pi­ly report­ing that com­pi­la­tion only took 2 sec­onds, where in real­i­ty it was block­ing the last ani­ma­tion frame for 11 seconds.

For the com­par­i­son I was most­ly inter­est­ed in run­ning Space Glid­er, my pro­ce­dur­al planet/atmospheric scattering/flight sim test­bed imple­ment­ed all in shad­er code with noto­ri­ous­ly long com­pile times, trig­ger­ing all sorts of dri­ver bugs and com­pat­i­bil­i­ty issues espe­cial­ly on Win­dows. Below are the results on com­pile times and run­time per­for­mance on Safari 14 and Fire­fox 80 (15-inch Mac­book Pro 2017; 2.8 GHz Intel 7700HQ; Radeon Pro 555):

Brows­er Com­pile time Run­time FPS @ 640×360
Safari 14 11 s around 30
Fire­fox 80 13 s around 30

As can be seen, the run time per­for­mance of the com­piled shaders are essen­tial­ly the same, how­ev­er Safari seems to com­pile a lit­tle bit faster.


As far as I could see at a quick glance there are no obvi­ous out­put dif­fer­ences between Safari’s and Firefox’s WebGL imple­men­ta­tions. Since the sim­u­la­tion runs at the edge of float­ing point pre­ci­sion, deter­min­is­tic out­put can­not be expect­ed. For exam­ple: I made an own ver­sion of a sin­cospi func­tion so that con­ver­sion from lat-long coor­di­nates is more con­sis­tent across plat­forms (not nec­es­sar­i­ly ‘bet­ter’ or more pre­cise, just so as to not to have a depen­den­cy on builtin sin/cos). But still the com­pil­er has a lot of lat­i­tude in the eval­u­a­tion of the cus­tom func­tion and how it is inlined.

For the com­par­i­son I choose start loca­tion ‘L’, then wait­ed for t = 30s to make the screen­shot. The top one is from Safari and bot­tom one is from Firefox:

What looks reas­sur­ing is that the pat­terns on the ground tex­ture are in agree­ment. There is a slight 0.4 m dif­fer­ence in alti­tude and 0.02° dif­fer­ence in heading.

The plan­et is so large that the observed alti­tude dif­fer­ence amounts to only 4 ulp in a 32-bit float­ing point posi­tion vec­tor. Since there is a clear par­al­lax between the images (in the Safari ver­sion the cam­era is clos­er to the ground), it seems that the cause it is not the ter­rain height itself, but the play­er posi­tion against the ter­rain. The play­er is posi­tioned by a ray inter­sec­tion rou­tine and 4 ulp are actu­al­ly pret­ty decent for that.

Authoring experience

While the shaders them­selves now run fine, the expe­ri­ence of writ­ing and edit­ing shaders using the Shader­toy UI is still not as smooth as in Chrome or Firefox.

Issue 1: Viewport size

The map­ping from win­dow size to view­port size is incon­sis­tent and bro­ken. One has to use the screen zoom via Cmd + and – to get to the intend­ed view­port res­o­lu­tion for a giv­en win­dow size. And even at the default zoom lev­el, the view­port con­tents is nev­er pix­el per­fect but always scaled (at least gam­ma correct).

Issue 2: Fullscreen size

The size of the fullscreen view­port equals the win­dow view­port. Going fullscreen in 640×360 invokes this VGA flight sim nos­tal­gia, with the slight aspect ratio dis­tor­tion (since the Mac­Book has a 16:10 screen) giv­ing that extra authenticity.

Issue 3: No Shadertoy-plugin

There is a cool plu­g­in that extends the Shader­toy UI with new tools, some of which are real­ly super use­ful. An equiv­a­lent Safari-exten­sion is miss­ing so no points.


Curi­ous­ly, the ini­tial devel­op­ment of Space Glid­er start­ed out in Safari when it was WebGL 1 only. Most of the code was writ­ten ear­ly in 2018 when I had one and a half hours time to kill on a dai­ly com­mute. Lat­er that year, Shader­toy was updat­ed to sup­port WebGL 2, and then I switched to Firefox.

While it would have been pos­si­ble to live with­out int and uint types, or arrays, the addi­tion of 3‑D tex­tures for vol­ume noise with prop­er mipmap­ping and sup­port for the textureLod() func­tion were basi­cal­ly essen­tial for the pro­ce­dur­al ter­rain and the vol­u­met­ric clouds.

Safari has had for a long time ‘exper­i­men­tal WebGL 2’ sup­port, but it lacked sup­port for exact­ly the things that I need­ed. Buffer mipmaps and 3‑D tex­ture lookup was bro­ken. And it would not accept the back­slash-line con­tin­u­a­tion so that macros were con­strained onto a sin­gle line, which is too impractical.

It is nice to see that Safari is now back in the club, so to speak!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Please answer the following anti-spam test

Which thing makes "tick-tock" and if it falls down, the clock is broken?

  1.    ruler
  2.    pencil
  3.    table
  4.    chair
  5.    watch