Merge commit '0c96ce5cdfde8503e1ffc3fd65fdc9d7f3793d35' into feat/p1-p3-integration
# Conflicts: # PLAN.md # docs/IMPLEMENTATION.md # docs/manual/editor/diagnostics.md # docs/manual/editor/lighting.md # docs/manual/editor/profiling.md # docs/validation/README.md # docs/validation/p3-lighting-2026-09-24/README.md
This commit is contained in:
@@ -520,6 +520,41 @@ real-diagnostic-navigation assertion still awaits its Windows CI result.
|
||||
Windows had no active Khronos validation layer, and no physical Windows GPU
|
||||
performance result is claimed.
|
||||
|
||||
## P3 lighting checkpoint — authored lights and bounded shadow views
|
||||
|
||||
At source revision `b191ae0`, the versioned `faset.light` schema and SceneView
|
||||
extract directional, point, and spot lights. Any authored Light, even disabled,
|
||||
suppresses the compatibility sun; scenes without a Light keep their previous
|
||||
appearance. The renderer validates all local records, then selects at most 128
|
||||
by priority, projected influence, and stable ID. A single typed lighting
|
||||
descriptor ABI serves Direct and P2 GPU graphics: materials remain set 0,
|
||||
lighting is set 1, GPU scene graphics data moves to set 2, and existing push
|
||||
constant sizes remain unchanged. Both paths shade the same sun/local PBR lights
|
||||
before tone mapping.
|
||||
|
||||
A pure CPU shadow planner builds up to four texel-snapped sun cascades from an
|
||||
explicit camera frustum, ending at at most 80 world units; a low-level Snapshot
|
||||
without the frustum keeps one shadow view. Shadow caster bounds come from the
|
||||
source LOD-0 draw and are tested against the light view, independently of
|
||||
camera/P2 culling. The Vulkan backend renders the sun to its own D32 atlas and
|
||||
point/spot shadows to a separate 4×4 D32 atlas. A point light claims six faces
|
||||
atomically, a spot one. Both atlases try 2048² and then 1024² if required by
|
||||
capabilities or allocation. The combined frame budget is 4096 caster draws;
|
||||
scheduled tiles are cleared and redrawn each frame. Overflow, disabled shadow,
|
||||
or unavailable atlas leaves a submitted light illuminating without shadow.
|
||||
There is no hidden sun raster when the sun is absent, its shadow is disabled, or
|
||||
the scene only has sprites. Atlas ownership, dropout, submitted light counts,
|
||||
actual raster work and GPU timings are exposed in `FrameStats`, Player profiles
|
||||
and the optional Editor diagnostics overlay.
|
||||
|
||||
The implementation's Linux Debug checkpoint at `a5fb216` built all targets and
|
||||
ran 60 CTests with no failures; the existing native window lifecycle test
|
||||
skipped under the compositor. The optional ImGui overlay passed its dedicated
|
||||
test in an enabled build. After benchmark integration at `b191ae0`, six focused
|
||||
tests passed, including the real Vulkan benchmark smoke. These are bounded
|
||||
checks, not a final P3 acceptance run. The [lighting validation record](validation/p3-lighting-2026-09-24/README.md)
|
||||
lists cases, exact revision, and remaining Windows/Release evidence.
|
||||
|
||||
The fixed-scene Release reference-GPU sweep uses 1920×1080, 0/4/16/32/64/128
|
||||
lights, Direct/GPU frustum/GPU occlusion, shadows on/off, three independent
|
||||
repeats, ten warm-up and thirty measured frames per configuration. It reached
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
@@ -35,6 +35,12 @@ On Windows, use `windows-debug` for both presets and `build/windows-debug/faset_
|
||||
|
||||
Use the **Visibility** selector to compare **Direct**, **GPU frustum**, and **GPU occlusion** on the same open scene. This is a live renderer setting for the Editor viewport; it does not change the scene or exported game. The selected mode is independent of **Freeze counters**. The counters describe the previous completed frame, so render one more frame after changing modes before reading them. **Effective path** names the algorithm that actually ran. A **Fallback from** line appears when device or target capabilities prevent the selected mode; for example, GPU occlusion may use GPU frustum if HZB is unavailable.
|
||||
|
||||
Use the **Temporal** selector for **Off**, **TAA**, or **Upscale**. Upscale shows a
|
||||
50–99% render-scale slider; output UI remains sharp. The requested/effective
|
||||
mode, fallback reason, internal extent, history reset reason and temporal GPU
|
||||
pass times are shown separately from visibility and HZB history. This selector
|
||||
only changes the live Editor viewport. See [Temporal rendering](temporal.md).
|
||||
|
||||
The panel reports the previous completed frame: renderer wall time, GPU timestamp time where available, synchronous readback time, draw calls, packed vertices, culled meshes, textures, explicit Vulkan allocation sizes, actual validation availability/errors, and GPU pass-label count. It also shows whether GPU visibility ran, submitted indirect bins, visible instances, frustum rejects, deferred and post-pass visible instances, HZB history validity, counts per prepared LOD level, and GPU pass timings where available. GPU counts are explicitly marked unavailable until the first frame rendered with diagnostics open; only a displayed zero is a measured zero. **Previous HZB history: invalid** is expected after a camera cut or resize until compatible depth history is available. A current HZB preview can still exist after that first frame because it was built from the current depth. Renderer wall time includes waiting for GPU work; it is not thread CPU usage. Memory excludes driver-internal allocations. The overlay itself adds drawing work, so hide it for a baseline performance measurement.
|
||||
|
||||
In **GPU occlusion** mode, enable **Show HZB** to inspect the current grayscale depth pyramid. The **Mip** slider selects a pyramid level; the preview starts at mip 3 to keep its readback small. A larger mip number shows coarser depth. The preview reads the HZB only while the panel and toggle are open, and only once per completed frame or mip change. Switching it off or closing the panel releases the preview; its GPU texture retires when the next frame begins. Opening diagnostics also enables readback of GPU visibility counters, which is disabled again when the panel closes. Disable the HZB preview for performance comparisons: its diagnostic copy and texture upload add GPU and CPU work. **Freeze counters** does not freeze the HZB image.
|
||||
|
||||
@@ -147,6 +147,32 @@ and reads back the full image, so `cpu_ms` is wall time including waits, not CPU
|
||||
utilization. An open scene can run slower with HZB; visibility correctness and
|
||||
full-frame speed are separate findings.
|
||||
|
||||
## Compare temporal modes
|
||||
|
||||
Use one scene, output resolution, camera sequence, visibility path, binary and GPU
|
||||
for Off, TAA and Upscale. Run enough frames to include both the first-frame reset
|
||||
and steady-state accumulation. Keep the raw captures as well as timing samples:
|
||||
|
||||
```sh
|
||||
./faset_player --headless --frames 240 --profile off.json --temporal off
|
||||
./faset_player --headless --frames 240 --profile taa.json --temporal taa
|
||||
./faset_player --headless --frames 240 --profile upscale.json \
|
||||
--temporal upscale --render-scale 0.67
|
||||
```
|
||||
|
||||
The profile records requested and effective temporal modes, fallback and history
|
||||
reset reason, internal/output extent, jitter, and valid previous-transform count
|
||||
per completed frame. `gpu_temporal_resolve_ms`, `gpu_temporal_composite_ms`, and
|
||||
`gpu_ui_ms` are separate submitted GPU pass times when timestamp queries work;
|
||||
otherwise they are `null`. `gpu_allocated_bytes` includes live temporal targets
|
||||
and histories, subject to the allocation limits described above. Compare full
|
||||
frame GPU and renderer wall time too: scene raster savings can be offset by
|
||||
resolve, memory and synchronous readback. A valid frame-level history flag says
|
||||
the previous frame may be sampled, not that every pixel accepted it. For image
|
||||
quality, inspect a still thin edge, a slow pan and a newly uncovered surface, and
|
||||
compare the same frame against Off. See [Temporal rendering](temporal.md) for
|
||||
mode controls and native C++ configuration.
|
||||
|
||||
## Measure P3 lighting and shadows
|
||||
|
||||
A Player `--profile` sample includes `effective_lighting_path`, local lights
|
||||
@@ -216,9 +242,11 @@ raw frames, shader hashes, and the decision.
|
||||
|
||||
The accepted MVP path uses direct draws and CPU culling; P2 adds optional GPU
|
||||
visibility for opaque static meshes, with prepared LODs supplied by the project.
|
||||
Both paths currently use one graphics queue and synchronous full-image
|
||||
capture/readback. Use measurements to find the next bottleneck before introducing
|
||||
parallel jobs or expanding GPU-driven rendering. Neither an offscreen capture
|
||||
benchmark nor a tiny demo is a promise of a production frame budget. Observed
|
||||
measurements and follow-up targets belong in the implementation acceptance report
|
||||
with their source revision and method.
|
||||
P3 adds local lights and bounded sun/local shadow atlases. The benchmark's
|
||||
`lighting_path` and a Player profile's `effective_lighting_path` identify the
|
||||
algorithm actually used. Both paths currently use one graphics queue and
|
||||
synchronous full-image capture/readback. Use measurements to find the next
|
||||
bottleneck before introducing parallel jobs or expanding GPU-driven rendering.
|
||||
Neither an offscreen capture benchmark nor a tiny demo is a promise of a
|
||||
production frame budget. Observed measurements and follow-up targets belong in
|
||||
the implementation acceptance report with their source revision and method.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Temporal rendering
|
||||
|
||||
Faset renders the scene with **Off** by default. In the optional Editor diagnostics
|
||||
panel (**F12**), choose **TAA** to accumulate a full-resolution scene over successive
|
||||
frames, or **Upscale** to render the scene at a lower resolution and reconstruct it
|
||||
at the output resolution. The Upscale slider accepts 50–99%; 67% is a useful
|
||||
starting point for visual comparison. UI text and controls always render at output
|
||||
resolution after the scene resolve. Shadow maps keep their own unjittered views.
|
||||
|
||||
The diagnostic selector affects only the current Editor viewport. It does not edit
|
||||
the scene, gameplay code, or an exported Player. The panel's **Requested** and
|
||||
**Effective** fields identify a device fallback. It also shows internal and output
|
||||
extent, whether the previous completed frame's color history was eligible, the
|
||||
reason it reset, and separate GPU times for resolve, composite and UI where
|
||||
timestamp queries are available. A reset on the first frame, camera cut, changed
|
||||
view, resize, scale switch or compatible shader reload is expected. A valid history
|
||||
does not imply every pixel reused it: newly visible surfaces can still reject
|
||||
their individual history samples.
|
||||
|
||||
For a Player or exported game, select the mode at launch:
|
||||
|
||||
```sh
|
||||
./faset_player --headless --frames 120 --temporal taa --profile taa.json
|
||||
./faset_player --headless --frames 120 --temporal upscale \
|
||||
--render-scale 0.67 --profile upscale.json
|
||||
```
|
||||
|
||||
`--temporal` accepts `off`, `taa`, or `upscale`. Off and TAA use scale `1`; Upscale
|
||||
requires a scale from `0.5` inclusive to `1` exclusive. An invalid mode or scale
|
||||
stops startup with an error. If Vulkan compute or the required image formats are
|
||||
unavailable, the renderer falls back to Off and records its effective mode and
|
||||
reason in the profile. Direct, GPU frustum and GPU occlusion visibility can be
|
||||
combined with either temporal mode. See [Profiling](profiling.md) for how to compare
|
||||
their timings fairly.
|
||||
|
||||
Native renderer users can make the same choice without modifying gameplay scripts:
|
||||
|
||||
```cpp
|
||||
faset::render::RendererConfig config;
|
||||
config.temporal_mode = faset::render::TemporalMode::Upscale;
|
||||
config.render_scale = 0.67f;
|
||||
faset::render::Renderer renderer(config);
|
||||
|
||||
// A live viewport switch recreates scene targets and resets color history.
|
||||
renderer.set_temporal_mode(faset::render::TemporalMode::TAA);
|
||||
```
|
||||
|
||||
Provide a stable `DrawItem::instance_key` for moving opaque objects so the renderer
|
||||
can find their previous model transform. Camera cuts must be marked in the
|
||||
`Snapshot`; cuts, teleports and incompatible projection changes reject old history.
|
||||
World transparency and sprites use the scene depth/order and reject stale color on
|
||||
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.
|
||||
@@ -0,0 +1,12 @@
|
||||
Test project /home/emil/Desktop/.worktrees/Faset_Engine-p3-lighting/build/linux-debug
|
||||
Start 9: render_lighting_policy
|
||||
1/2 Test #9: render_lighting_policy ............. Passed 0.04 sec
|
||||
Start 17: render_lighting_benchmark_schema
|
||||
2/2 Test #17: render_lighting_benchmark_schema ... Passed 4.95 sec
|
||||
|
||||
100% tests passed, 0 tests failed out of 2
|
||||
|
||||
Label Time Summary:
|
||||
p3 = 4.99 sec*proc (2 tests)
|
||||
|
||||
Total Test time (real) = 5.00 sec
|
||||
@@ -0,0 +1,8 @@
|
||||
Test project /home/emil/Desktop/.worktrees/Faset_Engine-p3-lighting/build/linux-debug
|
||||
Test #7: render_lighting_sun
|
||||
Test #8: render_lighting_local
|
||||
Test #9: render_lighting_policy
|
||||
Test #17: render_lighting_benchmark_schema
|
||||
Test #18: render_lighting_benchmark_smoke
|
||||
|
||||
Total Tests: 5
|
||||
@@ -0,0 +1,20 @@
|
||||
warning: An executable named `mkdocs` is not provided by package `mkdocs-material` but is available via the dependency `mkdocs`. Consider using `uvx --from mkdocs mkdocs` instead.
|
||||
|
||||
[31m │ ⚠ Warning from the Material for MkDocs team[0m
|
||||
[31m │[0m
|
||||
[31m │[0m MkDocs 2.0, the underlying framework of Material for MkDocs,
|
||||
[31m │[0m will introduce backward-incompatible changes, including:
|
||||
[31m │[0m
|
||||
[31m │ × [0mAll plugins will stop working – the plugin system has been removed
|
||||
[31m │ × [0mAll theme overrides will break – the theming system has been rewritten
|
||||
[31m │ × [0mNo migration path exists – existing projects cannot be upgraded
|
||||
[31m │ × [0mClosed contribution model – community members can't report bugs
|
||||
[31m │ × [0mCurrently unlicensed – unsuitable for production use
|
||||
[31m │[0m
|
||||
[31m │[0m Our full analysis:
|
||||
[31m │[0m
|
||||
[31m │[0m [4mhttps://squidfunk.github.io/mkdocs-material/blog/2026/02/18/mkdocs-2.0/[0m
|
||||
[0m
|
||||
INFO - Cleaning site directory
|
||||
INFO - Building documentation to directory: /home/emil/Desktop/.worktrees/Faset_Engine-p3-lighting/build/manual
|
||||
INFO - Documentation built in 0.84 seconds
|
||||
Reference in New Issue
Block a user