@bldrs-ai/conway 1.534.1505 → 1.536.1507
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.
- package/compiled/examples/browser-bundled.cjs +260 -3
- package/compiled/examples/cli-bundled.cjs +284 -3
- package/compiled/examples/cli-step-bundled.cjs +1 -1
- package/compiled/examples/validator-bundled.cjs +260 -3
- package/compiled/src/compat/web-ifc/ifc_api.d.ts +75 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api.js +61 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +547 -4
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +18 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +88 -3
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +468 -21
- package/compiled/src/ifc/geometry_dispatch.d.ts +68 -0
- package/compiled/src/ifc/geometry_dispatch.d.ts.map +1 -0
- package/compiled/src/ifc/geometry_dispatch.js +112 -0
- package/compiled/src/ifc/geometry_dispatch.test.d.ts +2 -0
- package/compiled/src/ifc/geometry_dispatch.test.d.ts.map +1 -0
- package/compiled/src/ifc/geometry_dispatch.test.js +70 -0
- package/compiled/src/ifc/geometry_residency.d.ts +170 -0
- package/compiled/src/ifc/geometry_residency.d.ts.map +1 -0
- package/compiled/src/ifc/geometry_residency.js +363 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_model_geometry.js +17 -2
- package/compiled/src/ifc/ifc_scene_builder.d.ts +13 -0
- package/compiled/src/ifc/ifc_scene_builder.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_scene_builder.js +25 -0
- package/compiled/src/ifc/ifc_step_model.d.ts +2 -0
- package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_model.js +4 -0
- package/compiled/src/index.d.ts +1 -0
- package/compiled/src/index.d.ts.map +1 -1
- package/compiled/src/index.js +1 -0
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
|
|
|
30
30
|
var readline = __toESM(require("node:readline"), 1);
|
|
31
31
|
|
|
32
32
|
// compiled/src/version/version.js
|
|
33
|
-
var versionString = "Conway v1.
|
|
33
|
+
var versionString = "Conway v1.536.1507";
|
|
34
34
|
|
|
35
35
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
36
36
|
var wasmType = "";
|
|
@@ -71239,6 +71239,257 @@ var CanonicalMeshType;
|
|
|
71239
71239
|
CanonicalMeshType2[CanonicalMeshType2["BUFFER_GEOMETRY"] = 0] = "BUFFER_GEOMETRY";
|
|
71240
71240
|
})(CanonicalMeshType || (CanonicalMeshType = {}));
|
|
71241
71241
|
|
|
71242
|
+
// compiled/src/ifc/geometry_residency.js
|
|
71243
|
+
var BYTES_PER_VERTEX_ELEMENT = 8;
|
|
71244
|
+
var BYTES_PER_INDEX_ELEMENT = 4;
|
|
71245
|
+
var VOID_STORE_BIT = 1;
|
|
71246
|
+
var BYTES_PER_MIB = 1024 * 1024;
|
|
71247
|
+
var GeometryResidency = class {
|
|
71248
|
+
constructor() {
|
|
71249
|
+
this.budgetBytes_ = Number.POSITIVE_INFINITY;
|
|
71250
|
+
this.liveBytes_ = 0;
|
|
71251
|
+
this.everEvicted_ = false;
|
|
71252
|
+
this.order_ = /* @__PURE__ */ new Map();
|
|
71253
|
+
this.natives_ = /* @__PURE__ */ new Map();
|
|
71254
|
+
this.stores_ = [];
|
|
71255
|
+
}
|
|
71256
|
+
/**
|
|
71257
|
+
* @return {boolean} Whether a finite budget is configured. Every hook below
|
|
71258
|
+
* returns immediately when this is false, so an unbudgeted model pays one
|
|
71259
|
+
* predictable-branch per geometry add and lookup rather than the
|
|
71260
|
+
* bookkeeping — `getByLocalID` is on the scene-walk hot path.
|
|
71261
|
+
*/
|
|
71262
|
+
get enabled() {
|
|
71263
|
+
return this.budgetBytes_ !== Number.POSITIVE_INFINITY;
|
|
71264
|
+
}
|
|
71265
|
+
/**
|
|
71266
|
+
* @return {number} The configured budget in bytes, or Infinity.
|
|
71267
|
+
*/
|
|
71268
|
+
get budgetBytes() {
|
|
71269
|
+
return this.budgetBytes_;
|
|
71270
|
+
}
|
|
71271
|
+
/**
|
|
71272
|
+
* @return {number} Bytes currently accounted resident.
|
|
71273
|
+
*/
|
|
71274
|
+
get liveBytes() {
|
|
71275
|
+
return this.liveBytes_;
|
|
71276
|
+
}
|
|
71277
|
+
/**
|
|
71278
|
+
* @return {number} How many assets are tracked.
|
|
71279
|
+
*/
|
|
71280
|
+
get residentCount() {
|
|
71281
|
+
return this.order_.size;
|
|
71282
|
+
}
|
|
71283
|
+
/**
|
|
71284
|
+
* @return {boolean} Whether this model has ever had geometry evicted.
|
|
71285
|
+
*/
|
|
71286
|
+
get everEvicted() {
|
|
71287
|
+
return this.everEvicted_;
|
|
71288
|
+
}
|
|
71289
|
+
/**
|
|
71290
|
+
* Register a store so a budget enabled later can see what it already
|
|
71291
|
+
* holds.
|
|
71292
|
+
*
|
|
71293
|
+
* @param store The store.
|
|
71294
|
+
*/
|
|
71295
|
+
registerStore(store) {
|
|
71296
|
+
this.stores_.push(store);
|
|
71297
|
+
}
|
|
71298
|
+
/**
|
|
71299
|
+
* Set the budget. A non-finite or non-positive value disables eviction,
|
|
71300
|
+
* which is the default and the behaviour every consumer had before this
|
|
71301
|
+
* existed.
|
|
71302
|
+
*
|
|
71303
|
+
* Raising or lowering it takes effect at the next eviction pass rather than
|
|
71304
|
+
* immediately, so a caller that lowers the budget mid-load does not stall
|
|
71305
|
+
* the current batch freeing memory.
|
|
71306
|
+
*
|
|
71307
|
+
* **Enabling seeds from what is already cached.** The bookkeeping is fed
|
|
71308
|
+
* by `noteAdded`, which no-ops while unlimited, so a model that pumped
|
|
71309
|
+
* batches before a budget arrived — or one whose budget was disabled and
|
|
71310
|
+
* re-enabled — would start counting from zero and evict nothing until it
|
|
71311
|
+
* had extracted a budget's worth MORE geometry. The pre-existing residency
|
|
71312
|
+
* would sit there permanently while liveBytes reported the ceiling was
|
|
71313
|
+
* satisfied. That is precisely the case SetGeometryBudget exists for: a
|
|
71314
|
+
* tab already under pressure.
|
|
71315
|
+
*
|
|
71316
|
+
* Seeding takes the stores in iteration order, which is extraction order,
|
|
71317
|
+
* so the recency order it produces is oldest-first — the right guess when
|
|
71318
|
+
* no better information survived.
|
|
71319
|
+
*
|
|
71320
|
+
* @param bytes The new ceiling, or Infinity to disable.
|
|
71321
|
+
*/
|
|
71322
|
+
setBudgetBytes(bytes) {
|
|
71323
|
+
if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
71324
|
+
this.budgetBytes_ = Number.POSITIVE_INFINITY;
|
|
71325
|
+
this.order_.clear();
|
|
71326
|
+
this.natives_.clear();
|
|
71327
|
+
this.liveBytes_ = 0;
|
|
71328
|
+
return;
|
|
71329
|
+
}
|
|
71330
|
+
const wasDisabled = !this.enabled;
|
|
71331
|
+
this.budgetBytes_ = bytes;
|
|
71332
|
+
if (wasDisabled) {
|
|
71333
|
+
this.seedFromStores_();
|
|
71334
|
+
}
|
|
71335
|
+
}
|
|
71336
|
+
/**
|
|
71337
|
+
* Account for everything the stores already hold, for a budget enabled
|
|
71338
|
+
* after extraction has started.
|
|
71339
|
+
*/
|
|
71340
|
+
seedFromStores_() {
|
|
71341
|
+
for (const store of this.stores_) {
|
|
71342
|
+
for (const mesh of store) {
|
|
71343
|
+
this.noteAdded(store, mesh);
|
|
71344
|
+
}
|
|
71345
|
+
}
|
|
71346
|
+
}
|
|
71347
|
+
/**
|
|
71348
|
+
* Record an asset as resident, or refresh one being replaced.
|
|
71349
|
+
*
|
|
71350
|
+
* @param store The store holding it.
|
|
71351
|
+
* @param mesh The mesh added.
|
|
71352
|
+
*/
|
|
71353
|
+
noteAdded(store, mesh) {
|
|
71354
|
+
if (!this.enabled) {
|
|
71355
|
+
return;
|
|
71356
|
+
}
|
|
71357
|
+
const key = residencyKey(store, mesh.localID);
|
|
71358
|
+
if (this.order_.has(key)) {
|
|
71359
|
+
this.releaseKey_(key);
|
|
71360
|
+
}
|
|
71361
|
+
if (mesh.type !== CanonicalMeshType.BUFFER_GEOMETRY) {
|
|
71362
|
+
return;
|
|
71363
|
+
}
|
|
71364
|
+
const native = mesh.geometry;
|
|
71365
|
+
const tracked = this.natives_.get(native);
|
|
71366
|
+
if (tracked !== void 0) {
|
|
71367
|
+
tracked.keys.add(key);
|
|
71368
|
+
} else {
|
|
71369
|
+
const bytes = meshBytes(mesh);
|
|
71370
|
+
this.natives_.set(native, { bytes, keys: /* @__PURE__ */ new Set([key]) });
|
|
71371
|
+
this.liveBytes_ += bytes;
|
|
71372
|
+
}
|
|
71373
|
+
this.order_.set(key, { store, native });
|
|
71374
|
+
}
|
|
71375
|
+
/**
|
|
71376
|
+
* Drop one key's reference, reporting whether the native it names is now
|
|
71377
|
+
* unreferenced and therefore safe to free.
|
|
71378
|
+
*
|
|
71379
|
+
* @param key The composite key.
|
|
71380
|
+
* @return {boolean} True when this was the last reference.
|
|
71381
|
+
*/
|
|
71382
|
+
releaseKey_(key) {
|
|
71383
|
+
const entry = this.order_.get(key);
|
|
71384
|
+
this.order_.delete(key);
|
|
71385
|
+
if (entry === void 0) {
|
|
71386
|
+
return true;
|
|
71387
|
+
}
|
|
71388
|
+
const tracked = this.natives_.get(entry.native);
|
|
71389
|
+
if (tracked === void 0) {
|
|
71390
|
+
return true;
|
|
71391
|
+
}
|
|
71392
|
+
tracked.keys.delete(key);
|
|
71393
|
+
if (tracked.keys.size > 0) {
|
|
71394
|
+
return false;
|
|
71395
|
+
}
|
|
71396
|
+
this.liveBytes_ -= tracked.bytes;
|
|
71397
|
+
this.natives_.delete(entry.native);
|
|
71398
|
+
return true;
|
|
71399
|
+
}
|
|
71400
|
+
/**
|
|
71401
|
+
* Whether freeing the native behind a store entry is safe — false while
|
|
71402
|
+
* another cached mesh still references the same native.
|
|
71403
|
+
*
|
|
71404
|
+
* @param store The store.
|
|
71405
|
+
* @param localID The asset's local ID.
|
|
71406
|
+
* @return {boolean} True when the caller should free the native.
|
|
71407
|
+
*/
|
|
71408
|
+
releaseReference(store, localID) {
|
|
71409
|
+
if (!this.enabled) {
|
|
71410
|
+
return true;
|
|
71411
|
+
}
|
|
71412
|
+
return this.releaseKey_(residencyKey(store, localID));
|
|
71413
|
+
}
|
|
71414
|
+
/**
|
|
71415
|
+
* Record a use, moving the asset to the most-recent end.
|
|
71416
|
+
*
|
|
71417
|
+
* @param store The store queried.
|
|
71418
|
+
* @param localID The asset's local ID.
|
|
71419
|
+
*/
|
|
71420
|
+
noteUsed(store, localID) {
|
|
71421
|
+
if (!this.enabled) {
|
|
71422
|
+
return;
|
|
71423
|
+
}
|
|
71424
|
+
const key = residencyKey(store, localID);
|
|
71425
|
+
const existing = this.order_.get(key);
|
|
71426
|
+
if (existing === void 0) {
|
|
71427
|
+
return;
|
|
71428
|
+
}
|
|
71429
|
+
this.order_.delete(key);
|
|
71430
|
+
this.order_.set(key, existing);
|
|
71431
|
+
}
|
|
71432
|
+
/**
|
|
71433
|
+
* Stop accounting for an asset something else freed — an explicit delete,
|
|
71434
|
+
* or the extractor reclaiming its own temporaries. Without this the budget
|
|
71435
|
+
* would keep charging for bytes nobody holds and evict live assets to make
|
|
71436
|
+
* room for them.
|
|
71437
|
+
*
|
|
71438
|
+
* @param store The store it was in.
|
|
71439
|
+
* @param localID The asset's local ID.
|
|
71440
|
+
*/
|
|
71441
|
+
noteRemoved(store, localID) {
|
|
71442
|
+
if (!this.enabled) {
|
|
71443
|
+
return;
|
|
71444
|
+
}
|
|
71445
|
+
this.releaseKey_(residencyKey(store, localID));
|
|
71446
|
+
}
|
|
71447
|
+
/**
|
|
71448
|
+
* Evict least-recently-used assets until the live set fits the budget.
|
|
71449
|
+
*
|
|
71450
|
+
* @return {{evicted: number, freedBytes: number}} What this pass reclaimed.
|
|
71451
|
+
*/
|
|
71452
|
+
evictToBudget() {
|
|
71453
|
+
if (!this.enabled) {
|
|
71454
|
+
return { evicted: 0, freedBytes: 0 };
|
|
71455
|
+
}
|
|
71456
|
+
let evicted = 0;
|
|
71457
|
+
let freedBytes = 0;
|
|
71458
|
+
for (const [key, entry] of this.order_) {
|
|
71459
|
+
if (this.liveBytes_ <= this.budgetBytes_) {
|
|
71460
|
+
break;
|
|
71461
|
+
}
|
|
71462
|
+
const localID = localIDOf(key);
|
|
71463
|
+
const bytes = this.natives_.get(entry.native)?.bytes ?? 0;
|
|
71464
|
+
entry.store.delete(localID);
|
|
71465
|
+
this.everEvicted_ = true;
|
|
71466
|
+
++evicted;
|
|
71467
|
+
freedBytes += bytes;
|
|
71468
|
+
}
|
|
71469
|
+
return { evicted, freedBytes };
|
|
71470
|
+
}
|
|
71471
|
+
};
|
|
71472
|
+
function residencyKey(store, localID) {
|
|
71473
|
+
return localID * 2 + (store.isVoid ? VOID_STORE_BIT : 0);
|
|
71474
|
+
}
|
|
71475
|
+
function localIDOf(key) {
|
|
71476
|
+
return (key - key % 2) / 2;
|
|
71477
|
+
}
|
|
71478
|
+
function meshBytes(mesh) {
|
|
71479
|
+
if (mesh.type !== CanonicalMeshType.BUFFER_GEOMETRY) {
|
|
71480
|
+
return 0;
|
|
71481
|
+
}
|
|
71482
|
+
try {
|
|
71483
|
+
const allocated = mesh.geometry.getAllocationSize?.();
|
|
71484
|
+
if (typeof allocated === "number" && allocated > 0) {
|
|
71485
|
+
return allocated;
|
|
71486
|
+
}
|
|
71487
|
+
return mesh.geometry.GetVertexDataSize() * BYTES_PER_VERTEX_ELEMENT + mesh.geometry.GetIndexDataSize() * BYTES_PER_INDEX_ELEMENT;
|
|
71488
|
+
} catch {
|
|
71489
|
+
return 0;
|
|
71490
|
+
}
|
|
71491
|
+
}
|
|
71492
|
+
|
|
71242
71493
|
// compiled/src/core/canonical_material.js
|
|
71243
71494
|
var ROUGNESS_CONVERSION_FACTOR = 2;
|
|
71244
71495
|
function roughnessToExponent(roughness) {
|
|
@@ -71318,6 +71569,7 @@ var IfcModelGeometry = class {
|
|
|
71318
71569
|
this.model = model2;
|
|
71319
71570
|
this.isVoid = isVoid;
|
|
71320
71571
|
this.meshes_ = /* @__PURE__ */ new Map();
|
|
71572
|
+
model2.geometryResidency.registerStore(this);
|
|
71321
71573
|
}
|
|
71322
71574
|
/**
|
|
71323
71575
|
* Get the number of items in this.
|
|
@@ -71334,7 +71586,8 @@ var IfcModelGeometry = class {
|
|
|
71334
71586
|
for (const [key, value] of this.meshes_) {
|
|
71335
71587
|
if (value.temporary) {
|
|
71336
71588
|
this.meshes_.delete(key);
|
|
71337
|
-
|
|
71589
|
+
const isLastReference = this.model.geometryResidency.releaseReference(this, key);
|
|
71590
|
+
if (value.type === CanonicalMeshType.BUFFER_GEOMETRY && isLastReference) {
|
|
71338
71591
|
value.geometry.delete();
|
|
71339
71592
|
}
|
|
71340
71593
|
}
|
|
@@ -71362,6 +71615,7 @@ var IfcModelGeometry = class {
|
|
|
71362
71615
|
mesh.geometry.GetVertexData();
|
|
71363
71616
|
}
|
|
71364
71617
|
this.meshes_.set(mesh.localID, mesh);
|
|
71618
|
+
this.model.geometryResidency.noteAdded(this, mesh);
|
|
71365
71619
|
}
|
|
71366
71620
|
/**
|
|
71367
71621
|
* Drop the mesh for a particular local ID
|
|
@@ -71372,7 +71626,8 @@ var IfcModelGeometry = class {
|
|
|
71372
71626
|
const value = this.meshes_.get(localID);
|
|
71373
71627
|
if (value !== void 0) {
|
|
71374
71628
|
this.meshes_.delete(localID);
|
|
71375
|
-
|
|
71629
|
+
const isLastReference = this.model.geometryResidency.releaseReference(this, localID);
|
|
71630
|
+
if (value.type === CanonicalMeshType.BUFFER_GEOMETRY && isLastReference) {
|
|
71376
71631
|
value.geometry.delete();
|
|
71377
71632
|
}
|
|
71378
71633
|
}
|
|
@@ -71384,6 +71639,7 @@ var IfcModelGeometry = class {
|
|
|
71384
71639
|
* @return {CanonicalMesh | undefined}
|
|
71385
71640
|
*/
|
|
71386
71641
|
getByLocalID(localID) {
|
|
71642
|
+
this.model.geometryResidency.noteUsed(this, localID);
|
|
71387
71643
|
return this.meshes_.get(localID);
|
|
71388
71644
|
}
|
|
71389
71645
|
/**
|
|
@@ -71844,6 +72100,7 @@ var IfcStepModel = class extends step_model_base_default {
|
|
|
71844
72100
|
constructor(buffer, elementIndex, provider) {
|
|
71845
72101
|
super(schema_ifc_gen_default, buffer, elementIndex, provider);
|
|
71846
72102
|
this.externalMappingType = ifc_step_external_mapping_default;
|
|
72103
|
+
this.geometryResidency = new GeometryResidency();
|
|
71847
72104
|
this.geometry = new IfcModelGeometry(this);
|
|
71848
72105
|
this.voidGeometry = new IfcModelGeometry(this, true);
|
|
71849
72106
|
this.profiles = new IfcModelProfile(this);
|
|
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
|
|
|
14965
14965
|
var import_process = require("process");
|
|
14966
14966
|
|
|
14967
14967
|
// compiled/src/version/version.js
|
|
14968
|
-
var versionString = "Conway v1.
|
|
14968
|
+
var versionString = "Conway v1.536.1507";
|
|
14969
14969
|
|
|
14970
14970
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
14971
14971
|
function pThreadsAllowed() {
|
|
@@ -87176,6 +87176,257 @@ var CanonicalMeshType;
|
|
|
87176
87176
|
CanonicalMeshType2[CanonicalMeshType2["BUFFER_GEOMETRY"] = 0] = "BUFFER_GEOMETRY";
|
|
87177
87177
|
})(CanonicalMeshType || (CanonicalMeshType = {}));
|
|
87178
87178
|
|
|
87179
|
+
// compiled/src/ifc/geometry_residency.js
|
|
87180
|
+
var BYTES_PER_VERTEX_ELEMENT = 8;
|
|
87181
|
+
var BYTES_PER_INDEX_ELEMENT = 4;
|
|
87182
|
+
var VOID_STORE_BIT = 1;
|
|
87183
|
+
var BYTES_PER_MIB = 1024 * 1024;
|
|
87184
|
+
var GeometryResidency = class {
|
|
87185
|
+
constructor() {
|
|
87186
|
+
this.budgetBytes_ = Number.POSITIVE_INFINITY;
|
|
87187
|
+
this.liveBytes_ = 0;
|
|
87188
|
+
this.everEvicted_ = false;
|
|
87189
|
+
this.order_ = /* @__PURE__ */ new Map();
|
|
87190
|
+
this.natives_ = /* @__PURE__ */ new Map();
|
|
87191
|
+
this.stores_ = [];
|
|
87192
|
+
}
|
|
87193
|
+
/**
|
|
87194
|
+
* @return {boolean} Whether a finite budget is configured. Every hook below
|
|
87195
|
+
* returns immediately when this is false, so an unbudgeted model pays one
|
|
87196
|
+
* predictable-branch per geometry add and lookup rather than the
|
|
87197
|
+
* bookkeeping — `getByLocalID` is on the scene-walk hot path.
|
|
87198
|
+
*/
|
|
87199
|
+
get enabled() {
|
|
87200
|
+
return this.budgetBytes_ !== Number.POSITIVE_INFINITY;
|
|
87201
|
+
}
|
|
87202
|
+
/**
|
|
87203
|
+
* @return {number} The configured budget in bytes, or Infinity.
|
|
87204
|
+
*/
|
|
87205
|
+
get budgetBytes() {
|
|
87206
|
+
return this.budgetBytes_;
|
|
87207
|
+
}
|
|
87208
|
+
/**
|
|
87209
|
+
* @return {number} Bytes currently accounted resident.
|
|
87210
|
+
*/
|
|
87211
|
+
get liveBytes() {
|
|
87212
|
+
return this.liveBytes_;
|
|
87213
|
+
}
|
|
87214
|
+
/**
|
|
87215
|
+
* @return {number} How many assets are tracked.
|
|
87216
|
+
*/
|
|
87217
|
+
get residentCount() {
|
|
87218
|
+
return this.order_.size;
|
|
87219
|
+
}
|
|
87220
|
+
/**
|
|
87221
|
+
* @return {boolean} Whether this model has ever had geometry evicted.
|
|
87222
|
+
*/
|
|
87223
|
+
get everEvicted() {
|
|
87224
|
+
return this.everEvicted_;
|
|
87225
|
+
}
|
|
87226
|
+
/**
|
|
87227
|
+
* Register a store so a budget enabled later can see what it already
|
|
87228
|
+
* holds.
|
|
87229
|
+
*
|
|
87230
|
+
* @param store The store.
|
|
87231
|
+
*/
|
|
87232
|
+
registerStore(store) {
|
|
87233
|
+
this.stores_.push(store);
|
|
87234
|
+
}
|
|
87235
|
+
/**
|
|
87236
|
+
* Set the budget. A non-finite or non-positive value disables eviction,
|
|
87237
|
+
* which is the default and the behaviour every consumer had before this
|
|
87238
|
+
* existed.
|
|
87239
|
+
*
|
|
87240
|
+
* Raising or lowering it takes effect at the next eviction pass rather than
|
|
87241
|
+
* immediately, so a caller that lowers the budget mid-load does not stall
|
|
87242
|
+
* the current batch freeing memory.
|
|
87243
|
+
*
|
|
87244
|
+
* **Enabling seeds from what is already cached.** The bookkeeping is fed
|
|
87245
|
+
* by `noteAdded`, which no-ops while unlimited, so a model that pumped
|
|
87246
|
+
* batches before a budget arrived — or one whose budget was disabled and
|
|
87247
|
+
* re-enabled — would start counting from zero and evict nothing until it
|
|
87248
|
+
* had extracted a budget's worth MORE geometry. The pre-existing residency
|
|
87249
|
+
* would sit there permanently while liveBytes reported the ceiling was
|
|
87250
|
+
* satisfied. That is precisely the case SetGeometryBudget exists for: a
|
|
87251
|
+
* tab already under pressure.
|
|
87252
|
+
*
|
|
87253
|
+
* Seeding takes the stores in iteration order, which is extraction order,
|
|
87254
|
+
* so the recency order it produces is oldest-first — the right guess when
|
|
87255
|
+
* no better information survived.
|
|
87256
|
+
*
|
|
87257
|
+
* @param bytes The new ceiling, or Infinity to disable.
|
|
87258
|
+
*/
|
|
87259
|
+
setBudgetBytes(bytes) {
|
|
87260
|
+
if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
87261
|
+
this.budgetBytes_ = Number.POSITIVE_INFINITY;
|
|
87262
|
+
this.order_.clear();
|
|
87263
|
+
this.natives_.clear();
|
|
87264
|
+
this.liveBytes_ = 0;
|
|
87265
|
+
return;
|
|
87266
|
+
}
|
|
87267
|
+
const wasDisabled = !this.enabled;
|
|
87268
|
+
this.budgetBytes_ = bytes;
|
|
87269
|
+
if (wasDisabled) {
|
|
87270
|
+
this.seedFromStores_();
|
|
87271
|
+
}
|
|
87272
|
+
}
|
|
87273
|
+
/**
|
|
87274
|
+
* Account for everything the stores already hold, for a budget enabled
|
|
87275
|
+
* after extraction has started.
|
|
87276
|
+
*/
|
|
87277
|
+
seedFromStores_() {
|
|
87278
|
+
for (const store of this.stores_) {
|
|
87279
|
+
for (const mesh of store) {
|
|
87280
|
+
this.noteAdded(store, mesh);
|
|
87281
|
+
}
|
|
87282
|
+
}
|
|
87283
|
+
}
|
|
87284
|
+
/**
|
|
87285
|
+
* Record an asset as resident, or refresh one being replaced.
|
|
87286
|
+
*
|
|
87287
|
+
* @param store The store holding it.
|
|
87288
|
+
* @param mesh The mesh added.
|
|
87289
|
+
*/
|
|
87290
|
+
noteAdded(store, mesh) {
|
|
87291
|
+
if (!this.enabled) {
|
|
87292
|
+
return;
|
|
87293
|
+
}
|
|
87294
|
+
const key = residencyKey(store, mesh.localID);
|
|
87295
|
+
if (this.order_.has(key)) {
|
|
87296
|
+
this.releaseKey_(key);
|
|
87297
|
+
}
|
|
87298
|
+
if (mesh.type !== CanonicalMeshType.BUFFER_GEOMETRY) {
|
|
87299
|
+
return;
|
|
87300
|
+
}
|
|
87301
|
+
const native = mesh.geometry;
|
|
87302
|
+
const tracked = this.natives_.get(native);
|
|
87303
|
+
if (tracked !== void 0) {
|
|
87304
|
+
tracked.keys.add(key);
|
|
87305
|
+
} else {
|
|
87306
|
+
const bytes = meshBytes(mesh);
|
|
87307
|
+
this.natives_.set(native, { bytes, keys: /* @__PURE__ */ new Set([key]) });
|
|
87308
|
+
this.liveBytes_ += bytes;
|
|
87309
|
+
}
|
|
87310
|
+
this.order_.set(key, { store, native });
|
|
87311
|
+
}
|
|
87312
|
+
/**
|
|
87313
|
+
* Drop one key's reference, reporting whether the native it names is now
|
|
87314
|
+
* unreferenced and therefore safe to free.
|
|
87315
|
+
*
|
|
87316
|
+
* @param key The composite key.
|
|
87317
|
+
* @return {boolean} True when this was the last reference.
|
|
87318
|
+
*/
|
|
87319
|
+
releaseKey_(key) {
|
|
87320
|
+
const entry = this.order_.get(key);
|
|
87321
|
+
this.order_.delete(key);
|
|
87322
|
+
if (entry === void 0) {
|
|
87323
|
+
return true;
|
|
87324
|
+
}
|
|
87325
|
+
const tracked = this.natives_.get(entry.native);
|
|
87326
|
+
if (tracked === void 0) {
|
|
87327
|
+
return true;
|
|
87328
|
+
}
|
|
87329
|
+
tracked.keys.delete(key);
|
|
87330
|
+
if (tracked.keys.size > 0) {
|
|
87331
|
+
return false;
|
|
87332
|
+
}
|
|
87333
|
+
this.liveBytes_ -= tracked.bytes;
|
|
87334
|
+
this.natives_.delete(entry.native);
|
|
87335
|
+
return true;
|
|
87336
|
+
}
|
|
87337
|
+
/**
|
|
87338
|
+
* Whether freeing the native behind a store entry is safe — false while
|
|
87339
|
+
* another cached mesh still references the same native.
|
|
87340
|
+
*
|
|
87341
|
+
* @param store The store.
|
|
87342
|
+
* @param localID The asset's local ID.
|
|
87343
|
+
* @return {boolean} True when the caller should free the native.
|
|
87344
|
+
*/
|
|
87345
|
+
releaseReference(store, localID) {
|
|
87346
|
+
if (!this.enabled) {
|
|
87347
|
+
return true;
|
|
87348
|
+
}
|
|
87349
|
+
return this.releaseKey_(residencyKey(store, localID));
|
|
87350
|
+
}
|
|
87351
|
+
/**
|
|
87352
|
+
* Record a use, moving the asset to the most-recent end.
|
|
87353
|
+
*
|
|
87354
|
+
* @param store The store queried.
|
|
87355
|
+
* @param localID The asset's local ID.
|
|
87356
|
+
*/
|
|
87357
|
+
noteUsed(store, localID) {
|
|
87358
|
+
if (!this.enabled) {
|
|
87359
|
+
return;
|
|
87360
|
+
}
|
|
87361
|
+
const key = residencyKey(store, localID);
|
|
87362
|
+
const existing = this.order_.get(key);
|
|
87363
|
+
if (existing === void 0) {
|
|
87364
|
+
return;
|
|
87365
|
+
}
|
|
87366
|
+
this.order_.delete(key);
|
|
87367
|
+
this.order_.set(key, existing);
|
|
87368
|
+
}
|
|
87369
|
+
/**
|
|
87370
|
+
* Stop accounting for an asset something else freed — an explicit delete,
|
|
87371
|
+
* or the extractor reclaiming its own temporaries. Without this the budget
|
|
87372
|
+
* would keep charging for bytes nobody holds and evict live assets to make
|
|
87373
|
+
* room for them.
|
|
87374
|
+
*
|
|
87375
|
+
* @param store The store it was in.
|
|
87376
|
+
* @param localID The asset's local ID.
|
|
87377
|
+
*/
|
|
87378
|
+
noteRemoved(store, localID) {
|
|
87379
|
+
if (!this.enabled) {
|
|
87380
|
+
return;
|
|
87381
|
+
}
|
|
87382
|
+
this.releaseKey_(residencyKey(store, localID));
|
|
87383
|
+
}
|
|
87384
|
+
/**
|
|
87385
|
+
* Evict least-recently-used assets until the live set fits the budget.
|
|
87386
|
+
*
|
|
87387
|
+
* @return {{evicted: number, freedBytes: number}} What this pass reclaimed.
|
|
87388
|
+
*/
|
|
87389
|
+
evictToBudget() {
|
|
87390
|
+
if (!this.enabled) {
|
|
87391
|
+
return { evicted: 0, freedBytes: 0 };
|
|
87392
|
+
}
|
|
87393
|
+
let evicted = 0;
|
|
87394
|
+
let freedBytes = 0;
|
|
87395
|
+
for (const [key, entry] of this.order_) {
|
|
87396
|
+
if (this.liveBytes_ <= this.budgetBytes_) {
|
|
87397
|
+
break;
|
|
87398
|
+
}
|
|
87399
|
+
const localID = localIDOf(key);
|
|
87400
|
+
const bytes = this.natives_.get(entry.native)?.bytes ?? 0;
|
|
87401
|
+
entry.store.delete(localID);
|
|
87402
|
+
this.everEvicted_ = true;
|
|
87403
|
+
++evicted;
|
|
87404
|
+
freedBytes += bytes;
|
|
87405
|
+
}
|
|
87406
|
+
return { evicted, freedBytes };
|
|
87407
|
+
}
|
|
87408
|
+
};
|
|
87409
|
+
function residencyKey(store, localID) {
|
|
87410
|
+
return localID * 2 + (store.isVoid ? VOID_STORE_BIT : 0);
|
|
87411
|
+
}
|
|
87412
|
+
function localIDOf(key) {
|
|
87413
|
+
return (key - key % 2) / 2;
|
|
87414
|
+
}
|
|
87415
|
+
function meshBytes(mesh) {
|
|
87416
|
+
if (mesh.type !== CanonicalMeshType.BUFFER_GEOMETRY) {
|
|
87417
|
+
return 0;
|
|
87418
|
+
}
|
|
87419
|
+
try {
|
|
87420
|
+
const allocated = mesh.geometry.getAllocationSize?.();
|
|
87421
|
+
if (typeof allocated === "number" && allocated > 0) {
|
|
87422
|
+
return allocated;
|
|
87423
|
+
}
|
|
87424
|
+
return mesh.geometry.GetVertexDataSize() * BYTES_PER_VERTEX_ELEMENT + mesh.geometry.GetIndexDataSize() * BYTES_PER_INDEX_ELEMENT;
|
|
87425
|
+
} catch {
|
|
87426
|
+
return 0;
|
|
87427
|
+
}
|
|
87428
|
+
}
|
|
87429
|
+
|
|
87179
87430
|
// compiled/src/core/canonical_material.js
|
|
87180
87431
|
var ROUGNESS_CONVERSION_FACTOR = 2;
|
|
87181
87432
|
function exponentToRoughness(shininess) {
|
|
@@ -87286,6 +87537,7 @@ var IfcModelGeometry = class {
|
|
|
87286
87537
|
this.model = model;
|
|
87287
87538
|
this.isVoid = isVoid;
|
|
87288
87539
|
this.meshes_ = /* @__PURE__ */ new Map();
|
|
87540
|
+
model.geometryResidency.registerStore(this);
|
|
87289
87541
|
}
|
|
87290
87542
|
/**
|
|
87291
87543
|
* Get the number of items in this.
|
|
@@ -87302,7 +87554,8 @@ var IfcModelGeometry = class {
|
|
|
87302
87554
|
for (const [key, value] of this.meshes_) {
|
|
87303
87555
|
if (value.temporary) {
|
|
87304
87556
|
this.meshes_.delete(key);
|
|
87305
|
-
|
|
87557
|
+
const isLastReference = this.model.geometryResidency.releaseReference(this, key);
|
|
87558
|
+
if (value.type === CanonicalMeshType.BUFFER_GEOMETRY && isLastReference) {
|
|
87306
87559
|
value.geometry.delete();
|
|
87307
87560
|
}
|
|
87308
87561
|
}
|
|
@@ -87330,6 +87583,7 @@ var IfcModelGeometry = class {
|
|
|
87330
87583
|
mesh.geometry.GetVertexData();
|
|
87331
87584
|
}
|
|
87332
87585
|
this.meshes_.set(mesh.localID, mesh);
|
|
87586
|
+
this.model.geometryResidency.noteAdded(this, mesh);
|
|
87333
87587
|
}
|
|
87334
87588
|
/**
|
|
87335
87589
|
* Drop the mesh for a particular local ID
|
|
@@ -87340,7 +87594,8 @@ var IfcModelGeometry = class {
|
|
|
87340
87594
|
const value = this.meshes_.get(localID);
|
|
87341
87595
|
if (value !== void 0) {
|
|
87342
87596
|
this.meshes_.delete(localID);
|
|
87343
|
-
|
|
87597
|
+
const isLastReference = this.model.geometryResidency.releaseReference(this, localID);
|
|
87598
|
+
if (value.type === CanonicalMeshType.BUFFER_GEOMETRY && isLastReference) {
|
|
87344
87599
|
value.geometry.delete();
|
|
87345
87600
|
}
|
|
87346
87601
|
}
|
|
@@ -87352,6 +87607,7 @@ var IfcModelGeometry = class {
|
|
|
87352
87607
|
* @return {CanonicalMesh | undefined}
|
|
87353
87608
|
*/
|
|
87354
87609
|
getByLocalID(localID) {
|
|
87610
|
+
this.model.geometryResidency.noteUsed(this, localID);
|
|
87355
87611
|
return this.meshes_.get(localID);
|
|
87356
87612
|
}
|
|
87357
87613
|
/**
|
|
@@ -87812,6 +88068,7 @@ var IfcStepModel = class extends step_model_base_default {
|
|
|
87812
88068
|
constructor(buffer, elementIndex, provider) {
|
|
87813
88069
|
super(schema_ifc_gen_default, buffer, elementIndex, provider);
|
|
87814
88070
|
this.externalMappingType = ifc_step_external_mapping_default;
|
|
88071
|
+
this.geometryResidency = new GeometryResidency();
|
|
87815
88072
|
this.geometry = new IfcModelGeometry(this);
|
|
87816
88073
|
this.voidGeometry = new IfcModelGeometry(this, true);
|
|
87817
88074
|
this.profiles = new IfcModelProfile(this);
|
|
@@ -88710,6 +88967,30 @@ var IfcSceneBuilder = class {
|
|
|
88710
88967
|
yield resolved;
|
|
88711
88968
|
}
|
|
88712
88969
|
}
|
|
88970
|
+
/**
|
|
88971
|
+
* The products owning geometry nodes whose geometry does not currently
|
|
88972
|
+
* resolve — everything that would be silently missing from a whole-scene
|
|
88973
|
+
* walk right now.
|
|
88974
|
+
*
|
|
88975
|
+
* Exists for recovery after eviction: a budget can free geometry that the
|
|
88976
|
+
* accumulated per-entity meshes still reference, and re-extracting the
|
|
88977
|
+
* owning products is what puts it back. Returns owners rather than nodes
|
|
88978
|
+
* because extraction is per-product.
|
|
88979
|
+
*
|
|
88980
|
+
* @return {Set<number>} Local IDs of the owning products, possibly empty.
|
|
88981
|
+
*/
|
|
88982
|
+
unresolvedGeometryOwners() {
|
|
88983
|
+
const owners = /* @__PURE__ */ new Set();
|
|
88984
|
+
for (const node of this.scene_) {
|
|
88985
|
+
if (!(node instanceof IfcSceneGeometry) || node.relatedElementLocalId === void 0) {
|
|
88986
|
+
continue;
|
|
88987
|
+
}
|
|
88988
|
+
if (node.model.geometry?.getByLocalID(node.localID) === void 0) {
|
|
88989
|
+
owners.add(node.relatedElementLocalId);
|
|
88990
|
+
}
|
|
88991
|
+
}
|
|
88992
|
+
return owners;
|
|
88993
|
+
}
|
|
88713
88994
|
/**
|
|
88714
88995
|
* Resolve one node by index, for retrying a node {@link walkFrom} yielded
|
|
88715
88996
|
* without geometry.
|
|
@@ -15943,7 +15943,7 @@ var ParsingBuffer = class {
|
|
|
15943
15943
|
};
|
|
15944
15944
|
|
|
15945
15945
|
// compiled/src/version/version.js
|
|
15946
|
-
var versionString = "Conway v1.
|
|
15946
|
+
var versionString = "Conway v1.536.1507";
|
|
15947
15947
|
|
|
15948
15948
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
15949
15949
|
function pThreadsAllowed() {
|