Skip to content

State & Resource Management

This page documents the WebGL state management and GPU resource management systems in Three.js. These systems minimize redundant GPU state changes and manage the lifecycle of GPU resources (textures, buffers, framebuffers) to optimize rendering performance.

For information about shader programs and compilation, see Shader Programs & Compilation. For geometry buffer management specifically, see Geometry System.


Overview

The state and resource management layer sits between the high-level renderer and the WebGL API. Its primary responsibilities are:

  • State Tracking: Cache current WebGL state to avoid redundant gl.* calls
  • Texture Management: Upload, cache, and share texture data on the GPU
  • Resource Lifecycle: Allocate, track, and dispose of GPU resources
  • Capability Detection: Query GPU limits and extension availability
  • Format Conversion: Translate Three.js constants to WebGL enums

WebGLState Architecture

The WebGLState class maintains a shadow copy of WebGL state to eliminate redundant state changes. It exposes methods that compare requested state against cached state before issuing WebGL commands.

State Buffers

Three specialized buffer classes manage render target state:

SVG
100%
BufferPurposeKey State Variables
ColorBufferColor write mask and clear colorcurrentColorMask, currentColorClear
DepthBufferDepth testing and writingcurrentDepthFunc, currentDepthMask, currentReversed
StencilBufferStencil testing and operationscurrentStencilFunc, currentStencilFail, currentStencilZPass

State Tracking Variables

The WebGLState instance maintains cached state for numerous WebGL parameters:

State CategoryCached VariablesPurpose
BlendingcurrentBlending, currentBlendEquation, currentBlendSrc, currentBlendDst, currentBlendColor, currentBlendAlphaTrack blending mode and parameters
CullingcurrentFlipSided, currentCullFaceTrack face culling direction
TexturescurrentTextureSlot, currentBoundTexturesTrack active texture unit and bindings
FramebufferscurrentBoundFramebuffers, currentDrawbuffersTrack framebuffer bindings
ProgramcurrentProgramTrack active shader program
ViewportcurrentScissor, currentViewportTrack scissor and viewport rectangles
Polygon OffsetcurrentPolygonOffsetFactor, currentPolygonOffsetUnitsTrack depth offset parameters

State Change Flow

SVG
100%

Example: The setBlending function compares requested blending state against cached state:

Sources: src/renderers/webgl/WebGLState.js620-763

Material State Application

The setMaterial function translates material properties to WebGL state:

SVG
100%

Implementation Details:

  • Maps material.side (DoubleSide/BackSide/FrontSide) to gl.CULL_FACE enable/disable
  • Translates material.blending to gl.blendFunc and gl.blendEquation
  • Applies depth function, test, and write mask
  • Configures stencil operations when material.stencilWrite is enabled
  • Handles reversed depth buffers via EXT_clip_control extension

Texture Binding Optimization

The texture binding system tracks which textures are bound to which texture units to avoid redundant gl.bindTexture calls:

SVG
100%

The currentBoundTextures object maps texture slots to { type, texture } objects. Empty textures are created at initialization to avoid binding null.

Texture Resource Management

The WebGLTextures class manages texture uploads, caching, and lifecycle. It implements a source-based caching system where multiple Texture objects sharing the same Source can reuse the same WebGL texture.

Texture Caching Architecture

SVG
100%

Cache Key Generation: The getTextureCacheKey function creates a unique key from texture parameters:

cacheKey = [wrapS, wrapT, wrapR, magFilter, minFilter, anisotropy, 
            internalFormat, format, type, generateMipmaps, 
            premultiplyAlpha, flipY, unpackAlignment, colorSpace].join()

Reference Counting: Each WebGL texture tracks usedTimes to support sharing. When a texture changes parameters, its cache key changes, triggering:

  1. Decrement old texture's usedTimes
  2. Increment new texture's usedTimes (or create new texture)
  3. Delete old texture if usedTimes reaches 0

Texture Upload Pipeline

SVG
100%

Key Upload Functions:

FunctionPurposeLine Reference
uploadTextureMain upload coordinatorsrc/renderers/webgl/WebGLTextures.js859-1313
initTextureInitialize WebGL texture and manage cachesrc/renderers/webgl/WebGLTextures.js670-748
updateTexturePartial texture updates via update rangessrc/renderers/webgl/WebGLTextures.js756-857
setTextureParametersSet texture filtering and wrappingsrc/renderers/webgl/WebGLTextures.js623-668
getInternalFormatDetermine internal format from format/type/colorSpacesrc/renderers/webgl/WebGLTextures.js128-229

Texture Type Specializations

The upload pipeline branches based on texture type:

Texture TypeUpload MethodSpecial Handling
DepthTexturetexStorage2D or texImage2DUses getInternalDepthFormat for depth/stencil formats
DataTexturetexImage2D or texSubImage2DHandles manual mipmaps, supports updateRanges for partial updates
CompressedTexturecompressedTexImage2D/3D or compressedTexSubImage2D/3DSupports layer updates for array textures
DataArrayTexturetexImage3D or texSubImage3D3D upload with layer update support
Data3DTexturetexImage3D or texSubImage3D3D volume texture upload
Regular TexturetexStorage2D + texSubImage2DUses texStorage2D for immutable storage when supported

Partial Texture Updates: The updateTexture function supports incremental updates via texture.updateRanges, merging adjacent ranges to minimize gl.texSubImage2D calls.

Texture Lifecycle Management

SVG
100%

Dispose Handling: Textures register a dispose event listener in initTexture that triggers deallocateTexture, which decrements reference counts and deletes GPU resources when no longer needed.

Render Target Disposal

Render targets manage multiple GPU resources (framebuffers, renderbuffers, depth textures):

SVG
100%

Capability Detection

The WebGLCapabilities class queries GPU limits and extension support at renderer initialization.

Capabilities Object Structure

SVG
100%

Precision Selection: The system attempts to use the requested precision (default 'highp') but falls back to lower precision if unsupported by the GPU.

Reversed Depth Buffer: Enabled when EXT_clip_control extension is available, providing better depth precision by reversing the depth range from [0,1] to [1,0].

Extension Management

The WebGLExtensions class provides a centralized interface for querying and caching WebGL extensions.

Extension Initialization

SVG
100%

Extension Access Pattern:

  • extensions.has(name): Returns true if extension is supported
  • extensions.get(name): Returns extension object or null, logs warning if unsupported

Common extensions include:

  • EXT_color_buffer_float: Float render targets
  • EXT_texture_filter_anisotropic: Anisotropic filtering
  • WEBGL_compressed_texture_*: Compressed texture formats (S3TC, PVRTC, ETC, ASTC, BPTC, RGTC)
  • WEBGL_multi_draw: Multi-draw commands for instancing
  • EXT_clip_control: Reversed depth buffers

Format Conversion Utilities

The WebGLUtils class converts Three.js constants to WebGL enums, handling color space and compression formats.

Conversion Categories

CategoryThree.js ConstantsWebGL Enums
Data TypesUnsignedByteType, FloatType, HalfFloatType, IntType, etc.gl.UNSIGNED_BYTE, gl.FLOAT, gl.HALF_FLOAT, gl.INT, etc.
FormatsRGBAFormat, RGBFormat, RedFormat, DepthFormat, etc.gl.RGBA, gl.RGB, gl.RED, gl.DEPTH_COMPONENT, etc.
Compressed FormatsRGBA_S3TC_DXT5_Format, RGBA_ASTC_4x4_Format, etc.Extension-specific enums (e.g., extension.COMPRESSED_RGBA_S3TC_DXT5_EXT)

Color Space Handling: The convert function accepts an optional colorSpace parameter. For compressed formats in sRGB color space, it retrieves the corresponding SRGB variant from the extension (e.g., COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT instead of COMPRESSED_RGBA_S3TC_DXT5_EXT).

State Reset and Initialization

Initialization Sequence

At renderer creation, the state system is initialized with default values:

colorBuffer.setClear(0, 0, 0, 1)
depthBuffer.setClear(1)
stencilBuffer.setClear(0)

enable(gl.DEPTH_TEST)
depthBuffer.setFunc(LessEqualDepth)
setFlipSided(false)
setCullFace(CullFaceBack)
enable(gl.CULL_FACE)
setBlending(NoBlending)

Reset Function

The reset() function restores WebGL to a known initial state, used when the context is lost or when switching renderers:

Actions Performed:

  1. Disable all state flags (BLEND, CULL_FACE, DEPTH_TEST, etc.)
  2. Reset blend functions and equations
  3. Reset color mask, depth mask, stencil mask
  4. Reset clear colors
  5. Reset framebuffer bindings
  6. Reset program binding
  7. Reset texture bindings
  8. Reset viewport and scissor
  9. Clear all internal state caches

Memory Tracking

The info object tracks GPU memory usage:

info.memory.textures++  // Incremented when WebGL texture created
info.memory.textures--  // Decremented when WebGL texture deleted

Texture creation occurs in initTexture and render target setup. Deletion occurs in deleteTexture and deallocateRenderTarget.

Performance Optimizations

State Change Minimization

Every state-modifying function compares the requested state against the cached state before issuing WebGL calls:

if (currentValue !== newValue) {
    gl.someStateFunction(newValue);
    currentValue = newValue;
}

This pattern appears in:

  • setBlending: Compares 8+ blending parameters
  • bindTexture: Compares texture type and object per slot
  • useProgram: Compares program object
  • bindFramebuffer: Compares framebuffer per target

Texture Storage vs Texture Image

Modern code paths prefer gl.texStorage2D (immutable storage) over gl.texImage2D:

Benefits:

  • Allocates all mipmap levels in one call
  • Allows more efficient gl.texSubImage2D updates
  • Prevents accidental format changes

The system uses texStorage2D when texture.isVideoTexture !== true and only allocates memory once per source.

Update Range Merging

The updateTexture function merges adjacent or overlapping update ranges before issuing gl.texSubImage2D calls, reducing GPU command overhead:

// Before merging: [{start: 0, count: 100}, {start: 100, count: 100}]
// After merging:  [{start: 0, count: 200}]

Integration with Rendering Pipeline

SVG
100%

The state and resource management systems are called throughout the render loop, ensuring minimal redundant state changes while maintaining correct rendering state.