playcanvas
Version:
PlayCanvas WebGL game engine
82 lines (79 loc) • 3.17 kB
JavaScript
import { TRACEID_RENDER_QUEUE } from '../../../core/constants.js';
import { Debug, DebugHelper } from '../../../core/debug.js';
/**
* @import { WebgpuGraphicsDevice } from './webgpu-graphics-device.js'
*/ /**
* A WebGPU implementation of the Buffer.
*
* @ignore
*/ class WebgpuBuffer {
constructor(usageFlags = 0){
/**
* @type {GPUBuffer|null}
* @private
*/ this.buffer = null;
this.usageFlags = 0;
this.usageFlags = usageFlags;
}
destroy(device) {
if (this.buffer) {
this.buffer.destroy();
this.buffer = null;
}
}
get initialized() {
return !!this.buffer;
}
loseContext() {}
allocate(device, size) {
Debug.assert(!this.buffer, 'Buffer already allocated');
this.buffer = device.wgpu.createBuffer({
size,
usage: this.usageFlags
});
}
/**
* @param {WebgpuGraphicsDevice} device - Graphics device.
* @param {*} storage -
*/ unlock(device, storage) {
const wgpu = device.wgpu;
// offset of getMappedRange must me a multiple of 8
// size of getMappedRange must be a multiple of 4
if (!this.buffer) {
// size needs to be a multiple of 4
// note: based on specs, descriptor.size must be a multiple of 4 if descriptor.mappedAtCreation is true
const size = storage.byteLength + 3 & -4;
this.usageFlags |= GPUBufferUsage.COPY_DST;
this.allocate(device, size);
DebugHelper.setLabel(this.buffer, this.usageFlags & GPUBufferUsage.VERTEX ? 'VertexBuffer' : this.usageFlags & GPUBufferUsage.INDEX ? 'IndexBuffer' : this.usageFlags & GPUBufferUsage.UNIFORM ? 'UniformBuffer' : this.usageFlags & GPUBufferUsage.STORAGE ? 'StorageBuffer' : '');
// mappedAtCreation path - this could be used when the data is provided
// this.buffer = device.wgpu.createBuffer({
// size: size,
// usage: target,
// mappedAtCreation: true
// });
// const dest = new Uint8Array(this.buffer.getMappedRange());
// const src = new Uint8Array(storage.buffer ? storage.buffer : storage);
// dest.set(src);
// this.buffer.unmap();
}
// src size needs to be a multiple of 4 as well
const srcOffset = storage.byteOffset ?? 0;
const srcData = new Uint8Array(storage.buffer ?? storage, srcOffset, storage.byteLength);
const data = new Uint8Array(this.buffer.size);
data.set(srcData);
// copy data to the gpu buffer
Debug.trace(TRACEID_RENDER_QUEUE, `writeBuffer: ${this.buffer.label}`);
wgpu.queue.writeBuffer(this.buffer, 0, data, 0, data.length);
}
read(device, offset, size, data, immediate) {
return device.readStorageBuffer(this, offset, size, data, immediate);
}
write(device, bufferOffset, data, dataOffset, size) {
device.writeStorageBuffer(this, bufferOffset, data, dataOffset, size);
}
clear(device, offset, size) {
device.clearStorageBuffer(this, offset, size);
}
}
export { WebgpuBuffer };