Document temporal quality captures and 720p costs

This commit is contained in:
Emil
2026-09-24 05:09:39 +03:00
parent 4a3453e2b1
commit 92a29719d2
379 changed files with 1650 additions and 0 deletions
+11
View File
@@ -52,3 +52,14 @@ World transparency and sprites use the scene depth/order and reject stale color
their reactive pixels. TAA and Upscale are optional image-quality paths; compare
them against Off on the actual game scene, especially thin geometry, slow pans,
newly revealed surfaces and moving transparent content.
These are first-generation, opt-in reconstruction modes. They can reduce shimmer
on a stationary edge while lowering the peak brightness of a subpixel line, and
a newly revealed edge can differ by one pixel from its settled appearance. The
amount depends on scene content, resolution and motion. Upscale also trades
internal render resolution for resolve cost and extra images; it is not always
faster. Compare Off, TAA and Upscale at the target output resolution with both
still and moving cameras, and inspect thin objects and opening doors before
choosing a mode for a game. The [P3 temporal validation record](https://github.com/emil28092005/Faset_Engine/blob/main/docs/validation/p3-temporal-2026-09-24/README.md)
contains source captures, paired image measurements and a bounded 720p cost
profile.
+1
View File
@@ -7,6 +7,7 @@ These files preserve bounded checks and their inputs. Each record states its sou
- [P2 GPU visibility Linux evidence](p2-gpu-visibility-2026-09-23/README.md): Debug/Release GPU acceptance, lavapipe functional checks, relocated Player exports, and explicit platform/performance limits.
- [P2 pinned SwiftShader compatibility](p2-swiftshader-2026-09-23/README.md): the Windows CI regression, shader capability fix, independent review closure, final native CI and relocated Player evidence.
- [P3 lighting and shadows](p3-lighting-2026-09-24/README.md): implementation, Forward+ A/B and image parity, acceptance matrix, bounded Linux evidence, and remaining Windows/platform checks; temporal reconstruction is tracked separately.
- [P3 temporal reconstruction](p3-temporal-2026-09-24/README.md): Off/TAA/Upscale source captures, edge and reveal measurements, and bounded 720p costs.
- [Windows software Vulkan](windows-software-vulkan-2026-09-18/README.md): fresh native build, 35 tests, launcher/window/MCP workflows and both relocated Release games on SwiftShader.
- [Checkpoint 5 Linux acceptance](checkpoint5-linux-2026-09-18/README.md): clean offline source build, first Editor launch, exact-candidate standalone games and live Blender checks.
- [Final Linux source checks](final-linux-2026-09-18/README.md): `4cb8255` integrated test results and both Release games after the asset-relocation correction, including package manifests and standalone captures.
@@ -0,0 +1,119 @@
# P3 temporal reconstruction: image quality and cost, 2026-09-24
This record covers Faset's first-generation, opt-in TAA and temporal upscaler.
The temporal shader source under test is
`1a1f69f7e88b3ea69986931dfcf6baf9b43a431c` on
`feat/p3-temporal-integration`; the combined integration source revision is
`4a3453e`. Final CI results are tracked with that integration branch. The
physical Vulkan device was an
NVIDIA GeForce RTX 2080 Ti with proprietary driver 595.84 on Linux. Both
fixtures requested Vulkan validation and every recorded frame reported zero
validation errors. These observations do not establish physical Windows GPU
behavior or high-end reconstruction quality.
## Raw artifacts and method
- [Lossless PNG example](captures/wire-static-taa-15.png) and
[frame-level CSV linking every capture](frames.csv) cover
the Direct visibility path at 160×120, except the 319×241 resize frame.
The sequences are static subpixel wire (16 phases), slow camera pan (16),
moving cube (16), unobstructed background (16), opening door (4), camera cut
(2), resize (2), and translucent world geometry plus sharp UI (2). Each has
Off, jittered current-only TAA, accumulated TAA, current-only Upscale, and
accumulated Upscale captures. The current-only controls mark each frame as a
camera cut: they retain the same 16-phase jitter and internal extent while
rejecting history. Upscale uses render scale 0.67. Off has no jitter.
- [Computed metrics](metrics.json) contain every sample, fixed ROI coordinates,
steady-state timing distributions and paired image errors. The
[contact sheet](contact-sheet.png) shows representative source frames without
artistic retouching. The [door edge detail](door-edge-nearest-5x.png) crops
phase 3 and enlarges pixels 5× with nearest-neighbor sampling; its second row
is the same-jitter unobstructed reference.
`tools/analyze_temporal_quality.py` converts the raw PPM output of
`faset_render_temporal_acceptance_tests --capture-quality DIR` to PNG
losslessly and computes the metrics. It needs Python with NumPy and Pillow.
- [720p raw profile](profile-720p-debug.csv) contains 30 measured frames per
Off/TAA/Upscale mode after 10 warm-up frames, with rotating mode order.
`faset_render_temporal_acceptance_tests --profile-720p CSV` reproduces this
fixed Direct scene: one opaque cube and one thin wire, output 1280×720,
Upscale internal 858×483. It was a Linux Debug run with validation requested,
not a Release or gameplay frame-rate result. GPU timestamps include submitted
work and the synchronous image-to-buffer capture; renderer CPU time includes
the wait and host readback.
Reproduction from a configured build:
```sh
cmake --build build/linux-debug --target faset_render_temporal_acceptance_tests --parallel 2
ctest --test-dir build/linux-debug --no-tests=error -R '^render_temporal_acceptance$' --output-on-failure
build/linux-debug/faset_render_temporal_acceptance_tests --capture-quality /tmp/faset-p3-quality
python3 tools/analyze_temporal_quality.py --input /tmp/faset-p3-quality \
--output docs/validation/p3-temporal-2026-09-24 \
--revision 1a1f69f7e88b3ea69986931dfcf6baf9b43a431c \
--driver 'NVIDIA proprietary 595.84'
build/linux-debug/faset_render_temporal_acceptance_tests --profile-720p /tmp/faset-p3-720p.csv
```
## Image-quality observations
The static variation measure is the mean absolute RGB difference between
consecutive frames over phases 5–15 in the fixed ROI; lower means less frame
shimmer, but it says nothing by itself about retained contrast. Wire energy is
the mean summed RGB value over phases 4–15 in that ROI, and peak is the mean
brightest channel per frame. All color figures use 8-bit output values.
| 160×120 fixture | Current-only | Accumulated | Change |
| --- | ---: | ---: | ---: |
| Static wire RGB frame delta, TAA | 0.388 | 0.360 | −7.2% |
| Static wire RGB frame delta, Upscale | 0.439 | 0.412 | −6.1% |
| Static wire ROI RGB energy, TAA | 8,234 | 8,275 | +0.5% |
| Static wire ROI RGB energy, Upscale | 7,429 | 7,485 | +0.8% |
| Static wire mean peak, TAA | 179 | 167 | −6.7% |
| Static wire mean peak, Upscale | 179 | 161 | −9.9% |
| Slow pan RGB frame delta, TAA | 0.399 | 0.398 | −0.2% |
| Moving cube RGB frame delta, TAA | 1.930 | 1.917 | includes real motion |
The separate static cube-edge acceptance ROI fell from 0.832 jittered
current-only to about 0.739 under TAA. Its exact percentage does not transfer
to the thin wire. The original resolver achieved a much larger apparent wire
variance reduction by dimming the wire about 15%; the final depth-aware
resolver retains total wire energy within 1% in this fixture. It still reduces
peak contrast and offers little gain during a slow pan. Upscale is not
equivalent to a full-resolution reference for thin detail.
Off has zero static frame variation because it has no jitter; that does not
make its edges alias-free.
The door's newly exposed center matched current-only within one RGB value on
the first open frame. No red pixels from the old door appeared in the tested
old-door ROI. Against a phase-aligned, unobstructed temporal background, the
30×35 edge ROI had 121 TAA and 176 Upscale pixels with any channel difference
above 8 on the first open frame, then 17 and 28 respectively on the next frame.
The enlarged comparison shows a one-pixel dark green/top-bottom edge
difference, with no displaced red silhouette. It is a bounded residual, not a
claim of zero halo. The explicit cut output matched
current-only exactly in its ROI; resize and UI pixels matched their controls.
The existing Direct, GPU-frustum and GPU-occlusion tests separately cover
moving reveal, cut, reset, resize, shader reload and Vulkan validation.
## 1280×720 cost on this sparse scene
All values below are milliseconds except allocation. p95 is linearly
interpolated at rank `(n − 1) × 0.95` among the 30 measured frames.
| Mode | Full GPU p50 / p95 | Resolve p50 / p95 | Composite p50 / p95 | Renderer CPU p50 / p95 | Live Vulkan allocation |
| --- | ---: | ---: | ---: | ---: | ---: |
| Off | 0.560 / 0.580 | — | — | 2.256 / 2.527 | 43.02 MiB |
| TAA | 0.671 / 0.715 | 0.081 / 0.101 | 0.026 / 0.028 | 2.545 / 2.927 | 76.77 MiB (+33.75) |
| Upscale 0.67 | 0.672 / 0.703 | 0.079 / 0.099 | 0.025 / 0.027 | 2.630 / 3.448 | 68.52 MiB (+25.50) |
Main raster p50 was only 0.015–0.018 ms because this fixture is sparse; at
this resolution and content, lower scene resolution did not pay for the output
resolve/composite. The depth-aware 2×2 history sampling is included in these
costs. A dense game scene, Release build, another driver or display path may
have different results. The renderer's synchronous full-frame capture makes
these CPU and GPU totals unsuitable as unqualified gameplay FPS predictions.
TAA and Upscale therefore remain opt-in. Compare Off and a jittered
current-only capture at the game's target resolution, watch thin-object peak
contrast and newly revealed edges, and profile the whole frame. These fixtures
are a bounded regression check, not parity with Unreal TSR, FSR or DLSS.
Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Some files were not shown because too many files have changed in this diff Show More