CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-webgpu--types

Complete TypeScript type definitions for the WebGPU standard enabling type-safe GPU programming.

Pending
Overview
Eval results
Files

pipelines.mddocs/

Pipelines and Shaders

Render pipelines, compute pipelines, and shader modules for defining GPU programs and rendering state.

Capabilities

GPU Shader Module

Compiled shader code that can be used in pipelines.

interface GPUShaderModule {
  /** Optional debug label */
  readonly label: string | undefined;
  
  /**
   * Gets compilation information including errors and warnings
   * @returns Promise resolving to compilation info
   */
  getCompilationInfo(): Promise<GPUCompilationInfo>;
}

interface GPUShaderModuleDescriptor extends GPUObjectDescriptorBase {
  /** WGSL shader code */
  code: string;
  
  /** Optional compilation hints */
  hints?: Record<string, GPUShaderModuleCompilationHint>;
}

interface GPUShaderModuleCompilationHint {
  /** Entry point name */
  entryPoint?: string;
  
  /** Pipeline layout for optimization */
  layout?: GPUPipelineLayout | "auto";
}

interface GPUCompilationInfo {
  /** Array of compilation messages */
  readonly messages: ReadonlyArray<GPUCompilationMessage>;
}

interface GPUCompilationMessage {
  /** Message text */
  readonly message: string;
  
  /** Message type */
  readonly type: GPUCompilationMessageType;
  
  /** Line number (1-based) */
  readonly lineNum: number;
  
  /** Line position (1-based) */
  readonly linePos: number;
  
  /** Byte offset in source */
  readonly offset: number;
  
  /** Length of the relevant source region */
  readonly length: number;
}

type GPUCompilationMessageType = "error" | "warning" | "info";

GPU Pipeline Layout

Defines the resource binding layout for a pipeline.

interface GPUPipelineLayout {
  /** Optional debug label */
  readonly label: string | undefined;
}

interface GPUPipelineLayoutDescriptor extends GPUObjectDescriptorBase {
  /** Array of bind group layouts */
  bindGroupLayouts: Iterable<GPUBindGroupLayout>;
}

GPU Render Pipeline

Graphics pipeline for vertex processing and fragment shading.

interface GPURenderPipeline {
  /** Optional debug label */
  readonly label: string | undefined;
  
  /**
   * Gets bind group layout at the specified index
   * @param index - Bind group index
   * @returns The bind group layout
   */
  getBindGroupLayout(index: number): GPUBindGroupLayout;
}

interface GPURenderPipelineDescriptor extends GPUPipelineDescriptorBase {
  /** Vertex stage configuration */
  vertex: GPUVertexState;
  
  /** Primitive assembly configuration */
  primitive?: GPUPrimitiveState;
  
  /** Depth/stencil state */
  depthStencil?: GPUDepthStencilState;
  
  /** Multisample state */
  multisample?: GPUMultisampleState;
  
  /** Fragment stage configuration */
  fragment?: GPUFragmentState;
}

interface GPUPipelineDescriptorBase extends GPUObjectDescriptorBase {
  /** Pipeline layout */
  layout: GPUPipelineLayout | "auto";
}

interface GPUVertexState extends GPUProgrammableStage {
  /** Vertex buffer layouts */
  buffers?: Iterable<GPUVertexBufferLayout | null>;
}

interface GPUProgrammableStage {
  /** Shader module */
  module: GPUShaderModule;
  
  /** Entry point function name */
  entryPoint?: string;
  
  /** Pipeline constants */
  constants?: Record<string, GPUPipelineConstantValue>;
}

interface GPUVertexBufferLayout {
  /** Stride between vertices in bytes */
  arrayStride: GPUSize64;
  
  /** Step mode for vertex fetching */
  stepMode?: GPUVertexStepMode;
  
  /** Vertex attributes */
  attributes: Iterable<GPUVertexAttribute>;
}

interface GPUVertexAttribute {
  /** Vertex format */
  format: GPUVertexFormat;
  
  /** Byte offset within vertex */
  offset: GPUSize64;
  
  /** Shader location binding */
  shaderLocation: GPUIndex32;
}

interface GPUPrimitiveState {
  /** Primitive topology */
  topology?: GPUPrimitiveTopology;
  
  /** Strip index format */
  stripIndexFormat?: GPUIndexFormat;
  
  /** Front face winding */
  frontFace?: GPUFrontFace;
  
  /** Face culling mode */
  cullMode?: GPUCullMode;
  
  /** Whether to enable conservative rasterization */
  unclippedDepth?: boolean;
}

interface GPUMultisampleState {
  /** Number of samples */
  count?: GPUSize32;
  
  /** Sample mask */
  mask?: GPUSampleMask;
  
  /** Alpha to coverage */
  alphaToCoverageEnabled?: boolean;
}

interface GPUFragmentState extends GPUProgrammableStage {
  /** Color target states */
  targets: Iterable<GPUColorTargetState | null>;
}

interface GPUColorTargetState {
  /** Color format */
  format: GPUTextureFormat;
  
  /** Blend state */
  blend?: GPUBlendState;
  
  /** Write mask */
  writeMask?: GPUColorWriteFlags;
}

interface GPUBlendState {
  /** Color blend component */
  color: GPUBlendComponent;
  
  /** Alpha blend component */
  alpha: GPUBlendComponent;
}

interface GPUBlendComponent {
  /** Blend operation */
  operation?: GPUBlendOperation;
  
  /** Source factor */
  srcFactor?: GPUBlendFactor;
  
  /** Destination factor */
  dstFactor?: GPUBlendFactor;
}

interface GPUDepthStencilState {
  /** Depth/stencil format */
  format: GPUTextureFormat;
  
  /** Whether depth writes are enabled */
  depthWriteEnabled?: boolean;
  
  /** Depth comparison function */
  depthCompare?: GPUCompareFunction;
  
  /** Stencil front face state */
  stencilFront?: GPUStencilFaceState;
  
  /** Stencil back face state */
  stencilBack?: GPUStencilFaceState;
  
  /** Stencil read mask */
  stencilReadMask?: GPUStencilValue;
  
  /** Stencil write mask */
  stencilWriteMask?: GPUStencilValue;
  
  /** Depth bias constant */
  depthBias?: GPUDepthBias;
  
  /** Depth bias slope scale */
  depthBiasSlopeScale?: number;
  
  /** Depth bias clamp */
  depthBiasClamp?: number;
}

interface GPUStencilFaceState {
  /** Comparison function */
  compare?: GPUCompareFunction;
  
  /** Fail operation */
  failOp?: GPUStencilOperation;
  
  /** Depth fail operation */
  depthFailOp?: GPUStencilOperation;
  
  /** Pass operation */
  passOp?: GPUStencilOperation;
}

type GPUStencilOperation =
  | "keep" | "zero" | "replace" | "invert"
  | "increment-clamp" | "decrement-clamp"
  | "increment-wrap" | "decrement-wrap";

GPU Compute Pipeline

Compute shader pipeline for general-purpose GPU computing.

interface GPUComputePipeline {
  /** Optional debug label */
  readonly label: string | undefined;
  
  /**
   * Gets bind group layout at the specified index
   * @param index - Bind group index
   * @returns The bind group layout
   */
  getBindGroupLayout(index: number): GPUBindGroupLayout;
}

interface GPUComputePipelineDescriptor extends GPUPipelineDescriptorBase {
  /** Compute stage configuration */
  compute: GPUProgrammableStage;
}

Pipeline Base Interface

Common functionality shared by all pipeline types.

interface GPUPipelineBase {
  /** Optional debug label */
  readonly label: string | undefined;
  
  /**
   * Gets bind group layout at the specified index
   * @param index - Bind group index
   * @returns The bind group layout
   */
  getBindGroupLayout(index: number): GPUBindGroupLayout;
}

Usage Examples

Shader Module Creation

// Create a vertex shader
const vertexShader = device.createShaderModule({
  code: `
    struct VertexInput {
      @location(0) position: vec3<f32>,
      @location(1) normal: vec3<f32>,
      @location(2) uv: vec2<f32>,
    }
    
    struct VertexOutput {
      @builtin(position) position: vec4<f32>,
      @location(0) normal: vec3<f32>,
      @location(1) uv: vec2<f32>,
    }
    
    @group(0) @binding(0) var<uniform> mvpMatrix: mat4x4<f32>;
    
    @vertex
    fn main(input: VertexInput) -> VertexOutput {
      var output: VertexOutput;
      output.position = mvpMatrix * vec4<f32>(input.position, 1.0);
      output.normal = input.normal;
      output.uv = input.uv;
      return output;
    }
  `,
  label: "Vertex Shader"
});

// Create a fragment shader
const fragmentShader = device.createShaderModule({
  code: `
    struct FragmentInput {
      @location(0) normal: vec3<f32>,
      @location(1) uv: vec2<f32>,
    }
    
    @group(1) @binding(0) var baseColorTexture: texture_2d<f32>;
    @group(1) @binding(1) var baseColorSampler: sampler;
    
    @fragment
    fn main(input: FragmentInput) -> @location(0) vec4<f32> {
      let baseColor = textureSample(baseColorTexture, baseColorSampler, input.uv);
      let lighting = max(dot(normalize(input.normal), vec3<f32>(0.0, 1.0, 0.0)), 0.1);
      return vec4<f32>(baseColor.rgb * lighting, baseColor.a);
    }
  `,
  label: "Fragment Shader"
});

// Check compilation info
const vertexInfo = await vertexShader.getCompilationInfo();
for (const message of vertexInfo.messages) {
  if (message.type === "error") {
    console.error(`Shader error at line ${message.lineNum}: ${message.message}`);
  }
}

Render Pipeline Creation

// Create pipeline layout
const pipelineLayout = device.createPipelineLayout({
  bindGroupLayouts: [
    uniformsBindGroupLayout,
    materialBindGroupLayout
  ],
  label: "Render Pipeline Layout"
});

// Create render pipeline
const renderPipeline = device.createRenderPipeline({
  layout: pipelineLayout,
  vertex: {
    module: vertexShader,
    entryPoint: "main",
    buffers: [
      {
        arrayStride: 32, // 3 * 4 + 3 * 4 + 2 * 4 = position + normal + uv
        attributes: [
          {
            format: "float32x3",
            offset: 0,
            shaderLocation: 0 // position
          },
          {
            format: "float32x3", 
            offset: 12,
            shaderLocation: 1 // normal
          },
          {
            format: "float32x2",
            offset: 24,
            shaderLocation: 2 // uv
          }
        ]
      }
    ]
  },
  fragment: {
    module: fragmentShader,
    entryPoint: "main",
    targets: [
      {
        format: "bgra8unorm",
        blend: {
          color: {
            srcFactor: "src-alpha",
            dstFactor: "one-minus-src-alpha",
            operation: "add"
          },
          alpha: {
            srcFactor: "one",
            dstFactor: "one-minus-src-alpha",
            operation: "add"
          }
        }
      }
    ]
  },
  primitive: {
    topology: "triangle-list",
    cullMode: "back",
    frontFace: "ccw"
  },
  depthStencil: {
    format: "depth24plus-stencil8",
    depthWriteEnabled: true,
    depthCompare: "less"
  },
  multisample: {
    count: 4,
    alphaToCoverageEnabled: false
  },
  label: "Mesh Render Pipeline"
});

Compute Pipeline Creation

// Create compute shader
const computeShader = device.createShaderModule({
  code: `
    @group(0) @binding(0) var<storage, read> inputData: array<f32>;
    @group(0) @binding(1) var<storage, read_write> outputData: array<f32>;
    
    @compute @workgroup_size(64)
    fn main(@builtin(global_invocation_id) globalId: vec3<u32>) {
      let index = globalId.x;
      if (index >= arrayLength(&inputData)) {
        return;
      }
      
      outputData[index] = inputData[index] * 2.0;
    }
  `,
  label: "Double Values Compute Shader"
});

// Create compute pipeline
const computePipeline = device.createComputePipeline({
  layout: "auto",
  compute: {
    module: computeShader,
    entryPoint: "main"
  },
  label: "Double Values Pipeline"
});

// Get the auto-generated bind group layout
const computeBindGroupLayout = computePipeline.getBindGroupLayout(0);

Advanced Shader Features

// Shader with constants
const advancedShader = device.createShaderModule({
  code: `
    override workgroupSize: u32 = 64;
    override multiplier: f32 = 1.0;
    
    @group(0) @binding(0) var<storage, read_write> data: array<f32>;
    
    @compute @workgroup_size(workgroupSize, 1, 1)
    fn main(@builtin(global_invocation_id) globalId: vec3<u32>) {
      let index = globalId.x;
      if (index >= arrayLength(&data)) {
        return;
      }
      
      data[index] = data[index] * multiplier;
    }
  `,
  label: "Parameterized Compute Shader"
});

// Create pipeline with constants
const parameterizedPipeline = device.createComputePipeline({
  layout: "auto",
  compute: {
    module: advancedShader,
    entryPoint: "main",
    constants: {
      workgroupSize: 128,
      multiplier: 2.5
    }
  },
  label: "Parameterized Pipeline"
});

Pipeline with Multiple Render Targets

const multiTargetPipeline = device.createRenderPipeline({
  layout: pipelineLayout,
  vertex: {
    module: vertexShader,
    entryPoint: "main",
    buffers: [vertexBufferLayout]
  },
  fragment: {
    module: multiTargetFragmentShader,
    entryPoint: "main",
    targets: [
      { format: "rgba8unorm" },    // Color target 0
      { format: "rgba16float" },   // Color target 1 (HDR)
      { format: "rg16float" },     // Color target 2 (normals)
      null,                        // Skip target 3
      { format: "r8uint" }         // Color target 4 (object ID)
    ]
  },
  primitive: {
    topology: "triangle-list"
  },
  label: "G-Buffer Pipeline"
});

Async Pipeline Creation

// Create pipelines asynchronously for better performance
const [renderPipelineAsync, computePipelineAsync] = await Promise.all([
  device.createRenderPipelineAsync({
    layout: renderPipelineLayout,
    vertex: { module: vertexShader, entryPoint: "main" },
    fragment: { 
      module: fragmentShader, 
      entryPoint: "main",
      targets: [{ format: "bgra8unorm" }]
    },
    label: "Async Render Pipeline"
  }),
  
  device.createComputePipelineAsync({
    layout: "auto",
    compute: { module: computeShader, entryPoint: "main" },
    label: "Async Compute Pipeline"
  })
]);

console.log("Both pipelines created asynchronously");

Error Handling in Shaders

// Create shader with potential compilation issues
const shaderWithError = device.createShaderModule({
  code: `
    @vertex
    fn main() -> @builtin(position) vec4<f32> {
      // Missing required vertex output
      return vec4<f32>(0.0, 0.0, 0.0, 1.0);
    }
  `,
  label: "Test Shader"
});

// Check for compilation errors
const compilationInfo = await shaderWithError.getCompilationInfo();
if (compilationInfo.messages.length > 0) {
  console.log("Compilation messages:");
  for (const message of compilationInfo.messages) {
    const level = message.type.toUpperCase();
    console.log(`${level} at line ${message.lineNum}:${message.linePos} - ${message.message}`);
  }
}

// Handle pipeline creation errors
device.pushErrorScope("validation");

const pipeline = device.createRenderPipeline({
  layout: "auto",
  vertex: { module: shaderWithError, entryPoint: "main" },
  fragment: { 
    module: fragmentShader, 
    entryPoint: "main",
    targets: [{ format: "bgra8unorm" }]
  }
});

const error = await device.popErrorScope();
if (error) {
  console.error("Pipeline creation failed:", error.message);
}

Pipeline Specialization

// Create multiple specialized pipelines from the same shader
const basePipelineDesc: GPURenderPipelineDescriptor = {
  layout: pipelineLayout,
  vertex: {
    module: vertexShader,
    entryPoint: "main",
    buffers: [vertexBufferLayout]
  },
  fragment: {
    module: fragmentShader,
    entryPoint: "main",
    targets: [{ format: "bgra8unorm" }]
  }
};

// Opaque rendering pipeline
const opaquePipeline = device.createRenderPipeline({
  ...basePipelineDesc,
  primitive: {
    topology: "triangle-list",
    cullMode: "back"
  },
  depthStencil: {
    format: "depth24plus",
    depthWriteEnabled: true,
    depthCompare: "less"
  },
  label: "Opaque Pipeline"
});

// Transparent rendering pipeline
const transparentPipeline = device.createRenderPipeline({
  ...basePipelineDesc,
  primitive: {
    topology: "triangle-list",
    cullMode: "none"
  },
  fragment: {
    ...basePipelineDesc.fragment!,
    targets: [{
      format: "bgra8unorm",
      blend: {
        color: {
          srcFactor: "src-alpha",
          dstFactor: "one-minus-src-alpha"
        },
        alpha: {
          srcFactor: "one",
          dstFactor: "one-minus-src-alpha"
        }
      }
    }]
  },
  depthStencil: {
    format: "depth24plus",
    depthWriteEnabled: false,
    depthCompare: "less-equal"
  },
  label: "Transparent Pipeline"
});

Install with Tessl CLI

npx tessl i tessl/npm-webgpu--types

docs

commands.md

configuration.md

core-types.md

gpu-interfaces.md

index.md

pipelines.md

render-bundles.md

resources.md

tile.json