UNPKG

playcanvas

Version:

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

84 lines (83 loc) 3.08 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 { BUFFERUSAGE_COPY_DST, BUFFERUSAGE_INDIRECT } from "../constants.js"; import { StorageBuffer } from "../storage-buffer.js"; import { DebugHelper } from "../../../core/debug.js"; class WebgpuDrawCommands { /** * @param {GraphicsDevice} device - Graphics device. */ constructor(device) { /** @type {GraphicsDevice} */ __publicField(this, "device"); /** @type {Uint32Array|null} */ __publicField(this, "gpuIndirect", null); /** @type {Int32Array|null} */ __publicField(this, "gpuIndirectSigned", null); /** * @type {StorageBuffer|null} */ __publicField(this, "storage", null); this.device = device; } /** * Allocate AoS buffer and backing storage buffer. * @param {number} maxCount - Number of sub-draws. */ allocate(maxCount) { if (this.gpuIndirect && this.gpuIndirect.length === 5 * maxCount) { return; } this.storage?.destroy(); this.gpuIndirect = new Uint32Array(5 * maxCount); this.gpuIndirectSigned = new Int32Array(this.gpuIndirect.buffer); this.storage = new StorageBuffer(this.device, this.gpuIndirect.byteLength, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST); DebugHelper.setName(this.storage, "WebgpuDrawCommands.indirectStorage"); } /** * Write a single draw entry. * @param {number} i - Draw index. * @param {number} indexOrVertexCount - Count of indices/vertices. * @param {number} instanceCount - Instance count. * @param {number} firstIndexOrVertex - First index/vertex. * @param {number} baseVertex - Base vertex (signed). * @param {number} firstInstance - First instance. */ add(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex = 0, firstInstance = 0) { const o = i * 5; this.gpuIndirect[o + 0] = indexOrVertexCount; this.gpuIndirect[o + 1] = instanceCount; this.gpuIndirect[o + 2] = firstIndexOrVertex; this.gpuIndirectSigned[o + 3] = baseVertex; this.gpuIndirect[o + 4] = firstInstance; } /** * Upload AoS data to storage buffer. * @param {number} count - Number of active draws. * @returns {number} Total primitive count. */ update(count) { if (this.storage && count > 0) { const used = count * 5; this.storage.write(0, this.gpuIndirect, 0, used); } let totalPrimitives = 0; if (this.gpuIndirect && count > 0) { for (let d = 0; d < count; d++) { const offset = d * 5; const indexOrVertexCount = this.gpuIndirect[offset + 0]; const instanceCount = this.gpuIndirect[offset + 1]; totalPrimitives += indexOrVertexCount * instanceCount; } } return totalPrimitives; } destroy() { this.storage?.destroy(); this.storage = null; } } export { WebgpuDrawCommands };