rayzee 8.2.0 → 8.4.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 CHANGED
@@ -287,6 +287,11 @@ configureAssets({
287
287
  oidnWeightsBaseUrl: '/oidn-tzas/',
288
288
  upscalerModelBaseUrl: '/upscaler-onnx/',
289
289
 
290
+ // DLSS. The runtime is a plain script the host must serve — it installs
291
+ // `globalThis.DLSSRuntime` as a side effect and cannot be imported.
292
+ dlssRuntimeUrl: '/dlss/dlss-runtime.js',
293
+ dlssAssetBaseUrl: '/dlss/',
294
+
290
295
  // Prefix for engine-managed IndexedDB stores. Set to a unique value if multiple
291
296
  // apps embed the engine on the same origin to avoid cache collisions.
292
297
  cacheNamespace: 'my-app',
@@ -588,8 +593,10 @@ engine.denoisingManager.setOIDNQuality('high')
588
593
  engine.denoisingManager.setStrategy('oidn') // OIDN owns the live view; see below
589
594
  engine.denoisingManager.continuousDenoiseInterval = 250 // cap refreshes at 4/sec (default 8 = uncapped)
590
595
  engine.denoisingManager.setUpscalerEnabled(true)
591
- engine.denoisingManager.setUpscalerScaleFactor(2)
592
- engine.denoisingManager.setUpscalerQuality('high')
596
+ engine.denoisingManager.setUpscalerBackend('dlss') // 'esrgan' (default) | 'dlss'
597
+ engine.denoisingManager.setUpscalerScaleFactor(2) // ESRGAN only; DLSS is fixed at 2x
598
+ engine.denoisingManager.setUpscalerQuality('high') // ESRGAN only
599
+ engine.denoisingManager.setNeuralRendering(true, { intensity: 1, colorStrength: 0 })
593
600
  ```
594
601
 
595
602
  ### engine.interactionManager
@@ -1197,6 +1204,51 @@ engine.addEventListener(EngineEvents.UPSCALING_END, () => console.log('Upsc
1197
1204
 
1198
1205
  **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.
1199
1206
 
1207
+ ### The DLSS passes
1208
+
1209
+ Two further neural passes, ported from NVIDIA's DLSS weights. Both run once when a render finishes
1210
+ and both need a denoised frame — on raw Monte-Carlo noise they measurably lose to a plain resize, so
1211
+ enable OIDN alongside them.
1212
+
1213
+ Unlike the ONNX upscaler these are **not fetched from a CDN**: `dlss-runtime.js` installs
1214
+ `globalThis.DLSSRuntime` as a side effect and cannot be imported, so the host serves it and points
1215
+ `configureAssets` at it (see above). It lives at `app/public/dlss/` in this repo, and the local edits
1216
+ it carries are written up in `app/public/dlss/PATCHES.md` — re-vendoring it without re-applying them
1217
+ breaks the retouch pass with an explanatory throw.
1218
+
1219
+ ```js
1220
+ // Super resolution, as a second AI Upscaler backend
1221
+ engine.denoisingManager.setUpscalerEnabled(true);
1222
+ engine.denoisingManager.setUpscalerBackend('dlss');
1223
+
1224
+ // The retouch pass — appearance, not resolution. Independent of the upscaler.
1225
+ engine.denoisingManager.setNeuralRendering(true, {
1226
+ intensity: 1, // 0..1 how much of the pass reaches the image
1227
+ localTone: 1, // 0..2 local light shaping; 1 is neutral
1228
+ localStructure: 1, // 0..2 fine surface detail; 1 is neutral
1229
+ colorStrength: 0, // 0..1 0 keeps the render's chroma, 1 takes the model's
1230
+ });
1231
+ ```
1232
+
1233
+ The chain is **denoise → retouch (at render size) → super resolution (2x) → tone map**, scene-referred
1234
+ throughout. The retouch pass runs *before* the upscale deliberately: it sees a quarter of the pixels
1235
+ there, and above `DLSS_NR_MAX_PIXELS` (4.19 MP) it takes minutes and then loses every GPU device in
1236
+ the page. `DenoisingManager` skips it above that size rather than letting it run.
1237
+
1238
+ | | Super resolution | Retouch |
1239
+ |---|---|---|
1240
+ | What it changes | Resolution, fixed 2x | Appearance only |
1241
+ | Weights | 3.2 MB | 141 MB, fetched on first use |
1242
+ | Cost (1.9M-tri interior, warm) | 260 ms at 1024²→2048², 947 ms at 2048²→4096² | ~6 s at 2048² |
1243
+ | Against a native render | Ties Real-ESRGAN on accuracy, 3x faster, sharper than native | Close to a no-op on path-traced images |
1244
+
1245
+ Exported for building UI against: `SR_SCALE`, `SR_MAX_INPUT`, `DLSS_NR_DEFAULTS`, `DLSS_NR_RANGES`,
1246
+ `DLSS_NR_MAX_PIXELS`, and `renderUpscaled( app, { outputWidth, outputHeight, samples } )` — the
1247
+ offline entry point that drives a half-size render, denoise and upscale in one call.
1248
+
1249
+ ⚠️ Each model brings **its own `GPUDevice`**, built by the runtime and not shareable. With both on,
1250
+ the page holds three: the renderer's and one each.
1251
+
1200
1252
  ## Troubleshooting
1201
1253
 
1202
1254
  **OIDN: `Cannot find module './tza'` (webpack)**
@@ -0,0 +1,202 @@
1
+ import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
2
+ import { o as t, r as n, t as r } from "./ToneMapGPU-DzqSyzTx.js";
3
+ //#region src/dlss/DLSSNeural.js
4
+ var i = /* @__PURE__ */ e({
5
+ DLSSNeural: () => m,
6
+ DLSS_NR_COLOR_STRENGTH: () => 0,
7
+ DLSS_NR_DEFAULTS: () => a,
8
+ DLSS_NR_MAX_PIXELS: () => c,
9
+ DLSS_NR_RANGES: () => l,
10
+ enhanceFrame: () => g
11
+ }), a = Object.freeze({
12
+ enabled: !0,
13
+ intensity: 1,
14
+ localTone: 1,
15
+ localStructure: 1,
16
+ skinStructure: -1,
17
+ autoMask: !0,
18
+ style: 0,
19
+ preset: 0,
20
+ uiCorrection: !1
21
+ });
22
+ function o(e = {}) {
23
+ let { colorStrength: t = 0, ...n } = e;
24
+ return {
25
+ runtime: {
26
+ ...a,
27
+ ...n
28
+ },
29
+ colorStrength: t
30
+ };
31
+ }
32
+ var s = t("dlss"), c = 2048 * 2048, l = Object.freeze({
33
+ intensity: [0, 1],
34
+ localTone: [0, 2],
35
+ localStructure: [0, 2],
36
+ skinStructure: [-1, 2],
37
+ style: [0, 2],
38
+ preset: [0, 3]
39
+ }), u = null;
40
+ function d() {
41
+ if (u) return u;
42
+ let { dlssRuntimeUrl: e, dlssAssetBaseUrl: t } = n();
43
+ return globalThis.__DLSS5_ASSET_BASE__ = t, u = new Promise((t, n) => {
44
+ if (globalThis.DLSSRuntime?.getSrNrChain) return t(globalThis.DLSSRuntime.getSrNrChain());
45
+ let r = document.createElement("script");
46
+ r.src = e, r.onload = () => {
47
+ let e = globalThis.DLSSRuntime?.getSrNrChain;
48
+ if (!e) return n(/* @__PURE__ */ Error("DLSS runtime loaded but exposed no neural-rendering entry"));
49
+ t(e());
50
+ }, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the DLSS runtime from ${e}`)), document.head.appendChild(r);
51
+ }), u;
52
+ }
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
+ constructor(e, t) {
55
+ this.chain = e, this.canvas = t, this.slot = 0, this.source = null, this.staging = null, this._readbackPipeline = null, this._readbackStorage = null, this._readbackMap = null, this._hdrPipeline = null, this._hdrStorage = null, this._hdrMap = null, this._toneMapper = null, this.disposed = !1;
56
+ }
57
+ get device() {
58
+ return this.chain.device;
59
+ }
60
+ get width() {
61
+ return this.chain.pipeline.geometry.validWidth;
62
+ }
63
+ get height() {
64
+ return this.chain.pipeline.geometry.validHeight;
65
+ }
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("DLSSNeural.create: width and height must be positive integers");
68
+ if (t * n > 4194304) throw Error(`DLSSNeural.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
+ let s = r ?? document.createElement("canvas");
70
+ r || (s.style.cssText = "position:fixed;left:-10000px;top:0;pointer-events:none");
71
+ let l = new e(await (await d()).create(s, t, n, a, o(i).runtime), s);
72
+ return l._allocate(), l;
73
+ }
74
+ _allocate() {
75
+ let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry;
76
+ this.source = this.device.createBuffer({
77
+ label: "rayzee:dlss-nr-source",
78
+ size: e * t * 8,
79
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
80
+ }), this.staging = new Uint16Array(e * t * 4);
81
+ let n = e * t * 4;
82
+ this._readbackStorage = this.device.createBuffer({
83
+ label: "rayzee:dlss-nr-readback",
84
+ size: n,
85
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
86
+ }), this._readbackMap = this.device.createBuffer({
87
+ label: "rayzee:dlss-nr-readback-map",
88
+ size: n,
89
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
90
+ }), this._readbackPipeline = this.device.createComputePipeline({
91
+ label: "rayzee:dlss-nr-readback",
92
+ layout: "auto",
93
+ compute: {
94
+ module: this.device.createShaderModule({ code: f }),
95
+ entryPoint: "main"
96
+ }
97
+ });
98
+ let r = e * t * 8;
99
+ this._hdrStorage = this.device.createBuffer({
100
+ label: "rayzee:dlss-nr-hdr",
101
+ size: r,
102
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
103
+ }), this._hdrMap = this.device.createBuffer({
104
+ label: "rayzee:dlss-nr-hdr-map",
105
+ size: r,
106
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
107
+ }), this._hdrPipeline = this.device.createComputePipeline({
108
+ label: "rayzee:dlss-nr-hdr",
109
+ layout: "auto",
110
+ compute: {
111
+ module: this.device.createShaderModule({ code: p }),
112
+ entryPoint: "main"
113
+ }
114
+ });
115
+ }
116
+ async _packHDR(e, t, n = !1) {
117
+ let r = this.chain.pipeline.slots[this.slot]?.hdrOutput;
118
+ if (!r) throw Error("DLSSNeural: the runtime has no scene-referred output. Either no frame has been produced yet, or dlss-runtime.js was re-vendored without the patch described in its PATCHES.md.");
119
+ let i = this.device.createBindGroup({
120
+ layout: this._hdrPipeline.getBindGroupLayout(0),
121
+ entries: [{
122
+ binding: 0,
123
+ resource: r.createView()
124
+ }, {
125
+ binding: 1,
126
+ resource: { buffer: this._hdrStorage }
127
+ }]
128
+ }), a = this.device.createCommandEncoder({ label: "rayzee:dlss-nr-hdr" }), o = a.beginComputePass();
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
+ }
131
+ async readOutputHDR() {
132
+ let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry;
133
+ await this._packHDR(e, t, !0), await this._hdrMap.mapAsync(GPUMapMode.READ);
134
+ let n = new Uint16Array(this._hdrMap.getMappedRange().slice(0));
135
+ return this._hdrMap.unmap(), {
136
+ half: n,
137
+ width: e,
138
+ height: t
139
+ };
140
+ }
141
+ async readOutputToned(e) {
142
+ let { validWidth: t, validHeight: n } = this.chain.pipeline.geometry;
143
+ return await this._packHDR(t, n), this._toneMapper ??= new r(this.device, "rayzee:dlss-nr-tonemap"), this._toneMapper.ensureSize(t, n), {
144
+ rgba8: await this._toneMapper.toRGBA8(this._hdrStorage, {
145
+ exposure: e.exposure ?? 1,
146
+ toneMapping: e.toneMapping ?? 0,
147
+ saturation: e.saturation ?? 1
148
+ }),
149
+ width: t,
150
+ height: n
151
+ };
152
+ }
153
+ async readOutput() {
154
+ let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry, n = this.chain.pipeline.slots[this.slot]?.output;
155
+ if (!n) throw Error("DLSSNeural.readOutput: the pass has not produced a frame yet");
156
+ let r = this.device.createBindGroup({
157
+ layout: this._readbackPipeline.getBindGroupLayout(0),
158
+ entries: [{
159
+ binding: 0,
160
+ resource: n.createView()
161
+ }, {
162
+ binding: 1,
163
+ resource: { buffer: this._readbackStorage }
164
+ }]
165
+ }), i = this.device.createCommandEncoder({ label: "rayzee:dlss-nr-readback" }), a = i.beginComputePass();
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
+ let o = new Uint8ClampedArray(this._readbackMap.getMappedRange().slice(0));
168
+ return this._readbackMap.unmap(), o;
169
+ }
170
+ dispose() {
171
+ if (!this.disposed) {
172
+ this.disposed = !0, this.source?.destroy(), this._readbackStorage?.destroy(), this._readbackMap?.destroy(), this._hdrStorage?.destroy(), this._hdrMap?.destroy(), this._toneMapper?.dispose();
173
+ try {
174
+ this.chain.destroy();
175
+ } catch (e) {
176
+ s.warn("retouch teardown:", e);
177
+ }
178
+ }
179
+ }
180
+ }, h = 20;
181
+ async function g({ source: e, settings: t = {}, instance: n = null, exposure: r = 1, tone: i = null, onProgress: a = () => {} }) {
182
+ let s = n;
183
+ s && (s.width !== e.width || s.height !== e.height) && (s.dispose(), s = null), s ||= await m.create({
184
+ width: e.width,
185
+ height: e.height,
186
+ settings: t,
187
+ onProgress: a
188
+ });
189
+ let { runtime: c, colorStrength: l } = o(t), u = s.staging;
190
+ if (!e.half || e.half.length !== u.length) throw Error(`DLSSNeural: expected ${u.length} packed halfs, got ${e.half?.length}`);
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:dlss-nr" });
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
+ let p = i ? await s.readOutputToned(i) : await s.readOutputHDR();
195
+ return {
196
+ instance: s,
197
+ ...p,
198
+ ms: performance.now() - d
199
+ };
200
+ }
201
+ //#endregion
202
+ export { l as i, a as n, c as r, i as t };
@@ -0,0 +1,266 @@
1
+ import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
2
+ import { o as t, r as n, t as r } from "./ToneMapGPU-DzqSyzTx.js";
3
+ //#region src/EngineEvents.js
4
+ var i = {
5
+ RENDER_COMPLETE: "engine:renderComplete",
6
+ RENDER_RESET: "engine:renderReset",
7
+ FRAME: "engine:frame",
8
+ DENOISING_START: "engine:denoisingStart",
9
+ DENOISING_END: "engine:denoisingEnd",
10
+ UPSCALING_START: "engine:upscalingStart",
11
+ UPSCALING_PROGRESS: "engine:upscalingProgress",
12
+ UPSCALING_END: "engine:upscalingEnd",
13
+ LOADING_UPDATE: "engine:loadingUpdate",
14
+ LOADING_RESET: "engine:loadingReset",
15
+ STATS_UPDATE: "engine:statsUpdate",
16
+ OBJECT_SELECTED: "engine:objectSelected",
17
+ OBJECT_DESELECTED: "engine:objectDeselected",
18
+ OBJECT_DOUBLE_CLICKED: "engine:objectDoubleClicked",
19
+ SELECT_MODE_CHANGED: "engine:selectModeChanged",
20
+ OBJECT_TRANSFORM_START: "engine:objectTransformStart",
21
+ OBJECT_TRANSFORM_END: "engine:objectTransformEnd",
22
+ TRANSFORM_MODE_CHANGED: "engine:transformModeChanged",
23
+ AUTO_FOCUS_UPDATED: "engine:autoFocusUpdated",
24
+ AUTO_EXPOSURE_UPDATED: "engine:autoExposureUpdated",
25
+ AF_POINT_PLACED: "engine:afPointPlaced",
26
+ SETTING_CHANGED: "engine:settingChanged",
27
+ ANIMATION_STARTED: "engine:animationStarted",
28
+ ANIMATION_PAUSED: "engine:animationPaused",
29
+ ANIMATION_STOPPED: "engine:animationStopped",
30
+ ANIMATION_FINISHED: "engine:animationFinished",
31
+ VIDEO_RENDER_PROGRESS: "engine:videoRenderProgress",
32
+ VIDEO_RENDER_COMPLETE: "engine:videoRenderComplete",
33
+ DISPOSE: "engine:dispose",
34
+ DEVICE_LOST: "engine:deviceLost",
35
+ ISSUE: "engine:issue",
36
+ SCENE_METADATA_APPLIED: "engine:sceneMetadataApplied"
37
+ }, a = /* @__PURE__ */ e({
38
+ DLSSSuperRes: () => g,
39
+ SR_MAX_INPUT: () => c,
40
+ SR_SCALE: () => 2,
41
+ presentRGBA8: () => b,
42
+ readDenoisedHalf: () => h,
43
+ releaseDenoisedReader: () => m,
44
+ renderUpscaled: () => v
45
+ }), o = 2, s = t("dlss"), c = 2048, l = null;
46
+ function u() {
47
+ if (l) return l;
48
+ let { dlssRuntimeUrl: e, dlssAssetBaseUrl: t } = n();
49
+ return globalThis.__DLSS5_ASSET_BASE__ = t, l = new Promise((t, n) => {
50
+ if (globalThis.DLSSRuntime?.getNativeSR) return t(globalThis.DLSSRuntime.getNativeSR());
51
+ let r = document.createElement("script");
52
+ r.src = e, r.onload = () => {
53
+ let e = globalThis.DLSSRuntime?.getNativeSR;
54
+ if (!e) return n(/* @__PURE__ */ Error("DLSS runtime loaded but exposed no super-resolution entry"));
55
+ t(e());
56
+ }, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the DLSS runtime from ${e}`)), document.head.appendChild(r);
57
+ }), l;
58
+ }
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
+ function p(e, t, n) {
61
+ if (f && (f.device !== e || f.width !== t || f.height !== n) && m(), f) return f;
62
+ let r = t * n * 8;
63
+ return f = {
64
+ device: e,
65
+ width: t,
66
+ height: n,
67
+ storage: e.createBuffer({
68
+ label: "rayzee:dlss-sr-pack",
69
+ size: r,
70
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
71
+ }),
72
+ map: e.createBuffer({
73
+ label: "rayzee:dlss-sr-pack-map",
74
+ size: r,
75
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
76
+ }),
77
+ pipeline: e.createComputePipeline({
78
+ label: "rayzee:dlss-sr-pack",
79
+ layout: "auto",
80
+ compute: {
81
+ module: e.createShaderModule({
82
+ label: "rayzee:dlss-sr-pack",
83
+ code: d
84
+ }),
85
+ entryPoint: "main"
86
+ }
87
+ })
88
+ }, f;
89
+ }
90
+ function m() {
91
+ f?.storage.destroy(), f?.map.destroy(), f = null;
92
+ }
93
+ async function h(e) {
94
+ let t = e?._outGPUTexture;
95
+ if (!t) throw Error("DLSSSuperRes: no denoised frame — enable OIDN and finish a render first");
96
+ let n = e.gpuDevice, { width: r, height: i } = e._outTexSize, a = p(n, r, i), o = n.createBindGroup({
97
+ layout: a.pipeline.getBindGroupLayout(0),
98
+ entries: [{
99
+ binding: 0,
100
+ resource: t.createView()
101
+ }, {
102
+ binding: 1,
103
+ resource: { buffer: a.storage }
104
+ }]
105
+ }), s = n.createCommandEncoder({ label: "rayzee:dlss-sr-pack" }), c = s.beginComputePass();
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
+ let l = new Uint16Array(a.map.getMappedRange().slice(0));
108
+ return a.map.unmap(), {
109
+ half: l,
110
+ width: r,
111
+ height: i
112
+ };
113
+ }
114
+ var g = class e {
115
+ constructor(e, t) {
116
+ this.sr = e, this.canvas = t, this.slot = 0, this._color = null, this._depth = null, this._motion = null, this._toneMapper = null, this.disposed = !1;
117
+ }
118
+ get geometry() {
119
+ return this.sr.geometry;
120
+ }
121
+ get inputWidth() {
122
+ return this.sr.geometry.width;
123
+ }
124
+ get inputHeight() {
125
+ return this.sr.geometry.height;
126
+ }
127
+ get outputWidth() {
128
+ return this.sr.geometry.outputWidth;
129
+ }
130
+ get outputHeight() {
131
+ return this.sr.geometry.outputHeight;
132
+ }
133
+ static async create({ width: t, height: n, onProgress: r = () => {} } = {}) {
134
+ if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("DLSSSuperRes.create: width and height must be positive integers");
135
+ if (t > 2048 || n > 2048) throw Error(`DLSSSuperRes.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
+ let i = await u(), a = document.createElement("canvas");
137
+ a.style.cssText = "position:fixed;left:-10000px;top:0;pointer-events:none", document.body.appendChild(a);
138
+ let o;
139
+ try {
140
+ o = await i.create(a, {
141
+ width: t,
142
+ height: n,
143
+ onProgress: r,
144
+ timestamps: !0,
145
+ nrSettings: null
146
+ });
147
+ } catch (e) {
148
+ throw a.remove(), e;
149
+ }
150
+ let s = new e(o, a);
151
+ return s._allocate(), s;
152
+ }
153
+ _allocate() {
154
+ let e = this.inputWidth, t = this.inputHeight;
155
+ this._color = new Uint16Array(e * t * 4), this._depth = new Float32Array(e * t), this._motion = new Uint16Array(e * t * 2);
156
+ }
157
+ async _run(e) {
158
+ if (this.disposed) throw Error("DLSSSuperRes: disposed");
159
+ let t = this.inputWidth, n = this.inputHeight;
160
+ if (e.width !== t || e.height !== n) throw Error(`DLSSSuperRes: expected a ${t}x${n} source, got ${e.width}x${e.height}`);
161
+ let r = this._color;
162
+ if (!e.half || e.half.length !== r.length) throw Error(`DLSSSuperRes: expected ${r.length} packed halfs from readDenoisedHalf, got ${e.half?.length}`);
163
+ r.set(e.half), this._depth.fill(.5), this._motion.fill(0);
164
+ let i = performance.now(), a = await this.sr.render(this.slot, {
165
+ color: r,
166
+ depth: this._depth,
167
+ motion: this._motion,
168
+ reset: !0,
169
+ jitter: [0, 0]
170
+ });
171
+ return await this.sr.device.queue.onSubmittedWorkDone(), {
172
+ result: a,
173
+ ms: performance.now() - i
174
+ };
175
+ }
176
+ async upscaleToRGBA8(e, t = {}) {
177
+ let { result: n, ms: i } = await this._run(e), { outputWidth: a, outputHeight: o } = this.geometry;
178
+ this._toneMapper ??= new r(this.sr.device, "rayzee:dlss-sr-tonemap"), this._toneMapper.ensureSize(a, o);
179
+ let s = performance.now();
180
+ return {
181
+ rgba8: await this._toneMapper.toRGBA8(n.hdr.buffer ?? n.hdr, {
182
+ exposure: t.exposure ?? 1,
183
+ toneMapping: t.toneMapping ?? 0,
184
+ saturation: t.saturation ?? 1,
185
+ flipY: !0
186
+ }),
187
+ width: a,
188
+ height: o,
189
+ ms: i,
190
+ toneMs: performance.now() - s
191
+ };
192
+ }
193
+ dispose() {
194
+ if (!this.disposed) {
195
+ this.disposed = !0, this._toneMapper?.dispose(), this._toneMapper = null, this.canvas.remove();
196
+ try {
197
+ this.sr.destroy();
198
+ } catch (e) {
199
+ s.warn("super resolution teardown:", e);
200
+ }
201
+ }
202
+ }
203
+ };
204
+ function _(e, t, n) {
205
+ return new Promise((r, a) => {
206
+ let o = !1, s = (t, n) => {
207
+ o || (o = !0, e.removeEventListener(i.DENOISING_END, l), clearInterval(u), clearTimeout(d), t ? r() : a(n));
208
+ }, c = !1, l = () => {
209
+ (e.stages?.pathTracer?.frameCount ?? 0) >= t && (c = !0);
210
+ };
211
+ e.addEventListener(i.DENOISING_END, l);
212
+ let u = setInterval(() => {
213
+ c && s(!0);
214
+ }, 200), d = setTimeout(() => s(!1, /* @__PURE__ */ Error("DLSSSuperRes: timed out waiting for the render to finish")), n);
215
+ });
216
+ }
217
+ async function v(e, { outputWidth: t, outputHeight: n, samples: r = 64, upscaler: i = null, timeoutMs: a = 6e5, present: o = !0, onProgress: s = () => {} } = {}) {
218
+ if (t % 2 || n % 2) throw Error(`renderUpscaled: output must be divisible by 2, got ${t}x${n}`);
219
+ let c = t / 2, l = n / 2, u = e.stages?.pathTracer, d = {
220
+ width: u?.width,
221
+ height: u?.height,
222
+ maxSamples: e.settings?.get?.("maxSamples"),
223
+ finalDenoise: e.denoisingManager?.finalDenoise,
224
+ paused: e.pauseRendering
225
+ }, f = !i, p = i, m = {};
226
+ try {
227
+ if (!p) {
228
+ let e = performance.now();
229
+ s("Loading the super-resolution model"), p = await g.create({
230
+ width: c,
231
+ height: l,
232
+ onProgress: s
233
+ }), m.load = performance.now() - e;
234
+ } else if (p.inputWidth !== c || p.inputHeight !== l) throw Error(`renderUpscaled: upscaler is ${p.inputWidth}x${p.inputHeight}, need ${c}x${l}`);
235
+ let i = performance.now();
236
+ s(`Tracing ${c}x${l} at ${r} spp`), e.pauseRendering = !1, e.setCanvasSize(c, l), await new Promise((e) => setTimeout(e, 300)), e.denoisingManager.applyOIDNEnabled(!0), e.settings.set("maxSamples", r);
237
+ let u = _(e, r, a);
238
+ e.reset(), await u, e.pauseRendering = !0, m.render = performance.now() - i, s("Reading the denoised frame");
239
+ let d = performance.now(), f = await h(e.denoisingManager?.denoiser);
240
+ m.read = performance.now() - d, s(`Upscaling to ${t}x${n}`);
241
+ let v = {
242
+ exposure: e.renderer.toneMappingExposure,
243
+ toneMapping: e.renderer.toneMapping,
244
+ saturation: e.settings.get("saturation") ?? 1
245
+ }, { rgba8: b, width: x, height: S, ms: C, toneMs: w } = await p.upscaleToRGBA8(f, v);
246
+ return m.upscale = C, m.tonemap = w, o && y(e.denoisingManager?.upscalerCanvas, b, x, S), {
247
+ rgba8: b,
248
+ width: x,
249
+ height: S,
250
+ timings: m,
251
+ upscaler: p
252
+ };
253
+ } catch (e) {
254
+ throw f && p?.dispose(), e;
255
+ } finally {
256
+ d.width && d.height && e.setCanvasSize(d.width, d.height), d.maxSamples !== void 0 && e.settings?.set?.("maxSamples", d.maxSamples), d.finalDenoise !== void 0 && e.denoisingManager?.applyOIDNEnabled(d.finalDenoise), e.pauseRendering = d.paused;
257
+ }
258
+ }
259
+ function y(e, t, n, r) {
260
+ return e ? (e.width = n, e.height = r, e.getContext("2d").putImageData(new ImageData(new Uint8ClampedArray(t.buffer ?? t), n, r), 0, 0), e.style.display = "block", !0) : !1;
261
+ }
262
+ function b(e, t, n, r) {
263
+ return y(e, t, n, r);
264
+ }
265
+ //#endregion
266
+ export { i as a, v as i, c as n, o as r, a as t };