D3D12LookDevPT
August 8, 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.
- Built-in PBRT v4 import plus 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, GI, and checkerboard PT backends with official packed reservoir ABIs, validated temporal/spatial reuse, and final current-surface visibility.
- Optional NVIDIA Streamline / DLSS Ray Reconstruction backend with render/output-resolution separation, per-frame constants and resource tags, command-list evaluation, and a native reconstruction fallback. Production evaluation requires an NVIDIA-issued NGX application ID.
- 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 primary/direct path + SurfaceGuides
-> RTXDI ReSTIR DI when selected
-> RTXDI ReSTIR GI or checkerboard PT when selected
-> Diffuse / Specular / Emission-Sky signals
-> NRD REBLUR or RELAX, internal fallback, Off, or DLSS Ray Reconstruction
-> HDR TAA/TAAU + sharpen (bypassed after successful DLSS-RR evaluation)
-> 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 original saved render-mode names remain compatible; PT adds two names:
| 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 one-light direct + RTXDI GI | Baseline PT fallback |
ReSTIR GI + DI | RTXDI DI + RTXDI GI | Baseline PT fallback |
ReSTIR PT | Baseline one-light direct + checkerboard RTXDI PT | Baseline PT fallback |
ReSTIR PT + DI | RTXDI DI + checkerboard RTXDI PT | 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.
- ReSTIR GI and PT each use initial and fused reuse/final-shading passes. GI uses the official 32-byte reservoir ABI; PT uses parity-swapped checkerboard 64-byte reservoirs and is isolated from the GI quality gate.
- DI scratch aliases the current GI/PT placed resource by frame parity, Final TAA output aliases its next A/B history, and the fused NRD/TAA path retains only a 1x1 post-denoise placeholder. An interval-aware placed-resource planner validates non-overlapping lifetimes. The measured 1080p GI+DI frame/history set is 493.44 MiB.
- Static BLAS builds request compaction, read the post-build compacted size, compact-copy before TLAS construction, and release the original BLAS/scratch after initialization.
- 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.
- Interactive Baseline/DI on DXR 1.1 can run an independent Primary Visibility pass, prefix-scan per-pixel SPP into a pixel/sample-ordered
SecondaryTasklist, dispatch a 1D secondary ray workload throughExecuteIndirect, and resolve race-free task results per pixel. Reference Still, RTXDI GI/PT, DXR 1.0, and diagnostic-quality runs retain the full-dispatch megakernel. native, fixed-scale, and budget-driven dynamic render resolutions share display-resolution output resources. Non-DLSS reconstruction uses TAAU while NRD continues to run at render resolution; dynamic scale changes in 1/16 steps after the configured settle hysteresis.- DLSS-RR prepares HDR color, linear depth, motion, packed normal/roughness, albedo, specular albedo, exposure, jitter, and reset state. A successful evaluation bypasses NRD/Internal/Final TAA; a runtime failure discards the feature result, reconstructs natively in that frame, and requests native resource reconstruction for the next frame.
The compact secondary path currently retraces the complete camera sample for each task instead of resuming from the stored primary intersection, so it is a correctness/work-scheduling implementation rather than a claimed speedup. Full SDK-equivalent PT hybrid-shift path replay also remains open. Quality runs record shader-side primary, secondary, shadow, DI/GI/PT visibility, and AnyHit counts; these are deliberately not labeled as hardware BVH-node traversal.
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",
"resolutionMode": "native",
"fixedRenderScale": 1.0,
"minRenderScale": 0.5,
"maxRenderScale": 1.0,
"rayBudget": {
"movingSpp": 1,
"movingBounces": 2,
"staticBaseSpp": 1,
"staticMaxSpp": 2,
"staticBounces": 4,
"settleFrames": 8,
"targetGpuMs": 14.5
},
"finalTaa": true,
"sharpenStrength": 0.0,
"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.resolutionModeacceptsnative,fixed, ordynamic. Old projects without the member load asnative. Fixed/dynamic scales are clamped to the configured range and quantized in 1/16 increments.
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/.
Interactive sharpening is opt-in (sharpenStrength: 0 by default). Nonzero values can amplify residual Monte Carlo variance after temporal reconstruction, so enable it only after validating the target scene and sampling budget.
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. The endpoint serves stateless MCP 2026-07-28 requests alongside the existing session-based 2025-11-25 / 2025-06-18 flow. 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. Modern clients can discover capabilities through server/discover and receive coalesced resource updates through subscriptions/listen. 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 and LocalMCPChatClient configuration, modern and legacy JSON-RPC examples, tools/resources/prompts, subscriptions, screenshots of an MCP-driven camera/denoise workflow, and troubleshooting. LocalMCPChatClient can import config/LocalMCPChatClient.mcp.json, and Scripts/TestLocalMcpChatClientIntegration.ps1 verifies both implementations together.
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/GI/PT with /p:EnableRTXDI=true. If the pinned SDK is missing, that request produces a warning and keeps the Baseline PT fallback build. See Optional NVIDIA RTXDI, 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.
PBRT v4 scenes
.pbrt files use the built-in PBRT v4 lexer/importer; no external pbrt executable is required. The v1 path supports relative Include, static transform and attribute scopes, saved coordinate systems, nested ObjectBegin / ObjectInstance, trianglemesh, Assimp-backed plymesh, perspective cameras, image/constant/simple scale and mix textures, named and inline materials, cutout alpha, and infinite/point/spot/distant/diffuse-area lights. PBRT's left-handed +Z-forward convention and camera/world transform rules are interpreted directly. PBRT v4 equal-area environment maps and their full light transforms are preserved. Existing glTF/GLB/FBX/OBJ imports remain on the Assimp path.
PBRT materials are deterministically approximated by the renderer's metal-rough model. Diffuse, coated diffuse, conductor, coated conductor, dielectric, thin dielectric, and diffuse transmission have explicit mappings; unsupported or non-evaluable graphs fall back to gray rough material with a diagnostic. PNG, JPEG, TGA, HDR, and EXR images are accepted. EXR decoding is provided by the pinned TinyEXR v3 submodule and converts RGB(A) or Y, half or float data to sanitized linear RGBA32F. Initialize it with the other dependencies:
git submodule update --init --recursive
The pbrt-v4-scenes repository and its large assets are intentionally not vendored. Clone it beside this repository, keep its relative asset layout, then load either acceptance scene from the UI, drag and drop, CLI, or MCP scenePath:
pbrt-v4-scenes sample data
The official mmp/pbrt-v4-scenes repository is a collection of example scenes for pbrt-v4. Origins and licenses differ by scene; consult the upstream README and each asset's terms before use or redistribution. The upstream descriptions of the scenes primarily exercised by this renderer are summarized below.
- Barcelona Pavilion models Mies van der Rohe's building with day and night setups. The day scene is illuminated by a realistic sky stored in an HDR environment map. The night scene combines a dark sky with area lights and is challenging because many light paths pass through glass. The model is by Hamza Cheggour and is licensed under CC BY 2.0.
- Bistro is Amazon Lumberyard's detailed Parisian street model, distributed through the NVIDIA Open Research Content Archive under CC BY 4.0.
- BMW M6 is a vehicle model by tyrant monkey from Blend Swap, released as CC0 / Public Domain.
- Contemporary Bathroom is a modern bathroom model by Mareck from Blend Swap, released as CC0 / Public Domain.
- Villa is a modern indoor environment provided by Florent Boyer. The upstream README does not state a per-scene license, so check the current upstream terms before use or redistribution.
Open the top-level .pbrt file in a scene folder. Keep the folder structure intact because geometry.pbrt, materials.pbrt, PLY meshes, EXR maps, and image textures are resolved relative to that entry file. These scenes contain many large PLY assets, so a Release build is recommended for acceptance testing.
git clone --depth 1 https://github.com/mmp/pbrt-v4-scenes.git ..\pbrt-v4-scenes
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\bistro\bistro_cafe.pbrt
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\contemporary-bathroom\contemporary-bathroom.pbrt
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\barcelona-pavilion\pavilion-day.pbrt
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\barcelona-pavilion\pavilion-night.pbrt
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\bmw-m6\bmw-m6.pbrt
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\villa\villa-daylight.pbrt
.\Bin\x64\Release\D3D12LookDevPT.exe --scene ..\pbrt-v4-scenes\villa\villa-lights-on.pbrt
Scene loading reports Parsing, LoadingAssets, BuildingBLAS, and BuildingTLAS; Cancel leaves the previous scene active. Missing includes and required PLY files fail the transaction. Optional missing textures use a fallback and are aggregated in Diagnostics / Stats, which shows counts by category and up to eight representative file/material names.
dielectric computes exact unpolarized Fresnel reflectance from the interface orientation and IOR, then samples mirror reflection or Snell refraction including total internal reflection. thindielectric samples mirror reflection or straight-through transmission with the two-interface Fresnel term. This applies to BMW M6 window/windscreen materials and Villa glass. Shadows and RTXDI inline visibility pass through glass without generating caustics. disk is tessellated into a triangle fan so the Villa lights-on camera-fill area light enters the existing emissive-triangle path. Simple imagemap uscale, vscale, udelta, and vdelta transforms are also applied during material sampling.
PBRT volumes/media, hair/curve, subdivision, motion blur, analytic shapes other than disk, non-perspective cameras, .ply.gz, displacement, full spectral rendering, rough dielectrics, colored absorption, refractive caustics, and complex procedural textures are not supported in v1. Rough dielectric and colored-transmittance inputs produce diagnostics and fall back to smooth/scalar approximations.
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 DI and GI/PT initial/fused stages; denoise prepare, core, and composite; Final TAA; quality counters; history publish; copy; and UI. CPU metrics separate update, MCP, UI construction, command recording, Present, NRD recording, benchmark aggregation, and fence wait. Performance runs retain budget estimates; quality runs additionally report actual shader invocations by ray role and AnyHit.
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. Backend and memory eligibility are reported from the active DI/GI pipelines. The three-run performance window passes in this checkout; full cross-scene temporal/reference quality acceptance remains separate. See Benchmark paths and analysis.
Validated locally in this checkout:
- VS 2022
v143: Debug x64, Release x64. - Debug and Release backend build matrices: all-enabled, no-NRD, no-RTXDI, no-DLSS, and all-disabled.
- RTX 4070 formal ReSTIR GI+DI performance gate after the final reconstruction clamp, three 120-warmup + 300-measured runs: median-p95 run GPU p95 9.919 ms, GPU p99 10.157 ms, CPU-active p95 1.809 ms, and frame/history 493.44 MiB; all runs had active NRD REBLUR/RTXDI GI+DI and zero non-finite pixels.
- Bistro Exterior long-static temporal gate over 32 captured HDR frames: median surface-luminance CV 0.197%, p95 1.430%, and zero NaN/Inf, within the 1%/3% thresholds. Cross-scene reference-energy and edge-width acceptance remains pending.
- MCP socket tests: stateless discovery/routing/cache/error handling, legacy initialize/session/DELETE compatibility, and subscription acknowledgment/filter/coalescing/graceful shutdown.
- Official
@modelcontextprotocol/conformance@0.2.0-alpha.10server suite for2026-07-28, with a strict baseline for fixed-name fixture content and the intentionally out-of-scope MRTR feature family. - VS 2026
v145: Debug x64 and Release x64 with the optional NVIDIA integrations disabled.
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 PBRT/glTF/GLB/FBX/OBJ and Project > Open Environment... for HDRI/environment textures. The scene dialog exposes both an all-supported filter and a dedicated PBRT v4 Scene (*.pbrt) filter.