@luma.gl/effects
Version:
Post-processing effects for luma.gl
1,426 lines (1,398 loc) • 134 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd) define([], factory);
else if (typeof exports === 'object') exports['luma'] = factory();
else root['luma'] = factory();})(globalThis, function () {
"use strict";
var __exports__ = (() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name2 in all)
__defProp(target, name2, { get: all[name2], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// external-global-plugin:@luma.gl/shadertools
var require_shadertools = __commonJS({
"external-global-plugin:@luma.gl/shadertools"(exports, module) {
module.exports = globalThis.luma;
}
});
// bundle.ts
var bundle_exports = {};
__export(bundle_exports, {
Adapter: () => Adapter,
Buffer: () => Buffer2,
CanvasContext: () => CanvasContext,
CommandBuffer: () => CommandBuffer,
CommandEncoder: () => CommandEncoder,
ComputePass: () => ComputePass,
ComputePipeline: () => ComputePipeline,
Device: () => Device,
DeviceFeatures: () => DeviceFeatures,
DeviceLimits: () => DeviceLimits,
ExternalTexture: () => ExternalTexture,
Framebuffer: () => Framebuffer,
PipelineLayout: () => PipelineLayout,
QuerySet: () => QuerySet,
RenderPass: () => RenderPass,
RenderPipeline: () => RenderPipeline,
Resource: () => Resource,
Sampler: () => Sampler,
Shader: () => Shader,
Texture: () => Texture,
TextureFormatDecoder: () => TextureFormatDecoder,
TextureView: () => TextureView,
TransformFeedback: () => TransformFeedback,
UniformBlock: () => UniformBlock,
UniformBufferLayout: () => UniformBufferLayout,
UniformStore: () => UniformStore,
VertexArray: () => VertexArray,
_getTextureFormatDefinition: () => getTextureFormatDefinition,
_getTextureFormatTable: () => getTextureFormatTable,
getAttributeInfosFromLayouts: () => getAttributeInfosFromLayouts,
getAttributeShaderTypeInfo: () => getAttributeShaderTypeInfo,
getDataType: () => getDataType,
getDataTypeInfo: () => getDataTypeInfo,
getNormalizedDataType: () => getNormalizedDataType,
getScratchArray: () => getScratchArray,
getTypedArrayConstructor: () => getTypedArrayConstructor,
getVariableShaderTypeInfo: () => getVariableShaderTypeInfo,
getVertexFormatFromAttribute: () => getVertexFormatFromAttribute,
getVertexFormatInfo: () => getVertexFormatInfo,
log: () => log,
luma: () => luma,
makeVertexFormat: () => makeVertexFormat,
readPixel: () => readPixel,
textureFormatDecoder: () => textureFormatDecoder,
writePixel: () => writePixel
});
// ../../node_modules/@probe.gl/stats/dist/utils/hi-res-timestamp.js
function getHiResTimestamp() {
let timestamp;
if (typeof window !== "undefined" && window.performance) {
timestamp = window.performance.now();
} else if (typeof process !== "undefined" && process.hrtime) {
const timeParts = process.hrtime();
timestamp = timeParts[0] * 1e3 + timeParts[1] / 1e6;
} else {
timestamp = Date.now();
}
return timestamp;
}
// ../../node_modules/@probe.gl/stats/dist/lib/stat.js
var Stat = class {
constructor(name2, type) {
this.sampleSize = 1;
this.time = 0;
this.count = 0;
this.samples = 0;
this.lastTiming = 0;
this.lastSampleTime = 0;
this.lastSampleCount = 0;
this._count = 0;
this._time = 0;
this._samples = 0;
this._startTime = 0;
this._timerPending = false;
this.name = name2;
this.type = type;
this.reset();
}
reset() {
this.time = 0;
this.count = 0;
this.samples = 0;
this.lastTiming = 0;
this.lastSampleTime = 0;
this.lastSampleCount = 0;
this._count = 0;
this._time = 0;
this._samples = 0;
this._startTime = 0;
this._timerPending = false;
return this;
}
setSampleSize(samples) {
this.sampleSize = samples;
return this;
}
/** Call to increment count (+1) */
incrementCount() {
this.addCount(1);
return this;
}
/** Call to decrement count (-1) */
decrementCount() {
this.subtractCount(1);
return this;
}
/** Increase count */
addCount(value) {
this._count += value;
this._samples++;
this._checkSampling();
return this;
}
/** Decrease count */
subtractCount(value) {
this._count -= value;
this._samples++;
this._checkSampling();
return this;
}
/** Add an arbitrary timing and bump the count */
addTime(time) {
this._time += time;
this.lastTiming = time;
this._samples++;
this._checkSampling();
return this;
}
/** Start a timer */
timeStart() {
this._startTime = getHiResTimestamp();
this._timerPending = true;
return this;
}
/** End a timer. Adds to time and bumps the timing count. */
timeEnd() {
if (!this._timerPending) {
return this;
}
this.addTime(getHiResTimestamp() - this._startTime);
this._timerPending = false;
this._checkSampling();
return this;
}
getSampleAverageCount() {
return this.sampleSize > 0 ? this.lastSampleCount / this.sampleSize : 0;
}
/** Calculate average time / count for the previous window */
getSampleAverageTime() {
return this.sampleSize > 0 ? this.lastSampleTime / this.sampleSize : 0;
}
/** Calculate counts per second for the previous window */
getSampleHz() {
return this.lastSampleTime > 0 ? this.sampleSize / (this.lastSampleTime / 1e3) : 0;
}
getAverageCount() {
return this.samples > 0 ? this.count / this.samples : 0;
}
/** Calculate average time / count */
getAverageTime() {
return this.samples > 0 ? this.time / this.samples : 0;
}
/** Calculate counts per second */
getHz() {
return this.time > 0 ? this.samples / (this.time / 1e3) : 0;
}
_checkSampling() {
if (this._samples === this.sampleSize) {
this.lastSampleTime = this._time;
this.lastSampleCount = this._count;
this.count += this._count;
this.time += this._time;
this.samples += this._samples;
this._time = 0;
this._count = 0;
this._samples = 0;
}
}
};
// ../../node_modules/@probe.gl/stats/dist/lib/stats.js
var Stats = class {
constructor(options) {
this.stats = {};
this.id = options.id;
this.stats = {};
this._initializeStats(options.stats);
Object.seal(this);
}
/** Acquire a stat. Create if it doesn't exist. */
get(name2, type = "count") {
return this._getOrCreate({ name: name2, type });
}
get size() {
return Object.keys(this.stats).length;
}
/** Reset all stats */
reset() {
for (const stat of Object.values(this.stats)) {
stat.reset();
}
return this;
}
forEach(fn) {
for (const stat of Object.values(this.stats)) {
fn(stat);
}
}
getTable() {
const table = {};
this.forEach((stat) => {
table[stat.name] = {
time: stat.time || 0,
count: stat.count || 0,
average: stat.getAverageTime() || 0,
hz: stat.getHz() || 0
};
});
return table;
}
_initializeStats(stats = []) {
stats.forEach((stat) => this._getOrCreate(stat));
}
_getOrCreate(stat) {
const { name: name2, type } = stat;
let result = this.stats[name2];
if (!result) {
if (stat instanceof Stat) {
result = stat;
} else {
result = new Stat(name2, type);
}
this.stats[name2] = result;
}
return result;
}
};
// ../core/src/utils/stats-manager.ts
var StatsManager = class {
stats = /* @__PURE__ */ new Map();
getStats(name2) {
return this.get(name2);
}
get(name2) {
if (!this.stats.has(name2)) {
this.stats.set(name2, new Stats({ id: name2 }));
}
return this.stats.get(name2);
}
};
var lumaStats = new StatsManager();
// ../../node_modules/@probe.gl/env/dist/lib/globals.js
var window_ = globalThis;
var document_ = globalThis.document || {};
var process_ = globalThis.process || {};
var console_ = globalThis.console;
var navigator_ = globalThis.navigator || {};
// ../../node_modules/@probe.gl/env/dist/lib/is-electron.js
function isElectron(mockUserAgent) {
if (typeof window !== "undefined" && window.process?.type === "renderer") {
return true;
}
if (typeof process !== "undefined" && Boolean(process.versions?.["electron"])) {
return true;
}
const realUserAgent = typeof navigator !== "undefined" && navigator.userAgent;
const userAgent = mockUserAgent || realUserAgent;
return Boolean(userAgent && userAgent.indexOf("Electron") >= 0);
}
// ../../node_modules/@probe.gl/env/dist/lib/is-browser.js
function isBrowser() {
const isNode = (
// @ts-expect-error
typeof process === "object" && String(process) === "[object process]" && !process?.browser
);
return !isNode || isElectron();
}
// ../../node_modules/@probe.gl/env/dist/index.js
var VERSION = true ? "4.1.0" : "untranspiled source";
// ../../node_modules/@probe.gl/log/dist/utils/local-storage.js
function getStorage(type) {
try {
const storage = window[type];
const x = "__storage_test__";
storage.setItem(x, x);
storage.removeItem(x);
return storage;
} catch (e) {
return null;
}
}
var LocalStorage = class {
constructor(id, defaultConfig, type = "sessionStorage") {
this.storage = getStorage(type);
this.id = id;
this.config = defaultConfig;
this._loadConfiguration();
}
getConfiguration() {
return this.config;
}
setConfiguration(configuration) {
Object.assign(this.config, configuration);
if (this.storage) {
const serialized = JSON.stringify(this.config);
this.storage.setItem(this.id, serialized);
}
}
// Get config from persistent store, if available
_loadConfiguration() {
let configuration = {};
if (this.storage) {
const serializedConfiguration = this.storage.getItem(this.id);
configuration = serializedConfiguration ? JSON.parse(serializedConfiguration) : {};
}
Object.assign(this.config, configuration);
return this;
}
};
// ../../node_modules/@probe.gl/log/dist/utils/formatters.js
function formatTime(ms) {
let formatted;
if (ms < 10) {
formatted = `${ms.toFixed(2)}ms`;
} else if (ms < 100) {
formatted = `${ms.toFixed(1)}ms`;
} else if (ms < 1e3) {
formatted = `${ms.toFixed(0)}ms`;
} else {
formatted = `${(ms / 1e3).toFixed(2)}s`;
}
return formatted;
}
function leftPad(string, length = 8) {
const padLength = Math.max(length - string.length, 0);
return `${" ".repeat(padLength)}${string}`;
}
// ../../node_modules/@probe.gl/log/dist/utils/color.js
var COLOR;
(function(COLOR2) {
COLOR2[COLOR2["BLACK"] = 30] = "BLACK";
COLOR2[COLOR2["RED"] = 31] = "RED";
COLOR2[COLOR2["GREEN"] = 32] = "GREEN";
COLOR2[COLOR2["YELLOW"] = 33] = "YELLOW";
COLOR2[COLOR2["BLUE"] = 34] = "BLUE";
COLOR2[COLOR2["MAGENTA"] = 35] = "MAGENTA";
COLOR2[COLOR2["CYAN"] = 36] = "CYAN";
COLOR2[COLOR2["WHITE"] = 37] = "WHITE";
COLOR2[COLOR2["BRIGHT_BLACK"] = 90] = "BRIGHT_BLACK";
COLOR2[COLOR2["BRIGHT_RED"] = 91] = "BRIGHT_RED";
COLOR2[COLOR2["BRIGHT_GREEN"] = 92] = "BRIGHT_GREEN";
COLOR2[COLOR2["BRIGHT_YELLOW"] = 93] = "BRIGHT_YELLOW";
COLOR2[COLOR2["BRIGHT_BLUE"] = 94] = "BRIGHT_BLUE";
COLOR2[COLOR2["BRIGHT_MAGENTA"] = 95] = "BRIGHT_MAGENTA";
COLOR2[COLOR2["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
COLOR2[COLOR2["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
})(COLOR || (COLOR = {}));
var BACKGROUND_INCREMENT = 10;
function getColor(color) {
if (typeof color !== "string") {
return color;
}
color = color.toUpperCase();
return COLOR[color] || COLOR.WHITE;
}
function addColor(string, color, background) {
if (!isBrowser && typeof string === "string") {
if (color) {
const colorCode = getColor(color);
string = `\x1B[${colorCode}m${string}\x1B[39m`;
}
if (background) {
const colorCode = getColor(background);
string = `\x1B[${colorCode + BACKGROUND_INCREMENT}m${string}\x1B[49m`;
}
}
return string;
}
// ../../node_modules/@probe.gl/log/dist/utils/autobind.js
function autobind(obj, predefined = ["constructor"]) {
const proto = Object.getPrototypeOf(obj);
const propNames = Object.getOwnPropertyNames(proto);
const object = obj;
for (const key of propNames) {
const value = object[key];
if (typeof value === "function") {
if (!predefined.find((name2) => key === name2)) {
object[key] = value.bind(obj);
}
}
}
}
// ../../node_modules/@probe.gl/log/dist/utils/assert.js
function assert(condition, message) {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
// ../../node_modules/@probe.gl/log/dist/utils/hi-res-timestamp.js
function getHiResTimestamp2() {
let timestamp;
if (isBrowser() && window_.performance) {
timestamp = window_?.performance?.now?.();
} else if ("hrtime" in process_) {
const timeParts = process_?.hrtime?.();
timestamp = timeParts[0] * 1e3 + timeParts[1] / 1e6;
} else {
timestamp = Date.now();
}
return timestamp;
}
// ../../node_modules/@probe.gl/log/dist/log.js
var originalConsole = {
debug: isBrowser() ? console.debug || console.log : console.log,
log: console.log,
info: console.info,
warn: console.warn,
error: console.error
};
var DEFAULT_LOG_CONFIGURATION = {
enabled: true,
level: 0
};
function noop() {
}
var cache = {};
var ONCE = { once: true };
var Log = class {
constructor({ id } = { id: "" }) {
this.VERSION = VERSION;
this._startTs = getHiResTimestamp2();
this._deltaTs = getHiResTimestamp2();
this.userData = {};
this.LOG_THROTTLE_TIMEOUT = 0;
this.id = id;
this.userData = {};
this._storage = new LocalStorage(`__probe-${this.id}__`, DEFAULT_LOG_CONFIGURATION);
this.timeStamp(`${this.id} started`);
autobind(this);
Object.seal(this);
}
set level(newLevel) {
this.setLevel(newLevel);
}
get level() {
return this.getLevel();
}
isEnabled() {
return this._storage.config.enabled;
}
getLevel() {
return this._storage.config.level;
}
/** @return milliseconds, with fractions */
getTotal() {
return Number((getHiResTimestamp2() - this._startTs).toPrecision(10));
}
/** @return milliseconds, with fractions */
getDelta() {
return Number((getHiResTimestamp2() - this._deltaTs).toPrecision(10));
}
/** @deprecated use logLevel */
set priority(newPriority) {
this.level = newPriority;
}
/** @deprecated use logLevel */
get priority() {
return this.level;
}
/** @deprecated use logLevel */
getPriority() {
return this.level;
}
// Configure
enable(enabled = true) {
this._storage.setConfiguration({ enabled });
return this;
}
setLevel(level) {
this._storage.setConfiguration({ level });
return this;
}
/** return the current status of the setting */
get(setting) {
return this._storage.config[setting];
}
// update the status of the setting
set(setting, value) {
this._storage.setConfiguration({ [setting]: value });
}
/** Logs the current settings as a table */
settings() {
if (console.table) {
console.table(this._storage.config);
} else {
console.log(this._storage.config);
}
}
// Unconditional logging
assert(condition, message) {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
warn(message) {
return this._getLogFunction(0, message, originalConsole.warn, arguments, ONCE);
}
error(message) {
return this._getLogFunction(0, message, originalConsole.error, arguments);
}
/** Print a deprecation warning */
deprecated(oldUsage, newUsage) {
return this.warn(`\`${oldUsage}\` is deprecated and will be removed in a later version. Use \`${newUsage}\` instead`);
}
/** Print a removal warning */
removed(oldUsage, newUsage) {
return this.error(`\`${oldUsage}\` has been removed. Use \`${newUsage}\` instead`);
}
probe(logLevel, message) {
return this._getLogFunction(logLevel, message, originalConsole.log, arguments, {
time: true,
once: true
});
}
log(logLevel, message) {
return this._getLogFunction(logLevel, message, originalConsole.debug, arguments);
}
info(logLevel, message) {
return this._getLogFunction(logLevel, message, console.info, arguments);
}
once(logLevel, message) {
return this._getLogFunction(logLevel, message, originalConsole.debug || originalConsole.info, arguments, ONCE);
}
/** Logs an object as a table */
table(logLevel, table, columns) {
if (table) {
return this._getLogFunction(logLevel, table, console.table || noop, columns && [columns], {
tag: getTableHeader(table)
});
}
return noop;
}
time(logLevel, message) {
return this._getLogFunction(logLevel, message, console.time ? console.time : console.info);
}
timeEnd(logLevel, message) {
return this._getLogFunction(logLevel, message, console.timeEnd ? console.timeEnd : console.info);
}
timeStamp(logLevel, message) {
return this._getLogFunction(logLevel, message, console.timeStamp || noop);
}
group(logLevel, message, opts = { collapsed: false }) {
const options = normalizeArguments({ logLevel, message, opts });
const { collapsed } = opts;
options.method = (collapsed ? console.groupCollapsed : console.group) || console.info;
return this._getLogFunction(options);
}
groupCollapsed(logLevel, message, opts = {}) {
return this.group(logLevel, message, Object.assign({}, opts, { collapsed: true }));
}
groupEnd(logLevel) {
return this._getLogFunction(logLevel, "", console.groupEnd || noop);
}
// EXPERIMENTAL
withGroup(logLevel, message, func) {
this.group(logLevel, message)();
try {
func();
} finally {
this.groupEnd(logLevel)();
}
}
trace() {
if (console.trace) {
console.trace();
}
}
// PRIVATE METHODS
/** Deduces log level from a variety of arguments */
_shouldLog(logLevel) {
return this.isEnabled() && this.getLevel() >= normalizeLogLevel(logLevel);
}
_getLogFunction(logLevel, message, method, args, opts) {
if (this._shouldLog(logLevel)) {
opts = normalizeArguments({ logLevel, message, args, opts });
method = method || opts.method;
assert(method);
opts.total = this.getTotal();
opts.delta = this.getDelta();
this._deltaTs = getHiResTimestamp2();
const tag = opts.tag || opts.message;
if (opts.once && tag) {
if (!cache[tag]) {
cache[tag] = getHiResTimestamp2();
} else {
return noop;
}
}
message = decorateMessage(this.id, opts.message, opts);
return method.bind(console, message, ...opts.args);
}
return noop;
}
};
Log.VERSION = VERSION;
function normalizeLogLevel(logLevel) {
if (!logLevel) {
return 0;
}
let resolvedLevel;
switch (typeof logLevel) {
case "number":
resolvedLevel = logLevel;
break;
case "object":
resolvedLevel = logLevel.logLevel || logLevel.priority || 0;
break;
default:
return 0;
}
assert(Number.isFinite(resolvedLevel) && resolvedLevel >= 0);
return resolvedLevel;
}
function normalizeArguments(opts) {
const { logLevel, message } = opts;
opts.logLevel = normalizeLogLevel(logLevel);
const args = opts.args ? Array.from(opts.args) : [];
while (args.length && args.shift() !== message) {
}
switch (typeof logLevel) {
case "string":
case "function":
if (message !== void 0) {
args.unshift(message);
}
opts.message = logLevel;
break;
case "object":
Object.assign(opts, logLevel);
break;
default:
}
if (typeof opts.message === "function") {
opts.message = opts.message();
}
const messageType = typeof opts.message;
assert(messageType === "string" || messageType === "object");
return Object.assign(opts, { args }, opts.opts);
}
function decorateMessage(id, message, opts) {
if (typeof message === "string") {
const time = opts.time ? leftPad(formatTime(opts.total)) : "";
message = opts.time ? `${id}: ${time} ${message}` : `${id}: ${message}`;
message = addColor(message, opts.color, opts.background);
}
return message;
}
function getTableHeader(table) {
for (const key in table) {
for (const title in table[key]) {
return title || "untitled";
}
}
return "empty";
}
// ../../node_modules/@probe.gl/log/dist/init.js
globalThis.probe = {};
// ../../node_modules/@probe.gl/log/dist/index.js
var dist_default = new Log({ id: "@probe.gl/log" });
// ../core/src/utils/log.ts
var log = new Log({ id: "luma.gl" });
// ../core/src/utils/uid.ts
var uidCounters = {};
function uid(id = "id") {
uidCounters[id] = uidCounters[id] || 1;
const count = uidCounters[id]++;
return `${id}-${count}`;
}
// ../core/src/adapter/resources/resource.ts
var Resource = class {
toString() {
return `${this[Symbol.toStringTag] || this.constructor.name}:"${this.id}"`;
}
/** props.id, for debugging. */
id;
props;
userData = {};
_device;
/** Whether this resource has been destroyed */
destroyed = false;
/** For resources that allocate GPU memory */
allocatedBytes = 0;
/** Attached resources will be destroyed when this resource is destroyed. Tracks auto-created "sub" resources. */
_attachedResources = /* @__PURE__ */ new Set();
/**
* Create a new Resource. Called from Subclass
*/
constructor(device, props, defaultProps) {
if (!device) {
throw new Error("no device");
}
this._device = device;
this.props = selectivelyMerge(props, defaultProps);
const id = this.props.id !== "undefined" ? this.props.id : uid(this[Symbol.toStringTag]);
this.props.id = id;
this.id = id;
this.userData = this.props.userData || {};
this.addStats();
}
/**
* destroy can be called on any resource to release it before it is garbage collected.
*/
destroy() {
this.destroyResource();
}
/** @deprecated Use destroy() */
delete() {
this.destroy();
return this;
}
/**
* Combines a map of user props and default props, only including props from defaultProps
* @returns returns a map of overridden default props
*/
getProps() {
return this.props;
}
// ATTACHED RESOURCES
/**
* Attaches a resource. Attached resources are auto destroyed when this resource is destroyed
* Called automatically when sub resources are auto created but can be called by application
*/
attachResource(resource) {
this._attachedResources.add(resource);
}
/**
* Detach an attached resource. The resource will no longer be auto-destroyed when this resource is destroyed.
*/
detachResource(resource) {
this._attachedResources.delete(resource);
}
/**
* Destroys a resource (only if owned), and removes from the owned (auto-destroy) list for this resource.
*/
destroyAttachedResource(resource) {
if (this._attachedResources.delete(resource)) {
resource.destroy();
}
}
/** Destroy all owned resources. Make sure the resources are no longer needed before calling. */
destroyAttachedResources() {
for (const resource of Object.values(this._attachedResources)) {
resource.destroy();
}
this._attachedResources = /* @__PURE__ */ new Set();
}
// PROTECTED METHODS
/** Perform all destroy steps. Can be called by derived resources when overriding destroy() */
destroyResource() {
this.destroyAttachedResources();
this.removeStats();
this.destroyed = true;
}
/** Called by .destroy() to track object destruction. Subclass must call if overriding destroy() */
removeStats() {
const stats = this._device.statsManager.getStats("Resource Counts");
const name2 = this[Symbol.toStringTag];
stats.get(`${name2}s Active`).decrementCount();
}
/** Called by subclass to track memory allocations */
trackAllocatedMemory(bytes, name2 = this[Symbol.toStringTag]) {
const stats = this._device.statsManager.getStats("Resource Counts");
stats.get("GPU Memory").addCount(bytes);
stats.get(`${name2} Memory`).addCount(bytes);
this.allocatedBytes = bytes;
}
/** Called by subclass to track memory deallocations */
trackDeallocatedMemory(name2 = this[Symbol.toStringTag]) {
const stats = this._device.statsManager.getStats("Resource Counts");
stats.get("GPU Memory").subtractCount(this.allocatedBytes);
stats.get(`${name2} Memory`).subtractCount(this.allocatedBytes);
this.allocatedBytes = 0;
}
/** Called by resource constructor to track object creation */
addStats() {
const stats = this._device.statsManager.getStats("Resource Counts");
const name2 = this[Symbol.toStringTag];
stats.get("Resources Created").incrementCount();
stats.get(`${name2}s Created`).incrementCount();
stats.get(`${name2}s Active`).incrementCount();
}
};
/** Default properties for resource */
__publicField(Resource, "defaultProps", {
id: "undefined",
handle: void 0,
userData: void 0
});
function selectivelyMerge(props, defaultProps) {
const mergedProps = { ...defaultProps };
for (const key in props) {
if (props[key] !== void 0) {
mergedProps[key] = props[key];
}
}
return mergedProps;
}
// ../core/src/adapter/resources/buffer.ts
var _Buffer = class extends Resource {
get [Symbol.toStringTag]() {
return "Buffer";
}
/** The usage with which this buffer was created */
usage;
/** For index buffers, whether indices are 16 or 32 bit */
indexType;
/** "Time" of last update, can be used to check if redraw is needed */
updateTimestamp;
constructor(device, props) {
const deducedProps = { ...props };
if ((props.usage || 0) & _Buffer.INDEX && !props.indexType) {
if (props.data instanceof Uint32Array) {
deducedProps.indexType = "uint32";
} else if (props.data instanceof Uint16Array) {
deducedProps.indexType = "uint16";
}
}
delete deducedProps.data;
super(device, deducedProps, _Buffer.defaultProps);
this.usage = deducedProps.usage || 0;
this.indexType = deducedProps.indexType;
this.updateTimestamp = device.incrementTimestamp();
}
/**
* Create a copy of this Buffer with new byteLength, with same props but of the specified size.
* @note Does not copy contents of the cloned Buffer.
*/
clone(props) {
return this.device.createBuffer({ ...this.props, ...props });
}
/** A partial CPU-side copy of the data in this buffer, for debugging purposes */
debugData = new ArrayBuffer(0);
/** This doesn't handle partial non-zero offset updates correctly */
_setDebugData(data, byteOffset, byteLength) {
const arrayBuffer2 = ArrayBuffer.isView(data) ? data.buffer : data;
const debugDataLength = Math.min(
data ? data.byteLength : byteLength,
_Buffer.DEBUG_DATA_MAX_LENGTH
);
if (arrayBuffer2 === null) {
this.debugData = new ArrayBuffer(debugDataLength);
} else if (byteOffset === 0 && byteLength === arrayBuffer2.byteLength) {
this.debugData = arrayBuffer2.slice(0, debugDataLength);
} else {
this.debugData = arrayBuffer2.slice(byteOffset, byteOffset + debugDataLength);
}
}
};
var Buffer2 = _Buffer;
/** Index buffer */
__publicField(Buffer2, "INDEX", 16);
/** Vertex buffer */
__publicField(Buffer2, "VERTEX", 32);
/** Uniform buffer */
__publicField(Buffer2, "UNIFORM", 64);
/** Storage buffer */
__publicField(Buffer2, "STORAGE", 128);
__publicField(Buffer2, "INDIRECT", 256);
__publicField(Buffer2, "QUERY_RESOLVE", 512);
// Usage Flags
__publicField(Buffer2, "MAP_READ", 1);
__publicField(Buffer2, "MAP_WRITE", 2);
__publicField(Buffer2, "COPY_SRC", 4);
__publicField(Buffer2, "COPY_DST", 8);
// PROTECTED METHODS (INTENDED FOR USE BY OTHER FRAMEWORK CODE ONLY)
/** Max amount of debug data saved. Two vec4's */
__publicField(Buffer2, "DEBUG_DATA_MAX_LENGTH", 32);
__publicField(Buffer2, "defaultProps", {
...Resource.defaultProps,
usage: 0,
// Buffer.COPY_DST | Buffer.COPY_SRC
byteLength: 0,
byteOffset: 0,
data: null,
indexType: "uint16",
onMapped: void 0
});
// ../core/src/shadertypes/data-types/decode-data-types.ts
function getDataTypeInfo(type) {
const [signedType, primitiveType, byteLength] = NORMALIZED_TYPE_MAP[type];
const normalized = type.includes("norm");
const integer = !normalized && !type.startsWith("float");
const signed = type.startsWith("s");
return {
signedType,
primitiveType,
byteLength,
normalized,
integer,
signed
};
}
function getNormalizedDataType(signedDataType) {
const dataType = signedDataType;
switch (dataType) {
case "uint8":
return "unorm8";
case "sint8":
return "snorm8";
case "uint16":
return "unorm16";
case "sint16":
return "snorm16";
default:
return dataType;
}
}
function alignTo(size, count) {
switch (count) {
case 1:
return size;
case 2:
return size + size % 2;
default:
return size + (4 - size % 4) % 4;
}
}
function getDataType(arrayOrType) {
const Constructor = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
if (Constructor === Uint8ClampedArray) {
return "uint8";
}
const info = Object.values(NORMALIZED_TYPE_MAP).find((entry) => Constructor === entry[4]);
if (!info) {
throw new Error(Constructor.name);
}
return info[0];
}
function getTypedArrayConstructor(type) {
const [, , , , Constructor] = NORMALIZED_TYPE_MAP[type];
return Constructor;
}
var NORMALIZED_TYPE_MAP = {
uint8: ["uint8", "u32", 1, false, Uint8Array],
sint8: ["sint8", "i32", 1, false, Int8Array],
unorm8: ["uint8", "f32", 1, true, Uint8Array],
snorm8: ["sint8", "f32", 1, true, Int8Array],
uint16: ["uint16", "u32", 2, false, Uint16Array],
sint16: ["sint16", "i32", 2, false, Int16Array],
unorm16: ["uint16", "u32", 2, true, Uint16Array],
snorm16: ["sint16", "i32", 2, true, Int16Array],
float16: ["float16", "f16", 2, false, Uint16Array],
float32: ["float32", "f32", 4, false, Float32Array],
uint32: ["uint32", "u32", 4, false, Uint32Array],
sint32: ["sint32", "i32", 4, false, Int32Array]
};
// ../core/src/shadertypes/vertex-arrays/decode-vertex-format.ts
function getVertexFormatInfo(format) {
let webglOnly;
if (format.endsWith("-webgl")) {
format.replace("-webgl", "");
webglOnly = true;
}
const [type_, count] = format.split("x");
const type = type_;
const components = count ? parseInt(count) : 1;
const decodedType = getDataTypeInfo(type);
const result = {
type,
components,
byteLength: decodedType.byteLength * components,
integer: decodedType.integer,
signed: decodedType.signed,
normalized: decodedType.normalized
};
if (webglOnly) {
result.webglOnly = true;
}
return result;
}
function makeVertexFormat(signedDataType, components, normalized) {
const dataType = normalized ? getNormalizedDataType(signedDataType) : signedDataType;
switch (dataType) {
case "unorm8":
if (components === 1) {
return "unorm8";
}
if (components === 3) {
return "unorm8x3-webgl";
}
return `${dataType}x${components}`;
case "snorm8":
case "uint8":
case "sint8":
case "uint16":
case "sint16":
case "unorm16":
case "snorm16":
case "float16":
if (components === 1 || components === 3) {
throw new Error(`size: ${components}`);
}
return `${dataType}x${components}`;
default:
return components === 1 ? dataType : `${dataType}x${components}`;
}
}
function getVertexFormatFromAttribute(typedArray, size, normalized) {
if (!size || size > 4) {
throw new Error(`size ${size}`);
}
const components = size;
const signedDataType = getDataType(typedArray);
return makeVertexFormat(signedDataType, components, normalized);
}
function getCompatibleVertexFormat(opts) {
let vertexType;
switch (opts.primitiveType) {
case "f32":
vertexType = "float32";
break;
case "i32":
vertexType = "sint32";
break;
case "u32":
vertexType = "uint32";
break;
case "f16":
return opts.components <= 2 ? "float16x2" : "float16x4";
}
if (opts.components === 1) {
return vertexType;
}
return `${vertexType}x${opts.components}`;
}
// ../core/src/shadertypes/textures/texture-format-table.ts
var texture_compression_bc = "texture-compression-bc";
var texture_compression_astc = "texture-compression-astc";
var texture_compression_etc2 = "texture-compression-etc2";
var texture_compression_etc1_webgl = "texture-compression-etc1-webgl";
var texture_compression_pvrtc_webgl = "texture-compression-pvrtc-webgl";
var texture_compression_atc_webgl = "texture-compression-atc-webgl";
var float32_renderable = "float32-renderable-webgl";
var float16_renderable = "float16-renderable-webgl";
var rgb9e5ufloat_renderable = "rgb9e5ufloat-renderable-webgl";
var snorm8_renderable = "snorm8-renderable-webgl";
var norm16_renderable = "norm16-renderable-webgl";
var snorm16_renderable = "snorm16-renderable-webgl";
var float32_filterable = "float32-filterable";
var float16_filterable = "float16-filterable-webgl";
function getTextureFormatDefinition(format) {
const info = TEXTURE_FORMAT_TABLE[format];
if (!info) {
throw new Error(`Unsupported texture format ${format}`);
}
return info;
}
function getTextureFormatTable() {
return TEXTURE_FORMAT_TABLE;
}
var TEXTURE_FORMAT_COLOR_DEPTH_TABLE = {
// 8-bit formats
"r8unorm": {},
"rg8unorm": {},
"rgb8unorm-webgl": {},
"rgba8unorm": {},
"rgba8unorm-srgb": {},
"r8snorm": { render: snorm8_renderable },
"rg8snorm": { render: snorm8_renderable },
"rgb8snorm-webgl": {},
"rgba8snorm": { render: snorm8_renderable },
"r8uint": {},
"rg8uint": {},
"rgba8uint": {},
"r8sint": {},
"rg8sint": {},
"rgba8sint": {},
"bgra8unorm": {},
"bgra8unorm-srgb": {},
"r16unorm": { f: norm16_renderable },
"rg16unorm": { render: norm16_renderable },
"rgb16unorm-webgl": { f: norm16_renderable },
// rgb not renderable
"rgba16unorm": { render: norm16_renderable },
"r16snorm": { f: snorm16_renderable },
"rg16snorm": { render: snorm16_renderable },
"rgb16snorm-webgl": { f: norm16_renderable },
// rgb not renderable
"rgba16snorm": { render: snorm16_renderable },
"r16uint": {},
"rg16uint": {},
"rgba16uint": {},
"r16sint": {},
"rg16sint": {},
"rgba16sint": {},
"r16float": { render: float16_renderable, filter: "float16-filterable-webgl" },
"rg16float": { render: float16_renderable, filter: float16_filterable },
"rgba16float": { render: float16_renderable, filter: float16_filterable },
"r32uint": {},
"rg32uint": {},
"rgba32uint": {},
"r32sint": {},
"rg32sint": {},
"rgba32sint": {},
"r32float": { render: float32_renderable, filter: float32_filterable },
"rg32float": { render: false, filter: float32_filterable },
"rgb32float-webgl": { render: float32_renderable, filter: float32_filterable },
"rgba32float": { render: float32_renderable, filter: float32_filterable },
// Packed 16-bit formats
"rgba4unorm-webgl": { channels: "rgba", bitsPerChannel: [4, 4, 4, 4], packed: true },
"rgb565unorm-webgl": { channels: "rgb", bitsPerChannel: [5, 6, 5, 0], packed: true },
"rgb5a1unorm-webgl": { channels: "rgba", bitsPerChannel: [5, 5, 5, 1], packed: true },
// Packed 32 bit formats
"rgb9e5ufloat": { channels: "rgb", packed: true, render: rgb9e5ufloat_renderable },
// , filter: true},
"rg11b10ufloat": { channels: "rgb", bitsPerChannel: [11, 11, 10, 0], packed: true, p: 1, render: float32_renderable },
"rgb10a2unorm": { channels: "rgba", bitsPerChannel: [10, 10, 10, 2], packed: true, p: 1 },
"rgb10a2uint": { channels: "rgba", bitsPerChannel: [10, 10, 10, 2], packed: true, p: 1 },
// Depth/stencil Formats
// Depth and stencil formats
stencil8: { attachment: "stencil", bitsPerChannel: [8, 0, 0, 0], dataType: "uint8" },
"depth16unorm": { attachment: "depth", bitsPerChannel: [16, 0, 0, 0], dataType: "uint16" },
"depth24plus": { attachment: "depth", bitsPerChannel: [24, 0, 0, 0], dataType: "uint32" },
"depth32float": { attachment: "depth", bitsPerChannel: [32, 0, 0, 0], dataType: "float32" },
// The depth component of the "depth24plus" and "depth24plus-stencil8" formats may be implemented as either a 24-bit depth value or a "depth32float" value.
"depth24plus-stencil8": { attachment: "depth-stencil", bitsPerChannel: [24, 8, 0, 0], packed: true },
// "depth32float-stencil8" feature
"depth32float-stencil8": { attachment: "depth-stencil", bitsPerChannel: [32, 8, 0, 0], packed: true }
};
var TEXTURE_FORMAT_COMPRESSED_TABLE = {
// BC compressed formats: check device.features.has("texture-compression-bc");
"bc1-rgb-unorm-webgl": { f: texture_compression_bc },
"bc1-rgb-unorm-srgb-webgl": { f: texture_compression_bc },
"bc1-rgba-unorm": { f: texture_compression_bc },
"bc1-rgba-unorm-srgb": { f: texture_compression_bc },
"bc2-rgba-unorm": { f: texture_compression_bc },
"bc2-rgba-unorm-srgb": { f: texture_compression_bc },
"bc3-rgba-unorm": { f: texture_compression_bc },
"bc3-rgba-unorm-srgb": { f: texture_compression_bc },
"bc4-r-unorm": { f: texture_compression_bc },
"bc4-r-snorm": { f: texture_compression_bc },
"bc5-rg-unorm": { f: texture_compression_bc },
"bc5-rg-snorm": { f: texture_compression_bc },
"bc6h-rgb-ufloat": { f: texture_compression_bc },
"bc6h-rgb-float": { f: texture_compression_bc },
"bc7-rgba-unorm": { f: texture_compression_bc },
"bc7-rgba-unorm-srgb": { f: texture_compression_bc },
// WEBGL_compressed_texture_etc: device.features.has("texture-compression-etc2")
// Note: Supposedly guaranteed availability compressed formats in WebGL2, but through CPU decompression
"etc2-rgb8unorm": { f: texture_compression_etc2 },
"etc2-rgb8unorm-srgb": { f: texture_compression_etc2 },
"etc2-rgb8a1unorm": { f: texture_compression_etc2 },
"etc2-rgb8a1unorm-srgb": { f: texture_compression_etc2 },
"etc2-rgba8unorm": { f: texture_compression_etc2 },
"etc2-rgba8unorm-srgb": { f: texture_compression_etc2 },
"eac-r11unorm": { f: texture_compression_etc2 },
"eac-r11snorm": { f: texture_compression_etc2 },
"eac-rg11unorm": { f: texture_compression_etc2 },
"eac-rg11snorm": { f: texture_compression_etc2 },
// X_ASTC compressed formats: device.features.has("texture-compression-astc")
"astc-4x4-unorm": { f: texture_compression_astc },
"astc-4x4-unorm-srgb": { f: texture_compression_astc },
"astc-5x4-unorm": { f: texture_compression_astc },
"astc-5x4-unorm-srgb": { f: texture_compression_astc },
"astc-5x5-unorm": { f: texture_compression_astc },
"astc-5x5-unorm-srgb": { f: texture_compression_astc },
"astc-6x5-unorm": { f: texture_compression_astc },
"astc-6x5-unorm-srgb": { f: texture_compression_astc },
"astc-6x6-unorm": { f: texture_compression_astc },
"astc-6x6-unorm-srgb": { f: texture_compression_astc },
"astc-8x5-unorm": { f: texture_compression_astc },
"astc-8x5-unorm-srgb": { f: texture_compression_astc },
"astc-8x6-unorm": { f: texture_compression_astc },
"astc-8x6-unorm-srgb": { f: texture_compression_astc },
"astc-8x8-unorm": { f: texture_compression_astc },
"astc-8x8-unorm-srgb": { f: texture_compression_astc },
"astc-10x5-unorm": { f: texture_compression_astc },
"astc-10x5-unorm-srgb": { f: texture_compression_astc },
"astc-10x6-unorm": { f: texture_compression_astc },
"astc-10x6-unorm-srgb": { f: texture_compression_astc },
"astc-10x8-unorm": { f: texture_compression_astc },
"astc-10x8-unorm-srgb": { f: texture_compression_astc },
"astc-10x10-unorm": { f: texture_compression_astc },
"astc-10x10-unorm-srgb": { f: texture_compression_astc },
"astc-12x10-unorm": { f: texture_compression_astc },
"astc-12x10-unorm-srgb": { f: texture_compression_astc },
"astc-12x12-unorm": { f: texture_compression_astc },
"astc-12x12-unorm-srgb": { f: texture_compression_astc },
// WEBGL_compressed_texture_pvrtc
"pvrtc-rgb4unorm-webgl": { f: texture_compression_pvrtc_webgl },
"pvrtc-rgba4unorm-webgl": { f: texture_compression_pvrtc_webgl },
"pvrtc-rbg2unorm-webgl": { f: texture_compression_pvrtc_webgl },
"pvrtc-rgba2unorm-webgl": { f: texture_compression_pvrtc_webgl },
// WEBGL_compressed_texture_etc1
"etc1-rbg-unorm-webgl": { f: texture_compression_etc1_webgl },
// WEBGL_compressed_texture_atc
"atc-rgb-unorm-webgl": { f: texture_compression_atc_webgl },
"atc-rgba-unorm-webgl": { f: texture_compression_atc_webgl },
"atc-rgbai-unorm-webgl": { f: texture_compression_atc_webgl }
};
var TEXTURE_FORMAT_TABLE = {
...TEXTURE_FORMAT_COLOR_DEPTH_TABLE,
...TEXTURE_FORMAT_COMPRESSED_TABLE
};
// ../core/src/shadertypes/textures/texture-format-decoder.ts
var COMPRESSED_TEXTURE_FORMAT_PREFIXES = [
"bc1",
"bc2",
"bc3",
"bc4",
"bc5",
"bc6",
"bc7",
"etc1",
"etc2",
"eac",
"atc",
"astc",
"pvrtc"
];
var RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
var TextureFormatDecoder = class {
/** Returns information about a texture format, e.g. attatchment type, components, byte length and flags (integer, signed, normalized) */
getInfo(format) {
return getTextureFormatInfo(format);
}
/** Checks if a texture format is color */
isColor(format) {
return format.startsWith("rgba") || format.startsWith("bgra") || format.startsWith("rgb");
}
/** Checks if a texture format is depth or stencil */
isDepthStencil(format) {
return format.startsWith("depth") || format.startsWith("stencil");
}
/** Checks if a texture format is compressed */
isCompressed(format) {
return COMPRESSED_TEXTURE_FORMAT_PREFIXES.some((prefix) => format.startsWith(prefix));
}
/**
* Returns the "static" capabilities of a texture format.
* @note Needs to be checked against current device
*/
getCapabilities(format) {
const info = getTextureFormatDefinition(format);
const formatCapabilities = {
format,
create: info.f ?? true,
render: info.render ?? true,
filter: info.filter ?? true,
blend: info.blend ?? true,
store: info.store ?? true
};
const formatInfo = getTextureFormatInfo(format);
const isDepthStencil = format.startsWith("depth") || format.startsWith("stencil");
const isSigned = formatInfo?.signed;
const isInteger = formatInfo?.integer;
const isWebGLSpecific = formatInfo?.webgl;
formatCapabilities.render &&= !isSigned;
formatCapabilities.filter &&= !isDepthStencil && !isSigned && !isInteger && !isWebGLSpecific;
return formatCapabilities;
}
};
var textureFormatDecoder = new TextureFormatDecoder();
function getTextureFormatInfo(format) {
let formatInfo = getTextureFormatInfoUsingTable(format);
if (textureFormatDecoder.isCompressed(format)) {
formatInfo.channels = "rgb";
formatInfo.components = 3;
formatInfo.bytesPerPixel = 1;
formatInfo.srgb = false;
formatInfo.compressed = true;
const blockSize = getCompressedTextureBlockSize(format);
if (blockSize) {
formatInfo.blockWidth = blockSize.blockWidth;
formatInfo.blockHeight = blockSize.blockHeight;
}
}
const matches = RGB_FORMAT_REGEX.exec(format);
if (matches) {
const [, channels, length, type, srgb, suffix] = matches;
const dataType = `${type}${length}`;
const decodedType = getDataTypeInfo(dataType);
const bits = decodedType.byteLength * 8;
const components = channels.length;
const bitsPerChannel = [
bits,
components >= 2 ? bits : 0,
components >= 3 ? bits : 0,
components >= 4 ? bits : 0
];
formatInfo = {
format,
attachment: formatInfo.attachment,
dataType: decodedType.signedType,
components,
channels,
integer: decodedType.integer,
signed: decodedType.signed,
normalized: decodedType.normalized,
bitsPerChannel,
bytesPerPixel: decodedType.byteLength * channels.length,
packed: formatInfo.packed,
srgb: formatInfo.srgb
};
if (suffix === "-webgl") {
formatInfo.webgl = true;
}
if (srgb === "-srgb") {
formatInfo.srgb = true;
}
}
if (format.endsWith("-webgl")) {
formatInfo.webgl = true;
}
if (format.endsWith("-srgb")) {
formatInfo.srgb = true;
}
return formatInfo;
}
function getTextureFormatInfoUsingTable(format) {
const info = getTextureFormatDefinition(format);
const bytesPerPixel = info.bytesPerPixel || 1;
const bitsPerChannel = info.bitsPerChannel || [8, 8, 8, 8];
delete info.bitsPerChannel;
delete info.bytesPerPixel;
delete info.f;
delete info.render;
delete info.filter;
delete info.blend;
delete info.store;
const formatInfo = {
...info,
format,
attachment: info.attachment || "color",
channels: info.channels || "r",
components: info.components || info.channels?.length || 1,
bytesPerPixel,
bitsPerChannel,
dataType: info.dataType || "uint8",
srgb: info.srgb ?? false,
packed: info.packed ?? false,
webgl: info.webgl ?? false,
integer: info.integer ?? false,
signed: info.signed ?? false,
normalized: info.normalized ?? false,
compressed: info.compressed ?? false