@plasius/gpu-renderer 0.2.48 → 0.2.49
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/CHANGELOG.md +17 -0
- package/README.md +6 -0
- package/dist/index.cjs +7513 -7390
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7513 -7390
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.d.ts +8 -1
- package/src/wavefront-compute.js +10 -2
- package/src/wavefront-config.js +13 -2
- package/src/wavefront-frame-dispatcher.js +12 -8
- package/src/wavefront-frame-encoder.js +7 -0
- package/src/wavefront-progressive-shader.js +25 -0
- package/src/wavefront-progressive.js +46 -0
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -869,6 +869,7 @@ export interface WavefrontEnvironmentMapSnapshot {
|
|
|
869
869
|
}
|
|
870
870
|
|
|
871
871
|
export interface WavefrontPathTracingComputeConfig {
|
|
872
|
+
readonly progressive: boolean;
|
|
872
873
|
readonly mode: typeof rendererWavefrontComputeMode;
|
|
873
874
|
readonly width: number;
|
|
874
875
|
readonly height: number;
|
|
@@ -1036,6 +1037,7 @@ export interface WavefrontPathTracingMemoryEstimate {
|
|
|
1036
1037
|
readonly queuePairBytes: number;
|
|
1037
1038
|
readonly hitBytes: number;
|
|
1038
1039
|
readonly accumulationBytes: number;
|
|
1040
|
+
readonly progressiveBytes: number;
|
|
1039
1041
|
readonly pathVertexBytes: number;
|
|
1040
1042
|
readonly sceneObjectBytes: number;
|
|
1041
1043
|
readonly triangleBytes: number;
|
|
@@ -1097,6 +1099,8 @@ export interface WavefrontGpuParallelismDiagnostics {
|
|
|
1097
1099
|
}
|
|
1098
1100
|
|
|
1099
1101
|
export interface CreateWavefrontPathTracingComputeRendererOptions {
|
|
1102
|
+
/** Accumulate linear radiance between frames until camera/scene/reset changes. Default false. */
|
|
1103
|
+
readonly progressive?: boolean;
|
|
1100
1104
|
readonly canvas?: HTMLCanvasElement | string;
|
|
1101
1105
|
readonly navigator?: Navigator | { gpu?: GPU };
|
|
1102
1106
|
readonly document?: Document;
|
|
@@ -1160,7 +1164,8 @@ export interface WavefrontPathTracingComputeRenderer {
|
|
|
1160
1164
|
readonly device: GPUDevice;
|
|
1161
1165
|
readonly format: GPUTextureFormat | string;
|
|
1162
1166
|
readonly config: WavefrontPathTracingComputeConfig;
|
|
1163
|
-
renderOnce(): WavefrontPathTracingComputeFrameStats;
|
|
1167
|
+
renderOnce(options?: { samplesPerPixel?: number }): WavefrontPathTracingComputeFrameStats;
|
|
1168
|
+
resetAccumulation(): void;
|
|
1164
1169
|
renderFrame(options?: {
|
|
1165
1170
|
readStats?: boolean;
|
|
1166
1171
|
readOutputProbe?: boolean;
|
|
@@ -1182,6 +1187,8 @@ export interface WavefrontPathTracingComputeRenderer {
|
|
|
1182
1187
|
updateSceneObjects(sceneObjects: readonly WavefrontSceneObjectInput[]): WavefrontPathTracingComputeConfig;
|
|
1183
1188
|
updateCamera(camera: WavefrontCameraOptions): WavefrontPathTracingComputeConfig;
|
|
1184
1189
|
getSnapshot(): Readonly<{
|
|
1190
|
+
/** Submitted samples; await GPU completion before reporting completed progress. */
|
|
1191
|
+
accumulatedSamplesPerPixel: number;
|
|
1185
1192
|
frame: number;
|
|
1186
1193
|
width: number;
|
|
1187
1194
|
height: number;
|
package/src/wavefront-compute.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createWavefrontProgressiveResources } from './wavefront-progressive.js';
|
|
1
2
|
import {
|
|
2
3
|
createGpuParallelismCounters,
|
|
3
4
|
createGpuParallelismDiagnostics,
|
|
@@ -299,7 +300,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
299
300
|
const outputConfigSlotCount = config.deferredPathResolve ? 0 : tiles.length;
|
|
300
301
|
const frameConfigSlotCount = Math.max(
|
|
301
302
|
1,
|
|
302
|
-
tiles.length * config.samplesPerPixel + outputConfigSlotCount + (config.denoise ? 1 : 0)
|
|
303
|
+
tiles.length * config.samplesPerPixel + outputConfigSlotCount + (config.denoise || config.progressive ? 1 : 0)
|
|
303
304
|
);
|
|
304
305
|
const configBuffer = createBuffer(
|
|
305
306
|
device,
|
|
@@ -369,7 +370,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
369
370
|
format: "rgba16float",
|
|
370
371
|
usage:
|
|
371
372
|
constants.texture.STORAGE_BINDING |
|
|
372
|
-
constants.texture.TEXTURE_BINDING,
|
|
373
|
+
constants.texture.TEXTURE_BINDING | constants.texture.COPY_DST,
|
|
373
374
|
});
|
|
374
375
|
const radianceView = radianceTexture.createView();
|
|
375
376
|
const denoiseScratchTexture = device.createTexture({
|
|
@@ -563,10 +564,12 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
563
564
|
outputView,
|
|
564
565
|
sampler,
|
|
565
566
|
});
|
|
567
|
+
const progressive = await createWavefrontProgressiveResources({device, constants, config, configBuffer, radianceTexture, radianceView, outputView});
|
|
566
568
|
let activeFrameTelemetry = null;
|
|
567
569
|
let frameTelemetryResources = null;
|
|
568
570
|
const frameEncoder = createWavefrontFrameEncoder({
|
|
569
571
|
getConfig: () => config,
|
|
572
|
+
progressive,
|
|
570
573
|
getBindGroups: () => bindGroups,
|
|
571
574
|
pipelines,
|
|
572
575
|
counterBuffer,
|
|
@@ -1022,6 +1025,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
1022
1025
|
}
|
|
1023
1026
|
|
|
1024
1027
|
function updateSceneObjects(sceneObjects) {
|
|
1028
|
+
progressive?.reset();
|
|
1025
1029
|
const nextPackedScene = packWavefrontSceneObjects(sceneObjects, config.sceneObjectCapacity);
|
|
1026
1030
|
packedScene = nextPackedScene;
|
|
1027
1031
|
const nextConfig = rebuildLiveConfig();
|
|
@@ -1034,6 +1038,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
1034
1038
|
}
|
|
1035
1039
|
|
|
1036
1040
|
function updateCamera(cameraOptions = {}) {
|
|
1041
|
+
progressive?.reset();
|
|
1037
1042
|
activeCameraOptions = cameraOptions;
|
|
1038
1043
|
config = rebuildLiveConfig();
|
|
1039
1044
|
return config;
|
|
@@ -1042,6 +1047,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
1042
1047
|
function getSnapshot() {
|
|
1043
1048
|
return Object.freeze({
|
|
1044
1049
|
frame,
|
|
1050
|
+
accumulatedSamplesPerPixel: progressive?.samples ?? 0,
|
|
1045
1051
|
width: config.width,
|
|
1046
1052
|
height: config.height,
|
|
1047
1053
|
maxDepth: config.maxDepth,
|
|
@@ -1073,6 +1079,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
1073
1079
|
}
|
|
1074
1080
|
|
|
1075
1081
|
function destroy() {
|
|
1082
|
+
progressive?.destroy();
|
|
1076
1083
|
frameTelemetryResources?.destroy?.();
|
|
1077
1084
|
activeQueue.destroy?.();
|
|
1078
1085
|
nextQueue.destroy?.();
|
|
@@ -1138,6 +1145,7 @@ export async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
1138
1145
|
readOutputProbe,
|
|
1139
1146
|
updateSceneObjects,
|
|
1140
1147
|
updateCamera,
|
|
1148
|
+
resetAccumulation: () => progressive?.reset(),
|
|
1141
1149
|
getSnapshot,
|
|
1142
1150
|
destroy,
|
|
1143
1151
|
});
|
package/src/wavefront-config.js
CHANGED
|
@@ -346,6 +346,7 @@ export function estimateWavefrontPathTracingMemory(options = {}) {
|
|
|
346
346
|
const queueBytes = tilePixelCapacity * RAY_RECORD_BYTES;
|
|
347
347
|
const hitBytes = tilePixelCapacity * HIT_RECORD_BYTES;
|
|
348
348
|
const accumulationBytes = tilePixelCapacity * ACCUMULATION_RECORD_BYTES;
|
|
349
|
+
const progressiveBytes = options.progressive === true ? width * height * 16 + 16 : 0;
|
|
349
350
|
const pathVertexBytes = tilePixelCapacity * (maxDepth + 1) * PATH_VERTEX_RECORD_BYTES;
|
|
350
351
|
const sceneObjectBytes = sceneObjectCapacity * SCENE_OBJECT_RECORD_BYTES;
|
|
351
352
|
const triangleBytes = allocatedRecordBytes(triangleCapacity, TRIANGLE_RECORD_BYTES);
|
|
@@ -372,7 +373,7 @@ export function estimateWavefrontPathTracingMemory(options = {}) {
|
|
|
372
373
|
const outputConfigSlotCount = deferredPathResolve ? 0 : tileCount;
|
|
373
374
|
const frameConfigSlotCount = Math.max(
|
|
374
375
|
1,
|
|
375
|
-
tileCount * samplesPerPixel + outputConfigSlotCount + (denoise ? 1 : 0)
|
|
376
|
+
tileCount * samplesPerPixel + outputConfigSlotCount + (denoise || options.progressive === true ? 1 : 0)
|
|
376
377
|
);
|
|
377
378
|
const configBufferStride = alignByteSize(
|
|
378
379
|
CONFIG_BUFFER_BYTES,
|
|
@@ -384,6 +385,7 @@ export function estimateWavefrontPathTracingMemory(options = {}) {
|
|
|
384
385
|
1 + bvhSortStageCount + bvhBuildLevelCount
|
|
385
386
|
) * configBufferStride;
|
|
386
387
|
const sceneStorageBufferBindingBytes = Math.max(
|
|
388
|
+
progressiveBytes,
|
|
387
389
|
sceneObjectBytes,
|
|
388
390
|
triangleBytes,
|
|
389
391
|
bvhCombinedBytes,
|
|
@@ -397,6 +399,7 @@ export function estimateWavefrontPathTracingMemory(options = {}) {
|
|
|
397
399
|
queueBytes * 2 +
|
|
398
400
|
hitBytes +
|
|
399
401
|
accumulationBytes +
|
|
402
|
+
progressiveBytes +
|
|
400
403
|
pathVertexBytes +
|
|
401
404
|
sceneObjectBytes +
|
|
402
405
|
triangleBytes +
|
|
@@ -416,6 +419,7 @@ export function estimateWavefrontPathTracingMemory(options = {}) {
|
|
|
416
419
|
queuePairBytes: queueBytes * 2,
|
|
417
420
|
hitBytes,
|
|
418
421
|
accumulationBytes,
|
|
422
|
+
progressiveBytes,
|
|
419
423
|
pathVertexBytes,
|
|
420
424
|
sceneObjectBytes,
|
|
421
425
|
triangleBytes,
|
|
@@ -459,6 +463,7 @@ export function estimateWavefrontPathTracingMemoryForConfig(config, limits = {})
|
|
|
459
463
|
bvhSortStageCount: config.bvhSortStages.length,
|
|
460
464
|
bvhBuildLevelCount: config.bvhBuildLevels.length,
|
|
461
465
|
denoise: config.denoise,
|
|
466
|
+
progressive: config.progressive,
|
|
462
467
|
deferredPathResolve: config.deferredPathResolve,
|
|
463
468
|
minUniformBufferOffsetAlignment:
|
|
464
469
|
limits.minUniformBufferOffsetAlignment ??
|
|
@@ -587,10 +592,15 @@ export function createWavefrontPathTracingComputeConfig(options = {}) {
|
|
|
587
592
|
);
|
|
588
593
|
const deferredPathResolve = resolveDeferredPathResolve(options);
|
|
589
594
|
const strictPhysicalLowSppLighting = resolveStrictPhysicalLowSppLighting(options);
|
|
590
|
-
|
|
595
|
+
// Progressive batches require distinct frame seeds, even when static-frame
|
|
596
|
+
// sample routing was requested by a consumer.
|
|
597
|
+
const transportExperiments = resolveTransportExperiments(options.progressive === true
|
|
598
|
+
? { ...options, "renderer.transport.stableSampleRouting.enabled": false }
|
|
599
|
+
: options, strictPhysicalLowSppLighting);
|
|
591
600
|
|
|
592
601
|
return Object.freeze({
|
|
593
602
|
mode: rendererWavefrontComputeMode,
|
|
603
|
+
progressive: options.progressive === true,
|
|
594
604
|
width,
|
|
595
605
|
height,
|
|
596
606
|
maxDepth,
|
|
@@ -641,6 +651,7 @@ export function createWavefrontPathTracingComputeConfig(options = {}) {
|
|
|
641
651
|
height,
|
|
642
652
|
tileSize,
|
|
643
653
|
samplesPerPixel,
|
|
654
|
+
progressive: options.progressive === true,
|
|
644
655
|
tilePixelCapacity,
|
|
645
656
|
maxDepth,
|
|
646
657
|
sceneObjectCapacity,
|
|
@@ -46,17 +46,19 @@ export function dispatchWavefrontFrame({
|
|
|
46
46
|
frameEncoder.encodeTileOutput(batch.reserve(1), tile, outputConfigOffset, parallelism);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
if (config.denoise) {
|
|
49
|
+
if (config.denoise || config.progressive) {
|
|
50
|
+
const totalSamples = renderedSamplesPerPixel + frameEncoder.getAccumulatedSamples();
|
|
50
51
|
const denoiseConfigOffset = writeFrameConfig(
|
|
51
52
|
{ x: 0, y: 0, width: config.width, height: config.height },
|
|
52
|
-
{ sampleIndex: 0, sampleWeight: 1 /
|
|
53
|
+
{ sampleIndex: 0, sampleWeight: 1 / totalSamples }
|
|
53
54
|
);
|
|
54
|
-
|
|
55
|
+
if (config.progressive) frameEncoder.encodeProgressive(batch.reserve(1), denoiseConfigOffset, parallelism, renderedSamplesPerPixel);
|
|
56
|
+
const denoisePassCount = totalSamples < 4 ? 2 : 1;
|
|
55
57
|
frameEncoder.encodeDenoise(
|
|
56
58
|
batch.reserve(denoisePassCount),
|
|
57
59
|
denoiseConfigOffset,
|
|
58
60
|
parallelism,
|
|
59
|
-
|
|
61
|
+
totalSamples
|
|
60
62
|
);
|
|
61
63
|
}
|
|
62
64
|
frameEncoder.encodePresent(batch.reserve(1));
|
|
@@ -76,7 +78,7 @@ export function dispatchWavefrontFrameAwaitingGpu({
|
|
|
76
78
|
}) {
|
|
77
79
|
const samplePassesPerSample = config.maxDepth + 1 + (config.deferredPathResolve ? 1 : 0);
|
|
78
80
|
const denoisePassCount = config.denoise ? (renderedSamplesPerPixel < 4 ? 2 : 1) : 0;
|
|
79
|
-
const tailPassCount = denoisePassCount + 1;
|
|
81
|
+
const tailPassCount = denoisePassCount + 1 + (config.progressive ? 1 : 0);
|
|
80
82
|
const sampleBatchSize = Math.max(
|
|
81
83
|
1,
|
|
82
84
|
Math.floor(
|
|
@@ -161,19 +163,21 @@ export function dispatchWavefrontFrameAwaitingGpu({
|
|
|
161
163
|
maxFramePassesPerSubmission: config.maxFramePassesPerSubmission,
|
|
162
164
|
startingSubmissionCount: submissionCount,
|
|
163
165
|
});
|
|
164
|
-
if (includeDenoise && config.denoise) {
|
|
166
|
+
if (includeDenoise && (config.denoise || config.progressive)) {
|
|
167
|
+
const totalSamples = renderedSamplesPerPixel + frameEncoder.getAccumulatedSamples();
|
|
165
168
|
const denoiseConfigOffset = writeFrameConfigSlot(
|
|
166
169
|
slot,
|
|
167
170
|
{ x: 0, y: 0, width: config.width, height: config.height },
|
|
168
171
|
frameIndex,
|
|
169
|
-
{ sampleIndex: 0, sampleWeight: 1 /
|
|
172
|
+
{ sampleIndex: 0, sampleWeight: 1 / totalSamples }
|
|
170
173
|
);
|
|
171
174
|
slot += 1;
|
|
175
|
+
if (config.progressive) frameEncoder.encodeProgressive(tail.reserve(1), denoiseConfigOffset, parallelism, renderedSamplesPerPixel);
|
|
172
176
|
frameEncoder.encodeDenoise(
|
|
173
177
|
tail.reserve(denoisePassCount),
|
|
174
178
|
denoiseConfigOffset,
|
|
175
179
|
parallelism,
|
|
176
|
-
|
|
180
|
+
totalSamples
|
|
177
181
|
);
|
|
178
182
|
}
|
|
179
183
|
if (includePresent) {
|
|
@@ -14,6 +14,7 @@ function resolveGetter(valueOrGetter) {
|
|
|
14
14
|
|
|
15
15
|
export function createWavefrontFrameEncoder({
|
|
16
16
|
getConfig,
|
|
17
|
+
progressive,
|
|
17
18
|
getBindGroups,
|
|
18
19
|
pipelines,
|
|
19
20
|
counterBuffer,
|
|
@@ -30,6 +31,12 @@ export function createWavefrontFrameEncoder({
|
|
|
30
31
|
const resolveBindGroups = resolveGetter(getBindGroups);
|
|
31
32
|
|
|
32
33
|
return Object.freeze({
|
|
34
|
+
getAccumulatedSamples() { return progressive?.samples ?? 0; },
|
|
35
|
+
encodeProgressive(encoder, configOffset, parallelism, samples) {
|
|
36
|
+
progressive.encode(encoder, configOffset, samples);
|
|
37
|
+
const config = resolveConfig();
|
|
38
|
+
recordDirectDispatch(parallelism, [Math.ceil(config.width / 8), Math.ceil(config.height / 8)], WORKGROUP_SIZE);
|
|
39
|
+
},
|
|
33
40
|
encodeTileSample(encoder, tile, configOffset, parallelism) {
|
|
34
41
|
const config = resolveConfig();
|
|
35
42
|
const bindGroups = resolveBindGroups();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const PROGRESSIVE_WGSL = `
|
|
2
|
+
@group(0) @binding(45) var<storage, read_write> progressiveHistory: array<vec4<f32>>;
|
|
3
|
+
@group(0) @binding(46) var<uniform> progressiveCounts: vec4<u32>;
|
|
4
|
+
|
|
5
|
+
@compute @workgroup_size(8, 8)
|
|
6
|
+
fn accumulateProgressiveRadiance(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
7
|
+
if (id.x >= config.canvasWidth || id.y >= config.canvasHeight) { return; }
|
|
8
|
+
let pixel = vec2<i32>(id.xy);
|
|
9
|
+
let index = id.y * config.canvasWidth + id.x;
|
|
10
|
+
let batch = textureLoad(denoiseInputRadiance, pixel, 0).xyz;
|
|
11
|
+
let previousCount = f32(progressiveCounts.x);
|
|
12
|
+
let batchCount = f32(progressiveCounts.y);
|
|
13
|
+
// Branch explicitly: discarded history may contain non-finite values after a reset.
|
|
14
|
+
var mean = batch;
|
|
15
|
+
if (progressiveCounts.x > 0u) {
|
|
16
|
+
let previous = progressiveHistory[index].xyz;
|
|
17
|
+
mean = previous + (batch - previous) * (batchCount / (previousCount + batchCount));
|
|
18
|
+
}
|
|
19
|
+
progressiveHistory[index] = vec4<f32>(mean, 1.0);
|
|
20
|
+
textureStore(denoisedRadianceImage, pixel, vec4<f32>(mean, 1.0));
|
|
21
|
+
if (config.denoise == 0u) {
|
|
22
|
+
textureStore(denoisedOutputImage, pixel, vec4<f32>(present_radiance(mean), 1.0));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CONFIG_BUFFER_BYTES } from './wavefront-core.js';
|
|
2
|
+
import { createBuffer } from './wavefront-gpu-resources.js';
|
|
3
|
+
import { assertShaderModuleCompiles, createComputePipeline } from './wavefront-runtime-support.js';
|
|
4
|
+
import { WAVEFRONT_COMPUTE_WGSL } from './wavefront-shaders.js';
|
|
5
|
+
import { PROGRESSIVE_WGSL } from './wavefront-progressive-shader.js';
|
|
6
|
+
|
|
7
|
+
// Accumulate linear, unfiltered radiance. Presentation never feeds back into history.
|
|
8
|
+
export async function createWavefrontProgressiveResources({device, constants, config,
|
|
9
|
+
configBuffer, radianceTexture, radianceView, outputView}) {
|
|
10
|
+
if (!config.progressive) return null;
|
|
11
|
+
const layout = device.createBindGroupLayout({entries:[
|
|
12
|
+
{binding:5,visibility:constants.shader.COMPUTE,buffer:{type:'uniform',hasDynamicOffset:true,minBindingSize:CONFIG_BUFFER_BYTES}},
|
|
13
|
+
{binding:14,visibility:constants.shader.COMPUTE,texture:{sampleType:'float'}},
|
|
14
|
+
{binding:15,visibility:constants.shader.COMPUTE,storageTexture:{access:'write-only',format:'rgba16float'}},
|
|
15
|
+
{binding:18,visibility:constants.shader.COMPUTE,storageTexture:{access:'write-only',format:'rgba8unorm'}},
|
|
16
|
+
{binding:45,visibility:constants.shader.COMPUTE,buffer:{type:'storage'}},
|
|
17
|
+
{binding:46,visibility:constants.shader.COMPUTE,buffer:{type:'uniform'}},
|
|
18
|
+
]});
|
|
19
|
+
const shader=device.createShaderModule({label:'plasius.wavefront.progressiveShader',code:WAVEFRONT_COMPUTE_WGSL+PROGRESSIVE_WGSL});
|
|
20
|
+
await assertShaderModuleCompiles(shader,'plasius.wavefront.progressiveShader');
|
|
21
|
+
const pipeline=await createComputePipeline(device,shader,device.createPipelineLayout({bindGroupLayouts:[layout]}),
|
|
22
|
+
'accumulateProgressiveRadiance','plasius.wavefront.progressive');
|
|
23
|
+
const history=createBuffer(device,constants.buffer.STORAGE,config.width*config.height*16,'plasius.wavefront.progressiveHistory');
|
|
24
|
+
const counts=createBuffer(device,constants.buffer.UNIFORM|constants.buffer.COPY_DST,16,'plasius.wavefront.progressiveCounts');
|
|
25
|
+
const texture=device.createTexture({label:'plasius.wavefront.progressiveRadiance',size:{width:config.width,height:config.height},
|
|
26
|
+
format:'rgba16float',usage:constants.texture.STORAGE_BINDING|constants.texture.COPY_SRC});
|
|
27
|
+
const bindGroup=device.createBindGroup({layout,entries:[
|
|
28
|
+
{binding:5,resource:{buffer:configBuffer,size:CONFIG_BUFFER_BYTES}},
|
|
29
|
+
{binding:14,resource:radianceView},{binding:15,resource:texture.createView()},
|
|
30
|
+
{binding:18,resource:outputView},{binding:45,resource:{buffer:history}},{binding:46,resource:{buffer:counts}},
|
|
31
|
+
]});
|
|
32
|
+
let samples=0;
|
|
33
|
+
return Object.freeze({
|
|
34
|
+
get samples(){return samples;},
|
|
35
|
+
reset(){samples=0;},
|
|
36
|
+
encode(encoder,offset,batchSamples){
|
|
37
|
+
device.queue.writeBuffer(counts,0,new Uint32Array([samples,batchSamples,0,0]));
|
|
38
|
+
const pass=encoder.beginComputePass({label:'plasius.wavefront.progressivePass'});
|
|
39
|
+
pass.setPipeline(pipeline);pass.setBindGroup(0,bindGroup,[offset]);
|
|
40
|
+
pass.dispatchWorkgroups(Math.ceil(config.width/8),Math.ceil(config.height/8));pass.end();
|
|
41
|
+
encoder.copyTextureToTexture({texture},{texture:radianceTexture},{width:config.width,height:config.height,depthOrArrayLayers:1});
|
|
42
|
+
samples+=batchSamples;
|
|
43
|
+
},
|
|
44
|
+
destroy(){history.destroy();counts.destroy();texture.destroy();},
|
|
45
|
+
});
|
|
46
|
+
}
|