@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.
@@ -24081,10 +24081,44 @@ class Uint8ArrayTexture extends Texture {
24081
24081
  }
24082
24082
  return this;
24083
24083
  }
24084
- updateTexture(width, height, data) {
24084
+ updateTexture(width, height, data, startRow, rowCount) {
24085
24085
  let device = webGPUContext.device;
24086
24086
  const bytesPerRow = Math.ceil(width * 4 / 256) * 256;
24087
24087
  this.mipmapCount = Math.floor(Math.log2(width) );
24088
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24089
+ const updateHeight = rowCount;
24090
+ const updateOffset = startRow * width * 4;
24091
+ const updateData = data.subarray(updateOffset, updateOffset + updateHeight * width * 4);
24092
+ const neededSize = updateData.byteLength;
24093
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize) {
24094
+ this._dataBuffer && this._dataBuffer.destroy();
24095
+ this._dataBuffer = device.createBuffer({
24096
+ size: neededSize,
24097
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24098
+ });
24099
+ }
24100
+ device.queue.writeBuffer(this._dataBuffer, 0, updateData.buffer, updateData.byteOffset, updateData.byteLength);
24101
+ const commandEncoder2 = GPUContext.beginCommandEncoder();
24102
+ commandEncoder2.copyBufferToTexture(
24103
+ {
24104
+ buffer: this._dataBuffer,
24105
+ bytesPerRow,
24106
+ offset: 0
24107
+ },
24108
+ {
24109
+ texture: this.getGPUTexture(),
24110
+ origin: [0, startRow, 0]
24111
+ // Start at row startRow
24112
+ },
24113
+ {
24114
+ width,
24115
+ height: updateHeight,
24116
+ depthOrArrayLayers: 1
24117
+ }
24118
+ );
24119
+ GPUContext.endCommandEncoder(commandEncoder2);
24120
+ return;
24121
+ }
24088
24122
  this._dataBuffer && this._dataBuffer.destroy();
24089
24123
  this._dataBuffer = null;
24090
24124
  const textureDataBuffer = this._dataBuffer = device.createBuffer({
@@ -24140,9 +24174,28 @@ class Uint32ArrayTexture extends Texture {
24140
24174
  this.gpuSampler = device.createSampler({});
24141
24175
  return this;
24142
24176
  }
24143
- updateTexture(width, height, data) {
24177
+ updateTexture(width, height, data, startRow, rowCount) {
24144
24178
  let device = webGPUContext.device;
24145
24179
  const bytesPerRow = width * 4 * 4;
24180
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24181
+ const updateHeight = rowCount;
24182
+ const updateOffset = startRow * width * 4;
24183
+ const updateData = data.subarray(updateOffset, updateOffset + updateHeight * width * 4);
24184
+ device.queue.writeTexture(
24185
+ {
24186
+ texture: this.getGPUTexture(),
24187
+ origin: [0, startRow, 0]
24188
+ // Start at row startRow
24189
+ },
24190
+ updateData.buffer,
24191
+ {
24192
+ bytesPerRow,
24193
+ offset: updateData.byteOffset
24194
+ },
24195
+ { width, height: updateHeight, depthOrArrayLayers: 1 }
24196
+ );
24197
+ return;
24198
+ }
24146
24199
  device.queue.writeTexture(
24147
24200
  { texture: this.getGPUTexture() },
24148
24201
  data.buffer,
@@ -24189,30 +24242,37 @@ class R32UintTexture extends Texture {
24189
24242
  }
24190
24243
  }
24191
24244
 
24192
- const _floatView = new Float32Array(1);
24193
- const _int32View = new Int32Array(_floatView.buffer);
24194
- let toHalfFloat = function(val) {
24195
- _floatView[0] = val;
24196
- const x = _int32View[0];
24197
- let bits = x >> 16 & 32768;
24198
- let m = x >> 12 & 2047;
24199
- const e = x >> 23 & 255;
24200
- if (e < 103) return bits;
24201
- if (e > 142) {
24202
- bits |= 31744;
24203
- bits |= (e == 255 ? 1 : 0) && x & 8388607;
24204
- return bits;
24205
- }
24206
- if (e < 114) {
24207
- m |= 2048;
24208
- bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24209
- return bits;
24245
+ const _floatView$1 = new Float32Array(1);
24246
+ const _int32View$1 = new Int32Array(_floatView$1.buffer);
24247
+ function batchConvertToHalfFloat(src, dst, offset, length) {
24248
+ for (let i = 0; i < length; i++) {
24249
+ const val = src[offset + i];
24250
+ _floatView$1[0] = val;
24251
+ const x = _int32View$1[0];
24252
+ let bits = x >> 16 & 32768;
24253
+ let m = x >> 12 & 2047;
24254
+ const e = x >> 23 & 255;
24255
+ if (e < 103) {
24256
+ dst[offset + i] = bits;
24257
+ continue;
24258
+ }
24259
+ if (e > 142) {
24260
+ bits |= 31744;
24261
+ bits |= (e == 255 ? 1 : 0) && x & 8388607;
24262
+ dst[offset + i] = bits;
24263
+ continue;
24264
+ }
24265
+ if (e < 114) {
24266
+ m |= 2048;
24267
+ bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24268
+ dst[offset + i] = bits;
24269
+ continue;
24270
+ }
24271
+ bits |= e - 112 << 10 | m >> 1;
24272
+ bits += m & 1;
24273
+ dst[offset + i] = bits;
24210
24274
  }
24211
- bits |= e - 112 << 10 | m >> 1;
24212
- bits += m & 1;
24213
- return bits;
24214
- };
24215
-
24275
+ }
24216
24276
  class Float16ArrayTexture extends Texture {
24217
24277
  uint16Array;
24218
24278
  floatArray;
@@ -24241,8 +24301,10 @@ class Float16ArrayTexture extends Texture {
24241
24301
  * @param height 纹理高度
24242
24302
  * @param numbers 像素数据数组
24243
24303
  * @param mipmap 是否生成Mipmap
24304
+ * @param startRow 起始行(部分更新)
24305
+ * @param rowCount 更新的行数(部分更新)
24244
24306
  */
24245
- updateTexture(width, height, numbers, mipmap = true) {
24307
+ updateTexture(width, height, numbers, mipmap = true, startRow, rowCount) {
24246
24308
  if (width != this.width || height != this.height) {
24247
24309
  this._dataBuffer && this._dataBuffer.destroy();
24248
24310
  this._dataBuffer = null;
@@ -24255,22 +24317,70 @@ class Float16ArrayTexture extends Texture {
24255
24317
  this.format = GPUTextureFormat.rgba16float;
24256
24318
  this.mipmapCount = Math.floor(mipmap ? Math.log2(width) : 1);
24257
24319
  this.createTextureDescriptor(width, height, this.mipmapCount, this.format);
24320
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24321
+ const updateHeight = rowCount;
24322
+ const updateOffset = startRow * width * 4;
24323
+ const updateLength = updateHeight * width * 4;
24324
+ if (!this.uint16Array || this.uint16Array.length < updateOffset + updateLength) {
24325
+ if (!this.uint16Array || this.uint16Array.length < numbers.length) {
24326
+ this.uint16Array = new Uint16Array(numbers.length);
24327
+ }
24328
+ }
24329
+ const uint16Array2 = this.uint16Array;
24330
+ batchConvertToHalfFloat(numbers, uint16Array2, updateOffset, updateLength);
24331
+ const updateData = uint16Array2.subarray(updateOffset, updateOffset + updateLength);
24332
+ const neededSize2 = updateData.byteLength;
24333
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize2) {
24334
+ this._dataBuffer && this._dataBuffer.destroy();
24335
+ this._dataBuffer = device.createBuffer({
24336
+ size: neededSize2,
24337
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24338
+ });
24339
+ }
24340
+ device.queue.writeBuffer(this._dataBuffer, 0, updateData.buffer, updateData.byteOffset, updateData.byteLength);
24341
+ const commandEncoder2 = GPUContext.beginCommandEncoder();
24342
+ commandEncoder2.copyBufferToTexture(
24343
+ {
24344
+ buffer: this._dataBuffer,
24345
+ bytesPerRow,
24346
+ offset: 0
24347
+ },
24348
+ {
24349
+ texture: this.getGPUTexture(),
24350
+ origin: [0, startRow, 0]
24351
+ // Start at row startRow
24352
+ },
24353
+ {
24354
+ width,
24355
+ height: updateHeight,
24356
+ depthOrArrayLayers: 1
24357
+ }
24358
+ );
24359
+ if (!this.useMipmap) {
24360
+ this.samplerBindingLayout.type = `filtering`;
24361
+ this.textureBindingLayout.sampleType = `float`;
24362
+ }
24363
+ GPUContext.endCommandEncoder(commandEncoder2);
24364
+ return;
24365
+ }
24258
24366
  if (!this.uint16Array || this.uint16Array.length != numbers.length) {
24259
24367
  this.uint16Array = new Uint16Array(numbers.length);
24260
24368
  }
24261
- let uint16Array = this.uint16Array;
24262
- for (let i = 0, c = uint16Array.length; i < c; i++) {
24263
- uint16Array[i] = toHalfFloat(numbers[i]);
24369
+ const uint16Array = this.uint16Array;
24370
+ batchConvertToHalfFloat(numbers, uint16Array, 0, numbers.length);
24371
+ const neededSize = uint16Array.byteLength;
24372
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize) {
24373
+ this._dataBuffer && this._dataBuffer.destroy();
24374
+ this._dataBuffer = device.createBuffer({
24375
+ size: neededSize,
24376
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24377
+ });
24264
24378
  }
24265
- const textureDataBuffer = this._dataBuffer = device.createBuffer({
24266
- size: uint16Array.byteLength,
24267
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24268
- });
24269
- device.queue.writeBuffer(textureDataBuffer, 0, uint16Array);
24379
+ device.queue.writeBuffer(this._dataBuffer, 0, uint16Array.buffer, uint16Array.byteOffset, uint16Array.byteLength);
24270
24380
  const commandEncoder = GPUContext.beginCommandEncoder();
24271
24381
  commandEncoder.copyBufferToTexture(
24272
24382
  {
24273
- buffer: textureDataBuffer,
24383
+ buffer: this._dataBuffer,
24274
24384
  bytesPerRow
24275
24385
  },
24276
24386
  {
@@ -24293,6 +24403,30 @@ class Float16ArrayTexture extends Texture {
24293
24403
  }
24294
24404
  }
24295
24405
 
24406
+ const _floatView = new Float32Array(1);
24407
+ const _int32View = new Int32Array(_floatView.buffer);
24408
+ let toHalfFloat = function(val) {
24409
+ _floatView[0] = val;
24410
+ const x = _int32View[0];
24411
+ let bits = x >> 16 & 32768;
24412
+ let m = x >> 12 & 2047;
24413
+ const e = x >> 23 & 255;
24414
+ if (e < 103) return bits;
24415
+ if (e > 142) {
24416
+ bits |= 31744;
24417
+ bits |= (e == 255 ? 1 : 0) && x & 8388607;
24418
+ return bits;
24419
+ }
24420
+ if (e < 114) {
24421
+ m |= 2048;
24422
+ bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24423
+ return bits;
24424
+ }
24425
+ bits |= e - 112 << 10 | m >> 1;
24426
+ bits += m & 1;
24427
+ return bits;
24428
+ };
24429
+
24296
24430
  var __getOwnPropDesc$m = Object.getOwnPropertyDescriptor;
24297
24431
  var __decorateClass$m = (decorators, target, key, kind) => {
24298
24432
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$m(target, key) : target;
@@ -42151,7 +42285,7 @@ class PostProcessingComponent extends ComponentBase {
42151
42285
  }
42152
42286
  }
42153
42287
 
42154
- const version = "1.0.36";
42288
+ const version = "1.0.38";
42155
42289
 
42156
42290
  class Engine3D {
42157
42291
  /**
@@ -54401,6 +54535,7 @@ let GSplatStreamRenderer = class extends RenderNode {
54401
54535
  transformB;
54402
54536
  texParams;
54403
54537
  // [numSplats, texWidth, validCount, visBoost]
54538
+ _texParamDirty = true;
54404
54539
  splatOrder;
54405
54540
  // Material and geometry
54406
54541
  gsplatMaterial;
@@ -54542,7 +54677,6 @@ let GSplatStreamRenderer = class extends RenderNode {
54542
54677
  if (!wasSet) {
54543
54678
  this._splatSetFlags[index] = true;
54544
54679
  this._validCount++;
54545
- this.texParams[2] = this._validCount;
54546
54680
  }
54547
54681
  this._pendingUpdates.add(index);
54548
54682
  }
@@ -54630,14 +54764,32 @@ let GSplatStreamRenderer = class extends RenderNode {
54630
54764
  /**
54631
54765
  * Flush pending updates to GPU
54632
54766
  * Updates GPU textures with all pending changes
54767
+ * Uses partial updates when possible for better performance
54633
54768
  */
54634
54769
  flushUpdates() {
54635
54770
  if (this._pendingUpdates.size === 0) return;
54636
54771
  const w = this.size.x | 0;
54637
54772
  const h = this.size.y | 0;
54638
- this.splatColor.updateTexture(w, h, this._colorData);
54639
- this.transformA.updateTexture(w, h, this._transformAData);
54640
- this.transformB.updateTexture(w, h, this._transformBData, false);
54773
+ const pendingIndices = Array.from(this._pendingUpdates);
54774
+ if (pendingIndices.length === 0) return;
54775
+ let minRow = h;
54776
+ let maxRow = 0;
54777
+ for (const index of pendingIndices) {
54778
+ const row = Math.floor(index / w);
54779
+ if (row < minRow) minRow = row;
54780
+ if (row > maxRow) maxRow = row;
54781
+ }
54782
+ const rowCount = maxRow - minRow + 1;
54783
+ const updateRatio = rowCount / h;
54784
+ if (updateRatio < 0.5 && rowCount < h) {
54785
+ this.splatColor.updateTexture(w, h, this._colorData, minRow, rowCount);
54786
+ this.transformA.updateTexture(w, h, this._transformAData, minRow, rowCount);
54787
+ this.transformB.updateTexture(w, h, this._transformBData, false, minRow, rowCount);
54788
+ } else {
54789
+ this.splatColor.updateTexture(w, h, this._colorData);
54790
+ this.transformA.updateTexture(w, h, this._transformAData);
54791
+ this.transformB.updateTexture(w, h, this._transformBData, false);
54792
+ }
54641
54793
  this.updatePendingWorldPositions();
54642
54794
  this._pendingUpdates.clear();
54643
54795
  }
@@ -54663,13 +54815,13 @@ let GSplatStreamRenderer = class extends RenderNode {
54663
54815
  * Update splat sorting before rendering
54664
54816
  * Uses the same logic as GSplatRenderer for reliable sorting
54665
54817
  */
54666
- onBeforeUpdate(view) {
54667
- if (this._validCount > 0 && view?.camera) {
54668
- if (view.camera.viewMatrix) {
54669
- this.scheduleOrder(view.camera.viewMatrix);
54670
- }
54671
- }
54672
- }
54818
+ // public onBeforeUpdate(view?: View3D) {
54819
+ // if (this._validCount > 0 && view?.camera) {
54820
+ // if (view.camera.viewMatrix) {
54821
+ // this.scheduleOrder(view.camera.viewMatrix);
54822
+ // }
54823
+ // }
54824
+ // }
54673
54825
  /**
54674
54826
  * Update world space positions when transform changes
54675
54827
  */
@@ -54743,8 +54895,7 @@ let GSplatStreamRenderer = class extends RenderNode {
54743
54895
  }
54744
54896
  this.splatOrder.updateTexture(this.size.x, this.size.y, this._orderData);
54745
54897
  const valid = Math.max(0, Math.min(this._validCount, ev.data.count | 0));
54746
- this.texParams[2] = valid;
54747
- this.texParams[0] = valid;
54898
+ this.setCount(valid);
54748
54899
  this._updateTexParams();
54749
54900
  const newInstanceCount = Math.ceil(valid / this._batchSize);
54750
54901
  this.instanceCount = newInstanceCount;
@@ -54950,12 +55101,17 @@ let GSplatStreamRenderer = class extends RenderNode {
54950
55101
  */
54951
55102
  setVisBoost(v) {
54952
55103
  this.texParams[3] = Math.max(0, v);
55104
+ this._texParamDirty = true;
54953
55105
  }
54954
55106
  setCount(c) {
54955
55107
  this.texParams[0] = Math.max(0, c);
55108
+ this._texParamDirty = true;
54956
55109
  }
54957
55110
  _updateTexParams() {
54958
- this.gsplatMaterial.setTexParams(this.texParams);
55111
+ if (this._texParamDirty) {
55112
+ this.gsplatMaterial.setTexParams(this.texParams);
55113
+ this._texParamDirty = false;
55114
+ }
54959
55115
  }
54960
55116
  /**
54961
55117
  * Set sort throttle interval (milliseconds)
@@ -55015,6 +55171,11 @@ let GSplatStreamRenderer = class extends RenderNode {
55015
55171
  * Update node before rendering
55016
55172
  */
55017
55173
  nodeUpdate(view, passType, renderPassState, clusterLightingBuffer) {
55174
+ if (this._validCount > 0 && view?.camera) {
55175
+ if (view.camera.viewMatrix) {
55176
+ this.scheduleOrder(view.camera.viewMatrix);
55177
+ }
55178
+ }
55018
55179
  if (this._pendingUpdates.size > 0 && this._frameCount >= 60) {
55019
55180
  this.flushUpdates();
55020
55181
  }
@@ -55022,6 +55183,7 @@ let GSplatStreamRenderer = class extends RenderNode {
55022
55183
  this._frameCount = 0;
55023
55184
  }
55024
55185
  this._frameCount++;
55186
+ this._updateTexParams();
55025
55187
  const worldMatrix = this.object3D.transform.worldMatrix;
55026
55188
  this.gsplatMaterial.setTransformMatrix(worldMatrix);
55027
55189
  const currentParams = `${this._minPixelCoverage},${this._maxPixelCoverage},${this._maxPixelCullDistance},${this._batchSize}`;