gaussian-splat-lite 1.0.1 → 1.0.2

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.
@@ -4913,11 +4913,8 @@ const ELEMENTS_PER_THREAD = 8;
4913
4913
  const ELEMENTS_PER_WORKGROUP = WORKGROUP_SIZE$1 * ELEMENTS_PER_THREAD;
4914
4914
  const PREFIX_ITEMS_PER_WORKGROUP = WORKGROUP_SIZE$1 * 2;
4915
4915
  const PREFIX_LEVELS = 3;
4916
- function storage(buffer2, type, name, readOnly = false) {
4917
- const getBuffer = () => buffer2.value;
4918
- const node = N$2.storage(getBuffer(), type).onObjectUpdate(getBuffer);
4919
- node.name = name;
4920
- return readOnly ? node.toReadOnly() : node;
4916
+ function storage(buffer2, name) {
4917
+ return N$2.storage(buffer2.value, "uint").setName(name).onObjectUpdate(() => buffer2.value);
4921
4918
  }
4922
4919
  function mutableUniform(value, type) {
4923
4920
  const holder = { value };
@@ -4942,8 +4939,8 @@ function makeHistogramTask({
4942
4939
  bitOffset,
4943
4940
  workgroupCount
4944
4941
  }) {
4945
- const inputKeys = storage(input, "uint", "gslRadixInputKeys", true);
4946
- const sums = storage(blockSums, "uint", "gslRadixBlockSums");
4942
+ const inputKeys = storage(input, "gslRadixInputKeys").toReadOnly();
4943
+ const sums = storage(blockSums, "gslRadixBlockSums");
4947
4944
  const bit = N$2.uint(bitOffset);
4948
4945
  const histogram = N$2.workgroupArray("uint", RADIX_BUCKETS).toAtomic().setName("gslRadixHistogram");
4949
4946
  return N$2.Fn(() => {
@@ -4976,8 +4973,8 @@ function makeHistogramTask({
4976
4973
  })().compute([1, 1, 1], [WORKGROUP_SIZE$1]).setName("Splat radix histogram");
4977
4974
  }
4978
4975
  function makePrefixScanTask(itemsBuffer, blockSumsBuffer, elementCount) {
4979
- const items = storage(itemsBuffer, "uint", "gslPrefixItems");
4980
- const blockSums = storage(blockSumsBuffer, "uint", "gslPrefixBlockSums");
4976
+ const items = storage(itemsBuffer, "gslPrefixItems");
4977
+ const blockSums = storage(blockSumsBuffer, "gslPrefixBlockSums");
4981
4978
  const temp = N$2.workgroupArray("uint", PREFIX_ITEMS_PER_WORKGROUP).setName(
4982
4979
  "gslPrefixTemp"
4983
4980
  );
@@ -5049,13 +5046,8 @@ function makePrefixScanTask(itemsBuffer, blockSumsBuffer, elementCount) {
5049
5046
  return compute;
5050
5047
  }
5051
5048
  function makePrefixAddTask(itemsBuffer, blockSumsBuffer, elementCount) {
5052
- const items = storage(itemsBuffer, "uint", "gslPrefixItems");
5053
- const blockSums = storage(
5054
- blockSumsBuffer,
5055
- "uint",
5056
- "gslPrefixBlockSums",
5057
- true
5058
- );
5049
+ const items = storage(itemsBuffer, "gslPrefixItems");
5050
+ const blockSums = storage(blockSumsBuffer, "gslPrefixBlockSums").toReadOnly();
5059
5051
  const compute = N$2.Fn(() => {
5060
5052
  const workgroup = workgroupIndex();
5061
5053
  const first = workgroup.mul(PREFIX_ITEMS_PER_WORKGROUP).add(N$2.invocationLocalIndex.mul(2));
@@ -5085,23 +5077,15 @@ function makeReorderTask({
5085
5077
  }) {
5086
5078
  const inputKeys = storage(
5087
5079
  inputKeysAttribute,
5088
- "uint",
5089
- "gslRadixInputKeys",
5090
- true
5091
- );
5092
- const outputKeys = lastPass ? null : storage(outputKeysAttribute, "uint", "gslRadixOutputKeys");
5080
+ "gslRadixInputKeys"
5081
+ ).toReadOnly();
5082
+ const outputKeys = lastPass ? null : storage(outputKeysAttribute, "gslRadixOutputKeys");
5093
5083
  const inputValues = storage(
5094
5084
  inputValuesAttribute,
5095
- "uint",
5096
- "gslRadixInputValues",
5097
- true
5098
- );
5099
- const outputValues = storage(
5100
- outputValuesAttribute,
5101
- "uint",
5102
- "gslRadixOutputValues"
5103
- );
5104
- const prefix = storage(prefixAttribute, "uint", "gslRadixPrefix", true);
5085
+ "gslRadixInputValues"
5086
+ ).toReadOnly();
5087
+ const outputValues = storage(outputValuesAttribute, "gslRadixOutputValues");
5088
+ const prefix = storage(prefixAttribute, "gslRadixPrefix").toReadOnly();
5105
5089
  const bitOffsetNode = N$2.uint(bitOffset);
5106
5090
  const digitMasks = N$2.workgroupArray("uint", RADIX_BUCKETS * 8).toAtomic().setName("gslRadixDigitMasks");
5107
5091
  const digitOffsets = N$2.workgroupArray("uint", RADIX_BUCKETS).setName(
@@ -5224,7 +5208,7 @@ class WebGPURadixSort {
5224
5208
  this.values = [makeBufferRef(safeCapacity), makeBufferRef(safeCapacity)];
5225
5209
  const histogramCount = RADIX_BUCKETS * this.paddedWorkgroups(safeCapacity, ELEMENTS_PER_WORKGROUP);
5226
5210
  this.blockSums = makeBufferRef(histogramCount);
5227
- const counts = storage(this.counts, "uint", "gslRadixCounts", true);
5211
+ const counts = storage(this.counts, "gslRadixCounts").toReadOnly();
5228
5212
  this.createPrefixLevels(histogramCount, counts);
5229
5213
  const setup = this.makeSetupTask(options.count);
5230
5214
  const prefixNodes = this.prefixLevels.map((_, lastLevel) => {
@@ -5291,13 +5275,11 @@ class WebGPURadixSort {
5291
5275
  return Math.max(1, width * Math.ceil(groups / this.maxWorkgroups));
5292
5276
  }
5293
5277
  makeSetupTask(gpuCount) {
5294
- const counts = storage(this.counts, "uint", "gslRadixCounts");
5278
+ const counts = storage(this.counts, "gslRadixCounts");
5295
5279
  const dispatchBuffers = [
5296
5280
  this.sortDispatch,
5297
5281
  ...this.prefixLevels.map((level) => level.dispatch)
5298
- ].map(
5299
- (value, index2) => storage({ value }, "uint", `gslRadixDispatch${index2}`)
5300
- );
5282
+ ].map((value, index2) => storage({ value }, `gslRadixDispatch${index2}`));
5301
5283
  const maxWorkgroups = N$2.uint(this.maxWorkgroups);
5302
5284
  return N$2.Fn(() => {
5303
5285
  const count = N$2.min(
@@ -5409,29 +5391,31 @@ class WebGPURadixSort {
5409
5391
  const N$1 = TSL;
5410
5392
  const WORKGROUP_SIZE = 256;
5411
5393
  const PROJECT_SLOTS = 8;
5412
- function buffer(count = 1) {
5413
- return { value: new StorageBufferAttribute(new Uint32Array(count), 1) };
5394
+ function buffer(name) {
5395
+ return { value: new StorageBufferAttribute(new Uint32Array(1), 1), name };
5414
5396
  }
5415
- function bindBuffer(ref, readOnly = false) {
5416
- const node = N$1.storage(ref.value, "uint").onObjectUpdate(() => ref.value);
5417
- return readOnly ? node.toReadOnly() : node;
5397
+ function bindBuffer(ref) {
5398
+ return N$1.storage(ref.value, "uint").setName(ref.name).onObjectUpdate(() => ref.value);
5418
5399
  }
5419
5400
  class ProjectedSplats {
5420
5401
  constructor(renderer, uniforms) {
5421
5402
  this.renderer = renderer;
5422
5403
  this.uniforms = uniforms;
5423
- this.indirect = new IndirectStorageBufferAttribute(new Uint32Array(5), 1);
5424
- this.pending = true;
5404
+ this.indirect = new IndirectStorageBufferAttribute(
5405
+ new Uint32Array([WEBGPU_SPLATS_PER_INSTANCE * 6, 0, 0, 0, 0]),
5406
+ 1
5407
+ );
5425
5408
  this.error = null;
5426
5409
  this.cache = new ProjectionCache();
5427
5410
  this.visibleCount = new StorageBufferAttribute(
5428
5411
  new Uint32Array(1),
5429
5412
  1
5430
5413
  );
5431
- this.keys = buffer();
5432
- this.seeds = buffer();
5433
- this.counts = buffer();
5414
+ this.keys = buffer("gslProjectionKeys");
5415
+ this.seeds = buffer("gslProjectionSeeds");
5416
+ this.counts = buffer("gslProjectionCounts");
5434
5417
  this.slots = [];
5418
+ this.compiledSlots = 0;
5435
5419
  this.matrix = new THREE.Matrix4();
5436
5420
  this.translation = new THREE.Matrix4();
5437
5421
  this.scale = new THREE.Vector3();
@@ -5461,8 +5445,8 @@ class ProjectedSplats {
5461
5445
  const viewBase = uniformBinding(this.state, "viewBase", "uint");
5462
5446
  const multiView = uniformBinding(this.state, "multiView", "bool");
5463
5447
  const stochastic = uniformBinding(uniforms, "stochastic", "bool");
5464
- const count = N$1.storage(this.visibleCount, "uint").toReadOnly().element(0);
5465
- const seeds = bindBuffer(this.seeds, true);
5448
+ const count = N$1.storage(this.visibleCount, "uint").setName("gslVisibleCount").toReadOnly().element(0);
5449
+ const seeds = bindBuffer(this.seeds).toReadOnly();
5466
5450
  this.sorter = new WebGPURadixSort(1, this.keys, {
5467
5451
  count,
5468
5452
  storeOrder: (index2, value) => {
@@ -5479,15 +5463,8 @@ class ProjectedSplats {
5479
5463
  this.limits.maxBufferSize
5480
5464
  )
5481
5465
  });
5482
- const draw = N$1.storage(this.indirect, "uint");
5483
- this.resetDraw = N$1.Fn(() => {
5484
- draw.element(0).assign(WEBGPU_SPLATS_PER_INSTANCE * 6);
5485
- draw.element(1).assign(0);
5486
- draw.element(2).assign(0);
5487
- draw.element(3).assign(0);
5488
- draw.element(4).assign(0);
5489
- })().compute(1).setName("Splat reset draw");
5490
- const counter = N$1.storage(this.visibleCount, "uint").toAtomic();
5466
+ const drawCount = N$1.storage(this.indirect, "uint").setName("gslDrawIndirect").element(1);
5467
+ const counter = N$1.storage(this.visibleCount, "uint").setName("gslVisibleCount").toAtomic();
5491
5468
  this.resetCount = N$1.Fn(() => {
5492
5469
  N$1.atomicStore(counter.element(0), N$1.uint(0));
5493
5470
  })().compute(1, [1]).setName("Splat reset visible count");
@@ -5498,7 +5475,9 @@ class ProjectedSplats {
5498
5475
  N$1.If(index2.equal(0), () => {
5499
5476
  counts.element(viewIndex).assign(count);
5500
5477
  const instances = count.add(WEBGPU_SPLATS_PER_INSTANCE - 1).div(N$1.uint(WEBGPU_SPLATS_PER_INSTANCE));
5501
- draw.element(1).assign(draw.element(1).max(instances));
5478
+ drawCount.assign(
5479
+ N$1.select(viewIndex.equal(0), instances, drawCount.max(instances))
5480
+ );
5502
5481
  });
5503
5482
  N$1.If(multiView.and(stochastic).and(index2.lessThan(count)), () => {
5504
5483
  this.cache.storeOrder(
@@ -5509,17 +5488,30 @@ class ProjectedSplats {
5509
5488
  })().compute(1, [WORKGROUP_SIZE]).setName("Splat visible draw arguments");
5510
5489
  for (let i = 0; i < PROJECT_SLOTS; i++) this.slots.push(this.createSlot());
5511
5490
  this.ready = computeRenderer.compileComputeAsync([
5512
- this.resetDraw,
5513
5491
  this.resetCount,
5514
5492
  this.finish,
5515
- ...this.slots.map((slot) => slot.node),
5516
- ...this.sorter.nodes
5517
- ]).catch((error) => {
5493
+ ...this.sorter.nodes,
5494
+ this.slots[0].node
5495
+ ]).then(() => {
5496
+ this.compiledSlots = 1;
5497
+ }).catch((error) => {
5518
5498
  this.error = error;
5519
- }).finally(() => {
5520
- this.pending = false;
5521
- if (this.disposed) this.disposeResources();
5522
5499
  });
5500
+ this.compilation = this.ready.then(() => this.compileRemainingSlots());
5501
+ }
5502
+ async compileRemainingSlots() {
5503
+ if (this.disposed || this.compiledSlots === 0) return;
5504
+ try {
5505
+ await new Promise((resolve) => setTimeout(resolve, 0));
5506
+ while (!this.disposed && this.compiledSlots < this.slots.length) {
5507
+ await this.renderer.compileComputeAsync([
5508
+ this.slots[this.compiledSlots].node
5509
+ ]);
5510
+ this.compiledSlots++;
5511
+ }
5512
+ } catch (error) {
5513
+ this.error = error;
5514
+ }
5523
5515
  }
5524
5516
  createSlot() {
5525
5517
  const uniforms = { ...this.state, ...makeGenerateUniforms() };
@@ -5543,7 +5535,7 @@ class ProjectedSplats {
5543
5535
  const pixelScale = u("renderSize", "vec2").mul(u("focalAdjustment", "float")).mul(0.5);
5544
5536
  const keys = bindBuffer(this.keys);
5545
5537
  const seeds = bindBuffer(this.seeds);
5546
- const counter = N$1.storage(this.visibleCount, "uint").toAtomic();
5538
+ const counter = N$1.storage(this.visibleCount, "uint").setName("gslVisibleCount").toAtomic();
5547
5539
  const node = N$1.Fn(() => {
5548
5540
  const index2 = N$1.uint(N$1.instanceIndex);
5549
5541
  const generated = generate.prepare(index2);
@@ -5596,7 +5588,7 @@ class ProjectedSplats {
5596
5588
  const stride = uniformBinding(this.state, "viewStride", "uint");
5597
5589
  const base = eye.mul(stride).toVar();
5598
5590
  const i = N$1.uint(N$1.instanceIndex).mul(WEBGPU_SPLATS_PER_INSTANCE).add(N$1.uint(N$1.positionGeometry.z));
5599
- const counts = bindBuffer(this.counts, true);
5591
+ const counts = bindBuffer(this.counts).toReadOnly();
5600
5592
  const clipPosition = N$1.vec4(0, 0, 2, 1).toVar();
5601
5593
  const rgba = N$1.vec4(0).toVar();
5602
5594
  const splatUv = N$1.vec2(0).toVar();
@@ -5612,7 +5604,7 @@ class ProjectedSplats {
5612
5604
  const cacheIndex = i.toVar();
5613
5605
  const assignSeed = () => {
5614
5606
  stochasticSeed.assign(
5615
- multiView ? this.cache.readOrder(base.add(i)).y : bindBuffer(this.seeds, true).element(i)
5607
+ multiView ? this.cache.readOrder(base.add(i)).y : bindBuffer(this.seeds).toReadOnly().element(i)
5616
5608
  );
5617
5609
  };
5618
5610
  if (depthOnly) {
@@ -5691,7 +5683,7 @@ class ProjectedSplats {
5691
5683
  }
5692
5684
  render(accumulator, camera, geometry, radial, shrink = false) {
5693
5685
  if (this.error) throw this.error;
5694
- if (this.pending || this.disposed) {
5686
+ if (this.compiledSlots === 0 || this.disposed) {
5695
5687
  geometry.instanceCount = 0;
5696
5688
  return;
5697
5689
  }
@@ -5725,12 +5717,11 @@ class ProjectedSplats {
5725
5717
  this.scale
5726
5718
  );
5727
5719
  this.state.renderToViewScale.value = (this.scale.x + this.scale.y + this.scale.z) / 3;
5728
- const pending = eye === 0 ? [this.resetDraw] : [];
5729
- pending.push(this.resetCount);
5720
+ const pending = [this.resetCount];
5730
5721
  let slotCount = 0;
5731
5722
  for (const { node, count } of accumulator.mapping) {
5732
5723
  if (!view.layers.test(node.layers)) continue;
5733
- if (slotCount === PROJECT_SLOTS) {
5724
+ if (slotCount === this.compiledSlots) {
5734
5725
  this.renderer.compute(pending);
5735
5726
  pending.length = 0;
5736
5727
  slotCount = 0;
@@ -5751,12 +5742,11 @@ class ProjectedSplats {
5751
5742
  dispose() {
5752
5743
  if (this.disposed) return;
5753
5744
  this.disposed = true;
5754
- if (!this.pending) this.disposeResources();
5745
+ void this.compilation.then(() => this.disposeResources());
5755
5746
  }
5756
5747
  disposeResources() {
5757
5748
  for (const slot of this.slots) slot.node.dispose();
5758
- for (const node of [this.resetDraw, this.resetCount, this.finish])
5759
- node.dispose();
5749
+ for (const node of [this.resetCount, this.finish]) node.dispose();
5760
5750
  this.sorter.dispose();
5761
5751
  this.cache.dispose();
5762
5752
  this.visibleCount.dispose();