@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,247 @@
|
|
|
1
|
+
// Compute kernel that builds an atlas sub-rect's mip pyramid AND fills
|
|
2
|
+
// both gutter rings entirely on GPU, using only core WebGPU 1.0
|
|
3
|
+
// features (no `readonly-and-readwrite-storage-textures`).
|
|
4
|
+
//
|
|
5
|
+
// Architecture
|
|
6
|
+
// ============
|
|
7
|
+
// The whole operation runs inside a per-acquire **scratch buffer**
|
|
8
|
+
// laid out exactly like the destination region of the atlas page
|
|
9
|
+
// (bounding rect of the Iliffe pyramid + gutter, in atlas-pixel
|
|
10
|
+
// coordinates relative to the sub-rect origin). Each pixel is one
|
|
11
|
+
// packed `u32` (rgba8). Rows are padded to 256-byte alignment so the
|
|
12
|
+
// final `copyBufferToTexture` is straight-through.
|
|
13
|
+
//
|
|
14
|
+
// Per acquire:
|
|
15
|
+
// 1. CPU writes the raw source pixels into the scratch buffer at
|
|
16
|
+
// the mip-0 interior offset (via `mappedAtCreation`). One JS
|
|
17
|
+
// loop, no upload validation pitfalls.
|
|
18
|
+
// 2. For each mip k > 0: dispatch the `interior` kernel, which
|
|
19
|
+
// reads 2×2 from mip-(k-1) in the buffer and writes the average
|
|
20
|
+
// to mip-k interior, all in-buffer. Each mip lives in its own
|
|
21
|
+
// compute pass — the pass boundary acts as a barrier so
|
|
22
|
+
// mip-(k-1) is fully written before mip-k reads from it.
|
|
23
|
+
// 3. For each mip k: dispatch the `gutter` kernel, which copies
|
|
24
|
+
// the appropriate clamp / wrap interior cell into each gutter
|
|
25
|
+
// cell. Also one compute pass per mip.
|
|
26
|
+
// 4. `copyBufferToTexture` writes the full scratch buffer to the
|
|
27
|
+
// atlas page at the sub-rect origin.
|
|
28
|
+
//
|
|
29
|
+
// The kernel reads and writes ONE storage buffer through a
|
|
30
|
+
// `read_write` binding. WebGPU validates a single binding (even with
|
|
31
|
+
// read_write access) as one usage entry per resource — no hazard.
|
|
32
|
+
//
|
|
33
|
+
// No device features required. No same-texture binding pitfalls. The
|
|
34
|
+
// scratch buffer is per-acquire and freed after submission completes.
|
|
35
|
+
const WGSL = /* wgsl */ `
|
|
36
|
+
struct Params {
|
|
37
|
+
buf_stride_u32: u32,
|
|
38
|
+
_pad0: u32,
|
|
39
|
+
src_origin_in_buf: vec2<u32>,
|
|
40
|
+
src_size: vec2<u32>,
|
|
41
|
+
dst_origin_in_buf: vec2<u32>,
|
|
42
|
+
dst_size: vec2<u32>,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@group(0) @binding(0) var<storage, read_write> buf: array<u32>;
|
|
46
|
+
@group(0) @binding(1) var<uniform> P: Params;
|
|
47
|
+
|
|
48
|
+
fn loadRgba(x: u32, y: u32) -> vec4<f32> {
|
|
49
|
+
let idx = y * P.buf_stride_u32 + x;
|
|
50
|
+
return unpack4x8unorm(buf[idx]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fn storeRgba(x: u32, y: u32, v: vec4<f32>) {
|
|
54
|
+
let idx = y * P.buf_stride_u32 + x;
|
|
55
|
+
buf[idx] = pack4x8unorm(v);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@compute @workgroup_size(8, 8, 1)
|
|
59
|
+
fn interior(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
60
|
+
if (gid.x >= P.dst_size.x || gid.y >= P.dst_size.y) { return; }
|
|
61
|
+
let sx0 = P.src_origin_in_buf.x + gid.x * 2u;
|
|
62
|
+
let sy0 = P.src_origin_in_buf.y + gid.y * 2u;
|
|
63
|
+
let sxMax = P.src_origin_in_buf.x + P.src_size.x - 1u;
|
|
64
|
+
let syMax = P.src_origin_in_buf.y + P.src_size.y - 1u;
|
|
65
|
+
let sx1 = min(sx0 + 1u, sxMax);
|
|
66
|
+
let sy1 = min(sy0 + 1u, syMax);
|
|
67
|
+
let a = loadRgba(sx0, sy0);
|
|
68
|
+
let b = loadRgba(sx1, sy0);
|
|
69
|
+
let c = loadRgba(sx0, sy1);
|
|
70
|
+
let d = loadRgba(sx1, sy1);
|
|
71
|
+
let avg = (a + b + c + d) * 0.25;
|
|
72
|
+
storeRgba(P.dst_origin_in_buf.x + gid.x, P.dst_origin_in_buf.y + gid.y, avg);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@compute @workgroup_size(8, 8, 1)
|
|
76
|
+
fn gutter(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
77
|
+
let totW = P.dst_size.x + 4u;
|
|
78
|
+
let totH = P.dst_size.y + 4u;
|
|
79
|
+
if (gid.x >= totW || gid.y >= totH) { return; }
|
|
80
|
+
let dx = i32(gid.x) - 2;
|
|
81
|
+
let dy = i32(gid.y) - 2;
|
|
82
|
+
let dw = i32(P.dst_size.x);
|
|
83
|
+
let dh = i32(P.dst_size.y);
|
|
84
|
+
if (dx >= 0 && dx < dw && dy >= 0 && dy < dh) { return; }
|
|
85
|
+
var sx: i32;
|
|
86
|
+
var sy: i32;
|
|
87
|
+
if (dx == -2) { sx = dw - 1; }
|
|
88
|
+
else if (dx == -1) { sx = 0; }
|
|
89
|
+
else if (dx == dw) { sx = dw - 1; }
|
|
90
|
+
else if (dx == dw + 1) { sx = 0; }
|
|
91
|
+
else { sx = dx; }
|
|
92
|
+
if (dy == -2) { sy = dh - 1; }
|
|
93
|
+
else if (dy == -1) { sy = 0; }
|
|
94
|
+
else if (dy == dh) { sy = dh - 1; }
|
|
95
|
+
else if (dy == dh + 1) { sy = 0; }
|
|
96
|
+
else { sy = dy; }
|
|
97
|
+
let v = loadRgba(u32(i32(P.dst_origin_in_buf.x) + sx),
|
|
98
|
+
u32(i32(P.dst_origin_in_buf.y) + sy));
|
|
99
|
+
storeRgba(u32(i32(P.dst_origin_in_buf.x) + dx),
|
|
100
|
+
u32(i32(P.dst_origin_in_buf.y) + dy),
|
|
101
|
+
v);
|
|
102
|
+
}
|
|
103
|
+
`;
|
|
104
|
+
const caches = new WeakMap();
|
|
105
|
+
function getKernel(device) {
|
|
106
|
+
const cached = caches.get(device);
|
|
107
|
+
if (cached !== undefined)
|
|
108
|
+
return cached;
|
|
109
|
+
const module = device.createShaderModule({ code: WGSL, label: "atlas/mipGutterKernel" });
|
|
110
|
+
const bindGroupLayout = device.createBindGroupLayout({
|
|
111
|
+
label: "atlas/mipGutterKernel/bgl",
|
|
112
|
+
entries: [
|
|
113
|
+
{ binding: 0, visibility: 0x4 /* COMPUTE */, buffer: { type: "storage" } },
|
|
114
|
+
{ binding: 1, visibility: 0x4 /* COMPUTE */, buffer: { type: "uniform" } },
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
const layout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });
|
|
118
|
+
const interiorPipeline = device.createComputePipeline({
|
|
119
|
+
layout, compute: { module, entryPoint: "interior" },
|
|
120
|
+
label: "atlas/mipGutterKernel/interior",
|
|
121
|
+
});
|
|
122
|
+
const gutterPipeline = device.createComputePipeline({
|
|
123
|
+
layout, compute: { module, entryPoint: "gutter" },
|
|
124
|
+
label: "atlas/mipGutterKernel/gutter",
|
|
125
|
+
});
|
|
126
|
+
const entry = { bindGroupLayout, interiorPipeline, gutterPipeline };
|
|
127
|
+
caches.set(device, entry);
|
|
128
|
+
return entry;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build the mip pyramid + gutters on GPU and upload the result to a
|
|
132
|
+
* sub-rect of `page`. `srcPixels` is the raw RGBA8 source for mip 0
|
|
133
|
+
* (`srcW × srcH` pixels). The kernel:
|
|
134
|
+
* - Allocates a per-acquire scratch buffer.
|
|
135
|
+
* - Initialises the buffer at creation with mip-0 source pixels at
|
|
136
|
+
* the mip-0 interior offset.
|
|
137
|
+
* - Dispatches per-mip interior + gutter compute passes.
|
|
138
|
+
* - copyBufferToTexture into the page at (subRectX, subRectY).
|
|
139
|
+
*
|
|
140
|
+
* Caller must ensure the page has COPY_DST usage (atlas pages
|
|
141
|
+
* always do).
|
|
142
|
+
*
|
|
143
|
+
* Buffer is destroyed once submitted work completes (fire-and-forget
|
|
144
|
+
* via `onSubmittedWorkDone`).
|
|
145
|
+
*/
|
|
146
|
+
export function buildMipsAndGutterOnGpu(device, page, subRectX, subRectY, boundsW, boundsH, srcPixels, srcW, srcH, mips) {
|
|
147
|
+
if (mips.length === 0)
|
|
148
|
+
return;
|
|
149
|
+
const { bindGroupLayout, interiorPipeline, gutterPipeline } = getKernel(device);
|
|
150
|
+
// Buffer layout: rows padded to 256 bytes for the final
|
|
151
|
+
// copyBufferToTexture. Stride in u32: 256 / 4 = 64 minimum, or
|
|
152
|
+
// ceil(boundsW * 4 / 256) * 256 / 4.
|
|
153
|
+
const rowBytes = Math.max(256, Math.ceil(boundsW * 4 / 256) * 256);
|
|
154
|
+
const bufStrideU32 = rowBytes / 4;
|
|
155
|
+
const bufSize = rowBytes * boundsH;
|
|
156
|
+
const scratch = device.createBuffer({
|
|
157
|
+
label: `atlas/mipGutter/scratch(${boundsW}x${boundsH})`,
|
|
158
|
+
size: bufSize,
|
|
159
|
+
usage: 0x80 /* STORAGE */ | 0x04 /* COPY_SRC */ | 0x08 /* COPY_DST */,
|
|
160
|
+
mappedAtCreation: true,
|
|
161
|
+
});
|
|
162
|
+
// CPU init: write mip-0 source pixels at the mip-0 interior offset
|
|
163
|
+
// inside the buffer. mips[0].origin is the interior offset.
|
|
164
|
+
const mip0 = mips[0];
|
|
165
|
+
{
|
|
166
|
+
const mapped = new Uint32Array(scratch.getMappedRange());
|
|
167
|
+
for (let y = 0; y < srcH; y++) {
|
|
168
|
+
for (let x = 0; x < srcW; x++) {
|
|
169
|
+
const si = (y * srcW + x) * 4;
|
|
170
|
+
const r = srcPixels[si];
|
|
171
|
+
const g = srcPixels[si + 1];
|
|
172
|
+
const b = srcPixels[si + 2];
|
|
173
|
+
const a = srcPixels[si + 3];
|
|
174
|
+
// little-endian rgba8: byte0=r, byte1=g, byte2=b, byte3=a.
|
|
175
|
+
const packed = (a << 24) | (b << 16) | (g << 8) | r;
|
|
176
|
+
mapped[(mip0.origin.y + y) * bufStrideU32 + (mip0.origin.x + x)] = packed >>> 0;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
scratch.unmap();
|
|
181
|
+
const enc = device.createCommandEncoder({ label: "atlas/mipGutterKernel" });
|
|
182
|
+
const ubos = [];
|
|
183
|
+
const makeUbo = (srcO, srcS, dstO, dstS) => {
|
|
184
|
+
const buf = device.createBuffer({
|
|
185
|
+
size: 48, // 12 u32, padded
|
|
186
|
+
usage: 0x40 /* UNIFORM */ | 0x08 /* COPY_DST */,
|
|
187
|
+
label: "atlas/mipGutter/params",
|
|
188
|
+
});
|
|
189
|
+
const u = new Uint32Array(12);
|
|
190
|
+
u[0] = bufStrideU32;
|
|
191
|
+
u[1] = 0;
|
|
192
|
+
u[2] = srcO.x;
|
|
193
|
+
u[3] = srcO.y;
|
|
194
|
+
u[4] = srcS.w;
|
|
195
|
+
u[5] = srcS.h;
|
|
196
|
+
u[6] = dstO.x;
|
|
197
|
+
u[7] = dstO.y;
|
|
198
|
+
u[8] = dstS.w;
|
|
199
|
+
u[9] = dstS.h;
|
|
200
|
+
device.queue.writeBuffer(buf, 0, u);
|
|
201
|
+
ubos.push(buf);
|
|
202
|
+
return buf;
|
|
203
|
+
};
|
|
204
|
+
const makeBg = (ubo) => device.createBindGroup({
|
|
205
|
+
layout: bindGroupLayout,
|
|
206
|
+
entries: [
|
|
207
|
+
{ binding: 0, resource: { buffer: scratch } },
|
|
208
|
+
{ binding: 1, resource: { buffer: ubo } },
|
|
209
|
+
],
|
|
210
|
+
});
|
|
211
|
+
// Interior passes: one compute pass per mip > 0 (pass boundary
|
|
212
|
+
// gives us the barrier ensuring mip-(k-1) is fully written before
|
|
213
|
+
// mip-k reads it).
|
|
214
|
+
for (let k = 1; k < mips.length; k++) {
|
|
215
|
+
const src = mips[k - 1];
|
|
216
|
+
const dst = mips[k];
|
|
217
|
+
const ubo = makeUbo(src.origin, src.size, dst.origin, dst.size);
|
|
218
|
+
const pass = enc.beginComputePass({ label: `atlas/mipGutter/interior/${k}` });
|
|
219
|
+
pass.setPipeline(interiorPipeline);
|
|
220
|
+
pass.setBindGroup(0, makeBg(ubo));
|
|
221
|
+
pass.dispatchWorkgroups(Math.ceil(dst.size.w / 8), Math.ceil(dst.size.h / 8), 1);
|
|
222
|
+
pass.end();
|
|
223
|
+
}
|
|
224
|
+
// Gutter passes: one per mip (each pass reads mip-k interior,
|
|
225
|
+
// which was either CPU-uploaded for k=0 or written by the interior
|
|
226
|
+
// pass for k>0).
|
|
227
|
+
for (let k = 0; k < mips.length; k++) {
|
|
228
|
+
const dst = mips[k];
|
|
229
|
+
const ubo = makeUbo(dst.origin, dst.size, dst.origin, dst.size);
|
|
230
|
+
const pass = enc.beginComputePass({ label: `atlas/mipGutter/gutter/${k}` });
|
|
231
|
+
pass.setPipeline(gutterPipeline);
|
|
232
|
+
pass.setBindGroup(0, makeBg(ubo));
|
|
233
|
+
pass.dispatchWorkgroups(Math.ceil((dst.size.w + 4) / 8), Math.ceil((dst.size.h + 4) / 8), 1);
|
|
234
|
+
pass.end();
|
|
235
|
+
}
|
|
236
|
+
// Final upload: buffer → page.
|
|
237
|
+
enc.copyBufferToTexture({ buffer: scratch, bytesPerRow: rowBytes, rowsPerImage: boundsH }, { texture: page, origin: { x: subRectX, y: subRectY, z: 0 } }, { width: boundsW, height: boundsH, depthOrArrayLayers: 1 });
|
|
238
|
+
device.queue.submit([enc.finish()]);
|
|
239
|
+
// Lifetime: destroy scratch + per-pass UBOs once submitted work is
|
|
240
|
+
// done. The submit holds a ref until completion.
|
|
241
|
+
void device.queue.onSubmittedWorkDone().then(() => {
|
|
242
|
+
scratch.destroy();
|
|
243
|
+
for (const b of ubos)
|
|
244
|
+
b.destroy();
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=atlasMipGutterKernel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlasMipGutterKernel.js","sourceRoot":"","sources":["../../../src/runtime/textureAtlas/atlasMipGutterKernel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { V2f } from "@aardworx/wombat.base";
|
|
2
|
+
import type { aval } from "@aardworx/wombat.adaptive";
|
|
3
|
+
import type { ITexture, HostTextureSource } from "../../core/texture.js";
|
|
4
|
+
import { TexturePacking } from "./packer.js";
|
|
5
|
+
export declare const ATLAS_PAGE_SIZE = 4096;
|
|
6
|
+
/** Tier S/M source-side dimension cap. */
|
|
7
|
+
export declare const ATLAS_MAX_DIM = 1024;
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of independent pages allowed per format. The shader's
|
|
10
|
+
* `switch pageRef` runs an N-way ladder; the BGL declares N consecutive
|
|
11
|
+
* texture slots per format. Allocations beyond this throw.
|
|
12
|
+
*/
|
|
13
|
+
export declare const ATLAS_MAX_PAGES_PER_FORMAT = 8;
|
|
14
|
+
export type AtlasPageFormat = "rgba8unorm" | "rgba8unorm-srgb";
|
|
15
|
+
export declare const ATLAS_PAGE_FORMATS: readonly AtlasPageFormat[];
|
|
16
|
+
/** Format index used in the drawHeader: 0 = linear, 1 = srgb. */
|
|
17
|
+
export declare const atlasFormatIndex: (f: AtlasPageFormat) => number;
|
|
18
|
+
export interface AtlasPage {
|
|
19
|
+
readonly format: AtlasPageFormat;
|
|
20
|
+
/**
|
|
21
|
+
* The page's own independent `GPUTexture` (dimension: "2d", single
|
|
22
|
+
* 4096² image). Stable for the page's lifetime — never reallocated.
|
|
23
|
+
*/
|
|
24
|
+
readonly texture: GPUTexture;
|
|
25
|
+
/** Immutable packer state — `tryAdd`/`remove` produce new instances. */
|
|
26
|
+
packing: TexturePacking<number>;
|
|
27
|
+
/**
|
|
28
|
+
* Page slot index in the format's binding sequence (0..N-1). Same
|
|
29
|
+
* value flows into the drawHeader `pageRef` field; the shader's
|
|
30
|
+
* `switch pageRef` selects the matching `atlasLinear<i>` /
|
|
31
|
+
* `atlasSrgb<i>` declaration.
|
|
32
|
+
*/
|
|
33
|
+
readonly pageId: number;
|
|
34
|
+
}
|
|
35
|
+
export interface AtlasAcquisition {
|
|
36
|
+
/** Page slot index within the format's binding sequence (0..N-1). */
|
|
37
|
+
readonly pageId: number;
|
|
38
|
+
/** Top-left of mip 0's interior in the atlas, in atlas pixels. */
|
|
39
|
+
readonly origin: V2f;
|
|
40
|
+
/** Size of mip 0's interior in the atlas, in atlas pixels. */
|
|
41
|
+
readonly size: V2f;
|
|
42
|
+
/** Number of mip levels stored for this acquisition (1 = no pyramid). */
|
|
43
|
+
readonly numMips: number;
|
|
44
|
+
/** Stable refcount handle: pass back to `release`. */
|
|
45
|
+
readonly ref: number;
|
|
46
|
+
/** The page's GPUTexture (so the caller can pin it in the bind group). */
|
|
47
|
+
readonly page: AtlasPage;
|
|
48
|
+
}
|
|
49
|
+
/** Source descriptor accepted by `acquire` (small enough not to need a full ITexture). */
|
|
50
|
+
export interface AtlasSource {
|
|
51
|
+
readonly width: number;
|
|
52
|
+
readonly height: number;
|
|
53
|
+
/**
|
|
54
|
+
* The host source for upload. The pool calls
|
|
55
|
+
* `device.queue.copyExternalImageToTexture` (external) or
|
|
56
|
+
* `writeTexture` (raw) into the page region the first time the
|
|
57
|
+
* sub-rect is allocated. For mipped uploads the pool downscales
|
|
58
|
+
* via canvas-2d and uploads each level into the pyramid sub-region.
|
|
59
|
+
*/
|
|
60
|
+
readonly host?: HostTextureSource;
|
|
61
|
+
}
|
|
62
|
+
export interface AtlasAcquireOptions {
|
|
63
|
+
readonly source?: AtlasSource;
|
|
64
|
+
/** When true, reserve a 1.5W×H rect and store an embedded mip pyramid. */
|
|
65
|
+
readonly wantsMips?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Number of mip levels to store. Defaults to
|
|
68
|
+
* `floor(log2(max(w,h))) + 1` (full chain to 1×1).
|
|
69
|
+
*/
|
|
70
|
+
readonly numMips?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Default mip count for a `w×h` source: full chain down to 1×1.
|
|
74
|
+
*/
|
|
75
|
+
export declare const defaultMipCount: (w: number, h: number) => number;
|
|
76
|
+
/**
|
|
77
|
+
* Mip-k pixel size given mip-0 size `(w,h)`. Halves each level and
|
|
78
|
+
* floors at 1×1.
|
|
79
|
+
*/
|
|
80
|
+
export declare const mipPixelSize: (w: number, h: number, k: number) => {
|
|
81
|
+
w: number;
|
|
82
|
+
h: number;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Mip-k interior offset from mip-0 interior, both inside the embedded
|
|
86
|
+
* Iliffe pyramid. Mip 0 is at (0,0). Mips 1..N stack vertically in
|
|
87
|
+
* the column at x = W + 4 (mip-0 width + 2 px right gutter of mip-0
|
|
88
|
+
* + 2 px left gutter of the mip column). Each mip k>=1 sits below
|
|
89
|
+
* mip k-1 with 4 px of vertical gutter between them (2 px bottom of
|
|
90
|
+
* mip k-1 + 2 px top of mip k):
|
|
91
|
+
* y_k = sum_{j=1..k-1} (max(1, H >> j) + 4).
|
|
92
|
+
* Caller writes at `(uploadOrigin + mipOffsetInPyramid(w, h, k))`
|
|
93
|
+
* where uploadOrigin is mip-0's interior pixel position.
|
|
94
|
+
*/
|
|
95
|
+
export declare const mipOffsetInPyramid: (w: number, h: number, k: number) => {
|
|
96
|
+
x: number;
|
|
97
|
+
y: number;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Aval-identity keyed pool over the per-format page sets. Multiple
|
|
101
|
+
* acquisitions of the same `aval<ITexture>` share one sub-rect; the
|
|
102
|
+
* refcount drives release.
|
|
103
|
+
*/
|
|
104
|
+
export declare class AtlasPool {
|
|
105
|
+
private readonly device;
|
|
106
|
+
private readonly pagesByFormat;
|
|
107
|
+
private readonly pageAddedListeners;
|
|
108
|
+
private readonly entriesByAval;
|
|
109
|
+
private readonly entriesByRef;
|
|
110
|
+
/**
|
|
111
|
+
* §5b value-equality dedup map. Constant avals (`isConstant ===
|
|
112
|
+
* true`) wrapping the same inner GPUTexture (kind:"gpu") or
|
|
113
|
+
* HostTextureSource (kind:"host") collapse to one sub-rect.
|
|
114
|
+
* Reactive avals fall through to identity-only since their
|
|
115
|
+
* content can change.
|
|
116
|
+
*/
|
|
117
|
+
private readonly entriesByValueKey;
|
|
118
|
+
private nextRef;
|
|
119
|
+
private innerKeyOf;
|
|
120
|
+
constructor(device: GPUDevice);
|
|
121
|
+
/** All currently allocated pages for a given format. */
|
|
122
|
+
pagesFor(format: AtlasPageFormat): readonly AtlasPage[];
|
|
123
|
+
/**
|
|
124
|
+
* Subscribe to page-allocation events. Fires after a fresh
|
|
125
|
+
* `AtlasPage` is appended to the format's page list (its `pageId`
|
|
126
|
+
* is the slot the bind group should now wire up).
|
|
127
|
+
*/
|
|
128
|
+
onPageAdded(format: AtlasPageFormat, cb: (pageId: number) => void): {
|
|
129
|
+
dispose(): void;
|
|
130
|
+
};
|
|
131
|
+
/** True for pages we can drive via the compute mip+gutter kernel.
|
|
132
|
+
* The kernel is buffer-based: it allocates a scratch storage
|
|
133
|
+
* buffer matching the sub-rect's bounding box, runs all mip
|
|
134
|
+
* downscale + gutter fill in compute passes over the buffer, then
|
|
135
|
+
* one `copyBufferToTexture` uploads the whole region to the page.
|
|
136
|
+
* No texture storage bindings are needed and no device features
|
|
137
|
+
* are required — works in core WebGPU 1.0. The only constraint is
|
|
138
|
+
* that JS-side pixel extraction succeeds, which falls back to the
|
|
139
|
+
* CPU path on headless platforms without canvas.
|
|
140
|
+
*
|
|
141
|
+
* Disabled in node mock-GPU mode (which lacks queue.onSubmittedWorkDone). */
|
|
142
|
+
private canUseGpuKernel;
|
|
143
|
+
private allocatePage;
|
|
144
|
+
/**
|
|
145
|
+
* Tier-S eligibility: dimension threshold + supported format. If
|
|
146
|
+
* this returns null, the caller should route the texture down the
|
|
147
|
+
* Tier L (standalone) path.
|
|
148
|
+
*/
|
|
149
|
+
static eligibleFormat(format: GPUTextureFormat): AtlasPageFormat | null;
|
|
150
|
+
static eligibleSize(width: number, height: number): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Acquire (or share) a sub-rect. The returned `AtlasAcquisition`
|
|
153
|
+
* gives the page slot index plus the mip-0 `origin`/`size` (in
|
|
154
|
+
* normalized atlas coords) and `numMips`. If the texture is already
|
|
155
|
+
* known (same aval), refcount bumps and we return the existing
|
|
156
|
+
* placement.
|
|
157
|
+
*/
|
|
158
|
+
acquire(format: AtlasPageFormat, sourceAval: aval<ITexture>, width: number, height: number, opts?: AtlasAcquireOptions): AtlasAcquisition;
|
|
159
|
+
/**
|
|
160
|
+
* Look up the existing acquisition for a source aval, or `undefined`
|
|
161
|
+
* if the aval is not currently held in the pool. Mirrors
|
|
162
|
+
* `UniformPool.entry` — used by the heap path's reactivity loop to
|
|
163
|
+
* detect "this aval has live refs and just marked".
|
|
164
|
+
*/
|
|
165
|
+
entry(sourceAval: aval<ITexture>): AtlasAcquisition | undefined;
|
|
166
|
+
/**
|
|
167
|
+
* Re-pack an aval's atlas placement against a new ITexture value.
|
|
168
|
+
* Mirrors `UniformPool.repack(av, newValue)` — used when an atlas-
|
|
169
|
+
* routed `aval<ITexture>` source swaps. Frees the old sub-rect (and
|
|
170
|
+
* the page slot in the packer) and acquires a fresh one for the new
|
|
171
|
+
* texture; the returned `AtlasAcquisition` carries the (potentially
|
|
172
|
+
* different) `pageId`/`origin`/`size`/`numMips`/`ref`. Refcount is
|
|
173
|
+
* preserved across the swap so multi-RO sharing keeps working.
|
|
174
|
+
*
|
|
175
|
+
* Throws if the new texture isn't Tier-S eligible (different format
|
|
176
|
+
* outside rgba8unorm/srgb, or larger than the cap). Callers should
|
|
177
|
+
* rely on the heap eligibility classifier, but this is a safety net.
|
|
178
|
+
*/
|
|
179
|
+
repack(sourceAval: aval<ITexture>, newTexture: ITexture, opts?: AtlasAcquireOptions): AtlasAcquisition;
|
|
180
|
+
/** Decrement the refcount; on zero, free the sub-rect. */
|
|
181
|
+
release(ref: number): void;
|
|
182
|
+
/** Destroy every page texture. The pool becomes unusable. */
|
|
183
|
+
dispose(): void;
|
|
184
|
+
private finalize;
|
|
185
|
+
private upload;
|
|
186
|
+
/**
|
|
187
|
+
* Build a (w+4)×(h+4) extended pixel buffer from `src` (w×h, RGBA8)
|
|
188
|
+
* with the 2-px gutter pre-filled:
|
|
189
|
+
* - Inner ring (1 px) = clamp-replicate (edge texel).
|
|
190
|
+
* - Outer ring (1 px) = wrap (opposite-edge texel).
|
|
191
|
+
* The shader needs both: clamp-replicate absorbs FP-edge bleed for
|
|
192
|
+
* any wrap mode; the outer wrap ring is sampled by the repeat
|
|
193
|
+
* seam-shift ±1 path. By pre-baking these CPU-side we get a single
|
|
194
|
+
* writeTexture call per slot — much faster than per-cell GPU
|
|
195
|
+
* copies, and dodges Dawn's overly-strict same-texture copy
|
|
196
|
+
* validation.
|
|
197
|
+
*
|
|
198
|
+
* Layout matches the shader expectations and `placeWithGutter` in
|
|
199
|
+
* the conformance test. Corner cells are populated by independent
|
|
200
|
+
* per-axis interpretation (e.g. outer-X × outer-Y = diagonal wrap;
|
|
201
|
+
* inner-X × outer-Y = clamp-X × wrap-Y).
|
|
202
|
+
*/
|
|
203
|
+
private static buildExtendedWithGutter;
|
|
204
|
+
/**
|
|
205
|
+
* Extract raw RGBA8 pixels from `host` at logical size (w, h).
|
|
206
|
+
* Falls back to a canvas draw + getImageData for external sources;
|
|
207
|
+
* raw sources are copied straight. Returns null when the runtime
|
|
208
|
+
* can't synthesise pixels (headless without canvas, etc.).
|
|
209
|
+
*/
|
|
210
|
+
private extractPixels;
|
|
211
|
+
/**
|
|
212
|
+
* Upload a mip level INCLUDING its 2-px gutter ring. Writes a
|
|
213
|
+
* single (w+4)×(h+4) block to (x-2, y-2) — caller passes the
|
|
214
|
+
* interior position (x, y), this routine offsets by -2/-2 to
|
|
215
|
+
* cover the gutter. Returns false if pixel extraction failed (very
|
|
216
|
+
* rare; only on platforms without canvas support).
|
|
217
|
+
*/
|
|
218
|
+
private uploadLevelWithGutter;
|
|
219
|
+
/** Unused stub kept for compatibility — see uploadLevelWithGutter. */
|
|
220
|
+
private fillClampGutter;
|
|
221
|
+
private uploadLevel;
|
|
222
|
+
/**
|
|
223
|
+
* Upload `src` (RGBA8, w×h) to `texture` at (x, y) via `writeTexture`.
|
|
224
|
+
* `writeTexture` requires `bytesPerRow` to be a multiple of 256 when
|
|
225
|
+
* the source has more than one row, so non-256-aligned widths need
|
|
226
|
+
* a padded buffer.
|
|
227
|
+
*/
|
|
228
|
+
private writeRgba8Padded;
|
|
229
|
+
/**
|
|
230
|
+
* Produce a `CanvasImageSource` we can feed to `drawImage` for
|
|
231
|
+
* downscaling. Returns null when the runtime can't synthesise one
|
|
232
|
+
* (no DOM / OffscreenCanvas / ImageBitmap support).
|
|
233
|
+
*/
|
|
234
|
+
private toDrawable;
|
|
235
|
+
private imageDataToCanvas;
|
|
236
|
+
private makeMipCanvas;
|
|
237
|
+
private makeCanvas;
|
|
238
|
+
private makeResult;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=atlasPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlasPool.d.ts","sourceRoot":"","sources":["../../../src/runtime/textureAtlas/atlasPool.ts"],"names":[],"mappings":"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"}
|