playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
93 lines (92 loc) • 3.16 kB
JavaScript
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
};