UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

93 lines (92 loc) 3.16 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { array } from "../../../core/array-utils.js"; import { Debug, DebugHelper } from "../../../core/debug.js"; import { TRACEID_COMPUTEPIPELINE_ALLOC } from "../../../core/constants.js"; import { hash32Fnv1a } from "../../../core/hash.js"; import { WebgpuDebug } from "./webgpu-debug.js"; import { WebgpuPipeline } from "./webgpu-pipeline.js"; let _pipelineId = 0; class CacheEntry { constructor() { /** * Compute pipeline * * @type {GPUComputePipeline|null} * @private */ __publicField(this, "pipeline", null); /** * The full array of hashes used to lookup the pipeline, used in case of hash collision. * * @type {Uint32Array|null} */ __publicField(this, "hashes", null); } } class WebgpuComputePipeline extends WebgpuPipeline { constructor() { super(...arguments); __publicField(this, "lookupHashes", new Uint32Array(2)); /** * The cache of compute pipelines * * @type {Map<number, CacheEntry[]>} */ __publicField(this, "cache", /* @__PURE__ */ new Map()); } get(shader, bindGroupFormat) { const lookupHashes = this.lookupHashes; lookupHashes[0] = shader.impl.computeKey; lookupHashes[1] = bindGroupFormat.impl.key; const hash = hash32Fnv1a(lookupHashes); let cacheEntries = this.cache.get(hash); if (cacheEntries) { for (let i = 0; i < cacheEntries.length; i++) { const entry = cacheEntries[i]; if (array.equals(entry.hashes, lookupHashes)) { return entry.pipeline; } } } const pipelineLayout = this.getPipelineLayout([bindGroupFormat.impl]); const cacheEntry = new CacheEntry(); cacheEntry.hashes = new Uint32Array(lookupHashes); cacheEntry.pipeline = this.create(shader, pipelineLayout); if (cacheEntries) { cacheEntries.push(cacheEntry); } else { cacheEntries = [cacheEntry]; } this.cache.set(hash, cacheEntries); return cacheEntry.pipeline; } create(shader, pipelineLayout) { const wgpu = this.device.wgpu; const webgpuShader = shader.impl; const desc = { compute: { module: webgpuShader.getComputeShaderModule(), entryPoint: webgpuShader.computeEntryPoint }, // uniform / texture binding layout layout: pipelineLayout }; WebgpuDebug.validate(this.device); _pipelineId++; DebugHelper.setLabel(desc, `ComputePipelineDescr-${_pipelineId}`); const pipeline = wgpu.createComputePipeline(desc); DebugHelper.setLabel(pipeline, `ComputePipeline-${_pipelineId}`); Debug.trace(TRACEID_COMPUTEPIPELINE_ALLOC, `Alloc: Id ${_pipelineId}`, desc); WebgpuDebug.end(this.device, "ComputePipeline creation", { computePipeline: this, desc, shader }); return pipeline; } } export { WebgpuComputePipeline };