Performance Configuration

Overview

The Performance Configuration System provides fine-grained control over rendering quality and performance trade-offs. It enables automatic device detection, preset-based configurations, runtime performance monitoring, and custom configuration for optimal rendering across all device types.

6 built-in presets from ultra_low to ultra
Automatic GPU and device capability detection
Runtime FPS / memory / thermal / battery monitoring
Hysteresis, rollback stack, and circuit breaker
Page-visibility awareness & draw-call tracking
External preset loading via JSON

Quick Start

Basic Usage with Preset

import { Text, getPreset } from 'funky-pixi-text';

const text = new Text("Hello", {
  fontName: 'Roboto-Black',
  fontSize: 48,
  color: 0xffffff,
  performanceConfig: getPreset('desktop')
});

Using performanceMode Shorthand

const text = new Text("Hello", {
  fontName: 'Roboto-Black',
  fontSize: 48,
  color: 0xffffff,
  performanceMode: 'balanced' // 'auto' | 'high-quality' | 'balanced' | 'mobile-optimized'
});

Global vs Local Configuration

Global configuration affects all text instances that don't specify their own config. Local config (per-instance) takes priority.

Priority
import { setGlobalPerformanceConfig, getPreset, PerformancePresets } from 'funky-pixi-text';

// Set global config
setGlobalPerformanceConfig(PerformancePresets.DESKTOP);

// Uses DESKTOP (global)
const text1 = new Text("Normal", { fontName: 'Roboto-Black', fontSize: 32 });

// Uses ULTRA (local override takes priority)
const text2 = new Text("Hero", {
  fontName: 'Roboto-Black',
  fontSize: 72,
  performanceConfig: PerformancePresets.ULTRA
});

When to Use Global vs Local

Use CaseRecommended
Consistent quality across all textGlobal config
Device-specific optimization at startupGlobal config with auto-detection
Hero/title text needing higher qualityLocal override
UI text that can be lower qualityLocal override with lighter preset
Dynamic quality adjustmentUpdate global config at runtime
A/B testing different configsLocal overrides for test instances

Configuration Properties

PerformanceConfig
interface PerformanceConfig {
  maxSupersamplingOffsets: 1 | 2 | 4 | 8;
  maxShadowBlurRadius: number;
  shadowBlurSamples: 1 | 2 | 3 | 4 | 5;
  useMediumPrecision: boolean;
  enableEarlyDiscard: boolean;
  earlyDiscardThreshold: number;
  cacheInverseAlpha: boolean;
  maxExtrudeSteps: number;
  enableShadowBlur: boolean;
  enableGradients: boolean;
  enableTextureFill: boolean;
  enableExtrusion: boolean;
  enableStroke: boolean;
  maxGradientStops: 2 | 4 | 8;
  simplifiedBlendModes: boolean;
  useHighPrecisionPosition: boolean;
  maxLoopIterations: number;
  avoidDynamicBranching: boolean;
}
PropertyTypeDescription
maxSupersamplingOffsets1|2|4|8Number of samples for anti-aliasing. Higher = smoother edges.
maxShadowBlurRadiusnumberMax blur radius for drop shadows (0-30). 0 disables blur.
shadowBlurSamples1-5Blur sample count. More = smoother but slower.
useMediumPrecisionbooleanUse mediump instead of highp in shaders. Better for mobile.
enableEarlyDiscardbooleanDiscard fragments early if alpha below threshold.
earlyDiscardThresholdnumberAlpha threshold for early discard (typically 0.001).
cacheInverseAlphabooleanCache 1.0 - alpha calculation. Minor optimization.
maxExtrudeStepsnumberMax steps for 3D extrusion (0-20). 0 disables.
enableShadowBlurbooleanMaster toggle for drop shadow blur.
enableGradientsbooleanMaster toggle for gradient fills.
enableTextureFillbooleanMaster toggle for texture-based fills.
enableExtrusionbooleanMaster toggle for 3D text extrusion.
enableStrokebooleanMaster toggle for text stroke/outline.
maxGradientStops2|4|8Max color stops in gradients.
simplifiedBlendModesbooleanSimplified blend mode calculations for mobile.
useHighPrecisionPositionbooleanUse highp for positions. Required for large scenes.
maxLoopIterationsnumberMax shader loop iterations (32-256).
avoidDynamicBranchingbooleanAvoid dynamic if statements. Better for older GPUs.

Built-in Presets

PresetSSShadow BlurExtrudeGradientsTextureBest For
ultra_low1Disabled0Very old mobile
mobile_low24px / 2 samples3Budget smartphones
mobile_mid212px / 3 samples5Modern mid-range mobile
mobile_high416px / 4 samples8Flagship phones
desktop420px / 5 samples10Desktop / laptops
ultra830px / 5 samples20High-end, max quality

ULTRA_LOW

Minimal configuration for extremely constrained devices

{
  maxSupersamplingOffsets: 1,
  maxShadowBlurRadius: 0,
  shadowBlurSamples: 1,
  maxExtrudeSteps: 0,
  enableShadowBlur: false,
  enableGradients: false,
  enableTextureFill: false,
  enableExtrusion: false,
  enableStroke: true,
  maxGradientStops: 2,
  simplifiedBlendModes: true,
  maxLoopIterations: 32,
  avoidDynamicBranching: true
}

MOBILE_LOW

Basic mobile with essential features

{
  maxSupersamplingOffsets: 2,
  maxShadowBlurRadius: 4,
  shadowBlurSamples: 2,
  maxExtrudeSteps: 3,
  enableShadowBlur: true,
  enableGradients: true,
  enableTextureFill: false,
  maxGradientStops: 4,
  simplifiedBlendModes: true,
  maxLoopIterations: 64
}

MOBILE_MID (Default)

Balanced for modern mobile devices

{
  maxSupersamplingOffsets: 2,
  maxShadowBlurRadius: 12,
  shadowBlurSamples: 3,
  maxExtrudeSteps: 5,
  enableShadowBlur: true,
  enableGradients: true,
  enableTextureFill: true,
  maxGradientStops: 8,
  simplifiedBlendModes: false,
  maxLoopIterations: 128
}

MOBILE_HIGH

High-quality mobile configuration

{
  maxSupersamplingOffsets: 4,
  maxShadowBlurRadius: 16,
  shadowBlurSamples: 4,
  maxExtrudeSteps: 8,
  enableShadowBlur: true,
  enableGradients: true,
  enableTextureFill: true,
  maxGradientStops: 8,
  maxLoopIterations: 128
}

DESKTOP

Standard desktop configuration

{
  maxSupersamplingOffsets: 4,
  maxShadowBlurRadius: 20,
  shadowBlurSamples: 5,
  useMediumPrecision: false,
  maxExtrudeSteps: 10,
  useHighPrecisionPosition: true,
  maxLoopIterations: 128
}

ULTRA

Maximum quality configuration

{
  maxSupersamplingOffsets: 8,
  maxShadowBlurRadius: 30,
  shadowBlurSamples: 5,
  useMediumPrecision: false,
  maxExtrudeSteps: 20,
  useHighPrecisionPosition: true,
  maxLoopIterations: 256
}

Automatic Device Detection

Auto-Detection
import { detectPerformancePreset, detectWebGLCapabilities } from 'funky-pixi-text';

const gl = app.renderer.gl;
const config = detectPerformancePreset(gl);

const capabilities = detectWebGLCapabilities(gl);
console.log(capabilities);
// {
//   webglVersion: 2,
//   hasDerivatives: true,
//   hasFloatTextures: true,
//   maxTextureSize: 16384,
//   maxFragmentUniforms: 1024,
//   renderer: 'NVIDIA GeForce RTX 3080',
//   vendor: 'NVIDIA Corporation',
//   isOldMali: false,
//   isOldAdreno: false,
//   isPowerVR: false
// }

Detection considers:

  • GPU Renderer — Old Mali/Adreno → ultra_low, PowerVR → mobile_low
  • WebGL Capabilities — Fragment uniforms, max texture size, WebGL version
  • Device Type — Desktop vs mobile via user agent
  • Hardware Specs — Core count and RAM

Runtime Performance Monitoring

Auto-Adjusting Monitor
import { PerformanceMonitor, Text } from 'funky-pixi-text';

Text.enableAutoConfigUpdate();

const monitor = new PerformanceMonitor({
  targetFPS: 60,
  autoAdjust: true,
  autoUpdateGlobalConfig: true,
  checkMemoryPressure: true,
  checkThermalState: true,
  checkBatteryState: true,
  checkGPUMemoryPressure: true,
  respectReducedMotion: true,
  onPerformanceChange: (newPreset, fps) => {
    console.log(`Performance changed to ${newPreset} at ${fps.toFixed(1)} FPS`);
  },
});

monitor.start();

PerformanceMonitorOptions

OptionDefaultDescription
targetFPS60Target frame rate
sampleSize60Rolling sample window (2-10000)
adjustmentInterval120Frames between adjustments
autoAdjustfalseEnable automatic quality adjustment
autoUpdateGlobalConfigfalseAuto-apply preset changes globally
checkMemoryPressurefalseMonitor performance.memory
checkThermalStatefalseMonitor thermal state
checkBatteryStatefalseMonitor Battery API
checkGPUMemoryPressurefalseMonitor GPU memory (requires gl)
respectReducedMotionfalseCap level on prefers-reduced-motion
initialLevelmobile_midStarting performance level
minLevelultra_lowMinimum allowed level
maxLevelultraMaximum allowed level
hysteresisFrames60Min frames between adjustments
circuitBreakerWindow600Window for oscillation detection
circuitBreakerMaxReversals3Max reversals before pausing
circuitBreakerCooldown300Cooldown frames after circuit break

Monitor Methods

MethodDescription
start()Begin monitoring via internal rAF loop
stop()Stop monitoring and cancel callback
pause() / resume()Temporarily pause/resume (auto on visibilitychange)
tick(timestamp?)Manually drive a frame sample
setAutoAdjust(enabled)Toggle auto-adjustment at runtime
getAverageFPS()Mean FPS over the rolling sample window
getMinFPS() / getMaxFPS()Min/max FPS in the window
getPercentileFPS(p)Arbitrary percentile (p50/p95/p99 cached)
getFrameTimeStdDev()Standard deviation of frame times (ms)
getCurrentLevel()Current performance level
setLevel(level)Manually set level (clamped to min/max)
getCurrentConfig()PerformanceConfig for current level
suggestLevel()Recommended level based on FPS and jitter
getStats()Comprehensive stats object
getDetailedMetrics()Stats + circuit breaker + history + budget
getDeviceProfile()Cached OS/browser/GPU/memory profile
setConsoleEnabled(bool)Toggle on-screen debug overlay
destroy()Clean up listeners and debug overlay

Performance Tuning Guide

Optimizing for Mobile

const mobileOptimized = {
  maxSupersamplingOffsets: 2,
  maxShadowBlurRadius: 8,
  shadowBlurSamples: 2,
  useMediumPrecision: true,
  enableEarlyDiscard: true,
  maxExtrudeSteps: 3,
  simplifiedBlendModes: true,
  avoidDynamicBranching: true
};

Optimizing for Quality

const highQuality = {
  maxSupersamplingOffsets: 8,
  maxShadowBlurRadius: 30,
  shadowBlurSamples: 5,
  useMediumPrecision: false,
  useHighPrecisionPosition: true,
  maxExtrudeSteps: 20,
  maxGradientStops: 8
};

Optimizing for Fill Rate

const fillRateOptimized = {
  enableEarlyDiscard: true,
  earlyDiscardThreshold: 0.01,
  maxSupersamplingOffsets: 1,
  maxShadowBlurRadius: 0,
  enableShadowBlur: false
};

Best Practices

Start with detection, then customize

Use detectPerformancePreset() as a base, then apply project-specific overrides with mergePerformanceConfig().

Use the monitor for dynamic adjustment

Let PerformanceMonitor handle runtime quality changes based on actual device performance.

Disable unused features

Set enableShadowBlur, enableExtrusion, enableTextureFill to false for features you don’t use.

Test on target devices

Create device-specific configs and test on actual hardware for best results.

Use config hash for caching

getConfigHash(config) returns a unique hash for caching compiled shaders.

Graceful degradation

Check capabilities before enabling features and fall back to lighter presets on weak hardware.

Troubleshooting

Shader Compilation Errors

  • Try avoidDynamicBranching: true on older GPUs
  • Reduce maxLoopIterations if GPU reports loop limit errors
  • Use useMediumPrecision: true on mobile if precision errors occur

Poor Performance on Mobile

  • Reduce maxSupersamplingOffsets to 1 or 2
  • Disable enableShadowBlur if not needed
  • Set maxExtrudeSteps to 0 if not using 3D text
  • Enable simplifiedBlendModes

Flickering or Artifacts

  • Try useHighPrecisionPosition: true
  • Increase earlyDiscardThreshold slightly
  • Disable cacheInverseAlpha to test

Features Not Rendering

  • Check feature toggle is enabled (e.g., enableGradients)
  • Verify quality limits allow the feature
  • Test with a higher preset to confirm