@aardworx/wombat.rendering 0.21.20 → 0.21.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aardworx/wombat.rendering",
3
- "version": "0.21.20",
3
+ "version": "0.21.22",
4
4
  "description": "WebGPU rendering layer for the Wombat TypeScript stack — RenderObject/RenderTask/runtime + window glue, port of Aardvark.Rendering's lower layers on top of WebGPU and wombat.shader.",
5
5
  "license": "MIT",
6
6
  "author": "krauthaufen",
@@ -109,7 +109,15 @@ export interface FragmentOutputLayout {
109
109
  // and on quota; every failure simply degrades to "recompute".
110
110
 
111
111
  /** Cache-generation stamp for the persistent (localStorage) tier. */
112
- export const HEAP_PERSIST_VERSION = "h11"; // h11: FS textureSize on atlas-routed textures reads the draw-header sizeemitted WGSL changed
112
+ // h12: the atlas PAGE SIZE is embedded in the WGSL (uv divisor) it
113
+ // must be part of the persist key or a cached 4096-shader poisons an
114
+ // 8192-page session (black beyond the first quadrant). The size rides
115
+ // in the version string so any future size change re-keys too.
116
+ export const HEAP_PERSIST_VERSION_BASE = "h12";
117
+ export const HEAP_PERSIST_VERSION = HEAP_PERSIST_VERSION_BASE; // legacy export (see persistVersionNow)
118
+ export function persistVersionNow(): string {
119
+ return `${HEAP_PERSIST_VERSION_BASE}-aps${atlasPageSizeNow()}`;
120
+ }
113
121
 
114
122
  /**
115
123
  * Uniforms whose drawHeader word IS the u32 value (no arena
@@ -190,7 +198,7 @@ export function compileHeapEffect(effect: Effect, fragmentOutputLayout?: Fragmen
190
198
  const contentKey = effect.id + effectHoleKey(effect) + fboLayoutKey(fragmentOutputLayout);
191
199
  const mem = _compiledHeapEffectMemCache.get(contentKey);
192
200
  if (mem !== undefined) return mem;
193
- const lsKey = persistKey(HEAP_PERSIST_VERSION, "che", contentKey);
201
+ const lsKey = persistKey(persistVersionNow(), "che", contentKey);
194
202
  const persisted = lsLoad(lsKey, isCompiledHeapEffect);
195
203
  if (persisted !== undefined) { _compiledHeapEffectMemCache.set(contentKey, persisted); return persisted; }
196
204
  const compiled = effect.compile(
@@ -30,7 +30,7 @@ import {
30
30
  } from "@aardworx/wombat.shader/ir";
31
31
  import {
32
32
  megacallSearchPrelude, atlasVaryingNames,
33
- generateAtlasBindings, generateAtlasSwitch, generateAtlasPrelude,
33
+ generateAtlasBindings, generateAtlasSwitch, generateAtlasPrelude, persistVersionNow,
34
34
  HEAP_PERSIST_VERSION, persistKey, lsLoad, lsStore,
35
35
  type BucketLayout,
36
36
  type DrawHeaderField,
@@ -987,7 +987,7 @@ export function compileHeapEffectIR(
987
987
  const contentKey = `${userEffect.id}${effectHoleKey(userEffect)}|${layout.id}|${mode}|${compileOptionsKey(compileOptions)}`;
988
988
  const mem = _heapIrMemCache.get(contentKey);
989
989
  if (mem !== undefined) return mem;
990
- const lsKey = persistKey(HEAP_PERSIST_VERSION, "ir", contentKey);
990
+ const lsKey = persistKey(persistVersionNow(), "ir", contentKey);
991
991
  const persisted = lsLoad(lsKey, isHeapEffectIR);
992
992
  if (persisted !== undefined) { _heapIrMemCache.set(contentKey, persisted); return persisted; }
993
993
 
@@ -5135,7 +5135,9 @@ export function buildHeapScene(
5135
5135
  device.queue.submit([enc.finish()]);
5136
5136
 
5137
5137
  await arenaCopy.mapAsync(GPUMapMode.READ);
5138
- if (indicesCopy !== undefined) await indicesCopy.mapAsync(GPUMapMode.READ);
5138
+ // indicesCopy may alias arenaCopy (indices live in the attr arena)
5139
+ // mapping the same buffer twice throws "already mapped".
5140
+ if (indicesCopy !== undefined && indicesCopy !== arenaCopy) await indicesCopy.mapAsync(GPUMapMode.READ);
5139
5141
  for (const dc of dcs) {
5140
5142
  await dc.drawHeap.mapAsync(GPUMapMode.READ);
5141
5143
  if (dc.drawTable !== undefined) await dc.drawTable.mapAsync(GPUMapMode.READ);
@@ -5442,7 +5444,9 @@ const KNOWN_TYPE_IDS = new Set<number>([0, 1, 2, 3]);
5442
5444
  device.queue.submit([enc.finish()]);
5443
5445
 
5444
5446
  await arenaCopy.mapAsync(GPUMapMode.READ);
5445
- if (indicesCopy !== undefined) await indicesCopy.mapAsync(GPUMapMode.READ);
5447
+ // indicesCopy may alias arenaCopy (indices live in the attr arena)
5448
+ // mapping the same buffer twice throws "already mapped".
5449
+ if (indicesCopy !== undefined && indicesCopy !== arenaCopy) await indicesCopy.mapAsync(GPUMapMode.READ);
5446
5450
  for (const dc of dcs) {
5447
5451
  await dc.drawHeap.mapAsync(GPUMapMode.READ);
5448
5452
  await dc.drawTable.mapAsync(GPUMapMode.READ);
@@ -5716,7 +5720,9 @@ const KNOWN_TYPE_IDS = new Set<number>([0, 1, 2, 3]);
5716
5720
  device.queue.submit([enc.finish()]);
5717
5721
  }
5718
5722
  await arenaCopy.mapAsync(GPUMapMode.READ);
5719
- if (indicesCopy !== undefined) await indicesCopy.mapAsync(GPUMapMode.READ);
5723
+ // indicesCopy may alias arenaCopy (indices live in the attr arena)
5724
+ // mapping the same buffer twice throws "already mapped".
5725
+ if (indicesCopy !== undefined && indicesCopy !== arenaCopy) await indicesCopy.mapAsync(GPUMapMode.READ);
5720
5726
  const arenaU32 = new Uint32Array(arenaCopy.getMappedRange());
5721
5727
  const arenaF32 = new Float32Array(arenaU32.buffer, arenaU32.byteOffset, arenaU32.length);
5722
5728
  const indicesU32 = indicesCopy !== undefined