CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-deck-gl--core

Core library for deck.gl WebGL2/WebGPU-powered visualization framework providing fundamental classes for high-performance data visualization

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

attribute-management.mddocs/

Attribute Management

Efficient data-to-GPU attribute management system with automatic buffer updates, memory optimization, and seamless integration with WebGL vertex attributes for high-performance data visualization.

Capabilities

AttributeManager Class

Central manager for vertex attributes handling data transformation and GPU buffer management.

/**
 * Manages vertex attributes for layers
 * Handles data-to-attribute transformations and WebGL buffer management
 */
class AttributeManager {
  /** Initialize attribute manager */
  constructor(device: Device, opts?: AttributeManagerOptions);
  
  /** Add vertex attributes */
  add(attributes: Record<string, AttributeOptions>): void;
  
  /** Add instanced vertex attributes */
  addInstanced(attributes: Record<string, AttributeOptions>): void;
  
  /** Remove attributes by name */
  remove(attributeNames: string[]): void;
  
  /** Update attributes from data */
  update(opts: UpdateOptions): void;
  
  /** Mark attributes for update */
  invalidate(triggerName: string, range?: [number, number]): void;
  
  /** Mark all attributes invalid */
  invalidateAll(): void;
  
  /** Get all managed attributes */
  getAttributes(): Record<string, Attribute>;
  
  /** Get attributes that changed since last check */
  getChangedAttributes(opts?: {clearChangedFlags?: boolean}): Record<string, Attribute>;
  
  /** Get shared attribute accessor */
  getSharedAccessor(attributeName: string): any;
  
  /** Set shared attribute accessor */
  setSharedAccessor(attributeName: string, accessor: any): void;
  
  /** Check if any attribute needs update */
  needsUpdate(): boolean;
  
  /** Check if any attribute needs redraw */
  needsRedraw(opts?: {clearRedrawFlags?: boolean}): boolean;
  
  /** Get statistics */
  getStats(): AttributeManagerStats;
  
  /** Unique manager identifier */
  readonly id: string;
  
  /** Managed attributes */
  readonly attributes: Record<string, Attribute>;
  
  /** Whether attributes need redraw */
  readonly needsRedraw: boolean;
}

interface AttributeManagerOptions {
  /** Manager identifier */
  id?: string;
  
  /** Default accessor statistics */
  stats?: any;
  
  /** Data change detection */
  dataComparator?: (newData: any, oldData: any) => boolean;
}

interface AttributeOptions {
  /** Elements per vertex (1, 2, 3, or 4) */
  size: number;
  
  /** Data type */
  type?: 'float32' | 'uint8' | 'int8' | 'uint16' | 'int16' | 'uint32' | 'int32';
  
  /** Accessor function or property name */
  accessor?: string | AccessorFunction<any, any>;
  
  /** Default value when accessor returns undefined */
  defaultValue?: number | number[];
  
  /** Transform function for accessor results */
  transform?: (value: any, objectInfo: any) => any;
  
  /** Whether values should be normalized to [0,1] range */
  normalized?: boolean;
  
  /** Whether attribute is instanced */
  instanced?: boolean | number;
  
  /** Whether attribute should be updated */
  noAlloc?: boolean;
  
  /** Custom update function */
  update?: (attribute: Attribute, opts: any) => void;
  
  /** Buffer update settings */
  bufferLayout?: any;
  
  /** Shader attribute name */
  shaderAttribute?: string;
}

interface UpdateOptions {
  /** Number of data instances */
  numInstances?: number;
  
  /** Data array or source */
  data?: any;
  
  /** Layer properties */
  props?: any;
  
  /** Context information */
  context?: any;
  
  /** Buffer layout information */
  bufferLayout?: any;
  
  /** Partial range to update [start, end] */
  range?: [number, number];
  
  /** Additional parameters */
  [key: string]: any;
}

interface AttributeManagerStats {
  /** Total attributes managed */
  attributeCount: number;
  
  /** Total buffer memory used (bytes) */
  totalMemory: number;
  
  /** Number of attributes updated this frame */
  attributesUpdated: number;
  
  /** Time spent updating attributes (ms) */
  updateTime: number;
}

Usage Examples:

import { AttributeManager } from "@deck.gl/core";

// Create attribute manager for a custom layer
class MyLayer extends Layer {
  initializeState(context) {
    const {device} = context;
    
    const attributeManager = new AttributeManager(device, {
      id: 'my-layer-attributes'
    });
    
    // Add vertex attributes
    attributeManager.add({
      positions: {
        size: 3,
        type: 'float32',
        accessor: 'getPosition',
        update: this.calculatePositions
      },
      colors: {
        size: 4,
        type: 'uint8',
        normalized: true,
        accessor: 'getColor',
        defaultValue: [255, 0, 0, 255]
      },
      sizes: {
        size: 1,
        type: 'float32',
        accessor: 'getSize',
        defaultValue: 1,
        transform: (size, {index, data}) => size * data.scaleFactor
      }
    });
    
    // Add instanced attributes  
    attributeManager.addInstanced({
      instancePositions: {
        size: 3,
        accessor: 'getPosition'
      },
      instanceColors: {
        size: 4,
        type: 'uint8',
        normalized: true,
        accessor: 'getColor'
      }
    });
    
    this.setState({attributeManager});
  }
  
  updateState({props, oldProps, changeFlags}) {
    const {attributeManager} = this.state;
    
    if (changeFlags.dataChanged) {
      attributeManager.invalidateAll();
    }
    
    // Update specific attributes based on prop changes
    if (props.getPosition !== oldProps.getPosition) {
      attributeManager.invalidate('getPosition');
    }
    
    if (props.getColor !== oldProps.getColor) {
      attributeManager.invalidate('getColor');
    }
    
    // Update attributes with current data
    attributeManager.update({
      data: props.data,
      numInstances: props.data.length,
      props: props,
      context: this.context
    });
  }
  
  calculatePositions(attribute, {data, numInstances}) {
    const {value} = attribute;
    for (let i = 0; i < numInstances; i++) {
      const position = this.props.getPosition(data[i], {index: i, data, target: []});
      value[i * 3] = position[0];
      value[i * 3 + 1] = position[1]; 
      value[i * 3 + 2] = position[2] || 0;
    }
  }
}

Attribute Class

Represents a single vertex attribute managing data transformation and GPU buffer operations.

/**
 * Represents a single vertex attribute
 * Manages data transformation and GPU buffer operations
 */
class Attribute {
  /** Initialize attribute */
  constructor(device: Device, opts: AttributeCreationOptions);
  
  /** Check if attribute needs update */
  needsUpdate(): boolean;
  
  /** Check if attribute needs redraw */
  needsRedraw(opts?: {clearRedrawFlags?: boolean}): boolean;
  
  /** Allocate GPU buffer for specified number of instances */
  allocate(numInstances: number): void;
  
  /** Update buffer data */
  updateBuffer(opts: UpdateBufferOptions): void;
  
  /** Set constant value for all instances */
  setConstantValue(value: number | number[]): void;
  
  /** Update data using external buffer */
  setExternalBuffer(buffer: Buffer): void;
  
  /** Update partial data range */
  updateSubData(opts: UpdateSubDataOptions): void;
  
  /** Get buffer statistics */
  getBufferStats(): BufferStats;
  
  /** Delete and cleanup attribute */
  delete(): void;
  
  /** Attribute identifier */
  readonly id: string;
  
  /** Elements per vertex */
  readonly size: number;
  
  /** Data type */
  readonly type: string;
  
  /** Whether values are normalized */
  readonly normalized: boolean;
  
  /** Whether attribute is instanced */
  readonly instanced: boolean | number;
  
  /** Current attribute data */
  readonly value: TypedArray;
  
  /** GPU buffer */
  readonly buffer: Buffer;
  
  /** Whether attribute has constant value */
  readonly constant: boolean;
  
  /** Settings for buffer updates */
  readonly settings: AttributeSettings;
}

interface AttributeCreationOptions {
  /** Attribute identifier */
  id: string;
  
  /** Elements per vertex */
  size: number;
  
  /** Data type */
  type?: string;
  
  /** Whether values are normalized */
  normalized?: boolean;
  
  /** Whether attribute is instanced */
  instanced?: boolean | number;
  
  /** Initial buffer size */
  bufferSize?: number;
  
  /** Default value */
  defaultValue?: number | number[];
  
  /** Update function */
  update?: (attribute: Attribute, opts: any) => void;
  
  /** Additional settings */
  settings?: Partial<AttributeSettings>;
}

interface AttributeSettings {
  /** Whether to allocate buffer automatically */
  noAlloc: boolean;
  
  /** Buffer update frequency */
  updateFrequency: 'once' | 'dynamic' | 'stream';
  
  /** Whether attribute is per-instance */
  isIndexed: boolean;
  
  /** Shader attribute location */
  shaderLocation: number;
}

interface UpdateBufferOptions {
  /** Data to upload */
  data?: TypedArray;
  
  /** Number of instances */
  numInstances?: number;
  
  /** Byte offset in buffer */
  offset?: number;
  
  /** Number of bytes to update */
  size?: number;
  
  /** Partial range [start, end] */
  range?: [number, number];
}

interface UpdateSubDataOptions {
  /** Start index */
  startOffset: number;
  
  /** End index */
  endOffset: number;
  
  /** Data to upload */
  data: TypedArray;
}

interface BufferStats {
  /** Buffer size in bytes */
  byteSize: number;
  
  /** Number of elements */
  elementCount: number;
  
  /** Memory usage per element */
  bytesPerElement: number;
  
  /** Whether buffer is allocated */
  allocated: boolean;
}

Usage Examples:

import { Attribute } from "@deck.gl/core";

// Create custom attribute with manual management
class CustomLayer extends Layer {
  initializeState({device}) {
    // Manual attribute creation
    const positionAttribute = new Attribute(device, {
      id: 'positions',
      size: 3,
      type: 'float32',
      update: this.updatePositions.bind(this)
    });
    
    const colorAttribute = new Attribute(device, {
      id: 'colors', 
      size: 4,
      type: 'uint8',
      normalized: true,
      defaultValue: [255, 255, 255, 255]
    });
    
    this.setState({
      positionAttribute,
      colorAttribute
    });
  }
  
  updateState({props, changeFlags}) {
    const {positionAttribute, colorAttribute} = this.state;
    
    if (changeFlags.dataChanged) {
      const numInstances = props.data.length;
      
      // Allocate buffers
      positionAttribute.allocate(numInstances);
      colorAttribute.allocate(numInstances);
      
      // Update data
      positionAttribute.updateBuffer({
        numInstances,
        data: this.extractPositions(props.data)
      });
      
      colorAttribute.updateBuffer({
        numInstances,
        data: this.extractColors(props.data)
      });
    }
  }
  
  updatePositions(attribute, {data, numInstances}) {
    const positions = new Float32Array(numInstances * 3);
    
    for (let i = 0; i < numInstances; i++) {
      const pos = this.props.getPosition(data[i]);
      positions[i * 3] = pos[0];
      positions[i * 3 + 1] = pos[1];
      positions[i * 3 + 2] = pos[2] || 0;
    }
    
    return positions;
  }
  
  draw({uniforms}) {
    const {positionAttribute, colorAttribute} = this.state;
    
    // Use attributes in WebGL draw call
    this.state.model.draw(this.context.renderPass, {
      uniforms,
      attributes: {
        positions: positionAttribute,
        colors: colorAttribute
      }
    });
  }
}

Binary Attribute Support

Support for binary attribute data for high-performance applications.

/**
 * Binary attribute interface for direct GPU buffer management
 * Enables zero-copy data transfer for optimal performance
 */
interface BinaryAttribute {
  /** Buffer containing attribute data */
  buffer: ArrayBuffer;
  
  /** Byte offset within buffer */
  offset?: number;
  
  /** Byte stride between elements */
  stride?: number;
  
  /** Number of instances */
  size: number;
  
  /** Attribute value accessor */
  value?: TypedArray;
}

Transition and Animation Support

Built-in support for attribute transitions and animations.

interface AttributeTransitionSettings {
  /** Transition type */  
  type: 'interpolation' | 'spring' | 'gpu';
  
  /** Transition duration in milliseconds */
  duration?: number;
  
  /** Easing function */
  easing?: (t: number) => number;
  
  /** Called when transition starts */
  onStart?: () => void;
  
  /** Called during transition */
  onUpdate?: (t: number) => void;
  
  /** Called when transition ends */
  onEnd?: () => void;
  
  /** Whether to use GPU-based transitions */
  useGPU?: boolean;
}

interface TransitionManager {
  /** Start attribute transition */
  startTransition(
    attributeName: string, 
    fromValue: any, 
    toValue: any, 
    settings: AttributeTransitionSettings
  ): void;
  
  /** Update all active transitions */
  update(deltaTime: number): void;
  
  /** Cancel transition */
  cancelTransition(attributeName: string): void;
  
  /** Get transition progress */
  getTransitionProgress(attributeName: string): number;
}

Usage Examples:

// Attribute transitions
const layer = new ScatterplotLayer({
  id: 'animated-points',
  data: data,
  getPosition: d => d.coordinates,
  getRadius: d => d.radius,
  getColor: d => d.color,
  
  // Animate radius changes
  transitions: {
    getRadius: {
      type: 'interpolation',
      duration: 1000,
      easing: t => t * t, // quadratic easing
      onStart: () => console.log('Radius animation started'),
      onEnd: () => console.log('Radius animation completed')
    },
    
    // Spring animation for color changes
    getColor: {
      type: 'spring',
      stiffness: 0.1,
      damping: 0.8
    }
  }
});

// Update data with smooth transitions
layer.setProps({
  data: newData,
  updateTriggers: {
    getRadius: Math.random(), // Force radius recalculation
    getColor: Math.random()   // Force color recalculation
  }
});

Performance Optimization

Advanced features for optimizing attribute performance.

interface AttributePerformanceSettings {
  /** Whether to use typed array managers for memory pooling */
  useTypedArrayManager?: boolean;
  
  /** Buffer reuse strategy */
  bufferReuseStrategy?: 'never' | 'same-size' | 'larger';
  
  /** Whether to pack attributes in interleaved arrays */
  interleaved?: boolean;
  
  /** Target GPU memory usage limit */
  memoryLimit?: number;
  
  /** Batch size for partial updates */
  batchSize?: number;
}

Usage Examples:

// Optimized attribute manager for large datasets
const optimizedAttributeManager = new AttributeManager(device, {
  id: 'large-dataset-attributes',
  stats: new Stats({id: 'attributes'}),
  performanceSettings: {
    useTypedArrayManager: true,
    bufferReuseStrategy: 'larger',
    interleaved: true,
    memoryLimit: 1024 * 1024 * 100, // 100MB limit
    batchSize: 10000
  }
});

// Add optimized attributes
optimizedAttributeManager.add({
  positions: {
    size: 3,
    accessor: 'getPosition',
    settings: {
      updateFrequency: 'dynamic',
      noAlloc: false
    }
  },
  colors: {
    size: 4,
    type: 'uint8',
    normalized: true,
    accessor: 'getColor',
    settings: {
      updateFrequency: 'once'
    }
  }
});

// Batch updates for performance
const updateAttributes = (dataChunks) => {
  dataChunks.forEach((chunk, index) => {
    const startIndex = index * optimizedAttributeManager.batchSize;
    const endIndex = Math.min(startIndex + chunk.length, totalDataSize);
    
    optimizedAttributeManager.update({
      data: chunk,
      range: [startIndex, endIndex],
      numInstances: chunk.length
    });
  });
};

Install with Tessl CLI

npx tessl i tessl/npm-deck-gl--core

docs

application-management.md

attribute-management.md

controllers.md

coordinate-systems.md

effects-and-lighting.md

index.md

layer-system.md

transitions-and-animation.md

utilities-and-helpers.md

views-and-viewports.md

tile.json