WebGL performance

Hi there,

WebGL

  • In short: 3D rendering on the web
  • Very low level (compared to other web APIs)

Under the hood

  • Both Firefox and Chrome use
    • On mobile: OpenGL ES2
    • On Mac and Linux: "desktop" OpenGL
    • On Windows: OpenGL ES2 (through ANGLE → Direct3D)
  • ANGLE also provides with shader translation/validation on all platforms.

The content process

  • The JS that calls into WebGL runs in the same thread as layout and most of the web content
  • Means other things can block your game's thread
  • WebGL workers \o/

Security

  • OpenGL specifications have behaviors left undefined to achieve the best performance
  • On the web we cannot allow undefined behaviors because they generally expose security vulnerabilities
  • Browsers needs to perform additional checks
    • Exemple: gl.drawElements() checks that all referenced vertices are within vertex buffer storage.
    • All newly allocated resources are cleared to zero to prevent access to unitialized data.

Synchronization

  • WebGL tries to pipeline commands as much as possible
  • A point of synchronization can block the JS thread for a long time
  • For instance: gl.getError(), gl.readPixels(), gl.finish()

Bandwidth

  • Data transfer betwwen CPU and GPU is slow
    • Texture uploads, vertex buffers, ect.
  • Cache getter calls like gl.getParameter(), gl.getUniformLocation()
  • Avoid gl.uniform1f(gl.getUniformLocation(program, "time"), time);

Batch drawing commands

  • This is generally the most important optimization!
  • State changes are expensive (texture bindings, shaders, etc.)
  • Pack all the geometry that share the same states together in the same drawing commands.
  • Pack several textures into one, and select the appropritae region with texture coordinates.
  • batch, batch, batch!

Shaders

Two triangles

Branching

            if (foo < 0.5) {
              // do A...
            } else {
              // do B...
            }
      
  • Branching is slow!
  • Often the cost of computing both A and B
  • Coherency usually improves performance

Sampling from textures

  • For the texture cache, proximity is considered in 2D
  • Cache misses are expensive

Mipmapping

Warning: shader compile times!

  • Shader compilation is synchronous
  • Very heavy shaders can block the browser for several seconds on some drivers
  • Example: shadertoy.com

Various tips

  • Avoid high precision floats in fragment shaders (mobile hardware don't support it)
  • Always have vertex attrib 0 array enabled.
    • Otherwise it forces the browser to do complicated emulation when running on desktop OpenGL.

Understand what the bottlenecks are

  • Is it JS code?
  • Data transfer?
  • Vertex processing?
  • Fragment processing?
  • Profile your code!
  • Test and measure on all the platforms you target

Beware when profiling

  • Due to pipelining, calls that show up in profiles are not always the ones that actually take time.
  • Use gl.finish() (but not in prduction!)

The GPU is not a silver bullet

  • The GPU is good at doing some specific opertations
  • It is NOT good at everything
    • Rendering text
    • Vector shapes in general (bezier curves)
    • processing that is sequencial by nature

Slightly off topic, but...

  • Publishing on the web, we need to care about network / loading times. Modern games often contain several gigabytes of Assets...
    • Asset LOD streaming
    • More client-side procedural content?

Thanks

Useful resources: