AVIF Texture Loading in WebGL and WebGPU

AVIF offers superior compression efficiency and high dynamic range support, making it an attractive asset format for real-time 3D web applications. Integrating AVIF into WebGL and WebGPU pipelines involves decoding the AV1-compressed bitstream into an uncompressed pixel representation using browser APIs like createImageBitmap or the WebCodecs API before uploading that data into GPU memory. This article explains the technical mechanics, modern upload pathways, color space management, and performance trade-offs when using AVIF for graphics programming on the web.

The Role of AVIF in Graphics Pipelines

AVIF is an image delivery format rather than a GPU texture format. Unlike block-compressed formats designed for hardware (such as ASTC, BCn, or Basis Universal), AVIF cannot remain compressed inside GPU VRAM.

Instead, AVIF acts as an ultra-lightweight transmission format over the network. Once fetched by the client, the browser decodes the AV1 bitstream into raw, uncompressed RGBA pixel buffers in system memory. These raw pixels are subsequently copied into GPU texture memory for rendering.

Decoding AVIF Asynchronously

To prevent frame drops on the main thread, AVIF images must be decoded asynchronously. Modern web architectures avoid using traditional HTMLImageElement instances in favor of fetch combined with createImageBitmap.

// Fetch the AVIF file as a Blob
const response = await fetch('texture.avif');
const blob = await response.blob();

// Decode off-thread into an ImageBitmap
const imageBitmap = await createImageBitmap(blob, {
  colorSpaceConversion: 'none',
  premultiplyAlpha: 'none'
});

Using createImageBitmap allows the browser’s underlying AV1 decoder to process the image on a worker thread. Specifying decoding options ensures the raw data is not prematurely converted or blended before reaching the shader.

WebGL Texture Upload Pipeline

In WebGL 1 and WebGL 2, the pipeline receives the decoded ImageBitmap and uploads it via the CPU-to-GPU bridge.

  1. Configure Pixel Storage: Define alignment and unpacking flags to match your asset’s layout:

    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  2. Allocate and Upload: Bind a texture target and call texImage2D or texSubImage2D:

    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      imageBitmap
    );
    gl.generateMipmap(gl.TEXTURE_2D);

Because AVIF does not store precomputed mipmaps, mip generation must occur dynamically on the GPU using gl.generateMipmap(), adding a small runtime overhead during scene initialization.

WebGPU Texture Upload Pipeline

WebGPU modernizes texture handling by introducing copyExternalImageToTexture(), which coordinates the transfer of image sources directly to GPU textures via the GPUQueue.

// Create target texture
const texture = device.createTexture({
  size: [imageBitmap.width, imageBitmap.height, 1],
  format: 'rgba8unorm',
  usage: GPUTextureUsage.TEXTURE_BINDING | 
         GPUTextureUsage.COPY_DST | 
         GPUTextureUsage.RENDER_ATTACHMENT,
});

// Direct transfer from decoded image source to GPU texture
device.queue.copyExternalImageToTexture(
  { source: imageBitmap, flipY: false },
  { texture: texture },
  [imageBitmap.width, imageBitmap.height]
);

This method is optimized inside browser engines to bypass unnecessary intermediate memory copies, achieving near-zero-copy transfers depending on the underlying OS compositor and hardware decoder capabilities.

High Dynamic Range (HDR) and Wide Color Gamut

One of AVIF's greatest advantages over older formats like WebP or JPEG is native support for 10-bit and 12-bit color depths, as well as wide color gamuts (BT.2020) and transfer functions like PQ and HLG.

  • In WebGL 2: HDR AVIF data must be unpacked into float or half-float textures (gl.RGBA16F or gl.RGBA32F) to retain dynamic range without clamping values to 8-bit limits.
  • In WebGPU: Textures can be initialized with formats like rgba16float, and color spaces can be preserved explicitly through the colorSpace configuration in copyExternalImageToTexture().

Performance Trade-Offs

When designing a production pipeline, consider the following trade-offs between AVIF and GPU-native formats:

  • Bandwidth vs. VRAM: AVIF dramatically reduces initial download times and storage requirements compared to raw or standard compressed files. However, once decoded, an AVIF image consumes full uncompressed VRAM (e.g., 4 bytes per pixel for standard RGBA8).
  • Decoding Latency: AV1 decoding is computationally intensive. While hardware-accelerated AV1 decoding is increasingly common on modern chipsets, older mobile devices rely on software fallbacks that can spike CPU usage during bulk loads.
  • Best Use Cases: AVIF excels for high-fidelity skyboxes, environmental lighting panoramas, user interface elements, and photorealistic overlays. For massive 3D asset libraries requiring hundreds of distinct surface maps, GPU-native formats like Basis Universal (transcoded directly to BCn/ASTC) remain preferable to keep runtime VRAM low.