UNPKG

typegpu

Version:

A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.

154 lines (153 loc) 5.74 kB
import { getName, hasTinyestMetadata } from "./shared/meta.js"; import { DEV, TEST } from "./shared/env.js"; const prefix = 'Invariant failed'; /** * Inspired by: https://github.com/alexreardon/tiny-invariant/blob/master/src/tiny-invariant.ts */ export function invariant(condition, message) { if (condition) { // Condition passed return; } // In production we strip the message but still throw if (!DEV && !TEST) { throw new Error(prefix); } // When not in production we allow the message to pass through // *This block will be removed in production builds* const provided = typeof message === 'function' ? message() : message; // Options: // 1. message provided: `${prefix}: ${provided}` // 2. message not provided: prefix const value = provided ? `${prefix}: ${provided}` : prefix; throw new Error(value); } /** * An error that happens during resolution of WGSL code. * Contains a trace of all ancestor resolvables in * which this error originated. * * @category Errors */ export class ResolutionError extends Error { cause; trace; constructor(cause, trace) { let entries = trace.map((ancestor) => `- ${hasTinyestMetadata(ancestor) ? `fn*:${getName(ancestor)}` : ancestor}`); // Showing only the root and leaf nodes. if (entries.length > 20) { entries = [...entries.slice(0, 11), '...', ...entries.slice(-10)]; } super(`Resolution of the following tree failed:\n${entries.join('\n')}: ${cause && typeof cause === 'object' && 'message' in cause ? cause.message : cause}`); this.cause = cause; this.trace = trace; // Set the prototype explicitly. Object.setPrototypeOf(this, ResolutionError.prototype); } appendToTrace(ancestor) { const newTrace = [ancestor, ...this.trace]; return new ResolutionError(this.cause, newTrace); } } /** * An error that happens during execution of TypeGPU functions. * Contains a trace of all TypeGPU functions called along the way. * * @category Errors */ export class ExecutionError extends Error { cause; trace; constructor(cause, trace) { let entries = trace.map((ancestor) => `- ${ancestor}`); // Showing only the root and leaf nodes. if (entries.length > 20) { entries = [...entries.slice(0, 11), '...', ...entries.slice(-10)]; } super(`Execution of the following tree failed:\n${entries.join('\n')}: ${cause && typeof cause === 'object' && 'message' in cause ? cause.message : cause}`); this.cause = cause; this.trace = trace; // Set the prototype explicitly. Object.setPrototypeOf(this, ExecutionError.prototype); } appendToTrace(ancestor) { const newTrace = [ancestor, ...this.trace]; return new ExecutionError(this.cause, newTrace); } } /** * @category Errors */ export class MissingSlotValueError extends Error { slot; constructor(slot) { super(`Missing value for '${slot}'`); this.slot = slot; // Set the prototype explicitly. Object.setPrototypeOf(this, MissingSlotValueError.prototype); } } /** * @category Errors */ export class NotUniformError extends Error { constructor(value) { super(`Buffer '${getName(value) ?? '<unnamed>'}' is not bindable as a uniform. Use .$usage('uniform') to allow it.`); // Set the prototype explicitly. Object.setPrototypeOf(this, NotUniformError.prototype); } } export class MissingBindGroupsError extends Error { constructor(layouts) { super(`Missing bind groups for layouts: '${[...layouts] .map((layout) => getName(layout) ?? '<unnamed>') .join(', ')}'. Please provide it using pipeline.with(bindGroup).(...)`); // Set the prototype explicitly. Object.setPrototypeOf(this, MissingBindGroupsError.prototype); } } export class MissingVertexBuffersError extends Error { constructor(layouts) { super(`Missing vertex buffers for layouts: '${[...layouts] .map((layout) => getName(layout) ?? '<unnamed>') .join(', ')}'. Please provide it using pipeline.with(layout, buffer).(...)`); // Set the prototype explicitly. Object.setPrototypeOf(this, MissingVertexBuffersError.prototype); } } export class IllegalVarAccessError extends Error { constructor(msg) { super(msg); // Set the prototype explicitly. Object.setPrototypeOf(this, IllegalVarAccessError.prototype); } } export class IllegalBufferAccessError extends Error { constructor(msg) { super(msg); // Set the prototype explicitly. Object.setPrototypeOf(this, IllegalBufferAccessError.prototype); } } export class WgslTypeError extends Error { constructor(msg) { super(msg); // Set the prototype explicitly. Object.setPrototypeOf(this, WgslTypeError.prototype); } } export class SignatureNotSupportedError extends Error { constructor(actual, candidates) { super(`Unsupported data types: ${actual .map((a) => a.type) .join(', ')}. Supported types are: ${candidates.map((r) => r.type).join(', ')}.`); // Set the prototype explicitly. Object.setPrototypeOf(this, SignatureNotSupportedError.prototype); } } export class FiniteMathAssumptionError extends Error { constructor(value, type) { super(`Cannot convert value '${value}' to type ${type.type} because of the Finite Math Assumption (see: https://www.w3.org/TR/WGSL/#finite-math-assumption)`); Object.setPrototypeOf(this, FiniteMathAssumptionError.prototype); } }