rayzee 8.6.0 → 8.7.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/README.md +1 -53
- package/dist/{DLSSNeural-BhBCBgKf.js → NeuralRetouch-CYOJ21Wn.js} +31 -31
- package/dist/{DLSSSuperRes-BCA7F_k5.js → NeuralSuperRes-Dc6jRYke.js} +23 -23
- package/dist/{ToneMapGPU-BzcLheoR.js → ToneMapGPU-BVE852iN.js} +2 -2
- package/dist/rayzee.es.js +3552 -2990
- package/dist/rayzee.umd.js +17 -17
- package/package.json +1 -1
- package/src/AssetConfig.js +6 -5
- package/src/Passes/OIDNDenoiser.js +13 -5
- package/src/PathTracerApp.js +97 -2
- package/src/Processor/AssetLoader.js +14 -8
- package/src/Processor/EmissiveTriangleBuilder.js +70 -0
- package/src/Processor/PBRT/PBRTAnimation.js +646 -0
- package/src/Processor/PBRT/PBRTParser.js +179 -52
- package/src/Processor/PBRT/PBRTSceneBuilder.js +181 -25
- package/src/Processor/PBRT/index.js +73 -14
- package/src/Processor/SceneProcessor.js +22 -0
- package/src/Stages/PathTracerStage.js +16 -1
- package/src/index.js +3 -3
- package/src/managers/AnimationManager.js +202 -8
- package/src/managers/DenoisingManager.js +60 -44
- package/src/{dlss/DLSSNeural.js → neural/NeuralRetouch.js} +42 -41
- package/src/{dlss/DLSSSuperRes.js → neural/NeuralSuperRes.js} +27 -26
package/README.md
CHANGED
|
@@ -288,11 +288,6 @@ configureAssets({
|
|
|
288
288
|
oidnWeightsBaseUrl: '/oidn-tzas/',
|
|
289
289
|
upscalerModelBaseUrl: '/upscaler-onnx/',
|
|
290
290
|
|
|
291
|
-
// DLSS. The runtime is a plain script the host must serve — it installs
|
|
292
|
-
// `globalThis.DLSSRuntime` as a side effect and cannot be imported.
|
|
293
|
-
dlssRuntimeUrl: '/dlss/dlss-runtime.js',
|
|
294
|
-
dlssAssetBaseUrl: '/dlss/',
|
|
295
|
-
|
|
296
291
|
// OpenColorIO runtime (~6 MB of WebAssembly) — the engine never names the package, so a host
|
|
297
292
|
// that loads colour configs supplies it, bundled or served. Unset, colour management stays inert.
|
|
298
293
|
ocioRuntimeFactory: () => import('@bb-studio/ocio'), // or: ocioRuntimeUrl: '/vendor/ocio/index.js'
|
|
@@ -636,10 +631,8 @@ engine.denoisingManager.setOIDNQuality('high')
|
|
|
636
631
|
engine.denoisingManager.setStrategy('oidn') // OIDN owns the live view; see below
|
|
637
632
|
engine.denoisingManager.continuousDenoiseInterval = 250 // cap refreshes at 4/sec (default 8 = uncapped)
|
|
638
633
|
engine.denoisingManager.setUpscalerEnabled(true)
|
|
639
|
-
engine.denoisingManager.
|
|
640
|
-
engine.denoisingManager.setUpscalerScaleFactor(2) // ESRGAN only; DLSS is fixed at 2x
|
|
634
|
+
engine.denoisingManager.setUpscalerScaleFactor(2) // 2 or 4
|
|
641
635
|
engine.denoisingManager.setUpscalerQuality('high') // ESRGAN only
|
|
642
|
-
engine.denoisingManager.setNeuralRendering(true, { intensity: 1, colorStrength: 0 })
|
|
643
636
|
```
|
|
644
637
|
|
|
645
638
|
### engine.interactionManager
|
|
@@ -1260,51 +1253,6 @@ engine.addEventListener(EngineEvents.UPSCALING_END, () => console.log('Upsc
|
|
|
1260
1253
|
|
|
1261
1254
|
**Chaining with OIDN:** Upscaling and OIDN **can** run together — on render completion, OIDN runs first, then its denoised output is fed into the upscaler. Enable both; no manual coordination required.
|
|
1262
1255
|
|
|
1263
|
-
### The DLSS passes
|
|
1264
|
-
|
|
1265
|
-
Two further neural passes, ported from NVIDIA's DLSS weights. Both run once when a render finishes
|
|
1266
|
-
and both need a denoised frame — on raw Monte-Carlo noise they measurably lose to a plain resize, so
|
|
1267
|
-
enable OIDN alongside them.
|
|
1268
|
-
|
|
1269
|
-
Unlike the ONNX upscaler these are **not fetched from a CDN**: `dlss-runtime.js` installs
|
|
1270
|
-
`globalThis.DLSSRuntime` as a side effect and cannot be imported, so the host serves it and points
|
|
1271
|
-
`configureAssets` at it (see above). It lives at `app/public/dlss/` in this repo, and the local edits
|
|
1272
|
-
it carries are written up in `app/public/dlss/PATCHES.md` — re-vendoring it without re-applying them
|
|
1273
|
-
breaks the retouch pass with an explanatory throw.
|
|
1274
|
-
|
|
1275
|
-
```js
|
|
1276
|
-
// Super resolution, as a second AI Upscaler backend
|
|
1277
|
-
engine.denoisingManager.setUpscalerEnabled(true);
|
|
1278
|
-
engine.denoisingManager.setUpscalerBackend('dlss');
|
|
1279
|
-
|
|
1280
|
-
// The retouch pass — appearance, not resolution. Independent of the upscaler.
|
|
1281
|
-
engine.denoisingManager.setNeuralRendering(true, {
|
|
1282
|
-
intensity: 1, // 0..1 how much of the pass reaches the image
|
|
1283
|
-
localTone: 1, // 0..2 local light shaping; 1 is neutral
|
|
1284
|
-
localStructure: 1, // 0..2 fine surface detail; 1 is neutral
|
|
1285
|
-
colorStrength: 0, // 0..1 0 keeps the render's chroma, 1 takes the model's
|
|
1286
|
-
});
|
|
1287
|
-
```
|
|
1288
|
-
|
|
1289
|
-
The chain is **denoise → retouch (at render size) → super resolution (2x) → tone map**, scene-referred
|
|
1290
|
-
throughout. The retouch pass runs *before* the upscale deliberately: it sees a quarter of the pixels
|
|
1291
|
-
there, and above `DLSS_NR_MAX_PIXELS` (4.19 MP) it takes minutes and then loses every GPU device in
|
|
1292
|
-
the page. `DenoisingManager` skips it above that size rather than letting it run.
|
|
1293
|
-
|
|
1294
|
-
| | Super resolution | Retouch |
|
|
1295
|
-
|---|---|---|
|
|
1296
|
-
| What it changes | Resolution, fixed 2x | Appearance only |
|
|
1297
|
-
| Weights | 3.2 MB | 141 MB, fetched on first use |
|
|
1298
|
-
| Cost (1.9M-tri interior, warm) | 260 ms at 1024²→2048², 947 ms at 2048²→4096² | ~6 s at 2048² |
|
|
1299
|
-
| Against a native render | Ties Real-ESRGAN on accuracy, 3x faster, sharper than native | Close to a no-op on path-traced images |
|
|
1300
|
-
|
|
1301
|
-
Exported for building UI against: `SR_SCALE`, `SR_MAX_INPUT`, `DLSS_NR_DEFAULTS`, `DLSS_NR_RANGES`,
|
|
1302
|
-
`DLSS_NR_MAX_PIXELS`, and `renderUpscaled( app, { outputWidth, outputHeight, samples } )` — the
|
|
1303
|
-
offline entry point that drives a half-size render, denoise and upscale in one call.
|
|
1304
|
-
|
|
1305
|
-
⚠️ Each model brings **its own `GPUDevice`**, built by the runtime and not shareable. With both on,
|
|
1306
|
-
the page holds three: the renderer's and one each.
|
|
1307
|
-
|
|
1308
1256
|
## Troubleshooting
|
|
1309
1257
|
|
|
1310
1258
|
**OIDN: `Cannot find module './tza'` (webpack)**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
|
|
2
|
-
import { S as t, t as n, y as r } from "./ToneMapGPU-
|
|
3
|
-
//#region src/
|
|
2
|
+
import { S as t, t as n, y as r } from "./ToneMapGPU-BVE852iN.js";
|
|
3
|
+
//#region src/neural/NeuralRetouch.js
|
|
4
4
|
var i = /* @__PURE__ */ e({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
NeuralRetouch: () => m,
|
|
6
|
+
RETOUCH_COLOR_STRENGTH: () => 0,
|
|
7
|
+
RETOUCH_DEFAULTS: () => a,
|
|
8
|
+
RETOUCH_MAX_PIXELS: () => c,
|
|
9
|
+
RETOUCH_RANGES: () => l,
|
|
10
10
|
enhanceFrame: () => g
|
|
11
11
|
}), a = Object.freeze({
|
|
12
12
|
enabled: !0,
|
|
@@ -29,7 +29,7 @@ function o(e = {}) {
|
|
|
29
29
|
colorStrength: t
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
var s = t("
|
|
32
|
+
var s = t("neural"), c = 2048 * 2048, l = Object.freeze({
|
|
33
33
|
intensity: [0, 1],
|
|
34
34
|
localTone: [0, 2],
|
|
35
35
|
localStructure: [0, 2],
|
|
@@ -39,16 +39,16 @@ var s = t("dlss"), c = 2048 * 2048, l = Object.freeze({
|
|
|
39
39
|
}), u = null;
|
|
40
40
|
function d() {
|
|
41
41
|
if (u) return u;
|
|
42
|
-
let {
|
|
43
|
-
return globalThis.
|
|
44
|
-
if (globalThis.
|
|
42
|
+
let { neuralRuntimeUrl: e, neuralAssetBaseUrl: t } = r();
|
|
43
|
+
return t ? (globalThis.__NEURAL_ASSET_BASE__ = t, u = new Promise((t, n) => {
|
|
44
|
+
if (globalThis.NeuralRuntime?.getSrNrChain) return t(globalThis.NeuralRuntime.getSrNrChain());
|
|
45
45
|
let r = document.createElement("script");
|
|
46
46
|
r.src = e, r.onload = () => {
|
|
47
|
-
let e = globalThis.
|
|
48
|
-
if (!e) return n(/* @__PURE__ */ Error("
|
|
47
|
+
let e = globalThis.NeuralRuntime?.getSrNrChain;
|
|
48
|
+
if (!e) return n(/* @__PURE__ */ Error("Neural runtime loaded but exposed no retouch entry"));
|
|
49
49
|
t(e());
|
|
50
|
-
}, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the
|
|
51
|
-
}), u;
|
|
50
|
+
}, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the neural runtime from ${e}`)), document.head.appendChild(r);
|
|
51
|
+
}), u) : Promise.reject(/* @__PURE__ */ Error("No neural model location: set neuralAssetBaseUrl with configureAssets()"));
|
|
52
52
|
}
|
|
53
53
|
var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 8)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let size = textureDimensions(src);\n if ( gid.x >= size.x || gid.y >= size.y ) { return; }\n let c = textureLoad(src, vec2<i32>(gid.xy), 0);\n let r = u32(clamp(c.r, 0.0, 1.0) * 255.0 + 0.5);\n let g = u32(clamp(c.g, 0.0, 1.0) * 255.0 + 0.5);\n let b = u32(clamp(c.b, 0.0, 1.0) * 255.0 + 0.5);\n dst[gid.y * size.x + gid.x] = r | (g << 8u) | (b << 16u) | (255u << 24u);\n}\n", p = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 8)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let size = textureDimensions(src);\n if ( gid.x >= size.x || gid.y >= size.y ) { return; }\n let c = textureLoad(src, vec2<i32>(gid.xy), 0);\n let a = (gid.y * size.x + gid.x) * 2u;\n dst[a] = pack2x16float(c.rg);\n dst[a + 1u] = pack2x16float(vec2<f32>(c.b, 1.0));\n}\n", m = class e {
|
|
54
54
|
constructor(e, t) {
|
|
@@ -64,8 +64,8 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
64
64
|
return this.chain.pipeline.geometry.validHeight;
|
|
65
65
|
}
|
|
66
66
|
static async create({ width: t, height: n, canvas: r = null, settings: i = {}, onProgress: a = () => {} }) {
|
|
67
|
-
if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("
|
|
68
|
-
if (t * n > 4194304) throw Error(`
|
|
67
|
+
if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("NeuralRetouch.create: width and height must be positive integers");
|
|
68
|
+
if (t * n > 4194304) throw Error(`NeuralRetouch.create: ${t}x${n} is ${(t * n / 1e6).toFixed(1)} MP, above the ${(c / 1e6).toFixed(1)} MP this pass survives. Past it the run takes minutes and then loses every GPU device in the page.`);
|
|
69
69
|
let s = r ?? document.createElement("canvas");
|
|
70
70
|
r || (s.style.cssText = "position:fixed;left:-10000px;top:0;pointer-events:none");
|
|
71
71
|
let l = new e(await (await d()).create(s, t, n, a, o(i).runtime), s);
|
|
@@ -74,21 +74,21 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
74
74
|
_allocate() {
|
|
75
75
|
let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry;
|
|
76
76
|
this.source = this.device.createBuffer({
|
|
77
|
-
label: "rayzee:
|
|
77
|
+
label: "rayzee:retouch-source",
|
|
78
78
|
size: e * t * 8,
|
|
79
79
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
80
80
|
}), this.staging = new Uint16Array(e * t * 4);
|
|
81
81
|
let n = e * t * 4;
|
|
82
82
|
this._readbackStorage = this.device.createBuffer({
|
|
83
|
-
label: "rayzee:
|
|
83
|
+
label: "rayzee:retouch-readback",
|
|
84
84
|
size: n,
|
|
85
85
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
86
86
|
}), this._readbackMap = this.device.createBuffer({
|
|
87
|
-
label: "rayzee:
|
|
87
|
+
label: "rayzee:retouch-readback-map",
|
|
88
88
|
size: n,
|
|
89
89
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
90
90
|
}), this._readbackPipeline = this.device.createComputePipeline({
|
|
91
|
-
label: "rayzee:
|
|
91
|
+
label: "rayzee:retouch-readback",
|
|
92
92
|
layout: "auto",
|
|
93
93
|
compute: {
|
|
94
94
|
module: this.device.createShaderModule({ code: f }),
|
|
@@ -97,15 +97,15 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
97
97
|
});
|
|
98
98
|
let r = e * t * 8;
|
|
99
99
|
this._hdrStorage = this.device.createBuffer({
|
|
100
|
-
label: "rayzee:
|
|
100
|
+
label: "rayzee:retouch-hdr",
|
|
101
101
|
size: r,
|
|
102
102
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
103
103
|
}), this._hdrMap = this.device.createBuffer({
|
|
104
|
-
label: "rayzee:
|
|
104
|
+
label: "rayzee:retouch-hdr-map",
|
|
105
105
|
size: r,
|
|
106
106
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
107
107
|
}), this._hdrPipeline = this.device.createComputePipeline({
|
|
108
|
-
label: "rayzee:
|
|
108
|
+
label: "rayzee:retouch-hdr",
|
|
109
109
|
layout: "auto",
|
|
110
110
|
compute: {
|
|
111
111
|
module: this.device.createShaderModule({ code: p }),
|
|
@@ -115,7 +115,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
115
115
|
}
|
|
116
116
|
async _packHDR(e, t, n = !1) {
|
|
117
117
|
let r = this.chain.pipeline.slots[this.slot]?.hdrOutput;
|
|
118
|
-
if (!r) throw Error("
|
|
118
|
+
if (!r) throw Error("NeuralRetouch: the runtime has no scene-referred output. Either no frame has been produced yet, or neural-runtime.js was re-vendored without its `rayzee-patch` edits.");
|
|
119
119
|
let i = this.device.createBindGroup({
|
|
120
120
|
layout: this._hdrPipeline.getBindGroupLayout(0),
|
|
121
121
|
entries: [{
|
|
@@ -125,7 +125,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
125
125
|
binding: 1,
|
|
126
126
|
resource: { buffer: this._hdrStorage }
|
|
127
127
|
}]
|
|
128
|
-
}), a = this.device.createCommandEncoder({ label: "rayzee:
|
|
128
|
+
}), a = this.device.createCommandEncoder({ label: "rayzee:retouch-hdr" }), o = a.beginComputePass();
|
|
129
129
|
o.setPipeline(this._hdrPipeline), o.setBindGroup(0, i), o.dispatchWorkgroups(Math.ceil(e / 8), Math.ceil(t / 8)), o.end(), n && a.copyBufferToBuffer(this._hdrStorage, 0, this._hdrMap, 0, e * t * 8), this.device.queue.submit([a.finish()]);
|
|
130
130
|
}
|
|
131
131
|
async readOutputHDR() {
|
|
@@ -140,7 +140,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
140
140
|
}
|
|
141
141
|
async readOutputToned(e) {
|
|
142
142
|
let { validWidth: t, validHeight: r } = this.chain.pipeline.geometry;
|
|
143
|
-
return await this._packHDR(t, r), this._toneMapper ??= new n(this.device, "rayzee:
|
|
143
|
+
return await this._packHDR(t, r), this._toneMapper ??= new n(this.device, "rayzee:retouch-tonemap"), this._toneMapper.ensureSize(t, r), {
|
|
144
144
|
rgba8: await this._toneMapper.toRGBA8(this._hdrStorage, {
|
|
145
145
|
exposure: e.exposure ?? 1,
|
|
146
146
|
toneMapping: e.toneMapping ?? 0,
|
|
@@ -152,7 +152,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
152
152
|
}
|
|
153
153
|
async readOutput() {
|
|
154
154
|
let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry, n = this.chain.pipeline.slots[this.slot]?.output;
|
|
155
|
-
if (!n) throw Error("
|
|
155
|
+
if (!n) throw Error("NeuralRetouch.readOutput: the pass has not produced a frame yet");
|
|
156
156
|
let r = this.device.createBindGroup({
|
|
157
157
|
layout: this._readbackPipeline.getBindGroupLayout(0),
|
|
158
158
|
entries: [{
|
|
@@ -162,7 +162,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
|
|
|
162
162
|
binding: 1,
|
|
163
163
|
resource: { buffer: this._readbackStorage }
|
|
164
164
|
}]
|
|
165
|
-
}), i = this.device.createCommandEncoder({ label: "rayzee:
|
|
165
|
+
}), i = this.device.createCommandEncoder({ label: "rayzee:retouch-readback" }), a = i.beginComputePass();
|
|
166
166
|
a.setPipeline(this._readbackPipeline), a.setBindGroup(0, r), a.dispatchWorkgroups(Math.ceil(e / 8), Math.ceil(t / 8)), a.end(), i.copyBufferToBuffer(this._readbackStorage, 0, this._readbackMap, 0, e * t * 4), this.device.queue.submit([i.finish()]), await this._readbackMap.mapAsync(GPUMapMode.READ);
|
|
167
167
|
let o = new Uint8ClampedArray(this._readbackMap.getMappedRange().slice(0));
|
|
168
168
|
return this._readbackMap.unmap(), o;
|
|
@@ -187,9 +187,9 @@ async function g({ source: e, settings: t = {}, instance: n = null, exposure: r
|
|
|
187
187
|
onProgress: a
|
|
188
188
|
});
|
|
189
189
|
let { runtime: c, colorStrength: l } = o(t), u = s.staging;
|
|
190
|
-
if (!e.half || e.half.length !== u.length) throw Error(`
|
|
190
|
+
if (!e.half || e.half.length !== u.length) throw Error(`NeuralRetouch: expected ${u.length} packed halfs, got ${e.half?.length}`);
|
|
191
191
|
u.set(e.half), s.device.queue.writeBuffer(s.source, 0, u), s.chain.pipeline.paperWhite = 1 / Math.min(Math.max(r, 1 / h), h), s.chain.pipeline.colorStrength = l;
|
|
192
|
-
let d = performance.now(), f = s.device.createCommandEncoder({ label: "rayzee:
|
|
192
|
+
let d = performance.now(), f = s.device.createCommandEncoder({ label: "rayzee:retouch" });
|
|
193
193
|
await s.chain.encode(f, s.slot, { buffer: s.source }, c, () => {}, { reset: !0 }), s.device.queue.submit([f.finish()]), await s.device.queue.onSubmittedWorkDone();
|
|
194
194
|
let p = i ? await s.readOutputToned(i) : await s.readOutputHDR();
|
|
195
195
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
|
|
2
|
-
import { S as t, t as n, y as r } from "./ToneMapGPU-
|
|
2
|
+
import { S as t, t as n, y as r } from "./ToneMapGPU-BVE852iN.js";
|
|
3
3
|
//#region src/EngineEvents.js
|
|
4
4
|
var i = {
|
|
5
5
|
RENDER_COMPLETE: "engine:renderComplete",
|
|
@@ -35,26 +35,26 @@ var i = {
|
|
|
35
35
|
ISSUE: "engine:issue",
|
|
36
36
|
SCENE_METADATA_APPLIED: "engine:sceneMetadataApplied"
|
|
37
37
|
}, a = /* @__PURE__ */ e({
|
|
38
|
-
|
|
38
|
+
NeuralSuperRes: () => g,
|
|
39
39
|
SR_MAX_INPUT: () => c,
|
|
40
40
|
SR_SCALE: () => 2,
|
|
41
41
|
presentRGBA8: () => b,
|
|
42
42
|
readDenoisedHalf: () => h,
|
|
43
43
|
releaseDenoisedReader: () => m,
|
|
44
44
|
renderUpscaled: () => v
|
|
45
|
-
}), o = 2, s = t("
|
|
45
|
+
}), o = 2, s = t("neural"), c = 2048, l = null;
|
|
46
46
|
function u() {
|
|
47
47
|
if (l) return l;
|
|
48
|
-
let {
|
|
49
|
-
return globalThis.
|
|
50
|
-
if (globalThis.
|
|
48
|
+
let { neuralRuntimeUrl: e, neuralAssetBaseUrl: t } = r();
|
|
49
|
+
return t ? (globalThis.__NEURAL_ASSET_BASE__ = t, l = new Promise((t, n) => {
|
|
50
|
+
if (globalThis.NeuralRuntime?.getNativeSR) return t(globalThis.NeuralRuntime.getNativeSR());
|
|
51
51
|
let r = document.createElement("script");
|
|
52
52
|
r.src = e, r.onload = () => {
|
|
53
|
-
let e = globalThis.
|
|
54
|
-
if (!e) return n(/* @__PURE__ */ Error("
|
|
53
|
+
let e = globalThis.NeuralRuntime?.getNativeSR;
|
|
54
|
+
if (!e) return n(/* @__PURE__ */ Error("Neural runtime loaded but exposed no super-resolution entry"));
|
|
55
55
|
t(e());
|
|
56
|
-
}, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the
|
|
57
|
-
}), l;
|
|
56
|
+
}, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the neural runtime from ${e}`)), document.head.appendChild(r);
|
|
57
|
+
}), l) : Promise.reject(/* @__PURE__ */ Error("No neural model location: set neuralAssetBaseUrl with configureAssets()"));
|
|
58
58
|
}
|
|
59
59
|
var d = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 8)\nfn main( @builtin(global_invocation_id) gid: vec3<u32> ) {\n let size = textureDimensions( src );\n if ( gid.x >= size.x || gid.y >= size.y ) { return; }\n let c = textureLoad( src, vec2<i32>( gid.xy ), 0 ).rgb;\n let a = ( gid.y * size.x + gid.x ) * 2u;\n dst[ a ] = pack2x16float( c.rg );\n dst[ a + 1u ] = pack2x16float( vec2<f32>( c.b, 1.0 ) );\n}\n", f = null;
|
|
60
60
|
function p(e, t, n) {
|
|
@@ -65,21 +65,21 @@ function p(e, t, n) {
|
|
|
65
65
|
width: t,
|
|
66
66
|
height: n,
|
|
67
67
|
storage: e.createBuffer({
|
|
68
|
-
label: "rayzee:
|
|
68
|
+
label: "rayzee:neural-sr-pack",
|
|
69
69
|
size: r,
|
|
70
70
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
71
71
|
}),
|
|
72
72
|
map: e.createBuffer({
|
|
73
|
-
label: "rayzee:
|
|
73
|
+
label: "rayzee:neural-sr-pack-map",
|
|
74
74
|
size: r,
|
|
75
75
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
76
76
|
}),
|
|
77
77
|
pipeline: e.createComputePipeline({
|
|
78
|
-
label: "rayzee:
|
|
78
|
+
label: "rayzee:neural-sr-pack",
|
|
79
79
|
layout: "auto",
|
|
80
80
|
compute: {
|
|
81
81
|
module: e.createShaderModule({
|
|
82
|
-
label: "rayzee:
|
|
82
|
+
label: "rayzee:neural-sr-pack",
|
|
83
83
|
code: d
|
|
84
84
|
}),
|
|
85
85
|
entryPoint: "main"
|
|
@@ -92,7 +92,7 @@ function m() {
|
|
|
92
92
|
}
|
|
93
93
|
async function h(e) {
|
|
94
94
|
let t = e?._outGPUTexture;
|
|
95
|
-
if (!t) throw Error("
|
|
95
|
+
if (!t) throw Error("NeuralSuperRes: no denoised frame — enable OIDN and finish a render first");
|
|
96
96
|
let n = e.gpuDevice, { width: r, height: i } = e._outTexSize, a = p(n, r, i), o = n.createBindGroup({
|
|
97
97
|
layout: a.pipeline.getBindGroupLayout(0),
|
|
98
98
|
entries: [{
|
|
@@ -102,7 +102,7 @@ async function h(e) {
|
|
|
102
102
|
binding: 1,
|
|
103
103
|
resource: { buffer: a.storage }
|
|
104
104
|
}]
|
|
105
|
-
}), s = n.createCommandEncoder({ label: "rayzee:
|
|
105
|
+
}), s = n.createCommandEncoder({ label: "rayzee:neural-sr-pack" }), c = s.beginComputePass();
|
|
106
106
|
c.setPipeline(a.pipeline), c.setBindGroup(0, o), c.dispatchWorkgroups(Math.ceil(r / 8), Math.ceil(i / 8)), c.end(), s.copyBufferToBuffer(a.storage, 0, a.map, 0, r * i * 8), n.queue.submit([s.finish()]), await a.map.mapAsync(GPUMapMode.READ);
|
|
107
107
|
let l = new Uint16Array(a.map.getMappedRange().slice(0));
|
|
108
108
|
return a.map.unmap(), {
|
|
@@ -131,8 +131,8 @@ var g = class e {
|
|
|
131
131
|
return this.sr.geometry.outputHeight;
|
|
132
132
|
}
|
|
133
133
|
static async create({ width: t, height: n, onProgress: r = () => {} } = {}) {
|
|
134
|
-
if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("
|
|
135
|
-
if (t > 2048 || n > 2048) throw Error(`
|
|
134
|
+
if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("NeuralSuperRes.create: width and height must be positive integers");
|
|
135
|
+
if (t > 2048 || n > 2048) throw Error(`NeuralSuperRes.create: input capped at ${c}px per side (${c * 2}px output), got ${t}x${n}. Above that the runtime's history plane exceeds maxTextureDimension2D and it fails later with an unrelated bind-group error.`);
|
|
136
136
|
let i = await u(), a = document.createElement("canvas");
|
|
137
137
|
a.style.cssText = "position:fixed;left:-10000px;top:0;pointer-events:none", document.body.appendChild(a);
|
|
138
138
|
let o;
|
|
@@ -155,11 +155,11 @@ var g = class e {
|
|
|
155
155
|
this._color = new Uint16Array(e * t * 4), this._depth = new Float32Array(e * t), this._motion = new Uint16Array(e * t * 2);
|
|
156
156
|
}
|
|
157
157
|
async _run(e) {
|
|
158
|
-
if (this.disposed) throw Error("
|
|
158
|
+
if (this.disposed) throw Error("NeuralSuperRes: disposed");
|
|
159
159
|
let t = this.inputWidth, n = this.inputHeight;
|
|
160
|
-
if (e.width !== t || e.height !== n) throw Error(`
|
|
160
|
+
if (e.width !== t || e.height !== n) throw Error(`NeuralSuperRes: expected a ${t}x${n} source, got ${e.width}x${e.height}`);
|
|
161
161
|
let r = this._color;
|
|
162
|
-
if (!e.half || e.half.length !== r.length) throw Error(`
|
|
162
|
+
if (!e.half || e.half.length !== r.length) throw Error(`NeuralSuperRes: expected ${r.length} packed halfs from readDenoisedHalf, got ${e.half?.length}`);
|
|
163
163
|
r.set(e.half), this._depth.fill(.5), this._motion.fill(0);
|
|
164
164
|
let i = performance.now(), a = await this.sr.render(this.slot, {
|
|
165
165
|
color: r,
|
|
@@ -175,7 +175,7 @@ var g = class e {
|
|
|
175
175
|
}
|
|
176
176
|
async upscaleToRGBA8(e, t = {}) {
|
|
177
177
|
let { result: r, ms: i } = await this._run(e), { outputWidth: a, outputHeight: o } = this.geometry;
|
|
178
|
-
this._toneMapper ??= new n(this.sr.device, "rayzee:
|
|
178
|
+
this._toneMapper ??= new n(this.sr.device, "rayzee:neural-sr-tonemap"), this._toneMapper.ensureSize(a, o);
|
|
179
179
|
let s = performance.now();
|
|
180
180
|
return {
|
|
181
181
|
rgba8: await this._toneMapper.toRGBA8(r.hdr.buffer ?? r.hdr, {
|
|
@@ -211,7 +211,7 @@ function _(e, t, n) {
|
|
|
211
211
|
e.addEventListener(i.DENOISING_END, l);
|
|
212
212
|
let u = setInterval(() => {
|
|
213
213
|
c && s(!0);
|
|
214
|
-
}, 200), d = setTimeout(() => s(!1, /* @__PURE__ */ Error("
|
|
214
|
+
}, 200), d = setTimeout(() => s(!1, /* @__PURE__ */ Error("NeuralSuperRes: timed out waiting for the render to finish")), n);
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
async function v(e, { outputWidth: t, outputHeight: n, samples: r = 64, upscaler: i = null, timeoutMs: a = 6e5, present: o = !0, onProgress: s = () => {} } = {}) {
|
|
@@ -108,8 +108,8 @@ var D = {
|
|
|
108
108
|
ocioRuntimeUrl: null,
|
|
109
109
|
ocioWasmUrl: null,
|
|
110
110
|
upscalerModelBaseUrl: "https://huggingface.co/notaneimu/onnx-image-models/resolve/main/",
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
neuralRuntimeUrl: "/neural/neural-runtime.js",
|
|
112
|
+
neuralAssetBaseUrl: null,
|
|
113
113
|
cacheNamespace: "rayzee"
|
|
114
114
|
};
|
|
115
115
|
function O(e) {
|