playcanvas
Version:
PlayCanvas WebGL game engine
67 lines (65 loc) • 2.22 kB
JavaScript
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 };