D3D12LookDevPT
July 16, 2026 · View on GitHub
Documentation: English / 日本語
D3D12LookDevPT is a Direct3D 12 / DXR look-development path tracing sandbox. Rasterization is used only for the swapchain copy and ImGui UI. Interactive profiles render the scene with a temporally reconstructed DXR pipeline, while selecting reference_still configures a separate progressive Baseline MIS path for an unclamped high-SPP reference.
This project is being developed with OpenAI Codex and GPT-5.6 Sol.
Preview


The screenshots above use Bistro Exterior and Bistro Interior as local test assets. Large scene assets are not stored in this repository; see Asset Setup for download and placement notes.
Scope
- Direct3D 12 Agility SDK and DXC from NuGet.
- Assimp scene import for static glTF/GLB/FBX/OBJ meshes.
- DirectXTex texture loading for PNG/JPEG/BMP/TGA/DDS/HDR paths and compressed embedded textures extracted by Assimp.
- PBR-oriented material slots: base color, normal, roughness, metallic, occlusion, emissive, alpha mask, texture overrides, material variants, and presets.
- DXR BLAS/TLAS, shader tables, progressive reference accumulation, SurfaceGuides, split lighting signals, debug views, HDR TAA, and contrast-adaptive sharpening.
- Optional NVIDIA NRD REBLUR/RELAX backend with source-built SDK shaders, D3D12 dispatch integration, diffuse/specular radiance and hit-distance inputs, validation views, and internal-denoiser fallback when the SDK or runtime evaluation is unavailable.
- Optional NVIDIA RTXDI v3.0.0 ReSTIR DI backend with packed sample reservoirs, validated temporal/spatial resampling, current-surface visibility/shading, and explicit Baseline PT fallback for ReSTIR GI/PT.
- Optional NVIDIA Streamline / DLSS Ray Reconstruction runtime probe. It loads/registers Streamline and reports support and recommended sizes, but per-frame resource tagging/evaluation is not integrated; selecting it currently uses the internal denoiser.
- Project files saved as
.lookdevpt.json. - A local MCP server for automation via the same validation-oriented action layer used by the UI.
Rendering pipeline and backend status
The normal interactive beauty path is:
DXR path tracing + SurfaceGuides
-> RTXDI ReSTIR DI when available and selected
-> Diffuse / Specular / Emission-Sky signals
-> NRD REBLUR or RELAX, internal fallback, or Off
-> HDR TAA + sharpen
-> tone map
For a diagram-led explanation of why each stage exists, how one pixel's ray path is evaluated, how Surface Guides and history flow between frames, and where to start reading the implementation, see the Rendering Pipeline Learning Guide.
When selected, reference_still configures Baseline MIS, Russian roulette, unclamped float32 accumulation, and tone mapping. RTXDI, contribution compression, denoising, and final TAA are disabled for its final output.
The four saved render-mode names remain compatible, but their current effective implementations are:
| Render mode | Effective implementation when RTXDI DI is available | Without RTXDI |
|---|---|---|
Baseline PT | Baseline direct and indirect MIS | Same |
ReSTIR DI | RTXDI DI + Baseline indirect | Baseline PT fallback |
ReSTIR GI | Baseline direct and indirect; RTXDI ReSTIR GI/PT is not integrated | Baseline PT fallback |
ReSTIR GI + DI | RTXDI DI + Baseline indirect; RTXDI ReSTIR GI/PT is not integrated | Baseline PT fallback |
The current stability and performance-oriented implementation includes:
- Explicit
FrameStaterevisions and history-domain invalidation. Ordinary camera motion preserves reprojection history; camera cuts, projection/resize changes, and geometry changes reset the affected domains. - Fixed A/B SurfaceGuide and identity descriptor tables. Frame parity swaps current/previous resources without copying the three guide textures and identity texture at the end of each frame.
- A two-dispatch ReSTIR DI resolve: Pass A fuses candidate generation with temporal reuse into scratch; Pass B performs adaptive spatial reuse, visibility, shading, and writes next history directly. It uses two physical reservoir buffers and no per-frame reservoir publish copy.
- A 32-byte path payload and a separate 12-byte shadow payload. Material shading remains in RayGen; material feature bits skip absent textures, packed ORM is sampled once, and non-alpha BLAS geometry is marked opaque so traversal can bypass AnyHit.
- Owen-scrambled Sobol sampling with stable dimension assignments, ray-cone texture LOD, split diffuse/specular/emission signals, and secondary hit distance for denoiser input.
- Three frame contexts. The CPU waits only when an in-flight context is reused or during explicit synchronization, and benchmark output reports fence throttling separately from active CPU work.
- On the ordinary NRD Beauty path, final HDR TAA reconstructs HDR directly from NRD diffuse/specular outputs and skips the separate full-screen NRD Composite dispatch. Debug views, quality runs, or TAA-off operation retain the explicit composite path.
Primary visibility is still produced inside the path-tracing RayGen rather than by a separate compact-work-list pass. Secondary one-light MIS, BLAS compaction, actual per-ray/AnyHit hardware counters, RTXDI ReSTIR GI/PT, and DLSS-RR per-frame evaluation remain future work.
Quality profiles and project schema
Project schema v2 stores renderer policy under quality. The same object is accepted by MCP lookdevpt.set_quality; these profile controls do not currently have a dedicated ImGui editor.
{
"schemaVersion": 2,
"mode": "ReSTIR GI + DI",
"quality": {
"qualityProfile": "interactive_game",
"restirBackend": "rtxdi",
"secondaryShadingRate": "auto",
"rayBudget": {
"movingSpp": 1,
"movingBounces": 2,
"staticBaseSpp": 1,
"staticMaxSpp": 2,
"staticBounces": 4,
"settleFrames": 8,
"targetGpuMs": 14.5
},
"finalTaa": true,
"sharpenStrength": 0.15,
"referenceSpp": 4096
}
}
interactive_gameselects REBLUR, temporal reconstruction, adaptive sampling, and the configured moving/static ray budget.sharp_previewselects RELAX and always uses full-rate secondary transport.- Selecting
reference_stillsets Baseline PT, denoiser Off, final TAA Off, full-rate secondary transport, and accumulation up toreferenceSpp. Path-tracing controls remain editable, so reselect the profile or verify them before a reference capture if they were changed afterward. secondaryShadingRateacceptsauto,full, oradaptive_half. The latter two meanings are literal. In Interactiveauto, sustained budget pressure first removes the extra-sample quota and lowers the bounce budget before enabling checkerboard secondary transport; invalid/disoccluded, alpha/coverage, low-roughness, and reactive pixels are promoted to full rate. Non-interactive profiles are forced tofull.
Missing quality members preserve defaults so older projects still load. Schema-v1 denoise.spatialIterations is accepted for one migration window and mapped to atrousPasses; newly saved schema-v2 projects write atrousPasses only. Example Interactive and Reference projects are in projects/.
UI
The app starts at 1920 x 1080. The first frame creates a main ImGui DockSpace with panels for Viewport, Scene, Material, Lighting, Path Tracing, ReSTIR, Denoise, Diagnostics / Stats, and MCP Server. UI text uses an 18 px default font with scaled spacing. The central dock node is pass-through so the DXR output remains visible behind docked tools. The material panel has Properties, Textures, Variants, and Presets tabs for PBR factor edits, texture slot overrides, A/B review snapshots, user presets, and material focus display.
The Window menu toggles every panel independently. Show All Panels reopens them, while Reset Default Layout reopens every panel and rebuilds the default docking layout. Render Only Mode or F10 disables the ImGui menu/panels and skips the GPU UI draw so the DXR output fills the complete client area. Press F10 again to restore the UI.
Diagnostics / Stats shows aggregate GPU path-trace, ReSTIR, denoise, copy, and UI timings; frame/history VRAM; active denoiser; history state; and the effective secondary shading rate. Closed panels skip their content construction, and scene/material usage counts are cached rather than rebuilt every frame.
Changing the display resolution resizes the DXGI swapchain, RTVs, DXR output, accumulation, reservoir, and denoise resources together so ImGui rendering and hit testing stay in sync.
An XInput-compatible gamepad can navigate the rendered scene whenever the app is in the foreground, including in Render Only Mode. The left stick moves, the right stick looks around, LT/RT moves down/up, and either clicking the left stick or holding RB enables fast movement. A newly connected controller is usable immediately with the standard zero-centered XInput stick ranges and radial deadzones. The Scene panel reports the active controller and provides enable, look-speed, Y-axis inversion, and neutral recalibration controls. If unusual hardware drift exceeds the standard deadzone, release both sticks before selecting Recalibrate Gamepad Neutral; Use Standard Center cancels a bad calibration. Trigger thresholds are applied automatically, and keyboard and mouse controls remain available at the same time.
MCP / Action Layer
D3D12PathTracingBackend::ApplyAction(method, params, diagnostics, validateOnly) currently accepts scene, camera, quality, material, lighting, path tracing, ReSTIR, denoise, view, material texture, material variant, material view, and color-management actions. set_camera.historyMode accepts auto, preserve, or reset; set_quality accepts the same quality members shown above.
The dockable MCP Server panel can start a localhost MCP endpoint at http://127.0.0.1:<port>/mcp. The server is disabled by default, uses a bearer token stored in %APPDATA%\D3D12LookDevPT\settings.json, and supports read-only, confirm-mutations, and allow-mutations access modes. MCP mutations are queued onto the main thread before they touch D3D12 or ImGui state.
MCP also exposes project save/load, camera fitting, display resolution changes, reset tools, debug-view capture packs, material texture/variant controls, capture resources, and reusable prompts. When the server is stopped no snapshots are regenerated; while running, dynamic state is capped at 30 Hz, stats at 10 Hz, and material/project catalogs update on revision changes. See MCP Server for VS Code configuration, JSON-RPC examples, tools/resources/prompts, screenshots of an MCP-driven camera/denoise workflow, and troubleshooting.
Build
Clone submodules before building:
git submodule update --init --recursive --depth 1
Check the local setup:
.\Scripts\CheckSetup.ps1
NRD, RTXDI, and DLSS Ray Reconstruction are optional. NRD and DLSS are enabled by default at build time and can be omitted with /p:EnableNRD=false and /p:EnableDLSS=false. RTXDI is disabled by default; enable ReSTIR DI with /p:EnableRTXDI=true. If the pinned SDK is missing, that request produces a warning and keeps the Baseline PT fallback build. ReSTIR GI/PT remains a deliberate Baseline fallback. See Optional NVIDIA RTXDI ReSTIR DI, Optional NVIDIA NRD Backend, and Optional DLSS Ray Reconstruction.
Visual Studio 2026 Insiders:
& "C:\Program Files\Microsoft Visual Studio\18\Insiders\MSBuild\Current\Bin\amd64\MSBuild.exe" .\D3D12LookDevPT.sln /m /p:Configuration=Debug /p:Platform=x64
Visual Studio 2022:
& "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\MSBuild.exe" .\D3D12LookDevPT.sln /m /p:Configuration=Debug /p:Platform=x64
The project auto-selects v145 on VS 2026 and v143 otherwise. Third-party static libraries, including optional NRD when enabled, are built by BuildThirdParty.ps1.
Large sample assets are not stored in this repository. See Asset Setup for download and placement notes. Download Bistro v5.2 or other test scenes separately and place them next to the solution, for example:
D3D12LookDevPT/
Bistro_v5_2/
BistroExterior.fbx
Textures/
Scenes can be loaded at startup for debugging:
.\Bin\x64\Debug\D3D12LookDevPT.exe --scene .\Bistro_v5_2\BistroExterior.fbx
For a recurring initial scene, use startup settings. Project > Save Startup Settings writes the current project / scene / environment to %APPDATA%\D3D12LookDevPT\startup.json, and the app loads it automatically on the next launch. Use Project > Clear Startup Settings to disable it.
Manual example:
{
"version": 1,
"enabled": true,
"baseDirectory": "C:/Projects/D3D12LookDevPT",
"projectPath": "",
"scenePath": "Bistro_v5_2/BistroExterior.fbx",
"environmentPath": "Bistro_v5_2/san_giuseppe_bridge_4k.hdr",
"environmentEnabled": true
}
When projectPath is set, the project is preferred and scenePath is used as a fallback if project loading fails. Relative paths resolve from baseDirectory, or from the startup JSON directory when baseDirectory is empty. Use --startup-config path for another settings file, and --project / --scene / --environment for temporary command-line overrides.
Load diagnostics are appended to %TEMP%\D3D12LookDevPT.log.
Deterministic benchmarks
Use the benchmark CLI with a fixed 1/60-second timestep, camera path, and seed to collect per-pass GPU/CPU timings and reproducible frame artifacts:
.\Bin\x64\Release\D3D12LookDevPT.exe --project .\projects\benchmark_interactive.lookdevpt.json --benchmark --benchmark-kind performance --camera-path .\benchmarks\bistro_exterior_stability.camera.json --frames 300 --warmup 120 --seed 1 --output .\benchmark-output\performance
--benchmark-kind accepts performance, quality, or combined (the compatibility default):
performanceomits the full-resolution quality-counter pass and is the only kind eligible for the official frame-time gate.qualityenables per-tile history-rejection, contribution-energy, disocclusion, TAA-acceptance, and finite-value diagnostics.combinedpreserves the older all-in-one output, but its extra diagnostic work makes it ineligible for the isolated performance gate.
Use --capture-every N to save measured-frame LDR/HDR sequences, and add --capture-aovs to include SurfaceGuides and lighting signals. --capture-aovs requires --capture-every. The output directory contains frames.csv, summary.json, artifacts.json, quality_analysis.json, and final or scheduled image artifacts.
GPU timestamps are split into Path Trace; ReSTIR candidate, temporal, spatial, shade, and publish; denoise prepare, core, and composite; Final TAA; quality counters; history publish; copy; and UI. Because ReSTIR is physically fused into two dispatches, Pass-A time is reported under candidate and Pass-B time under spatial; the retained temporal/shade/publish compatibility metrics should be near zero. CPU metrics separate update, MCP, UI construction, command recording, Present, NRD recording, benchmark aggregation, and fence wait. Ray values currently reported by the benchmark are estimates from resolution, SPP, bounce budget, and active secondary rate, not hardware traversal/AnyHit counters.
The official gate requires an isolated 1920 x 1080 performance run on an RTX 4070 with at least 120 warmup and 300 measured frames, matched delayed timestamps, Interactive Beauty, the prescribed ray budget, active NRD REBLUR, active RTXDI GI + DI, GPU p95 <= 16.7 ms, GPU p99 <= 20 ms, CPU-active p95 <= 4 ms, and frame/history resources <= 512 MiB. RTXDI GI/PT is not integrated yet, so the final combined-backend gate intentionally remains ineligible even when RTXDI DI is active; DI-only results are still useful for A/B analysis. See Benchmark paths and analysis for sequence capture, three-run automation, backend matrices, and temporal-CV analysis.
Validated locally in this checkout:
- VS 2022
v143: Debug x64, Release x64. - MCP HTTP smoke tests: initialize, tools/list, get_stats, resources/read, set_view, capture_viewport.
- The project is configured to select VS 2026
v145when available, but this environment only has VS 2022 installed.
Notes
The first viewport opens on a preview cube so the renderer can be validated before a scene is loaded. Use Project > Open Scene... for glTF/GLB/FBX/OBJ and Project > Open Environment... for HDRI/environment textures.