UNPKG

playcanvas

Version:

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

83 lines (82 loc) 2.37 kB
let id = 0; class WebgpuUploadStream { availableStagingBuffers = []; pendingStagingBuffers = []; _destroyed = false; _lastUploadSubmitVersion = -1; constructor(uploadStream) { this.uploadStream = uploadStream; this.useSingleBuffer = uploadStream.useSingleBuffer; } _onDeviceLost() { } destroy() { this._destroyed = true; this.availableStagingBuffers.forEach((buffer) => buffer.destroy()); this.pendingStagingBuffers.forEach((buffer) => buffer.destroy()); } update(minByteSize) { const pending = this.pendingStagingBuffers; for (let i = 0; i < pending.length; i++) { const buffer = pending[i]; buffer.mapAsync(GPUMapMode.WRITE).then(() => { if (!this._destroyed) { this.availableStagingBuffers.push(buffer); } else { buffer.destroy(); } }); } pending.length = 0; const available = this.availableStagingBuffers; for (let i = available.length - 1; i >= 0; i--) { if (available[i].size < minByteSize) { available[i].destroy(); available.splice(i, 1); } } } upload(data, target, offset, size) { if (this.useSingleBuffer) { this.uploadDirect(data, target, offset, size); } else { this.uploadStaging(data, target, offset, size); } } uploadDirect(data, target, offset, size) { const byteOffset = offset * data.BYTES_PER_ELEMENT; const byteSize = size * data.BYTES_PER_ELEMENT; target.write(byteOffset, data, 0, size); } uploadStaging(data, target, offset, size) { const device = this.uploadStream.device; const byteOffset = offset * data.BYTES_PER_ELEMENT; const byteSize = size * data.BYTES_PER_ELEMENT; if (this.pendingStagingBuffers.length > 0) { } this.update(byteSize); const buffer = this.availableStagingBuffers.pop() ?? (() => { const newBuffer = this.uploadStream.device.wgpu.createBuffer({ size: byteSize, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC, mappedAtCreation: true }); return newBuffer; })(); const mappedRange = buffer.getMappedRange(); new Uint8Array(mappedRange).set(new Uint8Array(data.buffer, data.byteOffset, byteSize)); buffer.unmap(); device.getCommandEncoder().copyBufferToBuffer( buffer, 0, target.impl.buffer, byteOffset, byteSize ); this.pendingStagingBuffers.push(buffer); this._lastUploadSubmitVersion = device.submitVersion; } } export { WebgpuUploadStream };