wgsl-renderer 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +48 -10
- package/dist/esm/index.d.ts +14 -1
- package/dist/esm/index.js +48 -10
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -542,7 +542,7 @@ var WGSLRenderer = class {
|
|
|
542
542
|
animationFrameId = null;
|
|
543
543
|
isResizing = false;
|
|
544
544
|
renderMode = "normal";
|
|
545
|
-
|
|
545
|
+
readedBuffer = null;
|
|
546
546
|
hasClearedCanvasThisFrame = false;
|
|
547
547
|
getPassOutputTextureName(passName) {
|
|
548
548
|
return `pass_${passName}_output`;
|
|
@@ -1033,8 +1033,8 @@ var WGSLRenderer = class {
|
|
|
1033
1033
|
this.stopLoop();
|
|
1034
1034
|
this.passes = [];
|
|
1035
1035
|
this.textureManager.destroy();
|
|
1036
|
-
this.
|
|
1037
|
-
this.
|
|
1036
|
+
this.readedBuffer?.destroy();
|
|
1037
|
+
this.readedBuffer = null;
|
|
1038
1038
|
}
|
|
1039
1039
|
/**
|
|
1040
1040
|
* 快速捕获当前帧的像素数据
|
|
@@ -1048,22 +1048,22 @@ var WGSLRenderer = class {
|
|
|
1048
1048
|
const height = outputTexture.height;
|
|
1049
1049
|
const bytesPerRow = Math.ceil(width * 4 / 256) * 256;
|
|
1050
1050
|
const bufferSize = bytesPerRow * height;
|
|
1051
|
-
if (!this.
|
|
1052
|
-
this.
|
|
1053
|
-
this.
|
|
1051
|
+
if (!this.readedBuffer || this.readedBuffer.size !== bufferSize) {
|
|
1052
|
+
this.readedBuffer?.destroy();
|
|
1053
|
+
this.readedBuffer = this.device.createBuffer({
|
|
1054
1054
|
size: bufferSize,
|
|
1055
1055
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1056
1056
|
});
|
|
1057
1057
|
}
|
|
1058
1058
|
const commandEncoder = this.device.createCommandEncoder();
|
|
1059
1059
|
commandEncoder.copyTextureToBuffer({ texture: outputTexture }, {
|
|
1060
|
-
buffer: this.
|
|
1060
|
+
buffer: this.readedBuffer,
|
|
1061
1061
|
bytesPerRow
|
|
1062
1062
|
}, [width, height]);
|
|
1063
1063
|
this.device.queue.submit([commandEncoder.finish()]);
|
|
1064
|
-
await this.
|
|
1065
|
-
const mappedBuffer = new Uint8Array(this.
|
|
1066
|
-
this.
|
|
1064
|
+
await this.readedBuffer.mapAsync(GPUMapMode.READ);
|
|
1065
|
+
const mappedBuffer = new Uint8Array(this.readedBuffer.getMappedRange().slice(0));
|
|
1066
|
+
this.readedBuffer.unmap();
|
|
1067
1067
|
const pixelData = new Uint8Array(width * height * 4);
|
|
1068
1068
|
for (let row = 0; row < height; row++) {
|
|
1069
1069
|
const srcOffset = row * bytesPerRow;
|
|
@@ -1073,6 +1073,44 @@ var WGSLRenderer = class {
|
|
|
1073
1073
|
return pixelData;
|
|
1074
1074
|
}
|
|
1075
1075
|
/**
|
|
1076
|
+
* Create a storage buffer for compute shader read/write
|
|
1077
|
+
*/
|
|
1078
|
+
createStorageBuffer(size, label) {
|
|
1079
|
+
return this.device.createBuffer({
|
|
1080
|
+
label,
|
|
1081
|
+
size,
|
|
1082
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Create an indirect buffer for GPU-driven draw/dispatch
|
|
1087
|
+
*/
|
|
1088
|
+
createIndirectBuffer(size, label) {
|
|
1089
|
+
return this.device.createBuffer({
|
|
1090
|
+
label,
|
|
1091
|
+
size,
|
|
1092
|
+
usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Read back data from a GPU buffer
|
|
1097
|
+
* Buffer must have COPY_SRC usage
|
|
1098
|
+
*/
|
|
1099
|
+
async readBuffer(buffer) {
|
|
1100
|
+
const stagingBuffer = this.device.createBuffer({
|
|
1101
|
+
size: buffer.size,
|
|
1102
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1103
|
+
});
|
|
1104
|
+
const commandEncoder = this.device.createCommandEncoder();
|
|
1105
|
+
commandEncoder.copyBufferToBuffer(buffer, 0, stagingBuffer, 0, buffer.size);
|
|
1106
|
+
this.device.queue.submit([commandEncoder.finish()]);
|
|
1107
|
+
await stagingBuffer.mapAsync(GPUMapMode.READ);
|
|
1108
|
+
const data = stagingBuffer.getMappedRange().slice(0);
|
|
1109
|
+
stagingBuffer.unmap();
|
|
1110
|
+
stagingBuffer.destroy();
|
|
1111
|
+
return data;
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1076
1114
|
* Create a storage-capable texture (useful for compute passes)
|
|
1077
1115
|
*/
|
|
1078
1116
|
createStorageTexture(options) {
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -235,7 +235,7 @@ declare class WGSLRenderer {
|
|
|
235
235
|
private animationFrameId;
|
|
236
236
|
private isResizing;
|
|
237
237
|
private renderMode;
|
|
238
|
-
private
|
|
238
|
+
private readedBuffer;
|
|
239
239
|
private hasClearedCanvasThisFrame;
|
|
240
240
|
private getPassOutputTextureName;
|
|
241
241
|
constructor(canvas: HTMLCanvasElement, options?: WGSLRendererOptions | undefined);
|
|
@@ -367,6 +367,19 @@ declare class WGSLRenderer {
|
|
|
367
367
|
* @returns Uint8Array格式的RGBA像素数据
|
|
368
368
|
*/
|
|
369
369
|
captureFrameFast(): Promise<Uint8Array>;
|
|
370
|
+
/**
|
|
371
|
+
* Create a storage buffer for compute shader read/write
|
|
372
|
+
*/
|
|
373
|
+
createStorageBuffer(size: number, label?: string): GPUBuffer;
|
|
374
|
+
/**
|
|
375
|
+
* Create an indirect buffer for GPU-driven draw/dispatch
|
|
376
|
+
*/
|
|
377
|
+
createIndirectBuffer(size: number, label?: string): GPUBuffer;
|
|
378
|
+
/**
|
|
379
|
+
* Read back data from a GPU buffer
|
|
380
|
+
* Buffer must have COPY_SRC usage
|
|
381
|
+
*/
|
|
382
|
+
readBuffer(buffer: GPUBuffer): Promise<ArrayBuffer>;
|
|
370
383
|
/**
|
|
371
384
|
* Create a storage-capable texture (useful for compute passes)
|
|
372
385
|
*/
|
package/dist/esm/index.js
CHANGED
|
@@ -541,7 +541,7 @@ var WGSLRenderer = class {
|
|
|
541
541
|
animationFrameId = null;
|
|
542
542
|
isResizing = false;
|
|
543
543
|
renderMode = "normal";
|
|
544
|
-
|
|
544
|
+
readedBuffer = null;
|
|
545
545
|
hasClearedCanvasThisFrame = false;
|
|
546
546
|
getPassOutputTextureName(passName) {
|
|
547
547
|
return `pass_${passName}_output`;
|
|
@@ -1032,8 +1032,8 @@ var WGSLRenderer = class {
|
|
|
1032
1032
|
this.stopLoop();
|
|
1033
1033
|
this.passes = [];
|
|
1034
1034
|
this.textureManager.destroy();
|
|
1035
|
-
this.
|
|
1036
|
-
this.
|
|
1035
|
+
this.readedBuffer?.destroy();
|
|
1036
|
+
this.readedBuffer = null;
|
|
1037
1037
|
}
|
|
1038
1038
|
/**
|
|
1039
1039
|
* 快速捕获当前帧的像素数据
|
|
@@ -1047,22 +1047,22 @@ var WGSLRenderer = class {
|
|
|
1047
1047
|
const height = outputTexture.height;
|
|
1048
1048
|
const bytesPerRow = Math.ceil(width * 4 / 256) * 256;
|
|
1049
1049
|
const bufferSize = bytesPerRow * height;
|
|
1050
|
-
if (!this.
|
|
1051
|
-
this.
|
|
1052
|
-
this.
|
|
1050
|
+
if (!this.readedBuffer || this.readedBuffer.size !== bufferSize) {
|
|
1051
|
+
this.readedBuffer?.destroy();
|
|
1052
|
+
this.readedBuffer = this.device.createBuffer({
|
|
1053
1053
|
size: bufferSize,
|
|
1054
1054
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1055
1055
|
});
|
|
1056
1056
|
}
|
|
1057
1057
|
const commandEncoder = this.device.createCommandEncoder();
|
|
1058
1058
|
commandEncoder.copyTextureToBuffer({ texture: outputTexture }, {
|
|
1059
|
-
buffer: this.
|
|
1059
|
+
buffer: this.readedBuffer,
|
|
1060
1060
|
bytesPerRow
|
|
1061
1061
|
}, [width, height]);
|
|
1062
1062
|
this.device.queue.submit([commandEncoder.finish()]);
|
|
1063
|
-
await this.
|
|
1064
|
-
const mappedBuffer = new Uint8Array(this.
|
|
1065
|
-
this.
|
|
1063
|
+
await this.readedBuffer.mapAsync(GPUMapMode.READ);
|
|
1064
|
+
const mappedBuffer = new Uint8Array(this.readedBuffer.getMappedRange().slice(0));
|
|
1065
|
+
this.readedBuffer.unmap();
|
|
1066
1066
|
const pixelData = new Uint8Array(width * height * 4);
|
|
1067
1067
|
for (let row = 0; row < height; row++) {
|
|
1068
1068
|
const srcOffset = row * bytesPerRow;
|
|
@@ -1072,6 +1072,44 @@ var WGSLRenderer = class {
|
|
|
1072
1072
|
return pixelData;
|
|
1073
1073
|
}
|
|
1074
1074
|
/**
|
|
1075
|
+
* Create a storage buffer for compute shader read/write
|
|
1076
|
+
*/
|
|
1077
|
+
createStorageBuffer(size, label) {
|
|
1078
|
+
return this.device.createBuffer({
|
|
1079
|
+
label,
|
|
1080
|
+
size,
|
|
1081
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Create an indirect buffer for GPU-driven draw/dispatch
|
|
1086
|
+
*/
|
|
1087
|
+
createIndirectBuffer(size, label) {
|
|
1088
|
+
return this.device.createBuffer({
|
|
1089
|
+
label,
|
|
1090
|
+
size,
|
|
1091
|
+
usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Read back data from a GPU buffer
|
|
1096
|
+
* Buffer must have COPY_SRC usage
|
|
1097
|
+
*/
|
|
1098
|
+
async readBuffer(buffer) {
|
|
1099
|
+
const stagingBuffer = this.device.createBuffer({
|
|
1100
|
+
size: buffer.size,
|
|
1101
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1102
|
+
});
|
|
1103
|
+
const commandEncoder = this.device.createCommandEncoder();
|
|
1104
|
+
commandEncoder.copyBufferToBuffer(buffer, 0, stagingBuffer, 0, buffer.size);
|
|
1105
|
+
this.device.queue.submit([commandEncoder.finish()]);
|
|
1106
|
+
await stagingBuffer.mapAsync(GPUMapMode.READ);
|
|
1107
|
+
const data = stagingBuffer.getMappedRange().slice(0);
|
|
1108
|
+
stagingBuffer.unmap();
|
|
1109
|
+
stagingBuffer.destroy();
|
|
1110
|
+
return data;
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1075
1113
|
* Create a storage-capable texture (useful for compute passes)
|
|
1076
1114
|
*/
|
|
1077
1115
|
createStorageTexture(options) {
|