Document Forward+ measurements and Linux lighting evidence
Native and manual checks / native (ubuntu-24.04) (push) Failing after 35s
Native and manual checks / manual (push) Successful in 27s
Native and manual checks / native (windows-2025) (push) Canceled after 0s
Windows editor and software Vulkan / windows-graphics (push) Canceled after 0s
Native and manual checks / native (ubuntu-24.04) (push) Failing after 35s
Native and manual checks / manual (push) Successful in 27s
Native and manual checks / native (windows-2025) (push) Canceled after 0s
Windows editor and software Vulkan / windows-graphics (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# P3 Forward+ experiment: correctness and cost on localized lights
|
||||
|
||||
The fixed 1920×1080 P3 benchmark crossed the agreed threshold for trying
|
||||
Forward+. A depth-free 16×16 tiled implementation now exists, but the measured
|
||||
**build + raster** cost is higher than a full light scan on that benchmark's
|
||||
dense lights. `RendererConfig::lighting_mode = Auto` therefore keeps the forward
|
||||
path. `Tiled` is an explicit option for scenes whose projected light volumes
|
||||
are localized. There is no unmeasured automatic occupancy heuristic.
|
||||
|
||||
This is a follow-up to the fixed-scene baseline sweep, which is being merged
|
||||
as a separate study. It compares both paths in the same source revision
|
||||
`a0a4e29d480ed3344f19bd3565d48668ca913fed`. The baseline's dense
|
||||
placement remains the default. An explicit `--light-layout localized` changes
|
||||
only point-light range from 8 to 1.75 world units; camera, nine casters,
|
||||
receiver, positions, colors, light count, and output size are unchanged. The
|
||||
localized fixture is a separate workload, not a replacement for the fixed
|
||||
baseline gate.
|
||||
|
||||
## Renderer behavior and safety
|
||||
|
||||
The compute pass builds up to 64 stable-order light indices per screen tile.
|
||||
It tests each world-space range sphere against four clip-space tile planes.
|
||||
It does not use depth or reject near-plane intersections. A tile with more than
|
||||
64 candidates sets an overflow bit; the fragment shader then scans **all**
|
||||
submitted lights for that tile. Zero lights, missing capability, excessive
|
||||
buffer size, failed optional allocation, and `Auto` use the forward path. The
|
||||
shader contract checks the new compute entry's descriptors and 96-byte push
|
||||
constants; Direct and P2 GPU graphics still use materials at set 0, lighting
|
||||
at set 1, and GPU scene data at set 2. The tile list is set 1 binding 4 in the
|
||||
shared fragment shader. Sprite/UI shading returns before tile reads.
|
||||
|
||||
The Linux Vulkan image test compares forward and tiled output in Direct, GPU
|
||||
frustum, and GPU occlusion modes, including a cropped scene viewport, near-plane
|
||||
crossing point light and shadow, resize, an offscreen light, and 80 coincident
|
||||
lights that exceed tile capacity. Every overflowing tile falls back to the full
|
||||
list. Shader reload preserves a working tiled pipeline after invalid bytecode
|
||||
and recreates it after a valid reload. A separate 1920×1080 capture with 128
|
||||
localized lights was byte-identical across both paths; its SHA-256 is in the
|
||||
[provenance record](data/p3-forward-plus-provenance-2026-09-24.json).
|
||||
|
||||
## Measurement
|
||||
|
||||
The device was NVIDIA GeForce RTX 2080 Ti with NVIDIA driver 595.84.0.0,
|
||||
Linux Clang Release, Direct visibility, shadows off, 1920×1080. Each mode had
|
||||
three independent process runs with ten warm-up and thirty measured frames.
|
||||
Forward/tiled run order alternated. The table uses the median of the three
|
||||
per-run medians in milliseconds. The tile build column is an actual GPU
|
||||
timestamp; `build + raster` also includes post raster if present. The dense
|
||||
and localized CSVs contain every one of the 1080 measured frames, with a
|
||||
`source_csv` identifier. The executable and all loaded `.spv`/reflection
|
||||
SHA-256 values are in the provenance record.
|
||||
|
||||
| Light layout | Lights | Forward raster | Tile build | Tiled raster | Tiled build + raster | Tiled change |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| Dense fixed scene | 32 | 0.5500 | 0.0617 | 0.5527 | 0.6144 | +0.0644 ms (11.7% slower) |
|
||||
| Dense fixed scene | 64 | 1.0701 | 0.1177 | 1.0740 | 1.1921 | +0.1220 ms (11.4% slower) |
|
||||
| Dense fixed scene | 128 | 2.1172 | 0.2219 | 2.1164 | 2.3388 | +0.2216 ms (10.5% slower) |
|
||||
| Localized range 1.75 | 32 | 0.2336 | 0.0555 | 0.0758 | 0.1312 | −0.1025 ms (43.9% faster) |
|
||||
| Localized range 1.75 | 64 | 0.4254 | 0.1060 | 0.1057 | 0.2109 | −0.2144 ms (50.4% faster) |
|
||||
| Localized range 1.75 | 128 | 0.8094 | 0.2048 | 0.1643 | 0.3691 | −0.4404 ms (54.4% faster) |
|
||||
|
||||
At 32 dense lights, the first forward process had a 0.7405 ms run median;
|
||||
the other two were 0.5488 and 0.5500 ms. A single paired run would have
|
||||
incorrectly suggested a tiled win. The median of three process medians and a
|
||||
separate earlier repeat both support the slower dense result. This is why
|
||||
`Auto` remains forward despite the localized-scene gain. The total GPU frame
|
||||
also includes visibility, shadow fallback, copies, and synchronous readback;
|
||||
the table isolates the passes that the optimization changes. For example, at
|
||||
32 localized lights the full GPU frame was 1.6494 ms forward and 1.6472 ms
|
||||
tiled, essentially unchanged despite lower build + raster cost. At 128 it
|
||||
was 2.2788 versus 1.7948 ms.
|
||||
|
||||
One diagnostic frame per layout/count copied the tile buffer after the timed
|
||||
draw. That copy was **not enabled** in the 1080 performance frames. The grid
|
||||
has 8160 tiles and a 64-index capacity per tile.
|
||||
|
||||
| Layout | Lights | Stored candidates across tiles | Overflowed tiles |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Dense | 32 | 259,896 | 0 |
|
||||
| Dense | 64 | 519,792 | 0 |
|
||||
| Dense | 128 | 522,240 | 8,160 |
|
||||
| Localized | 32 | 38,237 | 0 |
|
||||
| Localized | 64 | 76,103 | 0 |
|
||||
| Localized | 128 | 152,202 | 0 |
|
||||
|
||||
The dense 128 candidate count is capped at 64 × 8160 stored slots; all tiles
|
||||
overflow and correctly evaluate all 128 lights in the fragment shader. This
|
||||
explains why paying for tile construction cannot help that frame. The localized
|
||||
128 scene averages about 19 stored candidates per tile and avoids fallback.
|
||||
|
||||
Raw data: [all paired frames](data/p3-forward-plus-ab-2026-09-24.csv),
|
||||
[diagnostic frames](data/p3-forward-plus-diagnostics-2026-09-24.csv), and
|
||||
[binary/shader provenance](data/p3-forward-plus-provenance-2026-09-24.json).
|
||||
|
||||
## Verification and scope
|
||||
|
||||
At the implementation revision, Linux Debug built all targets and passed
|
||||
62/63 CTests, with the compositor-dependent window lifecycle case skipped and
|
||||
no failures. The pinned Linux SwiftShader ICD passed all six P3 cases, including
|
||||
the tiled parity/overflow test. The [lighting validation record](../validation/p3-lighting-2026-09-24/README.md)
|
||||
retains those logs. These are functional checks on Linux and software Vulkan,
|
||||
not physical Windows GPU performance. The A/B numbers apply to one GPU, driver,
|
||||
camera, receiver and two synthetic light layouts. They do not establish an
|
||||
engine-wide speedup. A measured runtime occupancy predictor and representative
|
||||
game scenes are prerequisites before changing `Auto` from forward.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Исследования для Faset Engine
|
||||
|
||||
Обновлено 23.09.2026. Исходники и официальная документация исследовались прежде всего 17.09.2026; затем результаты согласованы с принятой архитектурой. P2 implementation/acceptance добавлены позже и отделены от исходного статического исследования.
|
||||
Обновлено 24.09.2026. Исходники и официальная документация исследовались прежде всего 17.09.2026; затем результаты согласованы с принятой архитектурой. P2/P3 implementation/acceptance добавлены позже и отделены от исходного статического исследования.
|
||||
|
||||
**Актуальные решения — в [ARCHITECTURE.md](../ARCHITECTURE.md), порядок реализации — в [PLAN.md](../../PLAN.md).** Реализация MVP и проверки идут отдельно: [журнал реализации](../IMPLEMENTATION.md), [результаты проверок](../validation/README.md), [пользовательский Manual](../manual/index.md). Исследования дают обоснования и проверочные сценарии; их статический анализ не является измерением Faset.
|
||||
|
||||
@@ -41,6 +41,7 @@ Linux/Windows, десктопные 2D/3D, C++ сначала и Lua следу
|
||||
- [19 — P2 GPU visibility: протокол приёмки](19-p2-gpu-visibility-acceptance.md): GPU-сценарии, допуски сравнения и методика измерений; отделяет проверку реализации от предложений исследования 15.
|
||||
- [20 — P2 GPU visibility: первый benchmark](20-p2-gpu-visibility-benchmark-2026-09-23.md): три запуска, raw CSV, p50/p95 и границы интерпретации на Linux reference GPU.
|
||||
- [21 — P2 GPU visibility: оптимизация MainCull](21-p2-gpu-visibility-optimization-2026-09-23.md): отдельные измерения переноса выходных буферов в память GPU и замены CAS-цикла на atomic add.
|
||||
- [23 — P3 Forward+: корректность и стоимость](23-p3-forward-plus-2026-09-24.md): сравнение полной цены построения плиток и рисования на плотной и локализованной сценах, raw CSV и точный shader/binary provenance.
|
||||
|
||||
## Происхождение и воспроизводимость
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
light_count,light_layout,shadows,visibility,effective_visibility,lighting_path,requested_lighting,build_configuration,run_index,frame,device,driver,commit,width,height,validation_enabled,validation_errors,submitted_local_lights,omitted_local_lights,requested_local_shadow_faces,rendered_local_shadow_faces,dropped_shadow_faces,shadow_atlas_full_drops,shadow_tiles,draw_calls,gpu_bytes,gpu_main_raster_ms,gpu_post_raster_ms,gpu_post_visible,visibility_counters_valid,gpu_sun_shadow_ms,gpu_local_shadow_ms,gpu_shadow_ms,gpu_light_tiles_ms,gpu_build_plus_raster_ms,light_tile_count,light_tile_counts_valid,light_tile_candidate_count,light_tile_overflow_count,gpu_ms,cpu_ms,readback_cpu_ms
|
||||
32,dense,off,direct,direct,tiled,tiled,Release,0,0,NVIDIA GeForce RTX 2080 Ti,NVIDIA 595.84.0.0,a0a4e29d480ed3344f19bd3565d48668ca913fed,1920,1080,0,0,32,0,0,0,0,0,0,10,63881248,0.551200,0.000000,0,0,0.000000,0.000000,0.000000,0.061472,0.612672,8160,1,259896,0,3.324384,4.920211,1.106698
|
||||
64,dense,off,direct,direct,tiled,tiled,Release,0,0,NVIDIA GeForce RTX 2080 Ti,NVIDIA 595.84.0.0,a0a4e29d480ed3344f19bd3565d48668ca913fed,1920,1080,0,0,64,0,0,0,0,0,0,10,63883808,1.077376,0.000000,0,0,0.000000,0.000000,0.000000,0.117440,1.194816,8160,1,519792,0,3.713568,5.236988,1.014093
|
||||
128,dense,off,direct,direct,tiled,tiled,Release,0,0,NVIDIA GeForce RTX 2080 Ti,NVIDIA 595.84.0.0,a0a4e29d480ed3344f19bd3565d48668ca913fed,1920,1080,0,0,128,0,0,0,0,0,0,10,63888928,2.109440,0.000000,0,0,0.000000,0.000000,0.000000,0.221184,2.330624,8160,1,522240,8160,4.435136,6.211166,0.970080
|
||||
32,localized,off,direct,direct,tiled,tiled,Release,0,0,NVIDIA GeForce RTX 2080 Ti,NVIDIA 595.84.0.0,a0a4e29d480ed3344f19bd3565d48668ca913fed,1920,1080,0,0,32,0,0,0,0,0,0,10,63881248,0.075328,0.000000,0,0,0.000000,0.000000,0.000000,0.055296,0.130624,8160,1,38237,0,2.355808,3.586245,0.930515
|
||||
64,localized,off,direct,direct,tiled,tiled,Release,0,0,NVIDIA GeForce RTX 2080 Ti,NVIDIA 595.84.0.0,a0a4e29d480ed3344f19bd3565d48668ca913fed,1920,1080,0,0,64,0,0,0,0,0,0,10,63883808,0.105248,0.000000,0,0,0.000000,0.000000,0.000000,0.105312,0.210560,8160,1,76103,0,2.445600,3.884127,1.069417
|
||||
128,localized,off,direct,direct,tiled,tiled,Release,0,0,NVIDIA GeForce RTX 2080 Ti,NVIDIA 595.84.0.0,a0a4e29d480ed3344f19bd3565d48668ca913fed,1920,1080,0,0,128,0,0,0,0,0,0,10,63888928,0.215040,0.000000,0,0,0.000000,0.000000,0.000000,0.229376,0.444416,8160,1,152202,0,2.585504,4.059668,0.951374
|
||||
|
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"commit": "a0a4e29d480ed3344f19bd3565d48668ca913fed",
|
||||
"device": "NVIDIA GeForce RTX 2080 Ti",
|
||||
"driver": "NVIDIA 595.84.0.0",
|
||||
"build": "Linux Clang Release",
|
||||
"executable_sha256": "db151a07eeaee04871920f8617f5bcf4c8ac7cb11abf4e36e5595cc526440a36",
|
||||
"shader_bundle_sha256": "60d2abf2f43557f72f39de7a50f4bc92816eb7859c613b2797c0410e72dbaeed",
|
||||
"shader_bundle_hash_method": "SHA256 of UTF-8 canonical JSON mapping sorted shader filenames to per-file SHA256",
|
||||
"shader_files": {
|
||||
"vertexMain.spv": "1ad2631c35d654f48166321ae43d4165043e1b919b14f1dc61caf97b1ada0898",
|
||||
"vertexMain.reflection.json": "b3bdff863d53a0b385e06a36701a83a6ecafe9a93e97281a732cce8ff862c0db",
|
||||
"fragmentMain.spv": "eb65edf62a4ead573f740903dbbd1a61565fe97d234fbe8a09934ce6415bec92",
|
||||
"fragmentMain.reflection.json": "6b62a42ea448d9ae253d78b6b326dfe0d761532ce695b49263689ec649ede36c",
|
||||
"shadowMain.spv": "7643b4d688492b5ee923b9606f0b0e70343ca05fa67673838206119a6f86d8d8",
|
||||
"shadowMain.reflection.json": "d39e2f83c797589296eac9dce139b9ad836a895d6685bc40f79dd2609d687fee",
|
||||
"lightTileMain.spv": "92850edcc5ee5b586a90ce84ee69a98075a6fff3c13db4a57528d9431afe8b68",
|
||||
"lightTileMain.reflection.json": "bf6a9256aaa6d6edacfa1e1c265d7c8ce2c1e4ea4036e0bea078c22fd4b536ca",
|
||||
"gpuVertexMain.spv": "fc9770f304976875f8dd1f6acbe380c77cb06c13276f5596554b3f0b396b31bd",
|
||||
"gpuVertexMain.reflection.json": "09166d80fba7ab4167e97f85125a7c58ab92ea447c1a6a2ab5084e657401dae9",
|
||||
"gpuShadowMain.spv": "2da7e7f96bc7de4e9c8ac365fe0a63f608c7bb26ab3e7bfebfcf88b32e86c71d",
|
||||
"gpuShadowMain.reflection.json": "c9dd844aefb3840f29caad5dfc53986cacc2220f886eda5ad345ebdbb9ff5b1c",
|
||||
"gpuCullMain.spv": "7691360ec55f41d40d43652f506b051cef8b3a3ddcdcc7db61a7d4d97f9e87d8",
|
||||
"gpuCullMain.reflection.json": "996fe5c7e31c6b8f316d8f290b3be0ae7063eb46c500a661e8715e9b822a2598",
|
||||
"gpuHzbMain.spv": "08682362ee2120ed19d260e613285071747c3e436bb09bb6238e46f9cedc2308",
|
||||
"gpuHzbMain.reflection.json": "589818f670881c64f3aba726ee3bc82fe4b9d835a347f99134e0e157dc4a112e",
|
||||
"gpuPostCullMain.spv": "62cb72e356346e1511c6d640a3cecb4a6e5283795338299b357edae5f7f52be4",
|
||||
"gpuPostCullMain.reflection.json": "eed140bbe09c7d14935b688c770261ac0e81677c0974aa811c88ed67ea779b95"
|
||||
},
|
||||
"matrix": "Direct, shadows off, 1920x1080, dense or localized, 32/64/128 lights, 3 repeats, 10 warmup + 30 measured frames; alternating A/B order",
|
||||
"raw_rows": 1080,
|
||||
"localized_128_capture_sha256": "2aa5d408867f7193b7fd83984f2333b188623bda4d083512ede6b8318f11b45c",
|
||||
"localized_128_capture_exact_equal": true
|
||||
}
|
||||
Reference in New Issue
Block a user