@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
|
|
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,
|
|
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.
|
|
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
|
}
|