@volter/blender-engine 0.1.80 → 0.1.82

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.
@@ -4,15 +4,16 @@ export const ORDERED_BATCH_CAPACITY = 64;
4
4
  const FAMILY_BYTES = 4 * 1024 * 1024;
5
5
  const CACHE_BYTES = 32 * 1024 * 1024;
6
6
  const MAX_DRAWS = 1024;
7
- type Shape = {geometry: THREE.BufferGeometry; stamp: string};
7
+ type Shape = {geometry: THREE.BufferGeometry; stamp: string; bytes: number};
8
8
  type Family = {material: THREE.Material; shapes: Map<number, Shape>; template: THREE.BatchedMesh | null;
9
- ids: Map<number, number>; draws: THREE.BatchedMesh[]; dirty: boolean; bytes: number; refused: boolean};
9
+ ids: Map<number, number>; draws: THREE.BatchedMesh[]; dirty: boolean; bytes: number; reservedBytes: number; refused: boolean};
10
10
 
11
11
  /** Immutable packed attributes are shared between ordered draw runs. Only the
12
12
  * matrix/indirection textures and command lists belong to an individual run.
13
13
  * All interaction and authored geometry remain on the canonical meshes. */
14
14
  export class BlenderOrderedBatches {
15
15
  private readonly families = new Map<string, Family>();
16
+ private readonly partitions = new Map<string, string[]>();
16
17
  private readonly registrations = new Map<string, string | null>();
17
18
  private bytes = 0;
18
19
  private drawCount = 0;
@@ -43,16 +44,26 @@ export class BlenderOrderedBatches {
43
44
  bytes += attribute.array.byteLength;
44
45
  }
45
46
  if (bytes > FAMILY_BYTES) return null;
46
- const key = `multi:${material.uuid}:${order}:${JSON.stringify(layout)}`;
47
+ const layoutKey = `multi:${material.uuid}:${order}:${JSON.stringify(layout)}`;
48
+ let keys = this.partitions.get(layoutKey);
49
+ if (!keys) { keys = []; this.partitions.set(layoutKey, keys); }
50
+ // A new compatible shape must not evict every existing run when their
51
+ // union exceeds one bounded allocation (notably full + navigation copies).
52
+ // Partition deterministically, preserving established geometry membership.
53
+ let key = keys.find(key => this.families.get(key)!.shapes.has(geometry.id));
54
+ key ??= keys.find(key => this.families.get(key)!.reservedBytes + bytes <= FAMILY_BYTES);
55
+ if (!key) { key = `${layoutKey}:${keys.length}`; keys.push(key); }
47
56
  let family = this.families.get(key);
48
57
  if (!family) {
49
- family = {material, shapes: new Map(), template: null, ids: new Map(), draws: [], dirty: true, bytes: 0, refused: false};
58
+ family = {material, shapes: new Map(), template: null, ids: new Map(), draws: [], dirty: true,
59
+ bytes: 0, reservedBytes: 0, refused: false};
50
60
  this.families.set(key, family);
51
61
  }
52
62
  const stamp = JSON.stringify(versions);
53
63
  const held = family.shapes.get(geometry.id);
54
64
  if (!held || held.stamp !== stamp) {
55
- family.shapes.set(geometry.id, {geometry, stamp});
65
+ family.reservedBytes += bytes - (held?.bytes ?? 0);
66
+ family.shapes.set(geometry.id, {geometry, stamp, bytes});
56
67
  family.dirty = true;
57
68
  }
58
69
  this.registrations.set(registration, key);
@@ -150,6 +161,7 @@ export class BlenderOrderedBatches {
150
161
  clear(): void {
151
162
  for (const family of this.families.values()) this.release(family);
152
163
  this.families.clear();
164
+ this.partitions.clear();
153
165
  this.registrations.clear();
154
166
  this.pending = false;
155
167
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@volter/blender-engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "GPL-3.0-or-later",
5
- "version": "0.1.80",
5
+ "version": "0.1.82",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },