UNPKG

@luma.gl/core

Version:

The luma.gl core Device API

84 lines 3.19 kB
// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import { Shader } from "../adapter/resources/shader.js"; import { log } from "../utils/log.js"; /** Manages a cached pool of Shaders for reuse. */ export class ShaderFactory { static defaultProps = { ...Shader.defaultProps }; /** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */ static getDefaultShaderFactory(device) { const moduleData = device.getModuleData('@luma.gl/core'); moduleData.defaultShaderFactory ||= new ShaderFactory(device); return moduleData.defaultShaderFactory; } device; _cache = {}; get [Symbol.toStringTag]() { return 'ShaderFactory'; } toString() { return `${this[Symbol.toStringTag]}(${this.device.id})`; } /** @internal */ constructor(device) { this.device = device; } /** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */ createShader(props) { if (!this.device.props._cacheShaders) { return this.device.createShader(props); } const key = this._hashShader(props); let cacheEntry = this._cache[key]; if (!cacheEntry) { const resource = this.device.createShader({ ...props, id: props.id ? `${props.id}-cached` : undefined }); this._cache[key] = cacheEntry = { resource, useCount: 1 }; if (this.device.props.debugFactories) { log.log(3, `${this}: Created new shader ${resource.id}`)(); } } else { cacheEntry.useCount++; if (this.device.props.debugFactories) { log.log(3, `${this}: Reusing shader ${cacheEntry.resource.id} count=${cacheEntry.useCount}`)(); } } return cacheEntry.resource; } /** Releases a previously-requested {@link Shader}, destroying it if no users remain. */ release(shader) { if (!this.device.props._cacheShaders) { shader.destroy(); return; } const key = this._hashShader(shader); const cacheEntry = this._cache[key]; if (cacheEntry) { cacheEntry.useCount--; if (cacheEntry.useCount === 0) { if (this.device.props._destroyShaders) { delete this._cache[key]; cacheEntry.resource.destroy(); if (this.device.props.debugFactories) { log.log(3, `${this}: Releasing shader ${shader.id}, destroyed`)(); } } } else if (cacheEntry.useCount < 0) { throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`); } else if (this.device.props.debugFactories) { log.log(3, `${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)(); } } } // PRIVATE _hashShader(value) { return `${value.stage}:${value.source}`; } } //# sourceMappingURL=shader-factory.js.map