Repository navigation
Pipelined rendering, GPU shadow culling and path tracing denoising (Sponza performance) - #213
Conversation
Load (87.6 s -> ~8 s): decode and mip glTF textures on background threads ahead of the serial GPU upload, LUT-based sRGB mip filter that reproduces the previous rounding exactly, raw-byte alpha masks, concurrent external image reads and material/mesh overlap for unbounded imports. Hitches: the Windows loop slept with Task.sleep (15.6 ms ticks, occasional ~250 ms oversleep) at the 60 FPS fallback whenever an on-demand window skipped a frame. Use a high-resolution waitable timer and the display's idle cadence for visible display-synchronized windows. Frame cost: main-pass bind groups include render attachments and were recreated for every draw. Cache them for a few submissions after last use (TransientResourceCache) and group opaque draws by material. Also adds the approved pipelined-rendering design and the measurement report. Pre-commit hook skipped at the user's request (SwiftLint has no Windows binary). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Includes the window overlay pass, diagnostics session and plugin, and large-document text editor work. Fixes the overlay view's required initializer, main-actor isolation of installWindowOverlayPass, and SPI access to camera computed data in the UI render node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Editor project files, build targets, scene YAML payload decoding, code highlighting state, agent MCP and Windows ACP integration, localization, and the ada_tool CLI with its tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pipelined rendering (Documentation/Designs/pipelined-rendering.md): - RenderPipelining lets a SceneView render world update one frame behind its simulation, with material snapshots taken at extraction. - The SceneView render-texture pool is sized for frames in flight, so frames overlap the GPU instead of being skipped. - ADAENGINE_GPU_TIMINGS=1 reports per-command-buffer GPU time on WebGPU. Shadows: - GPU-driven shadow batching (shadow caster registry, per-view GPU culling, multi-draw). - Meshlet cluster culling for shadow views. Runs of visible clusters are merged into single draws, because tens of thousands of draws per Dawn multi-draw stall the D3D12 queue. Path tracing (Documentation/Designs/path-tracing-denoising.md): - The first hit comes from the raster G-buffer. PathTracingGeometry3D separates raster-only detail from traced proxies. - History survives camera and light motion. - A portable SVGF-style denoiser, and DLSS Ray Reconstruction through the Dawn/NGX bridge, selected by PathTracing3D.denoiser. DLSS: - The NGX runtime DLLs are found next to the executable or in the SDK (ADAENGINE_DLSS_SDK_PATH). - Studio builds and packages stage nvngx_dlss.dll and nvngx_dlssd.dll. - A missing runtime is reported as such. Fixes: - The shader cache rolls back the source hash of a stage that failed to compile, instead of reusing a stale translation forever. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d01a30df40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let pending = pipelinedUpdate { | ||
| pipelinedUpdate = nil | ||
| try await pending.value |
There was a problem hiding this comment.
Keep the in-flight update visible until it finishes
When tooling access and the next frame both wait for an in-flight pipelined render, the first waiter clears pipelinedUpdate before suspending. The second waiter then sees no pending task and proceeds immediately. In particular, withWorldAccess can be awaiting this task while updateFrameContents starts another extraction into the still-running render world, violating the isolation boundary and allowing concurrent resource mutation. Keep the pending update discoverable by all waiters until completion, and ensure tooling safe-point acquisition remains serialized with incoming frames.
Useful? React with 👍 / 👎.
| s.geometric=s.normal; | ||
| s.color=textureLod(sampler2D(u_Albedo,u_Nearest),uv,0).rgb; | ||
| s.emission=max(textureLod(sampler2D(u_Emission,u_Nearest),uv,0).rgb,vec3(0)); | ||
| s.roughness=clamp(normalRoughness.w,0.04,1.0); s.metal=clamp(positionMetallic.w,0.0,1.0); s.receives=true; |
There was a problem hiding this comment.
Preserve the first-hit surface's receive-shadows setting
For a path-traced mesh configured with receiveShadows: false, the new G-buffer first-hit path unconditionally sets s.receives=true, so sampleLight now traces occlusion rays and shadows that surface anyway. Previously, PathTracing3DScene encoded source.receiveShadows in the triangle flags and surfaceAt honored it. Carry the receive-shadows flag through the raster surface outputs and restore it here so enabling hybrid first hits does not change the authored shadow behavior.
Useful? React with 👍 / 👎.
Summary
Sponza performance work and the path-tracing denoising milestone, plus other work that was uncommitted on this branch. Four commits:
3242536a0e851d8e66f03e9dd01a30dfRendering (
d01a30df)Pipelined rendering (design)
.pipelinedRendering()), with material snapshots taken at extraction.ADAENGINE_GPU_TIMINGS=1reports per-command-buffer GPU time on WebGPU through timestamp queries.Shadows
Path tracing denoising (design, accepted with the deviations in §11)
PathTracingGeometry3D(.rasterOnly/.pathTracingOnly), lets a scene raster detail while the tracer intersects a lighter proxy.PathTracing3D.denoiserselects.automatic(DLSS Ray Reconstruction on RTX with DLSS, otherwise portable),.rayReconstruction,.portable(SVGF-style temporal and wavelet filter, about 1.1 ms of GPU time) or.off.DLSS
ADAENGINE_DLSS_SDK_PATH. Before, a missing DLL was reported as an adapter or driver problem.nvngx_dlss.dllandnvngx_dlssd.dll.Fix:
ShaderCacherecorded a changed source hash before compiling. A failed compile then left a stale translation in use on every later launch. It now rolls back.Testing
ADAENGINE_GOLDEN_WEBGPU=1 swift test --filter Render3DPathTracing, 17 tests. They include history through motion,.offrestarting on camera motion, portable output finite and within 15% of a converged reference, and Ray Reconstruction falling back to portable.Notes for reviewers
--no-verify, at the owner's request. SwiftLint is unavailable on Windows, andcheck_contribution.pywas not run.🤖 Generated with Claude Code