UBOs – Pal's Blog
Categories
PixiJS

UBOs

Thanks to Mat Grove’s work, PixiJS 6.1.0 will ship with support for Uniform Buffer Objects, a WebGL 2 optimization to make uniform uploads faster.

Context

UBOs are handles to GPU buffers that store uniform data. They can be attached to a shader in a single step, without needing to upload each uniform field individually. If you share uniforms between multiple shaders, this can be used to reduce uploads of relatively static data.

Theoretically, you can optimize filters with UBOs. The common uniforms passed to Filter don’t change between them: inputSize, inputPixel, inputClamp, outputFrame.

Usage

To use UBOs in a shader, you’ll need to use GLSL 3 ES.

#version 300 es
#define SHADER_NAME Example-Shader

precision highp float;

To migrate an existing GLSL 1 shader (the default), you need to use the in keyword instead of attribute, out instead of varying in the vertex shader, in instead of varying in the fragment shader, and then create an out variable in the fragment shader instead of using gl_FragColor.

You can then move some of your uniforms into a UBO block:

uniform location_data {
  mat3 locationMatrix;
};

In this example, you can reference the locationMatrix uniform directly.

void main(void) {
  mat3 matrix = locationMatrix;
}

To upload the UBO uniforms, you need to add an UniformBufferGroup in PixiJS in your shader’s uniform.

import { Shader, UniformBufferGroup } from 'pixi.js';

Shader.from(vertexSrc, fragmentSrc, {
    location_data: UniformBufferGroup.uboFrom({
        locationMatrix: new Matrix().toArray(),
    }),
})

UniformBufferGroup.uboFrom creates a “static” UBO. If you ever change a value in it, you’ll need to update it.

Here’s an example that applies a gradient color to a texture using a UBO:

When should I use UBOs?

UBOs are useful if you have multiple shaders that share static uniform data. If your uniforms are dynamic and change very often, UBOs will not be much of an optimization.