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.
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.
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 Case | Recommended |
|---|---|
| Consistent quality across all text | Global config |
| Device-specific optimization at startup | Global config with auto-detection |
| Hero/title text needing higher quality | Local override |
| UI text that can be lower quality | Local override with lighter preset |
| Dynamic quality adjustment | Update global config at runtime |
| A/B testing different configs | Local overrides for test instances |
Configuration Properties
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;
}| Property | Type | Description |
|---|---|---|
| maxSupersamplingOffsets | 1|2|4|8 | Number of samples for anti-aliasing. Higher = smoother edges. |
| maxShadowBlurRadius | number | Max blur radius for drop shadows (0-30). 0 disables blur. |
| shadowBlurSamples | 1-5 | Blur sample count. More = smoother but slower. |
| useMediumPrecision | boolean | Use mediump instead of highp in shaders. Better for mobile. |
| enableEarlyDiscard | boolean | Discard fragments early if alpha below threshold. |
| earlyDiscardThreshold | number | Alpha threshold for early discard (typically 0.001). |
| cacheInverseAlpha | boolean | Cache 1.0 - alpha calculation. Minor optimization. |
| maxExtrudeSteps | number | Max steps for 3D extrusion (0-20). 0 disables. |
| enableShadowBlur | boolean | Master toggle for drop shadow blur. |
| enableGradients | boolean | Master toggle for gradient fills. |
| enableTextureFill | boolean | Master toggle for texture-based fills. |
| enableExtrusion | boolean | Master toggle for 3D text extrusion. |
| enableStroke | boolean | Master toggle for text stroke/outline. |
| maxGradientStops | 2|4|8 | Max color stops in gradients. |
| simplifiedBlendModes | boolean | Simplified blend mode calculations for mobile. |
| useHighPrecisionPosition | boolean | Use highp for positions. Required for large scenes. |
| maxLoopIterations | number | Max shader loop iterations (32-256). |
| avoidDynamicBranching | boolean | Avoid dynamic if statements. Better for older GPUs. |
Built-in Presets
| Preset | SS | Shadow Blur | Extrude | Gradients | Texture | Best For |
|---|---|---|---|---|---|---|
| ultra_low | 1 | Disabled | 0 | ✗ | ✗ | Very old mobile |
| mobile_low | 2 | 4px / 2 samples | 3 | ✓ | ✗ | Budget smartphones |
| mobile_mid | 2 | 12px / 3 samples | 5 | ✓ | ✓ | Modern mid-range mobile |
| mobile_high | 4 | 16px / 4 samples | 8 | ✓ | ✓ | Flagship phones |
| desktop | 4 | 20px / 5 samples | 10 | ✓ | ✓ | Desktop / laptops |
| ultra | 8 | 30px / 5 samples | 20 | ✓ | ✓ | High-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
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
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
| Option | Default | Description |
|---|---|---|
| targetFPS | 60 | Target frame rate |
| sampleSize | 60 | Rolling sample window (2-10000) |
| adjustmentInterval | 120 | Frames between adjustments |
| autoAdjust | false | Enable automatic quality adjustment |
| autoUpdateGlobalConfig | false | Auto-apply preset changes globally |
| checkMemoryPressure | false | Monitor performance.memory |
| checkThermalState | false | Monitor thermal state |
| checkBatteryState | false | Monitor Battery API |
| checkGPUMemoryPressure | false | Monitor GPU memory (requires gl) |
| respectReducedMotion | false | Cap level on prefers-reduced-motion |
| initialLevel | mobile_mid | Starting performance level |
| minLevel | ultra_low | Minimum allowed level |
| maxLevel | ultra | Maximum allowed level |
| hysteresisFrames | 60 | Min frames between adjustments |
| circuitBreakerWindow | 600 | Window for oscillation detection |
| circuitBreakerMaxReversals | 3 | Max reversals before pausing |
| circuitBreakerCooldown | 300 | Cooldown frames after circuit break |
Monitor Methods
| Method | Description |
|---|---|
| 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