@aardworx/wombat.rendering 0.8.0 → 0.9.0
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/dist/core/command.d.ts +7 -9
- package/dist/core/command.d.ts.map +1 -1
- package/dist/core/renderTask.d.ts +64 -1
- package/dist/core/renderTask.d.ts.map +1 -1
- package/dist/core/renderTask.js +3 -1
- package/dist/core/renderTask.js.map +1 -1
- package/dist/resources/preparedRenderObject.js +3 -3
- package/dist/resources/preparedRenderObject.js.map +1 -1
- package/dist/resources/uniformBuffer.d.ts.map +1 -1
- package/dist/resources/uniformBuffer.js +17 -0
- package/dist/resources/uniformBuffer.js.map +1 -1
- package/dist/runtime/derivedUniforms/dispatch.d.ts +105 -0
- package/dist/runtime/derivedUniforms/dispatch.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/dispatch.js +355 -0
- package/dist/runtime/derivedUniforms/dispatch.js.map +1 -0
- package/dist/runtime/derivedUniforms/index.d.ts +6 -0
- package/dist/runtime/derivedUniforms/index.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/index.js +26 -0
- package/dist/runtime/derivedUniforms/index.js.map +1 -0
- package/dist/runtime/derivedUniforms/recipes.d.ts +42 -0
- package/dist/runtime/derivedUniforms/recipes.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/recipes.js +134 -0
- package/dist/runtime/derivedUniforms/recipes.js.map +1 -0
- package/dist/runtime/derivedUniforms/sceneIntegration.d.ts +56 -0
- package/dist/runtime/derivedUniforms/sceneIntegration.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/sceneIntegration.js +171 -0
- package/dist/runtime/derivedUniforms/sceneIntegration.js.map +1 -0
- package/dist/runtime/derivedUniforms/slotId.d.ts +15 -0
- package/dist/runtime/derivedUniforms/slotId.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/slotId.js +30 -0
- package/dist/runtime/derivedUniforms/slotId.js.map +1 -0
- package/dist/runtime/derivedUniforms/slots.d.ts +49 -0
- package/dist/runtime/derivedUniforms/slots.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/slots.js +123 -0
- package/dist/runtime/derivedUniforms/slots.js.map +1 -0
- package/dist/runtime/derivedUniforms/uberKernel.wgsl.d.ts +13 -0
- package/dist/runtime/derivedUniforms/uberKernel.wgsl.d.ts.map +1 -0
- package/dist/runtime/derivedUniforms/uberKernel.wgsl.js +218 -0
- package/dist/runtime/derivedUniforms/uberKernel.wgsl.js.map +1 -0
- package/dist/runtime/flattenTree.d.ts +5 -0
- package/dist/runtime/flattenTree.d.ts.map +1 -0
- package/dist/runtime/flattenTree.js +45 -0
- package/dist/runtime/flattenTree.js.map +1 -0
- package/dist/runtime/heapAdapter.d.ts +16 -0
- package/dist/runtime/heapAdapter.d.ts.map +1 -0
- package/dist/runtime/heapAdapter.js +263 -0
- package/dist/runtime/heapAdapter.js.map +1 -0
- package/dist/runtime/heapEffect.d.ts +235 -0
- package/dist/runtime/heapEffect.d.ts.map +1 -0
- package/dist/runtime/heapEffect.js +518 -0
- package/dist/runtime/heapEffect.js.map +1 -0
- package/dist/runtime/heapEffectIR.d.ts +34 -0
- package/dist/runtime/heapEffectIR.d.ts.map +1 -0
- package/dist/runtime/heapEffectIR.js +1161 -0
- package/dist/runtime/heapEffectIR.js.map +1 -0
- package/dist/runtime/heapEligibility.d.ts +9 -0
- package/dist/runtime/heapEligibility.d.ts.map +1 -0
- package/dist/runtime/heapEligibility.js +195 -0
- package/dist/runtime/heapEligibility.js.map +1 -0
- package/dist/runtime/heapScene.d.ts +240 -31
- package/dist/runtime/heapScene.d.ts.map +1 -1
- package/dist/runtime/heapScene.js +3334 -265
- package/dist/runtime/heapScene.js.map +1 -1
- package/dist/runtime/heapShaderFamily.d.ts +132 -0
- package/dist/runtime/heapShaderFamily.d.ts.map +1 -0
- package/dist/runtime/heapShaderFamily.js +866 -0
- package/dist/runtime/heapShaderFamily.js.map +1 -0
- package/dist/runtime/hybridScene.d.ts +133 -0
- package/dist/runtime/hybridScene.d.ts.map +1 -0
- package/dist/runtime/hybridScene.js +159 -0
- package/dist/runtime/hybridScene.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +9 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/renderTask.d.ts +21 -4
- package/dist/runtime/renderTask.d.ts.map +1 -1
- package/dist/runtime/renderTask.js +127 -32
- package/dist/runtime/renderTask.js.map +1 -1
- package/dist/runtime/runtime.d.ts +33 -3
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +12 -3
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/scenePass.d.ts +28 -3
- package/dist/runtime/scenePass.d.ts.map +1 -1
- package/dist/runtime/scenePass.js +37 -4
- package/dist/runtime/scenePass.js.map +1 -1
- package/dist/runtime/textureAtlas/atlasMipGutterKernel.d.ts +35 -0
- package/dist/runtime/textureAtlas/atlasMipGutterKernel.d.ts.map +1 -0
- package/dist/runtime/textureAtlas/atlasMipGutterKernel.js +247 -0
- package/dist/runtime/textureAtlas/atlasMipGutterKernel.js.map +1 -0
- package/dist/runtime/textureAtlas/atlasPool.d.ts +240 -0
- package/dist/runtime/textureAtlas/atlasPool.d.ts.map +1 -0
- package/dist/runtime/textureAtlas/atlasPool.js +798 -0
- package/dist/runtime/textureAtlas/atlasPool.js.map +1 -0
- package/dist/runtime/textureAtlas/bvhTree2d.d.ts +33 -0
- package/dist/runtime/textureAtlas/bvhTree2d.d.ts.map +1 -0
- package/dist/runtime/textureAtlas/bvhTree2d.js +501 -0
- package/dist/runtime/textureAtlas/bvhTree2d.js.map +1 -0
- package/dist/runtime/textureAtlas/packer.d.ts +50 -0
- package/dist/runtime/textureAtlas/packer.d.ts.map +1 -0
- package/dist/runtime/textureAtlas/packer.js +390 -0
- package/dist/runtime/textureAtlas/packer.js.map +1 -0
- package/dist/window/loop.d.ts +14 -0
- package/dist/window/loop.d.ts.map +1 -1
- package/dist/window/loop.js +18 -5
- package/dist/window/loop.js.map +1 -1
- package/package.json +5 -4
- package/src/core/command.ts +9 -9
- package/src/core/renderTask.ts +55 -2
- package/src/resources/preparedRenderObject.ts +3 -3
- package/src/resources/uniformBuffer.ts +15 -0
- package/src/runtime/derivedUniforms/dispatch.ts +407 -0
- package/src/runtime/derivedUniforms/index.ts +52 -0
- package/src/runtime/derivedUniforms/recipes.ts +159 -0
- package/src/runtime/derivedUniforms/sceneIntegration.ts +239 -0
- package/src/runtime/derivedUniforms/slotId.ts +35 -0
- package/src/runtime/derivedUniforms/slots.ts +155 -0
- package/src/runtime/derivedUniforms/uberKernel.wgsl.ts +220 -0
- package/src/runtime/flattenTree.ts +46 -0
- package/src/runtime/heapAdapter.ts +314 -0
- package/src/runtime/heapEffect.ts +719 -0
- package/src/runtime/heapEffectIR.ts +1211 -0
- package/src/runtime/heapEligibility.ts +189 -0
- package/src/runtime/heapScene.ts +3981 -349
- package/src/runtime/heapShaderFamily.ts +1102 -0
- package/src/runtime/hybridScene.ts +310 -0
- package/src/runtime/index.ts +46 -0
- package/src/runtime/renderTask.ts +167 -32
- package/src/runtime/runtime.ts +37 -4
- package/src/runtime/scenePass.ts +39 -4
- package/src/runtime/textureAtlas/atlasMipGutterKernel.ts +291 -0
- package/src/runtime/textureAtlas/atlasPool.ts +991 -0
- package/src/runtime/textureAtlas/bvhTree2d.ts +530 -0
- package/src/runtime/textureAtlas/packer.ts +429 -0
- package/src/window/loop.ts +32 -6
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// heapEligibility — reactive predicate over a RenderObject deciding
|
|
2
|
+
// whether it can ride the heap-bucket fast path.
|
|
3
|
+
//
|
|
4
|
+
// Three classes of conditions:
|
|
5
|
+
// 1. STATIC HARD WEDGES — features the heap path doesn't ingest
|
|
6
|
+
// yet (instanceAttributes, storageBuffers, > 1 texture or
|
|
7
|
+
// sampler). Decided once at classifier time.
|
|
8
|
+
// 2. STATIC SOFT WEDGES — supported with limits (indexed-only,
|
|
9
|
+
// instanceCount=1, baseVertex/firstIndex/firstInstance=0).
|
|
10
|
+
// Read once from the drawCall snapshot.
|
|
11
|
+
// 3. REACTIVE — every `aval<IBuffer>` (vertex attribs + indices)
|
|
12
|
+
// must currently resolve to `kind: "host"`. Every `aval<ITexture>`
|
|
13
|
+
// must be heap-servable: `kind: "host"` (atlasable / Tier-L
|
|
14
|
+
// host upload), 2D dimension, single array layer, and within
|
|
15
|
+
// `LEGACY_MAX_DIM` on each side. Anything failing those rules
|
|
16
|
+
// escalates to the legacy ScenePass — the user is managing a
|
|
17
|
+
// backend resource (render-target, video, environment probe,
|
|
18
|
+
// streaming tile) or asking for a cubemap/array/volume that
|
|
19
|
+
// the heap shaders don't support, or a texture too large for
|
|
20
|
+
// heap-side handling to be a win. Every `aval<ISampler>` must
|
|
21
|
+
// resolve to `kind: "gpu"`. When any of these mark and flip,
|
|
22
|
+
// the result aval marks → hybrid task repartitions.
|
|
23
|
+
//
|
|
24
|
+
// Out-of-scope blockers (return false unconditionally if present):
|
|
25
|
+
// - `storageBuffers` — same.
|
|
26
|
+
// - >1 texture or sampler — multi-binding API not in v1.
|
|
27
|
+
//
|
|
28
|
+
// Per-RO instancing IS supported: `instanceAttributes` are accepted as
|
|
29
|
+
// long as every entry passes the same tight-stride / stride-0-broadcast
|
|
30
|
+
// rule used for `vertexAttributes`, and `dc.instanceCount` may be any
|
|
31
|
+
// positive value (with `firstInstance === 0`).
|
|
32
|
+
//
|
|
33
|
+
// These are conservative wedges, not permanent: as the heap path
|
|
34
|
+
// grows feature support each becomes a per-buffer eligibility
|
|
35
|
+
// question instead of a blanket "no".
|
|
36
|
+
|
|
37
|
+
import { AVal, type aval } from "@aardworx/wombat.adaptive";
|
|
38
|
+
import type { IBuffer } from "../core/buffer.js";
|
|
39
|
+
import type { BufferView } from "../core/bufferView.js";
|
|
40
|
+
import type { ITexture } from "../core/texture.js";
|
|
41
|
+
import type { ISampler } from "../core/sampler.js";
|
|
42
|
+
import type { RenderObject } from "../core/renderObject.js";
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Maximum texture extent (per side) the heap path is willing to
|
|
46
|
+
* ingest. Anything wider/taller escalates to the legacy renderer
|
|
47
|
+
* which gives each RO its own dedicated GPUTexture — that's a
|
|
48
|
+
* better fit than wasting an atlas page on a single ~4K image
|
|
49
|
+
* (and it sidesteps device-limit risk near `maxTextureDimension2D`).
|
|
50
|
+
*/
|
|
51
|
+
const LEGACY_MAX_DIM = 4096;
|
|
52
|
+
|
|
53
|
+
const isHostBuffer = (b: IBuffer): boolean => b.kind === "host";
|
|
54
|
+
// Samplers: accept both descriptor-form (`kind: "host"`) and resolved
|
|
55
|
+
// (`kind: "gpu"`). The heap atlas path uses ONE shared GPU sampler for
|
|
56
|
+
// all atlas reads — per-RO sampler state (filter modes, wrap modes)
|
|
57
|
+
// is packed into the drawHeader's formatBits and consumed by the
|
|
58
|
+
// shader, not bound as a per-RO GPUSampler. So the heap path doesn't
|
|
59
|
+
// care whether the user handed in a descriptor or a pre-resolved
|
|
60
|
+
// sampler; both are equivalent at this level.
|
|
61
|
+
const isHeapServableSampler = (_s: ISampler): boolean => true;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Heap-servability check for a single texture value. Returns `true`
|
|
65
|
+
* when the texture fits the heap path's ingest envelope:
|
|
66
|
+
* - `kind === "host"` (the user isn't managing a backend
|
|
67
|
+
* resource — those go to legacy untouched).
|
|
68
|
+
* - 2D, single array layer (heap shaders are 2D-only).
|
|
69
|
+
* - Both extents `<= LEGACY_MAX_DIM`.
|
|
70
|
+
*
|
|
71
|
+
* For `kind: "gpu"` we currently always reject (rule 1) — even a
|
|
72
|
+
* plain 2D rgba8unorm GPUTexture goes legacy, on the assumption
|
|
73
|
+
* that the user attached a `GPUTexture` for a reason (render target,
|
|
74
|
+
* external import, streamed tile) and shouldn't be silently
|
|
75
|
+
* rebadged. The dimension/layer/size checks are still implemented
|
|
76
|
+
* for `kind: "gpu"` for clarity / future use if we relax rule 1.
|
|
77
|
+
*
|
|
78
|
+
* For `kind: "host"`, by construction `RawTextureSource` and
|
|
79
|
+
* `ExternalTextureSource` are 2D single-layer — but we read
|
|
80
|
+
* `depthOrArrayLayers` from raw sources defensively (it's optional
|
|
81
|
+
* on the descriptor and could in principle be set).
|
|
82
|
+
*/
|
|
83
|
+
function isHeapServableTexture(t: ITexture): boolean {
|
|
84
|
+
if (t.kind === "gpu") return false;
|
|
85
|
+
const src = t.source;
|
|
86
|
+
if (src.kind === "raw") {
|
|
87
|
+
if ((src.depthOrArrayLayers ?? 1) !== 1) return false;
|
|
88
|
+
if (src.width > LEGACY_MAX_DIM || src.height > LEGACY_MAX_DIM) return false;
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
// external — read width/height off the source. Most types have
|
|
92
|
+
// it; HTMLVideoElement uses videoWidth/videoHeight. Sources
|
|
93
|
+
// without measurable dimensions are deferred (eligible until
|
|
94
|
+
// they resolve — heapAdapter handles undimensioned gracefully).
|
|
95
|
+
const ext = src.source as unknown;
|
|
96
|
+
let w = 0, h = 0;
|
|
97
|
+
if (typeof HTMLVideoElement !== "undefined" && ext instanceof HTMLVideoElement) {
|
|
98
|
+
w = ext.videoWidth; h = ext.videoHeight;
|
|
99
|
+
} else if (typeof ImageData !== "undefined" && ext instanceof ImageData) {
|
|
100
|
+
w = ext.width; h = ext.height;
|
|
101
|
+
} else {
|
|
102
|
+
const any = ext as { width?: number; height?: number };
|
|
103
|
+
w = any.width ?? 0;
|
|
104
|
+
h = any.height ?? 0;
|
|
105
|
+
}
|
|
106
|
+
if (w > LEGACY_MAX_DIM || h > LEGACY_MAX_DIM) return false;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function bufferAvals(ro: RenderObject): aval<IBuffer>[] {
|
|
111
|
+
const out: aval<IBuffer>[] = [];
|
|
112
|
+
ro.vertexAttributes.iter((_k, v: BufferView) => { out.push(v.buffer); });
|
|
113
|
+
if (ro.instanceAttributes !== undefined) {
|
|
114
|
+
ro.instanceAttributes.iter((_k, v: BufferView) => { out.push(v.buffer); });
|
|
115
|
+
}
|
|
116
|
+
if (ro.indices !== undefined) out.push(ro.indices.buffer);
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function textureAvals(ro: RenderObject): aval<ITexture>[] {
|
|
121
|
+
const out: aval<ITexture>[] = [];
|
|
122
|
+
ro.textures.iter((_k, av) => { out.push(av); });
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function samplerAvals(ro: RenderObject): aval<ISampler>[] {
|
|
127
|
+
const out: aval<ISampler>[] = [];
|
|
128
|
+
ro.samplers.iter((_k, av) => { out.push(av); });
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* `true` when the RO is heap-bucketable, `false` when it must fall
|
|
134
|
+
* back to the legacy per-RO path. Reactive on every contributing
|
|
135
|
+
* `aval`: rewires the partition automatically when any input flips.
|
|
136
|
+
*/
|
|
137
|
+
export function isHeapEligible(ro: RenderObject): aval<boolean> {
|
|
138
|
+
// 1. Static hard wedges.
|
|
139
|
+
if (ro.storageBuffers !== undefined && ro.storageBuffers.count > 0) {
|
|
140
|
+
return AVal.constant(false);
|
|
141
|
+
}
|
|
142
|
+
if (ro.textures.count > 1 || ro.samplers.count > 1) {
|
|
143
|
+
return AVal.constant(false);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 2. BufferView stride wedge — only tight per-vertex/per-instance
|
|
147
|
+
// layouts (and broadcasts via `singleValue` / stride 0) are
|
|
148
|
+
// ingested. The shader-side cyclic addressing (`vid % length`,
|
|
149
|
+
// `iidx % length`) makes broadcasts a degenerate length-1 case,
|
|
150
|
+
// so we don't reject them here — but interleaved strides remain
|
|
151
|
+
// unsupported. Per-instance attributes follow the same rule.
|
|
152
|
+
let strideBlocked = false;
|
|
153
|
+
const checkStride = (v: BufferView): void => {
|
|
154
|
+
const stride = v.stride ?? v.elementType.byteSize;
|
|
155
|
+
const isBroadcast = v.singleValue !== undefined || stride === 0;
|
|
156
|
+
if (!isBroadcast && stride !== v.elementType.byteSize) strideBlocked = true;
|
|
157
|
+
};
|
|
158
|
+
ro.vertexAttributes.iter((_k, v: BufferView) => checkStride(v));
|
|
159
|
+
if (ro.instanceAttributes !== undefined) {
|
|
160
|
+
ro.instanceAttributes.iter((_k, v: BufferView) => checkStride(v));
|
|
161
|
+
}
|
|
162
|
+
if (strideBlocked) return AVal.constant(false);
|
|
163
|
+
|
|
164
|
+
// 3. Index-format wedge — heap stores indices as u32.
|
|
165
|
+
if (ro.indices !== undefined && ro.indices.elementType.indexFormat !== "uint32") {
|
|
166
|
+
return AVal.constant(false);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const buffers = bufferAvals(ro);
|
|
170
|
+
const textures = textureAvals(ro);
|
|
171
|
+
const samplers = samplerAvals(ro);
|
|
172
|
+
|
|
173
|
+
// Reactive AND-fold over all participating avals. We also subscribe
|
|
174
|
+
// to drawCall (instanceCount/baseVertex/firstIndex/firstInstance
|
|
175
|
+
// can flip; if they violate heap constraints the RO routes to the
|
|
176
|
+
// legacy path that frame).
|
|
177
|
+
return AVal.custom(token => {
|
|
178
|
+
for (const av of buffers) if (!isHostBuffer(av.getValue(token))) return false;
|
|
179
|
+
for (const av of textures) if (!isHeapServableTexture(av.getValue(token))) return false;
|
|
180
|
+
for (const av of samplers) if (!isHeapServableSampler(av.getValue(token))) return false;
|
|
181
|
+
const dc = ro.drawCall.getValue(token);
|
|
182
|
+
if (dc.kind !== "indexed") return false;
|
|
183
|
+
if (dc.instanceCount < 1) return false;
|
|
184
|
+
if (dc.baseVertex !== 0) return false;
|
|
185
|
+
if (dc.firstIndex !== 0) return false;
|
|
186
|
+
if (dc.firstInstance !== 0) return false;
|
|
187
|
+
return true;
|
|
188
|
+
});
|
|
189
|
+
}
|