|
@@ -519,27 +519,19 @@ export class WebGPUEngine extends Engine {
|
|
|
throw new Error("Unable to create WebGPU buffer: cannot create zero-sized buffer"); // Zero size buffer would kill the tab in chrome
|
|
|
}
|
|
|
const padding = view.byteLength % 4;
|
|
|
-
|
|
|
+ const mappedAtCreation: boolean = padding == 0 && view.byteLength < this._maxBufferChunk;
|
|
|
const verticesBufferDescriptor = {
|
|
|
- size: view.byteLength + padding,
|
|
|
- usage: flags
|
|
|
- };
|
|
|
- let buffer: GPUBuffer;
|
|
|
- let arrBuffer: Nullable<ArrayBuffer> = null;
|
|
|
- if (padding == 0 && view.byteLength < this._maxBufferChunk) {
|
|
|
- [buffer, arrBuffer] = this._device.createBufferMapped(verticesBufferDescriptor);
|
|
|
- }
|
|
|
- else {
|
|
|
- buffer = this._device.createBuffer(verticesBufferDescriptor);
|
|
|
- }
|
|
|
-
|
|
|
+ size: view.byteLength + padding,
|
|
|
+ usage: flags,
|
|
|
+ mappedAtCreation
|
|
|
+ };
|
|
|
+ const buffer = this._device.createBuffer(verticesBufferDescriptor);
|
|
|
const dataBuffer = new WebGPUDataBuffer(buffer);
|
|
|
dataBuffer.references = 1;
|
|
|
dataBuffer.capacity = view.byteLength;
|
|
|
- if (arrBuffer) {
|
|
|
- const outputView = new Uint8Array(arrBuffer);
|
|
|
- const inputView = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
|
- outputView.set(inputView);
|
|
|
+ if (mappedAtCreation) {
|
|
|
+ const range = buffer.getMappedRange();
|
|
|
+ new Uint8Array(range).set(new Uint8Array(view.buffer, view.byteOffset, view.byteLength));
|
|
|
buffer.unmap();
|
|
|
} else {
|
|
|
this._setSubData(dataBuffer, 0, view);
|
|
@@ -574,31 +566,35 @@ export class WebGPUEngine extends Engine {
|
|
|
|
|
|
// Chunk
|
|
|
const commandEncoder = this._device.createCommandEncoder();
|
|
|
- const tempBuffers: GPUBuffer[] = [];
|
|
|
- try {
|
|
|
- for (let offset = 0; offset < src.byteLength; offset += this._maxBufferChunk) {
|
|
|
- const uploadCount = Math.min(src.byteLength - offset, this._maxBufferChunk);
|
|
|
- if (uploadCount == 0) {
|
|
|
- throw new Error("Cannot create zero-sized buffer"); // Zero size buffer would kill the tab in chrome
|
|
|
+ if (byteLength - srcByteOffset < 1) {
|
|
|
+ throw new Error("Cannot create zero-sized buffer"); // 0 size buffer would kill the tab in chrome
|
|
|
+ }
|
|
|
+ const uploadBuffer = this._device.createBuffer({
|
|
|
+ usage: WebGPUConstants.GPUBufferUsage_TRANSFER_SRC | WebGPUConstants.GPUBufferUsage_MAP_WRITE,
|
|
|
+ size: byteLength - srcByteOffset
|
|
|
+ });
|
|
|
+
|
|
|
+ (async() => {
|
|
|
+ try {
|
|
|
+ for (let offset = 0; offset < byteLength; offset += this._maxBufferChunk) {
|
|
|
+ const uploadCount = Math.min(byteLength - offset, this._maxBufferChunk);
|
|
|
+ await uploadBuffer.mapAsync(WebGPUConstants.GPUMapMode_WRITE, offset, uploadCount);
|
|
|
+ const uploadMapping = uploadBuffer.getMappedRange();
|
|
|
+
|
|
|
+ new Uint8Array(uploadMapping).set(new Uint8Array(src.buffer, srcByteOffset + offset, uploadCount));
|
|
|
+ uploadBuffer.unmap();
|
|
|
}
|
|
|
- const [uploadBuffer, uploadMapping] = this._device.createBufferMapped({
|
|
|
- usage: WebGPUConstants.GPUBufferUsage_TRANSFER_SRC,
|
|
|
- size: uploadCount,
|
|
|
- });
|
|
|
- tempBuffers.push(uploadBuffer);
|
|
|
- new Uint8Array(uploadMapping).set(new Uint8Array(src.buffer, srcByteOffset + offset, uploadCount));
|
|
|
- uploadBuffer.unmap();
|
|
|
commandEncoder.copyBufferToBuffer(
|
|
|
uploadBuffer, 0,
|
|
|
- buffer, dstByteOffset + offset,
|
|
|
- uploadCount);
|
|
|
+ buffer, dstByteOffset,
|
|
|
+ byteLength);
|
|
|
+ this._device.defaultQueue.submit([commandEncoder.finish()]);
|
|
|
+ } catch (e) {
|
|
|
+ Logger.Error(e);
|
|
|
+ } finally {
|
|
|
+ uploadBuffer.destroy();
|
|
|
}
|
|
|
- this._device.defaultQueue.submit([commandEncoder.finish()]);
|
|
|
- } catch (e) {
|
|
|
- Logger.Error('Unable to update WebGPU buffer: ' + e);
|
|
|
- } finally {
|
|
|
- tempBuffers.forEach((buff) => buff.destroy());
|
|
|
- }
|
|
|
+ })();
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|