|
@@ -517,25 +517,32 @@ export class WebGPUEngine extends Engine {
|
|
|
//------------------------------------------------------------------------------
|
|
|
// WebGPU Buffers
|
|
|
//------------------------------------------------------------------------------
|
|
|
-
|
|
|
private _createBuffer(view: ArrayBufferView, flags: GPUBufferUsageFlags): DataBuffer {
|
|
|
if (view.byteLength == 0) {
|
|
|
- throw new Error("Unable to create WebGPU buffer"); // Zero size buffer would kill the tab in chrome
|
|
|
+ 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 verticesBufferDescriptor = {
|
|
|
size: view.byteLength + padding,
|
|
|
usage: flags
|
|
|
};
|
|
|
- const [buffer, arrbuffer] = this._device.createBufferMapped(verticesBufferDescriptor)
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
const dataBuffer = new WebGPUDataBuffer(buffer);
|
|
|
dataBuffer.references = 1;
|
|
|
dataBuffer.capacity = view.byteLength;
|
|
|
- if (padding == 0 && view.byteLength < this._maxBufferChunk) {
|
|
|
- new Uint8Array(arrbuffer).set(new Uint8Array(view.buffer));
|
|
|
+ if (arrBuffer) {
|
|
|
+ new Uint8Array(arrBuffer).set(new Uint8Array(view.buffer));
|
|
|
buffer.unmap();
|
|
|
} else {
|
|
|
- buffer.unmap();
|
|
|
this._setSubData(dataBuffer, 0, view);
|
|
|
}
|
|
|
return dataBuffer;
|
|
@@ -569,23 +576,30 @@ export class WebGPUEngine extends Engine {
|
|
|
// Chunk
|
|
|
const commandEncoder = this._device.createCommandEncoder();
|
|
|
const tempBuffers: GPUBuffer[] = [];
|
|
|
- for (let offset = 0; offset < src.byteLength; offset += this._maxBufferChunk) {
|
|
|
- const uploadCount = Math.min(src.byteLength - offset, this._maxBufferChunk);
|
|
|
-
|
|
|
- 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);
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ this._device.defaultQueue.submit([commandEncoder.finish()]);
|
|
|
+ } catch (e) {
|
|
|
+ Logger.Error('Unable to update WebGPU buffer: ' + e);
|
|
|
+ } finally {
|
|
|
+ tempBuffers.forEach((buff) => buff.destroy());
|
|
|
}
|
|
|
- this._device.defaultQueue.submit([commandEncoder.finish()]);
|
|
|
- tempBuffers.forEach((buff) => buff.destroy());
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
@@ -2132,13 +2146,17 @@ export class WebGPUEngine extends Engine {
|
|
|
for (let i = 0; i < webgpuPipelineContext.orderedUBOsAndSamplers.length; i++) {
|
|
|
const setDefinition = webgpuPipelineContext.orderedUBOsAndSamplers[i];
|
|
|
if (setDefinition === undefined) {
|
|
|
- const groupLayout = bindGroupLayouts[i];
|
|
|
- if (groupLayout) {
|
|
|
- bindGroups[i] = this._device.createBindGroup({
|
|
|
- layout: groupLayout,
|
|
|
- bindings: [],
|
|
|
- });
|
|
|
+ let groupLayout: GPUBindGroupLayout;
|
|
|
+ if (bindGroupLayouts && bindGroupLayouts[i]) {
|
|
|
+ groupLayout = bindGroupLayouts[i];
|
|
|
}
|
|
|
+ else {
|
|
|
+ groupLayout = webgpuPipelineContext.renderPipeline.getBindGroupLayout(i);
|
|
|
+ }
|
|
|
+ bindGroups[i] = this._device.createBindGroup({
|
|
|
+ layout: groupLayout,
|
|
|
+ entries: [],
|
|
|
+ });
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -2190,11 +2208,17 @@ export class WebGPUEngine extends Engine {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const groupLayout = bindGroupLayouts[i];
|
|
|
- if (groupLayout) {
|
|
|
+ if (bindings.length > 0) {
|
|
|
+ let groupLayout: GPUBindGroupLayout;
|
|
|
+ if (bindGroupLayouts && bindGroupLayouts[i]) {
|
|
|
+ groupLayout = bindGroupLayouts[i];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ groupLayout = webgpuPipelineContext.renderPipeline.getBindGroupLayout(i);
|
|
|
+ }
|
|
|
bindGroups[i] = this._device.createBindGroup({
|
|
|
layout: groupLayout,
|
|
|
- bindings,
|
|
|
+ entries: bindings,
|
|
|
});
|
|
|
}
|
|
|
}
|