UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

67 lines (65 loc) 2.22 kB
class WebgpuQuerySet { constructor(device, isTimestamp, capacity){ this.stagingBuffers = []; this.activeStagingBuffer = null; this.device = device; this.capacity = capacity; this.bytesPerSlot = isTimestamp ? 8 : 4; const wgpu = device.wgpu; this.querySet = wgpu.createQuerySet({ type: isTimestamp ? 'timestamp' : 'occlusion', count: capacity }); this.queryBuffer = wgpu.createBuffer({ size: this.bytesPerSlot * capacity, usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST }); } destroy() { this.querySet?.destroy(); this.querySet = null; this.queryBuffer?.destroy(); this.queryBuffer = null; this.activeStagingBuffer = null; this.stagingBuffers.forEach((stagingBuffer)=>{ stagingBuffer.destroy(); }); this.stagingBuffers = null; } getStagingBuffer() { let stagingBuffer = this.stagingBuffers.pop(); if (!stagingBuffer) { stagingBuffer = this.device.wgpu.createBuffer({ size: this.queryBuffer.size, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }); } return stagingBuffer; } resolve(count) { const device = this.device; const commandEncoder = device.getCommandEncoder(); commandEncoder.resolveQuerySet(this.querySet, 0, count, this.queryBuffer, 0); const activeStagingBuffer = this.getStagingBuffer(); this.activeStagingBuffer = activeStagingBuffer; commandEncoder.copyBufferToBuffer(this.queryBuffer, 0, activeStagingBuffer, 0, this.bytesPerSlot * count); } request(count, renderVersion) { const stagingBuffer = this.activeStagingBuffer; this.activeStagingBuffer = null; return stagingBuffer.mapAsync(GPUMapMode.READ).then(()=>{ const srcTimings = new BigInt64Array(stagingBuffer.getMappedRange()); const timings = []; for(let i = 0; i < count; i++){ timings.push(Number(srcTimings[i * 2 + 1] - srcTimings[i * 2]) * 0.000001); } stagingBuffer.unmap(); this.stagingBuffers?.push(stagingBuffer); return { renderVersion, timings }; }); } } export { WebgpuQuerySet };