playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
84 lines (83 loc) • 3.08 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 { 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
};