UNPKG

playcanvas

Version:

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

69 lines (68 loc) 2.91 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 { Debug, DebugHelper } from "../../../core/debug.js"; import { BindGroup } from "../bind-group.js"; import { DebugGraphics } from "../debug-graphics.js"; import { UniformBuffer } from "../uniform-buffer.js"; const _indirectDispatchEntryByteSize = 3 * 4; class WebgpuCompute { constructor(compute) { /** @type {UniformBuffer[]} */ __publicField(this, "uniformBuffers", []); /** @type {BindGroup} */ __publicField(this, "bindGroup", null); this.compute = compute; const { device, shader } = compute; DebugGraphics.pushGpuMarker(device, `Compute:${compute.name}`); const { computeBindGroupFormat, computeUniformBufferFormats } = shader.impl; Debug.assert(computeBindGroupFormat, "Compute shader does not have computeBindGroupFormat specified", shader); this.bindGroup = new BindGroup(device, computeBindGroupFormat); DebugHelper.setName(this.bindGroup, `Compute-BindGroup_${this.bindGroup.id}`); if (computeUniformBufferFormats) { for (const name in computeUniformBufferFormats) { if (computeUniformBufferFormats.hasOwnProperty(name)) { const ub = new UniformBuffer(device, computeUniformBufferFormats[name], true); this.uniformBuffers.push(ub); this.bindGroup.setUniformBuffer(name, ub); } } } this.pipeline = device.computePipeline.get(shader, computeBindGroupFormat); DebugGraphics.popGpuMarker(device); } destroy() { this.uniformBuffers.forEach((ub) => ub.destroy()); this.uniformBuffers.length = 0; this.bindGroup.destroy(); this.bindGroup = null; } updateBindGroup() { const { bindGroup } = this; bindGroup.updateUniformBuffers(); bindGroup.update(); } dispatch(x, y, z) { const device = this.compute.device; device.setBindGroup(0, this.bindGroup); const passEncoder = device.passEncoder; passEncoder.setPipeline(this.pipeline); const { indirectSlotIndex, indirectBuffer, indirectFrameStamp } = this.compute; if (indirectSlotIndex >= 0) { let gpuBuffer; if (indirectBuffer) { gpuBuffer = indirectBuffer.impl.buffer; } else { Debug.assert(indirectFrameStamp === device.renderVersion, "Indirect dispatch slot must be set each frame using setupIndirectDispatch()"); gpuBuffer = device.indirectDispatchBuffer.impl.buffer; } const offset = indirectSlotIndex * _indirectDispatchEntryByteSize; passEncoder.dispatchWorkgroupsIndirect(gpuBuffer, offset); } else { passEncoder.dispatchWorkgroups(x, y, z); } } } export { WebgpuCompute };