UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

70 lines (68 loc) 2.34 kB
class WebgpuUploadStream { constructor(uploadStream){ this.availableStagingBuffers = []; this.pendingStagingBuffers = []; this._destroyed = false; 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; 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; 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); } } export { WebgpuUploadStream };