@rings-webgpu/core 1.0.38 → 1.0.39

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.
@@ -24088,10 +24088,44 @@ struct InstanceData {
24088
24088
  }
24089
24089
  return this;
24090
24090
  }
24091
- updateTexture(width, height, data) {
24091
+ updateTexture(width, height, data, startRow, rowCount) {
24092
24092
  let device = webGPUContext.device;
24093
24093
  const bytesPerRow = Math.ceil(width * 4 / 256) * 256;
24094
24094
  this.mipmapCount = Math.floor(Math.log2(width) );
24095
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24096
+ const updateHeight = rowCount;
24097
+ const updateOffset = startRow * width * 4;
24098
+ const updateData = data.subarray(updateOffset, updateOffset + updateHeight * width * 4);
24099
+ const neededSize = updateData.byteLength;
24100
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize) {
24101
+ this._dataBuffer && this._dataBuffer.destroy();
24102
+ this._dataBuffer = device.createBuffer({
24103
+ size: neededSize,
24104
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24105
+ });
24106
+ }
24107
+ device.queue.writeBuffer(this._dataBuffer, 0, updateData.buffer, updateData.byteOffset, updateData.byteLength);
24108
+ const commandEncoder2 = GPUContext.beginCommandEncoder();
24109
+ commandEncoder2.copyBufferToTexture(
24110
+ {
24111
+ buffer: this._dataBuffer,
24112
+ bytesPerRow,
24113
+ offset: 0
24114
+ },
24115
+ {
24116
+ texture: this.getGPUTexture(),
24117
+ origin: [0, startRow, 0]
24118
+ // Start at row startRow
24119
+ },
24120
+ {
24121
+ width,
24122
+ height: updateHeight,
24123
+ depthOrArrayLayers: 1
24124
+ }
24125
+ );
24126
+ GPUContext.endCommandEncoder(commandEncoder2);
24127
+ return;
24128
+ }
24095
24129
  this._dataBuffer && this._dataBuffer.destroy();
24096
24130
  this._dataBuffer = null;
24097
24131
  const textureDataBuffer = this._dataBuffer = device.createBuffer({
@@ -24147,9 +24181,28 @@ struct InstanceData {
24147
24181
  this.gpuSampler = device.createSampler({});
24148
24182
  return this;
24149
24183
  }
24150
- updateTexture(width, height, data) {
24184
+ updateTexture(width, height, data, startRow, rowCount) {
24151
24185
  let device = webGPUContext.device;
24152
24186
  const bytesPerRow = width * 4 * 4;
24187
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24188
+ const updateHeight = rowCount;
24189
+ const updateOffset = startRow * width * 4;
24190
+ const updateData = data.subarray(updateOffset, updateOffset + updateHeight * width * 4);
24191
+ device.queue.writeTexture(
24192
+ {
24193
+ texture: this.getGPUTexture(),
24194
+ origin: [0, startRow, 0]
24195
+ // Start at row startRow
24196
+ },
24197
+ updateData.buffer,
24198
+ {
24199
+ bytesPerRow,
24200
+ offset: updateData.byteOffset
24201
+ },
24202
+ { width, height: updateHeight, depthOrArrayLayers: 1 }
24203
+ );
24204
+ return;
24205
+ }
24153
24206
  device.queue.writeTexture(
24154
24207
  { texture: this.getGPUTexture() },
24155
24208
  data.buffer,
@@ -24196,30 +24249,37 @@ struct InstanceData {
24196
24249
  }
24197
24250
  }
24198
24251
 
24199
- const _floatView = new Float32Array(1);
24200
- const _int32View = new Int32Array(_floatView.buffer);
24201
- let toHalfFloat = function(val) {
24202
- _floatView[0] = val;
24203
- const x = _int32View[0];
24204
- let bits = x >> 16 & 32768;
24205
- let m = x >> 12 & 2047;
24206
- const e = x >> 23 & 255;
24207
- if (e < 103) return bits;
24208
- if (e > 142) {
24209
- bits |= 31744;
24210
- bits |= (e == 255 ? 1 : 0) && x & 8388607;
24211
- return bits;
24212
- }
24213
- if (e < 114) {
24214
- m |= 2048;
24215
- bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24216
- return bits;
24252
+ const _floatView$1 = new Float32Array(1);
24253
+ const _int32View$1 = new Int32Array(_floatView$1.buffer);
24254
+ function batchConvertToHalfFloat(src, dst, offset, length) {
24255
+ for (let i = 0; i < length; i++) {
24256
+ const val = src[offset + i];
24257
+ _floatView$1[0] = val;
24258
+ const x = _int32View$1[0];
24259
+ let bits = x >> 16 & 32768;
24260
+ let m = x >> 12 & 2047;
24261
+ const e = x >> 23 & 255;
24262
+ if (e < 103) {
24263
+ dst[offset + i] = bits;
24264
+ continue;
24265
+ }
24266
+ if (e > 142) {
24267
+ bits |= 31744;
24268
+ bits |= (e == 255 ? 1 : 0) && x & 8388607;
24269
+ dst[offset + i] = bits;
24270
+ continue;
24271
+ }
24272
+ if (e < 114) {
24273
+ m |= 2048;
24274
+ bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24275
+ dst[offset + i] = bits;
24276
+ continue;
24277
+ }
24278
+ bits |= e - 112 << 10 | m >> 1;
24279
+ bits += m & 1;
24280
+ dst[offset + i] = bits;
24217
24281
  }
24218
- bits |= e - 112 << 10 | m >> 1;
24219
- bits += m & 1;
24220
- return bits;
24221
- };
24222
-
24282
+ }
24223
24283
  class Float16ArrayTexture extends Texture {
24224
24284
  uint16Array;
24225
24285
  floatArray;
@@ -24248,8 +24308,10 @@ struct InstanceData {
24248
24308
  * @param height 纹理高度
24249
24309
  * @param numbers 像素数据数组
24250
24310
  * @param mipmap 是否生成Mipmap
24311
+ * @param startRow 起始行(部分更新)
24312
+ * @param rowCount 更新的行数(部分更新)
24251
24313
  */
24252
- updateTexture(width, height, numbers, mipmap = true) {
24314
+ updateTexture(width, height, numbers, mipmap = true, startRow, rowCount) {
24253
24315
  if (width != this.width || height != this.height) {
24254
24316
  this._dataBuffer && this._dataBuffer.destroy();
24255
24317
  this._dataBuffer = null;
@@ -24262,22 +24324,70 @@ struct InstanceData {
24262
24324
  this.format = GPUTextureFormat.rgba16float;
24263
24325
  this.mipmapCount = Math.floor(mipmap ? Math.log2(width) : 1);
24264
24326
  this.createTextureDescriptor(width, height, this.mipmapCount, this.format);
24327
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24328
+ const updateHeight = rowCount;
24329
+ const updateOffset = startRow * width * 4;
24330
+ const updateLength = updateHeight * width * 4;
24331
+ if (!this.uint16Array || this.uint16Array.length < updateOffset + updateLength) {
24332
+ if (!this.uint16Array || this.uint16Array.length < numbers.length) {
24333
+ this.uint16Array = new Uint16Array(numbers.length);
24334
+ }
24335
+ }
24336
+ const uint16Array2 = this.uint16Array;
24337
+ batchConvertToHalfFloat(numbers, uint16Array2, updateOffset, updateLength);
24338
+ const updateData = uint16Array2.subarray(updateOffset, updateOffset + updateLength);
24339
+ const neededSize2 = updateData.byteLength;
24340
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize2) {
24341
+ this._dataBuffer && this._dataBuffer.destroy();
24342
+ this._dataBuffer = device.createBuffer({
24343
+ size: neededSize2,
24344
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24345
+ });
24346
+ }
24347
+ device.queue.writeBuffer(this._dataBuffer, 0, updateData.buffer, updateData.byteOffset, updateData.byteLength);
24348
+ const commandEncoder2 = GPUContext.beginCommandEncoder();
24349
+ commandEncoder2.copyBufferToTexture(
24350
+ {
24351
+ buffer: this._dataBuffer,
24352
+ bytesPerRow,
24353
+ offset: 0
24354
+ },
24355
+ {
24356
+ texture: this.getGPUTexture(),
24357
+ origin: [0, startRow, 0]
24358
+ // Start at row startRow
24359
+ },
24360
+ {
24361
+ width,
24362
+ height: updateHeight,
24363
+ depthOrArrayLayers: 1
24364
+ }
24365
+ );
24366
+ if (!this.useMipmap) {
24367
+ this.samplerBindingLayout.type = `filtering`;
24368
+ this.textureBindingLayout.sampleType = `float`;
24369
+ }
24370
+ GPUContext.endCommandEncoder(commandEncoder2);
24371
+ return;
24372
+ }
24265
24373
  if (!this.uint16Array || this.uint16Array.length != numbers.length) {
24266
24374
  this.uint16Array = new Uint16Array(numbers.length);
24267
24375
  }
24268
- let uint16Array = this.uint16Array;
24269
- for (let i = 0, c = uint16Array.length; i < c; i++) {
24270
- uint16Array[i] = toHalfFloat(numbers[i]);
24376
+ const uint16Array = this.uint16Array;
24377
+ batchConvertToHalfFloat(numbers, uint16Array, 0, numbers.length);
24378
+ const neededSize = uint16Array.byteLength;
24379
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize) {
24380
+ this._dataBuffer && this._dataBuffer.destroy();
24381
+ this._dataBuffer = device.createBuffer({
24382
+ size: neededSize,
24383
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24384
+ });
24271
24385
  }
24272
- const textureDataBuffer = this._dataBuffer = device.createBuffer({
24273
- size: uint16Array.byteLength,
24274
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24275
- });
24276
- device.queue.writeBuffer(textureDataBuffer, 0, uint16Array);
24386
+ device.queue.writeBuffer(this._dataBuffer, 0, uint16Array.buffer, uint16Array.byteOffset, uint16Array.byteLength);
24277
24387
  const commandEncoder = GPUContext.beginCommandEncoder();
24278
24388
  commandEncoder.copyBufferToTexture(
24279
24389
  {
24280
- buffer: textureDataBuffer,
24390
+ buffer: this._dataBuffer,
24281
24391
  bytesPerRow
24282
24392
  },
24283
24393
  {
@@ -24300,6 +24410,30 @@ struct InstanceData {
24300
24410
  }
24301
24411
  }
24302
24412
 
24413
+ const _floatView = new Float32Array(1);
24414
+ const _int32View = new Int32Array(_floatView.buffer);
24415
+ let toHalfFloat = function(val) {
24416
+ _floatView[0] = val;
24417
+ const x = _int32View[0];
24418
+ let bits = x >> 16 & 32768;
24419
+ let m = x >> 12 & 2047;
24420
+ const e = x >> 23 & 255;
24421
+ if (e < 103) return bits;
24422
+ if (e > 142) {
24423
+ bits |= 31744;
24424
+ bits |= (e == 255 ? 1 : 0) && x & 8388607;
24425
+ return bits;
24426
+ }
24427
+ if (e < 114) {
24428
+ m |= 2048;
24429
+ bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24430
+ return bits;
24431
+ }
24432
+ bits |= e - 112 << 10 | m >> 1;
24433
+ bits += m & 1;
24434
+ return bits;
24435
+ };
24436
+
24303
24437
  var __getOwnPropDesc$m = Object.getOwnPropertyDescriptor;
24304
24438
  var __decorateClass$m = (decorators, target, key, kind) => {
24305
24439
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$m(target, key) : target;
@@ -42158,7 +42292,7 @@ else if (typeof exports === 'object')
42158
42292
  }
42159
42293
  }
42160
42294
 
42161
- const version = "1.0.36";
42295
+ const version = "1.0.38";
42162
42296
 
42163
42297
  class Engine3D {
42164
42298
  /**
@@ -54408,6 +54542,7 @@ fn frag(){
54408
54542
  transformB;
54409
54543
  texParams;
54410
54544
  // [numSplats, texWidth, validCount, visBoost]
54545
+ _texParamDirty = true;
54411
54546
  splatOrder;
54412
54547
  // Material and geometry
54413
54548
  gsplatMaterial;
@@ -54549,7 +54684,6 @@ fn frag(){
54549
54684
  if (!wasSet) {
54550
54685
  this._splatSetFlags[index] = true;
54551
54686
  this._validCount++;
54552
- this.texParams[2] = this._validCount;
54553
54687
  }
54554
54688
  this._pendingUpdates.add(index);
54555
54689
  }
@@ -54637,14 +54771,32 @@ fn frag(){
54637
54771
  /**
54638
54772
  * Flush pending updates to GPU
54639
54773
  * Updates GPU textures with all pending changes
54774
+ * Uses partial updates when possible for better performance
54640
54775
  */
54641
54776
  flushUpdates() {
54642
54777
  if (this._pendingUpdates.size === 0) return;
54643
54778
  const w = this.size.x | 0;
54644
54779
  const h = this.size.y | 0;
54645
- this.splatColor.updateTexture(w, h, this._colorData);
54646
- this.transformA.updateTexture(w, h, this._transformAData);
54647
- this.transformB.updateTexture(w, h, this._transformBData, false);
54780
+ const pendingIndices = Array.from(this._pendingUpdates);
54781
+ if (pendingIndices.length === 0) return;
54782
+ let minRow = h;
54783
+ let maxRow = 0;
54784
+ for (const index of pendingIndices) {
54785
+ const row = Math.floor(index / w);
54786
+ if (row < minRow) minRow = row;
54787
+ if (row > maxRow) maxRow = row;
54788
+ }
54789
+ const rowCount = maxRow - minRow + 1;
54790
+ const updateRatio = rowCount / h;
54791
+ if (updateRatio < 0.5 && rowCount < h) {
54792
+ this.splatColor.updateTexture(w, h, this._colorData, minRow, rowCount);
54793
+ this.transformA.updateTexture(w, h, this._transformAData, minRow, rowCount);
54794
+ this.transformB.updateTexture(w, h, this._transformBData, false, minRow, rowCount);
54795
+ } else {
54796
+ this.splatColor.updateTexture(w, h, this._colorData);
54797
+ this.transformA.updateTexture(w, h, this._transformAData);
54798
+ this.transformB.updateTexture(w, h, this._transformBData, false);
54799
+ }
54648
54800
  this.updatePendingWorldPositions();
54649
54801
  this._pendingUpdates.clear();
54650
54802
  }
@@ -54670,13 +54822,13 @@ fn frag(){
54670
54822
  * Update splat sorting before rendering
54671
54823
  * Uses the same logic as GSplatRenderer for reliable sorting
54672
54824
  */
54673
- onBeforeUpdate(view) {
54674
- if (this._validCount > 0 && view?.camera) {
54675
- if (view.camera.viewMatrix) {
54676
- this.scheduleOrder(view.camera.viewMatrix);
54677
- }
54678
- }
54679
- }
54825
+ // public onBeforeUpdate(view?: View3D) {
54826
+ // if (this._validCount > 0 && view?.camera) {
54827
+ // if (view.camera.viewMatrix) {
54828
+ // this.scheduleOrder(view.camera.viewMatrix);
54829
+ // }
54830
+ // }
54831
+ // }
54680
54832
  /**
54681
54833
  * Update world space positions when transform changes
54682
54834
  */
@@ -54750,8 +54902,7 @@ fn frag(){
54750
54902
  }
54751
54903
  this.splatOrder.updateTexture(this.size.x, this.size.y, this._orderData);
54752
54904
  const valid = Math.max(0, Math.min(this._validCount, ev.data.count | 0));
54753
- this.texParams[2] = valid;
54754
- this.texParams[0] = valid;
54905
+ this.setCount(valid);
54755
54906
  this._updateTexParams();
54756
54907
  const newInstanceCount = Math.ceil(valid / this._batchSize);
54757
54908
  this.instanceCount = newInstanceCount;
@@ -54957,12 +55108,17 @@ fn frag(){
54957
55108
  */
54958
55109
  setVisBoost(v) {
54959
55110
  this.texParams[3] = Math.max(0, v);
55111
+ this._texParamDirty = true;
54960
55112
  }
54961
55113
  setCount(c) {
54962
55114
  this.texParams[0] = Math.max(0, c);
55115
+ this._texParamDirty = true;
54963
55116
  }
54964
55117
  _updateTexParams() {
54965
- this.gsplatMaterial.setTexParams(this.texParams);
55118
+ if (this._texParamDirty) {
55119
+ this.gsplatMaterial.setTexParams(this.texParams);
55120
+ this._texParamDirty = false;
55121
+ }
54966
55122
  }
54967
55123
  /**
54968
55124
  * Set sort throttle interval (milliseconds)
@@ -55022,6 +55178,11 @@ fn frag(){
55022
55178
  * Update node before rendering
55023
55179
  */
55024
55180
  nodeUpdate(view, passType, renderPassState, clusterLightingBuffer) {
55181
+ if (this._validCount > 0 && view?.camera) {
55182
+ if (view.camera.viewMatrix) {
55183
+ this.scheduleOrder(view.camera.viewMatrix);
55184
+ }
55185
+ }
55025
55186
  if (this._pendingUpdates.size > 0 && this._frameCount >= 60) {
55026
55187
  this.flushUpdates();
55027
55188
  }
@@ -55029,6 +55190,7 @@ fn frag(){
55029
55190
  this._frameCount = 0;
55030
55191
  }
55031
55192
  this._frameCount++;
55193
+ this._updateTexParams();
55032
55194
  const worldMatrix = this.object3D.transform.worldMatrix;
55033
55195
  this.gsplatMaterial.setTransformMatrix(worldMatrix);
55034
55196
  const currentParams = `${this._minPixelCoverage},${this._maxPixelCoverage},${this._maxPixelCullDistance},${this._batchSize}`;
@@ -35,6 +35,7 @@ export declare class GSplatStreamRenderer extends RenderNode {
35
35
  transformA: Uint32ArrayTexture;
36
36
  transformB: Float16ArrayTexture;
37
37
  texParams: Float32Array;
38
+ private _texParamDirty;
38
39
  splatOrder: R32UintTexture;
39
40
  gsplatMaterial: GSplatMaterial;
40
41
  private _colorData;
@@ -83,6 +84,7 @@ export declare class GSplatStreamRenderer extends RenderNode {
83
84
  /**
84
85
  * Flush pending updates to GPU
85
86
  * Updates GPU textures with all pending changes
87
+ * Uses partial updates when possible for better performance
86
88
  */
87
89
  flushUpdates(): void;
88
90
  /**
@@ -103,7 +105,6 @@ export declare class GSplatStreamRenderer extends RenderNode {
103
105
  * Update splat sorting before rendering
104
106
  * Uses the same logic as GSplatRenderer for reliable sorting
105
107
  */
106
- onBeforeUpdate(view?: View3D): void;
107
108
  /**
108
109
  * Update world space positions when transform changes
109
110
  */
@@ -23,6 +23,8 @@ export declare class Float16ArrayTexture extends Texture {
23
23
  * @param height 纹理高度
24
24
  * @param numbers 像素数据数组
25
25
  * @param mipmap 是否生成Mipmap
26
+ * @param startRow 起始行(部分更新)
27
+ * @param rowCount 更新的行数(部分更新)
26
28
  */
27
- updateTexture(width: number, height: number, numbers: number[], mipmap?: boolean): void;
29
+ updateTexture(width: number, height: number, numbers: number[], mipmap?: boolean, startRow?: number, rowCount?: number): void;
28
30
  }
@@ -7,5 +7,5 @@ import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture";
7
7
  export declare class Uint32ArrayTexture extends Texture {
8
8
  private _dataBuffer;
9
9
  create(width: number, height: number, data: Uint32Array): this;
10
- updateTexture(width: number, height: number, data: Uint32Array): void;
10
+ updateTexture(width: number, height: number, data: Uint32Array, startRow?: number, rowCount?: number): void;
11
11
  }
@@ -2,5 +2,5 @@ import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture";
2
2
  export declare class Uint8ArrayTexture extends Texture {
3
3
  private _dataBuffer;
4
4
  create(width: number, height: number, data: Uint8Array, useMipmap?: boolean): this;
5
- updateTexture(width: number, height: number, data: Uint8Array): void;
5
+ updateTexture(width: number, height: number, data: Uint8Array, startRow?: number, rowCount?: number): void;
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rings-webgpu/core",
3
- "version": "1.0.38",
3
+ "version": "1.0.39",
4
4
  "description": "Rings webgpu Engine",
5
5
  "main": "index.js",
6
6
  "exports": {