@plasius/gpu-renderer 0.2.0 → 0.2.2
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 +41 -4
- package/README.md +17 -1
- package/dist/index.cjs +131 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +126 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/index.d.ts +68 -26
- package/src/index.js +5 -0
- package/src/wavefront-compute.js +127 -16
package/CHANGELOG.md
CHANGED
|
@@ -23,18 +23,54 @@ All notable changes to this project will be documented in this file.
|
|
|
23
23
|
- **Security**
|
|
24
24
|
- (placeholder)
|
|
25
25
|
|
|
26
|
-
## [0.2.
|
|
26
|
+
## [0.2.2] - 2026-06-07
|
|
27
|
+
|
|
28
|
+
- **Added**
|
|
29
|
+
- (placeholder)
|
|
30
|
+
|
|
31
|
+
- **Changed**
|
|
32
|
+
- (placeholder)
|
|
33
|
+
|
|
34
|
+
- **Fixed**
|
|
35
|
+
- (placeholder)
|
|
36
|
+
|
|
37
|
+
- **Security**
|
|
38
|
+
- (placeholder)
|
|
39
|
+
|
|
40
|
+
## [0.2.1] - 2026-06-06
|
|
27
41
|
|
|
28
42
|
- **Added**
|
|
29
43
|
- Added deterministic wavefront reference helpers for primary-ray creation,
|
|
30
44
|
triangle-hit evaluation, nearest-hit selection, and environment-miss
|
|
31
45
|
fallback alongside regression tests for task-level acceptance coverage.
|
|
46
|
+
- Added ADR coverage for mesh BVH wavefront path tracing as the display-quality
|
|
47
|
+
baseline.
|
|
32
48
|
|
|
33
49
|
- **Changed**
|
|
34
|
-
-
|
|
50
|
+
- Promoted the mesh BVH wavefront renderer source into the canonical
|
|
51
|
+
`src/wavefront-compute.js` module so source, typings, tests, and package
|
|
52
|
+
builds no longer drift behind generated artifacts.
|
|
53
|
+
- Changed wavefront mesh tracing to dispatch bounce intersection and
|
|
54
|
+
surface-resolution work from GPU-authored active-ray counts instead of the
|
|
55
|
+
fixed tile capacity after queue compaction.
|
|
56
|
+
- Changed the npm CD workflow to prepare package version and changelog
|
|
57
|
+
metadata locally, then publish the validated tag while persisting release
|
|
58
|
+
metadata through an automation PR branch instead of direct protected-main
|
|
59
|
+
pushes.
|
|
35
60
|
|
|
36
61
|
- **Fixed**
|
|
37
|
-
-
|
|
62
|
+
- Fixed wavefront source ownership so display-quality mesh BVH code is not
|
|
63
|
+
hidden behind a legacy module split.
|
|
64
|
+
- Preserved the wavefront mode/workgroup constants, shader-source helper,
|
|
65
|
+
one-shot frame helper, and `renderFrame(...)` compatibility wrapper while
|
|
66
|
+
promoting the mesh BVH renderer source.
|
|
67
|
+
- Fixed a production performance regression where compacted continuation
|
|
68
|
+
queues still scheduled full-capacity per-bounce workgroups.
|
|
69
|
+
- Fixed low-sample wavefront surface traces so terminal non-emissive surface
|
|
70
|
+
collisions use an environment-derived ambient floor instead of a flat or
|
|
71
|
+
missing fallback.
|
|
72
|
+
- Fixed release metadata versioning, demo dependencies, and one-shot
|
|
73
|
+
wavefront cleanup blockers found during PR validation.
|
|
38
74
|
|
|
39
75
|
- **Security**
|
|
40
76
|
- (placeholder)
|
|
@@ -289,4 +325,5 @@ All notable changes to this project will be documented in this file.
|
|
|
289
325
|
[0.1.11]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.1.11
|
|
290
326
|
[0.1.12]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.1.12
|
|
291
327
|
[0.1.14]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.1.14
|
|
292
|
-
[0.2.
|
|
328
|
+
[0.2.1]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.1
|
|
329
|
+
[0.2.2]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.2
|
package/README.md
CHANGED
|
@@ -141,6 +141,10 @@ const renderer = await createWavefrontPathTracingComputeRenderer({
|
|
|
141
141
|
renderer.renderOnce();
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
Existing consumers that still call `renderFrame(...)` or
|
|
145
|
+
`renderWavefrontPathTracingComputeFrame(...)` remain supported as compatibility
|
|
146
|
+
wrappers around the canonical mesh renderer.
|
|
147
|
+
|
|
144
148
|
Analytic scene objects remain available for debug fixtures:
|
|
145
149
|
|
|
146
150
|
```js
|
|
@@ -203,7 +207,12 @@ sampling, temporal accumulation, and better material PDFs are hardened.
|
|
|
203
207
|
For static mesh scenes, the GPU acceleration build is submitted once and then
|
|
204
208
|
reused by subsequent frames. Per-frame tracing writes one dynamic uniform slot
|
|
205
209
|
per tile/sample or post-process pass and batches tile tracing, tile output,
|
|
206
|
-
optional denoise, and presentation into a single command submission.
|
|
210
|
+
optional denoise, and presentation into a single command submission. After each
|
|
211
|
+
primary-ray or compaction pass, the GPU writes the active-ray workgroup count
|
|
212
|
+
into the counter buffer and the encoder copies it into an indirect-dispatch
|
|
213
|
+
argument buffer. Intersection and surface-resolution passes therefore scale
|
|
214
|
+
with active continuation rays instead of the maximum tile capacity, while still
|
|
215
|
+
avoiding CPU readback between bounces. WebGPU
|
|
207
216
|
still preserves ordering between dependent bounce passes, but the renderer no
|
|
208
217
|
longer forces one CPU queue submission per tile/sample.
|
|
209
218
|
Environment-light portals can additionally guide and gate sky/HDRI contribution
|
|
@@ -242,6 +251,8 @@ renderer.bindXrManager(xr, {
|
|
|
242
251
|
- `createRayTracingRenderPlan(options)`
|
|
243
252
|
- `createWavefrontPathTracingComputeRenderer(options)`
|
|
244
253
|
- `createWavefrontPathTracingComputeConfig(options)`
|
|
254
|
+
- `createWavefrontPathTracingComputeShaderSource(options?)`
|
|
255
|
+
- `renderWavefrontPathTracingComputeFrame(options)`
|
|
245
256
|
- `createWavefrontReferenceRay(config, options?)`
|
|
246
257
|
- `intersectWavefrontReferenceTriangle(ray, triangle, options?)`
|
|
247
258
|
- `traceWavefrontReferenceTriangles(config, ray, triangles, options?)`
|
|
@@ -254,6 +265,9 @@ renderer.bindXrManager(xr, {
|
|
|
254
265
|
- `packWavefrontSceneObjects(sceneObjects, capacity?)`
|
|
255
266
|
- `packWavefrontTriangles(triangles, capacity?)`
|
|
256
267
|
- `packWavefrontBvhNodes(nodes, capacity?)`
|
|
268
|
+
- `rendererWavefrontComputeMode`
|
|
269
|
+
- `rendererWavefrontComputeWorkgroupSize`
|
|
270
|
+
- `rendererWavefrontComputeStatsStride`
|
|
257
271
|
- `bindRendererToXrManager(renderer, xrManager, options)`
|
|
258
272
|
- `defaultRendererClearColor`
|
|
259
273
|
- `rendererDebugOwner`
|
|
@@ -298,6 +312,8 @@ npm run pack:check
|
|
|
298
312
|
## Files
|
|
299
313
|
|
|
300
314
|
- `src/index.js`: WebGPU renderer runtime and XR binding helper.
|
|
315
|
+
- `src/wavefront-compute.js`: Canonical WebGPU mesh BVH wavefront renderer,
|
|
316
|
+
debug scene-object fixtures, and deterministic reference helpers.
|
|
301
317
|
- `src/index.d.ts`: public API typings.
|
|
302
318
|
- `tests/package.test.js`: unit tests for renderer lifecycle behavior.
|
|
303
319
|
- `docs/design/worker-manifest-integration.md`: renderer frame-stage DAG model.
|
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ __export(index_exports, {
|
|
|
31
31
|
createWavefrontMeshAcceleration: () => createWavefrontMeshAcceleration,
|
|
32
32
|
createWavefrontPathTracingComputeConfig: () => createWavefrontPathTracingComputeConfig,
|
|
33
33
|
createWavefrontPathTracingComputeRenderer: () => createWavefrontPathTracingComputeRenderer,
|
|
34
|
+
createWavefrontPathTracingComputeShaderSource: () => createWavefrontPathTracingComputeShaderSource,
|
|
34
35
|
createWavefrontPathTracingPlan: () => createWavefrontPathTracingPlan,
|
|
35
36
|
createWavefrontReferenceRay: () => createWavefrontReferenceRay,
|
|
36
37
|
defaultRendererClearColor: () => defaultRendererClearColor,
|
|
@@ -44,11 +45,15 @@ __export(index_exports, {
|
|
|
44
45
|
packWavefrontBvhNodes: () => packWavefrontBvhNodes,
|
|
45
46
|
packWavefrontSceneObjects: () => packWavefrontSceneObjects,
|
|
46
47
|
packWavefrontTriangles: () => packWavefrontTriangles,
|
|
48
|
+
renderWavefrontPathTracingComputeFrame: () => renderWavefrontPathTracingComputeFrame,
|
|
47
49
|
rendererAccelerationStructureUpdateClasses: () => rendererAccelerationStructureUpdateClasses,
|
|
48
50
|
rendererDebugOwner: () => rendererDebugOwner,
|
|
49
51
|
rendererRayTracingStageOrder: () => rendererRayTracingStageOrder,
|
|
50
52
|
rendererRepresentationBands: () => rendererRepresentationBands,
|
|
51
53
|
rendererWavefrontBufferSchemaVersion: () => rendererWavefrontBufferSchemaVersion,
|
|
54
|
+
rendererWavefrontComputeMode: () => rendererWavefrontComputeMode,
|
|
55
|
+
rendererWavefrontComputeStatsStride: () => rendererWavefrontComputeStatsStride,
|
|
56
|
+
rendererWavefrontComputeWorkgroupSize: () => rendererWavefrontComputeWorkgroupSize,
|
|
52
57
|
rendererWavefrontHitTypes: () => rendererWavefrontHitTypes,
|
|
53
58
|
rendererWavefrontPassOrder: () => rendererWavefrontPassOrder,
|
|
54
59
|
rendererWavefrontQueuePairStrategy: () => rendererWavefrontQueuePairStrategy,
|
|
@@ -74,6 +79,9 @@ var DEFAULT_SAMPLES_PER_PIXEL = 1;
|
|
|
74
79
|
var DEFAULT_SCENE_OBJECT_CAPACITY = 128;
|
|
75
80
|
var DEFAULT_ENVIRONMENT_PORTAL_CAPACITY = 32;
|
|
76
81
|
var WORKGROUP_SIZE = 64;
|
|
82
|
+
var rendererWavefrontComputeMode = "webgpu-compute";
|
|
83
|
+
var rendererWavefrontComputeWorkgroupSize = WORKGROUP_SIZE;
|
|
84
|
+
var rendererWavefrontComputeStatsStride = 8;
|
|
77
85
|
var RAY_RECORD_BYTES = 80;
|
|
78
86
|
var HIT_RECORD_BYTES = 208;
|
|
79
87
|
var SCENE_OBJECT_RECORD_BYTES = 96;
|
|
@@ -86,7 +94,9 @@ var EMISSIVE_TRIANGLE_INDEX_BYTES = 4;
|
|
|
86
94
|
var ENVIRONMENT_PORTAL_RECORD_BYTES = 96;
|
|
87
95
|
var ACCUMULATION_RECORD_BYTES = 16;
|
|
88
96
|
var CONFIG_BUFFER_BYTES = 272;
|
|
89
|
-
var
|
|
97
|
+
var COUNTER_DISPATCH_ARGS_OFFSET = 16;
|
|
98
|
+
var INDIRECT_DISPATCH_ARGS_BYTES = 12;
|
|
99
|
+
var COUNTER_BUFFER_BYTES = 32;
|
|
90
100
|
var TRACE_STORAGE_BUFFER_BINDINGS = 9;
|
|
91
101
|
var MATERIAL_DIFFUSE = 0;
|
|
92
102
|
var MATERIAL_METAL = 1;
|
|
@@ -126,7 +136,9 @@ var wavefrontPathTracingComputeLimits = Object.freeze({
|
|
|
126
136
|
emissiveTriangleIndexBytes: EMISSIVE_TRIANGLE_INDEX_BYTES,
|
|
127
137
|
emissiveTriangleMetadataRecordBytes: BVH_NODE_RECORD_BYTES,
|
|
128
138
|
environmentPortalRecordBytes: ENVIRONMENT_PORTAL_RECORD_BYTES,
|
|
129
|
-
accumulationRecordBytes: ACCUMULATION_RECORD_BYTES
|
|
139
|
+
accumulationRecordBytes: ACCUMULATION_RECORD_BYTES,
|
|
140
|
+
counterRecordBytes: COUNTER_BUFFER_BYTES,
|
|
141
|
+
indirectDispatchRecordBytes: INDIRECT_DISPATCH_ARGS_BYTES
|
|
130
142
|
});
|
|
131
143
|
var wavefrontSceneObjectKinds = Object.freeze({
|
|
132
144
|
sphere: OBJECT_KIND_SPHERE,
|
|
@@ -1077,7 +1089,8 @@ function estimateWavefrontPathTracingMemory(options = {}) {
|
|
|
1077
1089
|
environmentPortalBytes,
|
|
1078
1090
|
configBytes: CONFIG_BUFFER_BYTES,
|
|
1079
1091
|
counterBytes: COUNTER_BUFFER_BYTES,
|
|
1080
|
-
|
|
1092
|
+
indirectDispatchBytes: INDIRECT_DISPATCH_ARGS_BYTES,
|
|
1093
|
+
totalHotBufferBytes: queueBytes * 2 + hitBytes + accumulationBytes + sceneObjectBytes + triangleBytes + bvhNodeBytes + bvhLeafReferenceBytes + emissiveTriangleMetadataBytes + environmentPortalBytes + CONFIG_BUFFER_BYTES + COUNTER_BUFFER_BYTES + INDIRECT_DISPATCH_ARGS_BYTES
|
|
1081
1094
|
});
|
|
1082
1095
|
}
|
|
1083
1096
|
function createWavefrontPathTracingComputeConfig(options = {}) {
|
|
@@ -1154,6 +1167,7 @@ function createWavefrontPathTracingComputeConfig(options = {}) {
|
|
|
1154
1167
|
environmentPortals.length > 0
|
|
1155
1168
|
);
|
|
1156
1169
|
return Object.freeze({
|
|
1170
|
+
mode: rendererWavefrontComputeMode,
|
|
1157
1171
|
width,
|
|
1158
1172
|
height,
|
|
1159
1173
|
maxDepth,
|
|
@@ -1208,6 +1222,9 @@ function getGpuUsageConstants() {
|
|
|
1208
1222
|
if (typeof GPUBufferUsage === "undefined" || typeof GPUTextureUsage === "undefined" || typeof GPUShaderStage === "undefined") {
|
|
1209
1223
|
throw new Error("WebGPU runtime unavailable. Required GPU constants are missing.");
|
|
1210
1224
|
}
|
|
1225
|
+
if (typeof GPUBufferUsage.INDIRECT !== "number") {
|
|
1226
|
+
throw new Error("WebGPU runtime unavailable. GPUBufferUsage.INDIRECT is missing.");
|
|
1227
|
+
}
|
|
1211
1228
|
return {
|
|
1212
1229
|
buffer: GPUBufferUsage,
|
|
1213
1230
|
texture: GPUTextureUsage,
|
|
@@ -1844,6 +1861,10 @@ struct Counters {
|
|
|
1844
1861
|
nextCount: atomic<u32>,
|
|
1845
1862
|
terminatedCount: atomic<u32>,
|
|
1846
1863
|
hitCount: atomic<u32>,
|
|
1864
|
+
dispatchX: u32,
|
|
1865
|
+
dispatchY: u32,
|
|
1866
|
+
dispatchZ: u32,
|
|
1867
|
+
dispatchPad: u32,
|
|
1847
1868
|
};
|
|
1848
1869
|
|
|
1849
1870
|
struct Candidate {
|
|
@@ -2006,6 +2027,18 @@ fn gated_environment_radiance(origin: vec3<f32>, direction: vec3<f32>) -> vec3<f
|
|
|
2006
2027
|
return environment_radiance(origin, direction);
|
|
2007
2028
|
}
|
|
2008
2029
|
|
|
2030
|
+
fn terminal_surface_environment_contribution(ray: RayRecord, hit: HitRecord) -> vec3<f32> {
|
|
2031
|
+
let normal = safe_normalize(hit.shadingNormal.xyz, vec3<f32>(0.0, 1.0, 0.0));
|
|
2032
|
+
let surfaceColor = max(hit.color.xyz, config.ambientColor.xyz);
|
|
2033
|
+
let normalEnvironment = gated_environment_radiance(
|
|
2034
|
+
hit.position.xyz + normal * 0.003,
|
|
2035
|
+
normal
|
|
2036
|
+
);
|
|
2037
|
+
let environmentFloor = max(config.ambientColor.xyz, normalEnvironment * 0.12);
|
|
2038
|
+
let materialFloor = select(0.7, 1.0, hit.materialKind == 0u || hit.materialKind == 3u);
|
|
2039
|
+
return clamp_sample_radiance(ray.throughput.xyz * surfaceColor * environmentFloor * materialFloor);
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2009
2042
|
fn default_mesh_range() -> MeshRange {
|
|
2010
2043
|
return MeshRange(
|
|
2011
2044
|
0u,
|
|
@@ -2577,6 +2610,17 @@ fn tone_map_radiance(value: vec3<f32>) -> vec3<f32> {
|
|
|
2577
2610
|
return pow(clamp(mapped, vec3<f32>(0.0), vec3<f32>(1.0)), vec3<f32>(1.0 / 2.2));
|
|
2578
2611
|
}
|
|
2579
2612
|
|
|
2613
|
+
fn ray_workgroups_for_count(rayCount: u32) -> u32 {
|
|
2614
|
+
return max(1u, (rayCount + 63u) / 64u);
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
fn write_active_dispatch_args(activeCount: u32) {
|
|
2618
|
+
counters.dispatchX = ray_workgroups_for_count(activeCount);
|
|
2619
|
+
counters.dispatchY = 1u;
|
|
2620
|
+
counters.dispatchZ = 1u;
|
|
2621
|
+
counters.dispatchPad = 0u;
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2580
2624
|
fn denoise_range_space(value: vec3<f32>) -> vec3<f32> {
|
|
2581
2625
|
return value / (vec3<f32>(1.0) + value);
|
|
2582
2626
|
}
|
|
@@ -2589,6 +2633,7 @@ fn generatePrimaryRays(@builtin(global_invocation_id) globalId: vec3<u32>) {
|
|
|
2589
2633
|
atomicStore(&counters.nextCount, 0u);
|
|
2590
2634
|
atomicStore(&counters.terminatedCount, 0u);
|
|
2591
2635
|
atomicStore(&counters.hitCount, 0u);
|
|
2636
|
+
write_active_dispatch_args(config.tilePixelCount);
|
|
2592
2637
|
}
|
|
2593
2638
|
if (index >= config.tilePixelCount) {
|
|
2594
2639
|
return;
|
|
@@ -2864,9 +2909,9 @@ fn resolveSurfaceRecords(@builtin(global_invocation_id) globalId: vec3<u32>) {
|
|
|
2864
2909
|
}
|
|
2865
2910
|
|
|
2866
2911
|
if (ray.bounce + 1u >= config.maxDepth) {
|
|
2912
|
+
let terminalEnvironment = terminal_surface_environment_contribution(ray, hit);
|
|
2867
2913
|
accumulation[ray.rayId] =
|
|
2868
|
-
accumulation[ray.rayId] +
|
|
2869
|
-
vec4<f32>(ray.throughput.xyz * config.ambientColor.xyz * sample_weight(), 1.0);
|
|
2914
|
+
accumulation[ray.rayId] + vec4<f32>(terminalEnvironment * sample_weight(), 1.0);
|
|
2870
2915
|
atomicAdd(&counters.terminatedCount, 1u);
|
|
2871
2916
|
return;
|
|
2872
2917
|
}
|
|
@@ -2875,6 +2920,10 @@ fn resolveSurfaceRecords(@builtin(global_invocation_id) globalId: vec3<u32>) {
|
|
|
2875
2920
|
let scatter = scatter_direction(ray, hit, seed);
|
|
2876
2921
|
let nextIndex = atomicAdd(&counters.nextCount, 1u);
|
|
2877
2922
|
if (nextIndex >= config.tilePixelCount) {
|
|
2923
|
+
let overflowEnvironment = terminal_surface_environment_contribution(ray, hit);
|
|
2924
|
+
accumulation[ray.rayId] =
|
|
2925
|
+
accumulation[ray.rayId] + vec4<f32>(overflowEnvironment * sample_weight(), 1.0);
|
|
2926
|
+
atomicAdd(&counters.terminatedCount, 1u);
|
|
2878
2927
|
return;
|
|
2879
2928
|
}
|
|
2880
2929
|
let color = clamp(hit.color.xyz, vec3<f32>(0.0), vec3<f32>(1.0));
|
|
@@ -2903,8 +2952,10 @@ fn compactAndSwapQueues(@builtin(global_invocation_id) globalId: vec3<u32>) {
|
|
|
2903
2952
|
return;
|
|
2904
2953
|
}
|
|
2905
2954
|
let nextCount = atomicLoad(&counters.nextCount);
|
|
2906
|
-
|
|
2955
|
+
let activeCount = min(nextCount, config.tilePixelCount);
|
|
2956
|
+
atomicStore(&counters.activeCount, activeCount);
|
|
2907
2957
|
atomicStore(&counters.nextCount, 0u);
|
|
2958
|
+
write_active_dispatch_args(activeCount);
|
|
2908
2959
|
}
|
|
2909
2960
|
|
|
2910
2961
|
@compute @workgroup_size(64)
|
|
@@ -3182,10 +3233,16 @@ async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
3182
3233
|
);
|
|
3183
3234
|
const counterBuffer = createBuffer(
|
|
3184
3235
|
device,
|
|
3185
|
-
constants.buffer.STORAGE | constants.buffer.COPY_DST,
|
|
3236
|
+
constants.buffer.STORAGE | constants.buffer.COPY_DST | constants.buffer.COPY_SRC,
|
|
3186
3237
|
COUNTER_BUFFER_BYTES,
|
|
3187
3238
|
"plasius.wavefront.counters"
|
|
3188
3239
|
);
|
|
3240
|
+
const activeDispatchBuffer = createBuffer(
|
|
3241
|
+
device,
|
|
3242
|
+
constants.buffer.INDIRECT | constants.buffer.COPY_DST,
|
|
3243
|
+
INDIRECT_DISPATCH_ARGS_BYTES,
|
|
3244
|
+
"plasius.wavefront.activeDispatchArgs"
|
|
3245
|
+
);
|
|
3189
3246
|
let packedScene = packWavefrontSceneObjects(config.sceneObjects, config.sceneObjectCapacity);
|
|
3190
3247
|
device.queue.writeBuffer(sceneObjectBuffer, 0, packedScene.buffer);
|
|
3191
3248
|
const packedTriangles = packWavefrontTriangles(
|
|
@@ -3607,24 +3664,34 @@ async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
3607
3664
|
return true;
|
|
3608
3665
|
}
|
|
3609
3666
|
function encodeTileSample(encoder, tile, configOffset) {
|
|
3610
|
-
const
|
|
3611
|
-
label: "plasius.wavefront.
|
|
3667
|
+
const generatePass = encoder.beginComputePass({
|
|
3668
|
+
label: "plasius.wavefront.generatePrimaryRaysPass"
|
|
3612
3669
|
});
|
|
3613
3670
|
const tileWorkgroups = Math.ceil(tile.width * tile.height / WORKGROUP_SIZE);
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3671
|
+
generatePass.setBindGroup(0, bindGroups[0], [configOffset]);
|
|
3672
|
+
generatePass.setPipeline(pipelines.generatePrimaryRays);
|
|
3673
|
+
generatePass.dispatchWorkgroups(tileWorkgroups);
|
|
3674
|
+
generatePass.end();
|
|
3618
3675
|
for (let bounceIndex = 0; bounceIndex < config.maxDepth; bounceIndex += 1) {
|
|
3676
|
+
encoder.copyBufferToBuffer(
|
|
3677
|
+
counterBuffer,
|
|
3678
|
+
COUNTER_DISPATCH_ARGS_OFFSET,
|
|
3679
|
+
activeDispatchBuffer,
|
|
3680
|
+
0,
|
|
3681
|
+
INDIRECT_DISPATCH_ARGS_BYTES
|
|
3682
|
+
);
|
|
3683
|
+
const passEncoder = encoder.beginComputePass({
|
|
3684
|
+
label: `plasius.wavefront.bounce.${bounceIndex}`
|
|
3685
|
+
});
|
|
3619
3686
|
passEncoder.setBindGroup(0, bindGroups[bounceIndex % 2], [configOffset]);
|
|
3620
3687
|
passEncoder.setPipeline(pipelines.intersectActiveQueue);
|
|
3621
|
-
passEncoder.
|
|
3688
|
+
passEncoder.dispatchWorkgroupsIndirect(activeDispatchBuffer, 0);
|
|
3622
3689
|
passEncoder.setPipeline(pipelines.resolveSurfaceRecords);
|
|
3623
|
-
passEncoder.
|
|
3690
|
+
passEncoder.dispatchWorkgroupsIndirect(activeDispatchBuffer, 0);
|
|
3624
3691
|
passEncoder.setPipeline(pipelines.compactAndSwapQueues);
|
|
3625
3692
|
passEncoder.dispatchWorkgroups(1);
|
|
3693
|
+
passEncoder.end();
|
|
3626
3694
|
}
|
|
3627
|
-
passEncoder.end();
|
|
3628
3695
|
}
|
|
3629
3696
|
function encodeTileOutput(encoder, tile, configOffset) {
|
|
3630
3697
|
const passEncoder = encoder.beginComputePass({
|
|
@@ -3767,6 +3834,28 @@ async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
3767
3834
|
luminance: (0.2126 * bytes[0] + 0.7152 * bytes[1] + 0.0722 * bytes[2]) / 255
|
|
3768
3835
|
});
|
|
3769
3836
|
}
|
|
3837
|
+
async function renderFrame(renderOptions = {}) {
|
|
3838
|
+
const frameStats = renderOnce();
|
|
3839
|
+
const probe = renderOptions.readOutputProbe === false ? null : await readOutputProbe(renderOptions.probe);
|
|
3840
|
+
const maxChannel = probe ? Math.max(...probe.rgba.slice(0, 3)) : 0;
|
|
3841
|
+
return Object.freeze({
|
|
3842
|
+
...frameStats,
|
|
3843
|
+
outputProbe: probe ? Object.freeze({
|
|
3844
|
+
...probe,
|
|
3845
|
+
sampledPixels: 1,
|
|
3846
|
+
nonZeroSamples: maxChannel > 0 ? 1 : 0,
|
|
3847
|
+
maxChannel
|
|
3848
|
+
}) : null,
|
|
3849
|
+
bounces: [],
|
|
3850
|
+
termination: Object.freeze({
|
|
3851
|
+
emissive: 0,
|
|
3852
|
+
environment: 0,
|
|
3853
|
+
ambientFallback: 0,
|
|
3854
|
+
maxDepth: 0
|
|
3855
|
+
}),
|
|
3856
|
+
queueOverflow: 0
|
|
3857
|
+
});
|
|
3858
|
+
}
|
|
3770
3859
|
function updateSceneObjects(sceneObjects) {
|
|
3771
3860
|
const nextPackedScene = packWavefrontSceneObjects(sceneObjects, config.sceneObjectCapacity);
|
|
3772
3861
|
packedScene = nextPackedScene;
|
|
@@ -3825,6 +3914,7 @@ async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
3825
3914
|
configBuffer.destroy?.();
|
|
3826
3915
|
bvhBuildConfigBuffer.destroy?.();
|
|
3827
3916
|
counterBuffer.destroy?.();
|
|
3917
|
+
activeDispatchBuffer.destroy?.();
|
|
3828
3918
|
radianceTexture.destroy?.();
|
|
3829
3919
|
denoiseScratchTexture.destroy?.();
|
|
3830
3920
|
outputTexture.destroy?.();
|
|
@@ -3837,12 +3927,32 @@ async function createWavefrontPathTracingComputeRenderer(options = {}) {
|
|
|
3837
3927
|
format,
|
|
3838
3928
|
config,
|
|
3839
3929
|
renderOnce,
|
|
3930
|
+
renderFrame,
|
|
3840
3931
|
readOutputProbe,
|
|
3841
3932
|
updateSceneObjects,
|
|
3842
3933
|
getSnapshot,
|
|
3843
3934
|
destroy
|
|
3844
3935
|
});
|
|
3845
3936
|
}
|
|
3937
|
+
async function renderWavefrontPathTracingComputeFrame(options = {}) {
|
|
3938
|
+
const renderer = await createWavefrontPathTracingComputeRenderer(options);
|
|
3939
|
+
try {
|
|
3940
|
+
return await renderer.renderFrame(options);
|
|
3941
|
+
} finally {
|
|
3942
|
+
renderer.destroy();
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
function createWavefrontPathTracingComputeShaderSource(options = {}) {
|
|
3946
|
+
const workgroupSize = readPositiveInteger(
|
|
3947
|
+
"workgroupSize",
|
|
3948
|
+
options.workgroupSize ?? rendererWavefrontComputeWorkgroupSize,
|
|
3949
|
+
rendererWavefrontComputeWorkgroupSize
|
|
3950
|
+
);
|
|
3951
|
+
if (workgroupSize !== rendererWavefrontComputeWorkgroupSize) {
|
|
3952
|
+
throw new Error(`wavefront mesh compute currently requires workgroupSize=${rendererWavefrontComputeWorkgroupSize}.`);
|
|
3953
|
+
}
|
|
3954
|
+
return WAVEFRONT_COMPUTE_WGSL;
|
|
3955
|
+
}
|
|
3846
3956
|
|
|
3847
3957
|
// src/index.js
|
|
3848
3958
|
var DEFAULT_CLEAR_COLOR = Object.freeze([0.07, 0.11, 0.18, 1]);
|
|
@@ -5143,6 +5253,7 @@ var defaultRendererClearColor = DEFAULT_CLEAR_COLOR;
|
|
|
5143
5253
|
createWavefrontMeshAcceleration,
|
|
5144
5254
|
createWavefrontPathTracingComputeConfig,
|
|
5145
5255
|
createWavefrontPathTracingComputeRenderer,
|
|
5256
|
+
createWavefrontPathTracingComputeShaderSource,
|
|
5146
5257
|
createWavefrontPathTracingPlan,
|
|
5147
5258
|
createWavefrontReferenceRay,
|
|
5148
5259
|
defaultRendererClearColor,
|
|
@@ -5156,11 +5267,15 @@ var defaultRendererClearColor = DEFAULT_CLEAR_COLOR;
|
|
|
5156
5267
|
packWavefrontBvhNodes,
|
|
5157
5268
|
packWavefrontSceneObjects,
|
|
5158
5269
|
packWavefrontTriangles,
|
|
5270
|
+
renderWavefrontPathTracingComputeFrame,
|
|
5159
5271
|
rendererAccelerationStructureUpdateClasses,
|
|
5160
5272
|
rendererDebugOwner,
|
|
5161
5273
|
rendererRayTracingStageOrder,
|
|
5162
5274
|
rendererRepresentationBands,
|
|
5163
5275
|
rendererWavefrontBufferSchemaVersion,
|
|
5276
|
+
rendererWavefrontComputeMode,
|
|
5277
|
+
rendererWavefrontComputeStatsStride,
|
|
5278
|
+
rendererWavefrontComputeWorkgroupSize,
|
|
5164
5279
|
rendererWavefrontHitTypes,
|
|
5165
5280
|
rendererWavefrontPassOrder,
|
|
5166
5281
|
rendererWavefrontQueuePairStrategy,
|